DBA Data[Home] [Help]

PACKAGE BODY: APPS.AP_APPROVAL_PKG

Source


1 PACKAGE BODY AP_APPROVAL_PKG AS
2 /* $Header: apaprvlb.pls 120.140.12010000.28 2009/01/23 10:48:19 ctetala ship $ */
3 
4   G_PKG_NAME          CONSTANT VARCHAR2(30) := 'AP_APPROVAL_PKG';
5   G_MSG_UERROR        CONSTANT NUMBER       := FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR;
6   G_MSG_ERROR         CONSTANT NUMBER       := FND_MSG_PUB.G_MSG_LVL_ERROR;
7   G_MSG_SUCCESS       CONSTANT NUMBER       := FND_MSG_PUB.G_MSG_LVL_SUCCESS;
8   G_MSG_HIGH          CONSTANT NUMBER       := FND_MSG_PUB.G_MSG_LVL_DEBUG_HIGH;
9   G_MSG_MEDIUM        CONSTANT NUMBER       := FND_MSG_PUB.G_MSG_LVL_DEBUG_MEDIUM;
10   G_MSG_LOW           CONSTANT NUMBER       := FND_MSG_PUB.G_MSG_LVL_DEBUG_LOW;
11   G_LINES_PER_FETCH   CONSTANT NUMBER       := 1000;
12 
13   G_CURRENT_RUNTIME_LEVEL CONSTANT NUMBER       := FND_LOG.G_CURRENT_RUNTIME_LEVEL;
14   G_LEVEL_UNEXPECTED      CONSTANT NUMBER       := FND_LOG.LEVEL_UNEXPECTED;
15   G_LEVEL_ERROR           CONSTANT NUMBER       := FND_LOG.LEVEL_ERROR;
16   G_LEVEL_EXCEPTION       CONSTANT NUMBER       := FND_LOG.LEVEL_EXCEPTION;
17   G_LEVEL_EVENT           CONSTANT NUMBER       := FND_LOG.LEVEL_EVENT;
18   G_LEVEL_PROCEDURE       CONSTANT NUMBER       := FND_LOG.LEVEL_PROCEDURE;
19   G_LEVEL_STATEMENT       CONSTANT NUMBER       := FND_LOG.LEVEL_STATEMENT;
20   G_MODULE_NAME           CONSTANT VARCHAR2(100) := 'AP.PLSQL.AP_APPROVAL_PKG.';
21 
22 /*===========================================================================
23  | Private Global Variable specification
24  *==========================================================================*/
25    g_org_id            NUMBER(15); /* Bug 3700128. MOAC Project */
26 
27 /*============================================================================
28  | Private (Non Public) Procedure Specifications
29  *===========================================================================*/
30 FUNCTION Inv_Needs_Approving(
31              p_invoice_id        IN NUMBER,
32              p_run_option        IN VARCHAR2,
33              p_calling_sequence  IN VARCHAR2) RETURN BOOLEAN;
34 
35 FUNCTION Get_Inv_Matched_Status(
36              p_invoice_id        IN NUMBER,
37              p_calling_sequence  IN VARCHAR2) RETURN BOOLEAN;
38 
39 PROCEDURE Get_Invoice_Statuses(
40               p_invoice_id       IN            NUMBER,
41               p_holds_count      IN OUT NOCOPY NUMBER,
42               p_approval_status  IN OUT NOCOPY VARCHAR2,
43               p_calling_sequence IN            VARCHAR2);
44 
45 PROCEDURE Update_Inv_Dists_To_Approved(
46               p_invoice_id       IN            NUMBER,
47               p_user_id          IN            NUMBER,
48               p_calling_sequence IN            VARCHAR2);
49 
50 PROCEDURE Update_Inv_Dists_To_Selected(
51               p_invoice_id       IN            NUMBER,
52               P_line_number      IN            NUMBER,
53               p_run_option       IN            VARCHAR2,
54               p_calling_sequence IN            VARCHAR2);
55 
56 PROCEDURE Approval_Init(
57 	      p_org_id			     IN            NUMBER,
58 	      p_invoice_id		     IN 	   NUMBER,
59               p_invoice_type                 IN            VARCHAR2 DEFAULT NULL,
60               p_tolerance_id                 IN            NUMBER,
61               p_services_tolerance_id        IN            NUMBER,
62 	      p_conc_flag		     IN		   VARCHAR2,
63               p_set_of_books_id              IN OUT NOCOPY NUMBER,
64               p_recalc_pay_sched_flag        IN OUT NOCOPY VARCHAR2,
65               p_sys_xrate_gain_ccid          IN OUT NOCOPY NUMBER,
66               p_sys_xrate_loss_ccid          IN OUT NOCOPY NUMBER,
67               p_base_currency_code           IN OUT NOCOPY VARCHAR2,
68               p_inv_enc_type_id              IN OUT NOCOPY NUMBER,
69               p_purch_enc_type_id            IN OUT NOCOPY NUMBER,
70               p_gl_date_from_receipt_flag    IN OUT NOCOPY VARCHAR2,
71               p_receipt_acc_days             IN OUT NOCOPY NUMBER,
72               p_system_user                  IN OUT NOCOPY NUMBER,
73               p_user_id                      IN OUT NOCOPY NUMBER,
74               p_goods_ship_amt_tolerance     IN OUT NOCOPY NUMBER,
75               p_goods_rate_amt_tolerance     IN OUT NOCOPY NUMBER,
76               p_goods_total_amt_tolerance    IN OUT NOCOPY NUMBER,
77 	      p_services_ship_amt_tolerance  IN OUT NOCOPY NUMBER,
78 	      p_services_rate_amt_tolerance  IN OUT NOCOPY NUMBER,
79 	      p_services_total_amt_tolerance IN OUT NOCOPY NUMBER,
80               p_price_tolerance              IN OUT NOCOPY NUMBER,
81               p_qty_tolerance                IN OUT NOCOPY NUMBER,
82               p_qty_rec_tolerance            IN OUT NOCOPY NUMBER,
83 	      p_amt_tolerance                IN OUT NOCOPY NUMBER,
84 	      p_amt_rec_tolerance            IN OUT NOCOPY NUMBER,
85               p_max_qty_ord_tolerance        IN OUT NOCOPY NUMBER,
86               p_max_qty_rec_tolerance        IN OUT NOCOPY NUMBER,
87 	      p_max_amt_ord_tolerance	     IN OUT NOCOPY NUMBER,
88 	      p_max_amt_rec_tolerance        IN OUT NOCOPY NUMBER,
89               p_invoice_line_count           OUT NOCOPY NUMBER,   --Bug 6684139
90               p_calling_sequence             IN            VARCHAR2);
91 
92 PROCEDURE Set_Hold(
93               p_invoice_id          IN            NUMBER,
94               p_line_location_id    IN            NUMBER,
95               p_rcv_transaction_id  IN            NUMBER,
96               p_hold_lookup_code    IN            VARCHAR2,
97               p_hold_reason         IN            VARCHAR2,
98               p_holds               IN OUT NOCOPY HOLDSARRAY,
99               p_holds_count         IN OUT NOCOPY COUNTARRAY,
100               p_calling_sequence    IN            VARCHAR2);
101 
102 PROCEDURE Count_Hold(
103               p_hold_lookup_code    IN            VARCHAR2,
104               p_holds               IN OUT NOCOPY HOLDSARRAY,
105               p_count               IN OUT NOCOPY COUNTARRAY,
106               p_calling_sequence    IN            VARCHAR2);
107 
108 PROCEDURE Get_Release_Lookup_For_Hold(
109               p_hold_lookup_code    IN            VARCHAR2,
110               p_release_lookup_code IN OUT NOCOPY VARCHAR2,
111               p_calling_sequence    IN            VARCHAR2);
112 
113 PROCEDURE Withhold_Tax_On(
114               p_invoice_id              IN NUMBER,
115               p_gl_date_from_receipt    IN VARCHAR2,
116               p_last_updated_by         IN NUMBER,
117               p_last_update_login       IN NUMBER,
118               p_program_application_id  IN NUMBER,
119               p_program_id              IN NUMBER,
120               p_request_id              IN NUMBER,
121               p_system_user             IN NUMBER,
122               p_holds                   IN OUT NOCOPY HOLDSARRAY,
123               p_holds_count             IN OUT NOCOPY COUNTARRAY,
124               p_release_count           IN OUT NOCOPY COUNTARRAY,
125               p_calling_sequence        IN VARCHAR2);
126 
127 PROCEDURE Line_Base_Amount_Calculation(
128               p_invoice_id              IN            NUMBER,
129               p_invoice_currency_code   IN            VARCHAR2,
130               p_base_currency_code      IN            VARCHAR2,
131               p_exchange_rate           IN            NUMBER,
132               p_need_to_round_flag      IN            VARCHAR2 DEFAULT 'N',
133               p_calling_sequence        IN            VARCHAR2);
134 
135 PROCEDURE Dist_Base_Amount_Calculation(
136               p_invoice_id              IN            NUMBER,
137               p_invoice_line_number     IN            NUMBER,
138               p_invoice_currency_code   IN            VARCHAR2,
139               p_base_currency_code      IN            VARCHAR2,
140               p_invoice_exchange_rate   IN            NUMBER,
141               p_need_to_round_flag      IN            VARCHAR2 DEFAULT 'N',
142               p_calling_sequence        IN            VARCHAR2);
143 
144 PROCEDURE Execute_General_Checks(
145               p_invoice_id                IN            NUMBER,
146               p_set_of_books_id           IN            NUMBER,
147               p_base_currency_code        IN            VARCHAR2,
148               p_invoice_amount            IN            NUMBER,
149               p_base_amount               IN            NUMBER,
150               p_invoice_currency_code     IN            VARCHAR2,
151               p_invoice_amount_limit      IN            NUMBER,
152               p_hold_future_payments_flag IN            VARCHAR2,
153               p_system_user               IN            NUMBER,
154               p_holds                     IN OUT NOCOPY HOLDSARRAY,
155               p_holds_count               IN OUT NOCOPY COUNTARRAY,
156               p_release_count             IN OUT NOCOPY COUNTARRAY,
157               p_calling_sequence          IN            VARCHAR2);
158 
159 PROCEDURE Check_Dist_Variance(
160               p_invoice_id                  IN            NUMBER,
161               p_invoice_line_number         IN            NUMBER,
162               p_system_user                 IN            NUMBER,
163               p_holds                       IN OUT NOCOPY HOLDSARRAY,
164               p_holds_count                 IN OUT NOCOPY COUNTARRAY,
165               p_release_count               IN OUT NOCOPY COUNTARRAY,
166               p_distribution_variance_exist    OUT NOCOPY BOOLEAN,
167               p_calling_sequence            IN            VARCHAR2);
168 
169 PROCEDURE Check_Line_Variance(
170               p_invoice_id                  IN            NUMBER,
171               p_system_user                 IN            NUMBER,
172               p_holds                       IN OUT NOCOPY HOLDSARRAY,
173               p_holds_count                 IN OUT NOCOPY COUNTARRAY,
174               p_release_count               IN OUT NOCOPY COUNTARRAY,
175               p_line_variance_hold_exist       OUT NOCOPY BOOLEAN,
176               p_calling_sequence            IN            VARCHAR2,
177 	      p_base_currency_code          IN            VARCHAR2);   --bug7271262
178 
179 PROCEDURE Check_Prepaid_Amount(
180               p_invoice_id                IN            NUMBER,
181               p_system_user               IN            NUMBER,
182               p_holds                     IN OUT NOCOPY HOLDSARRAY,
183               p_holds_count               IN OUT NOCOPY COUNTARRAY,
184               p_release_count             IN OUT NOCOPY COUNTARRAY,
185               p_calling_sequence          IN            VARCHAR2);
186 
187 PROCEDURE Check_No_Rate(
188               p_invoice_id                IN            NUMBER,
189               p_base_currency_code        IN            VARCHAR2,
190               p_system_user               IN            NUMBER,
191               p_holds                     IN OUT NOCOPY HOLDSARRAY,
192               p_holds_count               IN OUT NOCOPY COUNTARRAY,
193               p_release_count             IN OUT NOCOPY COUNTARRAY,
194               p_calling_sequence          IN            VARCHAR2);
195 
196 PROCEDURE Check_invoice_vendor(
197               p_invoice_id                IN            NUMBER,
198               p_base_currency_code        IN            VARCHAR2,
199               p_invoice_amount            IN            NUMBER,
200               p_base_amount               IN            NUMBER,
201               p_invoice_currency_code     IN            VARCHAR2,
202               p_invoice_amount_limit      IN            NUMBER,
203               p_hold_future_payments_flag IN            VARCHAR2,
204               p_system_user               IN            NUMBER,
205               p_holds                     IN OUT NOCOPY HOLDSARRAY,
206               p_holds_count               IN OUT NOCOPY COUNTARRAY,
207               p_release_count             IN OUT NOCOPY COUNTARRAY,
208               p_calling_sequence          IN            VARCHAR2);
209 
210 PROCEDURE  Check_Manual_AWT_Segments(
211               p_invoice_id                IN            NUMBER,
212               p_system_user               IN            NUMBER,
213               p_holds                     IN OUT NOCOPY HOLDSARRAY,
214               p_holds_count               IN OUT NOCOPY COUNTARRAY,
215               p_release_count             IN OUT NOCOPY COUNTARRAY,
216               p_calling_sequence          IN            VARCHAR2);
217 
218 PROCEDURE Check_PO_Required(
219               p_invoice_id                IN            NUMBER,
220               p_system_user               IN            NUMBER,
221               p_holds                     IN OUT NOCOPY HOLDSARRAY,
222               p_holds_count               IN OUT NOCOPY COUNTARRAY,
223               p_release_count             IN OUT NOCOPY COUNTARRAY,
224               p_calling_sequence          IN            VARCHAR2);
225 
226 PROCEDURE Check_Invalid_Dist_Acct(
227               p_invoice_id                IN            NUMBER,
228               p_system_user               IN            NUMBER,
229               p_holds                     IN OUT NOCOPY HOLDSARRAY,
230               p_holds_count               IN OUT NOCOPY COUNTARRAY,
231               p_release_count             IN OUT NOCOPY COUNTARRAY,
232               p_calling_sequence          IN            VARCHAR2);
233 
234 FUNCTION Check_hold_batch_releaseable(
235              p_hold_name               IN            VARCHAR2,
236              p_calling_sequence        IN            VARCHAR2) RETURN VARCHAR2;
237 
238 PROCEDURE Generate_Account_Event(
239               p_invoice_id             IN            NUMBER,
240               p_calling_sequence       IN            VARCHAR2);
241 
242 PROCEDURE Update_Total_Dist_Amount(
243               p_invoice_id             IN            NUMBER,
244               p_calling_sequence       IN            VARCHAR2);
245 
246 PROCEDURE Exclude_Tax_Freight_From_Disc(
247 			p_invoice_id IN NUMBER,
248                         p_exclude_tax_from_discount 	IN VARCHAR2,
249 			p_exclude_freight_from_disc 	IN VARCHAR2,
250                         p_invoice_type_lookup_code 	IN VARCHAR2,
251                         p_curr_calling_sequence		IN VARCHAR2) ;
252 
253 PROCEDURE update_payment_schedule_prepay(
254                 p_invoice_id                    IN      NUMBER,
255                 p_apply_amount                  IN      NUMBER,
256                 p_amount_positive               IN      VARCHAR2,
257                 p_payment_currency_code         IN      VARCHAR2,
258                 p_user_id                       IN      NUMBER,
259                 p_last_update_login             IN      NUMBER,
260                 p_calling_sequence              IN      VARCHAR2);
261 
262 FUNCTION validate_period (p_invoice_id IN NUMBER) RETURN BOOLEAN;
263 
264 PROCEDURE Manual_Withhold_Tax(
265 		p_invoice_id              IN NUMBER,
266 		p_last_updated_by         IN NUMBER,
267 		p_last_update_login       IN NUMBER,
268 		p_calling_sequence        IN VARCHAR2);
269 
270 /* Bug 7393338 added this procedure*/
271 PROCEDURE Update_Pay_Sched_For_Awt(p_invoice_id         IN NUMBER,
272                         p_last_updated_by               IN NUMBER,
273                         p_last_update_login             IN NUMBER,
274                         p_calling_sequence              IN VARCHAR2);
275 
276 PROCEDURE createPaymentSchedules(
277 		p_invoice_id		IN NUMBER,
278 		p_calling_sequence	IN VARCHAR2);
279 
280 Procedure Print_Debug(
281 		p_api_name		IN VARCHAR2,
282 		p_debug_info		IN VARCHAR2);
283 
284 CURSOR invoice_line_cur (c_invoice_id NUMBER) IS
285   SELECT  INVOICE_ID,
286           LINE_NUMBER,
287           LINE_TYPE_LOOKUP_CODE,
288           REQUESTER_ID,
289           DESCRIPTION,
290           LINE_SOURCE,
291           ORG_ID,
292           LINE_GROUP_NUMBER,
293           INVENTORY_ITEM_ID,
294           ITEM_DESCRIPTION,
295           SERIAL_NUMBER,
296           MANUFACTURER,
297           MODEL_NUMBER,
298           WARRANTY_NUMBER,
299           GENERATE_DISTS,
300           MATCH_TYPE,
301           DISTRIBUTION_SET_ID,
302           ACCOUNT_SEGMENT,
303           BALANCING_SEGMENT,
304           COST_CENTER_SEGMENT,
305           OVERLAY_DIST_CODE_CONCAT,
306           DEFAULT_DIST_CCID,
307           PRORATE_ACROSS_ALL_ITEMS,
308           ACCOUNTING_DATE,
309           PERIOD_NAME ,
310           DEFERRED_ACCTG_FLAG ,
311           DEF_ACCTG_START_DATE ,
312           DEF_ACCTG_END_DATE,
313           DEF_ACCTG_NUMBER_OF_PERIODS,
314           DEF_ACCTG_PERIOD_TYPE ,
315           SET_OF_BOOKS_ID,
316           AMOUNT,
317           BASE_AMOUNT,
318           ROUNDING_AMT,
319           QUANTITY_INVOICED,
320           UNIT_MEAS_LOOKUP_CODE ,
321           UNIT_PRICE,
322           WFAPPROVAL_STATUS,
323           DISCARDED_FLAG,
324           ORIGINAL_AMOUNT,
325           ORIGINAL_BASE_AMOUNT ,
326           ORIGINAL_ROUNDING_AMT ,
327           CANCELLED_FLAG ,
328           INCOME_TAX_REGION,
329           TYPE_1099   ,
330           STAT_AMOUNT  ,
331           PREPAY_INVOICE_ID ,
332           PREPAY_LINE_NUMBER  ,
333           INVOICE_INCLUDES_PREPAY_FLAG ,
334           CORRECTED_INV_ID ,
335           CORRECTED_LINE_NUMBER ,
336           PO_HEADER_ID,
337           PO_LINE_ID  ,
338           PO_RELEASE_ID ,
339           PO_LINE_LOCATION_ID ,
340           PO_DISTRIBUTION_ID,
341           RCV_TRANSACTION_ID,
342           FINAL_MATCH_FLAG,
343           ASSETS_TRACKING_FLAG ,
344           ASSET_BOOK_TYPE_CODE ,
345           ASSET_CATEGORY_ID ,
346           PROJECT_ID ,
347           TASK_ID ,
348           EXPENDITURE_TYPE ,
349           EXPENDITURE_ITEM_DATE ,
350           EXPENDITURE_ORGANIZATION_ID ,
351           PA_QUANTITY,
352           PA_CC_AR_INVOICE_ID ,
353           PA_CC_AR_INVOICE_LINE_NUM ,
354           PA_CC_PROCESSED_CODE ,
355           AWARD_ID,
356           AWT_GROUP_ID ,
357           REFERENCE_1 ,
358           REFERENCE_2 ,
359           RECEIPT_VERIFIED_FLAG  ,
360           RECEIPT_REQUIRED_FLAG ,
361           RECEIPT_MISSING_FLAG ,
362           JUSTIFICATION  ,
363           EXPENSE_GROUP ,
364           START_EXPENSE_DATE ,
365           END_EXPENSE_DATE ,
366           RECEIPT_CURRENCY_CODE  ,
367           RECEIPT_CONVERSION_RATE,
368           RECEIPT_CURRENCY_AMOUNT ,
369           DAILY_AMOUNT ,
370           WEB_PARAMETER_ID ,
371           ADJUSTMENT_REASON ,
372           MERCHANT_DOCUMENT_NUMBER ,
373           MERCHANT_NAME ,
374           MERCHANT_REFERENCE ,
375           MERCHANT_TAX_REG_NUMBER,
376           MERCHANT_TAXPAYER_ID  ,
377           COUNTRY_OF_SUPPLY,
378           CREDIT_CARD_TRX_ID ,
379           COMPANY_PREPAID_INVOICE_ID,
380           CC_REVERSAL_FLAG ,
381           CREATION_DATE ,
382           CREATED_BY,
383           LAST_UPDATED_BY ,
384           LAST_UPDATE_DATE ,
385           LAST_UPDATE_LOGIN ,
386           PROGRAM_APPLICATION_ID ,
387           PROGRAM_ID ,
388           PROGRAM_UPDATE_DATE,
389           REQUEST_ID ,
390           ATTRIBUTE_CATEGORY,
391           ATTRIBUTE1,
392           ATTRIBUTE2 ,
393           ATTRIBUTE3 ,
394           ATTRIBUTE4 ,
395           ATTRIBUTE5 ,
396           ATTRIBUTE6 ,
397           ATTRIBUTE7 ,
398           ATTRIBUTE8,
399           ATTRIBUTE9 ,
400           ATTRIBUTE10,
401           ATTRIBUTE11,
402           ATTRIBUTE12,
403           ATTRIBUTE13 ,
404           ATTRIBUTE14,
405           ATTRIBUTE15,
406           GLOBAL_ATTRIBUTE_CATEGORY,
407           GLOBAL_ATTRIBUTE1,
408           GLOBAL_ATTRIBUTE2,
409           GLOBAL_ATTRIBUTE3,
410           GLOBAL_ATTRIBUTE4 ,
411           GLOBAL_ATTRIBUTE5 ,
412           GLOBAL_ATTRIBUTE6 ,
413           GLOBAL_ATTRIBUTE7 ,
414           GLOBAL_ATTRIBUTE8 ,
415           GLOBAL_ATTRIBUTE9 ,
416           GLOBAL_ATTRIBUTE10,
417           GLOBAL_ATTRIBUTE11,
418           GLOBAL_ATTRIBUTE12 ,
419           GLOBAL_ATTRIBUTE13 ,
420           GLOBAL_ATTRIBUTE14 ,
421           GLOBAL_ATTRIBUTE15 ,
422           GLOBAL_ATTRIBUTE16 ,
423           GLOBAL_ATTRIBUTE17 ,
424           GLOBAL_ATTRIBUTE18 ,
425           GLOBAL_ATTRIBUTE19 ,
426           GLOBAL_ATTRIBUTE20 ,
427           INCLUDED_TAX_AMOUNT,
428           PRIMARY_INTENDED_USE,
429           APPLICATION_ID,
430           PRODUCT_TABLE,
431           REFERENCE_KEY1,
432           REFERENCE_KEY2,
433           REFERENCE_KEY3,
434           REFERENCE_KEY4,
435           REFERENCE_KEY5,
436           SHIP_TO_LOCATION_ID,
437          PAY_AWT_GROUP_ID     --bug 7022001
438     FROM ap_invoice_lines_all
439    WHERE invoice_id = c_invoice_id
440    ORDER BY decode(line_type_lookup_code,'ITEM',1,2), line_number;
441 
442 PROCEDURE initialize_invoice_holds(
443 			p_invoice_id       IN NUMBER,
444 			p_calling_sequence IN VARCHAR2);
445 
446 TYPE holds_rec_type IS RECORD (
447 		hold_lookup_code	ap_holds_all.hold_lookup_code%type,
448 		hold_status		varchar2(30),
449 		invoice_id		ap_holds_all.invoice_id%type,
450 		hold_reason		ap_holds_all.hold_reason%type,
451 		release_lookup_code	ap_holds_all.release_lookup_code%type,
452 		line_location_id	ap_holds_all.line_location_id%type,
453 		rcv_transaction_id	ap_holds_all.rcv_transaction_id%type,
454 		last_updated_by		ap_holds_all.last_updated_by%type,
455 		responsibility_id	ap_holds_all.responsibility_id%type);
456 
457 TYPE holds_tab_type IS TABLE OF holds_rec_type INDEX BY BINARY_INTEGER;
458 
459 g_holds_tab holds_tab_type;
460 
461 Procedure Count_Org_Hold(
462               p_org_id              IN NUMBER,
463               p_hold_lookup_code    IN VARCHAR2,
464               p_place_or_release    IN VARCHAR2,
465               p_calling_sequence    IN VARCHAR2);
466 
467 
468 /*============================================================================
469  | Procedure Definitions
470  *===========================================================================*/
471 
472 /*=============================================================================
473  |  PUBLIC PROCEDURE  APPROVE
474  |
475  |  Description
476  |      Online Approval and later batch approval
477  |
478  |  PARAMETERS
479  |      p_run_option              Run Option to indicate whether to approve
480  |                                only invoices with unapproved distributions
481  |                                or all invoices ('New' or 'All)
482  |      p_invoice_batch_id        Invoice Batch Id (For Batch Approval)
483  |      p_begin_invoice_date      Begin Invoice Date (Selection criteria)
484  |      p_end_invoice_date        End of Invoice Date (Selection criteria)
485  |      p_pay_group               Pay Group(Select criteria for Batch Approval)
486  |      p_invoice_id              Invoice_id
487  |      p_entered_by              Entered_by User id
488  |      p_set_of_books_id         Set of books id
489  |                                (Selection criteria for Batch Approval)
490  |      p_trace_option
491  |      p_conc_flag               Indicate whether the approval process is a
492  |                                concurrent process or not or if it is online
493  |      p_holds_count             Return Hold Count of invoice (For Online
494  |                                 Approval called by invoice workbench)
495  |      p_approval_status         Return Approval Status of invoice
496  |                                (For Online Approval called by form)
497  |      p_calling_sequence        Debugging string to indicate path of module
498  |                                calls to be printed out upon error.
499  |      p_debug_switch            Debug switch to be turned on or off
500  |
501  |   PROGRAM FLOW
502  |
503  |     Retrieve system variables to be used by Approval Program
504  |     For each invoice
505  |     IF invoice needs approving (i.e. not the case where run_option is 'New'
506  |         and the invoice doesn't have any unapproved distributions)
507  |       IF Accrual Basis is being used
508  |         IF automatic offsets is enabled
509  |       Populate Invoice Dist liability account
510  |     Calculate Tax (Etax API) which will determine the tax amt and
511  |        whether it is inclusive or exclusive...
512  |     Check Line Variance
513  |     Calculate Base Amount and round at Line level
514  |     Call Etax api to 'Calculate Tax', which might return exclusive tax lines
515  |       and/or inclusive tax amount.
516  |     Open a Lines Cursor - loop for each Line
517  |        If inclusive tax is returned by tax calculation api, then create taxable
518  |	    distributions for (line_amount - inclusive tax amount).
519  |        If Line need to generate distributions
520  |           check sufficient line data
521  |           Generate distributions
522  |        end if
523  |        Update Invoice Distributions as selected for approval
524  |        Execute Distribution variance check
525  |        IPV/ERV creation and valid ERV ccid check
526  |     Close Line Cursor if no more line to check
527  |     Call Etax api 'Determine Recovery' to create Tax Distributions for the invoice.
528  |     Open a Lines Cursor - loop for each Line
529  |        Base amount calculation and rounding at Distribution Level for line
530  |     Close Line Cursor if no more line to check
531  |     Execute General Invoice Checks
532  |     Get invoice matched status
533  |     IF invoice is matched
534  |       Execute Quantity Variance Check
535  |       Execute Matched Checks
536  |       Execute PO Final Close Check
537  |     Validate Invoice for Tax (etax api), which will validate
538  |       the document for tax information.
539  |     IF invoice is not a matched prepayment
540  |       Execute Funds Control (Funds Reservation)
541  |       Execute Withholding Tax
542  |       Update Invoice Dists to Appropriate Approval Status
543  |   End Loop
544  |   Accounting Event Generation
545  |   IF Recalculate Payment Schedule Option is enabled
546  |     Execute Due Date Sweeper
547  |   If online approval then
548  |     Calculate Invoice Hold Count and Release Count
549  |     Print out appropriate Return Message
550  |   End If
551  |
552  |   KNOWN ISSUES:
553  |     p_begin_invoice_date,
554  |     p_end_invoice_date,
555  |     p_pay_group,
556  |     p_entered_by,
557  |     p_set_of_books_id,
558  |     p_trace_option
559  |     are not needed here in this
560  |     procedure. The logic of selecting all invoices included in a batch
561  |     is in Invoice Validation Report. Code clean up should be done when
562  |     invoice work bench form is being modified. Now is modified to have
563  |     default value so that these two parameters can be omitted.
564  *============================================================================*/
565 
566 PROCEDURE Approve(
567               p_run_option          IN            VARCHAR2,
568               p_invoice_batch_id    IN            NUMBER,
569               p_begin_invoice_date  IN            DATE DEFAULT NULL,
570               p_end_invoice_date    IN            DATE DEFAULT NULL,
571               p_vendor_id           IN            NUMBER,
572               p_pay_group           IN            VARCHAR2,
573               p_invoice_id          IN            NUMBER,
574               p_entered_by          IN            NUMBER,
575               p_set_of_books_id     IN            NUMBER,
576               p_trace_option        IN            VARCHAR2,
577               p_conc_flag           IN            VARCHAR2,
578               p_holds_count         IN OUT NOCOPY NUMBER,
579               p_approval_status     IN OUT NOCOPY VARCHAR2,
580               p_funds_return_code   OUT    NOCOPY VARCHAR2,
581 	      p_calling_mode	    IN		  VARCHAR2 DEFAULT 'APPROVE',
582               p_calling_sequence    IN            VARCHAR2,
583               p_debug_switch        IN            VARCHAR2 DEFAULT 'N',
584               p_budget_control      IN            VARCHAR2 DEFAULT 'Y',
585               p_commit              IN            VARCHAR2 DEFAULT 'Y') IS
586 
587   CURSOR approve_invoice_cur IS
588   SELECT AI.invoice_id,
589          AI.invoice_num,
590          AI.invoice_amount,
591          AI.base_amount,
592          AI.exchange_rate,
593          AI.invoice_currency_code,
594          PVS.invoice_amount_limit,
595          nvl(PVS.hold_future_payments_flag,'N'),
596          AI.invoice_type_lookup_code,
597          AI.exchange_date,
598          AI.exchange_rate_type,
599          AI.vendor_id,
600          AI.invoice_date,
601 	 AI.org_id,
602          nvl(AI.disc_is_inv_less_tax_flag,'N'),
603          nvl(AI.exclude_freight_from_discount,'N'),
604          pvs.tolerance_id,
605          pvs.services_tolerance_id
606   FROM   ap_invoices_all AI,
607          ap_suppliers PV,
608          ap_supplier_sites_all PVS
609   WHERE  AI.invoice_id = p_invoice_id
610   AND    AI.vendor_id = PV.vendor_id
611   AND    AI.vendor_site_id = PVS.vendor_site_id;
612 
613 
614   -- Payment Requests: Cursor for payment request type of invoices
615   CURSOR approve_pay_request_cur IS
616   SELECT AI.invoice_id,
617          AI.invoice_num,
618          AI.invoice_amount,
619          AI.base_amount,
620          AI.exchange_rate,
621          AI.invoice_currency_code,
622          NULL, -- invoice_amount_limit,
623          'N',  -- hold_future_payments_flag
624          AI.invoice_type_lookup_code,
625          AI.exchange_date,
626          AI.exchange_rate_type,
627          AI.vendor_id,
628          AI.invoice_date,
629          AI.org_id,
630          nvl(AI.disc_is_inv_less_tax_flag,'N'),
631          nvl(AI.exclude_freight_from_discount,'N')
632   FROM   ap_invoices_all AI
633   WHERE  AI.invoice_id = p_invoice_id;
634 
635   CURSOR invoice_type_cur IS
636   SELECT invoice_type_lookup_code
637   FROM   ap_invoices_all
638   WHERE  invoice_id = p_invoice_id;
639 
640   l_chart_of_accounts_id        NUMBER;
641   l_recalc_pay_schedule_flag    VARCHAR2(1);
642   l_gl_date_from_receipt        VARCHAR2(1);
643   l_cash_only                   BOOLEAN;
644   l_system_user                 NUMBER;
645 
646   -- Tolerance Related Variables
647   l_goods_ship_amt_tolerance		NUMBER;
648   l_goods_rate_amt_tolerance		NUMBER;
649   l_goods_total_amt_tolerance		NUMBER;
650   l_services_ship_amt_tolerance		NUMBER;
651   l_services_rate_amt_tolerance		NUMBER;
652   l_services_total_amt_tolerance	NUMBER;
653   l_price_tol				NUMBER;
654   l_qty_tol				NUMBER;
655   l_qty_rec_tol                 	NUMBER;
656   l_amt_tol				NUMBER;
657   l_amt_rec_tol				NUMBER;
658   l_max_qty_ord_tol             	NUMBER;
659   l_max_qty_rec_tol             	NUMBER;
660   l_max_amt_ord_tol			NUMBER;
661   l_max_amt_rec_tol			NUMBER;
662 
663   l_flex_method                 VARCHAR2(25);
664   l_sys_xrate_gain_ccid         NUMBER;
665   l_sys_xrate_loss_ccid         NUMBER;
666   l_base_currency_code          VARCHAR2(15);
667   l_inv_enc_type_id             NUMBER;
668   l_purch_enc_type_id           NUMBER;
669   l_user_id                     NUMBER;
670   l_invoice_id                  NUMBER;
671   l_invoice_num                 VARCHAR2(50);
672   l_holds                       HOLDSARRAY;
673   l_hold_count                  COUNTARRAY;
674   l_release_count               COUNTARRAY;
675   l_total_hold_count            NUMBER;
676   l_total_release_count         NUMBER;
677   l_set_of_books_id             NUMBER;
678   l_matched                     BOOLEAN;
679   l_receipt_acc_days            NUMBER;
680   l_return_message_name         VARCHAR2(100);
681   l_any_records_flag            VARCHAR2(1)  := 'N';
682   l_set_tokens                  VARCHAR2(1)  := 'N';
683   num                           BINARY_INTEGER   := 1;
684 
685   l_debug_loc                   VARCHAR2(30) := 'Approval';
686   l_curr_calling_sequence       VARCHAR2(2000);
687   l_debug_info                  VARCHAR2(2000);
688 
689   l_exchange_rate              AP_INVOICES.exchange_rate%TYPE;
690   l_exchange_rate_type         AP_INVOICES.exchange_rate_type%TYPE;
691   l_exchange_date              AP_INVOICES.exchange_date%TYPE;
692   l_invoice_amount             AP_INVOICES.invoice_amount%TYPE;
693   l_invoice_base_amount        AP_INVOICES.base_amount%TYPE;
694   l_vendor_id                  AP_INVOICES.vendor_id%TYPE;
695   l_invoice_date               AP_INVOICES.invoice_date%TYPE;
696   l_invoice_currency_code      AP_INVOICES.invoice_currency_code%TYPE;
697   l_invoice_type               AP_INVOICES.invoice_type_lookup_code%TYPE;
698 
699   t_inv_lines_table            AP_INVOICES_PKG.t_invoice_lines_table;
700 
701   l_insufficient_data_exist     BOOLEAN := FALSE;
702   l_line_variance_hold_exist    BOOLEAN := FALSE;
703   l_need_to_round_flag          VARCHAR2(1) := 'Y';
704   l_distribution_variance_exist BOOLEAN;
705   l_result                      BOOLEAN;
706   l_org_id			NUMBER;
707 
708   /* Introduced to handle Consumption Tax */
709   l_invoice_amount_limit        NUMBER;
710   l_hold_future_payments_flag   VARCHAR2(1);
711   l_diff_flag                   VARCHAR2(1);
712   l_success			BOOLEAN;
713   l_error_code			VARCHAR2(4000);
714 
715   Tax_Exception			EXCEPTION;
716   Global_Exception		EXCEPTION;
717   LCM_Exception         EXCEPTION; --Bug 7718385
718   --Retropricing
719   l_invoice_type_lookup_code    AP_INVOICES_ALL.invoice_type_lookup_code%TYPE;
720 
721   l_invoice_type_pr             AP_INVOICES_ALL.invoice_type_lookup_code%TYPE;
722   l_exclude_tax_from_discount   VARCHAR2(1);
723   l_exclude_freight_from_disc   VARCHAR2(1);
724   l_cur_count                   NUMBER := 0;
725   l_prorate_across_all_items    VARCHAR2(1);
726   l_debug_context               VARCHAR2(2000);
727 
728   l_prepay_dist_count           NUMBER;
729   l_retained_amount		NUMBER;
730   l_recouped_amount		NUMBER;
731   l_tolerance_id		NUMBER;
732   l_service_tolerance_id	NUMBER;
733 
734   l_invoice_rec			AP_APPROVAL_PKG.Invoice_Rec;
735 
736   l_api_name                  	CONSTANT VARCHAR2(200) := 'Approve';
737 
738   -- Bug 6648094
739   l_dist_total      NUMBER;
740   l_base_dist_total NUMBER;
741   l_inv_amount      NUMBER;
742   l_inv_base_amount NUMBER;
743   l_item_count      NUMBER;
744   l_row_count       NUMBER:=0;
745   -- Bug 6648094
746   l_invoice_line_count NUMBER :=0; --Bug 6684139
747   l_encumbrance_exists NUMBER := 0; -- Bug 6681580
748 
749   l_inv_header_rec     ap_invoices_all%rowtype;
750   l_event_class_code   zx_trx_headers_gt.event_class_code%TYPE;
751 
752     -- Project LCM 7588322
753   l_lcm_return_status VARCHAR2(30) := FND_API.G_RET_STS_SUCCESS;
754   l_lcm_msg_count     NUMBER;
755   l_lcm_msg_data      VARCHAR2(2000);
756   l_lcm_used          VARCHAR2(1) := 'N';
757   l_unpostable_holds_exist      VARCHAR2(1) := 'N';
758 
759 BEGIN
760 
761   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||p_calling_sequence;
762 
763   IF (p_debug_switch = 'Y') THEN
764      g_debug_mode := 'Y';
765   END IF;
766 
767   Print_Debug (l_api_name, 'AP_APPROVAL_PKG.APPROVE.BEGIN');
768 
769   ----------------------------------------------------------------
770   l_debug_info := 'Approving INVOICE_ID: '|| p_invoice_id;
771   Print_Debug (l_api_name, l_debug_info);
772   ----------------------------------------------------------------
773 
774   IF nvl(p_conc_flag,'N') <> 'Y' THEN
775      g_org_holds.delete;
776   END IF;
777 
778   IF p_calling_mode = 'CANCEL' THEN
779      ----------------------------------------------------------------
780      l_debug_info := 'Open Invoice_Type_Cur';
781      Print_Debug(l_api_name, l_debug_info);
782      ----------------------------------------------------------------
783      OPEN  Invoice_Type_Cur;
784      FETCH Invoice_Type_Cur
785       INTO l_invoice_type_pr;
786      CLOSE Invoice_Type_Cur;
787   END IF;
788 
789 
790   IF (p_calling_mode = 'PAYMENT REQUEST') OR
791      (p_calling_mode = 'CANCEL' and l_invoice_type_pr = 'PAYMENT REQUEST')  THEN
792 
793      ----------------------------------------------------------------
794      l_debug_info := 'Open Approve_Pay_Request_Cur';
795      Print_Debug(l_api_name, l_debug_info);
796      ----------------------------------------------------------------
797      OPEN Approve_Pay_Request_Cur;
798      FETCH Approve_Pay_Request_Cur
799      INTO l_invoice_id,
800           l_invoice_num,
801           l_invoice_amount,
802           l_invoice_base_amount,
803           l_exchange_rate,
804           l_invoice_currency_code,
805           l_invoice_amount_limit,
806           l_hold_future_payments_flag,
807           l_invoice_type,
808           l_exchange_date,
809           l_exchange_rate_type,
810           l_vendor_id,
811           l_invoice_date,
812           g_org_id,
813           l_exclude_tax_from_discount,
814           l_exclude_freight_from_disc;
815 
816   ELSE
817      ----------------------------------------------------------------
818      l_debug_info := 'Open Approve_Invoice_Cur';
819      Print_Debug(l_api_name, l_debug_info);
820      ----------------------------------------------------------------
821      OPEN Approve_Invoice_Cur;
822      FETCH Approve_Invoice_Cur
823      INTO l_invoice_id,
824           l_invoice_num,
825           l_invoice_amount,
826           l_invoice_base_amount,
827           l_exchange_rate,
828           l_invoice_currency_code,
829           l_invoice_amount_limit,
830           l_hold_future_payments_flag,
831           l_invoice_type,
832           l_exchange_date,
833           l_exchange_rate_type,
834           l_vendor_id,
835           l_invoice_date,
836           g_org_id,
837           l_exclude_tax_from_discount,
838           l_exclude_freight_from_disc,
839 	  l_tolerance_id,
840 	  l_service_tolerance_id;
841 
842      IF nvl(p_conc_flag,'N') <> 'Y' THEN
843         ----------------------------------------------------------------
844         l_debug_info := 'Cache Tolerance Templates';
845         Print_Debug(l_api_name, l_debug_info);
846         ----------------------------------------------------------------
847         Cache_Tolerance_Templates(
848                         l_tolerance_id,
849                         l_service_tolerance_id,
850                         l_curr_calling_sequence);
851      END IF;
852 
853   END IF;
854 
855   ----------------------------------------------------------------
856   l_debug_info := 'Retrieve System Options';
857   Print_Debug(l_api_name, l_debug_info);
858   ----------------------------------------------------------------
859   Approval_Init(
860       g_org_id,
861       l_invoice_id,
862       l_invoice_type,
863       l_tolerance_id,
864       l_service_tolerance_id,
865       p_conc_flag,
866       l_set_of_books_id,
867       l_recalc_pay_schedule_flag,
868       l_sys_xrate_gain_ccid,
869       l_sys_xrate_loss_ccid,
870       l_base_currency_code,
871       l_inv_enc_type_id,
872       l_purch_enc_type_id,
873       l_gl_date_from_receipt,
874       l_receipt_acc_days,
875       l_system_user,
876       l_user_id,
877       l_goods_ship_amt_tolerance,
878       l_goods_rate_amt_tolerance,
879       l_goods_total_amt_tolerance,
880       l_services_ship_amt_tolerance,
881       l_services_rate_amt_tolerance,
882       l_services_total_amt_tolerance,
883       l_price_tol,
884       l_qty_tol,
885       l_qty_rec_tol,
886       l_amt_tol,
887       l_amt_rec_tol,
888       l_max_qty_ord_tol,
889       l_max_qty_rec_tol,
890       l_max_amt_ord_tol,
891       l_max_amt_rec_tol,
892       l_invoice_line_count,   --Bug 6684139
893       l_curr_calling_sequence);
894 
895   ----------------------------------------------------------------
896   l_debug_info := 'Initialize Invoice Holds Array';
897   Print_Debug(l_api_name, l_debug_info);
898   ----------------------------------------------------------------
899   Initialize_Invoice_Holds(
900                 p_invoice_id       => p_invoice_id,
901                 p_calling_sequence => l_curr_calling_sequence);
902 
903 
904   IF (p_calling_mode = 'PAYMENT REQUEST') OR
905      (p_calling_mode = 'CANCEL' and l_invoice_type_pr = 'PAYMENT REQUEST') THEN
906      l_cur_count := Approve_Pay_Request_Cur%ROWCOUNT;
907   ELSE
908      l_cur_count := Approve_Invoice_Cur%ROWCOUNT;
909   END IF;
910 
911   IF (l_cur_count <> 0 ) THEN
912 
913     l_any_records_flag := 'Y';
914 
915     -----------------------------------------------------------------------
916     l_debug_info := 'Check run option, to determine whether ok to approve';
917     Print_Debug(l_api_name, l_debug_info);
918     -----------------------------------------------------------------------
919 
920     IF Inv_Needs_Approving(
921 	            p_invoice_id,
922 	            p_run_option,
923 	            l_curr_calling_sequence) THEN
924 
925       l_matched := Get_Inv_Matched_Status(
926 	                     l_invoice_id,
927 	                     l_curr_calling_sequence);
928 
929       IF (p_calling_mode = 'APPROVE'
930 	  and nvl(p_conc_flag,'N') <> 'Y'
931           and l_invoice_line_count >0 ) THEN   --Bug 6684139
932 
933          ----------------------------------------------------------------
934          l_debug_info := 'Calculate Tax on the Invoice';
935          Print_Debug(l_api_name, l_debug_info);
936          ----------------------------------------------------------------
937          l_success := ap_etax_pkg.calling_etax(
938                            p_invoice_id		=> l_invoice_id,
939                            p_calling_mode 	=> 'CALCULATE',
940                            p_all_error_messages	=> 'N',
941                            p_error_code		=> l_error_code,
942                            p_calling_sequence	=> l_curr_calling_sequence);
943 
944          IF (NOT l_success) THEN
945              RAISE Tax_Exception;
946          END IF;
947       END IF;
948 
949       ----------------------------------------------------------------
950       l_debug_info := 'Fetch Invoice Lines';
951       Print_Debug(l_api_name, l_debug_info);
952       ----------------------------------------------------------------
953       OPEN  Invoice_Line_Cur(p_invoice_id);
954       FETCH Invoice_Line_Cur
955       BULK  COLLECT INTO t_inv_lines_table;
956       CLOSE Invoice_Line_Cur;
957 
958       IF nvl(p_conc_flag, 'N') <> 'Y' THEN
959 
960          l_invoice_rec.invoice_id 		:= l_invoice_id;
961          l_invoice_rec.invoice_date 		:= l_invoice_date;
962          l_invoice_rec.invoice_currency_code 	:= l_invoice_currency_code;
963          l_invoice_rec.exchange_rate 	   	:= l_exchange_rate;
964          l_invoice_rec.exchange_rate_type	:= l_exchange_rate_type;
965          l_invoice_rec.exchange_date 		:= l_exchange_date;
966          l_invoice_rec.vendor_id		:= l_vendor_id;
967          l_invoice_rec.org_id			:= l_org_id;
968 
969         ----------------------------------------------------------------
970         l_debug_info := 'Generate Distributions. Variance Checks';
971         Print_Debug(l_api_name, l_debug_info);
972         ----------------------------------------------------------------
973 
974 	--bugfix:6684139/6699825
975 	IF (l_invoice_line_count > 0) THEN
976             AP_APPROVAL_PKG.Generate_Distributions
977                                 (p_invoice_rec        => l_invoice_rec,
978 				 p_base_currency_code => l_base_currency_code,
979                                  p_inv_batch_id       => p_invoice_batch_id, /*Bug#7036685 : Passed p_invoice_batch_id to
980 				                                               p_inv_batch_id parameter instead of NULL*/
981                                  p_run_option         => NULL,
982                                  p_calling_sequence   => l_curr_calling_sequence,
983                                  x_error_code         => l_error_code,
984 				 p_calling_mode       => p_calling_mode);   /*bug6833543 added p_calling_mode*/
985         END IF;
986 
987         IF (p_calling_mode = 'APPROVE' and l_invoice_line_count >0 ) THEN   --Bug 6684139
988 
989             ----------------------------------------------------------------
990   	    l_debug_info := 'Generate Tax Distributions';
991             Print_Debug(l_api_name, l_debug_info);
992        	    ----------------------------------------------------------------
993 	    l_success := ap_etax_pkg.calling_etax(
994 	                           p_invoice_id		=> p_invoice_id,
995 	                           p_calling_mode	=> 'DISTRIBUTE',
996 	                           p_all_error_messages => 'N',
997 	                           p_error_code 	=>  l_error_code,
998 	                           p_calling_sequence 	=> l_curr_calling_sequence);
999 
1000             IF (NOT l_success) THEN
1001                 Raise Tax_Exception;
1002             END IF;
1003         END IF;
1004       END IF; /* nvl(p_conc_flag, 'N')... */
1005 
1006       IF (nvl(t_inv_lines_table.count,0) <> 0 ) THEN
1007 
1008   -- Perf 6759699
1009   -- if p_run_option is not new then we can call this function
1010   -- for a invoice id
1011        IF (nvl(p_run_option,'Yes') <> 'New') THEN
1012           Update_Inv_Dists_To_Selected(     l_invoice_id,
1013                                             null ,
1014                                             p_run_option,
1015                                             l_curr_calling_sequence);
1016         ELSE
1017              FOR i IN NVL(t_inv_lines_table.first,0)..NVL(t_inv_lines_table.last,0)
1018           LOOP
1019               ----------------------------------------------------------------
1020               l_debug_info := 'Update Invoice Distributions to SELECTED';
1021               Print_Debug(l_api_name, l_debug_info);
1022               ----------------------------------------------------------------
1023               -- Update distributions to SELECTED as new inclusive/exclusive
1024               -- tax distributions could have been created.
1025 
1026               Update_Inv_Dists_To_Selected(
1027                                     l_invoice_id,
1028                                     t_inv_lines_table(i).line_number,
1029                                     p_run_option,
1030                                     l_curr_calling_sequence);
1031           END LOOP;      --bug6661773
1032        END IF; --p_run_option
1033 
1034               ----------------------------------------------------------------
1035   	      l_debug_info := 'Check Distribution Variance';
1036               Print_Debug(l_api_name, l_debug_info);
1037        	      ----------------------------------------------------------------
1038 
1039               Check_Dist_Variance(
1040 	            l_invoice_id,
1041 	            null,          --bug6661773
1042 	            l_system_user,
1043 	            l_holds,
1044 	            l_hold_count,
1045 	            l_release_count,
1046 	            l_distribution_variance_exist,
1047 	            l_curr_calling_sequence);
1048           --END LOOP;
1049       END IF;
1050 
1051    ----------------------------------------------------------------
1052    l_debug_info := 'Create payment schedule for invoice request';
1053    Print_Debug(l_api_name, l_debug_info);
1054    ----------------------------------------------------------------
1055    createPaymentSchedules(l_invoice_id, l_curr_calling_sequence);
1056 
1057 
1058    FOR i IN nvl(t_inv_lines_table.first,0)..nvl(t_inv_lines_table.last,0) LOOP
1059 
1060       IF (t_inv_lines_table.exists(i)) THEN
1061 
1062         IF (l_base_currency_code <> l_invoice_currency_code) AND
1063            (t_inv_lines_table(i).match_type <> 'ADJUSTMENT_CORRECTION') THEN
1064 
1065            ----------------------------------------------------------------
1066            l_debug_info := 'Distributions: Calculate Base Amount and Round';
1067            Print_Debug(l_api_name, l_debug_info);
1068            ----------------------------------------------------------------
1069 
1070            IF ( l_line_variance_hold_exist = TRUE  OR
1071                 l_distribution_variance_exist = TRUE ) THEN
1072              l_need_to_round_flag := 'N';
1073            END IF;
1074 
1075            Dist_Base_Amount_Calculation(
1076 	              p_invoice_id            => l_invoice_id,
1077 	              p_invoice_line_number   => t_inv_lines_table(i).line_number,
1078 	              p_invoice_currency_code => l_invoice_currency_code,
1079 	              p_base_currency_code    => l_base_currency_code,
1080 	              p_invoice_exchange_rate => l_exchange_rate,
1081 	              p_need_to_round_flag    => l_need_to_round_flag,
1082 	              p_calling_sequence      => l_curr_calling_sequence );
1083 
1084         END IF;
1085 
1086 	DECLARE
1087 	   l_awt_success   Varchar2(1000);
1088 	BEGIN
1089            ----------------------------------------------------------------
1090            l_debug_info := 'Call Extended Withholding Routine';
1091            Print_Debug(l_api_name, l_debug_info);
1092            ----------------------------------------------------------------
1093 	   Ap_Extended_Withholding_Pkg.Ap_Ext_Withholding_Default
1094 		                    (p_invoice_id 	=> p_invoice_id,
1095 		                     p_inv_line_num 	=> t_inv_lines_table(i).line_number,
1096 				     p_inv_dist_id  	=> NULL,
1097 		                     p_calling_module 	=> l_curr_calling_sequence,
1098 				     p_parent_dist_id 	=> NULL,
1099 		                     p_awt_success 	=> l_awt_success);
1100 
1101 	   IF (l_awt_success <> 'SUCCESS') THEN
1102 	       RAISE Global_Exception;
1103 	   END IF;
1104 	END;
1105 
1106       END IF; /* t_inv_lines_table.exists ...*/
1107    END LOOP;
1108 
1109    t_inv_lines_table.DELETE;
1110 
1111    -- Bug 6648094
1112    -- Adjust distribution base amount if dist variance does not exist.
1113    -- Needed only for foreign currency invoices which have an exchange
1114    -- rate and the distribution base amts do not add up to invoice
1115    -- base amt.
1116    ---------------------------------------------------------------
1117    l_debug_info := 'Adjust Dists Base Amount for foreign currency rounding';
1118    Print_Debug(l_api_name, l_debug_info);
1119    ---------------------------------------------------------------
1120 
1121    IF ( l_line_variance_hold_exist = FALSE AND
1122         l_distribution_variance_exist = FALSE ) THEN
1123 
1124       IF (l_base_currency_code <> l_invoice_currency_code) THEN
1125 
1126         SELECT SUM(amount)
1127         INTO   l_dist_total
1128         FROM   ap_invoice_distributions
1129         WHERE  invoice_id = l_invoice_id
1130         AND    (  (line_type_lookup_code NOT IN ('PREPAY','AWT') AND
1131                    prepay_tax_parent_id IS NULL)                 OR
1132                   (line_type_lookup_code = 'PREPAY'              AND
1133                    nvl(invoice_includes_prepay_flag,'N') = 'Y')  OR
1134                   (line_type_lookup_code IN ('REC_TAX', 'NONREC_TAX',
1135                                              'TERV','TIPV','TRV') AND
1136                    nvl(invoice_includes_prepay_flag,'N') = 'Y'   AND
1137                    prepay_tax_parent_id IS NOT NULL)
1138                 );
1139         ---------------------------------------------------------------
1140         l_debug_info := 'Sum of Distributions Amounts: '|| l_dist_total;
1141         Print_Debug(l_api_name, l_debug_info);
1142         ---------------------------------------------------------------
1143 
1144         SELECT invoice_amount, base_amount
1145         INTO   l_inv_amount  , l_inv_base_amount
1146         FROM   ap_invoices
1147         WHERE  invoice_id = l_invoice_id;
1148 
1149         ---------------------------------------------------------------
1150         l_debug_info := 'Invoice amount: '|| l_inv_amount ||
1151                         ' Invoice base amount: '||l_inv_base_amount;
1152         Print_Debug(l_api_name, l_debug_info);
1153         ---------------------------------------------------------------
1154 
1155         SELECT COUNT('X')
1156         INTO   l_item_count
1157         FROM   ap_invoice_distributions
1158         WHERE  invoice_id = l_invoice_id AND
1159                line_type_lookup_code = 'ITEM';
1160 
1161         IF (l_dist_total = l_inv_amount) THEN
1162 
1163            SELECT SUM(base_amount)
1164            INTO   l_base_dist_total
1165            FROM   ap_invoice_distributions
1166            WHERE  invoice_id = l_invoice_id
1167            AND    (
1168                   (line_type_lookup_code NOT IN ('PREPAY','AWT') AND
1169                    prepay_tax_parent_id IS NULL)                     OR
1170                   (line_type_lookup_code = 'PREPAY' AND
1171                    nvl(invoice_includes_prepay_flag,'N') = 'Y')      OR
1172                   (line_type_lookup_code IN ('REC_TAX', 'NONREC_TAX',
1173                                              'TERV','TIPV','TRV') AND
1174                    nvl(invoice_includes_prepay_flag,'N') = 'Y'   AND
1175                    prepay_tax_parent_id IS NOT NULL)
1176                   );
1177            ---------------------------------------------------------------
1178            l_debug_info := 'Sum of Distributions Base Amounts: '||
1179                            l_base_dist_total;
1180            Print_Debug(l_api_name, l_debug_info);
1181            ---------------------------------------------------------------
1182 
1183            IF (l_inv_base_amount <> l_base_dist_total) THEN
1184 
1185            ---------------------------------------------------------------
1186            l_debug_info := 'Adjust for rounding';
1187            ---------------------------------------------------------------
1188            IF (l_item_count > 0) THEN
1189               --Update ITEM Dists
1190               UPDATE ap_invoice_distributions
1191               SET    base_amount = base_amount - (l_base_dist_total - l_inv_base_amount)
1192               WHERE  invoice_id = l_invoice_id
1193               AND    invoice_distribution_id = (
1194                            SELECT MAX(AID1.invoice_distribution_id)
1195                            FROM ap_invoice_distributions AID1
1196                            WHERE AID1.invoice_id = l_invoice_id
1197                            AND   AID1.line_type_lookup_code = 'ITEM'
1198                           /* Bug 3784909. Folowing two lines Added */
1199                            AND NVL(AID1.reversal_flag, 'N') <> 'Y'
1200                            AND NVL(AID1.posted_flag, 'N') = 'N'
1201                            AND ABS(AID1.amount) = (
1202                                  SELECT MAX(ABS(AID2.amount))
1203                                  FROM ap_invoice_distributions AID2
1204                                  WHERE AID2.invoice_id = l_invoice_id
1205                                  AND AID2.line_type_lookup_code = 'ITEM'
1206                                  -- Bug 3784909. Folowing two lines Added
1207                                  AND NVL(AID2.reversal_flag, 'N') <> 'Y'
1208                                  AND NVL(AID2.posted_flag, 'N') = 'N'));
1209            ELSE
1210               -- Update FREIGHT or MISC Dists
1211               UPDATE ap_invoice_distributions
1212               SET    base_amount = base_amount - (l_base_dist_total - l_inv_base_amount)
1213               WHERE  invoice_id = l_invoice_id
1214               AND    invoice_distribution_id = (
1215                            SELECT MAX(AID3.invoice_distribution_id)
1216                            FROM   ap_invoice_distributions AID3
1217                            WHERE  AID3.invoice_id = l_invoice_id
1218                            AND    AID3.line_type_lookup_code
1219                                   IN ('FREIGHT','MISCELLANEOUS')
1220                            AND
1221                            /* Bug 3784909. Folowing two lines Added */
1222                                   NVL(AID3.reversal_flag, 'N') = 'N'
1223                            AND    NVL(AID3.posted_flag, 'N') = 'N'
1224                            AND   ABS(AID3.amount) = (
1225                                  SELECT MAX(ABS(AID4.amount))
1226                                  FROM ap_invoice_distributions AID4
1227                                  WHERE AID4.invoice_id = l_invoice_id
1228                                  AND   AID4.line_type_lookup_code
1229                                        IN('FREIGHT','MISCELLANEOUS')
1230                                  --Bug 3784909. Folowing two lines Added
1231                                  AND NVL(AID4.reversal_flag, 'N') <> 'Y'
1232                                  AND NVL(AID4.posted_flag, 'N') = 'N'));
1233            END IF;  --IF (l_item_count > 0)
1234 
1235                 l_row_count := SQL%ROWCOUNT;
1236                  IF (l_row_count > 0) THEN
1237                     ---------------------------------------------------------
1238                     l_debug_info := l_row_count||' rows updated.';
1239                     Print_Debug(l_api_name, l_debug_info);
1240                     ---------------------------------------------------------
1241                  ELSE
1242                     ---------------------------------------------------------
1243                     l_debug_info := 'No rows Updated';
1244                     Print_Debug(l_api_name, l_debug_info);
1245                     ---------------------------------------------------------
1246                  END IF;
1247            END IF; -- IF (l_dist_total = l_inv_amount)
1248         END IF; -- IF (l_dist_total = l_inv_amount)
1249       END IF; -- If inv currency <> base currency
1250    END IF; -- If l_distribution_variance_exist = TRUE
1251    -- Bug 6648094 Ends
1252 
1253    ----------------------------------------------------------------
1254    l_debug_info := 'Update Total Distribution Amount';
1255    Print_Debug(l_api_name, l_debug_info);
1256    ----------------------------------------------------------------
1257    Update_Total_Dist_Amount(l_invoice_id,
1258                             l_curr_calling_sequence);
1259 
1260    SELECT invoice_type_lookup_code
1261      INTO l_invoice_type_lookup_code
1262      FROM ap_invoices_all
1263     WHERE invoice_id = l_invoice_id;
1264 
1265    IF ((l_exclude_tax_from_discount = 'Y' OR l_exclude_freight_from_disc = 'Y')
1266         OR (l_invoice_type_lookup_code IN ('PO PRICE ADJUST','ADJUSTMENT'))) THEN
1267 
1268          ----------------------------------------------------------------
1269          l_debug_info := 'Exclude Tax/Freight: Recalculate Payment Schedules';
1270          Print_Debug(l_api_name, l_debug_info);
1271          ----------------------------------------------------------------
1272          Exclude_Tax_Freight_From_Disc(
1273 				l_invoice_id,
1274 				l_exclude_tax_from_discount,
1275 				l_exclude_freight_from_disc,
1276 				l_invoice_type_lookup_code,
1277 				l_curr_calling_sequence);
1278 
1279           IF (l_invoice_type in ('PO PRICE ADJUST','ADJUSTMENT')) THEN
1280               ----------------------------------------------------------------
1281               l_debug_info := 'Retropricing: Check Line Variance';
1282               Print_Debug(l_api_name, l_debug_info);
1283               ----------------------------------------------------------------
1284               Check_Line_Variance(
1285 		          l_invoice_id,
1286 		          l_system_user,
1287 		          l_holds,
1288 		          l_hold_count,
1289 		          l_release_count,
1290 		          l_line_variance_hold_exist,
1291 		          l_curr_calling_sequence,
1292 			  l_base_currency_code);   --bug 7271262
1293           END IF;
1294    END IF;
1295 
1296    ----------------------------------------------------------------
1297    l_debug_info := 'Execute General Checks';
1298    Print_Debug(l_api_name, l_debug_info);
1299    ----------------------------------------------------------------
1300    Execute_General_Checks(
1301           l_invoice_id,
1302           l_set_of_books_id,
1303           l_base_currency_code,
1304           l_invoice_amount,
1305           l_invoice_base_amount,
1306           l_invoice_currency_code,
1307           l_invoice_amount_limit,
1308           l_hold_future_payments_flag,
1309           l_system_user,
1310           l_holds,
1311           l_hold_count,
1312           l_release_count,
1313           l_curr_calling_sequence);
1314 
1315    IF (l_matched) THEN
1316 
1317        ----------------------------------------------------------------
1318        l_debug_info := 'Execute Quantity Variance Check';
1319        Print_Debug(l_api_name, l_debug_info);
1320        ----------------------------------------------------------------
1321        IF l_invoice_type_lookup_code <> 'PO PRICE ADJUST' THEN
1322           AP_APPROVAL_MATCHED_PKG.Exec_Qty_Variance_Check(
1323 	            p_invoice_id         => l_invoice_id,
1324 	            p_base_currency_code => l_base_currency_code,
1325 	            p_inv_currency_code  => l_invoice_currency_code,
1326 	            p_system_user        => l_system_user,
1327 	            p_calling_sequence   => l_curr_calling_sequence);
1328        END IF;
1329 
1330        ----------------------------------------------------------------
1331        l_debug_info := 'Execute Amount Variance Check';
1332        Print_Debug(l_api_name, l_debug_info);
1333        ----------------------------------------------------------------
1334        AP_APPROVAL_MATCHED_PKG.Exec_Amt_Variance_Check(
1335 	            p_invoice_id         => l_invoice_id,
1336 	            p_base_currency_code => l_base_currency_code,
1337 	            p_inv_currency_code  => l_invoice_currency_code,
1338 	            p_system_user        => l_system_user,
1339 	            p_calling_sequence   => l_curr_calling_sequence );
1340 
1341        -- 7299826 EnC project
1342        ----------------------------------------------------------------
1343        l_debug_info := 'Execute Pay when paid Check';
1344        Print_Debug(l_api_name, l_debug_info);
1345        ----------------------------------------------------------------
1346        AP_APPROVAL_MATCHED_PKG.exec_pay_when_paid_check(
1347                                  p_invoice_id       => l_invoice_id,
1348                                  p_system_user      => l_system_user,
1349                                  p_holds            => l_holds,
1350                                  p_holds_count      => l_hold_count,
1351                                  p_release_count    => l_release_count,
1352                                  p_calling_sequence => l_curr_calling_sequence);
1353 
1354        -- 7299826 EnC project
1355        ----------------------------------------------------------------
1356        l_debug_info := 'Execute PO Deliverable Check';
1357        Print_Debug(l_api_name, l_debug_info);
1358        ----------------------------------------------------------------
1359        AP_APPROVAL_MATCHED_PKG.exec_po_deliverable_check(
1360                                  p_invoice_id       => l_invoice_id,
1361                                  p_system_user      => l_system_user,
1362                                  p_holds            => l_holds,
1363                                  p_holds_count      => l_hold_count,
1364                                  p_release_count    => l_release_count,
1365                                  p_calling_sequence => l_curr_calling_sequence);
1366 
1367        ----------------------------------------------------------------
1368        l_debug_info := 'Execute Matched Checks';
1369        Print_Debug(l_api_name, l_debug_info);
1370        ----------------------------------------------------------------
1371        AP_APPROVAL_MATCHED_PKG.Execute_Matched_Checks(
1372 	            p_invoice_id          		=> l_invoice_id,
1373 	            p_base_currency_code  		=> l_base_currency_code,
1374 	            p_price_tol           		=> l_price_tol,
1375 	            p_qty_tol             		=> l_qty_tol,
1376 	            p_qty_rec_tol         		=> l_qty_rec_tol,
1377 	            p_amt_tol		  		=> l_amt_tol,
1378 		    p_amt_rec_tol	  		=> l_amt_rec_tol,
1379 	            p_max_qty_ord_tol     		=> l_max_qty_ord_tol,
1380 	            p_max_qty_rec_tol     		=> l_max_qty_rec_tol,
1381 		    p_max_amt_ord_tol     		=> l_max_amt_ord_tol,
1382 		    p_max_amt_rec_tol     		=> l_max_amt_rec_tol,
1383 	            p_goods_ship_amt_tolerance  	=> l_goods_ship_amt_tolerance,
1384 	            p_goods_rate_amt_tolerance  	=> l_goods_rate_amt_tolerance,
1385 	            p_goods_total_amt_tolerance 	=> l_goods_total_amt_tolerance,
1386 	            p_services_ship_amt_tolerance  	=> l_services_ship_amt_tolerance,
1387 	            p_services_rate_amt_tolerance  	=> l_services_rate_amt_tolerance,
1388 	            p_services_total_amt_tolerance 	=> l_services_total_amt_tolerance,
1389 	            p_system_user         		=> l_system_user,
1390 	            p_conc_flag           		=> p_conc_flag,
1391 	            p_holds               		=> l_holds,
1392 	            p_holds_count         		=> l_hold_count,
1393 	            p_release_count       		=> l_release_count,
1394 	            p_calling_sequence    		=> l_curr_calling_sequence);
1395 
1396        ----------------------------------------------------------------
1397        l_debug_info := 'Execute PO Final Close';
1398        Print_Debug(l_api_name, l_debug_info);
1399        ----------------------------------------------------------------
1400        AP_APPROVAL_MATCHED_PKG.Exec_PO_Final_Close(
1401 	                l_invoice_id,
1402 	                l_system_user,
1403 	                p_conc_flag,
1404 	                l_holds,
1405 	                l_hold_count,
1406 	                l_release_count,
1407 	                l_curr_calling_sequence);
1408 
1409    END IF;  -- end of matched check
1410 
1411    IF (p_calling_mode = 'APPROVE' and l_invoice_line_count >0 ) THEN --bug 6684139
1412        ----------------------------------------------------------------
1413        l_debug_info := 'Validate Invoice for Tax';
1414        Print_Debug(l_api_name, l_debug_info);
1415        ----------------------------------------------------------------
1416        l_success := ap_etax_pkg.calling_etax(
1417 	                       p_invoice_id 		=> p_invoice_id,
1418 			       p_calling_mode		=> 'VALIDATE',
1419 			       p_all_error_messages	=> 'N',
1420 			       p_error_code		=>  l_error_code,
1421 			       p_calling_sequence	=> l_curr_calling_sequence);
1422 
1423          IF (NOT l_success) THEN
1424             IF (nvl(p_conc_flag,'N') = 'N') THEN
1425                 Raise Tax_Exception;
1426             ELSE
1427 	        NULL;
1428             END IF;
1429          END IF;
1430    END IF;
1431 
1432    ----------------------------------------------------------------
1433    l_debug_info := 'Call GMS API to ensure missing ADLs are generated';
1434    Print_Debug(l_api_name, l_debug_info);
1435    ----------------------------------------------------------------
1436    GMS_AP_API2.verify_create_adls
1437 			(l_invoice_id,
1438 			 l_curr_calling_sequence);
1439 
1440    ----------------------------------------------------------------
1441    l_debug_info := 'Execute Withholding';
1442    Print_Debug(l_api_name, l_debug_info);
1443    ----------------------------------------------------------------
1444    Withhold_Tax_On(
1445           l_invoice_id,
1446           l_gl_date_from_receipt,
1447           l_system_user,
1448           l_system_user,
1449           -1,
1450           -1,
1451           -1,
1452           l_system_user,
1453           l_holds,
1454           l_hold_count,
1455           l_release_count,
1456           l_curr_calling_sequence);
1457 
1458    ----------------------------------------------------------------
1459    l_debug_info := 'Create Prepayment Application Distributions';
1460    Print_Debug(l_api_name, l_debug_info);
1461    ----------------------------------------------------------------
1462    SELECT count(*)
1463      INTO l_prepay_dist_count
1464      FROM ap_invoice_distributions_all
1465     WHERE Invoice_ID 		= l_invoice_id
1466       AND Line_Type_Lookup_Code = 'PREPAY'
1467       AND Accounting_Event_ID   IS NULL;
1468 
1469    IF l_prepay_dist_count > 0 THEN
1470       ap_acctg_prepay_dist_pkg.prepay_dist_appl(
1471 	             l_invoice_id,
1472 	             l_curr_calling_sequence);
1473    END IF;
1474 
1475    ----------------------------------------------------------------
1476    l_debug_info := 'Execute Budgetary Control';
1477    Print_Debug(l_api_name, l_debug_info);
1478    ----------------------------------------------------------------
1479 
1480    IF p_budget_control = 'Y' THEN
1481 
1482       l_debug_info := 'p_budget_control is Y';
1483       Print_Debug(l_api_name, l_debug_info);
1484       -- Bug 6681580
1485       select count(*)
1486       INTO   l_encumbrance_exists
1487       FROM   ap_invoice_distributions aid
1488       WHERE  nvl(aid.encumbered_flag,'N') not in ('N','R')        ----added check for 'R' due to bug 7264524
1489       AND    aid.invoice_id = l_invoice_id;
1490 
1491       -- Bug 6681580
1492       IF p_calling_mode =  'CANCEL' AND l_encumbrance_exists = 0 THEN
1493          l_debug_info := 'Calling Mode is CANCEL and No Prior Encumb';
1494          Print_Debug(l_api_name, l_debug_info);
1495       ELSE
1496          l_debug_info := 'Calling AP_FUNDS_CONTROL_PKG.Funds_Reserve';
1497          Print_Debug(l_api_name, l_debug_info);
1498 
1499          AP_FUNDS_CONTROL_PKG.Funds_Reserve(
1500 	            p_calling_mode,
1501 	            l_invoice_id,
1502 	            l_set_of_books_id,
1503 	            l_base_currency_code,
1504 	            p_conc_flag,
1505 	            l_system_user,
1506 	            l_holds,
1507 	            l_hold_count,
1508 	            l_release_count,
1509 	            p_funds_return_code,
1510 	            l_curr_calling_sequence);
1511       END IF; -- Bug 6681580
1512    END IF;
1513 
1514 
1515    -- Project LCM 7588322
1516    /*Check whether this invoice is matched to any LCM enabled receipt*/
1517    BEGIN
1518 	   SELECT 'Y'
1519 	   INTO l_lcm_used
1520 	   FROM DUAL
1521 	   WHERE EXISTS
1522 	       (SELECT 1 FROM AP_INVOICE_DISTRIBUTIONS aid, RCV_TRANSACTIONS rt
1523 				  WHERE aid.invoice_id         = l_invoice_id
1524 					AND   aid.rcv_transaction_id = rt.transaction_id
1525 					AND   rt.lcm_shipment_line_id IS NOT NULL
1526 					AND   aid.match_status_flag = 'S');
1527    EXCEPTION
1528        WHEN NO_DATA_FOUND THEN NULL;
1529    END;
1530 
1531    /*Check if there are unpostable holds put on this invoice by now.
1532      If any such holds are there, we should not be calling LCM to
1533      pick this invoice to LCM.*/
1534    -- Added by 7641045, modified by 7678786, modification reverted by 7830298
1535    BEGIN
1536              SELECT 'Y'
1537              INTO l_unpostable_holds_exist
1538              FROM dual
1539              WHERE EXISTS (SELECT 1
1540                             FROM    ap_holds H, ap_hold_codes C
1541                             WHERE   H.invoice_id = l_invoice_id
1542                             AND     H.hold_lookup_code = C.hold_lookup_code
1543                             AND     ((H.release_lookup_code IS NULL)
1544                             AND     ((C.postable_flag = 'N') OR (C.postable_flag = 'X'))));
1545       /* The condition above is same as the one used in Update_Inv_Dists_To_Approved
1546       procedure. However, we removed encumbrance checks.*/
1547 
1548     EXCEPTION
1549        WHEN NO_DATA_FOUND THEN NULL;
1550     END;
1551 
1552 
1553 
1554     IF(l_lcm_used = 'Y') THEN
1555      IF (l_unpostable_holds_exist <> 'Y') THEN -- Bug 7641045
1556 
1557 	   ----------------------------------------------------------------
1558 	   l_debug_info := 'Call LCM API';
1559 	   Print_Debug(l_api_name, l_debug_info);
1560 	   ----------------------------------------------------------------
1561 
1562 	   --EXECUTE IMMEDIATE
1563 	   INL_MATCH_GRP.Create_MatchesFromAP
1564 	   (p_api_version    => 1.0, -- API version
1565 	    p_init_msg_list  => FND_API.G_TRUE, -- This is to initialize the message list whenever the API is called, not cumulating messages from one execution to other
1566 	    p_commit         => FND_API.G_FALSE, -- This is to not issue any commit inside the API, since commit cycle is managed by the calling program
1567 	    p_invoice_id     => l_invoice_id,
1568 	    x_return_status  => l_lcm_return_status, -- Returns "S", "E" or "U", i.e. FND_API.G_RET_STS_SUCCESS , FND_API.G_RET_STS_ERROR or FND_API.G_RET_STS_UNEXP_ERROR.
1569 	    x_msg_count      => l_lcm_msg_count, -- Number of messages in the list
1570 	    x_msg_data       => l_lcm_msg_data); -- Messages stored in encoded format
1571 
1572 	   IF(l_lcm_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1573        -- Bug 7718385
1574        RAISE LCM_Exception;
1575 	   END IF;
1576     END IF; -- l_unpostable_holds_exist <> 'Y'
1577    END IF; -- l_lcm_used = 'Y'
1578 
1579    -- End Project LCM 7588322
1580 
1581    ----------------------------------------------------------------
1582    l_debug_info := 'Update Invoice Distributions to APPROVED';
1583    Print_Debug(l_api_name, l_debug_info);
1584    ----------------------------------------------------------------
1585    Update_Inv_Dists_To_Approved(
1586 	          l_invoice_id,
1587 	          l_user_id,
1588 	          l_curr_calling_sequence);
1589 
1590    ----------------------------------------------------------------
1591    l_debug_info := 'Generate Accounting Events';
1592    Print_Debug(l_api_name, l_debug_info);
1593    ----------------------------------------------------------------
1594    Generate_Account_Event(
1595             l_invoice_id,
1596             l_curr_calling_sequence);
1597 
1598 
1599    END IF; -- end of Inv_Needs_Approving...
1600 
1601    ----------------------------------------------------------------
1602    l_debug_info := 'Execute Due Date Sweeper after validation';
1603    Print_Debug(l_api_name, l_debug_info);
1604    ----------------------------------------------------------------
1605 
1606    IF (l_recalc_pay_schedule_flag = 'Y') THEN
1607 
1608       SELECT DECODE(NVL((MAX(aps.last_update_date)- MIN(aps.creation_date)),0),
1609                      0,'N','Y')
1610         INTO l_diff_flag
1611         FROM ap_payment_schedules aps
1612        WHERE aps.invoice_id = l_invoice_id;
1613 
1614       IF (l_diff_flag = 'N') THEN
1615         AP_PPA_PKG.Due_Date_Sweeper(
1616                 l_invoice_id,
1617                 l_matched,
1618                 l_system_user,
1619                 l_receipt_acc_days,
1620                 l_curr_calling_sequence);
1621       END IF;
1622    END IF;
1623 
1624    ----------------------------------------------------------------
1625    l_debug_info := 'Update force_revalidation_flag to No';
1626    Print_Debug(l_api_name, l_debug_info);
1627    ----------------------------------------------------------------
1628 
1629    UPDATE ap_invoices_all
1630       SET force_revalidation_flag = 'N'
1631     WHERE invoice_id = l_invoice_id;
1632 
1633   END IF; -- end of approve_invoice_cur cursor count check
1634 
1635 
1636   IF (p_calling_mode = 'PAYMENT REQUEST') OR
1637      (p_calling_mode = 'CANCEL' and l_invoice_type_pr = 'PAYMENT REQUEST')  THEN
1638      ----------------------------------------------------------------
1639      l_debug_info := 'Close approve_pay_request_cur';
1640      Print_Debug(l_api_name, l_debug_info);
1641      ----------------------------------------------------------------
1642      CLOSE approve_pay_request_cur;
1643   ELSE
1644      ----------------------------------------------------------------
1645      l_debug_info := 'Close approve_invoice_cursor';
1646      Print_Debug(l_api_name, l_debug_info);
1647      ----------------------------------------------------------------
1648      CLOSE approve_invoice_cur;
1649   END IF;
1650 
1651   ----------------------------------------------------------------
1652   l_debug_info := 'Retrieve total hold count and validation status';
1653   Print_Debug(l_api_name, l_debug_info);
1654   ----------------------------------------------------------------
1655   Get_Invoice_Statuses(
1656 	      l_invoice_id,
1657 	      p_holds_count,
1658 	      p_approval_status,
1659 	      l_curr_calling_sequence);
1660 
1661   ----------------------------------------------------------------
1662   l_debug_info := 'Validation Status: '||p_approval_status;
1663   Print_Debug(l_api_name, l_debug_info);
1664   ----------------------------------------------------------------
1665 
1666   IF  p_calling_mode = 'APPROVE' THEN
1667 
1668       IF l_invoice_line_count > 0 THEN
1669 
1670          BEGIN
1671           SELECT *
1672             INTO l_inv_header_rec
1673             FROM ap_invoices_all
1674            WHERE invoice_id = P_Invoice_Id;
1675          END;
1676 	--BUG 6974733
1677       IF (l_inv_header_rec.invoice_type_lookup_code NOT IN ('AWT', 'INTEREST')) THEN
1678          -------------------------------------------------------------------
1679          l_debug_info := 'Get event class code';
1680          Print_Debug(l_api_name, l_debug_info);
1681          -------------------------------------------------------------------
1682          IF NOT(AP_ETAX_UTILITY_PKG.Get_Event_Class_Code(
1683 			P_Invoice_Type_Lookup_Code => l_inv_header_rec.invoice_type_lookup_code,
1684 			P_Event_Class_Code         => l_event_class_code,
1685 			P_error_code               => l_error_code,
1686 			P_calling_sequence         => l_curr_calling_sequence)) THEN
1687 
1688             IF (nvl(p_conc_flag,'N') = 'N') THEN
1689                 Raise Tax_Exception;
1690             ELSE
1691                 NULL;
1692             END IF;
1693          END IF;
1694 
1695          -----------------------------------------------------------------
1696          l_debug_info := 'Call Freeze Distributions';
1697          Print_Debug(l_api_name, l_debug_info);
1698          -----------------------------------------------------------------
1699          --Bug7592845
1700          IF NOT(AP_ETAX_SERVICES_PKG.Freeze_itm_Distributions(
1701                         P_Invoice_Header_Rec  => l_inv_header_rec,
1702                         P_Calling_Mode        => 'FREEZE DISTRIBUTIONS',
1703                         P_Event_Class_Code    => l_event_class_code,
1704                         P_All_Error_Messages  => 'N',
1705                         P_Error_Code          => l_error_code,
1706                         P_Calling_Sequence    => l_curr_calling_sequence)) THEN
1707 
1708             IF (nvl(p_conc_flag,'N') = 'N') THEN
1709                 Raise Tax_Exception;
1710             ELSE
1711                 NULL;
1712             END IF;
1713          END IF;
1714     END IF;--BUG 6974733
1715          IF p_approval_status IN ('APPROVED','AVAILABLE','UNPAID','FULL') THEN
1716 
1717             ----------------------------------------------------------------
1718             l_debug_info := 'Call API to freeze invoice in tax schema';
1719             Print_Debug(l_api_name, l_debug_info);
1720             ----------------------------------------------------------------
1721             l_success := ap_etax_pkg.calling_etax(
1722 				p_invoice_id		=> p_invoice_id,
1723 				p_calling_mode		=> 'FREEZE INVOICE',
1724 				p_all_error_messages	=> 'N',
1725 				p_error_code		=> l_error_code,
1726 				p_calling_sequence	=> l_curr_calling_sequence);
1727 
1728             IF (NOT l_success) THEN
1729                 IF (nvl(p_conc_flag,'N') = 'N') THEN
1730                     Raise Tax_Exception;
1731                 ELSE
1732                     NULL;
1733                 END IF;
1734             END IF;
1735           END IF;
1736       END IF;
1737   END IF;
1738 
1739   AP_INVOICE_DISTRIBUTIONS_PKG.Make_Distributions_Permanent
1740                  (P_Invoice_Id          => p_invoice_id,
1741                   P_Invoice_Line_Number => NULL,
1742                   P_Calling_Sequence    => 'Invoice Validation'); --Bug6653070
1743 
1744   --END IF;
1745 
1746   IF (l_any_records_flag = 'Y') THEN
1747       IF NVL(p_commit, 'Y') = 'Y' THEN
1748          ----------------------------------------------------------------
1749          l_debug_info := 'Commit Data';
1750          Print_Debug(l_api_name, l_debug_info);
1751          ----------------------------------------------------------------
1752          COMMIT;
1753       END IF;
1754   END IF;
1755 
1756   Print_Debug (l_api_name, 'AP_APPROVAL_PKG.APPROVE.END');
1757 
1758 EXCEPTION
1759 -- Bug 7718385
1760   WHEN LCM_EXCEPTION THEN
1761 
1762        -- Logging error messages
1763  	     FOR i in 1 ..l_lcm_msg_count
1764 	     LOOP
1765 	      l_lcm_msg_data := FND_MSG_PUB.get(i, FND_API.g_false);
1766 	      l_debug_info :='l_msg_data ('||i||'): '||l_lcm_msg_data;
1767         Print_Debug(l_api_name, l_debug_info);
1768 	     END LOOP;
1769 
1770        -- Throwing error messages to form to display
1771        FND_MESSAGE.SET_NAME('SQLAP','AP_LCM_EXCEPTION');
1772        /*  Error Text is
1773        --  An error occurred while interfacing the invoice to Landed Cost Management.
1774        --  Error: &ERROR
1775        --
1776        */
1777        FND_MESSAGE.SET_TOKEN('ERROR', l_lcm_msg_data);
1778        APP_EXCEPTION.RAISE_EXCEPTION;
1779 
1780   WHEN TAX_EXCEPTION THEN
1781        FND_MESSAGE.SET_NAME('SQLAP','AP_TAX_EXCEPTION');
1782        IF l_error_code IS NOT NULL THEN
1783           FND_MESSAGE.SET_TOKEN('ERROR', l_error_code);
1784        ELSE
1785           FND_MESSAGE.SET_TOKEN('ERROR', SQLERRM);
1786        END IF;
1787 
1788        IF (approve_invoice_cur%ISOPEN) THEN
1789            CLOSE approve_invoice_cur;
1790        END IF;
1791        IF (approve_pay_request_cur%ISOPEN) THEN
1792            CLOSE approve_pay_request_cur;
1793        END IF;
1794        IF (invoice_line_cur%ISOPEN) THEN
1795            CLOSE invoice_line_cur;
1796        END IF;
1797 
1798        APP_EXCEPTION.RAISE_EXCEPTION;
1799 
1800   WHEN OTHERS THEN
1801        IF (SQLCODE <> -20001) THEN
1802            FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
1803            FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
1804            FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
1805            FND_MESSAGE.SET_TOKEN('PARAMETERS',
1806 	                  'Run Option  = '|| p_run_option
1807 	              ||', Batch Id = '|| to_char(p_invoice_batch_id)
1808 	              ||', Begin Date = '|| to_char(p_begin_invoice_date)
1809 	              ||', End Date = '|| to_char(p_end_invoice_date)
1810 	              ||', Vendor Id = '|| to_char(p_vendor_id)
1811 	              ||', Pay Group = '|| p_pay_group
1812 	              ||', Invoice Id = '|| to_char(p_invoice_id)
1813 	              ||', Entered By = '|| to_char(p_entered_by)
1814 	              ||', Set of Books Id = '|| to_char(p_set_of_books_id));
1815 	   FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
1816        END IF;
1817 
1818        IF (approve_invoice_cur%ISOPEN) THEN
1819            CLOSE approve_invoice_cur;
1820        END IF;
1821        IF (approve_pay_request_cur%ISOPEN) THEN
1822            CLOSE approve_pay_request_cur;
1823        END IF;
1824        IF (invoice_line_cur%ISOPEN) THEN
1825            CLOSE invoice_line_cur;
1826        END IF;
1827 
1828        APP_EXCEPTION.RAISE_EXCEPTION;
1829 
1830 END Approve;
1831 
1832 /*bug6858309 - modified the function to look for
1833 ap_invoice_lines instead of ap_invoic_distributions
1834 as dists are not created for freshly created
1835 recurring invoice in R12*/
1836 FUNCTION validate_period (p_invoice_id IN NUMBER)
1837 RETURN BOOLEAN IS
1838 
1839    CURSOR get_gl_date IS
1840    SELECT distinct accounting_date acc_date
1841      FROM ap_invoice_lines_all
1842     WHERE invoice_id = p_invoice_id
1843           and NVL(generate_dists,'N') <> 'D';
1844 
1845    CURSOR get_inv_source IS
1846    SELECT upper(nvl(source, 'X')), org_id
1847      FROM ap_invoices_all
1848     WHERE invoice_id = p_invoice_id;
1849 
1850    l_source ap_invoices_all.source%TYPE;
1851    l_org_id ap_invoices_all.org_id%TYPE;
1852 
1853 BEGIN
1854    OPEN get_inv_source;
1855    FETCH get_inv_source INTO l_source, l_org_id;
1856    CLOSE get_inv_source;
1857 
1858    IF l_source <> 'RECURRING INVOICE' THEN
1859       return true;
1860    END IF;
1861 
1862    FOR gl_date IN get_gl_date LOOP
1863           IF ap_utilities_pkg.period_status(gl_date.acc_date) ='N' then
1864              return false;
1865           END IF;
1866    END LOOP;
1867    return true;
1868 END validate_period;
1869 
1870 
1871 /*=============================================================================
1872  |  PROCEDURE  APPROVAL_INIT
1873  |
1874  |      Procedure called by APPROVAL to retrieve system variables to be used by
1875  |      the APPROVAL program
1876  |
1877  |  PROGRAM FLOW
1878  |      1. Retrieve system parameters
1879  |      2. Determine if accounting method is Cash Only
1880  |      3. Retrieve profile option user_id
1881  |      4. Set approval system user_id value
1882  |      5. Retrieve system tolerances
1883  *============================================================================*/
1884 
1885 PROCEDURE Approval_Init(
1886 	      p_org_id  		   IN            NUMBER,
1887 	      p_invoice_id		   IN            NUMBER,
1888               p_invoice_type               IN            VARCHAR2 DEFAULT NULL,
1889               p_tolerance_id               IN            NUMBER,
1890               p_services_tolerance_id      IN            NUMBER,
1891 	      p_conc_flag		   IN		 VARCHAR2,
1892               p_set_of_books_id            IN OUT NOCOPY NUMBER,
1893               p_recalc_pay_sched_flag      IN OUT NOCOPY VARCHAR2,
1894               p_sys_xrate_gain_ccid        IN OUT NOCOPY NUMBER,
1895               p_sys_xrate_loss_ccid        IN OUT NOCOPY NUMBER,
1896               p_base_currency_code         IN OUT NOCOPY VARCHAR2,
1897               p_inv_enc_type_id            IN OUT NOCOPY NUMBER,
1898               p_purch_enc_type_id          IN OUT NOCOPY NUMBER,
1899               p_gl_date_from_receipt_flag  IN OUT NOCOPY VARCHAR2,
1900               p_receipt_acc_days           IN OUT NOCOPY NUMBER,
1901               p_system_user                IN OUT NOCOPY NUMBER,
1902               p_user_id                    IN OUT NOCOPY NUMBER,
1903 	      p_goods_ship_amt_tolerance     IN OUT NOCOPY NUMBER,
1904 	      p_goods_rate_amt_tolerance     IN OUT NOCOPY NUMBER,
1905 	      p_goods_total_amt_tolerance    IN OUT NOCOPY NUMBER,
1906 	      p_services_ship_amt_tolerance  IN OUT NOCOPY NUMBER,
1907 	      p_services_rate_amt_tolerance  IN OUT NOCOPY NUMBER,
1908 	      p_services_total_amt_tolerance IN OUT NOCOPY NUMBER,
1909               p_price_tolerance            IN OUT NOCOPY NUMBER,
1910               p_qty_tolerance              IN OUT NOCOPY NUMBER,
1911               p_qty_rec_tolerance          IN OUT NOCOPY NUMBER,
1912 	      p_amt_tolerance		   IN OUT NOCOPY NUMBER,
1913 	      p_amt_rec_tolerance	   IN OUT NOCOPY NUMBER,
1914               p_max_qty_ord_tolerance      IN OUT NOCOPY NUMBER,
1915               p_max_qty_rec_tolerance      IN OUT NOCOPY NUMBER,
1916 	      p_max_amt_ord_tolerance      IN OUT NOCOPY NUMBER,
1917 	      p_max_amt_rec_tolerance      IN OUT NOCOPY NUMBER,
1918               p_invoice_line_count         OUT NOCOPY NUMBER,  --Bug 6684139
1919               p_calling_sequence           IN            VARCHAR2) IS
1920 
1921   l_debug_loc                 VARCHAR2(30)   := 'Approval_Init';
1922   l_curr_calling_sequence     VARCHAR2(2000);
1923   l_debug_info                VARCHAR2(1000);
1924 BEGIN
1925 
1926   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
1927                              p_calling_sequence;
1928 
1929    -- Select stmt added for bug 6684139
1930    SELECT count(*)
1931     into p_invoice_line_count
1932     from ap_invoice_lines
1933     where invoice_id = p_invoice_id;
1934 
1935   IF nvl(p_conc_flag, 'N') <> 'Y' THEN
1936 
1937 	 l_debug_info :=  'Retrieving system parameters for validation';
1938 	 Print_Debug(l_debug_loc, l_debug_info);
1939 
1940 	 SELECT   nvl(sp.set_of_books_id, -1),
1941 	          nvl(recalc_pay_schedule_flag, 'N'),
1942 	          nvl(sp.rate_var_gain_ccid, -1),
1943 	          nvl(sp.rate_var_loss_ccid, -1),
1944 	          nvl(sp.base_currency_code, 'USD'),
1945         	  nvl(fp.inv_encumbrance_type_id, -1),
1946 	          nvl(fp.purch_encumbrance_type_id, -1),
1947 	          nvl(sp.receipt_acceptance_days, 0),
1948 	          nvl(gl_date_from_receipt_flag, 'S')
1949 	 INTO     p_set_of_books_id,
1950 	          p_recalc_pay_sched_flag,
1951 	          p_sys_xrate_gain_ccid,
1952 	          p_sys_xrate_loss_ccid,
1953 	          p_base_currency_code,
1954 	          p_inv_enc_type_id,
1955 	          p_purch_enc_type_id,
1956 	          p_receipt_acc_days,
1957 	          p_gl_date_from_receipt_flag
1958 	  FROM    ap_system_parameters_all sp,
1959 	          financials_system_params_all fp,
1960 	          gl_sets_of_books gls
1961 	  WHERE   sp.org_id = p_org_id
1962 	  AND     fp.org_id = sp.org_id
1963 	  AND     sp.set_of_books_id = gls.set_of_books_id;
1964 
1965   ELSE
1966 
1967 	l_debug_info :=  'Set Options from Cache';
1968     	Print_Debug (l_debug_loc, l_debug_info);
1969 
1970 	p_set_of_books_id		:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).set_of_books_id;
1971 	p_recalc_pay_sched_flag		:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).recalc_pay_schedule_flag;
1972 	p_sys_xrate_gain_ccid		:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).rate_var_gain_ccid;
1973 	p_sys_xrate_loss_ccid		:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).rate_var_loss_ccid;
1974 	p_base_currency_code		:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).base_currency_code;
1975 	p_inv_enc_type_id		:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).inv_encumbrance_type_id;
1976 	p_purch_enc_type_id		:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).purch_encumbrance_type_id;
1977 	p_receipt_acc_days		:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).receipt_acceptance_days;
1978 	p_gl_date_from_receipt_flag	:= AP_APPROVAL_PKG.G_Options_Table(p_org_id).gl_date_from_receipt_flag;
1979 
1980   END IF;
1981 
1982   p_system_user := 5;
1983   p_user_id	:= FND_GLOBAL.user_id;
1984 
1985   l_debug_info :=  'Retrieving tolerances for validation';
1986   Print_Debug(l_debug_loc, l_debug_info);
1987 
1988   IF p_invoice_type <> 'PAYMENT REQUEST' THEN
1989 
1990      IF p_tolerance_id IS NOT NULL THEN
1991 	    p_price_tolerance		:= AP_APPROVAL_PKG.G_GOODS_TOLERANCES(p_tolerance_id).price_tolerance;
1992             p_qty_tolerance		:= AP_APPROVAL_PKG.G_GOODS_TOLERANCES(p_tolerance_id).quantity_tolerance;
1993             p_qty_rec_tolerance		:= AP_APPROVAL_PKG.G_GOODS_TOLERANCES(p_tolerance_id).qty_received_tolerance;
1994             p_max_qty_ord_tolerance	:= AP_APPROVAL_PKG.G_GOODS_TOLERANCES(p_tolerance_id).max_qty_ord_tolerance;
1995             p_max_qty_rec_tolerance	:= AP_APPROVAL_PKG.G_GOODS_TOLERANCES(p_tolerance_id).max_qty_rec_tolerance;
1996             p_goods_ship_amt_tolerance	:= AP_APPROVAL_PKG.G_GOODS_TOLERANCES(p_tolerance_id).ship_amt_tolerance;
1997             p_goods_rate_amt_tolerance	:= AP_APPROVAL_PKG.G_GOODS_TOLERANCES(p_tolerance_id).rate_amt_tolerance;
1998             p_goods_total_amt_tolerance	:= AP_APPROVAL_PKG.G_GOODS_TOLERANCES(p_tolerance_id).total_amt_tolerance;
1999     END IF;
2000 
2001     IF p_services_tolerance_id IS NOT NULL THEN
2002 	    p_amt_tolerance			:= AP_APPROVAL_PKG.G_SERVICES_TOLERANCES(p_services_tolerance_id).amount_tolerance;
2003             p_amt_rec_tolerance			:= AP_APPROVAL_PKG.G_SERVICES_TOLERANCES(p_services_tolerance_id).amt_received_tolerance;
2004             p_max_amt_ord_tolerance		:= AP_APPROVAL_PKG.G_SERVICES_TOLERANCES(p_services_tolerance_id).max_amt_ord_tolerance;
2005             p_max_amt_rec_tolerance		:= AP_APPROVAL_PKG.G_SERVICES_TOLERANCES(p_services_tolerance_id).max_amt_rec_tolerance;
2006             p_services_ship_amt_tolerance	:= AP_APPROVAL_PKG.G_SERVICES_TOLERANCES(p_services_tolerance_id).ser_ship_amt_tolerance;
2007             p_services_rate_amt_tolerance	:= AP_APPROVAL_PKG.G_SERVICES_TOLERANCES(p_services_tolerance_id).ser_rate_amt_tolerance;
2008             p_services_total_amt_tolerance	:= AP_APPROVAL_PKG.G_SERVICES_TOLERANCES(p_services_tolerance_id).ser_total_amt_tolerance;
2009     END IF;
2010 
2011   END IF;
2012 
2013 EXCEPTION
2014   WHEN OTHERS THEN
2015     IF (SQLCODE <> -20001) THEN
2016       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
2017       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
2018       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
2019       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
2020     END IF;
2021     APP_EXCEPTION.RAISE_EXCEPTION;
2022 END Approval_Init;
2023 
2024 /*=============================================================================
2025  |  PROCEDURE Inv_Needs_Approving
2026  |
2027  |      Function when given an invoice_id and run_option, it returns a boolean
2028  |      to indicate whether to approve an invoice or not.  Returns FALSE if the
2029  |      run_option is 'New' and the invoice doesn't have any unapproved
2030  |      distributions.
2031  |
2032  |  PARAMETERS
2033  |      p_invoice_id
2034  |      p_run_option
2035  |      p_calling_sequence
2036  |
2037  |  PROGRAM FLOW
2038  |
2039  |  KNOWN ISSUES
2040  |
2041  |  NOTES:
2042  |
2043  |  MODIFICATION HISTORY
2044  |  Date         Author             Description of Change
2045  |
2046  *============================================================================*/
2047 
2048 FUNCTION Inv_Needs_Approving(
2049              p_invoice_id          IN            NUMBER,
2050              p_run_option          IN            VARCHAR2,
2051              p_calling_sequence    IN            VARCHAR2) RETURN BOOLEAN
2052 IS
2053 
2054   l_unapproved_dist_exists     NUMBER;
2055   l_undistributed_line_exists  VARCHAR2(30);
2056   l_debug_loc                  VARCHAR2(30) := 'Inv_Needs_Approving';
2057   l_curr_calling_sequence      VARCHAR2(2000);
2058   l_debug_info                 VARCHAR2(1000);
2059   l_api_name                   CONSTANT VARCHAR2(200) := 'Approval_Init';
2060 BEGIN
2061 
2062   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
2063                              p_calling_sequence;
2064 
2065   l_undistributed_line_exists := 'N';
2066 
2067   IF (p_run_option = 'New') THEN
2068 
2069     SELECT count(*)
2070     INTO   l_unapproved_dist_exists
2071     FROM   ap_invoice_distributions_all
2072     WHERE  invoice_id = p_invoice_id
2073     AND    (nvl(match_status_flag, 'N')) = 'N'
2074     AND    rownum = 1;
2075 
2076     --bugfix:4745464
2077     BEGIN
2078         SELECT 'Y'
2079         INTO   l_undistributed_line_exists
2080         FROM   ap_invoice_lines_all L
2081         WHERE  L.invoice_id = p_invoice_id
2082         AND    L.amount <>
2083              (SELECT NVL(SUM(NVL(aid.amount,0)),0)
2084 	      FROM ap_invoice_distributions_all aid
2085 	      WHERE aid.invoice_id = L.invoice_id
2086 	      AND aid.invoice_line_number = L.line_number);
2087     END;
2088 
2089     IF (l_unapproved_dist_exists = 0 AND l_undistributed_line_exists = 'N') THEN
2090 
2091       l_debug_info := 'Skip Validation: Invoice_Id: ' || p_invoice_id;
2092       Print_Debug(l_api_name, l_debug_info);
2093 
2094       return(FALSE);
2095     END IF;
2096   END IF;
2097 
2098   return(TRUE);
2099 
2100 EXCEPTION
2101   WHEN OTHERS THEN
2102     IF (SQLCODE <> -20001) THEN
2103       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
2104       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
2105       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
2106       FND_MESSAGE.SET_TOKEN('PARAMETERS',
2107                   'Invoice_id  = '|| to_char(p_invoice_id)
2108          || 'Run Option = ' || p_run_option);
2109     END IF;
2110     APP_EXCEPTION.RAISE_EXCEPTION;
2111 END Inv_Needs_Approving;
2112 
2113 /*=============================================================================
2114  |  PROCEDURE  Update_Inv_Dists_To_Selected
2115  |
2116  |      Procedure given the invoice_id, invoice line number and  run option,
2117  |      updates the invoice distributions to be selected for approval depending
2118  |      on the run option.
2119  |      If the run_option is 'New' then we only select distributions that have
2120  |      never been processed by approval, otherwise we select all distributions
2121  |      that have not successfully been approved.
2122  |
2123  |  PARAMETERS
2124  |      p_invoice_id - invoice id
2125  |      p_line_number - invoice line number
2126  |      p_run_option
2127  |      p_calling_sequence
2128  |
2129  |  KNOWN ISSUES:
2130  |
2131  |  NOTES:
2132  |
2133  |  MODIFICATION HISTORY
2134  |  Date         Author             Description of Change
2135  |
2136  *============================================================================*/
2137 
2138 PROCEDURE Update_Inv_Dists_To_Selected(
2139               p_invoice_id        IN            NUMBER,
2140               p_line_number       IN            NUMBER,
2141               p_run_option        IN            VARCHAR2,
2142               p_calling_sequence  IN            VARCHAR2) IS
2143 
2144   l_debug_loc              VARCHAR2(30) := 'Update_Inv_Dists_To_Selected';
2145   l_curr_calling_sequence  VARCHAR2(2000);
2146   l_debug_info             VARCHAR2(1000);
2147 BEGIN
2148 
2149   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
2150                              p_calling_sequence;
2151 
2152   IF (p_run_option = 'New') THEN
2153 
2154     l_debug_info :=  'Run Option: New: Set new distribution flag to S';
2155     Print_Debug (l_debug_loc,l_debug_info);
2156 
2157     UPDATE  ap_invoice_distributions_all D
2158     SET     match_status_flag = 'S'
2159     WHERE   NVL(match_status_flag, 'N') = 'N'
2160     AND     D.invoice_id = p_invoice_id
2161     AND     D.invoice_line_number = p_line_number;
2162 
2163 
2164     --Bug	6963908
2165     UPDATE  ap_self_assessed_tax_dist_all D
2166     SET     match_status_flag = 'S'
2167     WHERE   NVL(match_status_flag, 'N') = 'N'
2168     AND     D.invoice_id = p_invoice_id
2169     AND     D.invoice_line_number = p_line_number;
2170     --Bug	6963908
2171 
2172   ELSE
2173 
2174     l_debug_info :=  'Run Option: All: Set new distribution flag to S';
2175     Print_Debug (l_debug_loc,l_debug_info);
2176 
2177     UPDATE  ap_invoice_distributions_all D
2178     SET     match_status_flag = 'S'
2179     WHERE   NVL(match_status_flag, '!') <> 'A'
2180     AND     D.invoice_id = p_invoice_id;
2181 
2182     --Bug	6963908
2183     UPDATE  ap_self_assessed_tax_dist_all D
2184     SET     match_status_flag = 'S'
2185     WHERE   NVL(match_status_flag, '!') <> 'A'
2186     AND     D.invoice_id = p_invoice_id;
2187     --Bug	6963908
2188 
2189   END IF;
2190 
2191 EXCEPTION
2192   WHEN OTHERS THEN
2193     IF (SQLCODE <> -20001) THEN
2194       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
2195       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
2196       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
2197       FND_MESSAGE.SET_TOKEN('PARAMETERS',
2198                   'Invoice_id  = '|| to_char(p_invoice_id)
2199          || 'Run Option = ' || p_run_option);
2200       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
2201     END IF;
2202     APP_EXCEPTION.RAISE_EXCEPTION;
2203 END Update_Inv_Dists_To_Selected;
2204 
2205 
2206 /*=============================================================================
2207  |  PUBLIC PROCEDURE  Check_Insufficient_Line_Data
2208  |
2209  |  DESCRIPTION:
2210  |                Check all the line information before Distribution generated
2211  |  PARAMETERS
2212  |    p_inv_line_rec
2213  |    p_system_user
2214  |    p_holds
2215  |    p_holds_count
2216  |    p_release_count
2217  |    p_insufficent_data_exist - boolean indicates if a hold is existing
2218  |    p_calling_sequence
2219  |
2220  |   PROGRAM FLOW
2221  |     Check for Sufficient Line Data in a priliminary level
2222  |  KNOWN ISSUES:
2223  |
2224  |  NOTES:
2225  |
2226  |  MODIFICATION HISTORY
2227  |  Date         Author             Description of Change
2228  |
2229  *============================================================================*/
2230 
2231 PROCEDURE Check_Insufficient_Line_Data(
2232               p_inv_line_rec             IN AP_INVOICES_PKG.r_invoice_line_rec,
2233               p_system_user              IN            NUMBER,
2234               p_holds                    IN OUT NOCOPY HOLDSARRAY,
2235               p_holds_count              IN OUT NOCOPY COUNTARRAY,
2236               p_release_count            IN OUT NOCOPY COUNTARRAY,
2237               p_insufficient_data_exist     OUT NOCOPY BOOLEAN,
2238 	      p_calling_mode		 IN            VARCHAR2,
2239               p_calling_sequence         IN            VARCHAR2)
2240 IS
2241 
2242   CURSOR Alloc_Rule_Cur IS
2243   SELECT ALOC.rule_type
2244   FROM   ap_invoice_lines  AIL,
2245          ap_allocation_rules ALOC
2246   WHERE  AIL.invoice_id = p_inv_line_rec.invoice_id
2247     AND  AIL.line_number = p_inv_line_rec.line_number
2248     AND  AIL.invoice_id = ALOC.invoice_id
2249     AND  AIL.line_number = ALOC.chrg_invoice_line_number(+);
2250 
2251   l_debug_loc              VARCHAR2(30) := 'Check_Insufficient_Line_Data';
2252   l_curr_calling_sequence  VARCHAR2(2000);
2253   l_debug_info             VARCHAR2(1000);
2254   l_ret_val                BOOLEAN;
2255   l_should_have_hold       VARCHAR2(1) := 'N';
2256   l_alloc_rule_type        ap_allocation_rules.rule_type%TYPE;
2257   l_product_registered     BOOLEAN;
2258   l_dummy                  VARCHAR2(100);
2259 
2260 BEGIN
2261 
2262   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||
2263                              '<-'||p_calling_sequence;
2264 
2265   p_insufficient_data_exist := FALSE;
2266 
2267   OPEN Alloc_Rule_Cur;
2268   FETCH Alloc_Rule_Cur INTO l_alloc_rule_type;
2269     IF (Alloc_Rule_Cur%NOTFOUND) THEN
2270       l_alloc_rule_type := NULL;
2271     END IF;
2272   CLOSE Alloc_Rule_Cur;
2273 
2274   IF (Is_Product_Registered(
2275   		P_application_id => p_inv_line_rec.application_id,
2276 	        X_registration_api    => l_dummy,
2277 	        X_registration_view   => l_dummy,
2278 	        P_calling_sequence    => l_curr_calling_sequence)) THEN
2279      l_product_registered := TRUE;
2280   ELSE
2281      l_product_registered := FALSE;
2282   END IF;
2283 
2284   ----
2285   l_debug_info := 'processing info for line number: '||p_inv_line_rec.line_number
2286                              ||' l_alloc_rule_type: '||l_alloc_rule_type
2287                                    || ' project_id: '||p_inv_line_rec.project_id
2288                                 ||' generate_dists: '||p_inv_line_rec.generate_dists;
2289   Print_Debug(l_debug_loc, l_debug_info);
2290   ----
2291 
2292   IF (p_inv_line_rec.generate_dists = 'Y'
2293       and p_inv_line_rec.distribution_set_id IS NULL
2294       and p_inv_line_rec.default_dist_ccid IS NULL
2295       and l_alloc_rule_type IS NULL
2296       and p_inv_line_rec.project_id IS NULL
2297       and NOT l_product_registered) THEN
2298 
2299       l_debug_info := 'should have hold for line:  '||p_inv_line_rec.line_number;
2300       Print_Debug(l_debug_loc, l_debug_info);
2301 
2302       l_should_have_hold := 'Y';
2303       p_insufficient_data_exist := TRUE;
2304   END IF;
2305 
2306   IF (p_calling_mode = 'PERMANENT_DISTRIBUTIONS') THEN
2307       Process_Inv_Hold_Status(
2308 		p_inv_line_rec.invoice_id,
2309 		null,
2310 		null,
2311 		'INSUFFICIENT LINE INFO',
2312 		l_should_have_hold,
2313 		null,
2314 		p_system_user,
2315 		p_holds,
2316 		p_holds_count,
2317 		p_release_count,
2318 		l_curr_calling_sequence);
2319   END IF;
2320 
2321 EXCEPTION
2322   WHEN OTHERS THEN
2323     IF (SQLCODE <> -20001) THEN
2324       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
2325       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
2326       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
2327       FND_MESSAGE.SET_TOKEN('PARAMETERS',
2328                   'Invoice_id  = '|| to_char(p_inv_line_rec.invoice_id));
2329       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
2330     END IF;
2331 
2332     IF ( Alloc_Rule_Cur%ISOPEN ) THEN
2333       CLOSE Alloc_Rule_Cur;
2334     END IF;
2335 
2336     APP_EXCEPTION.RAISE_EXCEPTION;
2337 END Check_Insufficient_Line_Data;
2338 
2339 
2340 /*=============================================================================
2341  |  PUBLIC PROCEDURE  Execute_Dist_Generation_Check
2342  |
2343  |  DESCRIPTION:
2344  |                Call API to generate Distribution from distribution set or
2345  |                generate distribution based on allocation/default account
2346  |                information. Handle the error code detected during dist.
2347  |                generation. Process/Release corresponding Hold.
2348  |  PARAMETERS
2349  |    p_batch_id
2350  |    p_invoice_date
2351  |    p_vendor_id
2352  |    p_invoice_currency
2353  |    p_exchange_rate
2354  |    p_exchange_rate_type
2355  |    p_exchange_date
2356  |    p_inv_line_rec
2357  |    p_system_user
2358  |    p_holds
2359  |    p_holds_count
2360  |    p_release_count
2361  |    p_curr_calling_sequence
2362  |
2363  |  PROGRAM FLOW
2364  |
2365  |  KNOWN ISSUES
2366  |
2367  |  NOTES:
2368  |
2369  |  MODIFICATION HISTORY
2370  |  Date         Author             Description of Change
2371  |
2372  *============================================================================*/
2373 
2374 FUNCTION  Execute_Dist_Generation_Check(
2375               p_batch_id                IN            NUMBER,
2376               p_invoice_date            IN            DATE,
2377               p_vendor_id               IN            NUMBER,
2378               p_invoice_currency        IN            VARCHAR2,
2379               p_exchange_rate           IN            NUMBER,
2380               p_exchange_rate_type      IN            VARCHAR2,
2381               p_exchange_date           IN            DATE,
2382               p_inv_line_rec            IN AP_INVOICES_PKG.r_invoice_line_rec,
2383               p_system_user             IN            NUMBER,
2384               p_holds                   IN OUT NOCOPY HOLDSARRAY,
2385               p_holds_count             IN OUT NOCOPY COUNTARRAY,
2386               p_release_count           IN OUT NOCOPY COUNTARRAY,
2387 	      p_generate_permanent      IN            VARCHAR2,
2388 	      p_calling_mode            IN            VARCHAR2 ,
2389 	      p_error_code              OUT NOCOPY    VARCHAR2,
2390               p_curr_calling_sequence   IN            VARCHAR2) RETURN BOOLEAN
2391 IS
2392 
2393   CURSOR Alloc_Rule_Cur IS
2394   SELECT ALOC.rule_type
2395   FROM   ap_invoice_lines  AIL,
2396          ap_allocation_rules ALOC
2397   WHERE  AIL.invoice_id = p_inv_line_rec.invoice_id
2398     AND  AIL.line_number = p_inv_line_rec.line_number
2399     AND  AIL.invoice_id = ALOC.invoice_id
2400     AND  AIL.line_number = ALOC.chrg_invoice_line_number(+);
2401 
2402   l_debug_loc                 VARCHAR2(30) := 'Execute_Dist_Generation_Check';
2403   l_curr_calling_sequence     VARCHAR2(2000);
2404   l_debug_info                VARCHAR2(2000);
2405   l_alloc_rule_type           ap_allocation_rules.rule_type%TYPE;
2406 
2407   l_debug_context             VARCHAR2(2000);
2408   l_msg_application           VARCHAR2(25);
2409   l_error_code                VARCHAR2(4000);
2410   l_msg_data                  VARCHAR2(30);
2411   l_hold_code                 VARCHAR2(30);
2412   l_success                   BOOLEAN := FALSE;
2413   l_gen_dist_hold_exists      VARCHAR2(1) := 'N';
2414 
2415   --Bugfix:4673607
2416   l_registration_api	      VARCHAR2(1000);
2417   l_registration_view         VARCHAR2(1000);
2418   l_reference_key1	      ap_invoice_lines_all.reference_key1%type;
2419   l_reference_key2	      ap_invoice_lines_all.reference_key2%type;
2420   l_reference_key3	      ap_invoice_lines_all.reference_key3%type;
2421   l_reference_key4	      ap_invoice_lines_all.reference_key4%type;
2422   l_reference_key5	      ap_invoice_lines_all.reference_key5%type;
2423   l_err varchar2(2000);
2424 
2425 BEGIN
2426 
2427   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
2428                              p_curr_calling_sequence;
2429 
2430   ----------------------------------------------------------------------
2431   l_debug_info := 'Input Parameters: '||' invoice id: '         ||p_inv_line_rec.invoice_id
2432 				      ||' line_number: '        ||p_inv_line_rec.line_number
2433 				      ||' generate_dists: '     ||p_inv_line_rec.generate_dists
2434 				      ||' distribution_set_id: '||p_inv_line_rec.distribution_set_id
2435 				      ||' accouting_date: '     ||p_inv_line_rec.accounting_date
2436 				      ||' period_name: '        ||p_inv_line_rec.period_name;
2437   Print_Debug(l_debug_loc, l_debug_info);
2438   ----------------------------------------------------------------------
2439 
2440   IF (Is_Product_Registered(P_application_id	=> p_inv_line_rec.application_id,
2441 			    X_registration_api  => l_registration_api,
2442 			    X_registration_view => l_registration_view,
2443 			    P_calling_sequence  => l_curr_calling_sequence)) THEN
2444 
2445       ----------------------------------------------------------------------
2446       l_debug_info := 'Call the api that will create the distributions '||
2447                       'based on the other products registered view/api';
2448       Print_Debug(l_debug_loc, l_debug_info);
2449       ----------------------------------------------------------------------
2450 
2451       l_success := Gen_Dists_From_Registration(
2452 				     P_Batch_Id		   => p_batch_id,
2453     				     P_Invoice_Line_Rec    => p_inv_line_rec,
2454 				     P_Registration_Api    => l_registration_api,
2455 				     P_Registration_View   => l_registration_view,
2456 				     P_Generate_Permanent  => p_generate_permanent,
2457 				     X_Error_Code          => l_error_code,
2458 				     P_Calling_Sequence    => l_curr_calling_sequence);
2459 
2460 
2461   ELSIF ( p_inv_line_rec.distribution_set_id is not null) THEN
2462 
2463     /*-----------------------------------------------------------------+
2464      | CASE 1 - Generate distribution from distribution set            |
2465      +-----------------------------------------------------------------*/
2466 
2467     l_debug_info := 'Execute_Dist_Generation_Check - insert from dist set';
2468     Print_Debug(l_debug_loc, l_debug_info);
2469 
2470     l_success := AP_INVOICE_LINES_PKG.Insert_From_Dist_Set(
2471                    X_invoice_id          => p_inv_line_rec.invoice_id,
2472                    X_line_number         => p_inv_line_rec.line_number,
2473                    X_GL_Date             => p_inv_line_rec.accounting_date,
2474                    X_Period_Name         => p_inv_line_rec.period_name,
2475                    X_Skeleton_Allowed    => 'Y', -- Bug 4928285
2476                    X_Generate_Dists      => p_inv_line_rec.generate_dists,
2477                    X_Generate_Permanent  => p_generate_permanent,
2478                    X_Error_Code          => l_error_code,
2479                    X_Debug_Info          => l_debug_info,
2480                    X_Debug_Context       => l_debug_context,
2481                    X_Msg_Application     => l_msg_application,
2482                    X_Msg_Data            => l_msg_data,
2483                    X_calling_sequence    => l_curr_calling_sequence);
2484 
2485     IF ( NOT l_success ) THEN
2486 
2487       IF ( l_error_code is not null ) THEN
2488 
2489 	 IF (p_calling_mode = 'PERMANENT_DISTRIBUTIONS') THEN
2490 
2491             CASE l_error_code
2492                WHEN 'AP_VEN_DIST_SET_INVALID'    THEN
2493                   l_hold_code := 'DISTRIBUTION SET INACTIVE';
2494                WHEN 'AP_CANT_USE_SKELETON_DIST_SET' THEN
2495                   l_hold_code := 'SKELETON DISTRIBUTION SET';
2496                WHEN 'AP_CANNOT_OVERLAY'    THEN
2497                   l_hold_code := 'CANNOT OVERLAY ACCOUNT';
2498                WHEN 'AP_INVALID_CCID'    THEN
2499                   l_hold_code := 'INVALID DEFAULT ACCOUNT';
2500                ELSE
2501                   l_hold_code := null;
2502             END CASE;
2503 
2504          ELSIF (p_calling_mode = 'CANDIDATE_DISTRIBUTIONS') THEN
2505 
2506             p_error_code := l_error_code;
2507 
2508          END IF;
2509 
2510          l_debug_info := 'Execute_Dist_Generation_Check: Error Code: ' || l_error_code;
2511 	 Print_Debug(l_debug_loc, l_debug_info);
2512 
2513       ELSE
2514 
2515          IF (p_calling_mode =  'CANDIDATE_DISTRIBUTIONS') THEN
2516            p_error_code := l_debug_info;
2517 
2518 	 END IF;
2519 
2520       END IF; /*l_error_code is not null*/
2521 
2522     END IF; -- end of check l_success
2523 
2524   ELSE
2525 
2526     /*-----------------------------------------------------------------+
2527      | CASE 2 - Generate distribution without distribution set info    |
2528      +-----------------------------------------------------------------*/
2529 
2530     OPEN Alloc_Rule_Cur;
2531     FETCH Alloc_Rule_Cur INTO l_alloc_rule_type;
2532     IF (Alloc_Rule_Cur%NOTFOUND) THEN
2533       l_alloc_rule_type := NULL;
2534     END IF;
2535     CLOSE Alloc_Rule_Cur;
2536 
2537     IF ( p_inv_line_rec.line_type_lookup_code in ('FREIGHT', 'MISCELLANEOUS' ) and
2538          l_alloc_rule_type is not null ) THEN
2539 
2540     /*-----------------------------------------------------------------+
2541      | CASE 2.1 - Generate distribution for charge line if there is an |
2542      |            allocation rule                                      |
2543      +-----------------------------------------------------------------*/
2544 
2545       l_debug_info := 'Execute_Dist_Generation_Check - charge line with an allocation rule';
2546       Print_Debug(l_debug_loc, l_debug_info);
2547 
2548       l_success := AP_INVOICE_DISTRIBUTIONS_PKG.Insert_Charge_From_Alloc(
2549                          X_invoice_id          => p_inv_line_rec.invoice_id,
2550                          X_line_number         => p_inv_line_rec.line_number,
2551                          X_Generate_Permanent  => p_generate_permanent,
2552                          X_Validate_Info       => TRUE,
2553                          X_Error_Code          => l_error_code,
2554                          X_Debug_Info          => l_debug_info,
2555                          X_Debug_Context       => l_debug_context,
2556                          X_Msg_Application     => l_msg_application,
2557                          X_Msg_Data            => l_msg_data,
2558                          X_Calling_Sequence    => l_curr_calling_sequence );
2559 
2560       IF ( NOT l_success ) THEN
2561         IF ( l_error_code is not null ) THEN
2562 
2563 	  IF (p_calling_mode = 'PERMANENT_DISTRIBUTIONS') THEN
2564              IF ( l_error_code IN ( 'AP_NO_ALLOCATION_RULE_FOUND',
2565                                   'AP_ALLOCATION_ALREADY_EXECUTED',
2566                                   'AP_NON_FULL_INVOICE',
2567                                   'AP_UNDISTRIBUTED_LINE_EXISTS',
2568                                   'AP_IMPROPER_LINE_IN_ALLOC_RULE',
2569                                   'AP_CANNOT_READ_EXP_DATE',
2570                                   'AP_INVALID_ACCOUNT',
2571                                   'AP_CANNOT_OVERLAY',
2572                                   'AP_NO_OPEN_PERIOD',
2573                                   'AP_GL_DATE_PA_NOT_OPEN' ) ) THEN
2574                 l_hold_code := 'CANNOT EXECUTE ALLOCATION';
2575              ELSE
2576                 l_hold_code := null;
2577              END IF;
2578 
2579           ELSIF (p_calling_mode = 'CANDIDATE_DISTRIBUTIONS') THEN
2580              p_error_code := l_error_code;
2581 	  END IF;
2582 
2583           l_debug_info := 'Execute_Dist_Generation_Check -  ' ||
2584                           'Insert_Charge_From_Alloc error '   || l_error_code;
2585 	  Print_Debug (l_debug_loc, l_debug_info);
2586 
2587         END IF; -- end of check l_error_code
2588       END IF; -- end of check l_success
2589 
2590     ELSE
2591 
2592      /*-----------------------------------------------------------------+
2593      | CASE 2.2 - Generate distribution for non-match item line or no   |
2594      |            allocation rule charge line                           |
2595      +-----------------------------------------------------------------*/
2596 
2597       l_debug_info := 'Execute_Dist_Generation_Check - Insert_Single_Dist_From_Line';
2598       Print_Debug(l_debug_loc, l_debug_info);
2599 
2600       l_success := AP_INVOICE_DISTRIBUTIONS_PKG.Insert_Single_Dist_From_Line(
2601                        X_batch_id            => p_batch_id,
2602                        X_invoice_id          => p_inv_line_rec.invoice_id,
2603                        X_invoice_date        => p_invoice_date,
2604                        X_vendor_id           => p_vendor_id,
2605                        X_invoice_currency    => p_invoice_currency,
2606                        X_exchange_rate       => p_exchange_rate,
2607                        X_exchange_rate_type  => p_exchange_rate_type,
2608                        X_exchange_date       => p_exchange_date,
2609                        X_line_number         => p_inv_line_rec.line_number,
2610                        X_invoice_lines_rec   => NULL,
2611                        X_line_source         => 'VALIDATION',
2612                        X_Generate_Permanent  => p_generate_permanent,
2613                        X_Validate_Info       => TRUE,
2614                        X_Error_Code          => l_error_code,
2615                        X_Debug_Info          => l_debug_info,
2616                        X_Debug_Context       => l_debug_context,
2617                        X_Msg_Application     => l_msg_application,
2618                        X_Msg_Data            => l_msg_data,
2619                        X_Calling_Sequence    => l_curr_calling_sequence);
2620 
2621       IF ( NOT l_success ) THEN
2622         IF ( l_error_code is not null ) THEN
2623 
2624 	  IF (p_calling_mode = 'PERMANENT_DISTRIBUTIONS') THEN
2625 
2626              CASE l_error_code
2627                WHEN 'INVALID_ACCOUNT'    THEN
2628                  l_hold_code := 'INVALID DEFAULT ACCT';
2629                WHEN 'CANNOT_OVERLAY'    THEN
2630                  l_hold_code := 'CANNOT OVERLAY ACCOUNT';
2631                WHEN 'NOT_OPEN_PERIOD'   THEN
2632                  -- attention: need to confirm later
2633                  l_hold_code := 'PERIOD CLOSED';
2634                WHEN 'GL_DATE_PA_NOT_OPEN'    THEN
2635                  l_hold_code := 'PROJECT GL DATE CLOSED';
2636                ELSE
2637                  l_hold_code := null;
2638              END CASE;
2639 
2640           ELSIF (p_calling_mode = 'CANDIDATE_DISTRIBUTIONS') THEN
2641 
2642 	     p_error_code := l_error_code;
2643 
2644 	  END IF;  /*p_calling_mode = 'PERMANENT_DISTRIBUTIONS' */
2645 
2646           l_debug_info := 'Execute_Dist_Generation_Check-insert from dist'
2647                            || ' set has error - ' || l_error_code ;
2648           Print_Debug(l_debug_loc, l_debug_info);
2649 
2650         END IF; -- end of check l_error_code
2651       END IF; -- end of check l_success
2652     END IF; -- end of p_inv_line_rec.line_type_lookup_code check
2653   END IF; -- end of p_inv_line_rec.distribution_set_id check
2654 
2655     /*-----------------------------------------------------------------+
2656      | To process the error code and the put hold if necessary         |
2657      +-----------------------------------------------------------------*/
2658 
2659   IF ( NOT l_success and l_hold_code is not null ) THEN
2660     l_gen_dist_hold_exists := 'Y';
2661 
2662     l_debug_info := 'Execute_Dist_Generation_Check - Process hold code';
2663     Print_Debug(l_debug_loc, l_debug_info);
2664 
2665   --BUGFIX:5685469
2666   --Need to release the holds (related to distribution generation) placed in earlier calls of
2667   --validation
2668   ELSIF (p_calling_mode = 'PERMANENT_DISTRIBUTIONS' AND  l_success AND l_hold_code IS NULL) THEN
2669 
2670      BEGIN
2671 
2672        l_debug_info := 'Release any holds related to distribution generation which were placed earlier';
2673        Print_Debug(l_debug_loc, l_debug_info);
2674 
2675        IF ( p_inv_line_rec.distribution_set_id is not null) THEN
2676 
2677           SELECT hold_lookup_code
2678           INTO l_hold_code
2679           FROM ap_holds_all
2680           WHERE invoice_id = p_inv_line_rec.invoice_id
2681           AND hold_lookup_code in ('DISTRIBUTION SET INACTIVE','SKELETON DISTRIBUTION SET',
2682                              'CANNOT OVERLAY ACCOUNT','INVALID DEFAULT ACCOUNT')
2683           AND release_lookup_code IS NULL;
2684 
2685        ELSIF ( p_inv_line_rec.line_type_lookup_code in ('FREIGHT', 'MISCELLANEOUS' ) and
2686                l_alloc_rule_type is not null ) THEN
2687 
2688           SELECT hold_lookup_code
2689 	  INTO l_hold_code
2690 	  FROM ap_holds_all
2691 	  WHERE invoice_id = p_inv_line_rec.invoice_id
2692 	  AND hold_lookup_code = 'CANNOT EXECUTE ALLOCATION'
2693 	  AND release_lookup_code IS NULL;
2694 
2695        ELSE
2696 
2697           SELECT hold_lookup_code
2698 	  INTO l_hold_code
2699 	  FROM ap_holds_all
2700 	  WHERE invoice_id = p_inv_line_rec.invoice_id
2701 	  AND hold_lookup_code in ('CANNOT OVERLAY ACCOUNT','INVALID DEFAULT ACCOUNT',
2702 	  			   'PERIOD CLOSED','PROJECT GL DATE CLOSED')
2703 	  AND release_lookup_code IS NULL;
2704 
2705        END IF;
2706 
2707      EXCEPTION WHEN OTHERS THEN
2708       /* l_err := sqlerrm;
2709        l_debug_info := 'in others exception '||l_err;
2710        Print_Debug(l_debug_loc, l_debug_info); */
2711 
2712        NULL;
2713      END ;
2714 
2715   END IF;
2716 
2717 
2718   --Etax: Validation. Added the IF condition so that when this
2719   --procedure is called from funds_check, we not process any holds.
2720   IF (p_calling_mode = 'PERMANENT_DISTRIBUTIONS') THEN
2721      Process_Inv_Hold_Status(
2722     	  p_inv_line_rec.invoice_id,
2723           null,
2724       	  null,
2725           l_hold_code,
2726           l_gen_dist_hold_exists,
2727           null,
2728           p_system_user,
2729           p_holds,
2730           p_holds_count,
2731           p_release_count,
2732           l_curr_calling_sequence);
2733   END IF;
2734 
2735   RETURN ( l_success );
2736 
2737 EXCEPTION
2738   WHEN OTHERS THEN
2739     IF (SQLCODE <> -20001) THEN
2740       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
2741       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
2742       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
2743       FND_MESSAGE.SET_TOKEN('PARAMETERS',
2744                   'Invoice_id  = '|| to_char(p_inv_line_rec.invoice_id));
2745       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
2746     END IF;
2747 
2748     IF ( Alloc_Rule_Cur%ISOPEN ) THEN
2749       CLOSE Alloc_Rule_Cur;
2750     END IF;
2751     APP_EXCEPTION.RAISE_EXCEPTION;
2752 
2753 END Execute_Dist_Generation_Check;
2754 
2755 
2756 /*=============================================================================
2757  |  PROCEDURE EXECUTE_GENERAL_CHECKS
2758  |      Procedure that checks general information hold at invoice level and
2759  |      invoice distribution level.
2760  |
2761  |  PARAMETER
2762  |      p_invoice_id
2763  |      p_set_of_books_id
2764  |      p_base_currency_code
2765  |      p_invoice_amount
2766  |      p_base_amount
2767  |      p_invoice_currency_code
2768  |      p_invoice_amount_limit
2769  |      p_hold_future_payments_flag
2770  |      p_system_user
2771  |      p_holds
2772  |      p_holds_count
2773  |      p_release_count
2774  |      p_calling_sequence
2775  |
2776  |  PROGRAM FLOW
2777  |      1. Check for Invalid Dist Acct - set or release hold
2778  |      2. Check for PO Required - set or release hold
2779  |      3. Check for Missing Exchange Rate - set or release hold
2780  |      4. Check for UnOpen Future Period - set or release hold
2781  |      5. Check for Invoice Limit and vendor holds - set or release hold
2782  |      6. Check for project information
2783  |      7. Check for AWT manual segment - comment out for now
2784  |      8. Check for Prepayment amount - comment out for now
2785  |
2786  |  KNOWN ISSUES:
2787  |
2788  |  NOTES:
2789  |
2790  |  MODIFICATION HISTORY
2791  |  Date         Author             Description of Change
2792  ============================================================================*/
2793 
2794 
2795 PROCEDURE Execute_General_Checks(
2796               p_invoice_id                IN            NUMBER,
2797               p_set_of_books_id           IN            NUMBER,
2798               p_base_currency_code        IN            VARCHAR2,
2799               p_invoice_amount            IN            NUMBER,
2800               p_base_amount               IN            NUMBER,
2801               p_invoice_currency_code     IN            VARCHAR2,
2802               p_invoice_amount_limit      IN            NUMBER,
2803               p_hold_future_payments_flag IN            VARCHAR2,
2804               p_system_user               IN            NUMBER,
2805               p_holds                     IN OUT NOCOPY HOLDSARRAY,
2806               p_holds_count               IN OUT NOCOPY COUNTARRAY,
2807               p_release_count             IN OUT NOCOPY COUNTARRAY,
2808               p_calling_sequence          IN            VARCHAR2) IS
2809 
2810   l_debug_loc                 VARCHAR2(30) := 'Execute_General_Checks';
2811   l_curr_calling_sequence     VARCHAR2(2000);
2812   l_debug_info                VARCHAR2(1000);
2813 
2814 BEGIN
2815 
2816    l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
2817                               p_calling_sequence;
2818 
2819    ---------------------------------------------------
2820    l_debug_info := 'Execute_General_Checks: '
2821     				||' invoice id: ' 	   ||p_invoice_id
2822 				||' set of books id: '	   ||p_set_of_books_id
2823 				||' base currency code: '  ||p_base_currency_code
2824 				||' invoice amount: '	   ||p_invoice_amount
2825 				||' inv base amount: '	   ||p_base_amount
2826 				||' inv currency code: '   ||p_invoice_currency_code
2827 				||' invoice amount limit: '||p_invoice_amount_limit
2828 				||' hold future pay flag: '||p_hold_future_payments_flag;
2829 
2830    Print_Debug(l_debug_loc, l_debug_info);
2831    ---------------------------------------------------
2832 
2833      -- Bug 7158219
2834      ---------------------------------------------------
2835      l_debug_info := 'Check Invalid Distribution Account';
2836      Print_Debug(l_debug_loc, l_debug_info);
2837      ---------------------------------------------------
2838 
2839      Check_Invalid_Dist_Acct(
2840               p_invoice_id,
2841               p_system_user,
2842               p_holds,
2843               p_holds_count,
2844               p_release_count,
2845               l_curr_calling_sequence);
2846 
2847     ---------------------------------------------------
2848     l_debug_info := 'Check PO Required';
2849     Print_Debug(l_debug_loc, l_debug_info);
2850     ---------------------------------------------------
2851     Check_PO_Required(
2852 	      p_invoice_id,
2853 	      p_system_user,
2854 	      p_holds,
2855 	      p_holds_count,
2856 	      p_release_count,
2857 	      l_curr_calling_sequence);
2858 
2859     ---------------------------------------------------
2860     l_debug_info := 'Check for Missing Exchange Rate';
2861     Print_Debug(l_debug_loc, l_debug_info);
2862     ---------------------------------------------------
2863     Check_No_Rate(
2864 	      p_invoice_id,
2865 	      p_base_currency_code,
2866 	      p_system_user,
2867 	      p_holds,
2868 	      p_holds_count,
2869 	      p_release_count,
2870 	      l_curr_calling_sequence);
2871 
2872     ---------------------------------------------------
2873     l_debug_info := 'Check for invoice limit and vendor holds';
2874     Print_Debug(l_debug_loc, l_debug_info);
2875     ---------------------------------------------------
2876     Check_invoice_vendor(
2877 	      p_invoice_id,
2878 	      p_base_currency_code,
2879 	      p_invoice_amount,
2880 	      p_base_amount,
2881 	      p_invoice_currency_code,
2882 	      p_invoice_amount_limit,
2883 	      p_hold_future_payments_flag,
2884 	      p_system_user,
2885 	      p_holds,
2886 	      p_holds_count,
2887 	      p_release_count,
2888 	      l_curr_calling_sequence);
2889 
2890     ---------------------------------------------------
2891     l_debug_info := 'Check Prepaid Amount Exceeds Invoice Amount';
2892     Print_Debug(l_debug_loc, l_debug_info);
2893     ---------------------------------------------------
2894     Check_Prepaid_Amount(
2895 	      p_invoice_id,
2896 	      p_system_user,
2897 	      p_holds,
2898 	      p_holds_count,
2899 	      p_release_count,
2900 	      l_curr_calling_sequence);
2901 
2902 EXCEPTION
2903   WHEN OTHERS THEN
2904     IF (SQLCODE <> -20001) THEN
2905       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
2906       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
2907       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
2908       FND_MESSAGE.SET_TOKEN('PARAMETERS',
2909                   'Invoice_id  = '|| to_char(p_invoice_id)
2910               ||', Set of Books Id = '|| to_char(p_set_of_books_id)
2911               ||', Base Currency Code = '|| p_base_currency_code);
2912       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
2913     END IF;
2914     APP_EXCEPTION.RAISE_EXCEPTION;
2915 END Execute_General_Checks;
2916 
2917 /*=============================================================================
2918  |  PROCEDURE CHECK_INVALID_DIST_ACCT
2919  |      Procedure that checks whether an invoice has a distribution with an
2920  |      invalid distribution account and places or releases the
2921  |      DIST ACCT INVALID hold depending on the condition.
2922  |
2923  |  PARAMETER
2924  |      p_invoice_id
2925  |      p_system_user
2926  |      p_holds
2927  |      p_holds_count
2928  |      p_release_count
2929  |      p_calling_sequence
2930  |
2931  |  PROGRAM FLOW
2932  |
2933  |  KNOWN ISSUES:
2934  |
2935  |  NOTES:
2936  |
2937  |  MODIFICATION HISTORY
2938  |  Date         Author             Description of Change
2939  ============================================================================*/
2940 
2941 PROCEDURE Check_Invalid_Dist_Acct(
2942               p_invoice_id          IN            NUMBER,
2943               p_system_user         IN            NUMBER,
2944               p_holds               IN OUT NOCOPY HOLDSARRAY,
2945               p_holds_count         IN OUT NOCOPY COUNTARRAY,
2946               p_release_count       IN OUT NOCOPY COUNTARRAY,
2947               p_calling_sequence    IN            VARCHAR2) IS
2948 
2949   CURSOR Invalid_Dist_Acct_Cur IS
2950     SELECT  D.dist_code_combination_id, D.accounting_date
2951     FROM    ap_invoice_distributions D
2952     WHERE   D.invoice_id = p_invoice_id
2953     AND     D.posted_flag||'' in ('N', 'P')
2954     AND ((EXISTS (select 'x'
2955                   from gl_code_combinations C
2956                   where D.dist_code_combination_id = C.code_combination_id (+)
2957                   and (C.code_combination_id is null
2958                      or C.detail_posting_allowed_flag = 'N'
2959                      or C.start_date_active > D.accounting_date
2960                      or C.end_date_active < D.accounting_date
2961                      or C.template_id is not null
2962                      or C.enabled_flag <> 'Y'
2963                      or C.summary_flag <> 'N'
2964                      )))
2965     OR (D.dist_code_combination_id = -1))
2966     AND ROWNUM = 1;
2967 
2968   CURSOR Alternate_Account_Cur (c_ccid NUMBER, c_acct_date DATE) IS
2969         SELECT 'Y'
2970           FROM gl_code_combinations glcc
2971          WHERE glcc.code_combination_id = c_ccid
2972            AND glcc.alternate_code_combination_id IS NOT NULL
2973            AND EXISTS
2974                 (
2975                  SELECT 'Account Valid'
2976                    FROM gl_code_combinations a
2977                   WHERE a.code_combination_id         = glcc.alternate_code_combination_id
2978                     AND a.enabled_flag                = 'Y'
2979                     AND a.detail_posting_allowed_flag = 'Y'
2980                     AND c_acct_date BETWEEN NVL(a.start_date_active, c_acct_date)
2981                                         AND NVL(a.end_date_active, c_acct_date)
2982                 );
2983 
2984   l_ccid			AP_INVOICE_DISTRIBUTIONS_ALL.dist_code_combination_id%TYPE;
2985   l_accounting_date		AP_INVOICE_DISTRIBUTIONS_ALL.accounting_date%TYPE;
2986   l_alt_exists			VARCHAR2(50) := 'N';
2987   l_invalid_dist_ccid_exists    VARCHAR2(1)  := 'N';
2988   l_test_var                    VARCHAR2(50);
2989   l_debug_loc                   VARCHAR2(30) := 'Check_Invalid_Dist';
2990   l_curr_calling_sequence       VARCHAR2(2000);
2991   l_debug_info                  VARCHAR2(1000);
2992 
2993 BEGIN
2994 
2995   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
2996                              p_calling_sequence;
2997 
2998   IF (g_debug_mode = 'Y') THEN
2999     l_debug_info := 'General check - check invalid dist account';
3000     AP_Debug_Pkg.Print(g_debug_mode, l_debug_info );
3001     AP_Debug_Pkg.Print(g_debug_mode, 'invoice id :'||
3002                        to_char(p_invoice_id) );
3003   END IF;
3004 
3005   OPEN Invalid_Dist_Acct_Cur;
3006   LOOP
3007     FETCH Invalid_Dist_Acct_Cur INTO l_ccid, l_accounting_date;
3008     EXIT WHEN Invalid_DIst_Acct_Cur%NOTFOUND;
3009 
3010      IF (g_debug_mode = 'Y') THEN
3011        l_debug_info := 'Inside loop of curser - Invalid_Dist_Acct_Cur';
3012        AP_Debug_Pkg.Print(g_debug_mode, l_debug_info );
3013        AP_Debug_Pkg.Print(g_debug_mode, 'invalid dist ccid hold'||
3014                           l_invalid_dist_ccid_exists);
3015      END IF;
3016 
3017      --
3018      -- Per discussion with Shelley/Enda we will not place a hold
3019      -- when the distribution account is invalid and there is a
3020      -- valid alternate account defined in GL.
3021      -- Create Accounting will use the alternate account to
3022      -- generate the journal entries. The invoice distribution
3023      -- will not be stamped back with the alternate account.
3024      --
3025      OPEN  Alternate_Account_Cur(l_ccid, l_accounting_date);
3026      FETCH Alternate_Account_Cur
3027       INTO l_alt_exists;
3028      CLOSE Alternate_Account_Cur;
3029 
3030      IF (g_debug_mode = 'Y') THEN
3031        AP_Debug_Pkg.Print(g_debug_mode, 'Alternate Account Exists: '||
3032                           l_alt_exists);
3033      END IF;
3034 
3035      IF l_alt_exists = 'Y'  THEN
3036         l_invalid_dist_ccid_exists := 'N';
3037      ELSE
3038         l_invalid_dist_ccid_exists := 'Y';
3039      END IF;
3040 
3041   END LOOP;
3042   CLOSE Invalid_Dist_Acct_Cur;
3043 
3044   IF (g_debug_mode = 'Y') THEN
3045     l_debug_info := 'Process DIST ACCT INVALID hold status on invoice';
3046     AP_Debug_Pkg.Print(g_debug_mode, l_debug_info );
3047   END IF;
3048 
3049   Process_Inv_Hold_Status(
3050       p_invoice_id,
3051       null,
3052       null,
3053       'DIST ACCT INVALID',
3054       l_invalid_dist_ccid_exists,
3055       null,
3056       p_system_user,
3057       p_holds,
3058       p_holds_count,
3059       p_release_count,
3060       l_curr_calling_sequence);
3061 
3062 EXCEPTION
3063   WHEN OTHERS THEN
3064     IF (SQLCODE <> -20001) THEN
3065       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
3066       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
3067       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
3068       FND_MESSAGE.SET_TOKEN('PARAMETERS',
3069                   'Invoice_id  = '|| to_char(p_invoice_id));
3070       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
3071     END IF;
3072 
3073     IF ( Invalid_Dist_Acct_Cur%ISOPEN ) THEN
3074       CLOSE Invalid_Dist_Acct_Cur;
3075     END IF;
3076 
3077     APP_EXCEPTION.RAISE_EXCEPTION;
3078 END Check_Invalid_Dist_Acct;
3079 
3080 /*=============================================================================
3081  |  PROCEDURE CHECK_PO_REQUIRED
3082  |      Procedure that checks whether an invoice  has a PO REQUIRED
3083  |      condition and places or releases the hold depending on the condition
3084  |      For those distribution lines which have "pa_additon_flag" = 'T', means
3085  |      they are transferred from projects; Payables does not enforce po
3086  |      information requirment.
3087  |
3088  |  PARAMETER
3089  |      p_invoice_id
3090  |      p_system_user
3091  |      p_holds
3092  |      p_holds_count
3093  |      p_release_count
3094  |      p_calling_sequence
3095  |
3096  |  PROGRAM FLOW
3097  |
3098  |  KNOWN ISSUES:
3099  |
3100  |  NOTES:
3101  |
3102  |  MODIFICATION HISTORY
3103  |  Date         Author             Description of Change
3104  ============================================================================*/
3105 
3106 PROCEDURE Check_PO_Required(
3107               p_invoice_id         IN            NUMBER,
3108               p_system_user        IN            NUMBER,
3109               p_holds              IN OUT NOCOPY HOLDSARRAY,
3110               p_holds_count        IN OUT NOCOPY COUNTARRAY,
3111               p_release_count      IN OUT NOCOPY COUNTARRAY,
3112               p_calling_sequence   IN            VARCHAR2) IS
3113 
3114     CURSOR PO_Required_Cur IS
3115     -- Perf bug 5058995
3116     -- Modify below SQL to go to base tables : AP_INVOICES_ALL,
3117     -- AP_INVOICE_DISTRIBUTIONS_ALL and
3118     -- AP_SUPPLIER_SITES(instead of po_vendor_sites)
3119     /* Added the Hint index(apd AP_INVOICE_DISTRIBUTIONS_U1) for bug#7270053 */
3120     SELECT 'PO REQUIRED'
3121     FROM ap_invoices_all api, ap_supplier_sites pov
3122     WHERE EXISTS (select /*+ index(apd AP_INVOICE_DISTRIBUTIONS_U1) */ 'X'
3123                   from ap_invoice_distributions_all apd
3124                   where apd.invoice_id = api.invoice_id
3125                   and apd.line_type_lookup_code in ( 'ITEM', 'ACCRUAL')
3126                   and apd.po_distribution_id is null
3127                   and apd.pa_addition_flag <> 'T'
3128                   group by apd.dist_code_combination_id
3129                   HAVING sum(apd.amount) <> 0)
3130     AND   nvl(pov.hold_unmatched_invoices_flag, 'X') = 'Y'
3131     AND   api.invoice_type_lookup_code not in ('PREPAYMENT', 'INTEREST')
3132     AND   api.vendor_site_id = pov.vendor_site_id
3133     AND   api.invoice_id = p_invoice_id;
3134 
3135   l_po_required_exists     VARCHAR2(1)  := 'N';
3136   l_test_var               VARCHAR2(30) :='';
3137   l_debug_loc              VARCHAR2(30) := 'Check_PO_Required';
3138   l_curr_calling_sequence  VARCHAR2(2000);
3139   l_debug_info             VARCHAR2(1000);
3140 
3141 BEGIN
3142 
3143   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
3144                              p_calling_sequence;
3145 
3146   OPEN PO_Required_Cur;
3147   FETCH PO_Required_Cur INTO l_test_var;
3148   CLOSE PO_Required_Cur;
3149 
3150   IF ( l_test_var is not NULL ) THEN
3151     l_po_required_exists := 'Y';
3152 
3153     ---------------------------------------------------
3154     l_debug_info := 'PO REQUIRED hold placed. Invoice_ID: '||p_invoice_id;
3155     Print_Debug(l_debug_loc, l_debug_info);
3156     ---------------------------------------------------
3157   END IF;
3158 
3159   Process_Inv_Hold_Status(
3160       p_invoice_id,
3161       null,
3162       null,
3163       'PO REQUIRED',
3164       l_po_required_exists,
3165       null,
3166       p_system_user,
3167       p_holds,
3168       p_holds_count,
3169       p_release_count,
3170       l_curr_calling_sequence);
3171 
3172 EXCEPTION
3173   WHEN OTHERS THEN
3174     IF (SQLCODE <> -20001) THEN
3175       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
3176       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
3177       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
3178       FND_MESSAGE.SET_TOKEN('PARAMETERS',
3179                   'Invoice_id  = '|| to_char(p_invoice_id));
3180       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
3181     END IF;
3182     IF ( PO_Required_Cur%ISOPEN ) THEN
3183       CLOSE PO_Required_Cur;
3184     END IF;
3185     APP_EXCEPTION.RAISE_EXCEPTION;
3186 END Check_PO_Required;
3187 
3188 /*=============================================================================
3189  |  PROCEDURE CHECK_NO_RATE
3190  |      Procedure that checks if an invoice is a foreign invoice,  missing an
3191  |      exchange rate and places or releases the NO RATE' hold depending on
3192  |      the condition.
3193  |
3194  |  PARAMETER
3195  |      p_invoice_id
3196  |      p_base_currency_code
3197  |      p_system_user
3198  |      p_holds
3199  |      p_holds_count
3200  |      p_release_count
3201  |      p_calling_sequence
3202  |
3203  |  PROGRAM FLOW
3204  |
3205  |  KNOWN ISSUES:
3206  |
3207  |  NOTES:
3208  |
3209  |  MODIFICATION HISTORY
3210  |  Date         Author             Description of Change
3211  ============================================================================*/
3212 PROCEDURE Check_No_Rate(
3213               p_invoice_id          IN            NUMBER,
3214               p_base_currency_code  IN            VARCHAR2,
3215               p_system_user         IN            NUMBER,
3216               p_holds               IN OUT NOCOPY HOLDSARRAY,
3217               p_holds_count         IN OUT NOCOPY COUNTARRAY,
3218               p_release_count       IN OUT NOCOPY COUNTARRAY,
3219               p_calling_sequence    IN            VARCHAR2) IS
3220 
3221   CURSOR No_Rate_Cur IS
3222     SELECT 'Foreign Invoice without exchange rate'
3223     FROM   ap_invoices I
3224     WHERE  I.invoice_id = p_invoice_id
3225     AND    I.invoice_currency_code <> p_base_currency_code
3226     AND    I.exchange_rate is null;
3227 
3228   l_no_rate_exists         VARCHAR2(1)  := 'N';
3229   l_test_var               VARCHAR2(50) := '';
3230   l_debug_loc              VARCHAR2(30) := 'Check_No_Rate';
3231   l_curr_calling_sequence  VARCHAR2(2000);
3232   l_debug_info             VARCHAR2(1000);
3233 
3234 BEGIN
3235 
3236   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
3237                              p_calling_sequence;
3238 
3239   OPEN No_Rate_Cur;
3240   FETCH No_Rate_Cur INTO l_test_var;
3241   CLOSE No_Rate_Cur;
3242 
3243   IF ( l_test_var is not NULL ) THEN
3244     l_no_rate_exists := 'Y';
3245 
3246     ---------------------------------------------------
3247     l_debug_info := 'NO RATE hold placed. Invoice_ID: '||p_invoice_id;
3248     Print_Debug(l_debug_loc, l_debug_info);
3249     ---------------------------------------------------
3250   END IF;
3251 
3252   Process_Inv_Hold_Status(
3253       p_invoice_id,
3254       null,
3255       null,
3256       'NO RATE',
3257       l_no_rate_exists,
3258       null,
3259       p_system_user,
3260       p_holds,
3261       p_holds_count,
3262       p_release_count,
3263       l_curr_calling_sequence);
3264 
3265 EXCEPTION
3266   WHEN OTHERS THEN
3267     IF (SQLCODE <> -20001) THEN
3268       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
3269       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
3270       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
3271       FND_MESSAGE.SET_TOKEN('PARAMETERS',
3272                   'Invoice_id  = '|| to_char(p_invoice_id)
3273               ||', Base Currency Code = '|| p_base_currency_code);
3274       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
3275     END IF;
3276 
3277     IF ( No_Rate_Cur%ISOPEN ) THEN
3278       CLOSE No_Rate_Cur;
3279     END IF;
3280 
3281     APP_EXCEPTION.RAISE_EXCEPTION;
3282 END Check_No_Rate;
3283 
3284 /*=============================================================================
3285  |  PROCEDURE CHECK_DIST_VARIANCE
3286  |      Procedure that checks whether an invoice has a DIST VARIANCE condition,
3287  |      i.e. distribution total does not equal to its invoice line amount and
3288  |      places or releases the hold depending on the condition.
3289  |
3290  |  PARAMETER
3291  |      p_invoice_id
3292  |      p_invoice_line_number
3293  |      p_system_user
3294  |      p_holds
3295  |      p_holds_count
3296  |      p_release_count
3297  |      p_distribution_variance_exist
3298  |      p_calling_sequence
3299  |
3300  |  KNOWN ISSUES:
3301  |
3302  |  NOTES:
3303  |
3304  |  MODIFICATION HISTORY
3305  |  Date         Author             Description of Change
3306  ============================================================================*/
3307 
3308 PROCEDURE Check_Dist_Variance(
3309               p_invoice_id                  IN            NUMBER,
3310               p_invoice_line_number         IN            NUMBER,
3311               p_system_user                 IN            NUMBER,
3312               p_holds                       IN OUT NOCOPY HOLDSARRAY,
3313               p_holds_count                 IN OUT NOCOPY COUNTARRAY,
3314               p_release_count               IN OUT NOCOPY COUNTARRAY,
3315               p_distribution_variance_exist    OUT NOCOPY BOOLEAN,
3316               p_calling_sequence            IN            VARCHAR2) IS
3317 
3318   CURSOR Dist_Var_Cur IS
3319     /* Modified by epajaril to fix bug 6729934 */
3320     SELECT 'Distribution needs to be verified. '
3321     FROM   DUAL
3322     WHERE  EXISTS (
3323              SELECT 'Dist Total <> Invoice Line Amount'
3324              FROM   ap_invoice_lines_all AIL, ap_invoice_distributions_all D
3325              -- WHERE  AIL.invoice_id = D.invoice_id
3326              WHERE  AIL.invoice_id = D.invoice_id(+)
3327              AND    AIL.line_number = nvl(p_invoice_line_number, AIL.line_number)  --bug6661773
3328              AND    AIL.invoice_id = p_invoice_id
3329              -- AND    AIL.line_number = D.invoice_line_number
3330              AND    AIL.line_number = D.invoice_line_number(+)
3331              -- AND    (D.line_type_lookup_code <> 'RETAINAGE'
3332              AND    (NVL(D.line_type_lookup_code, 'ITEM') <> 'RETAINAGE'
3333     	           OR (AIL.line_type_lookup_code = 'RETAINAGE RELEASE'
3334     	           and D.line_type_lookup_code = 'RETAINAGE'))
3335              AND    (AIL.line_type_lookup_code
3336 			NOT IN ('ITEM', 'RETAINAGE RELEASE')
3337                       or (AIL.line_type_lookup_code
3338 			  IN ('ITEM', 'RETAINAGE RELEASE')
3339                      and (D.prepay_distribution_id IS NULL
3340                          or (D.prepay_distribution_id IS NOT NULL
3341                              and D.line_type_lookup_code NOT IN ('PREPAY', 'REC_TAX', 'NONREC_TAX')))))
3342     /*
3343     AND   (ail.line_type_lookup_code <> 'ITEM'
3344            OR (d.line_type_lookup_code <> 'PREPAY'
3345                and d.prepay_tax_parent_id IS  NULL)
3346            )
3347     */
3348     GROUP BY AIL.invoice_id, AIL.line_number, AIL.amount
3349     HAVING AIL.amount <> nvl(SUM(nvl(D.amount,0)),0));
3350 
3351   l_dist_var_exists        VARCHAR2(1)  := 'N';
3352   l_debug_loc              VARCHAR2(30) := 'Check_Dist_Variance';
3353   l_curr_calling_sequence  VARCHAR2(2000);
3354   l_debug_info             VARCHAR2(1000);
3355   l_test_var               VARCHAR2(50);
3356   l_inv_amount		   AP_INVOICES_ALL.INVOICE_AMOUNT%TYPE;
3357   l_dist_count		   NUMBER;
3358 
3359 BEGIN
3360 
3361   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||
3362                              '<-'||p_calling_sequence;
3363 
3364 
3365   l_dist_count := 0;
3366   l_inv_amount := 0;
3367   p_distribution_variance_exist := FALSE;
3368 
3369   -- Bug 4539514
3370   SELECT invoice_amount
3371   INTO l_inv_amount
3372   FROM ap_invoices_all ai
3373   WHERE ai.invoice_id = p_invoice_id;
3374 
3375   SELECT count(*) INTO l_dist_count
3376   FROM   ap_invoice_distributions_all aid
3377   WHERE  aid.invoice_id = p_invoice_id
3378   AND   ((aid.line_type_lookup_code <> 'PREPAY'
3379           AND   aid.prepay_tax_parent_id IS NULL)
3380           OR    nvl(invoice_includes_prepay_flag,'N') = 'Y')
3381   AND rownum =1; --Perf 6759699
3382 
3383   IF (l_dist_count = 0 AND l_inv_amount <> 0) Then
3384       l_dist_var_exists := 'Y';
3385       p_distribution_variance_exist := TRUE;
3386 
3387   --------------------------------------------------------
3388   l_debug_info := 'Distribution Variance Exists 1: '||l_dist_var_exists;
3389   Print_Debug(l_debug_loc, l_debug_info);
3390   --------------------------------------------------------
3391 
3392 --  END IF;
3393   -- Perf 6759699
3394   -- If the variables  l_dist_var_exists and p_distribution_variance_exists
3395   -- are set in the above if block then there is no need to open the
3396   -- cursor Dist_Var_Cur.
3397 
3398 else
3399 
3400   OPEN Dist_Var_Cur;
3401   FETCH Dist_Var_Cur
3402   INTO l_test_var;
3403 
3404   IF (Dist_Var_Cur%ROWCOUNT > 0) THEN
3405     l_dist_var_exists := 'Y';
3406     p_distribution_variance_exist := TRUE;
3407 
3408   --------------------------------------------------------
3409   l_debug_info := 'Distribution Variance Exists 2: '||l_dist_var_exists;
3410   Print_Debug(l_debug_loc, l_debug_info);
3411   --------------------------------------------------------
3412 
3413   END IF;
3414   CLOSE Dist_Var_Cur;
3415 end if; -- l_dist_count  Bug 6759699
3416 
3417   Process_Inv_Hold_Status(p_invoice_id,
3418         null,
3419         null,
3420         'DIST VARIANCE',
3421         l_dist_var_exists,
3422         null,
3423         p_system_user,
3424         p_holds,
3425         p_holds_count,
3426         p_release_count,
3427         l_curr_calling_sequence);
3428 
3429 EXCEPTION
3430   WHEN OTHERS THEN
3431     IF (SQLCODE <> -20001) THEN
3432       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
3433       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
3434       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
3435       FND_MESSAGE.SET_TOKEN('PARAMETERS',
3436                   'Invoice_id  = '|| to_char(p_invoice_id));
3437       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
3438     END IF;
3439 
3440     IF ( Dist_Var_Cur%ISOPEN ) THEN
3441       CLOSE Dist_Var_Cur;
3442     END IF;
3443 
3444     APP_EXCEPTION.RAISE_EXCEPTION;
3445 END Check_Dist_Variance;
3446 
3447 /*=============================================================================
3448  |  PROCEDURE CHECK_LINE_VARIANCE
3449  |    Procedure that checks whether an invoice has a LINE VARIANCE condition,
3450  |    i.e. lines total does not equal to invoice amount and places or
3451  |    releases the hold depending on the condition.
3452  |
3453  |  PARAMETER
3454  |      p_invoice_id
3455  |      p_system_user
3456  |      p_holds
3457  |      p_holds_count
3458  |      p_release_count
3459  |      p_line_variance_hold_exist
3460  |      p_calling_sequence
3461  |
3462  |  KNOWN ISSUES:
3463  |
3464  |  NOTES:
3465  |
3466  |  MODIFICATION HISTORY
3467  |  Date         Author             Description of Change
3468  ============================================================================*/
3469 
3470 PROCEDURE Check_Line_Variance(
3471               p_invoice_id                IN            NUMBER,
3472               p_system_user               IN            NUMBER,
3473               p_holds                     IN OUT NOCOPY HOLDSARRAY,
3474               p_holds_count               IN OUT NOCOPY COUNTARRAY,
3475               p_release_count             IN OUT NOCOPY COUNTARRAY,
3476               p_line_variance_hold_exist     OUT NOCOPY BOOLEAN,
3477               p_calling_sequence          IN            VARCHAR2,
3478 	      p_base_currency_code        IN            VARCHAR2) IS    --bug7271262
3479 
3480 
3481          CURSOR Line_Var_Cur IS
3482           SELECT 'Line Total <> Invoice Amount'
3483           FROM   ap_invoice_lines_all AIL, ap_invoices_all A
3484           WHERE  AIL.invoice_id = A.invoice_id
3485           AND    AIL.invoice_id = p_invoice_id
3486           AND    ((AIL.line_type_lookup_code <> 'TAX'
3487                    and (AIL.line_type_lookup_code NOT IN ('AWT','PREPAY')
3488                         or NVL(AIL.invoice_includes_prepay_flag,'N') = 'Y') OR
3489                   (AIL.line_type_lookup_code = 'TAX'
3490                   /* bug 5222316 */
3491                    and (AIL.prepay_invoice_id IS NULL
3492                         or (AIL.prepay_invoice_id is not null
3493                             and NVL(AIL.invoice_includes_prepay_flag, 'N') = 'Y')))))
3494                --    and AIL.prepay_invoice_id IS NULL)))
3495           GROUP BY A.invoice_id, A.invoice_amount, A.net_of_retainage_flag
3496           HAVING A.invoice_amount <>
3497                   nvl(SUM(nvl(AIL.amount,0) + decode(A.net_of_retainage_flag,
3498                                  'Y', nvl(AIL.retained_amount,0),0)),0);
3499 
3500   l_line_var_exists            VARCHAR2(1)  := 'N';
3501   l_test_var                   VARCHAR2(50);
3502   l_debug_loc                  VARCHAR2(30) := 'Check_Line_Variance';
3503   l_curr_calling_sequence      VARCHAR2(2000);
3504   l_debug_info                 VARCHAR2(1000);
3505   l_inv_cur_code               ap_invoices.invoice_currency_code%type;
3506   l_inv_amount		       ap_invoices_all.invoice_amount%TYPE;
3507   l_line_count		       number;
3508   l_org_id		       ap_invoices_all.org_id%TYPE;             --bug 7271262
3509   l_set_of_books_id            ap_invoices_all.set_of_books_id%TYPE;    --bug 7271262
3510   l_return_code		       VARCHAR2(100);				--bug 7271262
3511   l_return_message	       VARCHAR2(1000);				--bug 7271262
3512 
3513 BEGIN
3514 
3515   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||
3516                              '<-'||p_calling_sequence;
3517 
3518   p_line_variance_hold_exist := FALSE;
3519   l_line_count := 0;
3520   l_inv_amount := 0;
3521 
3522   --Bugfix:4539514, added the below code so that we place
3523   --LINE VARIANCE hold when the user validates a invoice
3524   --with no lines in it.
3525 
3526   --Bug 7271262 Added the org_id and set_of_books_id parameters in the below
3527   --select, to pass as parameters for JAI hook jai_ap_tolerance_pkg.inv_holds_check
3528 
3529   SELECT invoice_amount,org_id,set_of_books_id
3530   INTO l_inv_amount,l_org_id,l_set_of_books_id
3531   FROM ap_invoices ai
3532   WHERE ai.invoice_id = p_invoice_id;
3533 
3534   --Added the below code hook for India Localization as part of bug7271262
3535 
3536   l_debug_info := 'Calling code hook jai_ap_tolerance_pkg.inv_holds_check';
3537 
3538   IF (p_base_currency_code = 'INR') Then
3539     jai_ap_tolerance_pkg.inv_holds_check(
3540          p_invoice_id             =>  p_invoice_id,
3541          p_org_id                 =>  l_org_id,
3542          p_set_of_books_id        =>  l_set_of_books_id,
3543          p_invoice_amount         =>  l_inv_amount,
3544          p_invoice_currency_code  =>  p_base_currency_code,
3545          p_return_code            =>  l_return_code,
3546          p_return_message         =>  l_return_message);
3547    End IF;
3548 
3549  /* End of Bug 7271262 */
3550 
3551   SELECT count(*)
3552   INTO l_line_count
3553   FROM   ap_invoice_lines ail
3554   WHERE  ail.invoice_id = p_invoice_id
3555   AND   (ail.line_type_lookup_code NOT IN ('PREPAY','AWT')
3556          OR nvl(invoice_includes_prepay_flag,'N') = 'Y');
3557 
3558   IF (l_line_count = 0 AND l_inv_amount <> 0) Then
3559     l_line_var_exists := 'Y';
3560     p_line_variance_hold_exist := TRUE;
3561   END IF;
3562 
3563   --
3564 
3565   OPEN Line_Var_Cur;
3566   FETCH Line_Var_Cur
3567   INTO l_test_var;
3568 
3569   IF ( Line_Var_Cur%ROWCOUNT > 0 ) THEN
3570     l_line_var_exists := 'Y';
3571     p_line_variance_hold_exist := TRUE;
3572   END IF;
3573 
3574   CLOSE Line_Var_Cur;
3575 
3576   --------------------------------------------------------
3577   l_debug_info := 'Line Variance Exists: '||l_line_var_exists;
3578   Print_Debug(l_debug_loc, l_debug_info);
3579   --------------------------------------------------------
3580 
3581   Process_Inv_Hold_Status(
3582       p_invoice_id,
3583       null,
3584       null,
3585       'LINE VARIANCE',
3586       l_line_var_exists,
3587       null,
3588       p_system_user,
3589       p_holds,
3590       p_holds_count,
3591       p_release_count,
3592       l_curr_calling_sequence);
3593 
3594 EXCEPTION
3595   WHEN OTHERS THEN
3596     IF (SQLCODE <> -20001) THEN
3597       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
3598       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
3599       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
3600       FND_MESSAGE.SET_TOKEN('PARAMETERS',
3601                   'Invoice_id  = '|| to_char(p_invoice_id));
3602       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
3603     END IF;
3604     IF ( Line_Var_Cur%ISOPEN ) THEN
3605       CLOSE Line_Var_Cur;
3606     END IF;
3607 
3608     APP_EXCEPTION.RAISE_EXCEPTION;
3609 END Check_Line_Variance;
3610 
3611 /*=============================================================================
3612  |  PROCEDURE Line_BASE_AMOUNT_CALCULATION
3613  |
3614  |  DESCRIPTION
3615  |      Calculate the functional amount for all the lines which were not
3616  |      partiallly or fully accounted. Populate the rounding amount for lines
3617  |
3618  |  PARAMETERS
3619  |      p_invoice_id
3620  |      p_invoice_currency_code
3621  |      p_base_currency_code
3622  |      p_exchange_rate
3623  |      p_need_to_round_flag
3624  |      p_calling_sequence
3625  |
3626  |  PROGRAM FLOW
3627  |
3628  |  KNOWN ISSUES:
3629  |
3630  |  NOTES:
3631  |
3632  |  MODIFICATION HISTORY
3633  |  Date         Author             Description of Change
3634  |
3635  *============================================================================*/
3636 
3637 PROCEDURE Line_Base_Amount_Calculation(
3638               p_invoice_id            IN            NUMBER,
3639               p_invoice_currency_code IN            VARCHAR2,
3640               p_base_currency_code    IN            VARCHAR2,
3641               p_exchange_rate         IN            NUMBER,
3642               p_need_to_round_flag    IN            VARCHAR2 DEFAULT 'N',
3643               p_calling_sequence      IN            VARCHAR2) IS
3644 
3645   l_rounded_line_num       ap_invoice_lines.line_number%TYPE;
3646   l_rounded_amt            NUMBER;
3647   l_round_amt_exist        BOOLEAN := FALSE;
3648   l_key_value              NUMBER;
3649 
3650   l_debug_loc              VARCHAR2(30) := 'Line_Base_Amount_Calculation';
3651   l_curr_calling_sequence  VARCHAR2(2000);
3652   l_debug_info             VARCHAR2(100);
3653   l_debug_context          VARCHAR2(2000);
3654 
3655   l_modified_line_rounding_amt   NUMBER; --6892789
3656   l_base_amt                     NUMBER; --6892789
3657   l_round_inv_line_numbers       AP_INVOICES_UTILITY_PKG.inv_line_num_tab_type; --6892789
3658 
3659 BEGIN
3660 
3661   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||
3662                              '<-'||p_calling_sequence;
3663 
3664   -----------------------------------------------------
3665   l_debug_info := 'Update Invoice Lines Base Amount';
3666   Print_Debug(l_debug_loc, l_debug_info);
3667   -----------------------------------------------------
3668 
3669   UPDATE AP_INVOICE_LINES AIL
3670      SET AIL.base_amount = DECODE(p_base_currency_code, p_invoice_currency_code,
3671                                   NULL,
3672                                   ap_utilities_pkg.ap_round_currency(
3673                                       amount * p_exchange_rate,
3674                                       p_base_currency_code)),
3675          AIL.last_update_date = SYSDATE,
3676          AIL.last_updated_by = FND_GLOBAL.user_id,
3677          AIL.last_update_login = FND_GLOBAL.login_id
3678   WHERE  AIL.invoice_id = p_invoice_id
3679   -- Bug 6621883
3680   AND    (EXISTS ( SELECT 'NOT POSTED'
3681                     FROM ap_invoice_distributions_all D
3682                    WHERE D.invoice_id = AIL.invoice_id
3683                      AND D.invoice_line_number = AIL.line_number
3684                      AND NVL(D.posted_flag, 'N') = 'N' )
3685           OR NOT EXISTS (SELECT 'DIST DOES NOT EXIST'
3686                     FROM ap_invoice_distributions_all D1
3687                    WHERE D1.invoice_id = AIL.invoice_id
3688                      AND D1.invoice_line_number = AIL.line_number
3689                      AND AIL.amount IS NOT NULL
3690                         )
3691           )
3692   --Retropricing: Adjustment Correction lines on the PPA should be
3693   -- excluded. Base amounts on zero amount adjustment lines adjustment
3694   -- correction lines on the PPA is handled while creating PPA Docs.
3695   --Bugfix:4625349, modified the AND clause
3696   AND
3697   ( line_type_lookup_code <> 'RETROITEM' OR
3698    (line_type_lookup_code = 'RETROITEM' and
3699     match_type <> 'ADJUSTMENT_CORRECTION')
3700   );
3701 
3702   -----------------------------------------------------
3703   l_debug_info := 'Round Invoice Lines Base Amount';
3704   Print_Debug(l_debug_loc, l_debug_info);
3705   -----------------------------------------------------
3706 
3707   IF ( NVL(p_need_to_round_flag, 'N') = 'Y' ) THEN
3708     --Retropricing: Max of the largest invoice line should exclude
3709     -- Adjustment Correction lines on the PPA as well as the
3710     -- Zero Amt Adjustment line on the Original Invoice.
3711     -- Change needs to be done in apinvutb.pls.
3712 
3713   /* modifying following code as per the bug 6892789 as there is a chance
3714      that line base amt goes to -ve value (line amount being +ve) so in such
3715      case, adjust line base amount upto zero and adjust the remaing amount in
3716      another line having next max amount */
3717 
3718     -- get the lines which can be adjusted
3719     l_round_amt_exist := AP_INVOICES_UTILITY_PKG.round_base_amts(
3720                              X_Invoice_Id           => p_invoice_id,
3721                              X_Reporting_Ledger_Id  => NULL,
3722                              X_Rounded_Line_Numbers => l_round_inv_line_numbers,
3723                              X_Rounded_Amt          => l_rounded_amt,
3724                              X_Debug_Info           => l_debug_info,
3725                              X_Debug_Context        => l_debug_context,
3726                              X_Calling_sequence     => l_curr_calling_sequence);
3727 
3728     --adjustment required and there exists line numbers that can be adjusted
3729     IF ( l_round_amt_exist  AND l_round_inv_line_numbers.count > 0 ) THEN
3730       -- iterate throgh lines until there is no need to adjust
3731       for i in 1 .. l_round_inv_line_numbers.count
3732       loop
3733         IF l_rounded_amt <> 0 THEN
3734         -- get the existing base amount for the selected line
3735           select base_amount
3736           INTO   l_base_amt
3737           FROM   AP_INVOICE_LINES
3738           WHERE  invoice_id = p_invoice_id
3739           AND    line_number = l_round_inv_line_numbers(i);
3740 
3741          -- get the calculated adjusted base amount and rounding amount
3742          -- get rounding amount for the next line if required
3743          l_base_amt := AP_APPROVAL_PKG.get_adjusted_base_amount(
3744                                 p_base_amount => l_base_amt,
3745                                 p_rounding_amt => l_modified_line_rounding_amt,
3746                                 p_next_line_rounding_amt => l_rounded_amt);
3747 
3748          -- update the calculatd base amount, rounding amount
3749           UPDATE AP_INVOICE_LINES
3750           SET    base_amount = l_base_amt,
3751                  rounding_amt = ABS( NVL(l_modified_line_rounding_amt, 0) ),
3752                  last_update_date = SYSDATE,
3753                  last_updated_by = FND_GLOBAL.user_id,
3754                  last_update_login = FND_GLOBAL.login_id
3755           WHERE  invoice_id = p_invoice_id
3756           AND    line_number = l_round_inv_line_numbers(i);
3757         ELSE--adjustment not required or there are no lines that can be adjusted
3758          EXIT;
3759         END IF;
3760       end loop;
3761     END IF;
3762   END IF;
3763 
3764 EXCEPTION
3765   WHEN OTHERS THEN
3766     IF (SQLCODE <> -20001) THEN
3767       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
3768       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
3769       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
3770       FND_MESSAGE.SET_TOKEN('PARAMETERS',
3771                   'Invoice_id  = '|| to_char(p_invoice_id));
3772       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
3773     END IF;
3774     APP_EXCEPTION.RAISE_EXCEPTION;
3775 END Line_Base_Amount_Calculation;
3776 
3777 /*=============================================================================
3778  |  PROCEDURE Dist_BASE_AMOUNT_CALCULATION
3779  |
3780  |  DESCRIPTION
3781  |      Calculate the functional amount for all the lines and distributions
3782  |      which were not partiallly or fully accounted. Populate the rounding
3783  |      amount for lines and distribuitons
3784  |
3785  |  PARAMETERS
3786  |      p_invoice_id
3787  |      p_invoice_line_number
3788  |      p_invoice_currency_code
3789  |      p_base_currency_code
3790  |      p_invoice_exchange_rate
3791  |
3792  |      p_calling_sequence
3793  |
3794  |  PROGRAM FLOW
3795  |
3796  |  KNOWN ISSUES:
3797  |
3798  |  NOTES:
3799  |
3800  |  MODIFICATION HISTORY
3801  |  Date         Author             Description of Change
3802  |
3803  *============================================================================*/
3804 
3805 PROCEDURE Dist_Base_Amount_Calculation(
3806               p_invoice_id            IN            NUMBER,
3807               p_invoice_line_number   IN            NUMBER,
3808               p_invoice_currency_code IN            VARCHAR2,
3809               p_base_currency_code    IN            VARCHAR2,
3810               p_invoice_exchange_rate IN            NUMBER,
3811               p_need_to_round_flag    IN            VARCHAR2 DEFAULT 'N',
3812               p_calling_sequence      IN            VARCHAR2) IS
3813 
3814 
3815   l_round_amt_exists       BOOLEAN := FALSE;
3816   l_rounded_amt            NUMBER;
3817   l_rounded_dist_id        ap_invoice_distributions.INVOICE_DISTRIBUTION_ID%TYPE;
3818   l_debug_loc              VARCHAR2(30) := 'Dist_Base_Amount_Calculation';
3819   l_curr_calling_sequence  VARCHAR2(2000);
3820   l_debug_info             VARCHAR2(1000);
3821   l_debug_context          VARCHAR2(2000);
3822 
3823   l_base_amt                   NUMBER; --6892789
3824   l_modified_dist_rounding_amt NUMBER; --6892789
3825   l_round_dist_id_list  AP_INVOICE_LINES_PKG.distribution_id_tab_type; --6892789
3826 
3827 BEGIN
3828 
3829   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||
3830                              '<-'||p_calling_sequence;
3831 
3832   ------------------------------------------------------
3833   l_debug_info := 'Update Distribution Base Amounts';
3834   Print_Debug(l_debug_loc, l_debug_info);
3835   ------------------------------------------------------
3836 
3837   --Bugfix:4625771
3838   --Added the AND clause so as to not to overwrite the
3839   --base_amounts calculated on matched distributions
3840   --which either have an IPV or ERV or both, during the
3841   --earlier call to exec_matched_variance_checks.
3842   UPDATE AP_INVOICE_DISTRIBUTIONS
3843      SET base_amount = DECODE(p_base_currency_code, p_invoice_currency_code,
3844                                NULL, ap_utilities_pkg.ap_round_currency(
3845                                          amount * p_invoice_exchange_rate,
3846                                          p_base_currency_code)),
3847          last_update_date = SYSDATE,
3848          last_updated_by = FND_GLOBAL.user_id,
3849          last_update_login = FND_GLOBAL.login_id
3850   WHERE  invoice_id = p_invoice_id
3851   AND    invoice_line_number = p_invoice_line_number
3852   AND    NVL(posted_flag,'N') = 'N'
3853   --Bugfix:4625771
3854   AND    related_id IS NULL;
3855 
3856   ------------------------------------------------------
3857   l_debug_info := 'Round Distribution Base Amounts';
3858   Print_Debug(l_debug_loc, l_debug_info);
3859   ------------------------------------------------------
3860 
3861   IF ( NVL(p_need_to_round_flag, 'N') = 'Y' ) THEN
3862 
3863   /* modifying following code as per the bug 6892789 as there is a chance that
3864      distribution base amt goes to -ve value (amount being +ve) so in such case,
3865      adjust dist base amount upto zero and adjust the remaing amount in another
3866      distribution having next max amount */
3867 
3868     -- get the distributions which can be adjusted
3869     l_round_amt_exists := AP_INVOICE_LINES_PKG.round_base_amts(
3870                               x_invoice_id          => p_invoice_id,
3871                               x_line_number         => p_invoice_line_number,
3872                               x_reporting_ledger_id => NULL,
3873                               x_round_dist_id_list  => l_round_dist_id_list,
3874                               x_rounded_amt         => l_rounded_amt,
3875                               x_debug_info          => l_debug_info,
3876                               x_debug_context       => l_debug_context,
3877                               x_calling_sequence    => l_curr_calling_sequence);
3878 
3879     -- adjustment required and there exists dists that can be adjusted
3880     IF ( l_round_amt_exists  AND l_round_dist_id_list.count > 0 ) THEN
3881     -- iterate through dists till there is no need to adjust
3882       for i in 1 .. l_round_dist_id_list.count
3883       loop
3884           IF l_rounded_amt <> 0 THEN
3885 
3886             -- get the existing base amount for the selected distribution
3887             select base_amount
3888             INTO   l_base_amt
3889             FROM   AP_INVOICE_DISTRIBUTIONS
3890             WHERE  invoice_id = p_invoice_id
3891             AND    invoice_line_number = p_invoice_line_number
3892             AND    invoice_distribution_id = l_round_dist_id_list(i);
3893 
3894             -- get the calculated adjusted base amount and rounding amount
3895             -- get rounding amount for the next dist, if required
3896             l_base_amt := AP_APPROVAL_PKG.get_adjusted_base_amount(
3897                                  p_base_amount => l_base_amt,
3898                                  p_rounding_amt => l_modified_dist_rounding_amt,
3899                                  p_next_line_rounding_amt => l_rounded_amt);
3900 
3901             -- update the calculatd base amount, rounding amount
3902             UPDATE AP_INVOICE_DISTRIBUTIONS
3903             SET    base_amount = l_base_amt,
3904             rounding_amt = ABS( l_modified_dist_rounding_amt ),
3905             last_update_date = SYSDATE,
3906             last_updated_by = FND_GLOBAL.user_id,
3907             last_update_login = FND_GLOBAL.login_id
3908             WHERE  invoice_distribution_id = l_round_dist_id_list(i);
3909 
3910           ELSE
3911           --adjustment not required or there are no dists that can be adjusted
3912               EXIT;
3913           END IF;
3914      end loop;
3915     END IF;
3916   END IF;
3917 
3918 EXCEPTION
3919   WHEN OTHERS THEN
3920     IF (SQLCODE <> -20001) THEN
3921       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
3922       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
3923       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
3924       FND_MESSAGE.SET_TOKEN('PARAMETERS',
3925                   'Invoice_id  = '|| to_char(p_invoice_id));
3926       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
3927     END IF;
3928     APP_EXCEPTION.RAISE_EXCEPTION;
3929 END Dist_Base_Amount_Calculation;
3930 
3931 /*=============================================================================
3932  |  PROCEDURE GENERATE_ACCOUNT_EVENT
3933  |
3934  |  DESCRIPTION:
3935  |             Generate Accounting Event
3936  |
3937  |  PARAMETERS
3938  |    p_invoice_id
3939  |    p_calling_sequence
3940  |
3941  |  KNOWN ISSUES:
3942  |
3943  |  NOTES:
3944  |      Events Project 5
3945  |      Before creating new events, we need to check if there are any
3946  |      events which have been created with the status 'INCOMPLETE'. If
3947  |      there are, and the holds have now been removed, we may want to
3948  |      change the status from 'INCOMPLETE' to 'CREATED' rather than
3949  |      creating a new event.
3950  |
3951  |  MODIFICATION HISTORY
3952  |  Date         Author             Description of Change
3953  |
3954  *============================================================================*/
3955 
3956 PROCEDURE Generate_Account_Event(
3957               p_invoice_id            IN            NUMBER,
3958               p_calling_sequence      IN            VARCHAR2) IS
3959 
3960   l_accounting_event_id         NUMBER;       -- Events Project - 1
3961   l_null_event_id               NUMBER;       -- Events Project - 4
3962 
3963   l_debug_loc             VARCHAR2(30) := 'Generate_Account_Event';
3964   l_curr_calling_sequence VARCHAR2(2000);
3965   l_debug_info            VARCHAR2(1000);
3966 
3967 BEGIN
3968 
3969   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
3970                              p_calling_sequence;
3971 
3972   -------------------------------------------------
3973   l_debug_info := 'Accounting Event Generation';
3974   Print_Debug(l_debug_loc, l_debug_info);
3975   -------------------------------------------------
3976 
3977   SELECT count(*)
3978     INTO l_null_event_id
3979     FROM ap_invoice_distributions aid
3980    WHERE aid.invoice_id = P_invoice_id
3981      AND aid.accounting_event_id is NULL;
3982 
3983 
3984   AP_ACCOUNTING_EVENTS_PKG.Update_Invoice_Events_Status(
3985 		   p_invoice_id		=> p_invoice_id,
3986 	           p_calling_sequence	=> l_curr_calling_sequence);
3987 
3988   IF l_null_event_id > 0 then
3989 
3990     -------------------------------------------------
3991     l_debug_info := 'Accounting Event - create event for null event rows';
3992     Print_Debug(l_debug_loc, l_debug_info);
3993     -------------------------------------------------
3994 
3995     AP_Accounting_Events_Pkg.Create_Events(
3996             p_event_type	  => 'INVOICES',
3997 	    p_doc_type		  => NULL,
3998             p_doc_id		  => p_invoice_id,
3999             p_accounting_date	  => NULL,
4000             p_accounting_event_id => l_accounting_event_id,
4001             p_checkrun_name	  => NULL,
4002             p_calling_sequence	  => l_curr_calling_sequence);
4003 
4004   END IF;
4005 
4006 EXCEPTION
4007   WHEN OTHERS THEN
4008     IF (SQLCODE <> -20001) THEN
4009       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
4010       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
4011       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
4012       FND_MESSAGE.SET_TOKEN('PARAMETERS',
4013                   'Invoice_id  = '|| to_char(p_invoice_id));
4014       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
4015     END IF;
4016     APP_EXCEPTION.RAISE_EXCEPTION;
4017 END Generate_Account_Event;
4018 
4019 /*=============================================================================
4020  |  PROCEDURE CHECK_PREPAID_AMOUNT
4021  |      Procedure that checks whether the invoice amount is more than
4022  |      the prepaid amount
4023  |
4024  |  PARAMETERS
4025  |      p_invoice_id
4026  |      p_system_user
4027  |      p_holds
4028  |      p_holds_count
4029  |      p_release_count
4030  |      p_calling_sequence
4031  |
4032  |  KNOWN ISSUES:
4033  |
4034  |  NOTES:
4035  |
4036  |  MODIFICATION HISTORY
4037  |  Date         Author             Description of Change
4038  |
4039  *============================================================================*/
4040 
4041 PROCEDURE Check_Prepaid_Amount(
4042               p_invoice_id              IN            NUMBER,
4043               p_system_user             IN            NUMBER,
4044               p_holds                   IN OUT NOCOPY HOLDSARRAY,
4045               p_holds_count             IN OUT NOCOPY COUNTARRAY,
4046               p_release_count           IN OUT NOCOPY COUNTARRAY,
4047               p_calling_sequence        IN            VARCHAR2) IS
4048 
4049   -- This select modified to use the lines table instead of distributions
4050   -- to get the prepaid_amount, only if the prepayments are not included
4051   -- in the invoice.  The prepaid amount will include taxes.
4052 
4053   CURSOR Prepay_Var_Cur IS
4054   SELECT AI.invoice_amount, (0 - sum(nvl(AIL.amount,0)))
4055     FROM ap_invoices_all AI, ap_invoice_lines_all AIL
4056    WHERE AI.invoice_id = p_invoice_id
4057      AND AIL.invoice_id = AI.invoice_id
4058      AND AIL.invoice_includes_prepay_flag = 'N'
4059      AND AIL.line_type_lookup_code IN ('PREPAY', 'TAX')
4060      AND AIL.prepay_invoice_id IS NOT NULL
4061      AND AIL.prepay_line_number IS NOT NULL
4062    GROUP BY AI.invoice_id, AI.invoice_amount
4063    Having sum(nvl(AIL.amount,0)) <>0; --Bug5724818
4064 
4065   l_invoice_amount              NUMBER;
4066   l_prepaid_amount              NUMBER;
4067   l_prepay_var_exists           VARCHAR2(1) := 'N';
4068   l_debug_loc                   VARCHAR2(30) := 'Check_Prepaid_Amount';
4069   l_debug_info                  VARCHAR2(1000);
4070   l_curr_calling_sequence       VARCHAR2(2000);
4071 
4072 BEGIN
4073 
4074   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||
4075                              '<-'||p_calling_sequence;
4076 
4077   OPEN Prepay_Var_Cur;
4078   LOOP
4079     FETCH Prepay_Var_Cur
4080      INTO l_invoice_amount, l_prepaid_amount;
4081 
4082     EXIT WHEN Prepay_Var_Cur%NOTFOUND;
4083 
4084     IF l_invoice_amount < l_prepaid_amount THEN
4085        l_prepay_var_exists := 'Y';
4086 
4087        -------------------------------------------------
4088        l_debug_info := 'PREPAY VARIANCE hold placed';
4089        Print_Debug(l_debug_loc, l_debug_info);
4090        -------------------------------------------------
4091     END IF;
4092   END LOOP;
4093   CLOSE Prepay_Var_Cur;
4094 
4095   Process_Inv_Hold_Status(
4096       p_invoice_id,
4097       null,
4098       null,
4099       'PREPAID AMOUNT',
4100       l_prepay_var_exists,
4101       null,
4102       p_system_user,
4103       p_holds,
4104       p_holds_count,
4105       p_release_count,
4106       l_curr_calling_sequence);
4107 
4108 EXCEPTION
4109   WHEN OTHERS THEN
4110     IF (SQLCODE <> -20001) THEN
4111       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
4112       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
4113       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
4114       FND_MESSAGE.SET_TOKEN('PARAMETERS',
4115                   'Invoice_id  = '|| to_char(p_invoice_id));
4116       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
4117     END IF;
4118     APP_EXCEPTION.RAISE_EXCEPTION;
4119 END Check_Prepaid_Amount;
4120 
4121 /*=============================================================================
4122  |  PROCEDURE CHECK_INVOICE_VENDOR
4123  |      Procedure that checks if an invoice has any of the following
4124  |      1. Exceeds the invoice amount limit stated at the vendor site level
4125  |         and places or releases the AMOUNT' hold
4126  |      2. The vendor site has set to hold future payments and places or
4127  |         release the 'VENDOR' hold
4128  |
4129  |  PARAMETERS
4130  |      p_invoice_id
4131  |      p_base_currency_code
4132  |      p_invoice_amount
4133  |      p_base_amount
4134  |      p_invoice_currency_code
4135  |      p_invoice_amount_limit
4136  |      p_hold_future_payments_flag
4137  |      p_system_user
4138  |      p_holds
4139  |      p_holds_count
4140  |      p_release_count
4141  |      p_calling_sequence
4142  |
4143  |  KNOWN ISSUES:
4144  |
4145  |  NOTES:
4146  |
4147  |  MODIFICATION HISTORY
4148  |  Date         Author             Description of Change
4149  |
4150  *============================================================================*/
4151 
4152 PROCEDURE Check_invoice_vendor(
4153               p_invoice_id                IN            NUMBER,
4154               p_base_currency_code        IN            VARCHAR2,
4155               p_invoice_amount            IN            NUMBER,
4156               p_base_amount               IN            NUMBER,
4157               p_invoice_currency_code     IN            VARCHAR2,
4158               p_invoice_amount_limit      IN            NUMBER,
4159               p_hold_future_payments_flag IN            VARCHAR2,
4160               p_system_user               IN            NUMBER,
4161               p_holds                     IN OUT NOCOPY HOLDSARRAY,
4162               p_holds_count               IN OUT NOCOPY COUNTARRAY,
4163               p_release_count             IN OUT NOCOPY COUNTARRAY,
4164               p_calling_sequence          IN            VARCHAR2) IS
4165 
4166   l_amount_hold_required        VARCHAR2(1)  := 'N';
4167   l_debug_loc                   VARCHAR2(30) := 'Check_invoice_vendor';
4168   l_curr_calling_sequence       VARCHAR2(2000);
4169   l_debug_info                  VARCHAR2(1000);
4170 
4171 BEGIN
4172 
4173 
4174   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||
4175                               '<-'||p_calling_sequence;
4176    /*-----------------------------------------------------------------+
4177     |  Check invoice amount limit                                     |
4178     +-----------------------------------------------------------------*/
4179 
4180   IF (p_invoice_amount_limit is not null) THEN
4181 
4182     IF ((p_invoice_currency_code = p_base_currency_code and
4183          p_invoice_amount > p_invoice_amount_limit) or
4184         (p_invoice_currency_code <> p_base_currency_code and
4185          p_base_amount > p_invoice_amount_limit)) THEN
4186       l_amount_hold_required := 'Y';
4187     ELSE
4188       l_amount_hold_required := 'N';
4189     END IF;
4190   END IF;
4191 
4192   -------------------------------------------------------
4193   l_debug_info := 'AMOUNT hold placed: '||l_amount_hold_required;
4194   Print_Debug(l_debug_loc, l_debug_info);
4195   -------------------------------------------------------
4196 
4197   Process_Inv_Hold_Status(
4198       p_invoice_id,
4199       null,
4200       null,
4201       'AMOUNT',
4202       l_amount_hold_required,
4203       null,
4204       p_system_user,
4205       p_holds,
4206       p_holds_count,
4207       p_release_count,
4208       l_curr_calling_sequence);
4209 
4210   -------------------------------------------------------
4211   l_debug_info := 'Check_invoice_vendor - check hold future payment';
4212   Print_Debug(l_debug_loc, l_debug_info);
4213   -------------------------------------------------------
4214 
4215   Process_Inv_Hold_Status(
4216       p_invoice_id,
4217       null,
4218       null,
4219       'VENDOR',
4220       p_hold_future_payments_flag,
4221       null,
4222       p_system_user,
4223       p_holds,
4224       p_holds_count,
4225       p_release_count,
4226       l_curr_calling_sequence);
4227 
4228 EXCEPTION
4229   WHEN OTHERS THEN
4230     IF (SQLCODE <> -20001) THEN
4231       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
4232       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
4233       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
4234       FND_MESSAGE.SET_TOKEN('PARAMETERS',
4235                   'Invoice_id  = '|| to_char(p_invoice_id)
4236               ||', Base Currency Code = '|| p_base_currency_code
4237               ||', Invoice Currency Code = '|| p_invoice_currency_code
4238               ||', Invoice Amount = '|| to_char(p_invoice_amount)
4239               ||', Base Amount = '|| to_char(p_base_amount)
4240               ||', Invoice Amount Limit = '|| to_char(p_invoice_amount_limit)
4241               ||', Hold Future Payments Flag = '|| p_hold_future_payments_flag);
4242       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
4243     END IF;
4244     APP_EXCEPTION.RAISE_EXCEPTION;
4245 END Check_invoice_vendor;
4246 
4247 
4248 /*=============================================================================
4249  |  PROCEDURE Check_Manual_AWT_Segments
4250  |      Procedure that checks AWT Account segments
4251  |
4252  |
4253  |  PARAMETERS
4254  |      p_invoice_id
4255  |      p_system_user
4256  |      p_holds
4257  |      p_holds_count
4258  |      p_release_count
4259  |      p_calling_sequence
4260  |
4261  |  KNOWN ISSUES:
4262  |
4263  |  NOTES:
4264  |      FOR NON-AWT LINES
4265  |      1. Excluding the tax line on the prepayment from the distributions
4266  |      2. Including the Prepayment and Prepayment Tax if
4267  |         invoice_includes_prepay_flag = 'Y'
4268  |  MODIFICATION HISTORY
4269  |  Date         Author             Description of Change
4270  |
4271  *============================================================================*/
4272 
4273 PROCEDURE Check_Manual_AWT_Segments(
4274               p_invoice_id       IN            NUMBER,
4275               p_system_user      IN            NUMBER,
4276               p_holds            IN OUT NOCOPY HOLDSARRAY,
4277               p_holds_count      IN OUT NOCOPY COUNTARRAY,
4278               p_release_count    IN OUT NOCOPY COUNTARRAY,
4279               p_calling_sequence IN            VARCHAR2) IS
4280 
4281   CURSOR c_manual_awt_dist_segs is
4282   SELECT ap_utilities_pkg.get_auto_offsets_segments(
4283                               aid.dist_code_combination_id)
4284   FROM   ap_invoice_distributions aid
4285   WHERE  aid.invoice_id = p_invoice_id
4286   AND    aid.line_type_lookup_code = 'AWT'
4287   AND    aid.awt_flag = 'M';
4288 
4289   -- eTax Uptake.  This select modified to use the
4290   -- prepay_distribution_id column to determine if a distribution
4291   -- is not created by a prepayment application
4292   -- and include the lines table to know if the prepayment was included
4293   -- in the invoice
4294   CURSOR c_non_awt_dists_segs is
4295   SELECT ap_utilities_pkg.get_auto_offsets_segments(
4296                                aid.dist_code_combination_id)
4297   FROM   ap_invoice_distributions_all aid, ap_invoice_lines_all ail
4298   WHERE  ail.invoice_id = p_invoice_id
4299   AND    ail.invoice_id = aid.invoice_id
4300   AND    ail.line_number = aid.invoice_line_number
4301   AND    ((aid.line_type_lookup_code not in ('AWT','PREPAY')
4302          AND    aid.prepay_distribution_id IS NULL)
4303          OR     NVL(ail.invoice_includes_prepay_flag,'N') = 'Y');
4304 
4305 
4306   l_manual_awt_dist_segs       VARCHAR2(100);
4307   l_non_awt_dist_segs          VARCHAR2(100);
4308   p_dist_segs_hold_required    VARCHAR2(1);
4309   l_curr_calling_sequence      VARCHAR2(2000);
4310   l_debug_info                 VARCHAR2(1000);
4311 
4312 
4313 BEGIN
4314 
4315   l_curr_calling_sequence := 'AP_APPROVAL_PKG.Check_Manual_AWT_Segments'||'<-'
4316                              ||p_calling_sequence;
4317 
4318     OPEN c_manual_awt_dist_segs;
4319     LOOP
4320       FETCH c_manual_awt_dist_segs into l_manual_awt_dist_segs;
4321       EXIT WHEN c_manual_awt_dist_segs%NOTFOUND ;
4322         OPEN c_non_awt_dists_segs;
4323         LOOP
4324           FETCH c_non_awt_dists_segs into l_non_awt_dist_segs;
4325           EXIT  WHEN c_non_awt_dists_segs%NOTFOUND ;
4326 
4327             IF ( l_non_awt_dist_segs = l_manual_awt_dist_segs ) THEN
4328               p_dist_segs_hold_required := 'N' ;
4329               EXIT;
4330             ELSE
4331               p_dist_segs_hold_required := 'Y';
4332             END IF;
4333         END LOOP;
4334         CLOSE c_non_awt_dists_segs;
4335     END LOOP;
4336     CLOSE c_manual_awt_dist_segs;
4337 
4338     /*-----------------------------------------------------------------+
4339     |  Process Invoice Hold FUTURE PERIOD                              |
4340     +-----------------------------------------------------------------*/
4341 
4342     Process_Inv_Hold_Status(
4343         p_invoice_id,
4344         null,
4345         null,
4346         'AWT ACCT INVALID',
4347         p_dist_segs_hold_required,
4348         null,
4349         p_system_user,
4350         p_holds,
4351         p_holds_count,
4352         p_release_count,
4353         l_curr_calling_sequence);
4354 
4355 END Check_Manual_AWT_Segments;
4356 
4357 /*=============================================================================
4358  |  PROCEDURE GET_INV_MATCHED_STATUS
4359  |      Function given an invoice_id returns TRUE ifthe invoice has any matched
4360  |      distribution lines, otherwise FALSE
4361  |
4362  |  PARAMETERS
4363  |      p_invoice_id
4364  |      p_calling_sequence
4365  |
4366  |  KNOWN ISSUES:
4367  |
4368  |  NOTES:
4369  |
4370  |  MODIFICATION HISTORY
4371  |  Date         Author             Description of Change
4372  |
4373  *============================================================================*/
4374 
4375 FUNCTION Get_Inv_Matched_Status(
4376              p_invoice_id        IN            NUMBER,
4377              p_calling_sequence  IN            VARCHAR2) RETURN BOOLEAN
4378 IS
4379 
4380   l_matched_count          NUMBER;
4381   l_debug_loc              VARCHAR2(30) := 'Get_Inv_Matched_Status';
4382   l_curr_calling_sequence  VARCHAR2(2000);
4383   l_debug_info             VARCHAR2(1000);
4384 
4385 BEGIN
4386 
4387   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
4388                              p_calling_sequence;
4389 
4390   SELECT count(*)
4391   INTO   l_matched_count
4392   FROM   ap_invoice_distributions
4393   WHERE  invoice_id = p_invoice_id
4394   AND    po_distribution_id is not null
4395   AND    line_type_lookup_code in ( 'ITEM', 'ACCRUAL', 'IPV');
4396 
4397   IF (l_matched_count > 0) THEN
4398     return(TRUE);
4399   ELSE
4400     return(FALSE);
4401   END IF;
4402 
4403 EXCEPTION
4404   WHEN NO_DATA_FOUND THEN
4405     return(FALSE);
4406   WHEN OTHERS THEN
4407     IF (SQLCODE <> -20001) THEN
4408       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
4409       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
4410       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
4411       FND_MESSAGE.SET_TOKEN('PARAMETERS',
4412                   'Invoice_id  = '|| to_char(p_invoice_id));
4413     END IF;
4414     APP_EXCEPTION.RAISE_EXCEPTION;
4415 END Get_Inv_Matched_Status;
4416 
4417 
4418 /* ============================================================================
4419  | WITHHOLD_TAX_ON:
4420  |
4421  | Procedure that calls the withholding tax package on an invoice and checks
4422  | for any errors.  Depending on whether an error exists or not, a hold gets
4423  | placed or released.
4424  |
4425  | Parameters:
4426  |
4427  |    p_invoice_id             : Invoice Id
4428  |    p_gl_date_from_receipt   : GL Date From Receipt Flag system option
4429  |    p_last_updated_by        : Column Who Info
4430  |    p_last_update_login      : Column Who Info
4431  |    p_program_application_id : Column Who Info
4432  |    p_program_id             : Column Who Info
4433  |    p_request_id             : Column Who Info
4434  |    p_system_user            : Approval Program User Id
4435  |    p_holds                  : Hold Array
4436  |    p_holds_count            : Holds Count Array
4437  |    p_release_count          : Release Count Array
4438  |    p_calling_sequence       : Debugging string to indicate path of module
4439  |                               calls to be printed out upon error.
4440  |
4441  | Program Flow:
4442  | -------------
4443  |
4444  | Check if okay to call Withholding Routine
4445  |   invoice has at lease on distribution with a withholding tax group
4446  |   invoice has not already been withheld by the system
4447  |   invoice has no user non-releaseable holds (ther than AWT ERROR)
4448  |   invoice has no manual withholding lines
4449  | IF okay then call AP_DO_WITHHOLDING package on the invoice
4450  | Depending on whether withholding is successful or not, place or
4451  | or release the 'AWT ERROR' with the new error reason.
4452  | (If the invoice already has the hold we want to release the old one and
4453  |  replace the hold with the new error reason)
4454  |============================================================================ */
4455 
4456 PROCEDURE Withhold_Tax_On(
4457           p_invoice_id               IN NUMBER,
4458           p_gl_date_from_receipt     IN VARCHAR2,
4459           p_last_updated_by          IN NUMBER,
4460           p_last_update_login        IN NUMBER,
4461           p_program_application_id   IN NUMBER,
4462           p_program_id               IN NUMBER,
4463           p_request_id               IN NUMBER,
4464           p_system_user              IN NUMBER,
4465           p_holds                    IN OUT NOCOPY HOLDSARRAY,
4466           p_holds_count	             IN OUT NOCOPY COUNTARRAY,
4467           p_release_count            IN OUT NOCOPY COUNTARRAY,
4468           p_calling_sequence         IN VARCHAR2)
4469 IS
4470   l_ok_to_withhold	  	VARCHAR2(30);
4471   l_withholding_amount		NUMBER;
4472   l_withholding_date		DATE;
4473   l_invoice_num			VARCHAR2(50);
4474   l_return_string		VARCHAR2(2000);
4475   l_withhold_error_exists       VARCHAR2(1);
4476   l_debug_loc	 		VARCHAR2(30) := 'Withhold_Tax_On';
4477   l_curr_calling_sequence	VARCHAR2(2000);
4478   l_debug_info			VARCHAR2(1000);
4479   l_calling_sequence            VARCHAR2(20);
4480 BEGIN
4481 
4482   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||p_calling_sequence;
4483 
4484   l_withhold_error_exists := 'N';
4485 
4486   ----------------------------------------------------
4487   -- Execute Core Withholding Tax Calculation Routine
4488   ----------------------------------------------------
4489 
4490   IF (NOT Ap_Extended_Withholding_Pkg.Ap_Extended_Withholding_Active) THEN
4491      BEGIN
4492        ------------------------------------------------------------------------
4493        l_debug_info := 'Check if okay to call Withholding Routine - Core';
4494        ------------------------------------------------------------------------
4495        -- invoice has at least one distribution with a withholding tax group --
4496        -- invoice has not already been withheld by the system                --
4497        -- invoice has no user non-releaseable holds (ther than AWT ERROR)    --
4498        -- invoice has no manual withholding lines                            --
4499        ------------------------------------------------------------------------
4500        -- Perf bug 5058995
4501        -- Modify below SQL to go to base tables : AP_INVOICES_ALL and
4502        -- AP_INVOICE_DISTRIBUTIONS_ALL
4503        SELECT 'OK to call Withholding Routine',
4504               (AI.invoice_amount * NVL(AI.exchange_rate, 1)),
4505               AI.invoice_num
4506          INTO l_ok_to_withhold,
4507               l_withholding_amount,
4508               l_invoice_num
4509          FROM ap_invoices_all AI
4510         WHERE AI.invoice_id = p_invoice_id
4511           AND EXISTS (SELECT 'At least 1 dist has an AWT Group'
4512                        FROM  ap_invoice_distributions_all AID1
4513                        WHERE  AID1.invoice_id    = AI.invoice_id
4514                          AND  AID1.awt_group_id  IS NOT NULL)
4515           AND NOT EXISTS (SELECT 'Unreleased System holds exist'
4516                             FROM  ap_holds AH,
4517                                   ap_hold_codes AHC
4518                            WHERE  AH.invoice_id             = AI.invoice_id
4519                              AND  AH.release_lookup_code    IS NULL
4520                              AND  AH.hold_lookup_code       <> 'AWT ERROR'
4521                              AND  AH.hold_lookup_code       = AHC.hold_lookup_code
4522                              AND  AHC.user_releaseable_flag = 'N')
4523           AND NOT EXISTS (SELECT 'Manual AWT lines exist'
4524                            FROM  ap_invoice_distributions_all AID
4525                            WHERE  AID.invoice_id            = AI.invoice_id
4526                              AND  AID.line_type_lookup_code = 'AWT'
4527                              AND  AID.awt_flag              IN ('M', 'O'));
4528 
4529 /*       SELECT  MAX(accounting_date)
4530          INTO  l_withholding_date
4531          FROM  ap_invoice_distributions
4532         WHERE  invoice_id   = p_invoice_id
4533           AND  awt_group_id IS NOT NULL;   */
4534 /* 5886500 */
4535          SELECT  invoice_date
4536          INTO  l_withholding_date
4537          FROM  ap_invoices
4538          WHERE  invoice_id = p_invoice_id;
4539 
4540      EXCEPTION
4541         WHEN NO_DATA_FOUND THEN
4542            RETURN;
4543      END;
4544 
4545      --------------------------------------------------
4546      l_debug_info := 'Call the Withholding API - Core';
4547      --------------------------------------------------
4548 
4549      AP_WITHHOLDING_PKG.AP_DO_WITHHOLDING(
4550           p_invoice_id,
4551           l_withholding_date,
4552           'AUTOAPPROVAL',
4553           l_withholding_amount,
4554           NULL,
4555           NULL,
4556           p_last_updated_by,
4557           p_last_update_login,
4558           p_program_application_id,
4559           p_program_id,
4560           p_request_id,
4561           l_return_string);
4562   ELSE
4563 
4564     ---------------------------------------------------------
4565     -- Execute Extended Withholding Tax Calculation Routine
4566     ---------------------------------------------------------
4567 
4568     BEGIN
4569       ------------------------------------------------------------------------
4570       l_debug_info := 'Check if okay to call Withholding Routine - Extended';
4571       ------------------------------------------------------------------------
4572       -- invoice has at least one distribution with a withholding tax group --
4573       -- invoice has not already been withheld by the system                --
4574       -- invoice has no user non-releaseable holds (ther than AWT ERROR)    --
4575       -- invoice has no manual withholding lines                            --
4576       ------------------------------------------------------------------------
4577 
4578       -- Perf bug 5058995
4579       -- Modify below SQL to go to base tables : AP_INVOICES_ALL and
4580       -- AP_INVOICE_DISTRIBUTIONS_ALL
4581       SELECT 'OK to call Withholding Routine',
4582              (AI.invoice_amount * NVL(AI.exchange_rate,1)),
4583              AI.invoice_num
4584         INTO l_ok_to_withhold,
4585              l_withholding_amount,
4586              l_invoice_num
4587         FROM ap_invoices_all AI
4588        WHERE AI.invoice_id = p_invoice_id
4589          AND NOT EXISTS (SELECT 'Unreleased System holds exist'
4590                            FROM  ap_holds AH,
4591                                  ap_hold_codes AHC
4592                           WHERE  AH.invoice_id                = AI.invoice_id
4593                             AND  AH.release_lookup_code       IS NULL
4594                             AND  AH.hold_lookup_code          <> 'AWT ERROR'
4595                             AND  AH.hold_lookup_code          = AHC.hold_lookup_code
4596                             AND  AHC.user_releaseable_flag    = 'N')
4597          AND    NOT EXISTS (SELECT 'Manual AWT lines exist'
4598                               FROM  ap_invoice_distributions_all AID
4599                              WHERE  AID.invoice_id            = AI.invoice_id
4600                                AND  AID.line_type_lookup_code = 'AWT'
4601                                AND  AID.awt_flag              IN ('M', 'O'));
4602 
4603       SELECT  MAX(accounting_date)
4604         INTO  l_withholding_date
4605         FROM  ap_invoice_distributions
4606        WHERE  invoice_id = p_invoice_id;
4607 
4608     EXCEPTION
4609       WHEN NO_DATA_FOUND THEN
4610         RETURN;
4611     END;
4612 
4613     ------------------------------------------------------
4614     l_debug_info := 'Call the Withholding API - Extended';
4615     ------------------------------------------------------
4616 
4617     IF INSTR(p_calling_sequence, 'AP_CANCEL_PKG') > 0 THEN
4618         l_calling_sequence := 'INVOICE CANCEL';
4619     ELSE
4620         l_calling_sequence :=  'AUTOAPPROVAL';
4621     END IF;
4622 
4623     AP_WITHHOLDING_PKG.AP_DO_WITHHOLDING(
4624           p_invoice_id,
4625           l_withholding_date,
4626           l_calling_sequence,
4627           l_withholding_amount,
4628           NULL,
4629           NULL,
4630           p_last_updated_by,
4631           p_last_update_login,
4632           p_program_application_id,
4633           p_program_id,
4634           p_request_id,
4635           l_return_string);
4636 
4637   END IF;
4638 
4639   ----------------------------------------
4640   l_debug_info := 'Process Return String';
4641   ----------------------------------------
4642 
4643   IF (l_return_string <> 'SUCCESS') THEN
4644 
4645     l_withhold_error_exists := 'Y';
4646 
4647   END IF;
4648 
4649   -------------------------------------------------------------
4650   l_debug_info := 'Process Invoice Hold Status for AWT ERROR';
4651   -------------------------------------------------------------
4652 
4653   Process_Inv_Hold_Status(
4654           p_invoice_id,
4655           NULL,
4656           NULL,
4657           'AWT ERROR',
4658           l_withhold_error_exists,
4659           l_return_string,
4660           p_system_user,
4661           p_holds,
4662           p_holds_count,
4663           p_release_count,
4664           p_calling_sequence);
4665 
4666 EXCEPTION
4667   WHEN OTHERS THEN
4668     IF (SQLCODE <> -20001) THEN
4669       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
4670       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
4671       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
4672       FND_MESSAGE.SET_TOKEN('PARAMETERS',
4673                   'Invoice_id  = '|| to_char(p_invoice_id)
4674               ||', Dist_line_num = '|| p_gl_date_from_receipt
4675               ||', Packet_id = '|| p_last_updated_by
4676               ||', Fundscheck mode = '|| p_last_update_login
4677               ||', Dist_line_num = '|| to_char(p_program_application_id)
4678               ||', Dist_line_num = '|| to_char(p_program_id)
4679               ||', Dist_line_num = '|| to_char(p_request_id));
4680       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
4681     END IF;
4682     APP_EXCEPTION.RAISE_EXCEPTION;
4683 END Withhold_Tax_On;
4684 
4685 
4686 /*=============================================================================
4687  |  PROCEDURE UPDATE_INV_DISTS_TO_APPROVED
4688  |      Procedure that updates the invoice distribution match_status_flag to
4689  |      'A' if encumbered or has no postable holds or is a reversal line,
4690  |      otherwise if the invoice has postable holds then the match_status_flag
4691  |      remains a 'T'.
4692  |
4693  |  PARAMETERS
4694  |      p_invoice_id
4695  |      p_user_id
4696  |      p_calling_sequence
4697  |
4698  |  KNOWN ISSUES:
4699  |
4700  |  NOTES:
4701  |
4702  |  MODIFICATION HISTORY
4703  |  Date         Author             Description of Change
4704  |
4705  *============================================================================*/
4706 
4707 PROCEDURE Update_Inv_Dists_To_Approved(
4708               p_invoice_id       IN            NUMBER,
4709               p_user_id          IN            NUMBER,
4710               p_calling_sequence IN            VARCHAR2) IS
4711 
4712   l_debug_loc              VARCHAR2(30) := 'Update_Inv_Dists_To_Approved';
4713   l_curr_calling_sequence  VARCHAR2(2000);
4714   l_debug_info             VARCHAR2(1000);
4715 
4716   l_dbi_key_value_list1        ap_dbi_pkg.r_dbi_key_value_arr;
4717   l_dbi_key_value_list2        ap_dbi_pkg.r_dbi_key_value_arr;
4718 
4719 BEGIN
4720 
4721 
4722   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
4723                               p_calling_sequence;
4724 
4725   ------------------------------------------------------------
4726   l_debug_info := 'Set selected dists match_status_flag to tested';
4727   Print_Debug(l_debug_loc, l_debug_info);
4728   ------------------------------------------------------------
4729 
4730   UPDATE  ap_invoice_distributions D
4731   SET     match_status_flag = 'T',
4732           last_update_date = SYSDATE,
4733           last_updated_by = p_user_id,
4734           program_application_id = decode(fnd_global.prog_appl_id,
4735                                           -1,null,
4736                                           fnd_global.prog_appl_id),
4737           request_id = decode(fnd_global.conc_request_id,
4738                               -1,null, fnd_global.conc_request_id),
4739           program_id = decode(fnd_global.conc_program_id,
4740                               -1,null, fnd_global.conc_program_id),
4741           program_update_date = decode(fnd_global.conc_program_id,
4742                                        -1,null, SYSDATE)
4743   WHERE   match_status_flag = 'S'
4744   AND     D.invoice_id = p_invoice_id;
4745 
4746   --Bug6963908
4747   UPDATE  ap_self_assessed_tax_dist_all D
4748   SET     match_status_flag = 'T',
4749           last_update_date = SYSDATE,
4750           last_updated_by = p_user_id,
4751           program_application_id = decode(fnd_global.prog_appl_id,
4752                                           -1,null,
4753                                           fnd_global.prog_appl_id),
4754           request_id = decode(fnd_global.conc_request_id,
4755                               -1,null, fnd_global.conc_request_id),
4756           program_id = decode(fnd_global.conc_program_id,
4757                               -1,null, fnd_global.conc_program_id),
4758           program_update_date = decode(fnd_global.conc_program_id,
4759                                        -1,null, SYSDATE)
4760   WHERE   match_status_flag = 'S'
4761   AND     D.invoice_id = p_invoice_id;
4762   --Bug6963908
4763 
4764 
4765   AP_DBI_PKG.Maintain_DBI_Summary
4766               (p_table_name => 'AP_INVOICE_DISTRIBUTIONS',
4767                p_operation => 'U',
4768                p_key_value1 => p_invoice_id,
4769                p_key_value_list => l_dbi_key_value_list1,
4770                 p_calling_sequence => l_curr_calling_sequence);
4771 
4772   ------------------------------------------------------------
4773   l_debug_info := 'Set Tested dists to Approved if no unpostable holds';
4774   Print_Debug(l_debug_loc, l_debug_info);
4775   ------------------------------------------------------------
4776 
4777   -- BUG 4340061
4778   -- For the AWT lines we have encumbered_flag set to N in invoice-dist.
4779 
4780   UPDATE  ap_invoice_distributions D
4781   SET     match_status_flag = 'A',
4782           packet_id = ''
4783   WHERE   match_status_flag = 'T'
4784   AND     D.invoice_id = p_invoice_id
4785   AND     ((NOT EXISTS
4786                    (SELECT  invoice_id
4787                     FROM    ap_holds H, ap_hold_codes C
4788                     WHERE   H.invoice_id = D.invoice_id
4789                     AND     H.hold_lookup_code = C.hold_lookup_code
4790                     AND     ((H.release_lookup_code IS NULL) AND
4791                              ((C.postable_flag = 'N') OR
4792                               (C.postable_flag = 'X')))))
4793 	            OR (D.line_type_lookup_code<>'AWT' and
4794         	        (nvl(D.encumbered_flag, 'N') in ('Y','W','D','X','R','T')))
4795 	            OR (D.line_type_lookup_code='AWT' and
4796         	        (nvl(D.encumbered_flag, 'N') in ('Y','W','D','X','R'))));    -- BUG 4340061
4797 
4798 
4799   --Bug6963908
4800   UPDATE  ap_self_assessed_tax_dist_all D
4801   SET     match_status_flag = 'A',
4802           packet_id = ''
4803   WHERE   match_status_flag = 'T'
4804   AND     D.invoice_id = p_invoice_id
4805   AND     ((NOT EXISTS
4806                    (SELECT  invoice_id
4807                     FROM    ap_holds H, ap_hold_codes C
4808                     WHERE   H.invoice_id = D.invoice_id
4809                     AND     H.hold_lookup_code = C.hold_lookup_code
4810                     AND     ((H.release_lookup_code IS NULL) AND
4811                              ((C.postable_flag = 'N') OR
4812                               (C.postable_flag = 'X')))))
4813 	            OR (D.line_type_lookup_code<>'AWT' and
4814         	        (nvl(D.encumbered_flag, 'N') in ('Y','W','D','X','R','T')))
4815 	            OR (D.line_type_lookup_code='AWT' and
4816         	        (nvl(D.encumbered_flag, 'N') in ('Y','W','D','X','R'))));    -- BUG 4340061
4817   --Bug6963908
4818 
4819 EXCEPTION
4820   WHEN OTHERS THEN
4821     IF (SQLCODE <> -20001) THEN
4822       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
4823       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
4824       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
4825       FND_MESSAGE.SET_TOKEN('PARAMETERS',
4826                   'Invoice_id  = '|| to_char(p_invoice_id)
4827          || 'Run Option = ' || p_user_id);
4828       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
4829     END IF;
4830     APP_EXCEPTION.RAISE_EXCEPTION;
4831 END Update_Inv_Dists_To_Approved;
4832 
4833 --============================================================================
4834 -- HOLD Processing Routines
4835 --============================================================================
4836 
4837 /*=============================================================================
4838  |  PROCEDURE PROCESS_INV_HOLD_STATUS
4839  |      Procedure that process and invoice hold status. Determines whether to
4840  |      place or release a given  hold.
4841  |
4842  |  PARAMETERS
4843  |      p_invoice_id
4844  |      p_line_location_id:  Line Location Id
4845  |      p_rcv_tansaction_id: rcv transaction id it is matched to
4846  |      p_hold_lookup_code:  Hold Lookup Code
4847  |      p_should_have_hold:  ('Y' or 'N') to indicate whether the invoice
4848  |                           should have the hold (previous parameter)
4849  |      p_hold_reason:  AWT ERROR parameter.  The only hold whose hold reason
4850  |                      is  not static.
4851  |      p_system_user:  Approval Program User Id
4852  |      p_holds:  Holds Array
4853  |      p_holds_count:  Holds Count Array
4854  |      p_release_count:  Release Count Array
4855  |      p_calling_sequence: Debugging string to indicate path of module calls
4856  |                          to be printed out upon error.
4857  |
4858  |  PROGRAM FLOW:
4859  |      Retrieve current hold_status for current hold
4860  |      IF already_on_hold
4861  |       IF shoould_not_have_hold OR if p_hold_reason is different from the
4862  |          exists hold reason
4863  |        Release the hold
4864  |       ELSIF should_have_hold and hold_status <> Released By User
4865  |         IF p_hold_reason is null or existing_hold_reason id different from
4866  |           p_hold_reason
4867  |        Place the hold on the invoice
4868  |
4869  |  KNOWN ISSUES:
4870  |
4871  |  NOTES:
4872  |
4873  |  MODIFICATION HISTORY
4874  |  Date         Author             Description of Change
4875  |
4876  *============================================================================*/
4877 
4878 PROCEDURE Process_Inv_Hold_Status(
4879               p_invoice_id          IN            NUMBER,
4880               p_line_location_id    IN            NUMBER,
4881               p_rcv_transaction_id  IN            NUMBER,
4882               p_hold_lookup_code    IN            VARCHAR2,
4883               p_should_have_hold    IN            VARCHAR2,
4884               p_hold_reason         IN            VARCHAR2,
4885               p_system_user         IN            NUMBER,
4886               p_holds               IN OUT NOCOPY HOLDSARRAY,
4887               p_holds_count         IN OUT NOCOPY COUNTARRAY,
4888               p_release_count       IN OUT NOCOPY COUNTARRAY,
4889               p_calling_sequence    IN            VARCHAR2)IS
4890   l_inv_hold_status       VARCHAR2(20);
4891   l_existing_hold_reason  VARCHAR2(240);
4892   l_user_id               NUMBER;
4893   l_resp_id               NUMBER;
4894   l_debug_loc             VARCHAR2(30) := 'Process_Inv_Hold_Status';
4895   l_curr_calling_sequence VARCHAR2(2000);
4896   l_debug_info            VARCHAR2(1000);
4897 BEGIN
4898 
4899   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
4900                              p_calling_sequence;
4901 
4902        l_debug_info := 'p_hold_lookup_code,p_should_have_hold,p_hold_reason,p_system_user '||p_hold_lookup_code||','||p_should_have_hold||','||p_hold_reason||','||p_system_user;
4903         Print_Debug(l_debug_loc, l_debug_info);
4904 
4905 
4906   Get_Hold_Status(
4907       p_invoice_id,
4908       p_line_location_id,
4909       p_rcv_transaction_id,
4910       p_hold_lookup_code,
4911       p_system_user,
4912       l_inv_hold_status,
4913       l_existing_hold_reason,
4914       l_user_id,
4915       l_resp_id,
4916       l_curr_calling_sequence);
4917 
4918   IF (l_inv_hold_status = 'ALREADY ON HOLD') THEN
4919 
4920     IF (p_should_have_hold = 'N') OR ((p_hold_reason IS NOT NULL) AND
4921         (l_existing_hold_reason <> p_hold_reason)) THEN
4922 
4923       -------------------------------------------
4924       l_debug_info := 'Release hold if on hold and should not be on hold';
4925       Print_Debug(l_debug_loc, l_debug_info);
4926       -------------------------------------------
4927 
4928       IF ( check_hold_batch_releaseable(
4929              p_hold_lookup_code,
4930              p_calling_sequence) = 'Y' ) THEN
4931 
4932         Release_Hold(
4933             p_invoice_id,
4934             p_line_location_id,
4935             p_rcv_transaction_id,
4936             p_hold_lookup_code,
4937             p_holds,
4938             p_release_count,
4939             l_curr_calling_sequence);
4940       END IF;
4941     END IF;
4942 
4943   ELSIF ((p_should_have_hold = 'Y') AND
4944          ((l_inv_hold_status <> 'RELEASED BY USER') OR
4945           ((p_hold_lookup_code = 'INSUFFICIENT FUNDS') AND
4946            (l_inv_hold_status <> 'ALREADY ON HOLD')))) THEN
4947 
4948     -------------------------------------------
4949     l_debug_info := 'Set hold if it is not user released and needs hold';
4950     Print_Debug(l_debug_loc, l_debug_info);
4951     -------------------------------------------
4952 
4953     IF ((p_hold_reason IS NULL) OR
4954          (nvl(l_existing_hold_reason,'dummy') <> p_hold_reason)) THEN
4955       IF (p_hold_lookup_code = 'INSUFFICIENT FUNDS') THEN
4956 
4957         -------------------------------------------
4958         l_debug_info := 'Erase responsibility id from old insuff funds holds';
4959         Print_Debug(l_debug_loc, l_debug_info);
4960         -------------------------------------------
4961 
4962         UPDATE ap_holds
4963         SET    responsibility_id = NULL
4964         WHERE  invoice_id = p_invoice_id
4965         AND    hold_lookup_code = 'INSUFFICIENT FUNDS';
4966 
4967       END IF;
4968 
4969       -------------------------------------------
4970       l_debug_info := 'Set Hold';
4971       Print_Debug(l_debug_loc, l_debug_info);
4972       -------------------------------------------
4973 
4974       Set_Hold(
4975           p_invoice_id,
4976           p_line_location_id,
4977           p_rcv_transaction_id,
4978           p_hold_lookup_code,
4979           p_hold_reason,
4980           p_holds,
4981           p_holds_count,
4982           l_curr_calling_sequence);
4983 
4984     END IF; -- end of check p_hold_reason
4985   END IF; -- end of l_inv_hold_status
4986 
4987 EXCEPTION
4988   WHEN OTHERS THEN
4989     IF (SQLCODE <> -20001) THEN
4990       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
4991       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
4992       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
4993       FND_MESSAGE.SET_TOKEN('PARAMETERS',
4994                   'Invoice_id  = '|| to_char(p_invoice_id)
4995               ||', Line_Location_id = '|| to_char(p_line_location_id)
4996               ||', Hold_code = '|| p_hold_lookup_code
4997               ||', Hold_reason = '|| p_hold_reason
4998               ||', Should_have_hold = '|| p_should_have_hold);
4999       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
5000     END IF;
5001     APP_EXCEPTION.RAISE_EXCEPTION;
5002 END Process_Inv_Hold_Status;
5003 
5004 /*=============================================================================
5005  |  PROCEDURE GET_HOLD_STATUS
5006  |      Procedure to return the hold information and status of an invoice,
5007  |      whether it is ALREADY ON HOLD, RELEASED BY USER or NOT ON HOLD.
5008  |
5009  |  PARAMETERS
5010  |      p_invoice_id
5011  |      p_line_location_id:  Line Location Id
5012  |      p_rcv_transaction_id
5013  |      p_hold_lookup_code
5014  |      p_system_user
5015  |      p_status
5016  |      p_return_hold_reason
5017  |      p_user_id
5018  |      p_resp_id
5019  |      p_calling_sequence: Debugging string to indicate path of module calls
5020  |                          to be printed out upon error.
5021  |
5022  |  KNOWN ISSUES:
5023  |
5024  |  NOTES:
5025  |
5026  |  MODIFICATION HISTORY
5027  |  Date         Author             Description of Change
5028  |
5029  *============================================================================*/
5030 PROCEDURE Get_Hold_Status(p_invoice_id		IN NUMBER,
5031 			  p_line_location_id	IN NUMBER,
5032 			  p_rcv_transaction_id  IN NUMBER,
5033 			  p_hold_lookup_code	IN VARCHAR2,
5034 			  p_system_user		IN NUMBER,
5035 			  p_status		IN OUT NOCOPY VARCHAR2,
5036 			  p_return_hold_reason  IN OUT NOCOPY VARCHAR2,
5037 			  p_user_id     	IN OUT NOCOPY VARCHAR2,
5038 			  p_resp_id		IN OUT NOCOPY VARCHAR2,
5039 			  p_calling_sequence  	IN VARCHAR2) IS
5040 
5041   l_debug_loc	 		VARCHAR2(30) := 'Get_Hold_Status';
5042   l_curr_calling_sequence	VARCHAR2(2000);
5043 
5044 BEGIN
5045 
5046   -- Update the calling sequence --
5047 
5048   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||p_calling_sequence;
5049 
5050   p_status := 'NOT ON HOLD';
5051 
5052   if g_holds_tab.count > 0 then
5053 
5054      for i in g_holds_tab.first..g_holds_tab.last
5055      loop
5056         if (p_hold_lookup_code <> 'INSUFFICIENT FUNDS') then
5057 
5058 	    if (g_holds_tab(i).invoice_id = p_invoice_id and
5059 	        g_holds_tab(i).hold_lookup_code = p_hold_lookup_code) then
5060 
5061 	        if (p_line_location_id is null
5062 	            or g_holds_tab(i).line_location_id = p_line_location_id) and
5063 	           (p_rcv_transaction_id is null
5064 	            or g_holds_tab(i).rcv_transaction_id = p_rcv_transaction_id) and
5065 	           (g_holds_tab(i).release_lookup_code is null
5066 	            or (g_holds_tab(i).release_lookup_code is not null
5067 	                and g_holds_tab(i).last_updated_by <> p_system_user)) then
5068 
5069                    p_status		:= g_holds_tab(i).hold_status;
5070                    p_return_hold_reason := g_holds_tab(i).hold_reason;
5071                    p_user_id            := g_holds_tab(i).last_updated_by;
5072                    p_resp_id            := g_holds_tab(i).responsibility_id;
5073 
5074                 end if;
5075 	    end if;
5076 	else
5077 	    if (g_holds_tab(i).invoice_id = p_invoice_id and
5078 	        g_holds_tab(i).hold_lookup_code = p_hold_lookup_code) then
5079 
5080 	        if (p_line_location_id is null
5081 	            or g_holds_tab(i).line_location_id = p_line_location_id) and
5082 	           (g_holds_tab(i).release_lookup_code is null
5083 	            or (g_holds_tab(i).release_lookup_code is not null
5084 	                and g_holds_tab(i).last_updated_by <> p_system_user
5085 	                and g_holds_tab(i).responsibility_id is not null)) then
5086 
5087                    p_status		:= g_holds_tab(i).hold_status;
5088                    p_return_hold_reason := g_holds_tab(i).hold_reason;
5089                    p_user_id            := g_holds_tab(i).last_updated_by;
5090                    p_resp_id            := g_holds_tab(i).responsibility_id;
5091 
5092                 end if;
5093 	    end if;
5094         end if;
5095      end loop;
5096   end if;
5097 
5098 EXCEPTION
5099   WHEN OTHERS THEN
5100     IF (SQLCODE <> -20001) THEN
5101       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
5102       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
5103       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
5104       FND_MESSAGE.SET_TOKEN('PARAMETERS',
5105                   'Invoice_id  = '|| to_char(p_invoice_id)
5106               ||', Line Location Id = '|| to_char(p_line_location_id)
5107               ||', System_User_id = '|| to_char(p_system_user)
5108               ||', Hold Code = '|| p_hold_lookup_code);
5109     END IF;
5110     APP_EXCEPTION.RAISE_EXCEPTION;
5111 END Get_Hold_Status;
5112 
5113 
5114 /*=============================================================================
5115  |  PROCEDURE RELEASE_HOLD
5116  |      Procedure to release a hold from an invoice and update the release
5117  |      count array.
5118  |
5119  |  PARAMETERS
5120  |      p_invoice_id
5121  |      p_line_location_id:  Line Location Id
5122  |      p_rcv_transaction_id
5123  |      p_hold_lookup_code
5124  |      p_holds
5125  |      p_release_count
5126  |      p_calling_sequence: Debugging string to indicate path of module calls
5127  |                          to be printed out upon error.
5128  |
5129  |  KNOWN ISSUES:
5130  |
5131  |  NOTES:
5132  |
5133  |  MODIFICATION HISTORY
5134  |  Date         Author             Description of Change
5135  |
5136  *============================================================================*/
5137 
5138 PROCEDURE Release_Hold(
5139               p_invoice_id          IN            NUMBER,
5140               p_line_location_id    IN            NUMBER,
5141               p_rcv_transaction_id  IN            NUMBER,
5142               p_hold_lookup_code    IN            VARCHAR2,
5143               p_holds               IN OUT NOCOPY HOLDSARRAY,
5144               p_release_count       IN OUT NOCOPY COUNTARRAY,
5145               p_calling_sequence    IN            VARCHAR2) IS
5146   l_release_lookup_code    VARCHAR2(30);
5147   l_debug_loc              VARCHAR2(30) := 'Release_Hold';
5148   l_curr_calling_sequence  VARCHAR2(2000);
5149   l_debug_info             VARCHAR2(1000);
5150 BEGIN
5151 
5152   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
5153                              p_calling_sequence;
5154 
5155   -------------------------------------------
5156   l_debug_info := 'Getting Release Info For Hold';
5157   Print_Debug(l_debug_loc, l_debug_info);
5158   -------------------------------------------
5159 
5160   Get_Release_Lookup_For_Hold(
5161       p_hold_lookup_code,
5162       l_release_lookup_code,
5163       l_curr_calling_sequence);
5164 
5165   -------------------------------------------
5166   l_debug_info := 'Updating AP_HOLDS with release info';
5167   Print_Debug(l_debug_loc, l_debug_info);
5168   -------------------------------------------
5169 
5170   UPDATE ap_holds
5171   SET    release_lookup_code = l_release_lookup_code,
5172          release_reason = (SELECT description
5173                              FROM   ap_lookup_codes
5174                              WHERE  lookup_code = l_release_lookup_code
5175                                AND    lookup_type = 'HOLD CODE'),
5176          last_update_date = sysdate,
5177          last_updated_by = 5,
5178          status_flag = 'R'
5179   WHERE invoice_id = p_invoice_id
5180   AND   nvl(line_location_id, -1) = nvl(p_line_location_id, -1)
5181   AND   nvl(rcv_transaction_id, -1) = nvl(rcv_transaction_id, -1)
5182   AND   hold_lookup_code = p_hold_lookup_code
5183   AND   nvl(status_flag, 'x') <> 'x';
5184 
5185   -------------------------------------------
5186   l_debug_info := 'Adjust the Release Count';
5187   Print_Debug(l_debug_loc, l_debug_info);
5188   -------------------------------------------
5189 
5190   IF (sql%rowcount >0) THEN
5191       Count_Org_Hold(
5192 		 p_org_id	   => g_org_id
5193 		,p_hold_lookup_code => p_hold_lookup_code
5194 		,p_place_or_release => 'R'
5195 		,p_calling_sequence => l_curr_calling_sequence);
5196 
5197   END IF;
5198 
5199   -------------------------------------------
5200   l_debug_info := 'Sync Invoice Holds Cache';
5201   Print_Debug(l_debug_loc, l_debug_info);
5202   -------------------------------------------
5203 
5204   initialize_invoice_holds
5205 		(p_invoice_id       => p_invoice_id,
5206 		 p_calling_sequence => l_curr_calling_sequence);
5207 
5208   AP_DBI_PKG.Maintain_DBI_Summary
5209               (p_table_name => 'AP_HOLDS',
5210                p_operation => 'U',
5211                p_key_value1 => p_invoice_id,
5212                 p_calling_sequence => l_curr_calling_sequence);
5213 
5214 EXCEPTION
5215   WHEN OTHERS THEN
5216     IF (SQLCODE <> -20001) THEN
5217       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
5218       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
5219       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
5220       FND_MESSAGE.SET_TOKEN('PARAMETERS',
5221                   'Invoice_id  = '|| to_char(p_invoice_id)
5222               ||', Hold_Code = '|| p_hold_lookup_code
5223               ||', Line Location Id = '|| (p_line_location_id));
5224       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
5225     END IF;
5226     APP_EXCEPTION.RAISE_EXCEPTION;
5227 END Release_Hold;
5228 
5229 /*=============================================================================
5230  |  PROCEDURE SET_HOLD
5231  |      Procedure to Set an Invoice on Hold and update the hold count array.
5232  |
5233  |  PARAMETERS
5234  |      p_invoice_id
5235  |      p_line_location_id:  Line Location Id
5236  |      p_rcv_transaction_id
5237  |      p_hold_lookup_code
5238  |      p_hold_reason
5239  |      p_holds
5240  |      p_hold_count
5241  |      p_calling_sequence: Debugging string to indicate path of module calls
5242  |                          to be printed out upon error.
5243  |
5244  |  KNOWN ISSUES:
5245  |
5246  |  NOTES:
5247  |
5248  |  MODIFICATION HISTORY
5249  |  Date         Author             Description of Change
5250  |
5251  *============================================================================*/
5252 
5253 PROCEDURE Set_Hold(
5254               p_invoice_id          IN            NUMBER,
5255               p_line_location_id    IN            NUMBER,
5256               p_rcv_transaction_id  IN            NUMBER,
5257               p_hold_lookup_code    IN            VARCHAR2,
5258               p_hold_reason         IN            VARCHAR2,
5259               p_holds               IN OUT NOCOPY HOLDSARRAY,
5260               p_holds_count         IN OUT NOCOPY COUNTARRAY,
5261               p_calling_sequence    IN            VARCHAR2) IS
5262   l_debug_loc              VARCHAR2(30) := 'Set_Hold';
5263   l_curr_calling_sequence  VARCHAR2(2000);
5264   l_debug_info             VARCHAR2(1000);
5265   l_hold_id                NUMBER(15);
5266   l_user_releaseable_flag  VARCHAR2(1);
5267   l_initiate_workflow_flag VARCHAR2(1);
5268 
5269 BEGIN
5270 
5271   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
5272                              p_calling_sequence;
5273 
5274   -------------------------------------------
5275   l_debug_info := 'Inserting Into AP_HOLDS';
5276   Print_Debug(l_debug_loc, l_debug_info);
5277   -------------------------------------------
5278 
5279   SELECT ap_holds_s.nextval
5280   INTO   l_hold_id
5281   FROM   DUAL;
5282 
5283   INSERT INTO ap_holds (
5284                   invoice_id,
5285                   line_location_id,
5286                   rcv_transaction_id,
5287                   hold_lookup_code,
5288                   last_update_date,
5289                   last_updated_by,
5290                   creation_date,
5291                   created_by,
5292                   held_by,
5293                   hold_date,
5294                   hold_reason,
5295                   status_flag,
5296 		  org_id,  /* Bug 3700128. MOAC Project */
5297                   hold_id) -- added for Negotiation Project
5298     (SELECT p_invoice_id,
5299             p_line_location_id,
5300             p_rcv_transaction_id,
5301             p_hold_lookup_code,
5302             sysdate,
5303             5,
5304             sysdate,
5305             5,
5306             5,
5307             sysdate,
5308             substrb(nvl(p_hold_reason, description),1,240),
5309             'S',
5310 	    g_org_id, /* Bug 3700128. MOAC Project */
5311             l_hold_id -- Added for Negotiation.
5312      FROM   ap_lookup_codes
5313      WHERE  lookup_code = p_hold_lookup_code
5314      AND    lookup_type = 'HOLD CODE');
5315 
5316   --
5317   -- Added for Negotiation Workflow
5318   -- The Holds workflow will be initiated if the placed hold is a system
5319   -- placed user releaseable hold.
5320   -- Check if the hold placed is a user releaseable hold
5321   --
5322 
5323   -------------------------------------------
5324   l_debug_info := 'Select to see if the hold is user releaseable hold';
5325   Print_Debug(l_debug_loc, l_debug_info);
5326   -------------------------------------------
5327 
5328   SELECT user_releaseable_flag,
5329          initiate_workflow_flag
5330   INTO   l_user_releaseable_flag,
5331          l_initiate_workflow_flag
5332   FROM   ap_hold_codes
5333   WHERE  hold_lookup_code = p_hold_lookup_code;
5334 
5335   --
5336   -- If the hold is a user releaseable hold then we will start the
5337   -- holds workflow.
5338   --
5339 
5340   IF (l_user_releaseable_flag = 'Y' AND
5341      l_initiate_workflow_flag = 'Y') THEN
5342 
5343      -------------------------------------------
5344      l_debug_info := 'Start the Holds Workflow';
5345      Print_Debug(l_debug_loc, l_debug_info);
5346      -------------------------------------------
5347 
5348      AP_WORKFLOW_PKG.create_hold_wf_process(l_hold_id);
5349 
5350      -------------------------------------------
5351      l_debug_info := 'Started the Holds Workflow';
5352      Print_Debug(l_debug_loc, l_debug_info);
5353      -------------------------------------------
5354 
5355   END IF;
5356 
5357   AP_DBI_PKG.Maintain_DBI_Summary
5358               (p_table_name => 'AP_HOLDS',
5359                p_operation => 'I',
5360                p_key_value1 => p_invoice_id,
5361                 p_calling_sequence => l_curr_calling_sequence);
5362 
5363   -------------------------------------------
5364   l_debug_info := 'Adjust the Holds Count';
5365   Print_Debug(l_debug_loc, l_debug_info);
5366   -------------------------------------------
5367   Count_Org_Hold(
5368          p_org_id           => g_org_id
5369         ,p_hold_lookup_code => p_hold_lookup_code
5370         ,p_place_or_release => 'P'
5371         ,p_calling_sequence => l_curr_calling_sequence);
5372 
5373   -------------------------------------------
5374   l_debug_info := 'Sync Invoice Holds Cache';
5375   Print_Debug(l_debug_loc, l_debug_info);
5376   -------------------------------------------
5377   initialize_invoice_holds
5378 		(p_invoice_id       => p_invoice_id,
5379 		 p_calling_sequence => l_curr_calling_sequence);
5380 
5381 
5382 EXCEPTION
5383   WHEN OTHERS THEN
5384     IF (SQLCODE <> -20001) THEN
5385       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
5386       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
5387       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
5388       FND_MESSAGE.SET_TOKEN('PARAMETERS',
5389                   'Invoice_id  = '|| to_char(p_invoice_id)
5390               ||', Hold_Code = '|| p_hold_lookup_code
5391               ||', Hold_Reason = '|| p_hold_reason);
5392       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
5393     END IF;
5394     APP_EXCEPTION.RAISE_EXCEPTION;
5395 END Set_Hold;
5396 
5397 /*=============================================================================
5398  |  PROCEDURE COUNT_HOLD
5399  |      Procedure given the hold_array and count_array, increments the
5400  |      count for a given hold
5401  |
5402  |  PARAMETERS
5403  |      p_hold_lookup_code
5404  |      p_holds
5405  |      p_count
5406  |      p_calling_sequence: Debugging string to indicate path of module calls
5407  |                          to be printed out upon error.
5408  |
5409  |  KNOWN ISSUES:
5410  |
5411  |  NOTES:
5412  |
5413  |  MODIFICATION HISTORY
5414  |  Date         Author             Description of Change
5415  |
5416  *============================================================================*/
5417 
5418 PROCEDURE Count_Hold(
5419               p_hold_lookup_code    IN            VARCHAR2,
5420               p_holds               IN OUT NOCOPY HOLDSARRAY,
5421               p_count               IN OUT NOCOPY COUNTARRAY,
5422               p_calling_sequence    IN            VARCHAR2) IS
5423   l_num                         NUMBER;
5424   l_debug_loc                   VARCHAR2(30) := 'Count_Hold';
5425   l_curr_calling_sequence       VARCHAR2(2000);
5426   l_debug_info                  VARCHAR2(1000);
5427 BEGIN
5428 
5429   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
5430                               p_calling_sequence;
5431 
5432   FOR num IN 1..100 LOOP
5433 
5434     IF ((p_holds(num) IS NULL) OR (p_holds(num) = p_hold_lookup_code)) THEN
5435 
5436       l_num := to_number(num);
5437 
5438       EXIT;
5439     END IF;
5440 
5441   END LOOP;
5442 
5443   p_holds(l_num) := p_hold_lookup_code;
5444   p_count(l_num) := nvl(p_count(l_num), 0) + 1;
5445 
5446 EXCEPTION
5447   WHEN OTHERS THEN
5448     IF (SQLCODE <> -20001) THEN
5449       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
5450       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
5451       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
5452       FND_MESSAGE.SET_TOKEN('PARAMETERS',
5453                   'Hold Code  = '|| p_hold_lookup_code);
5454       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
5455     END IF;
5456     APP_EXCEPTION.RAISE_EXCEPTION;
5457 END Count_Hold;
5458 
5459 
5460 /*=============================================================================
5461  |  PROCEDURE GET_RELEASE_LOOKUP_FOR_HOLD
5462  |      Procedure given a hold_lookup_code retunrs the associated
5463  |      return_lookup_code
5464  |
5465  |  PARAMETERS
5466  |      p_hold_lookup_code
5467  |      p_release_lookup_code
5468  |      p_calling_sequence: Debugging string to indicate path of module calls
5469  |                          to be printed out upon error.
5470  |
5471  |  KNOWN ISSUES:
5472  |
5473  |  NOTES:
5474  |
5475  |  MODIFICATION HISTORY
5476  |  Date         Author             Description of Change
5477  |
5478  *============================================================================*/
5479 
5480 PROCEDURE Get_Release_Lookup_For_Hold(
5481               p_hold_lookup_code       IN            VARCHAR2,
5482               p_release_lookup_code    IN OUT NOCOPY VARCHAR2,
5483               p_calling_sequence       IN            VARCHAR2) IS
5484 
5485   l_debug_loc              VARCHAR2(30) := 'Get_Release_Lookup_For_Hold';
5486   l_curr_calling_sequence  VARCHAR2(2000);
5487   l_debug_info             VARCHAR2(1000);
5488   invalid_hold             EXCEPTION;
5489 BEGIN
5490 
5491   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
5492                              p_calling_sequence;
5493 
5494   -------------------------------------------
5495   l_debug_info := 'Check hold_code to retrieve release code';
5496   Print_Debug(l_debug_loc, l_debug_info);
5497   -------------------------------------------
5498 
5499 
5500 --added the lookup code MILESTONE in the if statement to
5501 --release the MILESTONE hold when PO quantity or amount
5502 --matched properly and invoice validated or when HOLD released manually
5503 --as per bug6768401
5504 
5505 
5506   IF (p_hold_lookup_code in ('CANT CLOSE PO', 'CANT TRY PO CLOSE',
5507            'PO REQUIRED', 'QTY ORD', 'QTY REC',
5508 	   'AMT ORD','AMT REC',
5509            'PRICE', 'QUALITY', 'CURRENCY DIFFERENCE',
5510            'TAX DIFFERENCE', 'REC EXCEPTION',
5511            'PO NOT APPROVED', 'MAX QTY ORD',
5512            'MAX QTY REC', 'MAX AMT ORD',
5513 	   'MAX AMT REC','FINAL MATCHING',
5514            'MAX SHIP AMOUNT', 'MAX RATE AMOUNT',
5515            'MAX TOTAL AMOUNT','MILESTONE')) THEN
5516 
5517     p_release_lookup_code := 'MATCHED';
5518 
5519   ELSIF (p_hold_lookup_code = 'CANT FUNDS CHECK') THEN
5520 
5521     p_release_lookup_code := 'CAN FUNDS CHECK';
5522 
5523   ELSIF (p_hold_lookup_code = 'INSUFFICIENT FUNDS') THEN
5524 
5525     p_release_lookup_code := 'FUNDS NOW AVAILABLE';
5526 
5527   ELSIF (p_hold_lookup_code = 'AWT ERROR') THEN
5528 
5529     p_release_lookup_code := 'AWT OK';
5530 
5531   ELSIF (p_hold_lookup_code in ('TAX VARIANCE', 'DIST VARIANCE',
5532         'TAX AMOUNT RANGE', 'LINE VARIANCE')) THEN
5533 
5534     p_release_lookup_code := 'VARIANCE CORRECTED';
5535 
5536   ELSIF (p_hold_lookup_code = 'NATURAL ACCOUNT TAX') THEN
5537 
5538     p_release_lookup_code := 'NATURAL ACCOUNT TAX OK';
5539 
5540   ELSIF (p_hold_lookup_code = 'NO RATE') THEN
5541 
5542     p_release_lookup_code := 'RATE EXISTS';
5543 
5544   ELSIF (p_hold_lookup_code = 'FUTURE PERIOD') THEN
5545 
5546     p_release_lookup_code := 'FUTURE OPEN';
5547 
5548   ELSIF (p_hold_lookup_code = 'DIST ACCT INVALID') THEN
5549 
5550     p_release_lookup_code := 'DIST ACCT VALID';
5551 
5552   ELSIF (p_hold_lookup_code = 'ERV ACCT INVALID') THEN
5553 
5554     p_release_lookup_code := 'ERV ACCT VALID';
5555 
5556   ELSIF (p_hold_lookup_code = 'AWT ACCT INVALID') THEN
5557 
5558     p_release_lookup_code := 'AWT ACCT VALID';
5559 
5560   ELSIF (p_hold_lookup_code in ('AMOUNT','PREPAID AMOUNT')) THEN
5561 
5562     p_release_lookup_code := 'AMOUNT LOWERED';
5563 
5564   ELSIF (p_hold_lookup_code = 'VENDOR') THEN
5565 
5566     p_release_lookup_code := 'VENDOR UPDATED';
5567 
5568   ELSIF (p_hold_lookup_code = 'PROJECT GL DATE CLOSED') THEN
5569 
5570     p_release_lookup_code := 'PROJECT GL DATE OPENED';
5571 
5572   ELSIF (p_hold_lookup_code in ( 'INSUFFICIENT LINE INFO',
5573                                  'INVALID DEFAULT ACCOUNT',
5574                                  'DISTRIBUTION SET INACTIVE',
5575                                  'SKELETON DISTRIBUTION SET',
5576                                  'CANNOT OVERLAY ACCOUNT',
5577                                  'CANNOT EXECUTE ALLOCATION' ) ) THEN
5578     p_release_lookup_code := 'APPROVED';
5579 
5580   -- 7299826 EnC Project
5581   ELSIF (p_hold_lookup_code IN  ('Pay When Paid', 'PO Deliverable')) THEN
5582 
5583        p_release_lookup_code := 'Automatic Release';
5584 
5585   ELSE
5586     -------------------------------------------
5587     l_debug_info := 'Invalid Hold Code';
5588     Print_Debug(l_debug_loc, l_debug_info);
5589     -------------------------------------------
5590 
5591     Raise Invalid_Hold;
5592   END IF;
5593 
5594 EXCEPTION
5595   WHEN Invalid_Hold THEN
5596       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
5597       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
5598       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
5599       FND_MESSAGE.SET_TOKEN('PARAMETERS',
5600                   'Hold Code  = '|| p_hold_lookup_code
5601               ||', Release Code = '|| p_release_lookup_code);
5602       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
5603     APP_EXCEPTION.RAISE_EXCEPTION;
5604   WHEN OTHERS THEN
5605     IF (SQLCODE <> -20001) THEN
5606       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
5607       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
5608       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
5609       FND_MESSAGE.SET_TOKEN('PARAMETERS',
5610                   'Hold Code  = '|| p_hold_lookup_code
5611               ||', Release Code = '|| p_release_lookup_code);
5612       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
5613     END IF;
5614     APP_EXCEPTION.RAISE_EXCEPTION;
5615 END Get_Release_Lookup_For_Hold;
5616 
5617 
5618 /*=============================================================================
5619  |  PROCEDURE GET_INVOICE_STATUSES:
5620  |      Procedure given a hold_lookup_code retunrs the associated
5621  |      return_lookup_code
5622  |
5623  |  PARAMETERS
5624  |      p_invoice_id
5625  |      p_holds_count
5626  |      p_approval_status
5627  |      p_calling_sequence: Debugging string to indicate path of module calls
5628  |                          to be printed out upon error.
5629  |
5630  |  KNOWN ISSUES:
5631  |
5632  |  NOTES:
5633  |
5634  |  MODIFICATION HISTORY
5635  |  Date         Author             Description of Change
5636  |
5637  *============================================================================*/
5638 
5639 PROCEDURE Get_Invoice_Statuses(
5640               p_invoice_id       IN            NUMBER,
5641               p_holds_count      IN OUT NOCOPY NUMBER,
5642               p_approval_status  IN OUT NOCOPY VARCHAR2,
5643               p_calling_sequence IN            VARCHAR2) IS
5644 
5645   CURSOR Invoice_Status_Cur IS
5646     SELECT  AP_INVOICES_PKG.Get_Holds_Count(invoice_id),
5647             AP_INVOICES_PKG.Get_Approval_Status(
5648                 invoice_id,
5649                 invoice_amount,
5650                 payment_status_flag,
5651                 invoice_type_lookup_code)
5652     FROM    ap_invoices
5653     WHERE   invoice_id = p_invoice_id;
5654 
5655   l_debug_loc              VARCHAR2(30) := 'Get_Invoice_Statuses';
5656   l_curr_calling_sequence  VARCHAR2(2000);
5657   l_debug_info             VARCHAR2(1000);
5658 BEGIN
5659 
5660   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||
5661                              p_calling_sequence;
5662 
5663   -------------------------------------------
5664   l_debug_info := 'Retrieving new invoice statuses';
5665   Print_Debug(l_debug_loc, l_debug_info);
5666   -------------------------------------------
5667 
5668   OPEN Invoice_Status_Cur;
5669   Fetch Invoice_Status_Cur
5670    INTO p_holds_count,
5671         p_approval_status;
5672 
5673   CLOSE Invoice_Status_Cur;
5674 
5675 EXCEPTION
5676   WHEN OTHERS THEN
5677     IF (SQLCODE <> -20001) THEN
5678       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
5679       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
5680       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
5681       FND_MESSAGE.SET_TOKEN('PARAMETERS',
5682                   'Hold Code  = '|| to_char(p_invoice_id));
5683       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
5684     END IF;
5685     APP_EXCEPTION.RAISE_EXCEPTION;
5686 END Get_Invoice_Statuses;
5687 
5688 
5689 /*=============================================================================
5690  |  PROCEDURE Check_hold_batch_releaseable
5691  |      Function that returns if the hold batch is releasable.
5692  |
5693  |  PARAMETERS
5694  |      p_hold_name
5695  |      p_calling_sequence: Debugging string to indicate path of module calls
5696  |                          to be printed out upon error.
5697  |
5698  |  KNOWN ISSUES:
5699  |
5700  |  NOTES:
5701  |
5702  |  MODIFICATION HISTORY
5703  |  Date         Author             Description of Change
5704  |
5705  *============================================================================*/
5706 
5707 FUNCTION Check_hold_batch_releaseable(
5708              p_hold_name        IN            VARCHAR2,
5709              p_calling_sequence IN            VARCHAR2) RETURN VARCHAR2
5710 IS
5711 
5712   l_curr_calling_sequence         VARCHAR2(2000);
5713 
5714 BEGIN
5715 
5716   IF ( p_hold_name = 'VENDOR' and
5717        p_calling_sequence like '%APXAPRVL%' ) THEN
5718     RETURN 'N';
5719   ELSE
5720     RETURN 'Y';
5721   END IF;
5722 
5723 END Check_hold_batch_releaseable;
5724 
5725 PROCEDURE Update_Total_Dist_Amount(
5726               p_invoice_id             IN            NUMBER,
5727               p_calling_sequence       IN            VARCHAR2) IS
5728 
5729   l_debug_info             VARCHAR2(1000);
5730   l_curr_calling_sequence  VARCHAR2(2000);
5731   l_debug_loc              VARCHAR2(30) := 'Update_Total_Dist_Amount';
5732 
5733 BEGIN
5734 
5735   -------------------------------------------
5736   l_debug_info := 'Update Total Dist Amount';
5737   Print_Debug(l_debug_loc, l_debug_info);
5738   -------------------------------------------
5739 
5740   -- Fix for Bug #5107865.  Replaced bulk update with single update for
5741   -- performance reasons.
5742   UPDATE ap_invoice_distributions_all id1
5743      SET (id1.total_dist_amount,
5744           id1.total_dist_base_amount) = (SELECT SUM(NVL(id2.amount,0)),
5745                                                  SUM(NVL(id2.base_amount,0))
5746                                           FROM  ap_invoice_distributions_all id2
5747                                           WHERE id2.invoice_distribution_id =
5748                                                 id1.invoice_distribution_id
5749                                              OR id2.related_id =
5750                                                 id1.invoice_distribution_id)
5751    WHERE id1.invoice_id = p_invoice_id
5752      AND id1.line_type_lookup_code NOT IN ('IPV','ERV','TIPV','TRV','TERV');
5753 
5754 EXCEPTION
5755   WHEN OTHERS THEN
5756     NULL;
5757 
5758 END Update_Total_Dist_Amount;
5759 
5760 
5761 PROCEDURE Exclude_Tax_Freight_From_Disc(
5762 			p_invoice_id IN NUMBER,
5763                         p_exclude_tax_from_discount IN VARCHAR2,
5764 			p_exclude_freight_from_disc IN VARCHAR2,
5765                         p_invoice_type_lookup_code IN VARCHAR2,
5766                        p_curr_calling_sequence IN VARCHAR2) IS
5767 
5768   l_debug_loc                   VARCHAR2(100);
5769   l_curr_calling_sequence       VARCHAR2(2000);
5770   l_debug_info                  VARCHAR2(1000);
5771   l_purpose                     VARCHAR2(30);
5772   l_payment_status              VARCHAR2(1);
5773   l_prepayment_app_exists       VARCHAR2(1);
5774   l_discountable_amount         NUMBER;
5775   l_total_tax_amount		NUMBER;
5776   l_total_freight_amount	NUMBER;
5777   l_validated_amount            NUMBER;
5778   l_terms_id                    NUMBER;
5779   l_last_updated_by             NUMBER;
5780   l_created_by                  NUMBER;
5781   l_payment_priority            NUMBER;
5782   l_batch_id                    NUMBER;
5783   l_terms_date                  DATE;
5784   l_invoice_amount              NUMBER;
5785   l_pay_curr_invoice_amount     NUMBER;
5786   l_payment_cross_rate          NUMBER;
5787   l_payment_method              VARCHAR2(30);
5788   l_invoice_curr_code           VARCHAR2(15);
5789   l_pay_curr_code               VARCHAR2(15);
5790   l_new_amount_to_adjust        NUMBER;
5791   l_new_discountable_amount     NUMBER;
5792   l_total_amount_positive       VARCHAR(1);
5793   l_total_amount                NUMBER ;
5794   l_records_exist               BOOLEAN;
5795   j                             NUMBER;
5796   l_invoice_date                DATE;
5797   l_tmp_invoice_amount          NUMBER;
5798   l_tmp_base_amount             NUMBER;
5799 
5800   CURSOR Prepay_Distributions IS
5801   SELECT aid.invoice_id invoice_id,
5802          aid.amount*-1 amount,
5803          l_pay_curr_code pay_currency,
5804          aid.last_updated_by user_id,
5805          aid.last_update_login last_update_login,
5806          l_curr_calling_sequence calling_sequence
5807   FROM   ap_invoice_distributions  aid,
5808          ap_invoice_lines ail
5809   WHERE  aid.invoice_id = p_invoice_id
5810   AND    ail.invoice_id = aid.invoice_id
5811   AND    ail.line_number = aid.invoice_line_number
5812   --bugfix:5609186
5813   AND    ail.line_type_lookup_code = 'PREPAY'
5814   AND    aid.amount <> 0
5815   AND    (aid.line_type_lookup_code = 'PREPAY'
5816           OR aid.charge_applicable_to_dist_id in
5817             (SELECT invoice_distribution_id
5818              FROM ap_invoice_distributions
5819              WHERE line_type_lookup_code = 'PREPAY'
5820              AND invoice_id = p_invoice_id))
5821   AND    NVL(aid.invoice_includes_prepay_flag, 'N') <> 'Y';
5822 
5823 TYPE  t_prepay_dist_rec IS TABLE OF Prepay_Distributions%ROWTYPE
5824 				INDEX BY BINARY_INTEGER;
5825 
5826 v_prepay_dist_rec t_prepay_dist_rec;
5827 l_prepay_excl_tax_amt  number;
5828 BEGIN
5829 
5830   l_debug_loc := 'Exclude_Tax_Freight_From_Disc';
5831   l_curr_calling_sequence := 'AP_APPROVAL_PKG.Exclude_Tax_From_Discount<-'||P_curr_calling_sequence;
5832 
5833   l_payment_status   := 'N';
5834   l_prepayment_app_exists := 'N';
5835   l_total_amount_positive := 'N';
5836   l_total_amount          := 0;
5837   l_records_exist         := FALSE;
5838   j                       :=1;
5839 
5840   ------------------------------------------------------------
5841   l_debug_info := 'Verify the Parameters and set the purpose';
5842   ------------------------------------------------------------
5843   IF p_exclude_tax_from_discount = 'Y' OR p_exclude_freight_from_disc = 'Y' THEN
5844     l_purpose := 'EXCLUDE';
5845   ELSIF (p_invoice_type_lookup_code in ('PO PRICE ADJUST','ADJUSTMENT')) THEN
5846     l_purpose := 'RETROONLY';
5847   END IF;
5848 
5849   IF l_purpose = 'EXCLUDE' THEN
5850      ------------------------------------------------------------
5851      l_debug_info := 'Check if the Invoice is Paid/partially Paid';
5852      ------------------------------------------------------------
5853      BEGIN
5854         SELECT 'Y'
5855         INTO   l_payment_status
5856         FROM   ap_invoice_payments
5857         WHERE  invoice_id = p_invoice_id
5858         AND    nvl(reversal_flag,'N') <> 'Y'
5859         AND    rownum<2;
5860 
5861      EXCEPTION
5862         WHEN OTHERS THEN
5863           l_payment_status := 'N';
5864      END;
5865 
5866      IF l_payment_status <> 'N' THEN
5867         RETURN;
5868      END IF;
5869 
5870      ------------------------------------------------------------
5871      l_debug_info := 'Check if Prepayment Application Exists';
5872      ------------------------------------------------------------
5873      BEGIN
5874        SELECT 'Y'
5875        INTO   l_prepayment_app_exists
5876        FROM   ap_invoice_lines
5877        WHERE  invoice_id = p_invoice_id
5878        AND    line_type_lookup_code = 'PREPAY'
5879        AND    rownum < 2;
5880      EXCEPTION
5881        WHEN OTHERS THEN
5882          l_prepayment_app_exists := 'N';
5883      END;
5884 
5885      ------------------------------------------------------------
5886      l_debug_info := 'Get Required Info From Invoice Header';
5887      ------------------------------------------------------------
5888 
5889      BEGIN
5890        SELECT amount_applicable_to_discount,
5891               decode(p_exclude_tax_from_discount,
5892 	             'Y',nvl(total_tax_amount,0),0),
5893               nvl(validated_tax_amount,0),
5894               terms_id,
5895               last_updated_by,
5896               created_by,
5897               batch_id,
5898               terms_date,
5899               invoice_amount,
5900               nvl(pay_curr_invoice_amount, invoice_amount),
5901               payment_cross_rate,
5902               payment_method_code, --4552701
5903               invoice_currency_code,
5904               payment_currency_code,
5905               invoice_date
5906        INTO   l_discountable_amount,
5907               l_total_tax_amount,
5908               l_validated_amount,
5909               l_terms_id,
5910               l_last_updated_by,
5911               l_created_by,
5912               l_batch_id,
5913               l_terms_date,
5914               l_invoice_amount,
5915               l_pay_curr_invoice_amount,
5916               l_payment_cross_rate,
5917               l_payment_method,
5918               l_invoice_curr_code,
5919               l_pay_curr_code,
5920               l_invoice_date
5921        FROM   ap_invoices
5922        WHERE  invoice_id = p_invoice_id;
5923 
5924      EXCEPTION
5925       WHEN OTHERS THEN
5926        RETURN;
5927      END;
5928 
5929      IF (p_exclude_freight_from_disc = 'Y') THEN
5930               SELECT NVL(SUM(nvl(ail.amount,0)),0)
5931         INTO l_total_freight_amount
5932         FROM ap_invoice_lines ail
5933         WHERE ail.invoice_id = p_invoice_id
5934         AND ail.line_type_lookup_code = 'FREIGHT'
5935         AND nvl(ail.discarded_flag,'N') <> 'Y';
5936      ELSE
5937 	l_total_freight_amount := 0;
5938      END IF;
5939 
5940      ------------------------------------------------------------
5941      l_debug_info := 'Get the net Tax Amount to Adjust';
5942      ------------------------------------------------------------
5943 
5944      l_new_amount_to_adjust := (l_total_tax_amount+l_total_freight_amount) - l_validated_amount;
5945      IF l_new_amount_to_adjust <> 0 THEN
5946         ------------------------------------------------------------
5947         l_debug_info := 'Get new discountable Amount';
5948         ------------------------------------------------------------
5949         l_new_discountable_amount  := l_discountable_amount
5950                                   - l_new_amount_to_adjust;
5951         ------------------------------------------------------------
5952         l_debug_info := 'Recreate the Payment Schedules';
5953         ------------------------------------------------------------
5954         /* bug 4931755. Procedure Create_Payment_Schedules was called before */
5955         AP_CREATE_PAY_SCHEDS_PKG.Ap_Create_From_Terms
5956                      (p_invoice_id,
5957                       l_terms_id,
5958                       l_last_updated_by,
5959                       l_created_by,
5960                       null,
5961                       l_batch_id,
5962                       l_terms_date,
5963                       l_invoice_amount,
5964                       l_pay_curr_invoice_amount,
5965                       l_payment_cross_rate,
5966                       l_new_discountable_amount,
5967                       l_payment_method,
5968                       l_invoice_curr_code,
5969                       l_pay_curr_code,
5970                       l_curr_calling_sequence);
5971 
5972         ---------------------------------------------------------------
5973         l_debug_info := 'Update Pay Schedules if Prepayment APP Exists';
5974         --------------------------------------------------------------
5975 
5976         IF l_prepayment_app_exists = 'Y' THEN
5977 
5978            OPEN Prepay_Distributions;
5979 
5980            loop
5981              fetch Prepay_Distributions into v_prepay_dist_rec(j);
5982              exit when Prepay_Distributions%notfound;
5983              j:=j+1;
5984            end loop;
5985 
5986            CLOSE Prepay_Distributions;
5987 
5988            IF v_prepay_dist_rec.COUNT > 0 THEN
5989 
5990               FOR i IN v_prepay_dist_rec.FIRST .. v_prepay_dist_rec.LAST LOOP
5991                    l_total_amount := l_total_amount + v_prepay_dist_rec(i).amount;
5992                    l_records_exist := TRUE;
5993               END LOOP;
5994 
5995               IF l_records_exist THEN
5996 
5997 	         --bugfix:5638734
5998 		 -- Get the exculusive tax amount for the prepay appln line.
5999    	         SELECT sum(aid.amount)
6000 		 INTO l_prepay_excl_tax_amt
6001 		 FROM   ap_invoice_lines_all ail,ap_invoice_distributions_all aid
6002 		 WHERE  ail.line_type_lookup_code='TAX'
6003 		 AND    ail.invoice_id=p_invoice_id
6004 		 AND    aid.invoice_id=ail.invoice_id
6005 	         AND    aid.invoice_line_number=ail.line_number
6006 	         AND   ail.prepay_line_number is not null;
6007 
6008                  l_total_amount:= l_total_amount - nvl(l_prepay_excl_tax_amt,0);
6009 
6010                  IF l_total_amount > 0 THEN
6011                      l_total_amount_positive := 'Y';
6012                  ELSE
6013                      l_total_amount_positive := 'N';
6014                  END IF;
6015 
6016                  IF l_total_amount <> 0 THEN
6017 
6018                      Update_Payment_Schedule_Prepay(
6019                                 p_invoice_id,
6020                                 l_total_amount,
6021                                 l_total_amount_positive,
6022                                 v_prepay_dist_rec(1).pay_currency,
6023                                 v_prepay_dist_rec(1).user_id,
6024                                 v_prepay_dist_rec(1).last_update_login,
6025                                 v_prepay_dist_rec(1).calling_sequence);
6026 
6027                  END IF;
6028 
6029               END IF;
6030 
6031            END IF;
6032 
6033         END IF;
6034 
6035         --Exclude the manual withholding tax from the payment schedules
6036         Manual_Withhold_tax( p_invoice_id,
6037                              5,
6038                              5,
6039                              l_curr_calling_sequence);
6040 
6041         --Bug 7393338 added the below call to update amount remaining on payment schedule
6042                     Update_Pay_Sched_For_Awt( p_invoice_id,
6043                                         5,
6044                                         5,
6045                                        l_curr_calling_sequence);
6046         ------------------------------------------------------------
6047         l_debug_info := 'Update Invoice Header';
6048         ------------------------------------------------------------
6049 
6050        UPDATE ap_invoices
6051         SET    amount_applicable_to_discount = l_new_discountable_amount,
6052                validated_tax_amount = l_total_tax_amount+l_total_freight_amount
6053         WHERE  invoice_id = p_invoice_id;
6054 
6055 
6056      END IF;
6057 
6058   ELSE -- Retro Price Case
6059 
6060     l_debug_info := 'Retro price case';
6061     Print_Debug(l_debug_loc,l_debug_info);
6062 
6063     SELECT sum(nvl(amount,0)),
6064            sum(nvl(base_amount,0))
6065       INTO l_tmp_invoice_amount,
6066            l_tmp_base_amount
6067       FROM ap_invoice_distributions_all
6068      WHERE invoice_id = p_invoice_id
6069        AND ((line_type_lookup_code NOT IN ('PREPAY', 'AWT')
6070                     AND    prepay_distribution_id IS NULL)
6071                     OR     nvl(invoice_includes_prepay_flag,'N') = 'Y');
6072 
6073     UPDATE ap_invoices
6074     SET    invoice_amount                = l_tmp_invoice_amount,
6075            amount_applicable_to_discount = l_tmp_invoice_amount,
6076            base_amount                   = l_tmp_base_amount,
6077            pay_curr_invoice_amount = decode(invoice_currency_code,
6078                         			nvl(payment_currency_code,invoice_currency_code), l_tmp_invoice_amount,
6079                         			gl_currency_api.convert_amount
6080                           				(invoice_currency_code,
6081                            				 nvl(payment_currency_code,invoice_currency_code),
6082                            				 payment_cross_rate_date,
6083                            				 payment_cross_rate_type,
6084                            				 l_tmp_invoice_amount))
6085     WHERE invoice_id = p_invoice_id;
6086 
6087      ------------------------------------------------------------
6088      l_debug_info := 'Get Required Info From Invoice Header';
6089      ------------------------------------------------------------
6090      BEGIN
6091        SELECT amount_applicable_to_discount,
6092               nvl(total_tax_amount,0),
6093               nvl(validated_tax_amount,0),
6094               terms_id,
6095               last_updated_by,
6096               created_by,
6097               batch_id,
6098               terms_date,
6099               invoice_amount,
6100               pay_curr_invoice_amount,
6101               payment_cross_rate,
6102               payment_method_code, --4552701
6103               invoice_currency_code,
6104               payment_currency_code
6105        INTO   l_discountable_amount,
6106               l_total_tax_amount,
6107               l_validated_amount,
6108               l_terms_id,
6109               l_last_updated_by,
6110               l_created_by,
6111               l_batch_id,
6112               l_terms_date,
6113               l_invoice_amount,
6114               l_pay_curr_invoice_amount,
6115               l_payment_cross_rate,
6116               l_payment_method,
6117               l_invoice_curr_code,
6118               l_pay_curr_code
6119        FROM   ap_invoices
6120        WHERE  invoice_id = p_invoice_id;
6121 
6122      EXCEPTION
6123       WHEN OTHERS THEN
6124        RETURN;
6125      END;
6126 
6127      ------------------------------------------------------------
6128      l_debug_info := 'Recreate the Payment Schedules: '|| l_invoice_amount;
6129      Print_Debug(l_debug_loc,l_debug_info);
6130      ------------------------------------------------------------
6131 
6132      AP_CREATE_PAY_SCHEDS_PKG.AP_Create_From_Terms
6133                    (p_invoice_id,
6134                     l_terms_id,
6135                     l_last_updated_by,
6136                     l_created_by,
6137                     null,
6138                     l_batch_id,
6139                     l_terms_date,
6140                     l_invoice_amount,
6141                     l_pay_curr_invoice_amount,
6142                     l_payment_cross_rate,
6143                     l_discountable_amount,
6144                     l_payment_method,
6145                     l_invoice_curr_code,
6146                     l_pay_curr_code,
6147                     l_curr_calling_sequence);
6148   END IF;
6149 
6150 EXCEPTION
6151   WHEN OTHERS THEN
6152     IF (SQLCODE <> -20001) THEN
6153       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
6154       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
6155       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
6156       FND_MESSAGE.SET_TOKEN('PARAMETERS',
6157               ', Invoice Id = '|| to_char(p_invoice_id)
6158               ||', Exclude Tax from Discount = '|| p_exclude_tax_from_discount
6159               ||', Invoice Type = '|| p_invoice_type_lookup_code );
6160       FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
6161     END IF;
6162     APP_EXCEPTION.RAISE_EXCEPTION;
6163 
6164 END Exclude_Tax_Freight_From_Disc;
6165 
6166 
6167 
6168 -------------------------------------------------------------------------------
6169 --This procedure update payment schedules automatically for invoices
6170 --where prepayment is applied. This will be called from the prcedure
6171 -- Exclude_Tax_Freight_From_Discount for the feature as described in the description of
6172 --  the former procedure. A similar procedure exists in prepayment package
6173 -- however due to some restriction we are creating the procedure here. This
6174 -- procedure will not update ap_invoices, but will update payment schedule.
6175 -------------------------------------------------------------------------------
6176 
6177 PROCEDURE update_payment_schedule_prepay(
6178                 p_invoice_id                    IN      NUMBER,
6179                 p_apply_amount                  IN      NUMBER,
6180                 p_amount_positive               IN      VARCHAR2,
6181                 p_payment_currency_code         IN      VARCHAR2,
6182                 p_user_id                       IN      NUMBER,
6183                 p_last_update_login             IN      NUMBER,
6184                 p_calling_sequence              IN      VARCHAR2) AS
6185 l_debug_info                    VARCHAR2(1000);
6186 l_current_calling_sequence      VARCHAR2(2000);
6187 l_apply_amount_remaining        NUMBER;
6188 l_cursor_payment_num            NUMBER;
6189 l_cursor_amount                 NUMBER;
6190 
6191 CURSOR Schedules IS
6192     SELECT  payment_num,
6193             DECODE(p_amount_positive,
6194                  'N', gross_amount - amount_remaining,
6195                       amount_remaining)
6196     --
6197     -- If unapplying prepayment, we want to get the amount paid, else
6198     -- we want to get amount remaining so we won't overapply.
6199     --
6200     FROM    ap_payment_schedules
6201     WHERE   invoice_id = p_invoice_id
6202     AND     (payment_status_flag||'' = 'P'
6203     OR      payment_status_flag||'' = DECODE(p_amount_positive, 'N', 'Y', 'N'))
6204     ORDER BY DECODE(p_amount_positive,
6205                  'N', DECODE(payment_status_flag,'P',1,'Y',2,3),
6206                       DECODE(NVL(hold_flag,'N'),'N',1,2)),
6207              DECODE(p_amount_positive,
6208                      'N', due_date,
6209                           NULL) DESC,
6210              DECODE(p_amount_positive,
6211                      'Y', due_date,
6212                                NULL),
6213              DECODE(p_amount_positive,
6214                  'N', DECODE(hold_flag,'N',1,'Y',2,3),
6215                       DECODE(NVL(payment_status_flag,'N'),'P',1,'N',2,3));
6216 BEGIN
6217   -- Update the calling sequence
6218   l_current_calling_sequence := 'update_payment_schedule_prepay<-'||
6219                                  p_calling_sequence;
6220     IF (p_invoice_id IS NULL OR
6221         p_apply_amount IS NULL OR
6222         p_amount_positive IS NULL OR
6223         p_payment_currency_code IS NULL) THEN
6224 
6225        RAISE NO_DATA_FOUND;
6226     END IF;
6227    --
6228    -- l_amount_apply_remaining will keep track of the apply amount that is
6229    -- remaining to be factored into amount remaining.
6230    --
6231 
6232    l_apply_amount_remaining := p_apply_amount;
6233     --
6234     -- Open schedule ,fetch payment_num and amount into local variable array
6235     --
6236     l_debug_info := 'Open Payment Schedule Cursor';
6237 
6238     OPEN SCHEDULES;
6239     LOOP
6240     l_debug_info := 'Fetch Schedules into local variables';
6241 
6242     FETCH SCHEDULES INTO l_cursor_payment_num, l_cursor_amount;
6243 
6244     EXIT WHEN SCHEDULES%NOTFOUND;
6245 
6246     if ((((l_apply_amount_remaining - l_cursor_amount) <= 0) AND
6247         (p_amount_positive = 'Y')) OR
6248         (((l_apply_amount_remaining + l_cursor_amount) >= 0) AND
6249         (p_amount_positive = 'N'))) then
6250 
6251     /*-----------------------------------------------------------------------+
6252      * Case 1 for                                                            *
6253      *   1. In apply prepayment(amount_positive = 'Y'), the amount remaining *
6254      *     is greater than apply amount remaining.                           *
6255      *   2. In unapply prepayment, the apply amount (actually unapply amount *
6256      *     here) is greater than amount_paid (gross amount-amount remaining).*
6257      *                                                                       *
6258      *  It means that this schedule line has enough amount to apply(unapply) *
6259      *  the whole apply_amount.                                              *
6260      *                                                                       *
6261      *  Update the amount remaining for this payment schedule line so that:  *
6262      *  (amount remaining - apply amount remaining).                         *
6263      +-----------------------------------------------------------------------*/
6264 
6265      l_debug_info := 'Update ap_payment_schedule for the invoice, case 1';
6266 
6267      UPDATE ap_payment_schedules
6268         SET amount_remaining = (amount_remaining -
6269                                 ap_utilities_pkg.ap_round_currency(
6270                                 l_apply_amount_remaining,
6271                                 p_payment_currency_code)),
6272             payment_status_flag =
6273                         DECODE(amount_remaining -
6274                                ap_utilities_pkg.ap_round_currency(
6275                                l_apply_amount_remaining,
6276                                p_payment_currency_code),
6277                                0,'Y',
6278                                gross_amount, 'N',
6279                                'P'),
6280             last_update_date = SYSDATE,
6281             last_updated_by = p_user_id,
6282             last_update_login = p_last_update_login
6283       WHERE invoice_id = p_invoice_id
6284         AND payment_num = l_cursor_payment_num;
6285 
6286      EXIT;
6287 
6288      /* No more amount left */
6289 
6290   else
6291 
6292     /*----------------------------------------------------------------------*
6293      *Case 2 for this line don't have enough amount to apply(unapply).      *
6294      *                                                                      *
6295      *   Update the amount_remaining to 0 and amount_apply_remaining become *
6296      *   (amount_apply - amount_remaining(this line)), then go to next      *
6297      *   schedule line.                                                     *
6298      *----------------------------------------------------------------------*/
6299 
6300      l_debug_info := 'Update ap_payment_schedule for the invoice, case 2';
6301 
6302       UPDATE ap_payment_schedules
6303          SET amount_remaining = DECODE(p_amount_positive,
6304                                         'Y', 0,
6305                                        gross_amount),
6306              payment_status_flag = DECODE(p_amount_positive,
6307                                           'Y', 'Y',
6308                                           'N'),
6309              last_update_date = SYSDATE,
6310              last_updated_by = p_user_id,
6311              last_update_login = p_last_update_login
6312        WHERE  invoice_id = p_invoice_id
6313          AND  payment_num = l_cursor_payment_num;
6314 
6315      if (p_amount_positive = 'Y') then
6316         l_apply_amount_remaining := l_apply_amount_remaining - l_cursor_amount;
6317      else
6318         l_apply_amount_remaining := l_apply_amount_remaining + l_cursor_amount;
6319      end if;
6320 
6321    end if;
6322 
6323 END LOOP;
6324 
6325 l_debug_info := 'Close Schedule Cursor';
6326 
6327 CLOSE SCHEDULES;
6328 
6329 --Bug 4539462 DBI logging
6330 AP_DBI_PKG.Maintain_DBI_Summary
6331               (p_table_name => 'AP_INVOICES',
6332                p_operation => 'U',
6333                p_key_value1 => P_invoice_id,
6334                p_calling_sequence => l_current_calling_sequence);
6335 
6336 EXCEPTION
6337   WHEN OTHERS then
6338    if (SQLCODE <> -20001 ) then
6339      FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
6340      FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
6341      FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE',l_current_calling_sequence);
6342 
6343      FND_MESSAGE.SET_TOKEN('PARAMETERS','Invoice_id = '||TO_CHAR(p_invoice_id)
6344                 ||' Apply_amount = '||TO_CHAR(p_apply_amount)
6345                 ||' Amount_positive = '||p_amount_positive
6346                 ||' Apply_amount_remaining = '||
6347                 TO_CHAR(l_apply_amount_remaining)
6348                 ||' Cursor_amount = '||TO_CHAR(l_cursor_amount)
6349                 ||' Cursor_Payment_num = '||TO_CHAR(l_cursor_payment_num)
6350                 ||' User_id = '||TO_CHAR(p_user_id)
6351                 ||' Last_update_login = '||TO_CHAR(p_last_update_login)
6352                 ||' Payment_Currency_code = '||p_payment_currency_code);
6353 
6354      FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
6355 
6356    end if;
6357 
6358    APP_EXCEPTION.RAISE_EXCEPTION;
6359 
6360 END update_payment_schedule_prepay;
6361 
6362 
6363 --============================================================================
6364 -- MANUAL_WITHHOLD_TAX:  Procedure that update payment schedules
6365 --                               to reflect the manual withholding amount
6366 --============================================================================
6367 PROCEDURE Manual_Withhold_Tax(p_invoice_id                      IN NUMBER,
6368                         p_last_updated_by               IN NUMBER,
6369                         p_last_update_login             IN NUMBER,
6370                         p_calling_sequence              IN VARCHAR2) IS
6371   l_manual_awt_amount       ap_invoice_distributions.amount%TYPE :=0;
6372   l_payment_cross_rate      ap_invoices.payment_cross_rate%TYPE;
6373   l_pay_curr_code           ap_invoices.payment_currency_code%TYPE;
6374   l_num_payments                        NUMBER := 0;
6375   l_invoice_type            ap_invoices.invoice_type_lookup_code%TYPE;--1724924
6376   l_inv_amt_remaining       ap_payment_schedules.amount_remaining%TYPE := 0;
6377   l_gross_amount            ap_payment_schedules.gross_amount%TYPE := 0;
6378   l_debug_loc               VARCHAR2(30) := 'Manual_Withhold_Tax';
6379   l_curr_calling_sequence   VARCHAR2(2000);
6380 
6381 BEGIN
6382 
6383   -- AP_LOGGING_PKG.AP_Begin_Block(l_debug_loc);
6384 
6385   -- Update the calling sequence --
6386 
6387   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||p_calling_sequence;
6388 
6389   -- Initialize local variables
6390   -- BUG 4340061 : For the lines which have been already been validated but the invoice has been placed on hold.
6391 
6392   SELECT  sum( nvl(amount, 0) )
6393   INTO   l_manual_awt_amount
6394   FROM   ap_invoice_distributions
6395   WHERE  invoice_id = p_invoice_id
6396   AND    nvl(match_status_flag, 'N') in ('N','T')   -- BUG 4340061
6397   AND    line_type_lookup_code = 'AWT'
6398   AND    awt_flag in ('M', 'O');
6399 
6400 
6401   SELECT sum(nvl(amount_remaining,0)), sum(nvl(gross_amount,0))
6402   INTO l_inv_amt_remaining, l_gross_amount
6403   FROM ap_payment_schedules
6404   WHERE invoice_id = p_invoice_id;
6405 
6406   SELECT payment_cross_rate,
6407          payment_currency_code,
6408          invoice_type_lookup_code --Bug 1724924
6409   INTO   l_payment_cross_rate,
6410          l_pay_curr_code,
6411          l_invoice_type --Bug 1724924
6412   FROM   ap_invoices
6413   WHERE  invoice_id = p_invoice_id;
6414 
6415         --===================================================================
6416         --Prorate the manual AWT against the invoice amount remaining
6417         --===================================================================
6418         --Bug 1985604 - Modified if condition
6419 
6420         -- Bug 2636774. Checking if the manual_awt_amount is <> 0 instead of
6421         -- not null. This check will ensure that the payment schedule will not
6422         -- be updated for cancelled invoices.
6423 
6424         -- BUG 4344086 : if condition added. If l_gross_amount = 0 means, the
6425         -- invoice is either cancelled or is of 0$
6426         if l_gross_amount = 0
6427           then
6428                 update ap_payment_schedules
6429                   set amount_remaining = 0
6430                 where invoice_id = p_invoice_id;
6431 
6432         elsif ((l_inv_amt_remaining <> 0) and (nvl(l_manual_awt_amount,0) <> 0))
6433           then
6434 
6435                 update ap_payment_schedules
6436                   set amount_remaining = (amount_remaining +
6437                   ap_utilities_pkg.ap_round_currency(
6438                  (amount_remaining * (l_manual_awt_amount/l_inv_amt_remaining)
6439                     * l_payment_cross_rate), l_pay_curr_code ) )
6440                 where invoice_id = p_invoice_id;
6441 
6442         elsif ((l_inv_amt_remaining = 0) and (nvl(l_manual_awt_amount,0) <> 0))
6443           then
6444 
6445                update ap_payment_schedules
6446                  set amount_remaining =
6447                  (amount_remaining +
6448                  ap_utilities_pkg.ap_round_currency(
6449                  (gross_amount * (l_manual_awt_amount/l_gross_amount)
6450                     * l_payment_cross_rate), l_pay_curr_code) ),
6451                  payment_status_flag = DECODE(payment_status_flag,
6452                                                'Y','P',payment_status_flag)
6453                where invoice_id = p_invoice_id;
6454 
6455                update ap_invoices
6456                  set payment_status_flag = DECODE(payment_status_flag,
6457                                                'Y','P',payment_status_flag)
6458                where invoice_id = p_invoice_id;
6459 
6460         end if;
6461 
6462 
6463 EXCEPTION
6464   when OTHERS then
6465             IF (SQLCODE <> -20001) THEN
6466               FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
6467               FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
6468               FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE',p_calling_sequence);
6469               FND_MESSAGE.SET_TOKEN('PARAMETERS',
6470                       '  Invoice Id  = '    || to_char(P_Invoice_Id) ||
6471                       ', Calling module = ' || 'Manual_withhold_tax' );
6472            END IF;
6473            APP_EXCEPTION.RAISE_EXCEPTION;
6474 
6475 END Manual_Withhold_Tax;
6476 
6477 /* Added the following procedure for 7393338 */
6478 --============================================================================
6479 -- Update_Pay_Sched_For_Awt:  Procedure that update payment schedules
6480 --                               to reflect the Automatic withholding amount
6481 --============================================================================
6482 
6483 
6484 PROCEDURE Update_Pay_Sched_For_Awt(p_invoice_id         IN NUMBER,
6485                         p_last_updated_by               IN NUMBER,
6486                         p_last_update_login             IN NUMBER,
6487                         p_calling_sequence              IN VARCHAR2) IS
6488  CURSOR Update_payment_schedule IS
6489          SELECT payment_num,gross_amount,amount_remaining
6490          FROM ap_payment_schedules
6491          WHERE invoice_id=p_invoice_id;
6492   l_automatic_awt_amount       ap_invoice_distributions.amount%TYPE :=0;
6493   l_payment_cross_rate      ap_invoices.payment_cross_rate%TYPE;
6494   l_pay_curr_code           ap_invoices.payment_currency_code%TYPE;
6495   l_num_payments                        NUMBER := 0;
6496   l_invoice_type            ap_invoices.invoice_type_lookup_code%TYPE;
6497   l_inv_amt_remaining       ap_payment_schedules.amount_remaining%TYPE := 0;
6498   l_gross_amount            ap_payment_schedules.gross_amount%TYPE := 0;
6499   l_payment_num            ap_payment_schedules.payment_num%TYPE;
6500   l_debug_loc               VARCHAR2(30) := 'Update_Pay_Sched_For_Awt';
6501   l_curr_calling_sequence   VARCHAR2(2000);
6502   l_wt_amt_to_subtract      NUMBER := 0;
6503 BEGIN
6504 
6505 
6506   l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||p_calling_sequence;
6507 
6508 
6509   SELECT  (0 - sum(nvl(amount,0)))
6510   INTO   l_automatic_awt_amount
6511   FROM   ap_invoice_distributions
6512   WHERE  invoice_id = p_invoice_id
6513   AND    line_type_lookup_code = 'AWT'
6514   AND    awt_flag = 'A';
6515 
6516  IF  l_automatic_awt_amount <>  0 then
6517 
6518  SELECT payment_cross_rate,
6519          payment_currency_code,
6520          invoice_type_lookup_code
6521   INTO   l_payment_cross_rate,
6522          l_pay_curr_code,
6523          l_invoice_type
6524   FROM   ap_invoices
6525   WHERE  invoice_id = p_invoice_id;
6526 
6527 
6528  OPEN  Update_payment_schedule;
6529 
6530  LOOP
6531  FETCH Update_payment_schedule into l_payment_num,l_gross_amount,l_inv_amt_remaining;
6532  EXIT WHEN Update_payment_schedule%NOTFOUND;
6533          SELECT  nvl(ap_utilities_pkg.ap_round_currency(
6534                 l_automatic_awt_amount*
6535                 ai.payment_cross_rate,l_pay_curr_code),0)*
6536                 l_gross_amount/decode(ai.pay_curr_invoice_amount, 0, 1,
6537                                       nvl(ai.pay_curr_invoice_amount, 1))
6538         into    l_wt_amt_to_subtract
6539         from    ap_invoices ai
6540         where   ai.invoice_id=p_invoice_id;
6541 
6542         --===================================================================
6543         --Prorate the automatic AWT against the invoice amount remaining
6544         --===================================================================
6545         if l_gross_amount = 0 then
6546                 update ap_payment_schedules
6547                   set amount_remaining = 0
6548                 where invoice_id = p_invoice_id
6549                 and   payment_num=l_payment_num;
6550 
6551         elsif ((l_inv_amt_remaining <> 0) and (nvl(l_wt_amt_to_subtract,0) <> 0))
6552           then
6553 
6554                 update ap_payment_schedules
6555                   set amount_remaining = (amount_remaining -
6556                   ap_utilities_pkg.ap_round_currency(
6557                  (amount_remaining * ( l_wt_amt_to_subtract/l_inv_amt_remaining)
6558                     * l_payment_cross_rate), l_pay_curr_code ) )
6559                 where invoice_id = p_invoice_id
6560                 and   payment_num=l_payment_num;
6561 
6562          End If;
6563                update ap_payment_schedules
6564                set payment_status_flag ='Y'
6565                where invoice_id = p_invoice_id
6566                and payment_num=l_payment_num
6567                and amount_remaining = 0
6568                and nvl(payment_status_flag,'N') <> 'Y';
6569  END LOOP;
6570  CLOSE Update_payment_schedule;
6571 
6572  END IF;
6573 
6574 EXCEPTION
6575   when OTHERS then
6576             IF (SQLCODE <> -20001) THEN
6577               FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
6578               FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
6579               FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE',p_calling_sequence);
6580               FND_MESSAGE.SET_TOKEN('PARAMETERS',
6581                       '  Invoice Id  = '    || to_char(P_Invoice_Id) ||
6582                       ', Calling module = ' || 'Update_Pay_Sched_For_Awt' );
6583            END IF;
6584            APP_EXCEPTION.RAISE_EXCEPTION;
6585 
6586 END Update_Pay_Sched_For_Awt;
6587 
6588 --============================================================================
6589 -- createPaymentSchedules:  Procedure that creates payment schedules
6590 --                          for invoice (request) if not yet
6591 --============================================================================
6592 PROCEDURE createPaymentSchedules(p_invoice_id           IN NUMBER,
6593                         p_calling_sequence              IN VARCHAR2) IS
6594   l_discountable_amount         NUMBER;
6595   l_total_tax_amount            NUMBER;
6596   l_total_freight_amount        NUMBER;
6597   l_validated_amount            NUMBER;
6598   l_terms_id                    NUMBER;
6599   l_last_updated_by             NUMBER;
6600   l_created_by                  NUMBER;
6601   l_payment_priority            NUMBER;
6602   l_batch_id                    NUMBER;
6603   l_terms_date                  DATE;
6604   l_invoice_amount              NUMBER;
6605   l_pay_curr_invoice_amount     NUMBER;
6606   l_payment_method              VARCHAR2(30);
6607   l_payment_cross_rate          ap_invoices.payment_cross_rate%TYPE;
6608   l_invoice_curr_code           VARCHAR2(15);
6609   l_pay_curr_code               VARCHAR2(15);
6610   l_debug_info                  VARCHAR2(200);
6611   l_debug_loc                   VARCHAR2(30) := 'createPaymentSchedules';
6612   l_schedule_count              NUMBER := 0;
6613   l_curr_calling_sequence       VARCHAR2(2000);
6614 
6615 BEGIN
6616 
6617     l_curr_calling_sequence := 'AP_APPROVAL_PKG.createPaymentSchedules <- '||P_calling_sequence;
6618 
6619     select count(*)
6620     into   l_schedule_count
6621     from   ap_payment_schedules_all
6622     where  invoice_id = p_invoice_id;
6623 
6624     -------------------------------------------
6625     l_debug_info := 'createPaymentSchedules - payment schedule count = ' || l_schedule_count;
6626     Print_Debug(l_debug_loc, l_debug_info);
6627     -------------------------------------------
6628 
6629     if ( l_schedule_count <= 0 ) then
6630 
6631        -------------------------------------------
6632        l_debug_info := 'Get Required Info From Invoice Header';
6633        Print_Debug(l_debug_loc, l_debug_info);
6634        -------------------------------------------
6635 
6636        BEGIN
6637          SELECT invoice_amount,  -- TODO: amount_applicable_to_discount,
6638               terms_id,
6639               last_updated_by,
6640               created_by,
6641               batch_id,
6642               terms_date,
6643               invoice_amount,
6644               nvl(pay_curr_invoice_amount, invoice_amount),
6645               payment_cross_rate,
6646               payment_method_code, --4552701
6647               invoice_currency_code,
6648               payment_currency_code
6649          INTO   l_discountable_amount,
6650               l_terms_id,
6651               l_last_updated_by,
6652               l_created_by,
6653               l_batch_id,
6654               l_terms_date,
6655               l_invoice_amount,
6656               l_pay_curr_invoice_amount,
6657               l_payment_cross_rate,
6658               l_payment_method,
6659               l_invoice_curr_code,
6660               l_pay_curr_code
6661          FROM   ap_invoices
6662          WHERE  invoice_id = p_invoice_id;
6663 
6664        EXCEPTION
6665         WHEN OTHERS THEN
6666         RETURN;
6667        END;
6668 
6669        -- create payment schedules
6670        AP_CREATE_PAY_SCHEDS_PKG.Create_Payment_Schedules
6671                      (p_invoice_id,
6672                       l_terms_id,
6673                       l_last_updated_by,
6674                       l_created_by,
6675                       null, -- TODO: why payment_priority is null?
6676                       l_batch_id,
6677                       l_terms_date,
6678                       l_invoice_amount,
6679                       l_pay_curr_invoice_amount,
6680                       l_payment_cross_rate,
6681                       l_discountable_amount,
6682                       l_payment_method,
6683                       l_invoice_curr_code,
6684                       l_pay_curr_code,
6685                       l_curr_calling_sequence);
6686 
6687        -------------------------------------------
6688        l_debug_info := 'createPaymentSchedules - payment schedule created.';
6689        Print_Debug(l_debug_loc, l_debug_info);
6690        -------------------------------------------
6691 
6692     end if;
6693 
6694 EXCEPTION
6695   when OTHERS then
6696             IF (SQLCODE <> -20001) THEN
6697               FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
6698               FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
6699               FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE',l_curr_calling_sequence);
6700               FND_MESSAGE.SET_TOKEN('PARAMETERS',
6701                       '  Invoice Id  = '    || to_char(P_Invoice_Id) ||
6702                       ', Calling module = ' || 'createPaymentSchedules' );
6703            END IF;
6704            APP_EXCEPTION.RAISE_EXCEPTION;
6705 
6706 END createPaymentSchedules;
6707 
6708 
6709 FUNCTION Is_Product_Registered(P_Application_Id      IN         NUMBER,
6710 			       X_Registration_Api    OUT NOCOPY VARCHAR2,
6711 			       X_Registration_View   OUT NOCOPY VARCHAR2,
6712 			       P_Calling_Sequence    IN         VARCHAR2) RETURN BOOLEAN IS
6713 
6714  l_debug_info VARCHAR2(1000);
6715  l_curr_calling_sequence VARCHAR2(2000);
6716 
6717 BEGIN
6718 
6719   l_curr_calling_sequence := 'Is_Product_Registered <-'||p_calling_sequence;
6720 
6721   BEGIN
6722      SELECT registration_api,
6723             registration_view
6724      INTO x_registration_api,
6725           x_registration_view
6726      FROM ap_product_registrations
6727      WHERE application_id = 200
6728      AND reg_application_id = p_application_id
6729      AND registration_event_type = 'DISTRIBUTION_GENERATION';
6730 
6731   EXCEPTION WHEN NO_DATA_FOUND THEN
6732      x_registration_view := NULL;
6733      x_registration_api := NULL;
6734      RETURN(FALSE);
6735   END;
6736 
6737   RETURN(TRUE);
6738 
6739 EXCEPTION
6740   WHEN OTHERS then
6741      IF (SQLCODE <> -20001) THEN
6742        FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
6743        FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
6744        FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE',l_curr_calling_sequence);
6745        FND_MESSAGE.SET_TOKEN('PARAMETERS',
6746                          '  Application Id  = '    || to_char(P_Application_Id) );
6747      END IF;
6748      APP_EXCEPTION.RAISE_EXCEPTION;
6749 
6750 END Is_Product_Registered;
6751 
6752 
6753 FUNCTION  Gen_Dists_From_Registration(
6754 		       P_Batch_Id	     IN  NUMBER,
6755                        P_Invoice_Line_Rec    IN  AP_INVOICES_PKG.r_invoice_line_rec,
6756                        P_Registration_Api    IN  VARCHAR2,
6757                        P_Registration_View   IN  VARCHAR2,
6758 		       P_Generate_Permanent  IN  VARCHAR2,
6759                        X_Error_Code          OUT NOCOPY VARCHAR2,
6760                        P_Calling_Sequence    IN  VARCHAR2) RETURN BOOLEAN IS
6761 
6762   l_debug_info VARCHAR2(1000);
6763   l_curr_calling_sequence VARCHAR2(2000);
6764 
6765   TYPE Invoice_Dists_Tab_Type IS TABLE OF ap_invoice_distributions_all%ROWTYPE;
6766   l_dist_tab Invoice_Dists_Tab_Type := Invoice_Dists_Tab_Type();
6767 
6768   TYPE Expense_Report_Dists_Rec IS RECORD (
6769 	Org_id  ap_exp_report_dists_all.org_id%TYPE,
6770 	Sequence_Num ap_exp_report_dists_all.sequence_num%TYPE,
6771 	Code_Combination_Id ap_exp_report_dists_all.code_combination_id%TYPE,
6772 	Amount  ap_exp_report_dists_all.amount%TYPE,
6773 	Project_Id ap_exp_report_dists_all.project_id%TYPE,
6774 	Task_Id ap_exp_report_dists_all.task_id%TYPE,
6775 	Award_Id ap_exp_report_dists_all.award_id%TYPE,
6776 	pa_quantity ap_expense_report_lines_all.pa_quantity%TYPE, --bug6699834
6777 	Expenditure_Organization_Id ap_exp_report_dists_all.expenditure_organization_id%TYPE,
6778 	Expenditure_type  ap_expense_report_lines_all.expenditure_type%TYPE,
6779 	Expenditure_item_date ap_expense_report_lines_all.expenditure_item_date%TYPE,
6780         receipt_currency_amount ap_exp_report_dists_all.receipt_currency_amount%TYPE, --bug6520882
6781         receipt_currency_code    ap_exp_report_dists_all.receipt_currency_code%TYPE,
6782         receipt_conversion_rate  ap_exp_report_dists_all.receipt_conversion_rate%TYPE);
6783 
6784   TYPE Expense_Report_Dists_Tab_Type IS TABLE OF Expense_Report_Dists_Rec
6785        index by BINARY_INTEGER;
6786 
6787   l_exp_report_dists_tab  Expense_Report_Dists_Tab_Type;
6788 
6789   CURSOR c_expense_report_dists IS
6790   SELECT nvl(aerd.org_id,aerl.org_id), --Bug5867415
6791 	 aerd.sequence_num,
6792 	 aerd.code_combination_id,
6793 	 aerd.amount,
6794 	 aerd.project_id,
6795 	 aerd.task_id,
6796 	 aerd.award_id,
6797 	 aerl.pa_quantity,     -- bug6699834
6798 	 aerd.expenditure_organization_id,
6799 	 --bugfix:4939074
6800 	 aerl.expenditure_type,
6801 	 aerl.expenditure_item_date,
6802          aerd.receipt_currency_amount, --bug6520882
6803          aerd.receipt_currency_code,
6804          aerd.receipt_conversion_rate
6805   FROM ap_exp_report_dists_all aerd,
6806        ap_expense_report_lines_all aerl
6807   WHERE aerd.report_header_id = p_invoice_line_rec.reference_key1
6808   AND aerd.report_line_id = p_invoice_line_rec.reference_key2
6809   AND aerd.report_line_id = aerl.report_line_id
6810   AND aerd.report_header_id = aerl.report_header_id
6811   ORDER BY report_distribution_id;
6812 
6813   i NUMBER;
6814   j NUMBER;
6815   l_account_type VARCHAR2(10);
6816   l_distribution_line_number NUMBER;
6817   l_total_dist_amount NUMBER;
6818   l_api_name VARCHAR2(200) :=  'Gen_Dists_From_Registration';
6819 
6820 BEGIN
6821 
6822   i:= 0;
6823   l_distribution_line_number := 0;
6824   l_total_dist_amount := 0;
6825 
6826   l_curr_calling_sequence := 'Gen_Dists_From_Registration <- '||p_calling_sequence;
6827 
6828   -------------------------------------------
6829   l_debug_info := 'Generate Distributions as per the applications registered view';
6830   Print_Debug(l_api_name, l_debug_info);
6831   -------------------------------------------
6832 
6833   -------------------------------------------
6834   l_debug_info := 'P_Registration_View: '||P_Registration_View;
6835   Print_Debug(l_api_name, l_debug_info);
6836   -------------------------------------------
6837 
6838   IF (P_Registration_View = 'AP_EXP_REPORT_DISTS') THEN
6839 
6840      -------------------------------------------
6841      l_debug_info := 'Open Cursor c_expense_report_dists';
6842      Print_Debug(l_api_name, l_debug_info);
6843      -------------------------------------------
6844 
6845      OPEN c_expense_report_dists;
6846      FETCH c_expense_report_dists
6847      BULK COLLECT INTO l_exp_report_dists_tab;
6848      CLOSE c_expense_report_dists;
6849 
6850      IF (l_exp_report_dists_tab.COUNT > 0) THEN
6851 
6852        -------------------------------------------
6853        l_debug_info := 'Exp Report Dists more than zero - setting the amount';
6854        Print_Debug(l_api_name, l_debug_info);
6855        -------------------------------------------
6856 
6857        FOR i IN l_exp_report_dists_tab.first .. l_exp_report_dists_tab.last LOOP
6858           l_total_dist_amount := l_total_dist_amount + l_exp_report_dists_tab(i).amount;
6859        END LOOP;
6860 
6861      END IF;
6862 
6863      IF (l_exp_report_dists_tab.COUNT > 0) THEN
6864 
6865         l_dist_tab.EXTEND(l_exp_report_dists_tab.COUNT);
6866 
6867         -------------------------------------------
6868         l_debug_info := 'Exp Report Dists more than zero - setting other attributes';
6869         Print_Debug(l_api_name, l_debug_info);
6870         -------------------------------------------
6871 
6872         FOR i IN l_exp_report_dists_tab.first .. l_exp_report_dists_tab.last LOOP
6873 	   l_distribution_line_number := l_distribution_line_number + 1;
6874 
6875            l_dist_tab(i).org_id := l_exp_report_dists_tab(i).org_id;
6876 	   l_dist_tab(i).distribution_line_number := l_distribution_line_number;
6877 	   l_dist_tab(i).dist_code_combination_id := l_exp_report_dists_tab(i).code_combination_id;
6878            --bug6597595
6879 	   if l_total_dist_amount = 0 then
6880 	      l_dist_tab(i).amount := 0;
6881 	   else
6882               --bug6653070
6883               l_dist_tab(i).amount :=
6884 	   	((p_invoice_line_rec.amount) * l_exp_report_dists_tab(i).amount)/
6885 			l_total_dist_amount;
6886            end if;
6887 	   l_dist_tab(i).project_id := l_exp_report_dists_tab(i).project_id;
6888 	   l_dist_tab(i).task_id := l_exp_report_dists_tab(i).task_id;
6889 	   l_dist_tab(i).award_id := l_exp_report_dists_tab(i).award_id;
6890 	   l_dist_tab(i).pa_quantity :=  l_exp_report_dists_tab(i).pa_quantity;-- bug6699834
6891 
6892 	   l_dist_tab(i).expenditure_organization_id :=  l_exp_report_dists_tab(i).expenditure_organization_id;
6893 	   l_dist_tab(i).expenditure_type := l_exp_report_dists_tab(i).expenditure_type;
6894 	   l_dist_tab(i).expenditure_item_date := l_exp_report_dists_tab(i).expenditure_item_date;
6895            l_dist_tab(i).receipt_currency_amount:=l_exp_report_dists_tab(i).receipt_currency_amount;--bug6520882
6896            l_dist_tab(i).receipt_currency_code:= l_exp_report_dists_tab(i).receipt_currency_code;
6897            l_dist_tab(i).receipt_conversion_rate:= l_exp_report_dists_tab(i).receipt_conversion_rate;
6898            l_dist_tab(i).batch_id := p_batch_id;
6899            l_dist_tab(i).invoice_id := p_invoice_line_rec.invoice_id;
6900            l_dist_tab(i).invoice_line_number := p_invoice_line_rec.line_number;
6901 
6902            SELECT ap_invoice_distributions_s.nextval
6903            INTO l_dist_tab(i).invoice_distribution_id
6904            FROM DUAL;
6905 
6906            l_dist_tab(i).line_type_lookup_code := 'ITEM';
6907 
6908            IF (nvl(p_generate_permanent,'N') = 'N') THEN
6909               l_dist_tab(i).distribution_class := 'CANDIDATE';
6910            ELSE
6911               l_dist_tab(i).distribution_class := 'PERMANENT';
6912            END IF;
6913 
6914            l_dist_tab(i).description := p_invoice_line_rec.description;
6915            l_dist_tab(i).dist_match_type := 'NOT_MATCHED';
6916            l_dist_tab(i).accounting_date := p_invoice_line_rec.accounting_date;
6917            l_dist_tab(i).period_name := p_invoice_line_rec.period_name;
6918            l_dist_tab(i).accrual_posted_flag := 'N';
6919            l_dist_tab(i).cash_posted_flag := 'N';
6920            l_dist_tab(i).posted_flag := 'N';
6921            l_dist_tab(i).set_of_books_id := p_invoice_line_rec.set_of_books_id;
6922            l_dist_tab(i).encumbered_flag := 'N';
6923            l_dist_tab(i).reversal_flag := 'N';
6924            l_dist_tab(i).cancellation_flag := 'N';
6925            l_dist_tab(i).income_tax_region := p_invoice_line_rec.income_tax_region;
6926            l_dist_tab(i).type_1099 := p_invoice_line_rec.type_1099;
6927            l_dist_tab(i).assets_addition_flag := 'U';
6928 
6929            BEGIN
6930               SELECT account_type
6931               INTO l_account_type
6932               FROM gl_code_combinations
6933               WHERE code_combination_id = l_dist_tab(i).dist_code_combination_id;
6934 
6935            EXCEPTION
6936            WHEN NO_DATA_FOUND THEN
6937 
6938               l_debug_info := l_debug_info || ': cannot read account type information';
6939 	      Print_Debug(l_api_name,l_debug_info);
6940 
6941               RETURN(FALSE);
6942 
6943            END;
6944 
6945            IF (l_account_type = 'A' OR
6946               (l_account_type = 'E' AND
6947                p_invoice_line_rec.assets_tracking_flag = 'Y')) then
6948 
6949                l_dist_tab(i).assets_tracking_flag := 'Y';
6950                l_dist_tab(i).asset_book_type_code := p_invoice_line_rec.asset_book_type_code;
6951                l_dist_tab(i).asset_category_id := p_invoice_line_rec.asset_category_id;
6952            ELSE
6953                l_dist_tab(i).assets_tracking_flag := 'N';
6954            END IF;
6955 
6956            IF (l_dist_tab(i).project_id IS NULL) THEN
6957                l_dist_tab(i).pa_addition_flag := 'E';
6958            ELSE
6959 	       l_dist_tab(i).pa_addition_flag := 'N';
6960            END IF;
6961 
6962            l_dist_tab(i).awt_group_id := p_invoice_line_rec.awt_group_id;
6963            l_dist_tab(i).inventory_transfer_status := 'N';
6964            l_dist_tab(i).intended_use := p_invoice_line_rec.primary_intended_use;
6965            l_dist_tab(i).rcv_charge_addition_flag := 'N';
6966            l_dist_tab(i).created_by := FND_GLOBAL.user_id;
6967            l_dist_tab(i).creation_date := SYSDATE;
6968            l_dist_tab(i).last_update_date := SYSDATE;
6969            l_dist_tab(i).last_update_login := FND_GLOBAL.login_id;
6970 	   l_dist_tab(i).last_updated_by := FND_GLOBAL.user_id;
6971 
6972         END LOOP;
6973 
6974      END IF; /* If l_exp_report_dists_tab.count > 0 */
6975 
6976      -------------------------------------------
6977      l_debug_info := 'Bulk Insert into ap_invoice_distributions';
6978      Print_Debug(l_api_name, l_debug_info);
6979      -------------------------------------------
6980      IF (nvl(l_dist_tab.count,0)<>0) THEN
6981 
6982      FORALL j IN l_dist_tab.first .. l_dist_tab.last
6983         INSERT INTO ap_invoice_distributions
6984         VALUES l_dist_tab(j);
6985 
6986       FOR j IN l_dist_tab.first .. l_dist_tab.last
6987       LOOP
6988         IF l_dist_tab(j).award_id is not null then
6989           gms_ap_api.CREATE_AWARD_DISTRIBUTIONS( l_dist_tab(j). invoice_id,
6990                                                  l_dist_tab(j).distribution_line_number,
6991                                                  l_dist_tab(j).invoice_distribution_id,
6992                                                  l_dist_tab(j).award_id,
6993                                                  'AP',
6994                                                   NULL,
6995                                                   NULL);
6996         End If ;
6997        END LOOP ;
6998 
6999        END IF;
7000 
7001   ELSIF (P_Registration_Api IS NOT NULL) THEN
7002     NULL;
7003 
7004   END IF;
7005 
7006   -------------------------------------------
7007   l_debug_info := 'Setting generate distributions flag to Done';
7008   Print_Debug(l_api_name, l_debug_info);
7009   -------------------------------------------
7010 
7011   IF (nvl(p_generate_permanent,'N') = 'Y') then
7012     BEGIN
7013       UPDATE AP_INVOICE_LINES
7014       SET GENERATE_DISTS = 'D'
7015       WHERE invoice_id = p_invoice_line_rec.invoice_id
7016       AND line_number = p_invoice_line_rec.line_number;
7017     EXCEPTION
7018         WHEN OTHERS THEN
7019           l_debug_info := l_debug_info || ': Error encountered';
7020           return (FALSE);
7021     END;
7022   END IF;
7023 
7024   RETURN(TRUE);
7025 
7026 
7027 EXCEPTION
7028   WHEN OTHERS then
7029     IF (SQLCODE <> -20001) THEN
7030       l_debug_info := 'In others exception '||sqlerrm;
7031       Print_Debug(l_api_name,l_debug_info);
7032 
7033       FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
7034       FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
7035       FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE',l_curr_calling_sequence);
7036       FND_MESSAGE.SET_TOKEN('PARAMETERS',
7037                   '  Invoice Id  = '    || to_char(P_invoice_line_rec.Invoice_Id) ||
7038                   ', Invoice Line Number = '||to_char(p_invoice_line_rec.Line_Number) ||
7039 		  ', Registration Api  = '||P_Registration_Api ||
7040 		  ', Registration View = '||P_Registration_View);
7041     END IF;
7042     APP_EXCEPTION.RAISE_EXCEPTION;
7043 
7044 END Gen_Dists_From_Registration;
7045 
7046 
7047 ------------------------------------------------------------------------
7048 -- Function Batch_Approval:
7049 -- It selects all invoices depending on the parameters given to it and
7050 -- calls the on-line PL/SQL approval package to approve each invoice
7051 -- individually.
7052 ------------------------------------------------------------------------
7053 
7054 FUNCTION batch_approval
7055                 (p_run_option           IN VARCHAR2,
7056                  p_sob_id               IN NUMBER,
7057                  p_inv_start_date       IN DATE,
7058                  p_inv_end_date         IN DATE,
7059                  p_inv_batch_id         IN NUMBER,
7060                  p_vendor_id            IN NUMBER,
7061                  p_pay_group            IN VARCHAR2,
7062                  p_invoice_id           IN NUMBER,
7063                  p_entered_by           IN NUMBER,
7064                  p_debug_switch         IN VARCHAR2,
7065                  p_conc_request_id      IN NUMBER,
7066                  p_commit_size          IN NUMBER,
7067                  p_org_id               IN NUMBER,
7068                  p_report_holds_count   OUT NOCOPY NUMBER) RETURN BOOLEAN
7069 
7070 IS
7071 
7072     TYPE hold_codeTab     IS TABLE OF ap_hold_codes.hold_lookup_code%Type;
7073     TYPE invoiceIDTab     IS TABLE OF ap_invoices.invoice_id%Type INDEX BY BINARY_INTEGER;
7074     TYPE invoiceNUMTab    IS TABLE OF ap_invoices.invoice_num%Type INDEX BY BINARY_INTEGER;
7075     TYPE procinvoiceIDTab IS TABLE OF ap_invoices.invoice_id%Type;
7076     TYPE hold_org_idTab   IS TABLE OF ap_invoices.org_id%Type;
7077 
7078     TYPE orgIDTab         IS TABLE OF ap_invoices_all.org_id%Type INDEX BY BINARY_INTEGER;
7079     TYPE invtypeTab IS TABLE OF ap_invoices_all.invoice_type_lookup_code%Type INDEX BY BINARY_INTEGER;
7080 
7081     l_inv_batch_id     			NUMBER(15);
7082     l_vendor_id         		NUMBER(15);
7083     l_pay_group         		VARCHAR2(25);
7084     l_invoice_id        		NUMBER(15);
7085     l_entered_by        		NUMBER(15);
7086     l_holds_count       		NUMBER(5);
7087     l_approval_status   		VARCHAR2(25);
7088 
7089     l_status            		VARCHAR2(80);
7090     l_approval_error    		VARCHAR2(2000);
7091     l_org_id            		NUMBER(15);
7092     l_sel_org_id        		NUMBER(15);
7093     l_old_org_id        		NUMBER(15);
7094 
7095     l_sel_invoice_type  		VARCHAR2(25);
7096     l_calling_mode      		VARCHAR2(25);
7097     l_funds_return_code 		VARCHAR2(30); --Bug6610937
7098 
7099     l_sql_stmt                  	VARCHAR2(5000);
7100     l_sql_stmt_cursor           	INTEGER;
7101     ignore                      	INTEGER;
7102     no_of_rows_fetched          	INTEGER;
7103 
7104     l_hold_code                 	hold_codeTab;
7105     l_selected_invoice_ids        invoiceIDTab; -- 7461423
7106     l_sel_invoice_num           	invoiceNUMTab;
7107 
7108     lc_sel_org_id	       		orgIDTab;
7109     lc_sel_invoice_type	       		invtypeTab;
7110 
7111     l_processed_inv_id         		procinvoiceIDTab;
7112     l_hold_org_id              		hold_org_idTab;
7113 
7114     l_validation_request_id    		NUMBER;
7115     l_invoice_num              		VARCHAR2(50);
7116     l_commit_size              		NUMBER;
7117     l_curr_calling_sequence		VARCHAR2(2000);
7118 
7119     l_holds                       	HOLDSARRAY;
7120     l_hold_count                  	COUNTARRAY;
7121     l_release_count               	COUNTARRAY;
7122     l_total_hold_count            	NUMBER;
7123     l_total_release_count         	NUMBER;
7124     l_line_variance_hold_exist    	BOOLEAN := FALSE;
7125     l_need_to_round_flag          	VARCHAR2(1) := 'Y';
7126 
7127     l_success				BOOLEAN;
7128     l_error_code			VARCHAR2(4000);
7129     l_prorate_across_all_items    	VARCHAR2(1);
7130     l_debug_context               	VARCHAR2(2000);
7131     l_insufficient_data_exist     	BOOLEAN := FALSE;
7132 
7133     l_calling_sequence            	VARCHAR2(20);
7134 
7135     l_retained_amount			NUMBER;
7136     l_recouped_amount			NUMBER;
7137     l_invoice_rec			AP_APPROVAL_PKG.Invoice_Rec;
7138     l_invoice_date               	AP_INVOICES.invoice_date%TYPE;
7139     l_invoice_currency_code      	AP_INVOICES.invoice_currency_code%TYPE;
7140     l_exchange_rate              	AP_INVOICES.exchange_rate%TYPE;
7141     l_exchange_rate_type         	AP_INVOICES.exchange_rate_type%TYPE;
7142     l_exchange_date              	AP_INVOICES.exchange_date%TYPE;
7143     l_tolerance_id			AP_SUPPLIER_SITES_ALL.TOLERANCE_ID%TYPE;
7144     l_services_tolerance_id		AP_SUPPLIER_SITES_ALL.SERVICES_TOLERANCE_ID%TYPE;
7145 
7146     Tax_Exception                 	EXCEPTION;
7147 
7148     CURSOR SELECTED_INVOICES_CURSOR  IS
7149     SELECT
7150          I.invoice_id,
7151          I.invoice_num,
7152          I.org_id,
7153          I.invoice_amount,
7154          I.base_amount,
7155          I.exchange_rate,
7156          I.invoice_currency_code,
7157          S.invoice_amount_limit,
7158          nvl(S.hold_future_payments_flag,'N') hold_future_payments_flag,
7159          I.invoice_type_lookup_code,
7160          I.exchange_date,
7161          I.exchange_rate_type,
7162          I.vendor_id,
7163          I.invoice_date,
7164          nvl(I.disc_is_inv_less_tax_flag,'N') disc_is_inv_less_tax_flag,
7165          nvl(I.exclude_freight_from_discount,'N') exclude_freight_from_discount,
7166          S.tolerance_id,
7167          s.services_tolerance_id
7168     FROM   ap_invoices_all I,
7169 	   ap_supplier_sites_all S
7170     WHERE  I.vendor_site_id = S.vendor_site_id (+)
7171     AND    I.validation_request_id = AP_APPROVAL_PKG.G_VALIDATION_REQUEST_ID
7172     ORDER BY I.org_id;
7173 
7174     l_api_name CONSTANT VARCHAR2(200) := 'Batch_Approval';
7175 
7176 -- Start for bug 6511249
7177     CURSOR SELC_INV_CURSOR_BULK_ERROR  IS
7178     SELECT I.invoice_id, i.invoice_num, i.org_id
7179     FROM   ap_invoices_all I,
7180            ap_supplier_sites_all S
7181     WHERE  I.vendor_site_id = S.vendor_site_id (+)
7182     AND    I.validation_request_id = AP_APPROVAL_PKG.G_VALIDATION_REQUEST_ID
7183     ORDER  BY I.org_id;
7184 
7185     TYPE selc_inv_cursor_blk_err is table of selc_inv_cursor_bulk_error%rowtype;
7186 
7187     l_selc_inv_cursor_blk_err	selc_inv_cursor_blk_err;
7188     l_blk_err  		  	varchar2(1):='N';
7189     l_errbuf   		  	varchar2(200);
7190     l_conc_status   	  	varchar2(10);
7191     l_set_status          	boolean;
7192     Tax_Exception_Handled 	Exception;
7193     Tax_Dist_Exception_Handled  Exception;
7194 -- End for bug 6511249
7195 
7196      -- 7461423
7197      TYPE var_cur IS REF CURSOR;
7198      bat_inv_ref_cursor var_cur;
7199 
7200 BEGIN
7201     IF (p_debug_switch = 'Y') THEN
7202         g_debug_mode := 'Y';
7203     END IF;
7204 
7205     ---------------------------------------------------------------------
7206     Print_Debug(l_api_name, 'AP_APPROVAL_PKG.BATCH_APPROVAL.BEGIN');
7207     ---------------------------------------------------------------------
7208 
7209     ap_approval_pkg.g_validation_request_id := p_conc_request_id;
7210     g_org_holds.delete;
7211 
7212     ---------------------------------------------------------------------
7213     Print_Debug(l_api_name, 'Setting null input parameters');
7214     ---------------------------------------------------------------------
7215     l_inv_batch_id	:= NVL(p_inv_batch_id,-1);
7216     l_vendor_id		:= NVL(p_vendor_id,-1);
7217     l_pay_group		:= NVL(p_pay_group,'All');
7218     l_invoice_id	:= NVL(p_invoice_id,-1);
7219     l_entered_by	:= NVL(p_entered_by,-999);
7220     l_commit_size	:= NVL(p_commit_size,1000);
7221     l_org_id		:= NVL(p_org_id, -3115);
7222 
7223     ---------------------------------------------------------------------
7224     Print_Debug(l_api_name, 'Clean-up validation_request_id');
7225     ---------------------------------------------------------------------
7226     UPDATE ap_invoices api
7227        SET validation_request_id = NULL
7228      WHERE validation_request_id IS NOT NULL
7229        AND EXISTS
7230                ( SELECT 'Request Completed'
7231                    FROM fnd_concurrent_requests fcr
7232                   WHERE fcr.request_id = api.validation_request_id
7233                     AND fcr.phase_code = 'C' );
7234 
7235     ---------------------------------------------------------------------
7236     Print_Debug(l_api_name, 'Cache System Options');
7237     ---------------------------------------------------------------------
7238     AP_Approval_PKG.Cache_Options(l_curr_calling_sequence);
7239 
7240 
7241     IF (l_invoice_id <> -1) THEN
7242 
7243         IF validate_period(l_invoice_id) THEN  /*bug6858309 - changed location of the call*/
7244 
7245         ---------------------------------------------------------------------
7246         Print_Debug(l_api_name, 'Begin Approving Single Invoice');
7247         ---------------------------------------------------------------------
7248 
7249 /* 6699825/6684139: Added the AND condition to check if the invoice has any
7250    lines. Otherwise, we will not proceed with validating the invoice */
7251 
7252         UPDATE ap_invoices_all ai
7253            SET ai.validation_request_id = p_conc_request_id
7254          WHERE ai.invoice_id = l_invoice_id
7255            AND ai.validation_request_id IS NULL
7256 		   /*bug 7029877 Invoice saved but not submitted*/
7257            AND ai.approval_ready_flag <>'S'
7258            AND EXISTS (select ail.invoice_id
7259                        from ap_invoice_lines_all ail
7260                        where ail.invoice_id = ai.invoice_id) ;
7261 
7262          --  bug 6351170 -Added below if condition  -  Return if there are no invoices to process
7263         IF sql%rowcount = 0 THEN
7264            RETURN true;
7265         END IF;
7266 
7267         COMMIT;
7268 
7269         BEGIN
7270 	     SELECT
7271 		  ai.invoice_num, ai.org_id, ai.invoice_type_lookup_code, ai.validation_request_id,
7272                   ai.invoice_id,  ai.invoice_date, ai.invoice_currency_code, ai.exchange_rate,
7273                   ai.exchange_rate_type, ai.exchange_date, ai.vendor_id, ai.org_id, s.tolerance_id,
7274 		  s.services_tolerance_id
7275              INTO
7276 		  l_invoice_num, l_sel_org_id, l_sel_invoice_type, l_validation_request_id,
7277                   l_invoice_id, l_invoice_date, l_invoice_currency_code, l_exchange_rate,
7278                   l_exchange_rate_type, l_exchange_date, l_vendor_id, l_org_id, l_tolerance_id,
7279 		  l_services_tolerance_id
7280 	     FROM ap_invoices_all ai,
7281 		  ap_supplier_sites_all s
7282 	    WHERE ai.invoice_id = l_invoice_id
7283 	      AND ai.vendor_site_id = s.vendor_site_id(+);
7284 	EXCEPTION
7285 	    WHEN OTHERS THEN
7286 	           Print_Debug(l_api_name, 'Invoice Number Not Found');
7287 	           RETURN(FALSE);
7288         END;
7289 
7290         mo_global.set_policy_context('S', l_sel_org_id);
7291 
7292         ---------------------------------------------------------------------
7293         Print_Debug (l_api_name, 'Calculate Tax');
7294         ---------------------------------------------------------------------
7295         l_success := ap_etax_pkg.calling_etax(
7296                            p_invoice_id         => NULL,
7297                            p_calling_mode       => 'CALCULATE',
7298                            p_all_error_messages => 'N',
7299                            p_error_code         => l_error_code,
7300                            p_calling_sequence   => l_curr_calling_sequence);
7301 
7302         IF (NOT l_success) THEN
7303             RAISE Tax_Exception;
7304         END IF;
7305 
7306         ----------------------------------------------------------------
7307         Print_Debug(l_api_name, 'Initialize Invoice Holds Array');
7308         ----------------------------------------------------------------
7309         Initialize_Invoice_Holds(
7310                         p_invoice_id       => l_invoice_id,
7311                         p_calling_sequence => l_curr_calling_sequence);
7312 
7313         ---------------------------------------------------------------------
7314         Print_Debug (l_api_name, 'Generate Distributions');
7315         ---------------------------------------------------------------------
7316 
7317         l_invoice_rec.invoice_id               := l_invoice_id;
7318         l_invoice_rec.invoice_date             := l_invoice_date;
7319         l_invoice_rec.invoice_currency_code    := l_invoice_currency_code;
7320         l_invoice_rec.exchange_rate            := l_exchange_rate;
7321         l_invoice_rec.exchange_rate_type       := l_exchange_rate_type;
7322         l_invoice_rec.exchange_date            := l_exchange_date;
7323         l_invoice_rec.vendor_id                := l_vendor_id;
7324         l_invoice_rec.org_id                   := l_org_id;
7325 	g_org_id 			       := l_org_id;
7326 
7327 
7328         AP_APPROVAL_PKG.Generate_Distributions
7329                                 (p_invoice_rec        => l_invoice_rec,
7330                                  p_base_currency_code => AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_org_id).base_currency_code,
7331                                  p_inv_batch_id       => p_inv_batch_id,
7332                                  p_run_option         => p_run_option,
7333                                  p_calling_sequence   => l_curr_calling_sequence,
7334                                  x_error_code         => l_error_code);
7335 
7336        ---------------------------------------------------------------------
7337        Print_Debug (l_api_name, 'Generate Tax Distributions');
7338        ---------------------------------------------------------------------
7339        l_success := ap_etax_pkg.calling_etax (
7340                            p_invoice_id         => NULL,
7341                            p_calling_mode       => 'DISTRIBUTE',
7342                            p_all_error_messages => 'N',
7343                            p_error_code         => l_error_code,
7344                            p_calling_sequence   => l_curr_calling_sequence);
7345 
7346        IF (NOT l_success) THEN
7347            RAISE Tax_Exception;
7348        END IF;
7349 
7350 
7351         IF l_sel_invoice_type = 'PAYMENT REQUEST' THEN
7352            l_calling_mode := 'PAYMENT REQUEST';
7353         ELSE
7354            l_calling_mode := 'APPROVE';
7355         END IF;
7356 
7357         ---------------------------------------------------------------------
7358         Print_Debug(l_api_name, 'Approving specified invoice : '||l_invoice_num);
7359         ---------------------------------------------------------------------
7360 
7361         IF l_validation_request_id = p_conc_request_id THEN
7362 
7363            --IF validate_period(l_invoice_id) THEN  /*commented  for bug 6858309*/
7364 
7365               -- Cache Templates
7366               Cache_Tolerance_Templates(
7367                         l_tolerance_id,
7368                         l_services_tolerance_id,
7369                         l_calling_sequence);
7370 
7371               --Removed the hardcoded value of p_budget_control, bug6356402
7372               AP_APPROVAL_PKG.APPROVE(
7373 				'',
7374                                 '',
7375   				'',
7376 				'',
7377 				'',
7378 				'',
7379 				l_invoice_id,
7380 				'',
7381 				'',
7382 				'',
7383 				'Y',
7384 				l_holds_count,
7385 				l_approval_status,
7386                         	l_funds_return_code,
7387                         	l_calling_mode,
7388 				'APXAPRVL',
7389                         	p_debug_switch
7390                         	);
7391           /*commented for bug 6858309
7392 	   ELSE
7393             fnd_message.set_name('SQLAP', 'AP_INV_NEVER_OPEN_PERIOD');
7394             fnd_message.set_token('INV_NUM', l_invoice_num);
7395             fnd_file.put_line(fnd_file.log, fnd_message.get);
7396            END IF;   */
7397 
7398            UPDATE ap_invoices_all
7399               SET validation_request_id = NULL
7400             WHERE invoice_id = l_invoice_id;
7401 
7402         END IF;
7403 
7404       ELSE  /*bug6858309- changed location of the call*/
7405             fnd_message.set_name('SQLAP', 'AP_INV_NEVER_OPEN_PERIOD');
7406             fnd_message.set_token('INV_NUM', l_invoice_num);
7407             fnd_file.put_line(fnd_file.log, fnd_message.get);
7408 
7409       END IF;  --if validate_period(p_invoice_id)
7410 
7411         ---------------------------------------------------------------------
7412         Print_Debug(l_api_name, 'End Approving Single Invoice');
7413         ---------------------------------------------------------------------
7414 
7415     ELSE -- Invoice_id is null case -- Marker 0
7416 
7417         ---------------------------------------------------------------------
7418         Print_Debug(l_api_name, 'Batch Approval Start');
7419         ---------------------------------------------------------------------
7420 
7421        /*bug6858309 modified this dynamic update to filter out
7422          recurring invoices havign GL DATE in never open period*/
7423        /* Added for bug#7270053 Start */
7424         l_sql_stmt :=l_sql_stmt||
7425 		'SELECT  invoice_id from AP_INVOICES_ALL AI '||  -- 7461423
7426 		' WHERE AI.VALIDATION_REQUEST_ID IS NULL '||
7427 		'   AND AI.APPROVAL_READY_FLAG <> ''S'' '||
7428 		'   AND (UPPER(NVL(AI.SOURCE, ''X'')) <> ''RECURRING INVOICE'' OR '||
7429 		'       (UPPER(NVL(AI.SOURCE, ''X'')) = ''RECURRING INVOICE'' AND NOT EXISTS '||
7430 		'        (SELECT NULL '||
7431 		'            FROM GL_PERIOD_STATUSES GLPS, AP_SYSTEM_PARAMETERS SP '||
7432 		'           WHERE GLPS.APPLICATION_ID = ''200'' '||
7433 		'             AND SP.ORG_ID = AI.ORG_ID '||
7434 		'             AND GLPS.SET_OF_BOOKS_ID = SP.SET_OF_BOOKS_ID '||
7435 		'             AND TRUNC(AI.GL_DATE) BETWEEN GLPS.START_DATE AND GLPS.END_DATE '||
7436 		'             AND NVL(GLPS.ADJUSTMENT_PERIOD_FLAG, ''N'') = ''N'' '||
7437 		'             AND GLPS.CLOSING_STATUS = ''N''))) '||
7438 		'   AND NOT (AI.PAYMENT_STATUS_FLAG = ''Y'' AND '||
7439 		'            AI.HISTORICAL_FLAG = ''Y'') '||
7440 		'   AND (((  (  EXISTS '||
7441 		'               (SELECT 1 '||
7442 		'                  FROM AP_INVOICE_DISTRIBUTIONS D '||
7443 		'                 WHERE D.INVOICE_ID = AI.INVOICE_ID '||
7444 		'                   AND NVL(D.MATCH_STATUS_FLAG, ''N'') <> ''A''' ||
7445                 '               ) '||
7446                 '            OR EXISTS '||
7447 		'               (SELECT ''Unreleased Hold exists'' '||
7448 		'                     FROM AP_HOLDS H '||
7449 		'                    WHERE H.INVOICE_ID = AI.INVOICE_ID '||
7450 		'                      AND H.HOLD_LOOKUP_CODE IN '||
7451 		'                          (''QTY ORD'', ''QTY REC'', ''AMT ORD'', ''AMT REC'', ''QUALITY'', '||
7452 		'                           ''PRICE'', ''TAX DIFFERENCE'', ''CURRENCY DIFFERENCE'', '||
7453 		'                           ''REC EXCEPTION'', ''TAX VARIANCE'', ''PO NOT APPROVED'', '||
7454 		'                           ''PO REQUIRED'', ''MAX SHIP AMOUNT'', ''MAX RATE AMOUNT'', '||
7455 		'                           ''MAX TOTAL AMOUNT'', ''TAX AMOUNT RANGE'', ''MAX QTY ORD'', '||
7456 		'                           ''MAX QTY REC'', ''MAX AMT ORD'', ''MAX AMT REC'', '||
7457 		'                           ''CANT CLOSE PO'', ''CANT TRY PO CLOSE'', ''LINE VARIANCE'', '||
7458 		'                           ''CANT FUNDS CHECK'') '||
7459 		'                      AND H.RELEASE_LOOKUP_CODE IS NULL ' ||
7460 		'               ) '||
7461 		'            ) ' ||
7462 		'         OR '||
7463 		'            (AI.FORCE_REVALIDATION_FLAG = ''Y'')'||
7464 		'         ) '||
7465 		'      AND NOT EXISTS '||
7466 		'         (SELECT ''Cancelled distributions'' '||
7467 		'                   FROM AP_INVOICE_DISTRIBUTIONS_ALL D2 '||
7468 		'                  WHERE D2.INVOICE_ID = AI.INVOICE_ID '||
7469 		'                   AND D2.CANCELLATION_FLAG = ''Y'''||
7470 		'         )'||
7471 		'       )  '||
7472 		'    OR EXISTS '||
7473 		'       (SELECT 1 '||
7474 		'           FROM AP_INVOICE_LINES AIL '||
7475 		'          WHERE AIL.INVOICE_ID = AI.INVOICE_ID '||
7476 		'            AND AI.CANCELLED_DATE IS NULL '||
7477 		'            AND NVL(AIL.DISCARDED_FLAG, ''N'') <> ''Y'' '||
7478 		'            AND NVL(AIL.CANCELLED_FLAG, ''N'') <> ''Y'' '||
7479 		'            AND NOT EXISTS '||
7480 		'          (SELECT /*+ NO_UNNEST */ '||
7481 		'                  ''distributed line'' '||
7482 		'                   FROM AP_INVOICE_DISTRIBUTIONS_ALL D5 '||
7483 		'                  WHERE D5.INVOICE_ID = AIL.INVOICE_ID '||
7484 		'                    AND D5.INVOICE_LINE_NUMBER = AIL.LINE_NUMBER))) ' ;
7485          IF P_org_id IS NOT NULL THEN
7486            l_sql_stmt := l_sql_stmt|| 'AND AI.org_id = ' || l_org_id || ' ' ;
7487          END IF ;
7488          IF P_inv_batch_id IS NOT NULL THEN
7489            l_sql_stmt := l_sql_stmt|| 'AND AI.batch_id = ' || p_inv_batch_id || ' ' ;
7490          END IF ;
7491          IF P_vendor_id IS NOT NULL THEN
7492            l_sql_stmt := l_sql_stmt|| 'AND AI.vendor_id = ' || p_vendor_id || ' ' ;
7493          END IF ;
7494          IF P_inv_start_date IS NOT NULL AND P_inv_end_date IS NULL THEN
7495            l_sql_stmt := l_sql_stmt|| 'AND AI.invoice_date >= :b_start_date ' ;
7496          END IF ;
7497          IF P_inv_start_date IS NULL AND P_inv_end_date IS NOT NULL THEN
7498            l_sql_stmt := l_sql_stmt || 'AND AI.invoice_date <= :b_end_date ' ;
7499          END IF ;
7500          IF P_inv_start_date IS NOT NULL AND P_inv_end_date IS NOT NULL THEN
7501            IF P_inv_start_date  <> P_inv_end_date THEN
7502               l_sql_stmt := l_sql_stmt || 'AND AI.invoice_date BETWEEN :b_start_date AND :b_end_date ' ;
7503            ELSE
7504               l_sql_stmt := l_sql_stmt || 'AND AI.invoice_date = :b_start_date ' ;
7505            END IF ;
7506          END IF ;
7507          IF P_entered_by IS NOT NULL THEN
7508            l_sql_stmt := l_sql_stmt || ' AND AI.created_by = ' || l_entered_by || ' ' ;
7509          END IF ;
7510          IF P_pay_group IS NOT NULL THEN
7511            l_sql_stmt := l_sql_stmt || ' and AI.pay_group_lookup_code = ' || '''' || l_pay_group || '''' || ' ' ;
7512          END IF ;
7513 
7514 	 l_sql_stmt :=l_sql_stmt || ' FOR UPDATE SKIP LOCKED';
7515         ---------------------------------------------------------------------
7516         Print_Debug (l_api_name, l_sql_stmt);
7517         ---------------------------------------------------------------------
7518 
7519         IF p_inv_start_date IS NOT NULL OR p_inv_end_date IS NOT NULL
7520 	THEN
7521              IF (p_inv_start_date IS NOT NULL AND p_inv_end_date IS NOT NULL
7522 			     AND P_inv_start_date  <> P_inv_end_date) THEN		-- bug 7688696
7523 
7524               OPEN  bat_inv_ref_cursor FOR l_sql_stmt
7525               USING p_inv_start_date, p_inv_end_date; -- 7461423
7526 
7527 	     ELSE
7528 
7529               OPEN  bat_inv_ref_cursor FOR l_sql_stmt
7530               USING NVL(p_inv_start_date, p_inv_end_date); -- 7461423
7531 
7532 	     END IF;
7533 
7534 	ELSE
7535 	/* Added for bug#7270053 End */
7536            OPEN bat_inv_ref_cursor FOR l_sql_stmt; -- 7461423
7537 
7538         END IF;
7539 
7540          -- 7461423 to skip locked invoices
7541         FETCH bat_inv_ref_cursor
7542         BULK COLLECT INTO l_selected_invoice_ids;
7543         CLOSE bat_inv_ref_cursor;
7544 
7545         IF l_selected_invoice_ids.count > 0 THEN
7546 
7547           FOR k IN 1..l_selected_invoice_ids.count
7548           LOOP
7549 
7550               UPDATE ap_invoices_all
7551               SET validation_request_id = AP_APPROVAL_PKG.G_VALIDATION_REQUEST_ID
7552               WHERE  invoice_id = l_selected_invoice_ids(k)
7553               AND    validation_request_id IS NULL;
7554 
7555           END LOOP;
7556 
7557         ELSE
7558 
7559            RETURN true;
7560 
7561         END IF;
7562 
7563         COMMIT;
7564 
7565        ---------------------------------------------------------------------
7566        Print_Debug (l_api_name, 'Calculate Tax');
7567        ---------------------------------------------------------------------
7568 
7569        SAVEPOINT AP_APPROVAL_PKG_SP_ETAX;
7570 
7571        l_success := ap_etax_pkg.calling_etax(
7572                            p_invoice_id         => NULL,
7573                            p_calling_mode       => 'CALCULATE',
7574                            p_all_error_messages => 'N',
7575                            p_error_code         => l_error_code,
7576                            p_calling_sequence   => l_curr_calling_sequence);
7577 
7578        IF (NOT l_success) THEN  -- Marker 1
7579 
7580          ROLLBACK TO SAVEPOINT AP_APPROVAL_PKG_SP_ETAX;
7581 
7582          l_blk_err := 'Y';
7583 
7584          ---------------------------------------------------------------------
7585          Print_Debug (l_api_name, 'Set Concurrent Request Warning');
7586          ---------------------------------------------------------------------
7587 
7588          l_conc_status := 'WARNING';
7589          --bug 7512258 removed call to FND_CONCURRENT.SET_COMPLETION_STATUS
7590 
7591          ---------------------------------------------------------------------
7592          Print_Debug (l_api_name, 'Begin Single Mode');
7593          ---------------------------------------------------------------------
7594 
7595          OPEN  SELC_INV_CURSOR_BULK_ERROR;
7596          FETCH SELC_INV_CURSOR_BULK_ERROR
7597           BULK COLLECT INTO l_selc_inv_cursor_blk_err;
7598 
7599          UPDATE ap_invoices_all
7600             SET validation_request_id = NULL
7601           WHERE validation_request_id IS NOT NULL
7602             AND invoice_id IN (SELECT invoice_id
7603                                  FROM ap_invoices_all
7604                                 WHERE validation_request_id = AP_APPROVAL_PKG.G_VALIDATION_REQUEST_ID);
7605 
7606          FOR i IN 1..l_selc_inv_cursor_blk_err.count
7607          LOOP
7608 
7609            SAVEPOINT AP_APPROVAL_PKG_SP_INV;
7610 
7611 	   UPDATE ap_invoices_all
7612               SET validation_request_id = AP_APPROVAL_PKG.G_VALIDATION_REQUEST_ID
7613             WHERE invoice_id = l_selc_inv_cursor_blk_err(i).invoice_id;
7614 
7615            BEGIN
7616 
7617              BEGIN
7618                 SELECT
7619                    ai.invoice_num, ai.org_id, ai.invoice_type_lookup_code, ai.validation_request_id,
7620                    ai.invoice_id,  ai.invoice_date, ai.invoice_currency_code, ai.exchange_rate,
7621                    ai.exchange_rate_type, ai.exchange_date, ai.vendor_id, ai.org_id, s.tolerance_id,
7622                    s.services_tolerance_id
7623                 INTO
7624                    l_invoice_num, l_sel_org_id, l_sel_invoice_type, l_validation_request_id,
7625                    l_invoice_id, l_invoice_date, l_invoice_currency_code, l_exchange_rate,
7626                    l_exchange_rate_type, l_exchange_date, l_vendor_id, l_org_id, l_tolerance_id,
7627                    l_services_tolerance_id
7628                 FROM
7629                    ap_invoices_all ai,
7630                    ap_supplier_sites_all s
7631                 WHERE
7632                    ai.invoice_id = l_selc_inv_cursor_blk_err(i).invoice_id
7633                 AND
7634                    ai.vendor_site_id = s.vendor_site_id(+);
7635 
7636              EXCEPTION
7637                WHEN OTHERS THEN
7638                     Print_Debug(l_api_name, 'Invoice Number Not Found');
7639                     RAISE;
7640              END;
7641 
7642              mo_global.set_policy_context('S', l_sel_org_id);
7643 
7644             ---------------------------------------------------------------------
7645             Print_Debug (l_api_name, 'Calculate Tax');
7646             ---------------------------------------------------------------------
7647             l_success := ap_etax_pkg.calling_etax(
7648                            p_invoice_id         => NULL,
7649                            p_calling_mode       => 'CALCULATE',
7650                            p_all_error_messages => 'N',
7651                            p_error_code         => l_error_code,
7652                            p_calling_sequence   => l_curr_calling_sequence);
7653 
7654             IF (NOT l_success) THEN
7655                RAISE Tax_Exception_Handled;
7656             END IF;
7657 
7658             ----------------------------------------------------------------
7659             Print_Debug(l_api_name, 'Initialize Invoice Holds Array');
7660             ----------------------------------------------------------------
7661             Initialize_Invoice_Holds(
7662                         p_invoice_id       => l_invoice_id,
7663                         p_calling_sequence => l_curr_calling_sequence);
7664 
7665             ---------------------------------------------------------------------
7666             Print_Debug (l_api_name, 'Generate Distributions');
7667             ---------------------------------------------------------------------
7668 
7669             l_invoice_rec.invoice_id               := l_invoice_id;
7670             l_invoice_rec.invoice_date             := l_invoice_date;
7671             l_invoice_rec.invoice_currency_code    := l_invoice_currency_code;
7672             l_invoice_rec.exchange_rate            := l_exchange_rate;
7673             l_invoice_rec.exchange_rate_type       := l_exchange_rate_type;
7674             l_invoice_rec.exchange_date            := l_exchange_date;
7675             l_invoice_rec.vendor_id                := l_vendor_id;
7676             l_invoice_rec.org_id                   := l_org_id;
7677             g_org_id                               := l_org_id;
7678 
7679 
7680             AP_APPROVAL_PKG.Generate_Distributions
7681                                 (p_invoice_rec        => l_invoice_rec,
7682                                  p_base_currency_code => AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_org_id).base_currency_code,
7683                                  p_inv_batch_id       => p_inv_batch_id,
7684                                  p_run_option         => p_run_option,
7685                                  p_calling_sequence   => l_curr_calling_sequence,
7686                                  x_error_code         => l_error_code);
7687 
7688             ---------------------------------------------------------------------
7689             Print_Debug (l_api_name, 'Generate Tax Distributions');
7690             ---------------------------------------------------------------------
7691             l_success := ap_etax_pkg.calling_etax (
7692                            p_invoice_id         => NULL,
7693                            p_calling_mode       => 'DISTRIBUTE',
7694                            p_all_error_messages => 'N',
7695                            p_error_code         => l_error_code,
7696                            p_calling_sequence   => l_curr_calling_sequence);
7697 
7698             IF (NOT l_success) THEN
7699                RAISE  Tax_Exception_Handled;
7700             END IF;
7701 
7702             IF l_sel_invoice_type = 'PAYMENT REQUEST' THEN
7703                l_calling_mode := 'PAYMENT REQUEST';
7704             ELSE
7705                l_calling_mode := 'APPROVE';
7706             END IF;
7707 
7708             ---------------------------------------------------------------------
7709             Print_Debug(l_api_name, 'Approving specified invoice : '||l_selc_inv_cursor_blk_err(i).invoice_num);
7710             ---------------------------------------------------------------------
7711 
7712             IF l_validation_request_id = p_conc_request_id THEN
7713 
7714                IF validate_period(l_invoice_id) THEN
7715 
7716                  -- Cache Templates
7717                  Cache_Tolerance_Templates(
7718                         l_tolerance_id,
7719                         l_services_tolerance_id,
7720                         l_calling_sequence);
7721 
7722                    --Removed the hardcoded value of p_budget_control, bug6356402
7723                    AP_APPROVAL_PKG.APPROVE(
7724                                 '',
7725                                 '',
7726                                 '',
7727                                 '',
7728                                 '',
7729                                 '',
7730                                 l_invoice_id,
7731                                 '',
7732                                 '',
7733                                 '',
7734                                 'Y',
7735                                 l_holds_count,
7736                                 l_approval_status,
7737                                 l_funds_return_code,
7738                                 l_calling_mode,
7739                                 'APXAPRVL',
7740                                 p_debug_switch
7741                                 );
7742                 ELSE
7743                     fnd_message.set_name('SQLAP', 'AP_INV_NEVER_OPEN_PERIOD');
7744                     fnd_message.set_token('INV_NUM', l_invoice_num);
7745                     fnd_file.put_line(fnd_file.log, fnd_message.get);
7746                 END IF;
7747 
7748             END IF;
7749 		  -- BUG 7509921 Update Validation Request id to null
7750              UPDATE ap_invoices_all
7751              SET validation_request_id = NULL
7752             WHERE invoice_id = l_selc_inv_cursor_blk_err(i).invoice_id;
7753           --End 7509921
7754             ---------------------------------------------------------------------
7755             Print_Debug(l_api_name, 'End Approving Single Invoice');
7756             ---------------------------------------------------------------------
7757 
7758             EXCEPTION
7759             WHEN TAX_EXCEPTION_HANDLED THEN
7760 
7761                  ROLLBACK TO SAVEPOINT AP_APPROVAL_PKG_SP_INV;
7762 
7763                   ap_utilities_pkg.ap_get_message(l_approval_error);
7764                   fnd_file.put_line (fnd_file.log, ' ');
7765                   fnd_file.put_line (fnd_file.log, l_approval_error || 'Invoice Validation did not process Invoice Number: '|| l_invoice_num);
7766                   fnd_file.put_line (fnd_file.log, '  Error: ' ||sqlerrm);
7767                   Print_Debug (l_api_name, 'Exception: '|| sqlerrm ||' Invoice Validation did not process Invoice Number: '||
7768                                            l_invoice_num);
7769 
7770 
7771             WHEN OTHERS THEN
7772 
7773                  ROLLBACK TO SAVEPOINT AP_APPROVAL_PKG_SP_INV;
7774 
7775                   ap_utilities_pkg.ap_get_message(l_approval_error);
7776                   fnd_file.put_line (fnd_file.log, ' ');
7777                   fnd_file.put_line (fnd_file.log, l_approval_error || 'Invoice Validation did not process Invoice Number: '|| l_invoice_num);
7778                   fnd_file.put_line (fnd_file.log, '  Error: ' ||sqlerrm);
7779                   Print_Debug (l_api_name, 'Exception: '|| sqlerrm ||' Invoice Validation did not process Invoice Number: '||
7780                                            l_invoice_num);
7781 
7782             END;
7783          END LOOP;
7784 
7785          CLOSE SELC_INV_CURSOR_BULK_ERROR;
7786 
7787        END IF; -- Marker 1
7788 
7789 
7790        IF l_blk_err = 'N' THEN -- Marker 2
7791 
7792        ---------------------------------------------------------------------
7793        Print_Debug (l_api_name, 'Generate Distributions');
7794        ---------------------------------------------------------------------
7795 
7796        OPEN SELECTED_INVOICES_CURSOR;
7797        LOOP
7798          FETCH SELECTED_INVOICES_CURSOR
7799          BULK COLLECT INTO AP_APPROVAL_PKG.G_SELECTED_INVOICES
7800          LIMIT l_commit_size;
7801 
7802 	 EXIT WHEN SELECTED_INVOICES_CURSOR%NOTFOUND
7803                    AND AP_APPROVAL_PKG.G_SELECTED_INVOICES.COUNT <= 0;
7804 
7805          FOR i IN 1..AP_APPROVAL_PKG.G_SELECTED_INVOICES.COUNT
7806          LOOP
7807              -- Set Policy
7808              IF AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).org_id <> nvl(l_old_org_id, -3115) THEN
7809 
7810 		mo_global.set_policy_context
7811                         ('S', AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).org_id);
7812 
7813                 l_old_org_id := AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).org_id;
7814 
7815              END IF;
7816 
7817 	     -- Initialize Invoice Holds Array
7818 	     Initialize_Invoice_Holds(
7819 	                p_invoice_id       => AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).invoice_id,
7820 	                p_calling_sequence => l_curr_calling_sequence);
7821 
7822              g_org_id := AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).org_id;
7823 
7824              AP_APPROVAL_PKG.Generate_Distributions
7825 				(p_invoice_rec        => AP_APPROVAL_PKG.G_SELECTED_INVOICES(i),
7826 				 p_base_currency_code => AP_APPROVAL_PKG.G_OPTIONS_TABLE(g_org_id).base_currency_code,
7827 				 p_inv_batch_id	      => p_inv_batch_id,
7828 				 p_run_option	      => p_run_option,
7829 	                         p_calling_sequence   => l_curr_calling_sequence,
7830 				 x_error_code	      => l_error_code);
7831 
7832          END LOOP;
7833 
7834          AP_APPROVAL_PKG.G_SELECTED_INVOICES.DELETE;
7835 
7836        END LOOP;
7837        CLOSE SELECTED_INVOICES_CURSOR;
7838 
7839        ---------------------------------------------------------------------
7840        Print_Debug (l_api_name, 'Generate Tax Distributions');
7841        ---------------------------------------------------------------------
7842 
7843        SAVEPOINT AP_APPROVAL_PKG_SP_TAX_DIST;
7844 
7845        l_success := ap_etax_pkg.calling_etax (
7846                            p_invoice_id		=> NULL,
7847                            p_calling_mode	=> 'DISTRIBUTE',
7848                            p_all_error_messages => 'N',
7849                            p_error_code 	=> l_error_code,
7850                            p_calling_sequence 	=> l_curr_calling_sequence);
7851 
7852 
7853        IF (NOT l_success) THEN  -- Marker 3
7854 
7855          ROLLBACK TO SAVEPOINT AP_APPROVAL_PKG_SP_TAX_DIST;
7856 
7857          ---------------------------------------------------------------------
7858          Print_Debug (l_api_name, 'Set Concurrent Request Warning');
7859          ---------------------------------------------------------------------
7860 
7861          l_conc_status := 'WARNING';
7862          --bug 7512258 removed call to FND_CONCURRENT.SET_COMPLETION_STATUS
7863 
7864          ---------------------------------------------------------------------
7865          Print_Debug (l_api_name, 'Begin Single Mode');
7866          ---------------------------------------------------------------------
7867 
7868          OPEN  SELC_INV_CURSOR_BULK_ERROR;
7869          FETCH SELC_INV_CURSOR_BULK_ERROR
7870           BULK COLLECT INTO l_selc_inv_cursor_blk_err;
7871 
7872          UPDATE ap_invoices_all
7873             SET validation_request_id = NULL
7874           WHERE validation_request_id IS NOT NULL
7875             AND invoice_id IN (SELECT invoice_id
7876                                  FROM ap_invoices_all
7877                                 WHERE validation_request_id = AP_APPROVAL_PKG.G_VALIDATION_REQUEST_ID);
7878 
7879          FOR i IN 1..l_selc_inv_cursor_blk_err.count
7880          LOOP
7881 
7882            SAVEPOINT AP_APPROVAL_PKG_SP_TAX_DIST;
7883 
7884 	   UPDATE ap_invoices_all
7885               SET validation_request_id = AP_APPROVAL_PKG.G_VALIDATION_REQUEST_ID
7886             WHERE invoice_id = l_selc_inv_cursor_blk_err(i).invoice_id;
7887 
7888            BEGIN
7889 
7890              mo_global.set_policy_context('S', l_selc_inv_cursor_blk_err(i).org_id);
7891 
7892              ---------------------------------------------------------------------
7893              Print_Debug (l_api_name, 'Generate Tax Distributions: '||l_selc_inv_cursor_blk_err(i).invoice_id);
7894              ---------------------------------------------------------------------
7895              l_success := ap_etax_pkg.calling_etax (
7896                             p_invoice_id         => NULL,
7897                             p_calling_mode       => 'DISTRIBUTE',
7898                             p_all_error_messages => 'N',
7899                             p_error_code         => l_error_code,
7900                             p_calling_sequence   => l_curr_calling_sequence);
7901 
7902              IF (NOT l_success) THEN
7903                  RAISE  Tax_Dist_Exception_Handled;
7904              END IF;
7905 			--Bug 7509921
7906             IF l_sel_invoice_type = 'PAYMENT REQUEST' THEN
7907                l_calling_mode := 'PAYMENT REQUEST';
7908             ELSE
7909                l_calling_mode := 'APPROVE';
7910             END IF;
7911 
7912             ---------------------------------------------------------------------
7913             Print_Debug(l_api_name, 'Approving specified invoice : '||l_selc_inv_cursor_blk_err(i).invoice_num);
7914             ---------------------------------------------------------------------
7915 
7916             IF l_validation_request_id = p_conc_request_id THEN
7917 
7918                IF validate_period(l_invoice_id) THEN
7919 
7920                  -- Cache Templates
7921                  Cache_Tolerance_Templates(
7922                         l_tolerance_id,
7923                         l_services_tolerance_id,
7924                         l_calling_sequence);
7925 
7926                    --Removed the hardcoded value of p_budget_control, bug6356402
7927                    AP_APPROVAL_PKG.APPROVE(
7928                                 '',
7929                                 '',
7930                                 '',
7931                                 '',
7932                                 '',
7933                                 '',
7934                                 l_invoice_id,
7935                                 '',
7936                                 '',
7937                                 '',
7938                                 'Y',
7939                                 l_holds_count,
7940                                 l_approval_status,
7941                                 l_funds_return_code,
7942                                 l_calling_mode,
7943                                 'APXAPRVL',
7944                                 p_debug_switch
7945                                 );
7946                 ELSE
7947                     fnd_message.set_name('SQLAP', 'AP_INV_NEVER_OPEN_PERIOD');
7948                     fnd_message.set_token('INV_NUM', l_invoice_num);
7949                     fnd_file.put_line(fnd_file.log, fnd_message.get);
7950                 END IF;
7951 
7952             END IF;
7953           -- BUG 7509921 Update Validation Request id to null
7954             UPDATE ap_invoices_all
7955             SET validation_request_id = NULL
7956             WHERE invoice_id = l_selc_inv_cursor_blk_err(i).invoice_id;
7957           --End 7509921
7958             ---------------------------------------------------------------------
7959             Print_Debug(l_api_name, 'End Approving Single Invoice');
7960             ---------------------------------------------------------------------
7961 
7962 
7963            EXCEPTION
7964              WHEN TAX_DIST_EXCEPTION_HANDLED THEN
7965 
7966                   ROLLBACK TO SAVEPOINT AP_APPROVAL_PKG_SP_TAX_DIST;
7967 
7968                   ap_utilities_pkg.ap_get_message(l_approval_error);
7969 
7970                   fnd_file.put_line (fnd_file.log, ' ');
7971                   fnd_file.put_line (fnd_file.log, l_approval_error || 'Invoice Validation did not process Invoice Number: '||
7972                                            l_selc_inv_cursor_blk_err(i).invoice_num);
7973                   fnd_file.put_line (fnd_file.log, '  Error: ' ||sqlerrm);
7974                   Print_Debug (l_api_name, 'Exception: '|| sqlerrm ||' Invoice Validation did not process Invoice Number: '||
7975                                            l_selc_inv_cursor_blk_err(i).invoice_num);
7976 
7977              WHEN OTHERS THEN
7978 
7979                  ROLLBACK TO SAVEPOINT AP_APPROVAL_PKG_SP_TAX_DIST;
7980 
7981                  ap_utilities_pkg.ap_get_message(l_approval_error);
7982 
7983                  fnd_file.put_line (fnd_file.log, ' ');
7984                  fnd_file.put_line (fnd_file.log, l_approval_error || 'Invoice Validation did not process Invoice Number: '||
7985                                            l_selc_inv_cursor_blk_err(i).invoice_num);
7986                  fnd_file.put_line (fnd_file.log, '  Error: ' ||sqlerrm);
7987                  Print_Debug (l_api_name, 'Exception: '|| sqlerrm ||' Invoice Validation did not process Invoice Number: '||
7988                                            l_selc_inv_cursor_blk_err(i).invoice_num);
7989 
7990            END;
7991          END LOOP;
7992          CLOSE SELC_INV_CURSOR_BULK_ERROR;
7993 
7994        END IF; -- Marker 3
7995 
7996        ---------------------------------------------------------------------
7997        Print_Debug (l_api_name, 'Call Approve per invoice');
7998        ---------------------------------------------------------------------
7999 
8000        OPEN SELECTED_INVOICES_CURSOR;
8001        LOOP
8002          FETCH SELECTED_INVOICES_CURSOR
8003          BULK COLLECT INTO AP_APPROVAL_PKG.G_SELECTED_INVOICES
8004          LIMIT l_commit_size;
8005 
8006          EXIT WHEN SELECTED_INVOICES_CURSOR%NOTFOUND
8007                    and AP_APPROVAL_PKG.G_SELECTED_INVOICES.COUNT <= 0;
8008 
8009          FOR i IN 1..AP_APPROVAL_PKG.G_SELECTED_INVOICES.COUNT LOOP
8010 
8011            -- Set Policy
8012            IF AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).org_id <> nvl(l_old_org_id, -3115) THEN
8013 
8014               mo_global.set_policy_context('S', AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).org_id);
8015 
8016               l_old_org_id := AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).org_id;
8017 
8018            END IF;
8019 
8020            -- Set Calling Mode
8021            IF AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).invoice_type_lookup_code = 'PAYMENT REQUEST' THEN
8022               l_calling_mode := 'PAYMENT REQUEST';
8023            ELSE
8024               l_calling_mode := 'APPROVE';
8025 
8026                -- Cache Templates
8027                Cache_Tolerance_Templates(
8028 	                AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).tolerance_id,
8029 	                AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).services_tolerance_id,
8030 	                l_calling_sequence);
8031            END IF;
8032 
8033            -- Call Approve
8034            IF validate_period(
8035 	               AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).invoice_id) THEN
8036 
8037                --Removed the hardcoded value of p_budget_control, bug6356402
8038                AP_APPROVAL_PKG.approve(
8039 				'',
8040 	                        '',
8041   				'',
8042 				'',
8043 				'',
8044 				'',
8045 				AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).invoice_id,
8046 				'',
8047 				'',
8048 				'',
8049 				'Y',
8050 				l_holds_count,
8051 				l_approval_status,
8052 	                        l_funds_return_code,
8053 				l_calling_mode,
8054 				'APXAPRVL',
8055 	                        p_debug_switch
8056 	                        );
8057 
8058            ELSE
8059               fnd_message.set_name('SQLAP', 'AP_INV_NEVER_OPEN_PERIOD');
8060               fnd_message.set_token('INV_NUM',  AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).invoice_num);
8061               fnd_file.put_line(fnd_file.log, fnd_message.get);
8062            END IF;
8063 
8064            -- Update Validation Request_ID to NULL;
8065            UPDATE ap_invoices_all
8066               SET validation_request_id = NULL
8067             WHERE invoice_id = AP_APPROVAL_PKG.G_SELECTED_INVOICES(i).invoice_id;
8068 
8069          END LOOP;
8070 
8071 	 AP_APPROVAL_PKG.G_SELECTED_INVOICES.DELETE;
8072 
8073        END LOOP;
8074 
8075        CLOSE SELECTED_INVOICES_CURSOR;
8076 
8077     END IF; -- Marker 2
8078 
8079     END IF; -- Marker 0
8080 
8081     ---------------------------------------------------------------------
8082     Print_Debug (l_api_name, 'Populate ap_temp_approval_temp_gt');
8083     ---------------------------------------------------------------------
8084 
8085     DELETE FROM ap_temp_approval_gt;
8086 
8087     FORALL i in g_org_holds.first..g_org_holds.last
8088 	INSERT INTO ap_temp_approval_gt VALUES g_org_holds(i);
8089 
8090     COMMIT;
8091 
8092     ---------------------------------------------------------------------
8093     Print_Debug (l_api_name, 'Get the count of rows that will be printed');
8094     ---------------------------------------------------------------------
8095 
8096     SELECT count(*) into  p_report_holds_count
8097       FROM ap_temp_approval_gt
8098      WHERE number_holds_placed   <> 0
8099         OR number_holds_released <> 0;
8100 
8101     -- 7512258
8102     -- moved the call to end of the approval process
8103     ---------------------------------------------------------------------
8104      Print_Debug (l_api_name, 'Set Concurrent Request Warning');
8105     ---------------------------------------------------------------------
8106     IF l_conc_status = 'WARNING' THEN
8107        l_errbuf := 'Warning/Error message to be displayed';
8108        l_set_status := FND_CONCURRENT.SET_COMPLETION_STATUS(l_conc_status,l_errbuf);
8109     END IF;
8110 
8111 
8112     ---------------------------------------------------------------------
8113     Print_Debug(l_api_name, 'AP_APPROVAL_PKG.BATCH_APPROVAL.END');
8114     ---------------------------------------------------------------------
8115 
8116     RETURN(TRUE);
8117 
8118 EXCEPTION
8119 
8120 	WHEN TAX_EXCEPTION THEN
8121              AP_UTILITIES_PKG.AP_GET_MESSAGE(l_approval_error);
8122              fnd_file.put_line(fnd_file.log,l_approval_error);
8123              fnd_file.put_line(fnd_file.log,sqlerrm);
8124              Print_Debug(l_api_name, 'Exception: '||sqlerrm);
8125 
8126              --Bug7246971
8127 
8128              FND_MESSAGE.SET_NAME('SQLAP','AP_TAX_EXCEPTION');
8129              IF l_error_code IS NOT NULL THEN
8130                 FND_MESSAGE.SET_TOKEN('ERROR', l_error_code);
8131              ELSE
8132                 FND_MESSAGE.SET_TOKEN('ERROR', SQLERRM);
8133              END IF;
8134              FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
8135              FND_MESSAGE.SET_TOKEN('PARAMETERS',
8136                       'Run Option  = '|| p_run_option
8137 	              ||', Batch Id = '|| to_char(p_inv_batch_id)
8138 	              ||', Begin Date = '|| to_char(p_inv_start_date)
8139 	              ||', End Date = '|| to_char(p_inv_end_date)
8140 	              ||', Vendor Id = '|| to_char(p_vendor_id)
8141 	              ||', Pay Group = '|| p_pay_group
8142 	              ||', Invoice Id = '|| to_char(p_invoice_id)
8143 	              ||', Entered By = '|| to_char(p_entered_by)
8144 	              ||', Concurrent Request Id = '|| to_char(p_conc_request_id)
8145                       ||', Org Id = '|| to_char(p_org_id));
8146              APP_EXCEPTION.RAISE_EXCEPTION;
8147 
8148              --Bug7246971
8149 
8150              RETURN (FALSE);
8151 
8152 	WHEN OTHERS THEN
8153 	     AP_UTILITIES_PKG.AP_GET_MESSAGE(l_approval_error);
8154 	     fnd_file.put_line(fnd_file.log,l_approval_error);
8155 	     fnd_file.put_line(fnd_file.log,sqlerrm);
8156              Print_Debug(l_api_name, 'Others: Exception: '||sqlerrm);
8157 
8158              --Bug7246971
8159 
8160              IF (SQLCODE <> -20001) THEN
8161                 FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
8162                 FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
8163                 FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
8164                 FND_MESSAGE.SET_TOKEN('PARAMETERS',
8165                       'Run Option  = '|| p_run_option
8166 	              ||', Batch Id = '|| to_char(p_inv_batch_id)
8167 	              ||', Begin Date = '|| to_char(p_inv_start_date)
8168 	              ||', End Date = '|| to_char(p_inv_end_date)
8169 	              ||', Vendor Id = '|| to_char(p_vendor_id)
8170 	              ||', Pay Group = '|| p_pay_group
8171 	              ||', Invoice Id = '|| to_char(p_invoice_id)
8172 	              ||', Entered By = '|| to_char(p_entered_by)
8173 	              ||', Concurrent Request Id = '|| to_char(p_conc_request_id)
8174                       ||', Org Id = '|| to_char(p_org_id));
8175 
8176              END IF;
8177              APP_EXCEPTION.RAISE_EXCEPTION;
8178 
8179              --Bug7246971
8180 
8181 	     RETURN (FALSE);
8182 
8183 END BATCH_APPROVAL;
8184 
8185 PROCEDURE Cache_Options
8186             (p_calling_sequence              IN VARCHAR2) IS
8187 
8188     CURSOR C_Options_Query IS
8189     SELECT  nvl(gls.chart_of_accounts_id, -1) chart_of_accounts_id,
8190             nvl(sp.set_of_books_id, -1) set_of_books_id,
8191             nvl(sp.automatic_offsets_flag, 'N') automatic_offsets_flag,
8192             nvl(recalc_pay_schedule_flag, 'N') recalc_pay_schedule_flag,
8193             sp.liability_post_lookup_code liability_post_lookup_code,
8194             nvl(sp.rate_var_gain_ccid, -1) rate_var_gain_ccid,
8195             nvl(sp.rate_var_loss_ccid, -1) rate_var_loss_ccid,
8196             nvl(sp.base_currency_code, 'USD') base_currency_code,
8197             nvl(sp.match_on_tax_flag, 'N') match_on_tax_flag,
8198             nvl(sp.enforce_tax_from_account, 'N') enforce_tax_from_account,
8199             nvl(fp.inv_encumbrance_type_id, -1) inv_encumbrance_type_id,
8200             nvl(fp.purch_encumbrance_type_id, -1) purch_encumbrance_type_id,
8201             nvl(fp.receipt_acceptance_days, 0) receipt_acceptance_days,
8202             nvl(gl_date_from_receipt_flag, 'S') gl_date_from_receipt_flag,
8203             accounting_method_option,
8204             secondary_accounting_method,
8205             nvl(fp.cash_basis_enc_nr_tax, 'EXCLUDE RECOVERABLE TAX') cash_basis_enc_nr_tax,
8206             nvl(fp.non_recoverable_tax_flag, 'N') non_recoverable_tax_flag,
8207             nvl(disc_is_inv_less_tax_flag,'N') disc_is_inv_less_tax_flag,
8208             fp.org_id org_id,
8209             5 System_User,
8210             fnd_global.user_id User_Id
8211     FROM    ap_system_parameters_all sp,
8212             financials_system_params_all fp,
8213             gl_sets_of_books gls,
8214             Mo_Glob_Org_Access_Tmp mo
8215     WHERE   sp.set_of_books_id = gls.set_of_books_id
8216     AND     sp.org_id = fp.org_id
8217     AND     mo.organization_id = fp.org_id;
8218 
8219     l_options_rec C_Options_Query%rowtype;
8220 
8221     l_debug_loc	 		VARCHAR2(30) 	:= 'Cache_Options';
8222     l_curr_calling_sequence	VARCHAR2(2000);
8223     l_debug_info		VARCHAR2(1000);
8224   BEGIN
8225 
8226     l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||p_calling_sequence;
8227 
8228     ------------------------------------------------------------
8229     l_debug_info := 'Retrieving system parameters for approval';
8230     Print_Debug(l_debug_loc,l_debug_info);
8231     ------------------------------------------------------------
8232 
8233      OPEN C_Options_Query;
8234      LOOP
8235        FETCH C_Options_Query INTO l_options_rec;
8236        EXIT WHEN C_Options_Query%NOTFOUND;
8237 
8238          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).chart_of_accounts_id
8239           := l_options_rec.chart_of_accounts_id;
8240          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).set_of_books_id
8241           := l_options_rec.set_of_books_id;
8242          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).automatic_offsets_flag
8243           := l_options_rec.automatic_offsets_flag;
8244          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).recalc_pay_schedule_flag
8245           := l_options_rec.recalc_pay_schedule_flag;
8246          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).liability_post_lookup_code
8247           := l_options_rec.liability_post_lookup_code;
8248          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).rate_var_gain_ccid
8249           := l_options_rec.rate_var_gain_ccid;
8250          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).rate_var_loss_ccid
8251           := l_options_rec.rate_var_loss_ccid;
8252          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).base_currency_code
8253           := l_options_rec.base_currency_code;
8254          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).match_on_tax_flag
8255           := l_options_rec.match_on_tax_flag;
8256          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).enforce_tax_from_account
8257           := l_options_rec.enforce_tax_from_account;
8258          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).inv_encumbrance_type_id
8259           := l_options_rec.inv_encumbrance_type_id;
8260          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).purch_encumbrance_type_id
8261           := l_options_rec.purch_encumbrance_type_id;
8262          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).receipt_acceptance_days
8263           := l_options_rec.receipt_acceptance_days;
8264          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).gl_date_from_receipt_flag
8265           := l_options_rec.gl_date_from_receipt_flag;
8266          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).accounting_method_option
8267           := l_options_rec.accounting_method_option;
8268          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).secondary_accounting_method
8269           := l_options_rec.secondary_accounting_method;
8270          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).cash_basis_enc_nr_tax
8271           := l_options_rec.cash_basis_enc_nr_tax;
8272          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).non_recoverable_tax_flag
8273           := l_options_rec.non_recoverable_tax_flag;
8274          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).disc_is_inv_less_tax_flag
8275           := l_options_rec.disc_is_inv_less_tax_flag;
8276          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).org_id
8277           := l_options_rec.org_id;
8278          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).System_User
8279           := l_options_rec.System_User;
8280          AP_APPROVAL_PKG.G_OPTIONS_TABLE(l_options_rec.org_id).user_id
8281           := l_options_rec.user_id;
8282 
8283      END LOOP;
8284      CLOSE C_Options_Query;
8285 
8286   EXCEPTION
8287     WHEN OTHERS THEN
8288       IF (SQLCODE <> -20001) THEN
8289         FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
8290         FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
8291         FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
8292         FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
8293       END IF;
8294 
8295       IF C_Options_Query%ISOPEN THEN
8296          CLOSE C_Options_Query;
8297       END IF;
8298 
8299       APP_EXCEPTION.RAISE_EXCEPTION;
8300 
8301   END Cache_Options;
8302 
8303 
8304 PROCEDURE Cache_Tolerance_Templates
8305             ( p_tolerance_id                  IN NUMBER,
8306               p_services_tolerance_id         IN NUMBER,
8307               p_calling_sequence              IN VARCHAR2) IS
8308     l_debug_loc	 		VARCHAR2(30) 	:= 'Cache_Tolerance_Templates';
8309     l_curr_calling_sequence	VARCHAR2(2000);
8310     l_debug_info		VARCHAR2(1000);
8311   BEGIN
8312 
8313     l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||p_calling_sequence;
8314 
8315     ------------------------------------------------------------
8316     l_debug_info := 'Retrieving Supplier Site Tolerances';
8317     Print_Debug(l_debug_loc,l_debug_info);
8318     ------------------------------------------------------------
8319 
8320     IF p_tolerance_id IS NOT NULL THEN
8321 
8322        IF NOT G_GOODS_TOLERANCES.exists(p_tolerance_id) THEN
8323 
8324           SELECT decode( price_tolerance, NULL, NULL,
8325                     (1 + (price_tolerance/100))),
8326                  decode(quantity_tolerance, NULL, NULL,
8327                     (1 + (quantity_tolerance/100))),
8328                  decode( qty_received_tolerance, NULL, NULL,
8329                    (1 + (qty_received_tolerance/100))),
8330                  max_qty_ord_tolerance,
8331                  max_qty_rec_tolerance,
8332                  ship_amt_tolerance,
8333                  rate_amt_tolerance,
8334                  total_amt_tolerance
8335           INTO   G_GOODS_TOLERANCES(p_tolerance_id).price_tolerance,
8336                  G_GOODS_TOLERANCES(p_tolerance_id).quantity_tolerance,
8337                  G_GOODS_TOLERANCES(p_tolerance_id).qty_received_tolerance,
8338                  G_GOODS_TOLERANCES(p_tolerance_id).max_qty_ord_tolerance,
8339                  G_GOODS_TOLERANCES(p_tolerance_id).max_qty_rec_tolerance,
8340                  G_GOODS_TOLERANCES(p_tolerance_id).ship_amt_tolerance,
8341                  G_GOODS_TOLERANCES(p_tolerance_id).rate_amt_tolerance,
8342                  G_GOODS_TOLERANCES(p_tolerance_id).total_amt_tolerance
8343           FROM   ap_tolerance_templates
8344           WHERE  tolerance_id = p_tolerance_id;
8345 
8346        END IF;
8347     END IF;
8348 
8349     IF p_services_tolerance_id IS NOT NULL THEN
8350        IF NOT G_SERVICES_TOLERANCES.exists(p_services_tolerance_id) THEN
8351           SELECT decode(quantity_tolerance, NULL, NULL,
8352                     (1 + (quantity_tolerance/100))),
8353                  decode( qty_received_tolerance, NULL, NULL,
8354                    (1 + (qty_received_tolerance/100))),
8355                  max_qty_ord_tolerance,
8356                  max_qty_rec_tolerance,
8357                  ship_amt_tolerance,
8358                  rate_amt_tolerance,
8359                  total_amt_tolerance
8360           INTO   G_SERVICES_TOLERANCES(p_services_tolerance_id).amount_tolerance,
8361                  G_SERVICES_TOLERANCES(p_services_tolerance_id).amt_received_tolerance,
8362                  G_SERVICES_TOLERANCES(p_services_tolerance_id).max_amt_ord_tolerance,
8363                  G_SERVICES_TOLERANCES(p_services_tolerance_id).max_amt_rec_tolerance,
8364                  G_SERVICES_TOLERANCES(p_services_tolerance_id).ser_ship_amt_tolerance,
8365                  G_SERVICES_TOLERANCES(p_services_tolerance_id).ser_rate_amt_tolerance,
8366                  G_SERVICES_TOLERANCES(p_services_tolerance_id).ser_total_amt_tolerance
8367           FROM   ap_tolerance_templates
8368           WHERE  tolerance_id = p_services_tolerance_id;
8369        END IF;
8370     END IF;
8371 
8372 EXCEPTION
8373     WHEN OTHERS THEN
8374       IF (SQLCODE <> -20001) THEN
8375         FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
8376         FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
8377         FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
8378         FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
8379       END IF;
8380       APP_EXCEPTION.RAISE_EXCEPTION;
8381 END Cache_Tolerance_Templates;
8382 
8383 PROCEDURE Generate_Distributions
8384                 (p_invoice_rec      	IN AP_APPROVAL_PKG.Invoice_Rec,
8385 		 p_base_currency_code	IN VARCHAR2,
8386 		 p_inv_batch_id	    	IN NUMBER,
8387                  p_run_option       	IN VARCHAR2,
8388                  p_calling_sequence 	IN VARCHAR2,
8389                  x_error_code       	IN VARCHAR2,
8390 		 p_calling_mode         IN VARCHAR2  ) IS     /*bug 6833543 - added p_calling_mode*/
8391 
8392   t_inv_lines_table             AP_INVOICES_PKG.t_invoice_lines_table;
8393 
8394   l_curr_calling_sequence       VARCHAR2(2000);
8395   l_debug_info		  	VARCHAR2(2000);
8396   l_debug_loc                   VARCHAR2(30) := 'Generate_Distributions';
8397 
8398   l_prorate_across_all_items    VARCHAR2(1);
8399   l_error_code                  VARCHAR2(4000);
8400   l_debug_context               VARCHAR2(2000);
8401   l_success                     BOOLEAN;
8402 
8403   l_system_user                 NUMBER := 5;
8404 
8405   l_holds                       HOLDSARRAY;
8406   l_hold_count                  COUNTARRAY;
8407   l_release_count               COUNTARRAY;
8408   l_insufficient_data_exist     BOOLEAN := FALSE;
8409 
8410   l_recouped_amount             NUMBER;
8411   l_retained_amount		NUMBER;
8412   l_result                      BOOLEAN;
8413 
8414   l_line_variance_hold_exist    BOOLEAN := FALSE;
8415   l_need_to_round_flag          VARCHAR2(1) := 'Y';
8416 
8417   l_not_exist_nond_line         VARCHAR2(1);   --bug6783517
8418 
8419   -- bug6783517 starts
8420   CURSOR dist_gen_holds(p_invoice_id NUMBER)
8421       IS
8422   SELECT hold_lookup_code
8423     FROM ap_holds_all
8424    WHERE hold_lookup_code IN ('DISTRIBUTION SET INACTIVE',
8425                               'SKELETON DISTRIBUTION SET',
8426                               'CANNOT OVERLAY ACCOUNT',
8427                               'INVALID DEFAULT ACCOUNT',
8428                               'CANNOT EXECUTE ALLOCATION',
8429                               'CANNOT OVERLAY ACCOUNT',
8430                               'INVALID DEFAULT ACCOUNT',
8431                               'PERIOD CLOSED',
8432                               'PROJECT GL DATE CLOSED')
8433      AND release_lookup_code IS NULL
8434      AND invoice_id = p_invoice_id;
8435 
8436   TYPE holds_tab_type IS
8437   TABLE OF AP_HOLDS_ALL.HOLD_LOOKUP_CODE%TYPE
8438   INDEX BY BINARY_INTEGER;
8439 
8440   t_holds_tab                    holds_tab_type;
8441   -- bug6783517 ends
8442 
8443 BEGIN
8444 
8445       l_curr_calling_sequence := 'AP_APPROVAL_PKG.'||l_debug_loc||'<-'||p_calling_sequence;
8446 
8447       ----------------------------------------------------------------
8448       l_debug_info := 'Check Line Variance at invoice header level';
8449       Print_Debug(l_debug_loc, l_debug_info);
8450       ----------------------------------------------------------------
8451 
8452       Check_Line_Variance(
8453           p_invoice_rec.invoice_id,
8454           l_system_user,
8455           l_holds,
8456           l_hold_count,
8457           l_release_count,
8458           l_line_variance_hold_exist,
8459           l_curr_calling_sequence,
8460 	  p_base_currency_code);        --bug 7271262
8461 
8462       IF ( p_invoice_rec.invoice_currency_code <> p_base_currency_code ) THEN
8463 
8464         ----------------------------------------------------------------
8465         l_debug_info := 'Calculate Base Amount. Round if no line variance';
8466         Print_Debug(l_debug_loc, l_debug_info);
8467         ----------------------------------------------------------------
8468 
8469         IF ( l_line_variance_hold_exist ) THEN
8470           l_need_to_round_flag := 'N';
8471         END IF;
8472 
8473         Line_Base_Amount_Calculation(
8474             p_invoice_id            => p_invoice_rec.invoice_id,
8475             p_invoice_currency_code => p_invoice_rec.invoice_currency_code,
8476             p_base_currency_code    => p_base_currency_code,
8477             p_exchange_rate         => p_invoice_rec.exchange_rate,
8478             p_need_to_round_flag    => l_need_to_round_flag,
8479             p_calling_sequence      => l_curr_calling_sequence);
8480 
8481       END IF;
8482 
8483       ----------------------------------------------------------------
8484       l_debug_info := 'Bulk Collect Invoice Lines';
8485       Print_Debug(l_debug_loc, l_debug_info);
8486       ----------------------------------------------------------------
8487 
8488       OPEN  Invoice_Line_Cur (p_invoice_rec.invoice_id);
8489       FETCH Invoice_Line_Cur BULK COLLECT
8490       INTO  t_inv_lines_table;
8491       CLOSE Invoice_Line_Cur;
8492 
8493       /* There are some holds which are put on the invoice when */
8494       /* the distributions are generated for the Invoice        */
8495       /* But even after the fix in the bug6731107, if a distribution */
8496       /* is inserted for the Invoice, then the generate_dist flag */
8497       /* for the line is set to 'D', and hence the code         */
8498       /* Execute_Dist_Generation_Check would no longer be called */
8499       /*
8500       /* As such, when there are no lines on the invoice         */
8501       /* for which the generate_dist flag is NOT 'D' then we would */
8502       /* release all the holds on the Invoice which are put during */
8503       /* the dist generation process : bug6783517 */
8504 
8505 
8506       l_debug_info := 'Checking if there exists a non d line';
8507 
8508       BEGIN
8509 
8510         SELECT 'Y'
8511           INTO l_not_exist_nond_line
8512           FROM ap_invoice_lines_all ail
8513          WHERE ail.invoice_id     = p_invoice_rec.invoice_id
8514            AND nvl(ail.generate_dists, 'N') <> 'D'
8515            AND rownum < 2;
8516 
8517       EXCEPTION
8518         WHEN NO_DATA_FOUND THEN
8519            l_not_exist_nond_line := 'N';
8520 
8521       END;
8522 
8523        /*bug 6833543: While cancelling an invoice that has a non D line
8524         and postable hold which is not user releasable like CANNOT EXECUTE
8525 	ALLOCATION, the code failed to release the holds
8526 	and the invoice gets stuck in a semi-cancelled state.Fix of
8527 	6783517 has to take care of releasing holds in such scenario i.e
8528 	when p_calling_mode is CANCEL*/
8529 
8530       l_debug_info := 'If there is no non d line or p_calling_mode is CANCEL, then fetch all the dist gen holds';
8531 
8532       IF (l_not_exist_nond_line = 'N' OR p_calling_mode = 'CANCEL') THEN
8533         OPEN  dist_gen_holds (p_invoice_rec.invoice_id);
8534         FETCH dist_gen_holds BULK COLLECT INTO t_holds_tab;
8535         CLOSE dist_gen_holds;
8536       END IF;
8537 
8538       l_debug_info := 'Release all the non D holds';
8539 
8540       IF nvl(t_holds_tab.count, 0) > 0 THEN
8541 
8542         FOR i IN NVL(t_holds_tab.first,0)..NVL(t_holds_tab.last,0)
8543         LOOP
8544 
8545           l_debug_info := 'Inside the loop';
8546 
8547           Process_Inv_Hold_Status(
8548              p_invoice_rec.invoice_id,
8549              null,
8550              null,
8551              t_holds_tab(i),
8552              'N',
8553              null,
8554              l_system_user,
8555              l_holds,
8556              l_hold_count,
8557              l_release_count,
8558              l_curr_calling_sequence);
8559 
8560         END LOOP;
8561 
8562      END IF;
8563     /* bug 6783517 ends */
8564 
8565   -- Perf 6759699
8566   -- If the p_run_option is not new then the below function will be
8567   -- called once for a invoice id.
8568 
8569           IF ( nvl(t_inv_lines_table.count,0) <> 0 AND
8570                (nvl(p_run_option,'Yes') <> 'New' ))THEN
8571 
8572              Update_Inv_Dists_To_Selected( p_invoice_rec.invoice_id,
8573                                            null ,
8574                                            p_run_option,
8575                                            l_curr_calling_sequence);
8576           End IF; -- 6759699
8577 
8578       FOR i IN NVL(t_inv_lines_table.first,0)..NVL(t_inv_lines_table.last,0)
8579       LOOP
8580        IF (t_inv_lines_table.exists(i)) THEN
8581 
8582            IF t_inv_lines_table(i).line_type_lookup_code in
8583                           ('FREIGHT', 'MISCELLANEOUS') THEN
8584 
8585 	        ----------------------------------------------------------------
8586                 l_debug_info := 'Create charge allocations ';
8587                 Print_Debug(l_debug_loc, l_debug_info);
8588                 ----------------------------------------------------------------
8589 
8590            	SELECT nvl(prorate_across_all_items,'N')
8591 	          INTO l_prorate_across_all_items
8592                   FROM ap_invoice_lines_all
8593                  WHERE invoice_id  = t_inv_lines_table(i).invoice_id
8594                    AND line_number = t_inv_lines_table(i).line_number;
8595 
8596 		IF (l_prorate_across_all_items='Y') then
8597 
8598 		    l_success := AP_ALLOCATION_RULES_PKG.Create_Proration_Rule(
8599 					t_inv_lines_table(i).invoice_id,
8600 					t_inv_lines_table(i).line_number,
8601 					NULL,
8602 					'APAPRVLB',
8603 					l_error_code,
8604 					l_debug_info,
8605 					l_debug_context,
8606 					'Execute_Dist_Generation_Check');
8607 
8608 		END IF;
8609            END IF;
8610 
8611            -- Bug fix : 6731107: Added 'D' to the below if stmt
8612            IF (t_inv_lines_table(i).generate_dists IN ('D' , 'Y') ) THEN
8613 
8614 	       IF t_inv_lines_table(i).line_type_lookup_code <> 'TAX' THEN
8615 
8616 		  ----------------------------------------------------------------
8617                   l_debug_info := 'Check Insufficient Line Info: Number and Type: '||
8618                                   t_inv_lines_table(i).line_number ||' and '||
8619                                   t_inv_lines_table(i).line_type_lookup_code;
8620                   Print_Debug(l_debug_loc, l_debug_info);
8621                   ----------------------------------------------------------------
8622 
8623                   Check_Insufficient_Line_Data(
8624 				p_inv_line_rec            => t_inv_lines_table(i),
8625 				p_system_user             => l_system_user,
8626 				p_holds                   => l_holds,
8627 				p_holds_count             => l_hold_count,
8628 				p_release_count           => l_release_count,
8629 				p_insufficient_data_exist => l_insufficient_data_exist,
8630 				p_calling_mode		  => 'PERMANENT_DISTRIBUTIONS',
8631 				p_calling_sequence        => l_curr_calling_sequence );
8632 
8633 		  IF ( (NOT l_insufficient_data_exist)
8634                        AND (t_inv_lines_table(i).generate_dists = 'Y') ) THEN
8635                  --Bug fix 6731107 : added the AND condition to above IF stmt.
8636                  --Invoice distributions should be generated only when generate_dists flag is set to 'Y'
8637 
8638        	              ----------------------------------------------------------------
8639                       l_debug_info := 'Generate Invoice Distributions';
8640 	              Print_Debug(l_debug_loc, l_debug_info);
8641                       ----------------------------------------------------------------
8642 
8643                       l_result := Execute_Dist_Generation_Check(
8644 	                                    p_batch_id              => p_inv_batch_id,
8645 	                                    p_invoice_date          => p_invoice_rec.invoice_date,
8646 	                                    p_vendor_id             => p_invoice_rec.vendor_id,
8647 	                                    p_invoice_currency      => p_invoice_rec.invoice_currency_code,
8648 	                                    p_exchange_rate         => p_invoice_rec.exchange_rate,
8649 	                                    p_exchange_rate_type    => p_invoice_rec.exchange_rate_type,
8650 	                                    p_exchange_date         => p_invoice_rec.exchange_date,
8651 	                                    p_inv_line_rec          => t_inv_lines_table(i),
8652 	                                    p_system_user           => l_system_user,
8653 	                                    p_holds                 => l_holds,
8654 	                                    p_holds_count           => l_hold_count,
8655 	                                    p_release_count         => l_release_count,
8656 	                                    p_generate_permanent    => 'Y',
8657 	                                    p_calling_mode          => 'PERMANENT_DISTRIBUTIONS',
8658 	                                    p_error_code            => l_error_code,
8659 	                                    p_curr_calling_sequence => l_curr_calling_sequence);
8660 
8661 		 ELSE
8662        	             ----------------------------------------------------------------
8663                      l_debug_info := 'Insufficient info for invoice line number: '||
8664                                       t_inv_lines_table(i).line_number;
8665 	             Print_Debug(l_debug_loc, l_debug_info);
8666                      ----------------------------------------------------------------
8667                  END IF; -- end of sufficient data check
8668                END IF; -- end of line_type_lookup_code check
8669            END IF; -- end of generate_dists check
8670 
8671            IF (t_inv_lines_table(i).line_type_lookup_code IN ('ITEM', 'RETAINAGE RELEASE')) THEN
8672 
8673                 l_recouped_amount := AP_MATCHING_UTILS_PKG.Get_Inv_Line_Recouped_Amount
8674 	                                        (P_Invoice_Id          => t_inv_lines_table(i).invoice_id,
8675 	                                         P_Invoice_Line_Number => t_inv_lines_table(i).line_number);
8676 
8677                 IF l_recouped_amount <> 0 THEN
8678                    IF (ap_invoice_lines_utility_pkg.get_approval_status
8679 	                        ( p_invoice_id  => t_inv_lines_table(i).invoice_id
8680 	                         ,p_line_number => t_inv_lines_table(i).line_number) = 'NEVER APPROVED') THEN
8681 
8682                        ----------------------------------------------------------------
8683                        l_debug_info := 'Adjust Amount Paid if unapproved lines with recouped prepayments exist';
8684           	       Print_Debug(l_debug_loc, l_debug_info);
8685        	               ----------------------------------------------------------------
8686 
8687 		       --bugfix:5609186 removed the l_recouped_amount from the pay_curr_invoice_amount
8688 		       --as pay_curr_invoice_amount has nothing to do with recouped amount. Recoupment
8689 		       --should effect only amount_paid on the invoice.
8690 		       update  ap_invoices_all
8691                           set  amount_paid = nvl(amount_paid,0) + abs(l_recouped_amount)
8692                               ,pay_curr_invoice_amount = ap_utilities_pkg.ap_round_currency
8693 	                                                         (pay_curr_invoice_amount  * payment_cross_rate,
8694 	                                                           payment_currency_code)
8695 		        where  invoice_id  = t_inv_lines_table(i).invoice_id;
8696                   END IF;
8697                END IF;
8698            END IF;
8699 
8700            ----------------------------------------------------------------
8701            l_debug_info := 'Update Invoice Distributions to SELECTED';
8702            Print_Debug(l_debug_loc, l_debug_info);
8703            ----------------------------------------------------------------
8704   -- Perf 6759699
8705   -- All the reamining values for the p_run_option is handeled before
8706   -- the loop. If the line number is passed then it will use proper index.This will
8707   -- work only when the p_run_option is 'NEW'
8708     if ( p_run_option = 'NEW' ) then  --6759699
8709 
8710 	   Update_Inv_Dists_To_Selected(
8711 		            t_inv_lines_table(i).invoice_id,
8712 		            t_inv_lines_table(i).line_number,
8713 		            p_run_option,
8714 		            l_curr_calling_sequence);
8715      end if; -- p_run_option
8716            -----------------------------------------------------------------
8717            Print_Debug(l_debug_loc, 'Line Type : '|| t_inv_lines_table(i).line_type_lookup_code );
8718            Print_Debug(l_debug_loc, 'Match Type: '|| t_inv_lines_table(i).match_type );
8719            -----------------------------------------------------------------
8720 
8721            IF ( t_inv_lines_table(i).line_type_lookup_code = 'ITEM' AND
8722                 t_inv_lines_table(i).match_type in ('ITEM_TO_PO',
8723 	                                            'ITEM_TO_RECEIPT',
8724 	                                            'PRICE_CORRECTION',
8725 	                                            'QTY_CORRECTION',
8726 	                                            'ITEM_TO_SERVICE_PO',
8727 	                                            'ITEM_TO_SERVICE_RECEIPT',
8728 	                                            'AMOUNT_CORRECTION',
8729 	                                            'PO_PRICE_ADJUSTMENT' ) ) THEN
8730 
8731                 ----------------------------------------------------------------
8732                 l_debug_info := 'Calculate Exchange Rate and Invoice Price Variance';
8733                 Print_Debug(l_debug_loc, l_debug_info);
8734                 ----------------------------------------------------------------
8735 
8736 	        AP_APPROVAL_MATCHED_PKG.Exec_Matched_Variance_Checks(
8737 		              p_invoice_id                => t_inv_lines_table(i).invoice_id,
8738 		              p_inv_line_number           => t_inv_lines_table(i).line_number,
8739 		              p_base_currency_code        => p_base_currency_code,
8740 		              p_inv_currency_code         => p_invoice_rec.invoice_currency_code,
8741 		              p_sys_xrate_gain_ccid       => NULL,
8742 		              p_sys_xrate_loss_ccid       => NULL,
8743 		              p_system_user               => l_system_user,
8744 		              p_holds                     => l_holds,
8745 		              p_hold_count                => l_hold_count,
8746 		              p_release_count             => l_release_count,
8747 		              p_calling_sequence          => l_curr_calling_sequence );
8748 
8749           END IF;
8750        END IF;
8751       END LOOP;
8752 
8753       l_retained_amount := nvl(ap_invoices_utility_pkg.get_retained_total(p_invoice_rec.invoice_id, null),0);
8754 
8755       IF l_retained_amount <> 0 THEN
8756 
8757          ----------------------------------------------------------------
8758          l_debug_info := 'Adjust Amount Applicable To Discount with Retainage';
8759          Print_Debug(l_debug_loc, l_debug_info);
8760          ----------------------------------------------------------------
8761 
8762          update ap_invoices_all
8763          set    amount_applicable_to_discount = amount_applicable_to_discount + l_retained_amount
8764                ,pay_curr_invoice_amount = ap_utilities_pkg.ap_round_currency
8765                                                  ((invoice_amount + l_retained_amount) * payment_cross_rate,
8766                                                    payment_currency_code)
8767          where invoice_id = p_invoice_rec.invoice_id
8768          and   nvl(net_of_retainage_flag, 'N') <> 'Y';
8769       END IF;
8770 
8771 EXCEPTION
8772     WHEN OTHERS THEN
8773       IF (SQLCODE <> -20001) THEN
8774           FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
8775           FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
8776           FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE', l_curr_calling_sequence);
8777           FND_MESSAGE.SET_TOKEN('DEBUG_INFO', l_debug_info);
8778       END IF;
8779       APP_EXCEPTION.RAISE_EXCEPTION;
8780 END Generate_Distributions;
8781 
8782 PROCEDURE initialize_invoice_holds
8783 			(p_invoice_id       IN NUMBER,
8784 			 p_calling_sequence IN VARCHAR2) IS
8785 
8786   Cursor c_invoice_holds (c_invoice_id NUMBER) Is
8787   Select hold_lookup_code,
8788 	 decode(release_lookup_code, NULL, 'ALREADY ON HOLD',
8789 	        'RELEASED BY USER') hold_status,
8790   	 invoice_id,
8791 	 hold_reason,
8792 	 release_lookup_code,
8793 	 line_location_id,
8794 	 rcv_transaction_id,
8795 	 last_updated_by,
8796 	 responsibility_id
8797   From   ap_holds
8798   Where  invoice_id = c_invoice_id
8799   Order By 1, 2 DESC;
8800 
8801   j NUMBER := 1;
8802 
8803   l_debug_info                    VARCHAR2(100);
8804   l_current_calling_sequence      VARCHAR2(2000);
8805 
8806 BEGIN
8807 
8808     -- Update the calling sequence
8809     --
8810     l_current_calling_sequence := 'initialize_invoice_holds<-'||p_calling_sequence;
8811 
8812     g_holds_tab.delete;
8813 
8814     OPEN c_invoice_holds (p_invoice_id);
8815     LOOP
8816        FETCH c_invoice_holds
8817        INTO  g_holds_tab(j);
8818        EXIT WHEN c_invoice_holds%notfound;
8819        j:=j+1;
8820     END LOOP;
8821     CLOSE c_invoice_holds;
8822 
8823 EXCEPTION
8824   WHEN OTHERS then
8825 	if (SQLCODE <> -20001 ) then
8826 	    FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
8827 	    FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
8828 	    FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE',l_current_calling_sequence);
8829 	    FND_MESSAGE.SET_TOKEN('PARAMETERS','Invoice_id = '||TO_CHAR(p_invoice_id));
8830 	    FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
8831 	end if;
8832 
8833 	APP_EXCEPTION.RAISE_EXCEPTION;
8834 
8835 END initialize_invoice_holds;
8836 
8837 Procedure Count_Org_Hold(
8838 	      p_org_id		    IN NUMBER,
8839               p_hold_lookup_code    IN VARCHAR2,
8840 	      p_place_or_release    IN VARCHAR2,
8841               p_calling_sequence    IN VARCHAR2) IS
8842 
8843     l_array_set   VARCHAR2(1);
8844     l_array_count NUMBER;
8845 
8846   l_debug_info                    VARCHAR2(100);
8847   l_current_calling_sequence      VARCHAR2(2000);
8848 
8849 Begin
8850 
8851     -- Update the calling sequence
8852     --
8853     l_current_calling_sequence := 'count_org_hold<-'||p_calling_sequence;
8854 
8855     l_array_set := 'N';
8856     l_array_count := g_org_holds.count;
8857 
8858     l_debug_info := 'Update Org Hold Count';
8859 
8860     if l_array_count > 0 then
8861 
8862        for i in g_org_holds.first..g_org_holds.last loop
8863            if g_org_holds(i).org_id = p_org_id
8864               and g_org_holds(i).hold_lookup_code = p_hold_lookup_code then
8865               if p_place_or_release = 'P' then
8866 	         g_org_holds(i).holds_placed := g_org_holds(i).holds_placed + 1;
8867                  l_array_set := 'Y';
8868 	         exit;
8869 	      elsif p_place_or_release = 'R' then
8870                  g_org_holds(i).holds_released := g_org_holds(i).holds_released + 1;
8871 	         l_array_set := 'Y';
8872 	         exit;
8873 	      end if;
8874 	   end if;
8875        end loop;
8876 
8877     end if;
8878 
8879 
8880     if l_array_set = 'N' then
8881 
8882        l_debug_info := 'Set Org Hold Count';
8883 
8884        if l_array_count = 0 then
8885           l_array_count := 1;
8886        else
8887           l_array_count := l_array_count + 1;  --bug6370503
8888        end if;
8889 
8890        if p_place_or_release = 'P' then
8891           g_org_holds(l_array_count).org_id           := p_org_id;
8892           g_org_holds(l_array_count).hold_lookup_code := p_hold_lookup_code;
8893           g_org_holds(l_array_count).holds_placed     := 1;
8894           g_org_holds(l_array_count).holds_released   := 0;
8895        elsif p_place_or_release = 'R' then
8896           g_org_holds(l_array_count).org_id           := p_org_id;
8897           g_org_holds(l_array_count).hold_lookup_code := p_hold_lookup_code;
8898           g_org_holds(l_array_count).holds_placed     := 0;
8899           g_org_holds(l_array_count).holds_released   := 1;
8900        end if;
8901     end if;
8902 
8903 EXCEPTION
8904   WHEN OTHERS then
8905         if (SQLCODE <> -20001 ) then
8906             FND_MESSAGE.SET_NAME('SQLAP','AP_DEBUG');
8907             FND_MESSAGE.SET_TOKEN('ERROR',SQLERRM);
8908             FND_MESSAGE.SET_TOKEN('CALLING_SEQUENCE',l_current_calling_sequence);
8909             FND_MESSAGE.SET_TOKEN('PARAMETERS','Org_Id = '||to_char(p_org_id)
8910                                                ||' Hold = '||p_hold_lookup_code
8911                                                ||' Action = '||p_place_or_release);
8912             FND_MESSAGE.SET_TOKEN('DEBUG_INFO',l_debug_info);
8913         end if;
8914 
8915         APP_EXCEPTION.RAISE_EXCEPTION;
8916 End Count_Org_Hold;
8917 
8918 Procedure Print_Debug(
8919 		p_api_name		IN VARCHAR2,
8920 		p_debug_info		IN VARCHAR2) IS
8921 BEGIN
8922 
8923   IF g_debug_mode = 'Y' THEN
8924 
8925     AP_Debug_Pkg.Print(g_debug_mode, p_debug_info );
8926 
8927   END IF;
8928 
8929   IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
8930     FND_LOG.STRING(G_LEVEL_STATEMENT,G_MODULE_NAME||p_api_name,p_debug_info);
8931   END IF;
8932 END Print_Debug;
8933 
8934 /*=============================================================================
8935  |  FUNCTION - get_adjusted_base_amount()
8936  |
8937  |  DESCRIPTION
8938  |      This function returns base amount after rouding.
8939  |      Also calculates the rounding amount for the next line
8940  |      For ex:                           before adjustment  after adjustment
8941  |            ---------------------------|----------------------------------------------
8942  |               p_base_amount           |  0.1               0 (since adjustment goes to -ve)
8943  |               p_rounding_amt          | -0.2              -0.1 (this much amount is adjusted)
8944  |               p_next_line_rounding_amt|                   -0.1 (remaing amount..forward it to next line)
8945  |
8946  |
8947  |  PARAMETERS
8948  |      p_base_amount - entered base amount
8949  |      p_rounding_amt - rounding amount for the base amount
8950  |      p_next_line_rounding_amt - rounding amount calculate for the next line/distribution
8951  |
8952  |  MODIFICATION HISTORY
8953  |    DATE          Author         Action
8954  |    19-MAY-2008   KPASIKAN       Created for the bug 6892789
8955  |
8956  *============================================================================*/
8957 FUNCTION get_adjusted_base_amount(p_base_amount IN NUMBER,
8958                                   p_rounding_amt OUT NOCOPY NUMBER,
8959                                   p_next_line_rounding_amt IN OUT NOCOPY NUMBER)
8960 RETURN NUMBER IS
8961     l_adjusted_base_amount   NUMBER := 0;
8962     l_base_amount            NUMBER :=  p_base_amount;
8963     l_next_line_rounding_amt NUMBER :=  p_next_line_rounding_amt;
8964 BEGIN
8965     l_adjusted_base_amount := l_base_amount + l_next_line_rounding_amt;
8966 
8967     -- if adjusted base amount goes to -ve
8968     IF (l_base_amount > 0 AND l_adjusted_base_amount < 0)
8969       OR (l_base_amount < 0 AND l_adjusted_base_amount > 0) THEN
8970       -- rounding maount for the next line/dist
8971  	p_next_line_rounding_amt := l_adjusted_base_amount;
8972 
8973         -- rounding amt for the line/dist
8974         p_rounding_amt := -l_base_amount;
8975 
8976         -- base amount will be adjusted to zero
8977 	RETURN 0;
8978     ELSE
8979         -- rounding amt for the line/dist
8980         p_rounding_amt := l_next_line_rounding_amt;
8981 
8982         -- no need to adjust next line/dist
8983 	p_next_line_rounding_amt := 0;
8984 
8985         -- base amount
8986 	RETURN l_adjusted_base_amount;
8987     END IF;
8988 END;
8989 
8990 END AP_APPROVAL_PKG;