DBA Data[Home] [Help]

PACKAGE BODY: APPS.PO_WF_PO_NOTIFICATION

Source


1 PACKAGE BODY PO_WF_PO_NOTIFICATION AS
2 /* $Header: POXWPA7B.pls 120.30.12020000.6 2013/03/16 14:04:59 inagdeo ship $ */
3 
4 g_po_wf_debug VARCHAR2(1) := NVL(FND_PROFILE.VALUE('PO_SET_DEBUG_WORKFLOW_ON'),'N');
5 g_pkg_name         VARCHAR2(30) := 'PO_WF_PO_NOTIFICATION';    -- <BUG 3607009>
6 
7 --Added this private procedure as part of bug 13951919 fix
8 PROCEDURE update_action_history (p_action_code         IN VARCHAR2,
9                               p_recipient_id           IN NUMBER,
10                               p_note                   IN VARCHAR2,
11                               p_po_header_id           IN NUMBER,
12                               p_current_id             IN NUMBER,
13                               p_doc_type               IN  po_action_history.OBJECT_TYPE_CODE%TYPE,
14                               p_doc_subtype            IN po_action_history.OBJECT_SUB_TYPE_CODE%TYPE,
15                               p_approval_path_id       IN po_action_history.APPROVAL_PATH_ID%TYPE, --<bug 14105414>
16                               p_draft_id               IN NUMBER,
17                               p_draft_type             IN VARCHAR2); -- PAR Approval
18 
19 PROCEDURE get_po_approve_msg (	 document_id	in	varchar2,
20                                  display_type	in	varchar2,
21                                  document	in out	NOCOPY varchar2,
22                                  document_type	in out	NOCOPY varchar2) IS
23 
24   l_item_type    wf_items.item_type%TYPE;
25   l_item_key     wf_items.item_key%TYPE;
26 
27   l_document_id      po_headers.po_header_id%TYPE;
28   l_org_id           po_headers.org_id%TYPE;
29   l_currency_code    fnd_currencies.CURRENCY_CODE%TYPE;
30   l_header_msg       VARCHAR2(500);
31   l_po_amount        VARCHAR2(30);
32   l_tax_amount       VARCHAR2(30);
33  --bug 12396408
34   l_po_amount_numeric        NUMBER;
35   l_tax_amount_numeric       NUMBER;
36   l_description      po_headers.comments%TYPE;
37   l_forwarded_from   per_all_people_f.full_name%TYPE;
38   l_preparer         per_all_people_f.full_name%TYPE;
39 --<UTF-8 FPI START>
40 --  l_note             VARCHAR2(480);  /* < UTF8 FPI - changed from VARCHAR2(240) > */
41   l_note             po_action_history.note%TYPE;
42 --<UTF-8 FPI END>
43   l_document         VARCHAR2(32000) := '';
44   l_tax_amt          NUMBER;
45 
46   /* Start Bug# 3972475 */
47   X_precision        number;
48   X_ext_precision    number;
49   X_min_acct_unit    number;
50   /* End Bug# 3972475*/
51   l_supplier         po_vendors.vendor_name%type; --Bug 4254468
52   l_supplier_site    po_vendor_sites_all.vendor_site_code%type; --Bug 4254468
53   NL                 VARCHAR2(1) := fnd_global.newline;
54 
55 --Added by Eric Ma for IL PO Notification on Apr-13,2009 ,Begin
56 -------------------------------------------------------------------------------------
57 lv_tax_region        varchar2(30);        --tax region code
58 ln_jai_excl_nr_tax   NUMBER;              --exclusive non-recoverable tax
59 lv_progress          VARCHAR2(255);       --for saving the debug information
60 lv_document_type     VARCHAR2(25);        --document type
61 -------------------------------------------------------------------------------------
62 --Added by Eric Ma for IL PO Notification on Apr-13,2009 ,End
63 BEGIN
64 
65   l_item_type := substr(document_id, 1, instr(document_id, ':') - 1);
66   l_item_key := substr(document_id, instr(document_id, ':') + 1, length(document_id) - 2);
67 
68   l_document_id := wf_engine.GetItemAttrNumber
69                                         (itemtype   => l_item_type,
70                                          itemkey    => l_item_key,
71                                          aname      => 'DOCUMENT_ID');
72 
73   l_org_id := wf_engine.GetItemAttrNumber
74                                         (itemtype   => l_item_type,
75                                          itemkey    => l_item_key,
76                                          aname      => 'ORG_ID');
77 
78   PO_MOAC_UTILS_PVT.set_org_context(l_org_id) ;       -- <R12 MOAC>
79 
80 
81   l_currency_code := wf_engine.GetItemAttrText
82                                         (itemtype   => l_item_type,
83                                          itemkey    => l_item_key,
84                                          aname      => 'FUNCTIONAL_CURRENCY');
85 
86   l_po_amount := wf_engine.GetItemAttrText
87                                         (itemtype   => l_item_type,
88                                          itemkey    => l_item_key,
89                                          aname      => 'PO_AMOUNT_DSP');
90 
91   l_tax_amount := wf_engine.GetItemAttrText
92                                         (itemtype   => l_item_type,
93                                          itemkey    => l_item_key,
94                                          aname      => 'TAX_AMOUNT_DSP');
95 -- bug 12396408
96   l_po_amount_numeric := wf_engine.GetItemAttrNumber
97                                         (itemtype   => l_item_type,
98                                          itemkey    => l_item_key,
99                                          aname      => 'PO_AMOUNT_DSP_NUMERIC');
100 
101   l_tax_amount_numeric := wf_engine.GetItemAttrNumber
102                                         (itemtype   => l_item_type,
103                                          itemkey    => l_item_key,
104                                          aname      => 'TAX_AMOUNT_DSP_NUMERIC');
105 
106   l_description := wf_engine.GetItemAttrText
107                                         (itemtype   => l_item_type,
108                                          itemkey    => l_item_key,
109                                          aname      => 'PO_DESCRIPTION');
110 
111   l_forwarded_from := wf_engine.GetItemAttrText
112                                         (itemtype   => l_item_type,
113                                          itemkey    => l_item_key,
114                                          aname      => 'FORWARD_FROM_DISP_NAME');
115 
116   l_preparer := wf_engine.GetItemAttrText
117                                         (itemtype   => l_item_type,
118                                          itemkey    => l_item_key,
119                                          aname      => 'PREPARER_DISPLAY_NAME');
120 
121   l_note := wf_engine.GetItemAttrText
122                                         (itemtype   => l_item_type,
123                                          itemkey    => l_item_key,
124                                          aname      => 'NOTE');
125 
126   --<Bug 4254468 Start> Show supplier and supplier site for
127   -- approval notifications
128   l_supplier := PO_WF_UTIL_PKG.GetItemAttrText
129                                         (itemtype   => l_item_type,
130                                          itemkey    => l_item_key,
131                                          aname      => 'SUPPLIER');
132 
133   l_supplier_site := PO_WF_UTIL_PKG.GetItemAttrText
134                                         (itemtype   => l_item_type,
135                                          itemkey    => l_item_key,
136                                          aname      => 'SUPPLIER_SITE');
137   --<Bug 4254468 End>
138 
139 /*Start Bug# 3972475 - replaced the below sql to get the tax amount
140   to account for canceled QTY. Also accounted for new order types introduced
141   in 11i10 that use amount instead of quantity (where quantity_ordered is null).
142 
143   Since we are performing divide and multiply by operations we need rounding
144   logic based on the currency.
145 
146   If we are using minimum accountable unit we apply:
147    rounded tax = round(tax/mau)*mau, otherwise
148    rounded tax = round(tax, precision)
149 
150    Old tax select:
151   SELECT nvl(sum(nonrecoverable_tax), 0)
152     INTO l_tax_amt
153     FROM po_lines pol,
154          po_distributions pod
155    WHERE pol.po_header_id = l_document_id
156      AND pod.po_line_id = pol.po_line_id;
157 */
158 
159   --Modified by Eric Ma for IL po workflow notification on Apr-13,2009 ,Begin
160   -------------------------------------------------------------------------------------
161   lv_tax_region      := JAI_PO_WF_UTIL_PUB.Get_Tax_Region (pn_org_id => l_org_id);
162 
163   IF (lv_tax_region ='JAI')
164   THEN
165     --Get document type
166     lv_document_type := wf_engine.GetItemAttrText
167                         ( itemtype   => l_item_type
168                         , itemkey    => l_item_key
169                         , aname      => 'DOCUMENT_TYPE'
170                         );
171 
172     --Indian localization tax calculation
173     IF  lv_document_type = 'RELEASE'
174     THEN
175       JAI_PO_WF_UTIL_PUB.Get_Jai_Tax_Amount
176       ( pv_document_type      => JAI_PO_WF_UTIL_PUB.G_REL_DOC_TYPE
177       , pn_document_id        => l_document_id
178       , xn_excl_tax_amount    => l_tax_amt
179       , xn_excl_nr_tax_amount => ln_jai_excl_nr_tax
180       );
181 
182     ELSE
183       JAI_PO_WF_UTIL_PUB.Get_Jai_Tax_Amount
184       ( pv_document_type      => JAI_PO_WF_UTIL_PUB.G_PO_DOC_TYPE
185       , pn_document_id        => l_document_id
186       , xn_excl_tax_amount    => l_tax_amt
187       , xn_excl_nr_tax_amount => ln_jai_excl_nr_tax
188       );
189     END IF; --(lv_document_type = 'RELEASE')
190   ELSE
191     --original tax calc code
192 
193     fnd_currency.get_info( l_currency_code,
194                             X_precision,
195                             X_ext_precision,
196                             X_min_acct_unit);
197 
198 
199     IF (x_min_acct_unit IS NOT NULL) AND
200         (x_min_acct_unit <> 0)
201     THEN
202       SELECT sum( round (POD.nonrecoverable_tax *
203                          decode(quantity_ordered,
204                                 NULL,
205                                  --Bug16222308 Handling the quantity zero on distribution
206                                 (nvl(POD.amount_ordered,0) - nvl(POD.amount_cancelled,0)) / decode ( nvl(POD.amount_ordered, 1),0,1,nvl(POD.amount_ordered, 1) ) ,
207                                 (nvl(POD.quantity_ordered,0) - nvl(POD.quantity_cancelled,0)) / decode ( nvl(POD.quantity_ordered, 1),0,1, nvl(POD.quantity_ordered, 1) )
208                                ) / X_min_acct_unit
209                          ) * X_min_acct_unit
210                 )
211       INTO l_tax_amt
212       FROM po_lines pol,
213            po_distributions pod
214      WHERE pol.po_header_id = l_document_id
215        AND pod.po_line_id = pol.po_line_id;
216     ELSE
217       SELECT sum( round (POD.nonrecoverable_tax *
218                          decode(quantity_ordered,
219                                 NULL,
220                                 --Bug16222308 Handling the quantity zero on distribution
221                                 (nvl(POD.amount_ordered,0) - nvl(POD.amount_cancelled,0)) / decode ( nvl(POD.amount_ordered, 1),0,1,nvl(POD.amount_ordered, 1) ) ,
222                                 (nvl(POD.quantity_ordered,0) - nvl(POD.quantity_cancelled,0)) / decode ( nvl(POD.quantity_ordered, 1),0,1, nvl(POD.quantity_ordered, 1) )
223                                ),
224                          X_precision
225                         )
226                 )
227       INTO l_tax_amt
228       FROM po_lines pol,
229            po_distributions pod
230      WHERE pol.po_header_id = l_document_id
231        AND pod.po_line_id = pol.po_line_id;
232     END IF;
233   END IF;--(lv_tax_region ='JAI')
234   -------------------------------------------------------------------------------------
235   --Modified by Eric Ma for IL po workflow notification on Apr-13,2009 ,End
236 
237   if (display_type = 'text/html') then
238 
239     l_document := NL || NL || '<!-- PO_APPROVE_MSG -->'|| NL || NL || '<P>';
240 
241     l_document := l_document || '</P>' || NL;
242 
243     --Bug 9067919,   which is the entity used to represent a non-breaking
244     --space had the semi-colon missing. Replaced all occurences with the correct
245     --syntax   instead of  
246 
247     l_document := l_document || '<P><TABLE border=0 cellpadding=0 cellspacing=0 SUMMARY=""><TR><TD align=right >' || NL ||
248                   fnd_message.get_string('PO', 'PO_WF_NOTIF_PO_AMOUNT') ||
249                   '  </TD>' || NL;
250 
251      -- 12396408 Formatting the total amount
252     l_document := l_document || '<TD align=left>' || l_currency_code || ' ' || nvl(TO_CHAR(l_po_amount_numeric, FND_CURRENCY.GET_FORMAT_MASK(
253                               l_currency_code, 30)),' ') || '</TD></TR>' || NL;
254 
255     if l_tax_amt > 0 then
256 
257       l_document := l_document || '<TR><TD align=right>' ||
258                     fnd_message.get_string('PO', 'PO_WF_NOTIF_TAX_AMOUNT') ||
259                     '  </TD>' || NL;
260       --bug 12396408 formatting the tax
261       l_document := l_document || '<TD align=left>' || l_currency_code || ' ' || nvl(TO_CHAR(l_tax_amount_numeric , FND_CURRENCY.GET_FORMAT_MASK(
262                               l_currency_code, 30)),' ') ||
263                     '</TD></TR></TABLE></P>' || NL;
264 
265     else
266 
267       l_document := l_document || '</TABLE></P>' || NL || NL;
268 
269     end if;
270 
271     --<Bug 4254468 Start> Show supplier and supplier site for
272     -- approval notifications
273     l_document := l_document || '<P>' || NL;
274     l_document := l_document || fnd_message.get_string('PO', 'PO_FO_VENDOR') ||
275                   ' '|| l_supplier || NL;
276     l_document := l_document || '<BR>' || NL;
277     l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_SUPPLIER_SITE') ||
278                   ' '|| l_supplier_site || NL;
279     l_document := l_document || '</P>' || NL;
280     --<Bug 4254468 End>
281 
282     if l_description is not null then
283       l_document := l_document || '<P>' || NL;
284       l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_DOC_DESCRIPTION') || NL || '<BR>';
285       l_document := l_document || l_description;
286       l_document := l_document || '<BR></P>' || NL;
287     end if;
288 
289   else  -- plain text notification is defined in the WF.
290 
291 	null;
292 
293   end if;
294 
295   document := l_document;
296 
297 END;
298 
299 
300 PROCEDURE get_po_lines_details ( document_id	in	varchar2,
301                                  display_type	in	varchar2,
302                                  document	in out	NOCOPY CLOB, -- <BUG 7006113>
303                                  document_type	in out	NOCOPY varchar2) IS
304 
305   l_item_type        wf_items.item_type%TYPE;
306   l_item_key         wf_items.item_key%TYPE;
307 
308   l_document_id      po_lines.po_header_id%TYPE;
309   l_org_id           po_lines.org_id%TYPE;
310   l_document_type    VARCHAR2(25);
311 
312   l_document         VARCHAR2(32000) := '';
313 
314   l_currency_code    fnd_currencies.currency_code%TYPE;
315 
316   -- Bug 3668188: added new local var. note: the length of this
317   -- varchar was determined based on the length in POXWPA1B.pls,
318   -- which is the other place 'OPEN_FORM_COMMAND' attribute is used
319 
320   l_open_form_command VARCHAR2(200);
321   l_view_po_url      varchar2(1000);   -- HTML Orders R12
322   l_edit_po_url      varchar2(1000);   -- HTML Orders R12
323 
324   NL                 VARCHAR2(1) := fnd_global.newline;
325 
326   i 		     NUMBER := 0;
327   max_lines_dsp      NUMBER ;  -- <BUG 7006113>
328   l_line_count       NUMBER := 0; -- <BUG 3616816> # lines/shipments on document
329   line_mesg          fnd_new_messages.message_text%TYPE; --Bug 4695601
330   l_num_records_to_display NUMBER;      -- <BUG 3616816> actual # of records to be displayed in table
331 
332   -- <BUG 7006113 START>
333   curr_len           NUMBER := 0; --<BUG 7614278 Reverting back the commented variable>
334   -- prior_len          NUMBER := 0;
335   -- <BUG 7006113 END>
336 
337 -- po lines cursor
338 
339     -- <BUG 3616816 START> Declare TABLEs for each column that is selected
340     -- from po_line_csr and po_line_loc_csr.
341     --
342     TYPE line_num_tbl_type IS TABLE OF PO_LINES.line_num%TYPE;
343     TYPE shipment_num_tbl_type IS TABLE OF PO_LINE_LOCATIONS.shipment_num%TYPE;
344     TYPE item_num_tbl_type IS TABLE OF MTL_SYSTEM_ITEMS_KFV.concatenated_segments%TYPE;
345     TYPE item_revision_tbl_type IS TABLE OF PO_LINES.item_revision%TYPE;
346     TYPE item_desc_tbl_type IS TABLE OF PO_LINES.item_description%TYPE;
347     TYPE uom_tbl_type IS TABLE OF MTL_UNITS_OF_MEASURE.unit_of_measure_tl%TYPE;
348     TYPE quantity_tbl_type IS TABLE OF PO_LINES.quantity%TYPE;
349     TYPE unit_price_tbl_type IS TABLE OF PO_LINES.unit_price%TYPE;
350     TYPE amount_tbl_type IS TABLE OF PO_LINES.amount%TYPE;
351     TYPE location_tbl_type IS TABLE OF HR_LOCATIONS.location_code%TYPE;
352     TYPE organization_name_tbl_type IS TABLE OF ORG_ORGANIZATION_DEFINITIONS.organization_name%TYPE;
353     TYPE need_by_date_tbl_type IS TABLE OF PO_LINE_LOCATIONS.need_by_date%TYPE;
354     TYPE promised_date_tbl_type IS TABLE OF PO_LINE_LOCATIONS.promised_date%TYPE;
355     TYPE shipment_type_tbl_type IS TABLE OF PO_LINE_LOCATIONS.shipment_type%TYPE;
356     /* CLM Changes Start */
357     TYPE clm_option_num_tbl_type IS TABLE OF PO_LINES.CLM_OPTION_NUM%TYPE;
358     TYPE CLM_BASE_LINE_NUM_tbl_type IS TABLE OF po_lines.LINE_NUM_DISPLAY%TYPE;
359     TYPE CONTRACT_TYPE_tbl_type is table of po_lookup_codes.DESCRIPTION%TYPE;
360     TYPE LINE_NUM_DISPLAY_tbl_type is table of po_lines.line_num_display%type;
361     /* CLM changes End */
362 
363     l_line_num_tbl         line_num_tbl_type;
364     l_shipment_num_tbl     shipment_num_tbl_type;
365     l_item_num_tbl         item_num_tbl_type;
366     l_item_revision_tbl    item_revision_tbl_type;
367     l_item_desc_tbl        item_desc_tbl_type;
368     l_uom_tbl              uom_tbl_type;
369     l_quantity_tbl         quantity_tbl_type;
370     l_unit_price_tbl       unit_price_tbl_type;
371     l_amount_tbl           amount_tbl_type;
372     l_location_tbl         location_tbl_type;
373     l_org_name_tbl         organization_name_tbl_type;
374     l_need_by_date_tbl     need_by_date_tbl_type;
375     l_promised_date_tbl    promised_date_tbl_type;
376     l_shipment_type_tbl    shipment_type_tbl_type;
377 
378     --
379      /* CLM Changes Start */
380      l_clm_option_num_tbl    clm_option_num_tbl_type;
381      l_CLM_BASE_LINE_NUM_tbl CLM_BASE_LINE_NUM_tbl_type;
382      l_contract_type_tbl CONTRACT_TYPE_tbl_type;
383      l_line_num_display_tbl  LINE_NUM_DISPLAY_tbl_type;
384      l_clm_document VARCHAR2(1) := 'N';  -- Whether its a CLM document or Not
385      /* CLM Changes End */
386 	 --CLM apprvl
387 	 l_draft_id	NUMBER;
388     -- <BUG 3616816 END>
389 
390 /* Bug# 1419139: kagarwal
391 ** Desc: The where clause pol.org_id = msi.organization_id(+) in the
392 ** PO lines cursor, po_line_csr, is not correct as the pol.org_id
393 ** is the operating unit which is not the same as the inventory
394 ** organization_id.
395 **
396 ** We need to use the financials_system_parameter table for the
397 ** inventory organization_id.
398 **
399 ** Also did the similar changes for the Release cursor,po_line_loc_csr.
400 */
401 
402 /* Bug 2401933: sktiwari
403    Modifying cursor po_line_csr to return the translated UOM value
404    instead of unit_meas_lookup_code.
405 */
406 
407 CURSOR po_line_csr(v_document_id NUMBER) IS
408 SELECT pol.line_num,
409        msi.concatenated_segments,
410        pol.item_revision,
411        pol.item_description,
412 --     pol.unit_meas_lookup_code, -- bug 2401933.remove
413        nvl(muom.unit_of_measure_tl, pol.unit_meas_lookup_code), -- bug 2401933.add
414        pol.quantity,
415        pol.unit_price,
416        nvl(pol.amount, pol.quantity * pol.unit_price),
417        pol.CLM_OPTION_NUM,
418        po2.LINE_NUM_DISPLAY --Base line num
419 --       ,pol.contract_type
420        ,lkp1.description
421        ,pol.LINE_NUM_DISPLAY
422   FROM po_lines_all   pol, --CLM Apprvl
423        po_lines_all   po2, -- CLM Apprvl
424        po_lookup_codes lkp1,
425        mtl_system_items_kfv   msi,
426        mtl_units_of_measure   muom,     -- bug 2401933.add
427        financials_system_parameters  fsp
428  WHERE pol.po_header_id = v_document_id
429    AND lkp1.lookup_code(+) = pol.contract_type
430    AND lkp1.lookup_type(+) = decode(pol.order_type_lookup_code,
431                     'QUANTITY', 'PO_FEDERAL_CONTRACT_TYPES_QTY',
432                     'PO_FEDERAL_CONTRACT_TYPES_AMT')
433    AND pol.item_id = msi.inventory_item_id(+)
434    AND NVL(msi.organization_id, fsp.inventory_organization_id) =
435           fsp.inventory_organization_id
436 /* Bug 2299484 fixed. prevented the canceled lines to be displayed
437    in notifications.
438 */
439    AND NVL(pol.cancel_flag,'N') = 'N'
440    AND muom.unit_of_measure (+) = pol.unit_meas_lookup_code  -- bug 2401933.add
441    AND pol.CLM_BASE_LINE_NUM = po2.PO_LINE_ID(+)
442  ORDER BY pol.LINE_NUM_DISPLAY;
443 
444 -- release shipments cursor
445 
446 /* Bug# 1530303: kagarwal
447 ** Desc: We need to change the where clause as the item
448 ** may not be an inventory item. For this case we should
449 ** have an outer join with the mtl_system_items_kfv.
450 **
451 ** Changed the condition:
452 ** pol.item_id = msi.inventory_item_id
453 ** to pol.item_id = msi.inventory_item_id(+)
454 **
455 */
456 
457 /* Bug# 1718725: kagarwal
458 ** Desc: The unit of measure may be null at the shipment level
459 ** hence in this case we need to get the uom from line level.
460 **
461 ** Changed nvl(pll.unit_meas_lookup_code, pol.unit_meas_lookup_code)
462 */
463 /* Bug# 1770951: kagarwal
464 ** Desc: For Releases we should consider the price_override on the shipments
465 ** and not the price on the Blanket PO line as the shipment price could be
466 ** different if the price override is enabled on the Blanket.
467 */
468 
469 /* Bug 2401933: sktiwari
470    Modifying cursor po_line_loc_csr to return the translated UOM value
471    instead of unit_meas_lookup_code.
472 */
473 /* CLM apprvl start - for modification documents only the attributes that are chnaged from the original documents needs to be displayed.*/
474 CURSOR mod_line_csr(v_document_id NUMBER, v_draft_id NUMBER) IS
475 SELECT pol.line_num,
476        msi.concatenated_segments,
477        pol.item_revision,
478        pol.item_description,
479 --     pol.unit_meas_lookup_code, -- bug 2401933.remove
480        nvl(muom.unit_of_measure_tl, pol.unit_meas_lookup_code), -- bug 2401933.add
481        pol.quantity,
482        pol.unit_price,
483        nvl(pol.amount, pol.quantity * pol.unit_price),
484        pol.CLM_OPTION_NUM,
485        po2.LINE_NUM_DISPLAY --Base line num
486 --       ,pol.contract_type
487        ,lkp1.description
488        ,pol.LINE_NUM_DISPLAY
489   FROM po_lines_draft_all   pol, --CLM Apprvl
490        po_lines_draft_all   po2, -- CLM Apprvl
491        po_lookup_codes lkp1,
492        mtl_system_items_kfv   msi,
493        mtl_units_of_measure   muom,     -- bug 2401933.add
494        financials_system_parameters  fsp
495  WHERE pol.po_header_id = v_document_id
496    AND nvl(pol.draft_id, -1) = nvl(v_draft_id, -1)
497    AND lkp1.lookup_code(+) = pol.contract_type
498    AND lkp1.lookup_type(+) = decode(pol.order_type_lookup_code,
499                     'QUANTITY', 'PO_FEDERAL_CONTRACT_TYPES_QTY',
500                     'PO_FEDERAL_CONTRACT_TYPES_AMT')
501    AND pol.item_id = msi.inventory_item_id(+)
502    AND NVL(msi.organization_id, fsp.inventory_organization_id) =
503           fsp.inventory_organization_id
504 /* Bug 2299484 fixed. prevented the canceled lines to be displayed
505    in notifications.
506 */
507    AND NVL(pol.cancel_flag,'N') = 'N'
508    AND muom.unit_of_measure (+) = pol.unit_meas_lookup_code  -- bug 2401933.add
509    AND pol.CLM_BASE_LINE_NUM = po2.PO_LINE_ID(+)
510  ORDER BY pol.LINE_NUM_DISPLAY;
511 /*CLM Apprvl end*/
512 
513  CURSOR po_line_loc_csr(v_document_id NUMBER) IS
514 SELECT pll.shipment_num,
515        msi.concatenated_segments,
516        pol.item_revision,
517        pol.item_description,
518 -- Bug 2401933.start
519 --     nvl(pll.unit_meas_lookup_code, pol.unit_meas_lookup_code)
520 --         unit_meas_lookup_code,
521        nvl(muom.unit_of_measure_tl, pol.unit_meas_lookup_code),
522 -- Bug 2401933.end
523        pll.quantity,
524        nvl(pll.price_override, pol.unit_price) unit_price,
525        hrl.location_code,
526        ood.organization_name,
527        pll.need_by_date,
528        pll.promised_date,
529        pll.shipment_type,
530        --Bug 4950850 Added pll.amount
531        --Bug 5563024 AMOUNT NOT SHOWN FOR A RELEASE SHIPMENT IN APPROVAL NOTIFICATION.
532        nvl(pll.amount, nvl(pll.price_override, pol.unit_price) * pll.quantity)
533   FROM po_lines_all  pol,       		-- CLM apprvl
534        po_line_locations_all pll,		-- CLM apprvl
535        mtl_system_items_kfv msi,
536        hr_locations_all hrl,
537        hz_locations hz,
538        org_organization_definitions ood,
539        mtl_units_of_measure   muom,     -- Bug 2401933.add
540        financials_system_parameters  fsp
541   where  PLL.PO_RELEASE_ID = v_document_id
542   and    PLL.po_line_id    = POL.po_line_id
543   and    PLL.ship_to_location_id = HRL.location_id (+)
544   and    PLL.ship_to_location_id = HZ.location_id (+)
545   and    PLL.ship_to_organization_id = OOD.organization_id
546   and    pol.item_id = msi.inventory_item_id(+)
547   and    NVL(msi.organization_id, fsp.inventory_organization_id) =
548           fsp.inventory_organization_id
549  /* Bug 2299484 fixed. prevented the canceled shipments to be displayed
550    in notifications.
551 */
552    AND NVL(PLL.cancel_flag,'N') = 'N'
553    AND muom.unit_of_measure (+) = pol.unit_meas_lookup_code  -- Bug 2401933.add
554   order by Shipment_num asc;
555 
556 
557 
558 BEGIN
559 
560   if document is null then
561      document := ' ';
562   end if;
563 
564   l_item_type := substr(document_id, 1, instr(document_id, ':') - 1);
565   l_item_key := substr(document_id, instr(document_id, ':') + 1,
566                        length(document_id) - 2);
567 
568   /* Bug# 2353153
569   ** Setting application context
570   */
571 
572   PO_REQAPPROVAL_INIT1.Set_doc_mgr_context(l_item_type, l_item_key);
573 
574   l_document_id := wf_engine.GetItemAttrNumber (itemtype   => l_item_type,
575                                          	itemkey    => l_item_key,
576                                          	aname      => 'DOCUMENT_ID');
577 
578   l_org_id := wf_engine.GetItemAttrNumber (itemtype   => l_item_type,
579                                            itemkey    => l_item_key,
580                                            aname      => 'ORG_ID');
581 
582   l_document_type := wf_engine.GetItemAttrText (itemtype   => l_item_type,
583                                            	itemkey    => l_item_key,
584                                            	aname      => 'DOCUMENT_TYPE');
585 
586   -- CLM Apprvl
587   l_draft_id := po_wf_util_pkg.GetItemAttrNumber (itemtype   => l_item_type,
588                                          	itemkey    => l_item_key,
589                                          	aname      => 'DRAFT_ID');
590 
591   PO_MOAC_UTILS_PVT.set_org_context(l_org_id) ;       -- <R12 MOAC>
592 
593 
594   /* Bug# 1686066: kagarwal
595   ** Desc: Use the functional currency of the PO for the precision of
596   ** line amounts.
597   */
598 
599   l_currency_code := wf_engine.GetItemAttrText
600                                (itemtype   => l_item_type,
601                                 itemkey    => l_item_key,
602                                 aname      => 'FUNCTIONAL_CURRENCY');
603 
604 
605   -- Bug 3668188
606   l_open_form_command := PO_WF_UTIL_PKG.GetItemAttrText
607                                (itemtype   => l_item_type,
608                                 itemkey    => l_item_key,
609                                 aname      => 'OPEN_FORM_COMMAND');
610 
611   -- HTML Orders R12
612   -- Get the PO HTML Page URL's
613   l_view_po_url := PO_WF_UTIL_PKG.GetItemAttrText (
614                               itemtype   => l_item_type,
615                               itemkey    => l_item_key,
616                               aname      => 'VIEW_DOC_URL');
617 
618   l_edit_po_url := PO_WF_UTIL_PKG.GetItemAttrText (
619                               itemtype   => l_item_type,
620                               itemkey    => l_item_key,
621                               aname      => 'EDIT_DOC_URL');
622 
623 -- CLM Aprvl
624  Begin
625      SELECT 'Y' into l_clm_document
626      FROM   po_headers_all h,
627             po_doc_style_headers s
628      WHERE  h.po_header_id = l_document_id
629             AND h.style_id = s.style_id
630             AND Nvl(s.clm_flag,'N') = 'Y';
631  Exception
632  When No_Data_Found Then
633      l_clm_document := 'N';
634  End;
635 -- CLM Aprvl
636 
637 
638 /* Bug# 2668222: kagarwal
639 ** Desc: Using profile PO_NOTIF_LINES_LIMIT to get the maximum
640 ** number of PO lines to be displayed in Approval notification.
641 ** The same profile is also used for Requisitions.
642 */
643   -- <BUG 7006113  START Moved this code to the later section of the procedure >
644   --  max_lines_dsp:= to_number(fnd_profile.value('PO_NOTIF_LINES_LIMIT'));
645 
646   -- if max_lines_dsp is NULL then
647   --   max_lines_dsp := 20;
648   -- end if;
649   -- <BUG 7006113 END>
650 
651     -- <BUG 3616816 START> Fetch Release Shipments/PO Lines data into Tables.
652     --
653     IF ( l_document_type = 'RELEASE' ) THEN
654 
655         OPEN po_line_loc_csr(l_document_id);
656 
657         FETCH po_line_loc_csr BULK COLLECT INTO l_shipment_num_tbl
658                                               , l_item_num_tbl
659                                               , l_item_revision_tbl
660                                               , l_item_desc_tbl
661                                               , l_uom_tbl
662                                               , l_quantity_tbl
663                                               , l_unit_price_tbl
664                                               , l_location_tbl
665                                               , l_org_name_tbl
666                                               , l_need_by_date_tbl
667                                               , l_promised_date_tbl
668                                               , l_shipment_type_tbl
669                                               , l_amount_tbl;        --bug 4950850
670 
671 
672         l_line_count := po_line_loc_csr%ROWCOUNT; -- Get # of records fetched.
673 
674         CLOSE po_line_loc_csr;
675 
676     ELSE
677 	   -- CLM Apprvl. In case of modification document the mod_line_csr needs to opened
678         IF l_draft_id is not null AND l_draft_id <> -1 THEN
679 			OPEN mod_line_csr(l_document_id, l_draft_id);	-- CLM Apprvl
680 
681 			FETCH mod_line_csr BULK COLLECT INTO l_line_num_tbl
682                                           , l_item_num_tbl
683                                           , l_item_revision_tbl
684                                           , l_item_desc_tbl
685                                           , l_uom_tbl
686                                           , l_quantity_tbl
687                                           , l_unit_price_tbl
688                                           , l_amount_tbl
689                                           , l_clm_option_num_tbl
690                                           , l_CLM_BASE_LINE_NUM_tbl
691                                           , l_contract_type_tbl
692                                           , l_line_num_display_tbl;
693 
694 			l_line_count := mod_line_csr%ROWCOUNT; -- Get # of records fetched.
695 		ELSE
696 			OPEN po_line_csr(l_document_id);
697 
698 			FETCH po_line_csr BULK COLLECT INTO l_line_num_tbl
699                                           , l_item_num_tbl
700                                           , l_item_revision_tbl
701                                           , l_item_desc_tbl
702                                           , l_uom_tbl
703                                           , l_quantity_tbl
704                                           , l_unit_price_tbl
705                                           , l_amount_tbl
706                                           , l_clm_option_num_tbl
707                                           , l_CLM_BASE_LINE_NUM_tbl
708                                           , l_contract_type_tbl
709                                           , l_line_num_display_tbl;
710 
711 			l_line_count := po_line_csr%ROWCOUNT; -- Get # of records fetched.
712 
713 			CLOSE po_line_csr;
714 		END IF;
715 
716     END IF;
717     --
718     -- <BUG 3616816 END>
719 
720     max_lines_dsp:= to_number(fnd_profile.value('PO_NOTIF_LINES_LIMIT'));
721 
722     IF max_lines_dsp IS NULL THEN
723 
724 	max_lines_dsp := l_line_count;
725 
726     END IF;
727 
728     -- <BUG 3616816 START> Determine the actual number of records to display
729     -- in the table.
730     --
731     IF ( l_line_count >= max_lines_dsp )
732     THEN
733         l_num_records_to_display := max_lines_dsp;
734     ELSE
735         l_num_records_to_display := l_line_count;
736     END IF;
737     --
738     -- <BUG 3616816 END>
739 
740   if (display_type = 'text/html') then
741 
742     if (nvl(l_document_type, 'PO') <> 'RELEASE') then
743 
744     	l_document := NL || NL || '<!-- PO_LINE_DETAILS -->'|| NL || NL || '<P><B>';
745     	l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_PO_LINE_DETAILS');
746     	l_document := l_document || '</B>' || NL || '<P>';     -- <BUG 3616816>
747 
748         -- <BUG 3616816 START> Only display message if # of actual lines is
749         -- greater than maximum limit.
750         --
751         IF ( l_line_count > max_lines_dsp ) THEN
752 
753             -- Bug 3668188: changed the code check (originally created
754             -- in bug 3607009) that determines which message to show
755             -- based on whether Open Document icon is shown in the notif.
756             -- The value of WF attribute 'OPEN_FORM_COMMAND' is set in a
757             -- previous node, using the get_po_user_msg_attribute procedure.
758             --
759             -- HTML Orders R12
760             -- Check for the URL parameters as well
761             IF  (l_open_form_command IS NULL ) AND
762                 (l_view_po_url IS NULL )       AND
763                 (l_edit_po_url IS NULL )
764             THEN
765                -- "The first [COUNT] Purchase Order lines are summarized below."
766                FND_MESSAGE.set_name('PO','PO_WF_NOTIF_PO_LINE_MESG_TRUNC');
767             ELSE
768                -- "The first [COUNT] Purchase Order lines are summarized
769                -- below. For information on additional lines, please click
770                -- the Open Document icon."
771                FND_MESSAGE.set_name('PO','PO_WF_NOTIF_PO_LINE_MESG');
772             END IF;
773 
774             FND_MESSAGE.set_token('COUNT',to_char(max_lines_dsp));
775             line_mesg := FND_MESSAGE.get;
776             l_document := l_document || line_mesg || '<P>';
777 
778 
779         END IF;
780         --
781         -- <BUG 3616816 END>
782 
783     	l_document := l_document || NL || '<TABLE border=1 cellpadding=2 cellspacing=1 summary="' ||  fnd_message.get_string('ICX','ICX_POR_TBL_PO_TO_APPROVE_SUM') || '"> '|| NL;
784 
785     	l_document := l_document || '<TR>' || NL;
786 
787     	IF (l_clm_document='Y') THEN
788     	l_document := l_document || '<TH  id="lineNumDisp_1">' ||
789     	               fnd_message.get_string('PO', 'PO_WF_NOTIF_LINE_NUMBER') || '</TH>' || NL;
790     	else
791         l_document := l_document || '<TH  id="lineNum_1">' ||
792    	               fnd_message.get_string('PO', 'PO_WF_NOTIF_LINE_NUMBER') || '</TH>' || NL;
793    	    end if;
794 
795       IF (l_clm_document='Y') THEN
796        l_document := l_document || '<TH  id="BaselineNum_1">' ||
797     	               fnd_message.get_string('PO', 'PO_WF_NOTIF_BASE_LINE_NUMBER') || '</TH>' || NL;
798 
799    	   l_document := l_document || '<TH  id="OptionlineNum_1">' ||
800         	           fnd_message.get_string('PO', 'PO_WF_NOTIF_OPTION_NUMBER')   || '</TH>' || NL;
801       END IF;
802 
803 
804     	l_document := l_document || '<TH  id="itemNum_1">' ||
805     	              fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_NUMBER') || '</TH>' || NL;
806 
807    	    l_document := l_document || '<TH  id="itemRev_1">' ||
808         	      fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_REVISION') || '</TH>' || NL;
809 
810     	l_document := l_document || '<TH  id="itemDesc_1">' ||
811                   	fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_DESC') || '</TH>' || NL;
812 
813         IF (l_clm_document='Y') THEN
814         l_document := l_document || '<TH  id="ContractType_1">' ||
815     	               fnd_message.get_string('PO', 'PO_WF_NOTIF_CONTRACT_TYPE') || '</TH>' || NL;
816         END IF;
817 
818     	l_document := l_document || '<TH  id="uom_1">' ||
819                   	fnd_message.get_string('PO', 'PO_WF_NOTIF_UOM') || '</TH>' || NL;
820 
821     	l_document := l_document || '<TH  id="quant_1">' ||
822                   fnd_message.get_string('PO', 'PO_WF_NOTIF_QUANTITY') || '</TH>' || NL;
823 
824 
825     	l_document := l_document || '<TH  id="unitPrice_1">' ||
826                   fnd_message.get_string('PO', 'PO_WF_NOTIF_UNIT_PRICE') || '</TH>' || NL;
827 
828     	l_document := l_document || '<TH  id="lineAmt_1">' ||
829                   fnd_message.get_string('PO', 'PO_WF_NOTIF_LINE_AMOUNT') || '</TH>' || NL;
830 
831     	l_document := l_document || '</TR>' || NL;
832 
833         -- curr_len  := lengthb(l_document);
834         -- prior_len := curr_len;
835 
836         FOR i IN 1..l_num_records_to_display LOOP              -- <BUG 3616816>
837 
838                 /* Exit the cursor if the current document length and 2 times the
839                 ** length added in prior line exceeds 32000 char */
840 		-- < BUG 7006113 START Commented the loop to avoid the check so that maximum
841                 --  lines can be displayed >
842                 -- if (curr_len + (2 * (curr_len - prior_len))) >= 32000 then
843                 --  exit;
844                 --  end if;
845 		--  prior_len := curr_len;
846 		-- < BUG 7006113 END >
847 
848       		l_document := l_document || '<TR>' || NL;
849 IF (l_clm_document='Y') THEN
850     l_document := l_document || '<TD nowrap align=center headers="lineNumDisp_1">'
851 						    || nvl(l_line_num_display_tbl(i), ' ') || '</TD>' || NL;
852 else
853 	l_document := l_document || '<TD nowrap align=center headers="lineNum_1">'
854 						    || nvl(to_char(l_line_num_tbl(i)), ' ') || '</TD>' || NL;
855 end if;
856 
857           IF (l_clm_document='Y') THEN
858           l_document := l_document || '<TD nowrap align=center headers="BaselineNum_1">'
859 						    || nvl(to_char(l_CLM_BASE_LINE_NUM_tbl(i)), ' ') || '</TD>' || NL;
860 
861           l_document := l_document || '<TD nowrap align=center headers="OptionlineNum_1">'
862 						    || nvl(to_char(l_clm_option_num_tbl(i)), ' ') || '</TD>' || NL;
863           END IF;
864 
865       		l_document := l_document || '<TD nowrap headers="itemNum_1">'
866 						    || nvl(l_item_num_tbl(i), ' ') || '</TD>' || NL;
867       		l_document := l_document || '<TD nowrap headers="itemRev_1">'
868 						    || nvl(l_item_revision_tbl(i), ' ') || '</TD>' || NL;
869                   /* Bug 11825584 removing nowrap and adding align=left*/
870       		l_document := l_document || '<TD align=left headers="itemDesc_1">'
871 						    || nvl(l_item_desc_tbl(i), ' ') || '</TD>' || NL;
872 
873 		  IF (l_clm_document='Y') THEN
874             l_document := l_document || '<TD nowrap headers="ContractType_1">'
875 						    || nvl(l_contract_type_tbl(i), ' ') || '</TD>' || NL;
876           END IF;
877 
878 			l_document := l_document || '<TD nowrap headers="uom_1">'
879 						    || nvl(l_uom_tbl(i), ' ') || '</TD>' || NL;
880       		l_document := l_document || '<TD nowrap align=right headers="quant_1">'
881 						    || nvl(to_char(l_quantity_tbl(i)), ' ') || '</TD>' || NL;
882 
883 
884 
885 /* Bug 2868931: kagarwal
886 ** We will not format the unit price on the lines in notifications
887 */
888                 -- Bug 3547777. Added the nvl clauses to unit_price and line_
889                 -- amount so that box is still displayed even if value is null.
890       		l_document := l_document || '<TD nowrap align=right headers="unitPrice_1">' ||
891                      nvl(PO_WF_REQ_NOTIFICATION.FORMAT_CURRENCY_NO_PRECESION(l_currency_code,l_unit_price_tbl(i)),' ') || '</TD>' || NL; -- <BUG 7006113>
892 
893       		l_document := l_document || '<TD nowrap align=right headers="lineAmt_1">' ||
894                   nvl(TO_CHAR(l_amount_tbl(i), FND_CURRENCY.GET_FORMAT_MASK(
895                               l_currency_code, 30)),' ') || '</TD>' || NL;
896 
897       		l_document := l_document || '</TR>' || NL;
898 
899                 -- <BUG 7006113 START>
900 		--curr_len  := lengthb(l_document);
901 
902                 wf_notification.writetoclob(document, l_document);
903 
904                 l_document := NULL;
905 
906 		EXIT WHEN i = l_num_records_to_display;
907 		-- <BUG 7006113 END>
908     	end loop;
909 
910     else    -- release
911 
912     	l_document := NL || NL || '<!-- RELEASE_SHIPMENT_DETAILS -->'|| NL || NL || '<P><B>';
913     	l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_SHIP_DETAILS');
914     	l_document := l_document || '</B>' || NL || '<P>';
915 
916         -- <BUG 3616816 START> Only display message if # of actual lines is
917         -- greater than maximum limit.
918         --
919         IF ( l_line_count > max_lines_dsp )
920         THEN
921             FND_MESSAGE.set_name('PO','PO_WF_NOTIF_PO_REL_SHIP_MESG');
922             FND_MESSAGE.set_token('COUNT',to_char(max_lines_dsp));
923             line_mesg := FND_MESSAGE.get;
924             l_document := l_document || line_mesg || '<P>';
925         END IF;
926         --
927         -- <BUG 3616816 END>
928 
929     	l_document := l_document || '<TABLE border=1 cellpadding=2 cellspacing=1 summary="' ||  fnd_message.get_string('ICX','ICX_POR_TBL_BL_TO_APPROVE_SUM') || '"> '|| NL;
930 
931     	l_document := l_document || '<TR>' || NL;
932 
933     	l_document := l_document || '<TH  id="shipNum_2">' ||
934    	               fnd_message.get_string('PO', 'PO_WF_NOTIF_SHIP_NUMBER') || '</TH>' || NL;
935 
936     	l_document := l_document || '<TH  id="itemNum_2">' ||
937     	              fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_NUMBER') || '</TH>' || NL;
938 
939    	l_document := l_document || '<TH  id="itemRev_2">' ||
940         	      fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_REVISION') || '</TH>' || NL;
941 
942     	l_document := l_document || '<TH  id="itemDesc_2">' ||
943                   	fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_DESC') || '</TH>' || NL;
944 
945     	l_document := l_document || '<TH  id="uom_2">' ||
946                   	fnd_message.get_string('PO', 'PO_WF_NOTIF_UOM') || '</TH>' || NL;
947 
948     	l_document := l_document || '<TH  id="quant_2">' ||
949                   fnd_message.get_string('PO', 'PO_WF_NOTIF_QUANTITY') || '</TH>' || NL;
950 
951     	l_document := l_document || '<TH  id="unitPrice_2">' ||
952                   fnd_message.get_string('PO', 'PO_WF_NOTIF_UNIT_PRICE') || '</TH>' || NL;
953 
954     	l_document := l_document || '<TH  id="location_2">' ||
955                   fnd_message.get_string('PO', 'PO_WF_NOTIF_LOCATION') || '</TH>' || NL;
956 
957     	l_document := l_document || '<TH  id="shipToOrg_2">' ||
958                   fnd_message.get_string('PO', 'POA_SHIP_TO_ORG') || '</TH>' || NL;
959 
960     	l_document := l_document || '<TH  id="needByDate_2">' ||
961                   fnd_message.get_string('PO', 'PO_WF_NOTIF_NEED_BY_DATE') || '</TH>' || NL;
962 	/* bug 4950850 */
963        	l_document := l_document || '<TH  id="lineAmt_2">' ||
964                   fnd_message.get_string('PO', 'PO_WF_NOTIF_AMOUNT') || '</TH>' || NL;
965 
966     	l_document := l_document || '</TR>' || NL;
967 
968         -- curr_len  := lengthb(l_document);
969         -- prior_len := curr_len;
970 
971         FOR i IN 1..l_num_records_to_display LOOP              -- <BUG 3616816>
972 
973                 /* Exit the cursor if the current document length and 2 times the
974                 ** length added in prior line exceeds 32000 char */
975                 -- < BUG 7006113 START Commented the loop to avoid the check so that
976 		--   maximum lines can be displayed >
977                 -- if (curr_len + (2 * (curr_len - prior_len))) >= 32000 then
978                 --   exit;
979                 -- end if;
980 		-- prior_len := curr_len;
981 		-- < BUG 7006113 END >
982 
983       		l_document := l_document || '<TR>' || NL;
984 
985    		l_document := l_document || '<TD nowrap align=center headers="shipNum_2">'
986 				|| nvl(to_char(l_shipment_num_tbl(i)), ' ') || '</TD>' || NL;
987       		l_document := l_document || '<TD nowrap  headers="itemNum_2">'
988 				|| nvl(l_item_num_tbl(i), ' ') || '</TD>' || NL;
989       		l_document := l_document || '<TD nowrap  headers="itemRev_2">'
990 				|| nvl(l_item_revision_tbl(i), ' ') || '</TD>' || NL;
991           /* Bug 11825584 removing nowrap and adding align=left*/
992       		l_document := l_document || '<TD align=left headers="itemDesc_2">'
993 				|| nvl(l_item_desc_tbl(i), ' ') || '</TD>' || NL;
994       		l_document := l_document || '<TD nowrap  headers="uom_2">'
995 				|| nvl(l_uom_tbl(i), ' ') || '</TD>' || NL;
996       		l_document := l_document || '<TD nowrap align=right  headers="quant_2">'
997 				|| nvl(to_char(l_quantity_tbl(i)), ' ') || '</TD>' || NL;
998 
999 /* Bug 2868931: kagarwal
1000 ** We will not format the unit price on the lines in notifications
1001 */
1002 
1003       		l_document := l_document || '<TD nowrap align=right  headers="unitPrice_2">' ||
1004                                   nvl(PO_WF_REQ_NOTIFICATION.FORMAT_CURRENCY_NO_PRECESION(
1005 				      l_currency_code,l_unit_price_tbl(i)),' ') || '</TD>' || NL;  -- <BUG 7006113>
1006 
1007       		l_document := l_document || '<TD nowrap  headers="location_2">'
1008 				|| nvl(l_location_tbl(i), ' ') || '</TD>' || NL;
1009       		l_document := l_document || '<TD nowrap  headers="shipToOrg_2">'
1010 				|| nvl(l_org_name_tbl(i), ' ') || '</TD>' || NL;
1011 	      	l_document := l_document || '<TD nowrap  headers="needByDate_2">'
1012 				|| to_char(l_need_by_date_tbl(i) ,FND_PROFILE.VALUE_SPECIFIC('ICX_DATE_FORMAT_MASK', fnd_global.user_id),
1013 				                                  'NLS_CALENDAR = ''' || NVL( FND_PROFILE.VALUE_SPECIFIC('FND_FORMS_USER_CALENDAR', fnd_global.user_id) ,'GREGORIAN' ) || '''') || '</TD>' || NL;
1014                 /* bug 4950850 */
1015                 l_document := l_document || '<TD nowrap align=right headers="lineAmt_2">' ||
1016                   nvl(TO_CHAR(l_amount_tbl(i), FND_CURRENCY.GET_FORMAT_MASK(
1017                               l_currency_code, 30)),' ') || '</TD>' || NL;
1018       		l_document := l_document || '</TR>' || NL;
1019 
1020                 -- <BUG 7006113 START>
1021 		-- curr_len  := lengthb(l_document);
1022 
1023                 wf_notification.writetoclob(document, l_document);
1024 
1025                 l_document := NULL;
1026 
1027 		EXIT WHEN i = l_num_records_to_display;
1028 		-- <BUG 7006113 END>
1029 
1030     	end loop;
1031 
1032     end if;
1033     l_document := l_document || '</TABLE></P>' || NL;
1034 
1035     --<BUG 7614278 Added condition to check whether the document has value and if
1036     --so call the function WriteToClob().
1037     curr_len := lengthb(l_document);
1038     IF (NVL(curr_len,0) > 0 ) THEN
1039 	wf_notification.writetoclob(document, l_document); 	-- <BUG 7006113>
1040     END IF;
1041     -- document := l_document; -- <BUG 7006113>
1042 
1043   elsif (display_type = 'text/plain') then
1044 
1045     if (nvl(l_document_type, 'PO') <> 'RELEASE') then
1046 
1047     	l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_PO_LINE_DETAILS') || NL || NL;
1048 
1049         -- <BUG 3616816 START> Only display message if # of actual lines is
1050         -- greater than maximum limit.
1051         --
1052         IF ( l_line_count > max_lines_dsp ) THEN
1053 
1054             -- Bug 3668188: changed the code check (originally created
1055             -- in bug 3607009) that determines which message to show
1056             -- based on whether Open Document icon is shown in then notif.
1057             -- The value of WF attribute 'OPEN_FORM_COMMAND' is set in a
1058             -- previous node, using the get_po_user_msg_attribute procedure.
1059             -- HTML Orders R12
1060             -- Check for the URL parameters as well
1061             IF  (l_open_form_command IS NULL) AND
1062                 (l_view_po_url IS NULL)       AND
1063                 (l_edit_po_url IS NULL)
1064             THEN
1065                 -- "The first [COUNT] Purchase Order lines are summarized below."
1066                 FND_MESSAGE.set_name('PO','PO_WF_NOTIF_PO_LINE_MESG_TRUNC');
1067             ELSE
1068                 -- "The first [COUNT] Purchase Order lines are summarized
1069                 -- below. For information on additional lines, please click
1070                 -- the Open Document icon."
1071                 FND_MESSAGE.set_name('PO','PO_WF_NOTIF_PO_LINE_MESG');
1072             END IF;
1073 
1074             FND_MESSAGE.set_token('COUNT',to_char(max_lines_dsp));
1075             line_mesg := FND_MESSAGE.get;
1076             l_document := l_document || line_mesg || NL || NL;
1077 
1078         END IF;
1079         --
1080         -- <BUG 3616816 END>
1081 
1082         -- curr_len  := lengthb(l_document);
1083         -- prior_len := curr_len;
1084 
1085         FOR i IN 1..l_num_records_to_display LOOP              -- <BUG 3616816>
1086 
1087                 /* Exit the cursor if the current document length and 2 times the
1088                 ** length added in prior line exceeds 32000 char */
1089                 -- < BUG 7006113 START Commented the loop to avoid the check so
1090 		--   that maximum lines can be displayed >
1091                 --   if (curr_len + (2 * (curr_len - prior_len))) >= 32000 then
1092                 --     exit;
1093                 --   end if;
1094 		--   prior_len := curr_len;
1095 		-- < BUG 7006113 END >
1096         IF (not l_clm_document='Y') THEN
1097 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_LINE_NUMBER') || ':' || to_char(l_line_num_tbl(i)) || NL;
1098 		else
1099 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_LINE_NUMBER') || ':' || to_char(l_line_num_display_tbl(i)) || NL;
1100 		end if;
1101     IF (l_clm_document='Y') THEN
1102     l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_BASE_LINE_NUMBER')  || ':' || to_char(l_CLM_BASE_LINE_NUM_tbl(i)) || NL;
1103     l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_OPTION_NUMBER') || ':' || to_char(l_clm_option_num_tbl(i)) || NL;
1104     end if;
1105 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_NUMBER') || ': ' || l_item_num_tbl(i) || NL;
1106 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_REVISION') || ': ' || l_item_revision_tbl(i) || NL;
1107 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_DESC') || ': ' || l_item_desc_tbl(i) || NL;
1108 
1109 		IF (l_clm_document='Y') THEN
1110 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_CONTRACT_TYPE') || ': ' || l_contract_type_tbl(i) || NL;
1111 		end if;
1112 
1113 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_UOM') || ': ' || l_uom_tbl(i) || NL;
1114 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_QUANTITY') || ': ' || to_char(l_quantity_tbl(i)) || NL;
1115 
1116 /* Bug 2868931: kagarwal
1117 ** We will not format the unit price on the lines in notifications
1118 */
1119 
1120 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_UNIT_PRICE') || ': '
1121 					|| PO_WF_REQ_NOTIFICATION.FORMAT_CURRENCY_NO_PRECESION(l_currency_code,l_unit_price_tbl(i)) || NL;
1122 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_LINE_AMOUNT') || ': '
1123 					|| to_char(l_amount_tbl(i), FND_CURRENCY.GET_FORMAT_MASK(l_currency_code, 30)) || NL || NL;
1124 
1125 	    -- < BUG 7006113 START >
1126             -- curr_len  := lengthb(l_document);
1127 
1128             wf_notification.writetoclob(document, l_document);
1129 
1130 	    l_document := NULL;
1131 
1132 	    EXIT WHEN i = l_num_records_to_display;
1133 	    -- < BUG 7006113 END >
1134 
1135 	end loop;
1136 
1137     else   -- release
1138 
1139     	l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_SHIP_DETAILS') || NL || NL || NL;
1140 
1141         -- <BUG 3616816 START> Only display message if # of actual lines is
1142         -- greater than maximum limit.
1143         --
1144         IF ( l_line_count > max_lines_dsp )
1145         THEN
1146             FND_MESSAGE.set_name('PO','PO_WF_NOTIF_PO_REL_SHIP_MESG');
1147             FND_MESSAGE.set_token('COUNT',to_char(max_lines_dsp));
1148             line_mesg := FND_MESSAGE.get;
1149             l_document := l_document || line_mesg || NL || NL;
1150         END IF;
1151         --
1152         -- <BUG 3616816 END>
1153 
1154         -- curr_len  := lengthb(l_document);
1155         -- prior_len := curr_len;
1156 
1157         FOR i IN 1..l_num_records_to_display LOOP              -- <BUG 3616816>
1158 
1159                 /* Exit the cursor if the current document length and 2 times the
1160                 ** length added in prior line exceeds 32000 char */
1161                 -- <BUG 7006113 START Commented the loop to avoid the check so that
1162 		--  maximum lines can be displayed
1163                 --  if (curr_len + (2 * (curr_len - prior_len))) >= 32000 then
1164                 --  exit;
1165                 --  end if;
1166 		--  prior_len := curr_len;
1167 		-- <BUG 7006113 END>
1168 
1169 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_SHIP_NUMBER') || ': ' || to_char(l_shipment_num_tbl(i)) || NL;
1170 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_NUMBER') || ': ' || l_item_num_tbl(i) || NL;
1171 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_REVISION') || ': ' || l_item_revision_tbl(i) || NL;
1172 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ITEM_DESC') || ': ' || l_item_desc_tbl(i) || NL;
1173 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_UOM') || ': ' || l_uom_tbl(i) || NL;
1174 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_QUANTITY') || ': ' || to_char(l_quantity_tbl(i)) || NL;
1175 
1176 /* Bug 2868931: kagarwal
1177 ** We will not format the unit price on the lines in notifications
1178 */
1179 
1180 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_UNIT_PRICE') || ': '
1181 					||  PO_WF_REQ_NOTIFICATION.FORMAT_CURRENCY_NO_PRECESION(l_currency_code,l_unit_price_tbl(i)) || NL;
1182                 -- bug 4950850
1183 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_AMOUNT') || ': '
1184 					|| to_char(l_amount_tbl(i), FND_CURRENCY.GET_FORMAT_MASK(l_currency_code, 30)) || NL;
1185 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_LOCATION') || ': ' || l_location_tbl(i) || NL;
1186 		l_document := l_document || fnd_message.get_string('PO', 'POA_SHIP_TO_ORG') || ': ' || l_org_name_tbl(i) || NL;
1187                 l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_NEED_BY_DATE') || ': ' || to_char(l_need_by_date_tbl(i),FND_PROFILE.VALUE_SPECIFIC('ICX_DATE_FORMAT_MASK', fnd_global.user_id),
1188                                                                            'NLS_CALENDAR = ''' || NVL( FND_PROFILE.VALUE_SPECIFIC('FND_FORMS_USER_CALENDAR', fnd_global.user_id) ,'GREGORIAN') || '''') || NL || NL;
1189 
1190             -- <BUG 7006113 START>
1191 	    -- curr_len  := lengthb(l_document);
1192 
1193 
1194             wf_notification.writetoclob(document, l_document);
1195 
1196             l_document := NULL;
1197 
1198 	    EXIT WHEN i = l_num_records_to_display;
1199 	    -- <BUG 7006113 END>
1200 
1201 	end loop;
1202 
1203     end if;
1204 
1205     --<BUG 7614278 Added condition to check whether the document has value and if
1206     --so call the function WriteToClob().
1207     curr_len := lengthb(l_document);
1208     IF (NVL(curr_len,0) > 0 ) THEN
1209 	wf_notification.writetoclob(document, l_document); -- <BUG 7006113>
1210     END IF;
1211     -- document := l_document; -- <Bug 7006113>
1212   end if;
1213 
1214 END get_po_lines_details;
1215 
1216 PROCEDURE get_action_history (	 document_id	in	varchar2,
1217                                  display_type	in	varchar2,
1218                                  document	in out	NOCOPY varchar2,
1219                                  document_type	in out	NOCOPY varchar2) IS
1220 
1221     l_item_type    wf_items.item_type%TYPE;
1222     l_item_key     wf_items.item_key%TYPE;
1223 
1224     l_document_id      po_lines.po_header_id%TYPE;
1225     l_org_id           po_lines.org_id%TYPE;
1226     l_doc_type_code    VARCHAR2(80);
1227 
1228     l_document         VARCHAR2(32000) := '';
1229 
1230     -- Bug 3668188: added new local var. note: the length of this
1231     -- varchar was determined based on the length in POXWPA1B.pls,
1232     -- which is the other place 'OPEN_FORM_COMMAND' attribute is used
1233     l_open_form_command VARCHAR2(200);
1234 
1235     l_view_po_url varchar2(1000);   -- HTML Orders R12
1236     l_edit_po_url varchar2(1000);   -- HTML Orders R12
1237 
1238     NL                 VARCHAR2(1) := fnd_global.newline;
1239 
1240     -- <BUG 3616816 START> Declare TABLEs for each column that is selected
1241     -- from history_csr cursor.
1242     --
1243     TYPE sequence_num_tbl_type IS TABLE OF PO_ACTION_HISTORY.sequence_num%TYPE;
1244     TYPE full_name_tbl_type IS TABLE OF PER_ALL_PEOPLE_F.full_name%TYPE;
1245     TYPE displayed_field_tbl_type IS TABLE OF PO_LOOKUP_CODES.displayed_field%TYPE;
1246     TYPE action_date_tbl_type IS TABLE OF PO_ACTION_HISTORY.action_date%TYPE;
1247     TYPE note_tbl_type IS TABLE OF PO_ACTION_HISTORY.note%TYPE;
1248     TYPE object_revision_num_tbl_type IS TABLE OF PO_ACTION_HISTORY.object_revision_num%TYPE;
1249     TYPE employee_id_tbl_type IS TABLE OF PO_ACTION_HISTORY.employee_id%TYPE;
1250     TYPE created_by_tbl_type IS TABLE OF PO_ACTION_HISTORY.created_by%TYPE;
1251 
1252     l_sequence_num_tbl         sequence_num_tbl_type;
1253     l_employee_name_tbl        full_name_tbl_type;
1254     l_action_tbl               displayed_field_tbl_type;
1255     l_action_date_tbl          action_date_tbl_type;
1256     l_note_tbl                 note_tbl_type;
1257     l_object_revision_num_tbl  object_revision_num_tbl_type;
1258     l_employee_id_tbl          employee_id_tbl_type;
1259     l_created_by_tbl           created_by_tbl_type;
1260     --
1261     -- <BUG 3616816 END>
1262 
1263   --SQL What: Query action history which is updated by both buyer and vendor
1264   --SQL Why:  Since vendor doesn't have employee id, added outer join;
1265   -- CLM Apprvl. Introduced object_sub_type_code condition to get the proper records in case of modification document.
1266   CURSOR history_csr(v_document_id NUMBER, v_doc_type_code VARCHAR2, v_doc_sub_type_code VARCHAR2) IS
1267     SELECT poh.SEQUENCE_NUM,
1268            per.FULL_NAME,
1269            polc.DISPLAYED_FIELD,
1270            poh.ACTION_DATE,
1271            poh.NOTE,
1272            poh.OBJECT_REVISION_NUM,
1273            poh.employee_id, /* bug 2788683 */
1274            poh.created_by /* bug 2788683 */
1275       from po_action_history  poh,
1276            per_all_people_f   per, -- Bug 3404451
1277            po_lookup_codes    polc
1278      where OBJECT_TYPE_CODE = v_doc_type_code
1279 	   and poh.object_sub_type_code = v_doc_sub_type_code
1280        and poh.action_code = polc.lookup_code
1281        and POLC.LOOKUP_TYPE IN ('APPROVER ACTIONS','CONTROL ACTIONS')
1282        and per.person_id(+) = poh.employee_id /* bug 2788683 */
1283        and trunc(sysdate) between per.effective_start_date(+)
1284                               and per.effective_end_date(+)
1285        and OBJECT_ID = v_document_id
1286     UNION ALL
1287     SELECT poh.SEQUENCE_NUM,
1288            per.FULL_NAME,
1289            NULL,
1290            poh.ACTION_DATE,
1291            poh.NOTE,
1292            poh.OBJECT_REVISION_NUM,
1293            poh.employee_id, /* bug 2788683 */
1294            poh.created_by /* bug 2788683 */
1295       from po_action_history  poh,
1296            per_all_people_f   per -- Bug 3404451
1297      where OBJECT_TYPE_CODE = v_doc_type_code
1298 	   and poh.object_sub_type_code = v_doc_sub_type_code
1299        and poh.action_code is null
1300        and per.person_id(+) = poh.employee_id /* bug 2788683 */
1301        and trunc(sysdate) between per.effective_start_date(+)
1302                               and per.effective_end_date(+)
1303        and OBJECT_ID = v_document_id
1304    order by 1 desc;
1305 
1306   i                         NUMBER := 0;
1307   max_actions_dsp           NUMBER := 20;
1308   l_action_count            NUMBER; -- <BUG 3616816> # of action history records
1309   l_num_records_to_display  NUMBER; -- <BUG 3616816> actual # of records to display in table
1310   action_mesg              fnd_new_messages.message_text%TYPE; --Bug 4695601
1311   curr_len                  NUMBER := 0;
1312   prior_len                 NUMBER := 0;
1313 
1314   /* Bug 2788683 start */
1315   l_user_name        fnd_user.user_name%TYPE;
1316   l_vendor_name      hz_parties.party_name%TYPE;
1317   l_party_name       hz_parties.party_name%TYPE;
1318   /* Bug 2788683 end */
1319   l_supplier         po_vendors.vendor_name%TYPE; --<BUG 7475571>
1320   l_draft_id		NUMBER;
1321   l_doc_sub_type_code po_action_history.object_sub_type_code%TYPE; -- CLM Apprvl
1322   l_draft_type PO_DRAFTS.DRAFT_TYPE%TYPE; -- PAR Approval
1323 
1324 BEGIN
1325 
1326   l_item_type := substr(document_id, 1, instr(document_id, ':') - 1);
1327   l_item_key := substr(document_id, instr(document_id, ':') + 1,
1328                        length(document_id) - 2);
1329 
1330   l_document_id := wf_engine.GetItemAttrNumber
1331                                         (itemtype   => l_item_type,
1332                                          itemkey    => l_item_key,
1333                                          aname      => 'DOCUMENT_ID');
1334 
1335   l_draft_id := po_wf_util_pkg.GetItemAttrNumber
1336                                         (itemtype   => l_item_type,
1337                                          itemkey    => l_item_key,
1338                                          aname      => 'DRAFT_ID');
1339 
1340   l_org_id := wf_engine.GetItemAttrNumber
1341                                         (itemtype   => l_item_type,
1342                                          itemkey    => l_item_key,
1343                                          aname      => 'ORG_ID');
1344 
1345   l_doc_type_code := wf_engine.GetItemAttrText (itemtype   => l_item_type,
1346                                            	itemkey    => l_item_key,
1347                                            	aname      => 'DOCUMENT_TYPE');
1348 
1349   -- CLM Apprvl, object sub type code for mods need to recorded as 'MODIFICATION' in po action history
1350   if l_draft_id is not null and l_draft_id <> -1 then
1351       -- pAR Approval
1352       l_draft_type := wf_engine.GetItemAttrText (itemtype   => l_item_type,
1353                                            	itemkey    => l_item_key,
1354                                            	aname      => 'DRAFT_TYPE');
1355       IF l_draft_type = 'PAR' THEN
1356         l_doc_sub_type_code := 'POST_AWARD_REQUEST';
1357       ELSE
1358 	    l_doc_sub_type_code := 'MODIFICATION';
1359 	  END IF;
1360   else
1361 	  l_doc_sub_type_code := wf_engine.GetItemAttrText (itemtype   => l_item_type,
1362 												itemkey    => l_item_key,
1363 												aname      => 'DOCUMENT_SUBTYPE');
1364   end if;
1365 
1366   PO_MOAC_UTILS_PVT.set_org_context(l_org_id) ;       -- <R12 MOAC>
1367 
1368   -- Bug 3668188
1369   l_open_form_command :=  PO_WF_UTIL_PKG.GetItemAttrText
1370                                (itemtype   => l_item_type,
1371                                 itemkey    => l_item_key,
1372                                 aname      => 'OPEN_FORM_COMMAND');
1373 
1374   -- HTML Orders R12
1375   -- Get the PO HTML Page URL's
1376   l_view_po_url := PO_WF_UTIL_PKG.GetItemAttrText (
1377                               itemtype   => l_item_type,
1378                               itemkey    => l_item_key,
1379                               aname      => 'VIEW_DOC_URL');
1380 
1381   l_edit_po_url := PO_WF_UTIL_PKG.GetItemAttrText (
1382                               itemtype   => l_item_type,
1383                               itemkey    => l_item_key,
1384                               aname      => 'EDIT_DOC_URL');
1385 
1386 /* Bug# 2577478: kagarwal
1387 ** Desc: Added a new attribute ACT_HST_IN_NTF in wf definition for
1388 ** users to specify the number of PO actions to be displayed in a
1389 ** notification.
1390 ** If the attribute does not exist or is null, then we would use default
1391 ** value of 20.
1392 */
1393 
1394   max_actions_dsp:= PO_WF_UTIL_PKG.GetItemAttrNumber (itemtype   => l_item_type,
1395                                            itemkey    => l_item_key,
1396                                            aname      => 'ACT_HST_IN_NTF');
1397 
1398   if max_actions_dsp is NULL then
1399      max_actions_dsp := 20;
1400   end if;
1401 
1402     -- <BUG 3616816 START> Fetch all Action History data into Tables.
1403     --
1404 	--CLM Apprvl. for modification documents draft_id is recorded as the object_id of po_action_history.
1405 	if l_draft_id is not null and l_draft_id <> -1 then
1406 		OPEN history_csr(l_draft_id,l_doc_type_code,l_doc_sub_type_code);
1407 	else
1408 		OPEN history_csr(l_document_id,l_doc_type_code,l_doc_sub_type_code);
1409 	end if;
1410 
1411     FETCH history_csr BULK COLLECT INTO l_sequence_num_tbl
1412                                       , l_employee_name_tbl
1413                                       , l_action_tbl
1414                                       , l_action_date_tbl
1415                                       , l_note_tbl
1416                                       , l_object_revision_num_tbl
1417                                       , l_employee_id_tbl
1418                                       , l_created_by_tbl;
1419 
1420     l_action_count := history_csr%ROWCOUNT; -- Get # of records fetched.
1421 
1422     CLOSE history_csr;
1423     --
1424     -- <BUG 3616816 END>
1425 
1426     -- <BUG 3616816 START> Only display message if # of actual Action History
1427     -- records is greater than maximum limit.
1428     --
1429     IF  ( l_action_count > max_actions_dsp ) THEN
1430 
1431         l_num_records_to_display := max_actions_dsp;
1432 
1433         -- Bug 3668188: changed the code check (originally created
1434         -- in bug 3607009) that determines which message to show
1435         -- based on whether Open Document icon is shown in then notif.
1436         -- The value of WF attribute 'OPEN_FORM_COMMAND' is set in a
1437         -- previous node, using the get_po_user_msg_attribute procedure.
1438         --
1439         IF  (l_open_form_command IS NULL) AND
1440             (l_view_po_url IS NULL)       AND
1441             (l_edit_po_url IS NULL)
1442         THEN
1443             -- "The last [COUNT] Approval History details are summarized below."
1444             FND_MESSAGE.set_name('PO','PO_WF_NOTIF_PO_ACT_MESG_TRUNC');
1445         ELSE
1446             -- "The last [COUNT] Approval History details are summarized below.
1447             -- For information on additional Approval History, please click the
1448             -- Open Document icon."
1449             FND_MESSAGE.set_name('PO','PO_WF_NOTIF_PO_ACT_MESG');
1450         END IF;
1451 
1452         FND_MESSAGE.set_token('COUNT',to_char(max_actions_dsp));
1453         action_mesg := FND_MESSAGE.get;
1454 
1455     ELSE
1456 
1457         l_num_records_to_display := l_action_count;
1458         action_mesg := NULL;
1459 
1460     END IF;
1461     --
1462     -- <BUG 3616816 END>
1463 
1464   if (display_type = 'text/html') then
1465 
1466     l_document := NL || NL || '<!-- ACTION_HISTORY -->'|| NL || NL || '<P><B>';
1467     l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ACTION_HISTORY') || NL;
1468     l_document := l_document || '</B>' || NL || NL || '<P>';   -- <BUG 3616816>
1469 
1470     -- <BUG 3616816 START> Action History message may be NULL. Only append it
1471     -- and corresponding line breaks if there is a message to display.
1472     --
1473     IF ( action_mesg IS NOT NULL )
1474     THEN
1475         l_document := l_document || action_mesg || '<P>' || NL;
1476     END IF;
1477     --
1478     -- <BUG 3616816 END>
1479 
1480     l_document := l_document || '<TABLE border=1 cellpadding=2 cellspacing=1 summary="' || fnd_message.get_string('ICX', 'ICX_POR_TBL_OF_APPROVERS') || '">' || NL;
1481 
1482     l_document := l_document || '<TR>';
1483 
1484     l_document := l_document || '<TH id="seqNum_1">' ||
1485                   fnd_message.get_string('PO', 'PO_WF_NOTIF_SEQ_NUM') || '</TH>' || NL;
1486 
1487     l_document := l_document || '<TH id="employee_1">' ||
1488                   fnd_message.get_string('PO', 'PO_WF_NOTIF_EMPLOYEE') || '</TH>' || NL;
1489 
1490     l_document := l_document || '<TH id="action_1">' ||
1491                   fnd_message.get_string('PO', 'PO_WF_NOTIF_ACTION') || '</TH>' || NL;
1492 
1493     l_document := l_document || '<TH id="date_1">' ||
1494                   fnd_message.get_string('PO', 'PO_WF_NOTIF_DATE') || '</TH>' || NL;
1495 
1496     l_document := l_document || '<TH id="actionNote_1">' ||
1497                   fnd_message.get_string('PO', 'PO_WF_NOTIF_ACTION_NOTE') || '</TH>' || NL;
1498 
1499     l_document := l_document || '</TR>' || NL;
1500 
1501     curr_len  := lengthb(l_document);
1502     prior_len := curr_len;
1503 
1504     FOR i IN 1..l_num_records_to_display LOOP                  -- <BUG 3616816>
1505 
1506       /* Exit the cursor if the current document length and 2 times the
1507       ** length added in prior line exceeds 32000 char */
1508 
1509       if (curr_len + (2 * (curr_len - prior_len))) >= 32000 then
1510          exit;
1511       end if;
1512 
1513       prior_len := curr_len;
1514 
1515       l_document := l_document || '<TR>' || NL;
1516 
1517       l_document := l_document || '<TD nowrap align=center headers="seqNum_1">'
1518 					 || nvl(to_char(l_sequence_num_tbl(i)), ' ') || '</TD>' || NL;
1519 
1520       /* Bug 2788683 start */
1521       /* if action history is updated by vendor
1522        *    show vendor true name(vendor name)
1523        * else action history is updated by buyer
1524        *    show buyer's true name
1525        */
1526       IF l_employee_id_tbl(i) IS NULL THEN
1527          BEGIN --<BUG 7475571>
1528 		SELECT fu.user_name,
1529 		       hp.party_name
1530 		  INTO l_user_name,
1531 		       l_party_name
1532 		  FROM fnd_user fu,
1533 		       hz_parties hp
1534 		 WHERE hp.party_id = fu.customer_id
1535 		   AND fu.user_id = l_created_by_tbl(i);
1536 	 EXCEPTION
1537 	 WHEN OTHERS THEN
1538 		NULL;
1539 	 END;
1540       -- <BUG 7475571 Added the below IF condition so that if the l_user_name
1541       -- returns NULL value because of supplier user setup the PO approval
1542       -- notifcation should not error out. Instead modified the code such that
1543       -- the action history column for change request will show the corresponding
1544       -- supplier name rather than supplier user name.
1545 	IF l_user_name IS NULL THEN
1546 		l_user_name := PO_WF_UTIL_PKG.GetItemAttrText(itemtype   => l_item_type,
1547                                                               itemkey    => l_item_key,
1548                                                               aname      => 'SUPPLIER');
1549 
1550 		l_document := l_document || '<TD nowrap headers="employee1">' || l_user_name || '</TD>' || NL;
1551 	ELSE
1552 		po_inq_sv.get_vendor_name(l_user_name => l_user_name, x_vendor_name => l_vendor_name);
1553 
1554 		l_document := l_document || '<TD nowrap headers="employee_1">' || l_party_name || '(' || l_vendor_name || ')' || '</TD>' || NL;
1555 	END IF;
1556       ELSE
1557       l_document := l_document || '<TD nowrap headers="employee_1">'
1558 					 || nvl(l_employee_name_tbl(i), ' ') || '</TD>' || NL;
1559       END IF;
1560       /* Bug 2788683 end */
1561 
1562       l_document := l_document || '<TD nowrap headers="action_1">'
1563 					 || nvl(l_action_tbl(i), ' ') || '</TD>' || NL;
1564       l_document := l_document || '<TD nowrap headers="date_1">'
1565 					 || nvl(to_char(l_action_date_tbl(i),FND_PROFILE.VALUE_SPECIFIC('ICX_DATE_FORMAT_MASK', fnd_global.user_id),
1566 					                                      'NLS_CALENDAR = ''' || NVL( FND_PROFILE.VALUE_SPECIFIC('FND_FORMS_USER_CALENDAR', fnd_global.user_id) ,'GREGORIAN' ) || ''''), ' ') || '</TD>' || NL;
1567                                /* Bug 11825584 removing nowrap and adding align=left*/
1568       l_document := l_document || '<TD align=left headers="actionNote_1">'
1569 					 || nvl(l_note_tbl(i), ' ') || '</TD>' || NL;
1570 
1571       l_document := l_document || '</TR>' || NL;
1572 
1573       curr_len  := lengthb(l_document);
1574 
1575     end loop;
1576 
1577     l_document := l_document || '</TABLE></P>' || NL;
1578 
1579     document := l_document;
1580 
1581   elsif (display_type = 'text/plain') then
1582 
1583     l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ACTION_HISTORY') || NL;
1584 
1585     -- <BUG 3616816 START> Action History message may be NULL. Only append it
1586     -- and corresponding line breaks if there is a message to display.
1587     --
1588     IF ( action_mesg IS NOT NULL )
1589     THEN
1590         l_document := l_document || action_mesg || NL || NL;
1591     END IF;
1592     --
1593     -- <BUG 3616816 END>
1594 
1595     curr_len  := lengthb(l_document);
1596     prior_len := curr_len;
1597 
1598     FOR i IN 1..l_num_records_to_display LOOP                  -- <BUG 3616816>
1599 
1600       /* Exit the cursor if the current document length and 2 times the
1601       ** length added in prior line exceeds 32000 char */
1602 
1603       if (curr_len + (2 * (curr_len - prior_len))) >= 32000 then
1604          exit;
1605       end if;
1606 
1607       prior_len := curr_len;
1608 
1609       l_document := l_document || NL;
1610 
1611 /* Bug 2462005 sktiwari:
1612 ** Added a ':' between the prompt and the data. Modified the following lines.
1613 */
1614       l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_SEQ_NUM') || ': ' || to_char(l_sequence_num_tbl(i)) || NL;
1615 
1616       /* Bug 2788683 start */
1617       /* if action history is updated by vendor
1618        *    show vendor true name(vendor name)
1619        * else action history is updated by buyer
1620        *    show buyer's true name
1621        */
1622       IF l_employee_id_tbl(i) IS NULL THEN
1623          BEGIN --<BUG 7475571>
1624 		SELECT fu.user_name, hp.party_name
1625 		  INTO l_user_name, l_party_name
1626 		  FROM fnd_user fu,
1627 		       hz_parties hp
1628 		 WHERE hp.party_id = fu.customer_id
1629 		   AND fu.user_id = l_created_by_tbl(i);
1630 	 EXCEPTION
1631 	 WHEN OTHERS THEN
1632 		NULL;
1633 	 END;
1634 	 -- <BUG 7475571 Added the below IF condition so that if the l_user_name
1635          -- returns NULL value because of supplier user setup the PO approval
1636          -- notifcation should not error out. Instead modified the code such that
1637          -- the action history column for change request will show the corresponding
1638          -- supplier name rather than supplier user name.
1639 	 IF l_user_name IS NULL THEN
1640 		l_user_name := PO_WF_UTIL_PKG.GetItemAttrText(itemtype   => l_item_type,
1641                                                               itemkey    => l_item_key,
1642                                                               aname      => 'SUPPLIER');
1643 
1644 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_EMPLOYEE') || l_user_name || NL;
1645 	ELSE
1646 		po_inq_sv.get_vendor_name(l_user_name => l_user_name, x_vendor_name => l_vendor_name);
1647 
1648 		l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_EMPLOYEE') || ': ' || l_party_name || '(' || l_vendor_name || ')' || NL;
1649 	END IF;
1650       ELSE
1651       l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_EMPLOYEE') || ': ' || l_employee_name_tbl(i) || NL;
1652       END IF;
1653       /* Bug 2788683 end */
1654 
1655       l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ACTION') || ': ' || l_action_tbl(i) || NL;
1656       l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_DATE') || ': ' || to_char(l_action_date_tbl(i),FND_PROFILE.VALUE_SPECIFIC('ICX_DATE_FORMAT_MASK', fnd_global.user_id),
1657                                     'NLS_CALENDAR = ''' || NVL( FND_PROFILE.VALUE_SPECIFIC('FND_FORMS_USER_CALENDAR', fnd_global.user_id) ,'GREGORIAN' ) || '''') || NL;
1658       l_document := l_document || fnd_message.get_string('PO', 'PO_WF_NOTIF_ACTION_NOTE') || ': ' || l_note_tbl(i) || NL;
1659 
1660       l_document := l_document || NL;
1661 
1662       curr_len  := lengthb(l_document);
1663     end loop;
1664 
1665     l_document := l_document;
1666 
1667     document := l_document;
1668 
1669   end if;
1670 
1671 END;
1672 
1673 PROCEDURE post_approval_notif(itemtype   in varchar2,
1674                               itemkey    in varchar2,
1675                               actid      in number,
1676                               funcmode   in varchar2,
1677                               resultout  in out NOCOPY varchar2) is
1678 
1679 -- Context setting revamp <variable addition start>
1680 l_responder_id       fnd_user.user_id%TYPE;
1681 l_session_user_id    NUMBER;
1682 l_session_resp_id    NUMBER;
1683 l_session_appl_id    NUMBER;
1684 l_preparer_resp_id   NUMBER;
1685 l_preparer_appl_id   NUMBER;
1686 l_progress           VARCHAR2(1000);
1687 l_nid                NUMBER;
1688 l_preserved_ctx      VARCHAR2(5);
1689 -- Context setting revamp <variable addition end>
1690 
1691 --Added the below variables as part of bug 13951919 fix. Used to log the Delegate action in the PO_ACTION_HISTORY table.
1692 l_po_header_id      po_headers_all.po_header_id%TYPE;
1693 l_doc_type          po_action_history.OBJECT_TYPE_CODE%TYPE;
1694 l_doc_sub_type      po_action_history.OBJECT_SUB_TYPE_CODE%TYPE;
1695 l_action             po_action_history.action_code%TYPE;
1696 l_new_recipient_id   wf_roles.orig_system_id%TYPE;
1697 l_current_recipient_id   wf_roles.orig_system_id%TYPE;
1698 l_origsys            wf_roles.orig_system%TYPE;
1699 l_original_recipient       wf_notifications.original_recipient%TYPE;
1700 l_current_recipient_role   wf_notifications.recipient_role%TYPE;
1701 
1702 --Added the below variables as part of bug 14105414 fix.
1703 x_user_id         number;
1704 l_forward_to_username_response varchar2(100);
1705 l_forward_to_id                number;
1706 l_forward_to_username          varchar2(100);
1707 l_error_msg                    varchar2(500);
1708 l_preparer_id number;
1709 x_CanOwnerApproveFlag varchar2(1);
1710 l_orgid         number;
1711 l_note po_action_history.note%TYPE;
1712 l_respond_action_text varchar2(100);
1713 l_is_forward_valid boolean;
1714 l_approval_path_id PO_ACTION_HISTORY.APPROVAL_PATH_ID%TYPE;
1715 
1716 l_draft_id number;
1717 --15859236 start
1718 l_new_recipient_name           wf_users.name%type;
1719 l_new_recipient_display_name   wf_users.display_name%type;
1720 --15859236 end
1721 l_draft_type PO_DRAFTS.DRAFT_TYPE%TYPE; -- PAR Approval
1722 begin
1723 
1724 --Start of code changes for inserting the delegate action in Action History. Bug 13951919 fix
1725   l_progress := '001';
1726   IF (g_po_wf_debug = 'Y') THEN
1727         PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
1728         PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'funcmode : '||funcmode);
1729    END IF;
1730 
1731    if (funcmode IN  ('FORWARD', 'QUESTION', 'ANSWER','TIMEOUT')) then
1732    	if (funcmode = 'FORWARD') then
1733 	  l_action := 'DELEGATE';
1734 	elsif (funcmode = 'QUESTION') then
1735 	  l_action := 'QUESTION';
1736 	elsif (funcmode = 'ANSWER') then
1737 	  l_action := 'ANSWER';
1738 	elsif (funcmode = 'TIMEOUT') then
1739 	  l_action := 'NO ACTION';
1740 	end if;
1741 
1742 	IF (g_po_wf_debug = 'Y') THEN
1743           /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_action : '||l_action);
1744 	END IF;
1745 
1746 	l_po_header_id := PO_WF_UTIL_PKG.GetItemAttrNumber(	itemtype   => itemtype,
1747 							itemkey    => itemkey,
1748 							aname      => 'DOCUMENT_ID');
1749 	l_doc_type  := PO_WF_UTIL_PKG.GetItemAttrText(itemtype   => itemtype,
1750 						 itemkey    => itemkey,
1751 						 aname      => 'DOCUMENT_TYPE');
1752 	l_doc_sub_type  := PO_WF_UTIL_PKG.GetItemAttrText(itemtype   => itemtype,
1753 						 itemkey    => itemkey,
1754 						 aname      => 'DOCUMENT_SUBTYPE');
1755 
1756 	l_draft_id := PO_WF_UTIL_PKG.GetItemAttrNumber(	itemtype   => itemtype,
1757 							itemkey    => itemkey,
1758 							aname      => 'DRAFT_ID');
1759  -- PAR Approval
1760  l_draft_type := PO_WF_UTIL_PKG.GetItemAttrText ( itemtype => itemtype,
1761        itemkey => itemkey,
1762         aname => 'DRAFT_TYPE');
1763 
1764 	IF (g_po_wf_debug = 'Y') THEN
1765            PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'Document_ID : '||l_po_header_id);
1766            PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'Draft_id : '||l_draft_id);
1767            PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_doc_type : '||l_doc_type);
1768            PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_doc_sub_type : '||l_doc_sub_type);
1769           PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_draft_type : '||l_draft_type);
1770 	END IF;
1771 
1772 	IF (l_action <> 'NO ACTION') THEN
1773 	    Wf_Directory.GetRoleOrigSysInfo(WF_ENGINE.CONTEXT_NEW_ROLE, l_origsys, l_new_recipient_id);
1774 
1775 	    IF (g_po_wf_debug = 'Y') THEN
1776           	/* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_origsys : '||l_origsys);
1777           	/* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_new_recipient_id : '||l_new_recipient_id);
1778 	    END IF;
1779 
1780 	ELSE
1781 	    BEGIN
1782 		SELECT  original_recipient,
1783 			Decode(MORE_INFO_ROLE, NULL, RECIPIENT_ROLE,MORE_INFO_ROLE)
1784 			INTO l_original_recipient, l_current_recipient_role
1785 		FROM wf_notifications
1786 		WHERE
1787 			notification_id = WF_ENGINE.context_nid
1788 			AND ( MORE_INFO_ROLE IS NOT NULL OR RECIPIENT_ROLE <> ORIGINAL_RECIPIENT );
1789 
1790       		IF (g_po_wf_debug = 'Y') THEN
1791           		PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_original_recipient : '||l_original_recipient);
1792           		PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_current_recipient_role : '||l_current_recipient_role);
1793       		END IF;
1794 
1795 	    EXCEPTION
1796 		WHEN OTHERS THEN
1797 			l_original_recipient := NULL;
1798 	    END;
1799 
1800 	    IF l_original_recipient IS NOT NULL THEN
1801 		Wf_Directory.GetRoleOrigSysInfo(l_original_recipient, l_origsys, l_new_recipient_id);
1802 	    END IF;
1803 
1804 	END IF;
1805 
1806 	/* We should not be allowing the delegation of a notication
1807 	     to a user who is not an employee. */
1808 
1809 	if((funcmode = 'FORWARD') AND (l_origsys <> 'PER')) then
1810 	    fnd_message.set_name('PO', 'PO_INVALID_USER_FOR_REASSIGN');
1811 	    app_exception.raise_exception;
1812 	end if;
1813 
1814 	l_progress := '002';
1815 
1816 	IF (funcmode = 'ANSWER') THEN
1817 	   Wf_Directory.GetRoleOrigSysInfo(WF_ENGINE.CONTEXT_MORE_INFO_ROLE, l_origsys, l_current_recipient_id);
1818 	ELSIF (funcmode = 'TIMEOUT') THEN
1819 	   Wf_Directory.GetRoleOrigSysInfo(l_current_recipient_role, l_origsys, l_current_recipient_id);
1820 	ELSE
1821 	   Wf_Directory.GetRoleOrigSysInfo(WF_ENGINE.CONTEXT_RECIPIENT_ROLE, l_origsys, l_current_recipient_id);
1822 	END IF;
1823 
1824 	l_progress := '003';
1825 
1826      	IF (g_po_wf_debug = 'Y') THEN
1827           /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
1828      	END IF;
1829 
1830 	IF l_new_recipient_id IS NOT NULL THEN
1831       		IF (g_po_wf_debug = 'Y') THEN
1832           	   /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'Before executing update_action_history');
1833       		END IF;
1834 
1835 		--15859236 start
1836           wf_directory.GetUserName(l_origsys, l_new_recipient_id, l_new_recipient_name, l_new_recipient_display_name);
1837 
1838           wf_engine.SetItemAttrNumber (itemtype        => itemtype,
1839                                  itemkey         => itemkey,
1840                                  aname           => 'FORWARD_TO_ID',
1841                                  avalue          =>  l_new_recipient_id);
1842 
1843           wf_engine.SetItemAttrText (itemtype        => itemtype,
1844                                  itemkey         => itemkey,
1845                                  aname           => 'FORWARD_TO_USERNAME',
1846                                  avalue          =>  l_new_recipient_name);
1847 
1848           wf_engine.SetItemAttrText (itemtype        => itemtype,
1849                                  itemkey         => itemkey,
1850                                  aname           => 'FORWARD_TO_DISPLAY_NAME',
1851                                  avalue          =>  l_new_recipient_display_name);
1852           --15859236 end
1853 
1854         -- PAR Approval
1855 		update_action_history(p_action_code => l_action,
1856                              p_recipient_id => l_new_recipient_id,
1857                              p_note => WF_ENGINE.CONTEXT_USER_COMMENT,
1858                              p_po_header_id => l_po_header_id,
1859                              p_current_id => l_current_recipient_id,
1860                              p_doc_type => l_doc_type,
1861                              p_doc_subtype => l_doc_sub_type,
1862                              p_approval_path_id => NULL, --<bug 14105414>
1863                              p_draft_id => l_draft_id,
1864                              p_draft_type => l_draft_type);
1865 
1866       		IF (g_po_wf_debug = 'Y') THEN
1867           		/* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'After executing update_action_history');
1868       		END IF;
1869 	END IF;
1870 
1871 	l_progress := '004';
1872 
1873 	IF (funcmode <> 'TIMEOUT') THEN
1874 	    resultout := wf_engine.eng_completed || ':' || wf_engine.eng_null;
1875 	END IF;
1876 
1877 	return;
1878    end if;
1879 
1880 --End of code changes for inserting the delegate action in Action History. Bug 13951919 fix
1881 
1882  -- Context setting revamp <start>
1883 if (funcmode = 'RESPOND') then
1884   l_nid := WF_ENGINE.context_nid;
1885 
1886     SELECT fu.USER_ID
1887       INTO l_responder_id
1888       FROM fnd_user fu,
1889            wf_notifications wfn
1890      WHERE wfn.notification_id = l_nid
1891        AND wfn.original_recipient = fu.user_name;
1892 
1893 --Start of code changes for updating the action code in the action history
1894 --as per the approver action. <bug 14105414>
1895   /* Get the current approver's response/action. Here it can be either FORWARD
1896     or APPROVE or APPROVE_AND_FORWARD or REJECT. */
1897   l_respond_action_text := Wf_Notification.GetAttrText(l_nid, 'RESULT');
1898 
1899   IF (g_po_wf_debug = 'Y') THEN
1900      PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,
1901                        'l_respond_action_text: ' || l_respond_action_text);
1902   END IF;
1903 
1904   /* This boolean flag will be set to FALSE if the forwarded person is invalid */
1905   l_is_forward_valid := TRUE;
1906 
1907   IF (l_respond_action_text = 'FORWARD'
1908       OR l_respond_action_text = 'APPROVE_AND_FORWARD') THEN
1909 
1910     /*
1911     ** Desc: When responding from the E-mail notifications, the forward
1912     ** to failed as the org context was not set.
1913     */
1914 
1915     l_orgid := wf_engine.GetItemAttrNumber (itemtype => itemtype,
1916                                          itemkey  => itemkey,
1917                                          aname    => 'ORG_ID');
1918     IF (g_po_wf_debug = 'Y') THEN
1919         PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,
1920                        'l_orgid: ' || l_orgid);
1921     END IF;
1922 
1923     IF l_orgid is NOT NULL THEN
1924 
1925       po_moac_utils_pvt.set_org_context(l_orgid); --<R12 MOAC>
1926 
1927     END IF;
1928 
1929     /* Check that the value entered by responder as the FORWARD-TO user, is actually
1930     ** a valid employee (has an employee id).
1931     ** If valid, then set the FORWARD-FROM USERNAME and ID from the old FORWARD-TO.
1932     ** Then set the Forward-To to the one the user entered in the response.
1933     */
1934     /* NOTE: We take the value entered by the user and set it to ALL CAPITAL LETTERS!!!
1935     */
1936     l_forward_to_username_response := wf_notification.GetAttrText(l_nid, 'FORWARD_TO_USERNAME_RESPONSE');
1937 
1938     IF (g_po_wf_debug = 'Y') THEN
1939       PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,
1940                        'l_forward_to_username_response: ' || l_forward_to_username_response);
1941     END IF;
1942 
1943     l_forward_to_username_response := UPPER(l_forward_to_username_response);
1944 
1945     IF po_reqapproval_findapprv1.CheckForwardTo(l_forward_to_username_response,
1946                                    x_user_id) = 'Y'
1947     THEN
1948 
1949       /* The FORWARD-FROM is now the old FORWARD-TO and the NEW FORWARD-TO is set
1950       ** to what the user entered in the response
1951       */
1952 
1953       l_forward_to_username:= wf_engine.GetItemAttrText (itemtype => itemtype,
1954                                          itemkey  => itemkey,
1955                                          aname    => 'FORWARD_TO_USERNAME');
1956       IF (g_po_wf_debug = 'Y') THEN
1957         PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,
1958                        'l_forward_to_username: ' || l_forward_to_username);
1959       END IF;
1960 
1961     /*
1962     ** Desc: When the approver takes approve action from the Notification form after
1963     ** modifying the PO. The Approver attributes are set but forward-to attributes
1964     ** are set to Null. Now if any error is encountered, the Notification is sent to
1965     ** the approver and if after the error the approver forwards the PO, the
1966     ** is_forward_to_valid function sets the forward-from and approver attributes
1967     ** from the forward-to attributes (it has not changed as of now) and then sets
1968     ** the forward-to attributes to the the response-forward person but in this case
1969     ** the forward-to attributes had been set to null by previous approve action
1970     ** hence the approver_username was set to NULL by this function.
1971     **
1972     ** If the forward-to attributes are null when taking the forward action we
1973     ** should use the approver attributes. This will ensure that the approver
1974     ** attributes and the forward-from attributes are not set to NULL on
1975     ** forwarding the document.
1976     */
1977 
1978       IF l_forward_to_username is NOT NULL THEN
1979 
1980        	 l_forward_to_id:= wf_engine.GetItemAttrNumber (itemtype => itemtype,
1981                                          itemkey  => itemkey,
1982                                          aname    => 'FORWARD_TO_ID');
1983       ELSE /* get the approver name who took this action */
1984          l_forward_to_id:= wf_engine.GetItemAttrNumber (itemtype => itemtype,
1985                                          itemkey  => itemkey,
1986                                          aname    => 'APPROVER_EMPID');
1987       END IF;
1988 
1989       l_current_recipient_id := l_forward_to_id; --for updating action history
1990 
1991       /*
1992       ** Here, x_user_id is forwarded person user ID
1993       ** l_preparer_id is Document Preparer ID
1994       */
1995       l_preparer_id := wf_engine.GetItemAttrText(itemtype => itemtype,
1996                                                 itemkey => itemkey,
1997                                                 aname => 'PREPARER_ID');
1998       IF (g_po_wf_debug = 'Y') THEN
1999         PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,
2000                        'l_preparer_id: ' || l_preparer_id ||
2001                        ', x_user_id: ' || x_user_id);
2002       END IF;
2003 
2004       IF (x_user_id = l_preparer_id) THEN
2005        /* If the forward person is Preparer. Then check whether the owner can approve or not */
2006         PO_REQAPPROVAL_FINDAPPRV1.CheckOwnerCanApprove(itemtype, itemkey,
2007                                     x_CanOwnerApproveFlag);
2008 
2009         IF (g_po_wf_debug = 'Y') THEN
2010           PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,
2011                        'l_preparer_id: ' || l_preparer_id ||
2012                        ', x_CanOwnerApproveFlag: ' || x_CanOwnerApproveFlag);
2013         END IF;
2014 
2015         IF x_CanOwnerApproveFlag = 'N' then
2016           l_is_forward_valid := FALSE;
2017         END IF;
2018       END IF;
2019     ELSE
2020       --Forward-To person is invalid, set current employee id as recipient.
2021       l_is_forward_valid := FALSE;
2022       l_current_recipient_id := wf_engine.GetItemAttrNumber (itemtype => itemtype,
2023                                          itemkey  => itemkey,
2024                                          aname    => 'APPROVER_EMPID');
2025     END IF;
2026   ELSE
2027     l_is_forward_valid := FALSE;
2028     --To record the real approver.
2029     Wf_Directory.GetRoleOrigSysInfo(WF_ENGINE.CONTEXT_RECIPIENT_ROLE, l_origsys, l_current_recipient_id);
2030 
2031   END IF;
2032 
2033   l_progress := '005 PO_WF_PO_NOTIFICATION.post_approval_notif';
2034   IF (g_po_wf_debug = 'Y') THEN
2035       PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2036   END IF;
2037 
2038   /* If the FORWARD is valid, set all the required workflow attributes */
2039   IF (l_is_forward_valid = TRUE) THEN
2040 
2041       l_progress := '005 is_forward_valid TRUE';
2042       IF (g_po_wf_debug = 'Y') THEN
2043          PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2044       END IF;
2045 
2046       /* Set the FORWARD_FROM */
2047       wf_engine.SetItemAttrNumber (     itemtype        => itemtype,
2048                                         itemkey         => itemkey,
2049                                         aname           => 'FORWARD_FROM_ID',
2050                                         avalue          =>  l_forward_to_id);
2051 
2052       /* Set the approver to the person who took the action on the notification,
2053       ** i.e. the old forward-to person
2054       */
2055       wf_engine.SetItemAttrNumber (     itemtype        => itemtype,
2056                                         itemkey         => itemkey,
2057                                         aname           => 'APPROVER_EMPID',
2058                                         avalue          =>  l_forward_to_id);
2059 
2060       wf_engine.SetItemAttrNumber ( itemtype   => itemType,
2061                                    itemkey    => itemkey,
2062                                    aname      => 'FORWARD_TO_ID',
2063                                    avalue     => x_user_id);
2064 
2065      /* Set the Subject of the Approval notification to "requires your approval".
2066      ** Since the user entered a valid forward-to, then set the
2067      ** "Invalid Forward-to" message to NULL.
2068      */
2069      fnd_message.set_name ('PO','PO_WF_NOTIF_REQUIRES_APPROVAL');
2070      l_error_msg := fnd_message.get;
2071 
2072      wf_engine.SetItemAttrText ( itemtype   => itemType,
2073                                  itemkey    => itemkey,
2074                                  aname      => 'REQUIRES_APPROVAL_MSG' ,
2075                                  avalue     => l_error_msg);
2076 
2077      wf_engine.SetItemAttrText ( itemtype   => itemType,
2078                                  itemkey    => itemkey,
2079                                  aname      => 'WRONG_FORWARD_TO_MSG' ,
2080                                  avalue     => '');
2081 
2082 
2083      /* Other workflow attributes are set in PO_REQAPPROVAL_FINDAPPRV1.Set_Forward_To_From_App_fwd */
2084 
2085   ELSIF (l_is_forward_valid = FALSE) THEN
2086      /* If the forwarded person is invalid or forwarded person is Preparer
2087      ** and doesn't have approval authority, show error message.
2088      */
2089 
2090      /* Set the error message that will be shown to the user in the ERROR MESSAGE
2091      ** Field in the Notification.
2092      */
2093     l_progress := '005 is_forward_valid FALSE';
2094     IF (g_po_wf_debug = 'Y') THEN
2095       PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2096     END IF;
2097 
2098      /* Set the Subject of the Approval notification to "Invalid forward-to"
2099      ** Since the user entered an invalid forward-to, then set the
2100      ** "requires your approval" message to NULL.
2101      */
2102      fnd_message.set_name ('PO','PO_WF_NOTIF_INVALID_FORWARD');
2103      l_error_msg := fnd_message.get;
2104 
2105      wf_engine.SetItemAttrText ( itemtype   => itemType,
2106                                  itemkey    => itemkey,
2107                                  aname      => 'REQUIRES_APPROVAL_MSG' ,
2108                                  avalue     => '');
2109 
2110      wf_engine.SetItemAttrText ( itemtype   => itemType,
2111                                  itemkey    => itemkey,
2112                                  aname      => 'WRONG_FORWARD_TO_MSG' ,
2113                                  avalue     => l_error_msg);
2114 
2115   END IF;
2116 
2117   /*
2118   ** Here the logic to update the action code in action history.
2119   ** The insert action is still performed in PO_DOCUMENT_ACTION_UTIL.handle_auth_action_history.
2120   */
2121   l_progress := '006 PO_WF_PO_NOTIFICATION.post_approval_notif';
2122   IF (g_po_wf_debug = 'Y') THEN
2123       PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2124   END IF;
2125 
2126   /*
2127   ** Update action history for APPROVE_AND_FORWARD
2128   ** even when the forward-to person is invalid.
2129   */
2130   IF (l_respond_action_text in ('APPROVE','APPROVE_AND_FORWARD'))
2131      OR (l_respond_action_text = 'FORWARD' AND l_is_forward_valid = TRUE) THEN
2132 
2133       IF l_respond_action_text = 'FORWARD' THEN
2134         l_action := 'FORWARD';
2135       ELSIF l_respond_action_text = 'APPROVE' THEN
2136         l_action := 'APPROVE';
2137       ELSIF l_respond_action_text = 'APPROVE_AND_FORWARD' THEN
2138         l_action := 'APPROVE AND FORWARD';
2139       END IF;
2140 
2141       /* Reset response note */
2142       l_doc_type := wf_engine.GetItemAttrText (itemtype => itemtype,
2143                                          itemkey  => itemkey,
2144                                          aname    => 'DOCUMENT_TYPE');
2145 
2146       IF (l_doc_type='PO' OR l_doc_type='PA' OR l_doc_type='RELEASE' ) THEN
2147         l_note := wf_notification.GetAttrText(l_nid, 'NOTE_R');
2148         PO_WF_UTIL_PKG.SetItemAttrText(itemtype=>itemtype,
2149 	  			      itemkey => itemkey,
2150 				      aname   => 'NOTE',
2151 	  			      avalue  => l_note);
2152         PO_WF_UTIL_PKG.SetItemAttrText(itemtype=>itemtype,
2153 	  			      itemkey => itemkey,
2154 				      aname   => 'NOTE_R',
2155 	  			      avalue  => NULL);
2156         wf_notification.SetAttrText(l_nid, 'NOTE', l_note);
2157         wf_notification.SetAttrText(l_nid, 'NOTE_R', null);
2158       END IF;
2159 
2160       l_po_header_id := wf_engine.GetItemAttrNumber(itemtype   => itemtype,
2161                                                     itemkey    => itemkey,
2162                                                     aname      => 'DOCUMENT_ID');
2163       l_doc_sub_type  := wf_engine.GetItemAttrText(itemtype   => itemtype,
2164                                                    itemkey    => itemkey,
2165                                                    aname      => 'DOCUMENT_SUBTYPE');
2166       l_approval_path_id := wf_engine.GetItemAttrNumber (itemtype => itemtype,
2167                                             itemkey  => itemkey,
2168                                             aname    => 'APPROVAL_PATH_ID');
2169 
2170 	  l_draft_id := wf_engine.GetItemAttrNumber(itemtype   => itemtype,
2171 							                    itemkey    => itemkey,
2172                       							aname      => 'DRAFT_ID');
2173      -- PAR Approval
2174      l_draft_type := PO_WF_UTIL_PKG.GetItemAttrText ( itemtype => itemtype,
2175                                                       itemkey => itemkey,
2176                                                       aname => 'DRAFT_TYPE');
2177 
2178       l_progress := '007 start to update action history';
2179       IF (g_po_wf_debug = 'Y') THEN
2180         PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2181         PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_action : ' || l_action ||
2182                           ', l_po_header_id: ' || l_po_header_id ||
2183                           ', l_draft_id: ' || l_draft_id ||
2184                           ', l_draft_type: ' || l_draft_type ||
2185                           ', l_current_recipient_id: ' || l_current_recipient_id);
2186         PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,'l_note: ' || l_note);
2187       END IF;
2188 
2189       update_action_history(p_action_code => l_action,
2190                             p_recipient_id => NULL,
2191                             p_note => l_note,
2192                             p_po_header_id => l_po_header_id,
2193                             p_current_id => l_current_recipient_id,
2194                             p_doc_type=> l_doc_type,
2195                             p_doc_subtype => l_doc_sub_type,
2196                             p_approval_path_id => l_approval_path_id,
2197                             p_draft_id => l_draft_id,
2198                             p_draft_type => l_draft_type); -- PAR Approval
2199   END IF;
2200 
2201   l_progress := '008 PO_WF_PO_NOTIFICATION.post_approval_notif';
2202   IF (g_po_wf_debug = 'Y') THEN
2203       PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2204   END IF;
2205 --End of code changes. <bug 14105414>
2206 
2207 -- <debug start>
2208    if (wf_engine.preserved_context = TRUE) then
2209       l_preserved_ctx := 'TRUE';
2210    else
2211       l_preserved_ctx := 'FALSE';
2212    end if;
2213    l_progress := 'notif callback preserved_ctx : '||l_preserved_ctx;
2214    IF (g_po_wf_debug = 'Y') THEN
2215           /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2216    END IF;
2217 -- <debug end>
2218 
2219 -- <debug start>
2220        l_progress := '010 notif callback -responder id : '||l_responder_id;
2221        IF (g_po_wf_debug = 'Y') THEN
2222           /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2223        END IF;
2224 --<debug end>
2225     --Bug 5389914
2226     --Fnd_Profile.Get('USER_ID',l_session_user_id);
2227     --Fnd_Profile.Get('RESP_ID',l_session_resp_id);
2228     --Fnd_Profile.Get('RESP_APPL_ID',l_session_appl_id);
2229     l_session_user_id := fnd_global.user_id;
2230     l_session_resp_id := fnd_global.resp_id;
2231     l_session_appl_id := fnd_global.resp_appl_id;
2232 
2233 	  IF (l_session_user_id = -1) THEN
2234 	      l_session_user_id := NULL;
2235 	  END IF;
2236 
2237 	  IF (l_session_resp_id = -1) THEN
2238 	      l_session_resp_id := NULL;
2239 	  END IF;
2240 
2241 	  IF (l_session_appl_id = -1) THEN
2242 	      l_session_appl_id := NULL;
2243 	  END IF;
2244 
2245 -- <debug start>
2246        l_progress :='020 notification callback ses_userid: '||l_session_user_id
2247                     ||' sess_resp_id '||l_session_resp_id||' sess_appl_id '
2248 		    ||l_session_appl_id;
2249        IF (g_po_wf_debug = 'Y') THEN
2250           /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2251        END IF;
2252 --<debug end>
2253 
2254 -- bug 4901406 <start> : need to shift the setting of the preparer resp and appl id
2255 -- to here, it was not initialized inside the if condition if the control went to the
2256 -- else part.
2257           l_preparer_resp_id :=
2258 	  PO_WF_UTIL_PKG.GetItemAttrNumber (itemtype=>itemtype,
2259 	  			      itemkey => itemkey,
2260 				      aname   => 'RESPONSIBILITY_ID');
2261           l_preparer_appl_id :=
2262           PO_WF_UTIL_PKG.GetItemAttrNumber (itemtype=>itemtype,
2263 	  			      itemkey => itemkey,
2264 				      aname   => 'APPLICATION_ID');
2265 
2266 -- <debug start>
2267           l_progress := '030 notif callback prep resp_id:'||l_preparer_resp_id
2268 	  		||' prep appl id '||l_preparer_appl_id;
2269           IF (g_po_wf_debug = 'Y') THEN
2270              /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2271           END IF;
2272 --<debug end>
2273 
2274 -- bug 4901406 <end>
2275 
2276 
2277     if (l_responder_id is not null) then
2278        if (l_responder_id <> l_session_user_id) then
2279        /* possible in 2 scenarios :
2280           1. when the response is made from email using guest user feature
2281 	  2. When the response is made from sysadmin login
2282        */
2283 
2284 
2285 
2286           PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2287 	  			      itemkey => itemkey,
2288 				      aname   => 'RESPONDER_USER_ID',
2289 	  			      avalue  => l_responder_id);
2290           PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2291 	  			      itemkey => itemkey,
2292 				      aname   => 'RESPONDER_RESP_ID',
2293 	  			      avalue  => l_preparer_resp_id);
2294           PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2295 	  			      itemkey => itemkey,
2296 				      aname   => 'RESPONDER_APPL_ID',
2297 	  			      avalue  => l_preparer_appl_id);
2298        else
2299           if (l_session_resp_id is null) THEN
2300 	  /* possible when the response is made from the default worklist
2301 	     without choosing a valid responsibility */
2302 	      PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2303 	  			      itemkey => itemkey,
2304 				      aname   => 'RESPONDER_USER_ID',
2305 	  			      avalue  => l_responder_id);
2306               PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2307 	  			      itemkey => itemkey,
2308 				      aname   => 'RESPONDER_RESP_ID',
2309 	  			      avalue  => l_preparer_resp_id);
2310               PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2311 	  			      itemkey => itemkey,
2312 				      aname   => 'RESPONDER_APPL_ID',
2313 	  			      avalue  => l_preparer_appl_id);
2314            else
2315 	   /* all values available - possible when the response is made
2316 	      after choosing a correct responsibility */
2317 
2318 	   /* bug 5333226 : If the values of responsibility_id and application
2319 	      id are available but are incorrect - i.e. not conforming to say the
2320 	      sls (subledger security). This may happen when a response is made
2321 	      through the email or the background process picks the wf up.
2322 	      This may happen due to the fact that the mailer / background process
2323 	      carries the context set by the notification/wf it processed last*/
2324 
2325 		 	 if ( l_preserved_ctx = 'TRUE') then
2326 	             PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2327 	  			      itemkey => itemkey,
2328 				      aname   => 'RESPONDER_USER_ID',
2329 	  			      avalue  => l_responder_id);
2330                      PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2331 	  			      itemkey => itemkey,
2332 				      aname   => 'RESPONDER_RESP_ID',
2333 	  			      avalue  => l_session_resp_id);
2334                      PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2335 	  			      itemkey => itemkey,
2336 				      aname   => 'RESPONDER_APPL_ID',
2337 	  			      avalue  => l_session_appl_id);
2338 	          else
2339 	             PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2340 	  			      itemkey => itemkey,
2341 				      aname   => 'RESPONDER_USER_ID',
2342 	  			      avalue  => l_responder_id);
2343                      PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2344 	  			      itemkey => itemkey,
2345 				      aname   => 'RESPONDER_RESP_ID',
2346 	  			      avalue  => l_preparer_resp_id);
2347                      PO_WF_UTIL_PKG.SetItemAttrNumber(itemtype=>itemtype,
2348 	  			      itemkey => itemkey,
2349 				      aname   => 'RESPONDER_APPL_ID',
2350 	  			      avalue  => l_preparer_appl_id);
2351 	          end if;
2352 
2353 
2354 	   end if;
2355        end if;
2356     end if;
2357 
2358     -- Context setting revamp <end>
2359 
2360 
2361      resultout := wf_engine.eng_completed || ':' || wf_engine.eng_null;
2362       l_progress := '040 returning from notif callback -respond mode';
2363           IF (g_po_wf_debug = 'Y') THEN
2364              /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2365           END IF;
2366      return;
2367   end if;
2368 
2369 
2370   -- Don't allow transfer
2371   if (funcmode = 'TRANSFER') then
2372 
2373     fnd_message.set_name('PO', 'PO_WF_NOTIF_NO_TRANSFER');
2374     app_exception.raise_exception;
2375 
2376   resultout := wf_engine.eng_completed;
2377   return;
2378 
2379   end if; -- end if for funcmode = 'TRANSFER'
2380 
2381 end post_approval_notif;
2382 
2383 
2384 /* Bug# 2616433: kagarwal
2385 ** Desc: Added new procedure to set notification subject token in
2386 ** user language.
2387 */
2388 
2389 procedure Get_po_user_msg_attribute(itemtype in varchar2,
2390                                 itemkey         in varchar2,
2391                                 actid           in number,
2392                                 funcmode        in varchar2,
2393                                 resultout       out NOCOPY varchar2) IS
2394 
2395 l_progress  VARCHAR2(100) := '000';
2396 l_doc_string varchar2(200);
2397 l_user_name varchar2(100);
2398 l_preparer_user_name varchar2(100);
2399 l_orgid number;
2400 l_notification_type varchar2(15);  --bug 3668188
2401 
2402 -- <Start Word Integration 11.5.10+>
2403 l_okc_doc_type          varchar2(20);
2404 l_conterms_exist_flag   PO_HEADERS_ALL.conterms_exist_flag%TYPE;
2405 l_document_id           NUMBER;
2406 l_document_subtype      PO_HEADERS_ALL.type_lookup_code%TYPE;
2407 -- <End Word Integration 11.5.10+>
2408 
2409 BEGIN
2410 
2411   -- Do nothing in cancel or timeout mode
2412   --
2413   if (funcmode <> wf_engine.eng_run) then
2414       resultout := wf_engine.eng_null;
2415       return;
2416   end if;
2417 
2418   l_progress := 'Get_po_user_msg_attribute:001: actid: ' || actid;
2419   /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2420 
2421   l_orgid := wf_engine.GetItemAttrNumber (itemtype => itemtype,
2422                                          itemkey  => itemkey,
2423                                          aname    => 'ORG_ID');
2424 
2425   IF l_orgid is NOT NULL THEN
2426     PO_MOAC_UTILS_PVT.set_org_context(l_orgid) ;       -- <R12 MOAC>
2427   END IF;
2428 
2429   l_progress := 'Get_po_user_msg_attribute:010: orgid: ' || l_orgid;
2430   /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2431 
2432   l_user_name := wf_engine.GetActivityAttrText (itemtype => itemtype,
2433                                                 itemkey  => itemkey,
2434                                                 actid    => actid,
2435                                                 aname    => 'NTF_USER_NAME',
2436                                                 ignore_notfound => TRUE);
2437 
2438   PO_WF_PO_NOTIFICATION.GetDisplayValue(itemtype, itemkey, l_user_name);
2439 
2440 
2441   l_progress := 'Get_po_user_msg_attribute:015: username: ' || l_user_name;
2442   /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2443 
2444 
2445   -- Bug 3668188: added the NTF_USER_ROLE Activity Attribute, which is
2446   -- a constant with value 'SUBMITTER' or 'APPROVER'.  This distinguishes
2447   -- between the 3 different notification-functions that share this procedure.
2448   l_notification_type := wf_engine.GetActivityAttrText (
2449                                       itemtype => itemtype,
2450                                       itemkey  => itemkey,
2451                                       actid    => actid,
2452                                       aname    => 'NTF_USER_ROLE',
2453                                       ignore_notfound => TRUE);
2454 
2455   l_progress := 'Get_po_user_msg_attribute:020: notif type: ' || l_notification_type;
2456   -- DEBUG
2457      PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2458 
2459 
2460   -- Bug 3668188: Removed old logic from bug 3564727 and replaced it
2461   -- with a call to is_open_document_allowed, which has updated logic.
2462   IF NOT (PO_WF_PO_NOTIFICATION.is_open_document_allowed(
2463                                   p_itemtype => itemtype
2464                                ,  p_itemkey => itemkey
2465                                ,  p_notification_type => l_notification_type)
2466   ) THEN
2467      l_progress := 'Get_po_approver_msg_attribute: 040: NULL open form';
2468      /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2469 
2470      -- HTML Orders R12
2471      -- Set the URL and form attributes
2472      PO_WF_UTIL_PKG.SetItemAttrText ( itemtype   => itemType,
2473                               itemkey    => itemkey,
2474                               aname      => 'OPEN_FORM_COMMAND' ,
2475                               avalue     => '');
2476 
2477      -- PO AME Project : VIEW_DOC_URL must always be seen even though po is in PRE-APPROVED state.
2478      /*PO_WF_UTIL_PKG.SetItemAttrText ( itemtype   => itemType,
2479                               itemkey    => itemkey,
2480                               aname      => 'VIEW_DOC_URL' ,
2481                               avalue     => '');*/
2482 
2483      PO_WF_UTIL_PKG.SetItemAttrText ( itemtype   => itemType,
2484                               itemkey    => itemkey,
2485                               aname      => 'EDIT_DOC_URL' ,
2486                               avalue     => '');
2487   END IF;
2488 
2489 
2490   -- <Start Word Integration 11.5.10+>
2491 
2492   l_conterms_exist_flag := PO_WF_UTIL_PKG.GetItemAttrText(
2493                                    itemtype => itemtype,
2494                                    itemkey => itemkey,
2495                                    aname => 'CONTERMS_EXIST_FLAG');
2496 
2497   l_document_subtype := PO_WF_UTIL_PKG.GetItemAttrText(
2498                                    itemtype => itemtype,
2499                                    itemkey => itemkey,
2500                                    aname => 'DOCUMENT_SUBTYPE');
2501 
2502   l_document_id := PO_WF_UTIL_PKG.GetItemAttrNumber(
2503                                    itemtype => itemtype,
2504                                    itemkey => itemkey,
2505                                    aname => 'DOCUMENT_ID');
2506 
2507 
2508   /* Set or reset the okc doc attachment attribute */
2509 
2510   IF (l_conterms_exist_flag = 'Y')
2511   THEN
2512     l_okc_doc_type :=
2513                 PO_CONTERMS_UTL_GRP.get_po_contract_doctype(l_document_subtype);
2514 
2515     IF (('STRUCTURED' <>
2516      OKC_TERMS_UTIL_GRP.get_contract_source_code(p_document_type => l_okc_doc_type
2517                                                , p_document_id => l_document_id))
2518           AND
2519       ('N' =
2520       OKC_TERMS_UTIL_GRP.is_primary_terms_doc_mergeable(
2521                                                P_document_type => l_okc_doc_type
2522                                              , p_document_id => l_document_id))
2523          AND
2524       (PO_COMMUNICATION_PVT.PO_COMMUNICATION_PROFILE = 'T')
2525     )
2526     THEN
2527 
2528       PO_WF_UTIL_PKG.SetItemAttrText (itemtype => itemtype,
2529                                       itemkey => itemkey,
2530                                       aname => 'OKC_DOC_ATTACHMENT',
2531                                       avalue =>
2532                                 'PLSQLBLOB:PO_COMMUNICATION_PVT.OKC_DOC_ATTACH/'||
2533                                     itemtype||':'||itemkey);
2534 
2535     ELSE
2536 
2537       /* Contract terms are structured, or attached document is mergeable.
2538        * All contract terms will be in pdf; no need for other okc doc attachment.
2539        */
2540 
2541       PO_WF_UTIL_PKG.SetItemAttrText (itemtype => itemtype,
2542                                       itemkey => itemkey,
2543                                       aname => 'OKC_DOC_ATTACHMENT',
2544                                       avalue => '');
2545 
2546     END IF /* not structured and not mergeable */;
2547 
2548   END IF; /* l_conterms_exist_flag = 'Y' */
2549 
2550 
2551   -- <End Word Integration 11.5.10+>
2552 
2553 
2554 
2555   l_progress := 'Get_po_approver_msg_attribute: 999';
2556   /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2557 
2558   resultout := wf_engine.eng_completed || ':' ||  'ACTIVITY_PERFORMED';
2559 
2560 EXCEPTION
2561  WHEN OTHERS THEN
2562     l_doc_string := PO_REQAPPROVAL_INIT1.get_error_doc(itemType, itemkey);
2563     l_preparer_user_name := PO_REQAPPROVAL_INIT1.get_preparer_user_name(itemType, itemkey);
2564     wf_core.context('PO_WF_PO_NOTIFICATION','Get_req_approval_msg_attribute',l_progress);
2565     PO_REQAPPROVAL_INIT1.send_error_notif(itemType, itemkey, l_preparer_user_name,
2566     l_doc_string, sqlerrm, 'PO_WF_PO_NOTIFICATION.Get_po_approver_msg_attribute');
2567     raise;
2568 
2569 END Get_po_user_msg_attribute;
2570 
2571 
2572 /* Bug# 2616433: kagarwal
2573 ** Desc: Added new procedure to set doc type display according to the
2574 ** default language of approver or preparer.
2575 */
2576 
2577 procedure GetDisplayValue(itemtype in varchar2,
2578                           itemkey  in varchar2,
2579                           username in varchar2,
2580                           doctype  in varchar2,
2581                           docsubtype in varchar2) IS
2582 
2583 l_progress  VARCHAR2(400) := '000';
2584 l_doc_type varchar2(25);
2585 l_doc_subtype varchar2(25);
2586 l_doc_disp varchar2(240);
2587 l_ga_flag   varchar2(1) := null;
2588 
2589 l_display_name varchar2(240);
2590 l_email_address varchar2(240);
2591 l_notification_preference  varchar2(240);
2592 l_language  varchar2(240);
2593 l_territory varchar2(240);
2594 l_msg_text   varchar2(2000) := NULL; -- Bug 3430545
2595 l_language_code fnd_languages.language_code%TYPE;
2596 
2597 cursor c_lookup_value_user(p_doc_type varchar2, p_doc_subtype varchar2,
2598                       p_language varchar2) is
2599   select type_name
2600   from po_document_types_tl tl, FND_LANGUAGES fl
2601   where fl.nls_language = p_language
2602   and   tl.LANGUAGE = fl.language_code
2603   and   tl.document_type_code = p_doc_type
2604   and   tl.document_subtype = p_doc_subtype;
2605 
2606 cursor c_lookup_value_doc(p_doc_type varchar2, p_doc_subtype varchar2) is
2607   select type_name
2608   from po_document_types
2609   where document_type_code = p_doc_type
2610   and   document_subtype = p_doc_subtype;
2611 
2612   l_document_id      PO_HEADERS_ALL.po_header_id%TYPE; --<R12 STYLES PHASE II>
2613   l_draft_id	NUMBER; -- CLM Apprvl
2614   l_draft_type PO_DRAFTS.DRAFT_TYPE%TYPE; -- PAR Approval
2615 
2616 BEGIN
2617   l_progress := 'PO_WF_PO_NOTIFICATION.GetDisplayValue: 001, user name: '
2618                 || username;
2619   /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2620 
2621   if ((doctype is NULL) or (docsubtype is null)) then
2622     l_doc_type := PO_WF_UTIL_PKG.GetItemAttrText (itemtype => itemtype,
2623                                          itemkey  => itemkey,
2624                                          aname    => 'DOCUMENT_TYPE');
2625 
2626     l_doc_subtype := PO_WF_UTIL_PKG.GetItemAttrText (itemtype => itemtype,
2627                                          itemkey  => itemkey,
2628                                          aname    => 'DOCUMENT_SUBTYPE');
2629   else
2630    l_doc_type := doctype;
2631    l_doc_subtype := docsubtype;
2632   end if;
2633 
2634   IF l_doc_type = 'PA' AND l_doc_subtype = 'BLANKET' THEN
2635 
2636        l_ga_flag := PO_WF_UTIL_PKG.GetItemAttrText  ( itemtype    => itemtype,
2637                                          itemkey     => itemkey,
2638                                          aname       => 'GLOBAL_AGREEMENT_FLAG');
2639   END IF;
2640 
2641   /* Bug 3430545: Modified the code to get the translated values for the wf
2642    notification attribute 'REQUIRES_APPROVAL_MSG' and 'PO_GA_TYPE'.
2643    Deleted the previous code and revamped it.
2644   */
2645    --<R12 STYLES PHASE II START>
2646    l_document_id := PO_WF_UTIL_PKG.GetItemAttrNumber
2647                                        (itemtype   => itemtype,
2648                                         itemkey    => itemkey,
2649                                         aname      => 'DOCUMENT_ID');
2650 
2651    -- CLM Apprvl
2652    l_draft_id := PO_WF_UTIL_PKG.GetItemAttrNumber
2653                                        (itemtype   => itemtype,
2654                                         itemkey    => itemkey,
2655                                         aname      => 'DRAFT_ID');
2656 
2657    -- PAR Approval
2658    l_draft_type := PO_WF_UTIL_PKG.GetItemAttrText (itemtype => itemtype,
2659                                                    itemkey  => itemkey,
2660                                                    aname    => 'DRAFT_TYPE');
2661 
2662   IF  username is NULL THEN
2663 	  l_progress := 'PO_WF_PO_NOTIFICATION.GetDisplayValue: 050';
2664         /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2665 
2666       IF l_doc_type = 'PA' AND l_doc_subtype IN ('BLANKET','CONTRACT') OR
2667          l_doc_type = 'PO' AND l_doc_subtype = 'STANDARD'  then
2668 		-- CLM Apprvl. In case of modification documents that document type display needs to be 'Modification'
2669 	    -- PAr Approval. For PAr, documnet type display is 'Post Award Request' and it is based on draft type.
2670 	    IF l_draft_id is not null AND l_draft_id <> -1 AND l_draft_type = 'MOD' then
2671 			l_doc_disp:= 'Modification';
2672         -- PAR Approval
2673         ELSIF l_draft_id is not null AND l_draft_id <> -1 AND l_draft_type = 'PAR' then
2674 			l_doc_disp:= 'Post Award Request';
2675 		ELSE
2676 			l_doc_disp:= PO_DOC_STYLE_PVT.GET_STYLE_DISPLAY_NAME(l_document_id);
2677 		END IF;
2678 
2679       ELSE
2680          OPEN c_lookup_value_doc(l_doc_type, l_doc_subtype);
2681          FETCH c_lookup_value_doc into l_doc_disp;
2682          CLOSE c_lookup_value_doc;
2683       END IF;
2684   ELSE
2685 	  l_progress := 'PO_WF_PO_NOTIFICATION.GetDisplayValue: 060';
2686         /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2687       WF_DIRECTORY.GETROLEINFO(
2688            username,
2689            l_display_name,
2690            l_email_address,
2691            l_notification_preference,
2692            l_language,
2693            l_territory);
2694       l_progress := 'PO_WF_PO_NOTIFICATION.GetDisplayValue: 080, language: '
2695                     || l_language;
2696         /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2697 
2698       BEGIN
2699 
2700       SELECT language_code
2701 	INTO l_language_code
2702 	FROM fnd_languages
2703        WHERE nls_language = l_language;
2704 
2705       EXCEPTION
2706       WHEN OTHERS THEN
2707 	l_language_code := NULL;
2708       END;
2709 
2710       IF l_doc_type = 'PA' AND l_doc_subtype IN ('BLANKET','CONTRACT') OR
2711          l_doc_type = 'PO' AND l_doc_subtype = 'STANDARD'  then
2712          -- CLM Apprvl. In case of modification documents that document type display needs to be 'Modification'
2713 		-- PAR Approval. For PAr, documnet type display is 'Post Award Request' and it is based on draft type.
2714 	    IF l_draft_id is not null AND l_draft_id <> -1 AND l_draft_type = 'MOD' then
2715 			l_doc_disp:= 'Modification';
2716         -- PAR Approval
2717         ELSIF l_draft_id is not null AND l_draft_id <> -1 AND l_draft_type = 'PAR' then
2718 			l_doc_disp:= 'Post Award Request';
2719 		ELSE
2720 			l_doc_disp:= PO_DOC_STYLE_PVT.GET_STYLE_DISPLAY_NAME(l_document_id);
2721 		END IF;
2722 
2723      ELSE
2724           OPEN c_lookup_value_user(l_doc_type, l_doc_subtype, l_language);
2725           FETCH c_lookup_value_user into l_doc_disp;
2726           CLOSE c_lookup_value_user;
2727      END IF;
2728   END IF;  /* if username is null  */
2729    --<R12 STYLES PHASE II END>
2730 	 l_progress := 'PO_WF_PO_NOTIFICATION.GetDisplayValue: 100, type disp: '
2731                 || l_doc_disp;
2732         /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2733 
2734      PO_WF_UTIL_PKG.SetItemAttrText ( itemtype    => itemtype,
2735                                  itemkey     => itemkey,
2736                                  aname       => 'DOCUMENT_TYPE_DISP',
2737                                  avalue      =>  l_doc_disp);
2738      BEGIN
2739        select message_text
2740        into l_msg_text
2741        from fnd_new_messages fm,fnd_languages fl
2742        where fm.message_name = 'PO_WF_NOTIF_REQUIRES_APPROVAL'
2743        and fm.language_code = fl.language_code
2744        and fl.nls_language = l_language
2745        and fm.application_id = 201;  --<BUG 3712124> Include application_id to better use PK index
2746        EXCEPTION
2747            WHEN OTHERS THEN
2748             l_msg_text := PO_WF_UTIL_PKG.GetItemAttrText(itemtype    => itemtype,
2749                                                     itemkey     => itemkey,
2750                                                     aname       => 'REQUIRES_APPROVAL_MSG');
2751        END;
2752 
2753     PO_WF_UTIL_PKG.SetItemAttrText ( itemtype    => itemtype,
2754                                    itemkey     => itemkey,
2755                                    aname       => 'REQUIRES_APPROVAL_MSG',
2756                                    avalue      => l_msg_text );
2757 
2758 	/* PO AME Project start :
2759        Fetching and setting REQUIRES_REVIEW_MSG attribute */
2760      BEGIN
2761        select message_text
2762        into l_msg_text
2763        from fnd_new_messages fm,fnd_languages fl
2764        where fm.message_name = 'PO_WF_NOTIF_REQUIRES_REVIEW'
2765        and fm.language_code = fl.language_code
2766        and fl.nls_language = l_language
2767        and fm.application_id = 201;
2768        EXCEPTION
2769            WHEN OTHERS THEN
2770             l_msg_text := PO_WF_UTIL_PKG.GetItemAttrText(itemtype    => itemtype,
2771                                                     itemkey     => itemkey,
2772                                                     aname       => 'REQUIRES_REVIEW_MSG');
2773      END;
2774 
2775       PO_WF_UTIL_PKG.SetItemAttrText ( itemtype    => itemtype,
2776                                    itemkey     => itemkey,
2777                                    aname       => 'REQUIRES_REVIEW_MSG',
2778                                    avalue      => l_msg_text );
2779 
2780      BEGIN
2781        select message_text
2782        into l_msg_text
2783        from fnd_new_messages fm,fnd_languages fl
2784        where fm.message_name = 'PO_WF_NOTIF_REQUIRES_ESIGN'
2785        and fm.language_code = fl.language_code
2786        and fl.nls_language = l_language
2787        and fm.application_id = 201;
2788        EXCEPTION
2789            WHEN OTHERS THEN
2790             l_msg_text := PO_WF_UTIL_PKG.GetItemAttrText(itemtype    => itemtype,
2791                                                          itemkey     => itemkey,
2792                                                          aname       => 'REQUIRES_ESIGN_MSG');
2793      END;
2794 
2795       PO_WF_UTIL_PKG.SetItemAttrText ( itemtype    => itemtype,
2796                                        itemkey     => itemkey,
2797                                        aname       => 'REQUIRES_ESIGN_MSG',
2798                                        avalue      => l_msg_text );
2799 
2800     /* PO AME Project end */
2801 
2802 EXCEPTION
2803   WHEN OTHERS THEN
2804     l_progress := 'PO_WF_PO_NOTIFICATION.GetDisplayValue: sql err: ' || sqlerrm;
2805     /* DEBUG */  PO_WF_DEBUG_PKG.insert_debug(itemtype,itemkey,l_progress);
2806     IF (c_lookup_value_user%ISOPEN) THEN
2807       CLOSE c_lookup_value_user;
2808     END IF;
2809     IF (c_lookup_value_doc%ISOPEN) THEN
2810       CLOSE c_lookup_value_doc;
2811     END IF;
2812 
2813 END GetDisplayValue;
2814 
2815 ------------------------------------------------------------------<BUG 3607009>
2816 -------------------------------------------------------------------------------
2817 --Start of Comments
2818 --Name: is_open_document_allowed
2819 --Pre-reqs:
2820 --  None.
2821 --Modifies:
2822 --  None
2823 --Locks:
2824 --  None.
2825 --Function:
2826 --  Determines if the Open Document icon should be shown in the
2827 --  PO Approval Notification. The Open Document should not be shown if...
2828 --  (1) the document is in 'Pre-Approved' state and
2829 --  (2) document signature is required.
2830 --Parameters:
2831 --IN:
2832 --p_itemtype
2833 --  Standard parameter to be used in a workflow procedure
2834 --p_itemkey
2835 --  Standard parameter to be used in a workflow procedure
2836 --p_notification_type
2837 --  Specifies whether this notification is for the Preparer/Submitter
2838 --  or an Approver/Reviewer
2839 --  The value is derived from the WF Function attribute NTF_USER_ROLE
2840 --  in the GET_<>_NOTIFICATION_ATTRIBUTE functions in POAPPRV workflow
2841 --  Added for bug 3668188
2842 --Returns:
2843 --resultout
2844 --  A BOOLEAN TRUE if the Open Document icon should be shown, FALSE otherwise.
2845 --Testing:
2846 --  N/A
2847 --End of Comments
2848 -------------------------------------------------------------------------------
2849 -------------------------------------------------------------------------------
2850 FUNCTION is_open_document_allowed
2851 (
2852     p_itemtype            IN   VARCHAR2
2853 ,   p_itemkey             IN   VARCHAR2
2854 ,   p_notification_type   IN   VARCHAR2   --bug 3668188
2855 )
2856 RETURN BOOLEAN
2857 IS
2858     l_api_name               VARCHAR2(30) := 'is_open_document_allowed';
2859     l_log_head               VARCHAR2(100) := g_pkg_name||'.'||l_api_name;
2860     l_progress               VARCHAR2(3);
2861 
2862     l_authorization_status   PO_HEADERS_ALL.authorization_status%TYPE;
2863     l_result                 BOOLEAN := TRUE;
2864 
2865 BEGIN
2866 
2867 l_progress:='000'; PO_WF_DEBUG_PKG.insert_debug(p_itemtype,p_itemkey,l_log_head||':'||l_progress || 'Notification Type = ' || p_notification_type);
2868 
2869     -- Get the Authorization Status (e.g. 'PRE-APPROVED','APPROVED',
2870     -- 'INCOMPLETE', etc.) of the document.
2871     --
2872     l_authorization_status := wf_engine.GetItemAttrText
2873                               (   itemtype => p_itemtype
2874                               ,   itemkey  => p_itemkey
2875                               ,   aname    => 'AUTHORIZATION_STATUS'
2876                               );
2877 
2878 l_progress:='010'; PO_WF_DEBUG_PKG.insert_debug(p_itemtype,p_itemkey,l_log_head||':'||l_progress||' Authorization Status = '||l_authorization_status);
2879 
2880 
2881     -- bug 3668188: changed the Open Doc allowed logic.
2882     -- If document is ('Pre-Approved' or 'In Process') and the
2883     -- notification is going back to the Submitter, then that
2884     -- user should not be able to open the document for edit.
2885     --
2886     IF (l_authorization_status IN ('PRE-APPROVED', 'IN PROCESS')
2887         AND nvl(p_notification_type, 'SUBMITTER') = 'SUBMITTER')
2888     THEN
2889         l_progress:='020';
2890         PO_WF_DEBUG_PKG.insert_debug(p_itemtype,p_itemkey,l_log_head||':'||l_progress||':FALSE');
2891         l_result := FALSE;
2892     END IF;
2893 
2894     l_progress:='030';
2895     PO_WF_DEBUG_PKG.insert_debug(p_itemtype,p_itemkey,l_log_head||':'||l_progress||':TRUE');
2896     return (l_result);
2897 
2898 EXCEPTION
2899 
2900     WHEN OTHERS THEN
2901         PO_WF_DEBUG_PKG.insert_debug(p_itemtype,p_itemkey,l_log_head||':'||SQLERRM);
2902         RAISE;
2903 
2904 END is_open_document_allowed;
2905 
2906 ------------------<BUG 13951919>-----------------------------------------------
2907 -------------------------------------------------------------------------------
2908 --Start of Comments
2909 --Name: update_action_history
2910 --Pre-reqs:
2911 --  None.
2912 --Modifies:
2913 --  None
2914 --Locks:
2915 --  None.
2916 --Function:
2917 --  This procedure updates the po_action_history table based on the approvers response.
2918 --Parameters:
2919 --IN:
2920 --p_action_code
2921 --p_recipient_id
2922 --p_note
2923 --p_po_header_id
2924 --p_current_id
2925 --p_doc_type
2926 --p_doc_subtype
2927 --p_approval_path_id --<bug 14105414>
2928 --p_draft_id
2929 
2930 --OUT:
2931 
2932 --End of Comments
2933 -------------------------------------------------------------------------------
2934 -------------------------------------------------------------------------------
2935 
2936 PROCEDURE update_action_history (p_action_code         IN VARCHAR2,
2937                               p_recipient_id           IN NUMBER,
2938                               p_note                   IN VARCHAR2,
2939                               p_po_header_id           IN NUMBER,
2940                               p_current_id             IN NUMBER,
2941                               p_doc_type               IN  po_action_history.OBJECT_TYPE_CODE%TYPE,
2942                               p_doc_subtype            IN po_action_history.OBJECT_SUB_TYPE_CODE%TYPE,
2943                               p_approval_path_id       IN PO_ACTION_HISTORY.APPROVAL_PATH_ID%TYPE,  --<bug 14105414>
2944                               p_draft_id               IN NUMBER,
2945                               p_draft_type             IN VARCHAR2)  --PAR Approval
2946 IS
2947   pragma AUTONOMOUS_TRANSACTION;
2948 
2949   l_progress               VARCHAR2(100) := '000';
2950 
2951   l_sequence_num           PO_ACTION_HISTORY.SEQUENCE_NUM%TYPE;
2952   l_object_revision_num    PO_ACTION_HISTORY.OBJECT_REVISION_NUM%TYPE;
2953   l_approval_path_id       PO_ACTION_HISTORY.APPROVAL_PATH_ID%TYPE;
2954   l_request_id             PO_ACTION_HISTORY.REQUEST_ID%TYPE;
2955   l_program_application_id PO_ACTION_HISTORY.PROGRAM_APPLICATION_ID%TYPE;
2956   l_program_date           PO_ACTION_HISTORY.PROGRAM_DATE%TYPE;
2957   l_program_id             PO_ACTION_HISTORY.PROGRAM_ID%TYPE;
2958 
2959   l_document_id            NUMBER;
2960   l_doc_sub_type           po_action_history.OBJECT_SUB_TYPE_CODE%TYPE;
2961 
2962 BEGIN
2963 
2964   -- Handling mod approval case.
2965   if(nvl(p_draft_id, -1) = -1) then
2966     l_document_id := p_po_header_id;
2967     l_doc_sub_type := p_doc_subtype;
2968   else
2969     l_document_id := p_draft_id;
2970     -- PAR Approval
2971     IF p_draft_type = 'MOD' THEN
2972       l_doc_sub_type := 'MODIFICATION';
2973     ELSIF p_draft_type ='PAR' THEN
2974       l_doc_sub_type := 'POST_AWARD_REQUEST';
2975     END IF;
2976   end if;
2977 
2978   --Start of code changes: <bug 14105414>
2979   SELECT max(sequence_num)
2980   INTO l_sequence_num
2981   FROM PO_ACTION_HISTORY
2982   WHERE object_id = l_document_id
2983      AND object_type_code = p_doc_type
2984      AND object_sub_type_code = l_doc_sub_type;
2985 
2986 
2987    SELECT object_revision_num,
2988   	 approval_path_id,
2989          request_id,
2990          program_application_id,
2991          program_date,
2992          program_id
2993   INTO   l_object_revision_num,
2994          l_approval_path_id,
2995          l_request_id,
2996          l_program_application_id,
2997          l_program_date,
2998          l_program_id
2999   FROM PO_ACTION_HISTORY
3000   WHERE object_id = l_document_id
3001      AND object_type_code = p_doc_type
3002      AND object_sub_type_code = l_doc_sub_type
3003      AND employee_id = p_current_id
3004      AND ACTION_CODE IS NULL
3005      AND rownum =1;
3006   --End of code changes. <bug 14105414>
3007 
3008   l_progress := '010';
3009 
3010   -- Update action history with the action details
3011   UPDATE PO_ACTION_HISTORY
3012   SET     last_update_date = sysdate,
3013           last_updated_by =  fnd_global.user_id,
3014           last_update_login = fnd_global.login_id ,
3015           action_date = sysdate,
3016           action_code = p_action_code,
3017           note = p_note,
3018           approval_path_id = nvl(p_approval_path_id, l_approval_path_id), --<bug 14105414>
3019           offline_code = NULL
3020    WHERE  employee_id = p_current_id
3021    AND	object_id = l_document_id
3022    AND	object_type_code = p_doc_type
3023    AND  object_sub_type_code = l_doc_sub_type
3024    AND  action_code IS NULL;
3025 
3026   l_progress := '020';
3027 
3028   IF p_recipient_id IS NOT NULL THEN --<bug 14105414>
3029     INSERT INTO PO_ACTION_HISTORY
3030         	(object_id,
3031         	object_type_code,
3032         	object_sub_type_code,
3033         	sequence_num,
3034         	last_update_date,
3035         	last_updated_by,
3036         	employee_id,
3037         	action_code,
3038 		action_date,
3039         	note,
3040         	object_revision_num,
3041         	last_update_login,
3042         	creation_date,
3043         	created_by,
3044         	request_id,
3045         	program_application_id,
3046         	program_id,
3047         	program_date,
3048         	approval_path_id,
3049         	offline_code,
3050         	program_update_date
3051                 )
3052     VALUES (l_document_id,
3053         	p_doc_type,
3054         	l_doc_sub_type,
3055         	l_sequence_num + 1,
3056         	sysdate,
3057         	fnd_global.user_id,
3058         	p_recipient_id,
3059         	NULL,
3060 		NULL,
3061         	NULL,
3062         	l_object_revision_num,
3063         	fnd_global.login_id,
3064         	sysdate,
3065         	fnd_global.user_id,
3066         	l_request_id,
3067         	l_program_application_id,
3068         	l_program_id,
3069         	l_program_date,
3070         	l_approval_path_id,
3071         	NULL,
3072         	sysdate);
3073   END IF; --<bug 14105414>
3074   l_progress := '030';
3075 
3076   commit;
3077 EXCEPTION
3078   WHEN OTHERS THEN
3079     wf_core.context('PO_WF_PO_NOTIFICATION','update_action_history',l_progress,sqlerrm);
3080     RAISE;
3081 END;
3082 
3083 END PO_WF_PO_NOTIFICATION;