DBA Data[Home] [Help]

PACKAGE BODY: APPS.PO_CHG_REQUEST_GRP

Source


1 PACKAGE BODY PO_CHG_REQUEST_GRP AS
2 /* $Header: POXGCHGB.pls 120.3.12010000.3 2008/10/20 15:30:54 vchiran ship $ */
3 
4 
5  g_module_prefix CONSTANT VARCHAR2(50) := 'po.plsql.' || g_pkg_name || '.';
6 
7 -- Read the profile option that enables/disables the debug log
8 g_fnd_debug VARCHAR2(1) := NVL(FND_PROFILE.VALUE('AFLOG_ENABLED'),'N');
9 
10 
11 /*
12 This PL/SQL table will store the supplier request.  A new row will be added
13 for each call of the store_supplier_request.
14 
15 g_po_change_table pos_chg_rec_tbl;
16 */
17 /*
18   g_int_cont_num value will store the internal control number of each request.
19   This will be set in the initialize call and reset on the windup call.
20   Each time the API is called, it will be matched for the integrity purposes.
21 
22 g_int_cont_num   varchar2(256);
23 */
24 
25 
26 /*******************************  Private Procedures  ***********************/
27 
28 procedure getNewShipmentNumber (p_line_id IN number,
29                                 x_new_shipment_number OUT NOCOPY number) is
30 i  number;
31 l_shipment_number  number := null;
32 l_api_name          CONSTANT VARCHAR2(30) := 'getNewShipmentNumber';
33 begin
34   select max(shipment_num) + 1
35   into l_shipment_number
36   from po_line_locations_archive_all
37   where po_line_id = p_line_id
38         and latest_external_flag = 'Y';
39 
40 
41 
42    if (g_po_change_table.count() > 0) then
43      FOR i in 1..g_po_change_table.count()
44        LOOP
45         if (g_po_change_table(i).Document_Line_Id =  p_line_id ) then
46            if (l_shipment_number <= g_po_change_table(i).Document_Shipment_Number) then
47              l_shipment_number := g_po_change_table(i).Document_Shipment_Number + 1;
48            end if;
49         end if;
50        end loop;
51     end if;
52   x_new_shipment_number := l_shipment_number;
53   exception when others then
54    --There can be only unforeseen system errors.
55    IF g_fnd_debug = 'Y' THEN
56       IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_UNEXPECTED) THEN
57         FND_LOG.string(FND_LOG.level_unexpected, g_module_prefix ||
58                      l_api_name || '.others_exception', sqlcode);
59       END IF;
60 	    END IF;
61     raise;
62 end;
63 
64 
65 procedure validateCancelRequest(
66            p_api_version    IN     NUMBER,
67            p_init_msg_list  IN     VARCHAR2 := FND_API.G_FALSE,
68            x_return_status  OUT    NOCOPY VARCHAR2,
69            p_po_header_id   IN     NUMBER,
70            p_po_release_id  IN     NUMBER,
71            p_po_line_location_id IN number default null) IS
72 
73     p_document_id       NUMBER;
74     v_document_type     PO_HEADERS_ALL.TYPE_LOOKUP_CODE%TYPE;
75     v_document_subtype  PO_HEADERS_ALL.TYPE_LOOKUP_CODE%TYPE;
76     v_type_code         PO_HEADERS_ALL.TYPE_LOOKUP_CODE%TYPE;
77     l_api_name          CONSTANT VARCHAR2(30) := 'validateCancelRequest';
78     l_api_version       CONSTANT NUMBER := 1.0;
79     l_doc_line_id	number; -- added for bug# 5639722
80     x_org_id            number;
81 
82   BEGIN
83     IF NOT FND_API.compatible_api_call(l_api_version, p_api_version,
84                                        l_api_name, g_pkg_name)
85     THEN
86         RAISE FND_API.g_exc_unexpected_error;
87     END IF;
88 
89     x_return_status := FND_API.g_ret_sts_success;
90 
91     -- Call this when logging is enabled
92 
93    IF g_fnd_debug = 'Y' THEN
94     IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
95       FND_LOG.string(FND_LOG.LEVEL_PROCEDURE, g_module_prefix || l_api_name ||
96                    '.invoked', 'Type: ' ||
97                    ', Header  ID: ' || NVL(TO_CHAR(p_po_header_id),'null') ||
98                    ', Release ID: ' || NVL(TO_CHAR(p_po_release_id),'null'));
99     END IF;
100    END IF;
101     if (p_po_release_id is not null) then
102         p_document_id      := p_po_release_id;
103         v_document_type    := 'RELEASE';
104         v_document_subtype := 'BLANKET';
105 
106         select org_id
107         into x_org_id
108         from po_releases_all
109         where po_release_id= p_po_release_id;
110 
111     else
112         p_document_id := p_po_header_id;
113         select type_lookup_code into v_type_code
114         from po_headers_all
115         where po_header_id= p_po_header_id;
116         if (v_type_code in ('STANDARD','PLANNED')) then
117             v_document_type    := 'PO';
118             v_document_subtype := v_type_code;
119         elsif (v_type_code in ('BLANKET','CONTRACT')) then
120             v_document_type    := 'PA';
121             v_document_subtype := v_type_code;
122         end if;
123 
124         select org_id
125         into x_org_id
126         from po_headers_all
127         where po_header_id= p_po_header_id;
128 
129     end if;
130          -- Set the org context before calling the cancel api
131 
132 	 PO_MOAC_UTILS_PVT.set_org_context(x_org_id) ; -- <R12 MOAC>
133 
134 	 -- added for bug# 5639722
135 	 select plla.PO_LINE_ID into l_doc_line_id
136 	 from po_line_locations_all plla
137 	 where plla.line_location_id = p_po_line_location_id;
138 
139          PO_Document_Control_GRP.check_control_action(
140          p_api_version      => 1.0,
141          p_init_msg_list    => FND_API.G_TRUE,
142          x_return_status    => x_return_status,
143          p_doc_type         => v_document_type,
144          p_doc_subtype      => v_document_subtype,
145          p_doc_id           => p_po_header_id,
146          p_doc_num          => null,
147          p_release_id       => p_po_release_id,
148          p_release_num      => null,
149          p_doc_line_id      => l_doc_line_id, -- bug# 5639722
150          p_doc_line_num     => null,
151          p_doc_line_loc_id  => p_po_line_location_id ,
152          p_doc_shipment_num => null,
153          p_action           => 'CANCEL');
154 
155         -- dbms_output.put_line ('The error is ' || x_return_status);
156 
157 
158 EXCEPTION
159 
160     WHEN FND_API.g_exc_error THEN
161         x_return_status := FND_API.g_ret_sts_error;
162     WHEN FND_API.g_exc_unexpected_error THEN
163         x_return_status := FND_API.g_ret_sts_unexp_error;
164     WHEN OTHERS THEN
165         x_return_status := FND_API.g_ret_sts_unexp_error;
166         IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.g_msg_lvl_unexp_error) THEN
167             FND_MSG_PUB.add_exc_msg(g_pkg_name, l_api_name);
168             IF g_fnd_debug = 'Y' THEN
169             IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_UNEXPECTED) THEN
170               FND_LOG.string(FND_LOG.level_unexpected, g_module_prefix ||
171                             l_api_name || '.others_exception', sqlcode);
172             END IF;
173             END IF;
174         END IF;
175 
176 END validateCancelRequest;
177 
178 
179 
180 /********
181   Note this procedure will not check if there is a change pending already in
182        the change tables as if there is a change pending already it
183        would have been validated in the validate header.
184 ********/
185 -- Bug 7287009
186 /*Added vendor id and vendor site id in the signature of the procedure
187 Added l_org_id variable to capture org_id*/
188 
189 procedure handle_header_level_requests
190     (p_po_number IN  varchar2,  --PO # of the PO being modified or
191                                 --the Blanket's PO #
192      p_release_number IN  number,   -- Release number if the PO Type
193                                     -- is release or null
194      p_po_type IN  varchar2,  --  RELEASE or STANDARD.
195      p_revision_num IN  number,   -- Revision number of the PO or the release
196      p_tp_id  IN  number,      --  vendor_id
197      p_tp_site_id     IN  number,  --  vendor_site_id
198      p_reason  IN  varchar2,
199      p_ack_type   IN  varchar2,     -- 'ACCEPT' or 'REJECT' or 'MODIFICATION' or 'CANCELLATION'
200      p_so_order_number IN varchar2,
201      p_is_change  IN OUT NOCOPY number,
202      x_error_id_out IN OUT NOCOPY number,   -- The error id will be 2;
203                                             -- errors will go to the TP sysadmin
204      x_error_status_out IN OUT NOCOPY varchar2 -- Error message in this call
205                                                --concatenated with the old ones
206 )
207 is
208 l_release_id number;
209 l_po_header_id  number;
210 l_max_rev  number;
211 l_rec_cur_index number := 0;
212 l_ack_type varchar2 (30) := null;
213 l_old_so_order_number varchar2(25) := null;
214 l_new_so_order_number varchar2(25) := null;
215 l_req_status  varchar2(30);
216 l_po_type varchar2(25);
217 l_can_cancel_status varchar2 (3) := null;
218 l_org_id   number;
219 
220 begin
221 
222    if (p_ack_type <> 'CANCELLATION') then
223      l_release_id := null;
224      if (p_po_type = 'RELEASE') then
225        if (p_so_order_number is not null) then
226          /*
227            PO_CHG_API_REL_SO_CHG_INVLD  = Sales Order Number change is not
228                                         supported for releases.
229          */
230           x_error_id_out := 2;
231           x_error_status_out := x_error_status_out ||
232        	                     fnd_message.get_string('PO',
233        	                                  'PO_CHG_API_REL_SO_CHG_INVLD');
234        end if;
235        return;  -- p_so_order_number is null, simply return as there no change
236      else
237       -- Bug 7287009 - Start
238       /*Used vendor id and vendor site id combination to fetch org_id.
239       Org_id is used in the second query's where clause to restrict
240       mutiple records fetch.*/
241 
242       SELECT org_id
243       into   l_org_id
244       FROM   po_vendor_sites_all
245       WHERE  vendor_id = p_tp_id
246              AND vendor_site_id  = p_tp_site_id;
247 
248       select po_header_id, VENDOR_ORDER_NUM
249       into l_po_header_id, l_old_so_order_number
250       from po_headers_all
251       where segment1 = p_po_number
252             AND org_id = l_org_id
253             AND TYPE_LOOKUP_CODE NOT IN ('QUOTATION','RFQ');
254       -- Bug 7287009 - End
255 
256 
257      end if;  --if p_po_type = 'RELEASE'
258 
259      --Ack Type always should be modification.
260 
261       l_ack_type := 'MODIFICATION';
262 
263 
264      if (p_so_order_number is not null and
265          p_so_order_number <> l_old_so_order_number) then
266          p_is_change := 1;
267          l_new_so_order_number := p_so_order_number;
268      else  --if there is no so_line_number change or if new is
269            --same as old so_line_number
270          p_is_change := 0;  --we don't allow any other changes at the header.
271          l_new_so_order_number := null;
272          l_old_so_order_number := null;
273 
274      end if;
275    else -- if (p_ack_type <> 'CANCELLATION')
276      l_ack_type := p_ack_type;
277 
278       -- Bug 7287009 - Start
279       /*Used vendor id and vendor site id combination to fetch org_id.
280       Org_id is used in the second query's where clause to restrict
281       mutiple records fetch.*/
282 
283       SELECT org_id
284       into   l_org_id
285       FROM   po_vendor_sites_all
286       WHERE  vendor_id = p_tp_id
287              AND vendor_site_id  = p_tp_site_id;
288 
289      select po_header_id into l_po_header_id
290      from po_headers_all
291      where segment1 = p_po_number
292            AND org_id = l_org_id
293            AND TYPE_LOOKUP_CODE NOT IN ('QUOTATION','RFQ');
294      -- Bug 7287009 - End
295 
296      if (upper(p_po_type) = 'RELEASE') then
297        select po_release_id into l_release_id
298        from po_releases_all
299        where po_header_id = l_po_header_id and release_num = p_release_number;
300      end if;
301 
302      if (p_ack_type = 'CANCELLATION') then
303        validateCancelRequest(
304            p_api_version => 1.0,
305            p_init_msg_list  => FND_API.G_FALSE,
306            x_return_status  => l_can_cancel_status,
307            p_po_header_id   => l_po_header_id,
308            p_po_release_id  => l_release_id
309            );
310 
311            if (l_can_cancel_status <> FND_API.G_RET_STS_SUCCESS) then
312                 /*
313 	              PO_INVALID_CANCEL_REQ_REL = "The Release RELNUM for PO  PONUMBER
317 	             fnd_message.set_token('RELNUM', p_release_number, false);
314 	                                            cannot be canelled due to error: ERRCODE. The error message is : ERRMSG"
315 	             */
316 	             fnd_message.set_name('PO', 'PO_INVALID_CANCEL_REQ_REL');
318 	             fnd_message.set_token('PONUMBER', p_po_number, false);
319                  fnd_message.set_token('ERRCODE', l_can_cancel_status, false);
320                  fnd_message.set_token('ERRMSG', FND_MSG_PUB.Get(p_msg_index => 1,p_encoded   => 'F'));
321 
322 
323 
324                  x_error_status_out := x_error_status_out || fnd_message.get;
325 
326                  x_error_id_out := 2;
327                  return;
328            end if;
329        end if;
330 
331    end if;
332 
333 
334       /************** Store Request *********************/
335       if (x_error_id_out <> 0) then
336         return;  --there was an error.
337       end if;
338 
339       if (p_is_change = 0 and l_ack_type <> 'CANCELLATION') then
340         return;  --There is no change or there is error.
341       end if;
342 
343       select max(REVISION_NUM)
344       into l_max_rev
345       from po_headers_archive_all
346       where PO_HEADER_ID = l_po_header_id;
347 
348       if (upper(p_po_type) = 'STANDARD') then
349           l_po_type := 'PO';
350       else
351           l_po_type := p_po_type;
352       end if;
353 
354       l_req_status := 'PENDING';  -- 'PENDING' state, initially.
355       g_po_change_table.extend(1);
356       l_rec_cur_index := g_po_change_table.last;
357             /*  Note N/U in the following comments stands for
358                 not used in case of supplier change
359                 N/A stands for not applicable in case of SHIPMENT level.
360              */
361 
362 
363       g_po_change_table(l_rec_cur_index) := PO_CHG_REQUEST_PVT.create_pos_change_rec(
364             p_Action_Type => l_ack_type,
365             p_Initiator => 'SUPPLIER',
366             p_Document_Type => l_po_type,
367             p_Request_Level => 'HEADER',
368             p_Request_Status => l_req_status,
369             p_Document_Header_Id => l_po_header_id,
370             p_Request_Reason => p_reason,
371             p_PO_Release_Id => l_release_id,
372             p_Document_Num => p_po_number,
373             p_Document_Revision_Num => l_max_rev,
374             p_Old_Supplier_Order_Number => l_old_so_order_number,
375             p_New_Supplier_Order_Number => l_new_so_order_number
376       );
377 
378   exception
379   when others then
380     x_error_id_out := 2;
381     x_error_status_out := x_error_status_out || SQLERRM;
382 
383 
384 end handle_header_level_requests;
385 
386 
387 /****
388    Note:  This procedure is called only if the change is at the line level.
389 ****/
390 
391 -- Bug 7287009
392 /*Added vendor id and vendor site id in the signature of the procedure
393 Added l_org_id variable to capture org_id*/
394 procedure validate_line_change (
395      p_po_number IN  varchar2,  --PO # of the PO being modified or the Blanket's PO #
396      p_release_number IN  number, -- Release number if the PO Type
397                                   -- is release or null
398      p_po_type IN  varchar2,      --  RELEASE or STANDARD.
399      p_revision_num IN  number,   -- Revision number of the PO or the release
400      p_tp_id  IN  number,      --  vendor_id
401      p_tp_site_id     IN  number,  --  vendor_site_id
402      p_line_num IN  number,       -- Line number being modified
403      p_quantity IN  number,       -- The new quantity (can be null)
404      p_quantity_uom IN varchar2,  -- The UOM of the new quantity
405      p_price IN  number,          -- The new price value (can be null)
406      p_price_currency IN  varchar2, -- The currency code of the new price
407                                     --(can be null)
408      p_price_uom IN  varchar2,   -- The UOM code of the new price (can be null)
409      p_supplier_part_num IN varchar2, --Can be null
410      p_reason IN varchar2,
411      p_is_change IN OUT NOCOPY number,
412      x_error_id_out IN OUT NOCOPY number,
413      x_error_status_out IN OUT NOCOPY varchar2
414 )
415 is
416 l_line_id  number;
417 l_po_header_id number;
418 l_max_rev  number;
419 l_rec_cur_index number := 0;
420 l_old_price_currency  varchar2(10);
421 l_old_price number;
422 l_new_price number;
423 l_closed_code varchar2(30);
424 l_closed_flag varchar2(1);
425 l_cancel_flag varchar2(1);
426 l_old_supplier_part_num  varchar2(25);
427 l_new_supplier_part_num  varchar2(25);
428 l_req_status  varchar2(30);
429 l_po_type varchar2(25);
430 l_stage  varchar2(10) := 'BEGIN';
431 l_po_curr  varchar2(10);
432 l_org_id   number;
433 begin
434 
435  --validate the the line number exists for the po specified and
436  -- get some more information about the line.
437  begin
438 
439    -- Bug 7287009 - Start
440    /*Used vendor id and vendor site id combination to fetch org_id.
441    Org_id is used in the second query's where clause to restrict
442    mutiple records fetch.*/
443 
444    SELECT org_id
445    into   l_org_id
446    FROM   po_vendor_sites_all
447    WHERE  vendor_id = p_tp_id
451      PLA.PO_LINE_ID, PHA.PO_HEADER_ID,
448           AND vendor_site_id  = p_tp_site_id;
449 
450    select
452      FSPA.PAYMENT_CURRENCY_CODE BUYING_ORG_CURRENCY,
453      PLA.UNIT_PRICE UNIT_PRICE,
454      PLA.CLOSED_CODE,PLA.CLOSED_FLAG, PLA.CANCEL_FLAG, PLA.VENDOR_PRODUCT_NUM,
455      POCR.REQUEST_STATUS, PHA.CURRENCY_CODE
456     into l_line_id, l_po_header_id,
457        l_old_price_currency, l_old_price,
458        l_closed_code, l_closed_flag, l_cancel_flag, l_old_supplier_part_num,
459        l_req_status, l_po_curr
460 
461     FROM
462      PO_LINES_ALL PLA,
463      FINANCIALS_SYSTEM_PARAMS_ALL FSPA,
464      PO_HEADERS_ALL PHA,
465      PO_CHANGE_REQUESTS POCR
466 
467     WHERE
468 
469      FSPA.ORG_ID = PLA.ORG_ID AND
470      pha.po_header_id = PLA.PO_HEADER_ID and
471      pha.segment1 = p_po_number and
472      pha.org_id = l_org_id AND
473      pha.TYPE_LOOKUP_CODE = 'STANDARD' and
474      PLA.line_num = p_line_num and
475      PLA.PO_HEADER_ID = POCR.DOCUMENT_HEADER_ID (+) AND
476      PLA.PO_LINE_ID   = POCR.DOCUMENT_LINE_ID (+) AND
477      POCR.REQUEST_LEVEL	(+)= 'LINE' AND
478      POCR.CHANGE_ACTIVE_FLAG (+)= 'Y';
479 
480     -- Bug 7287009 - End
481 
482      exception
483      when no_data_found then
484        /*
485        PO_LINE_NUM_INVALID = 'The Line number LINENUM for
486                               PO PONUM does not exists'.
487        */
488         fnd_message.set_name('PO', 'PO_LINE_NUM_INVALID');
489         fnd_message.set_token('LINENUM', p_line_num, false);
490         fnd_message.set_token('PONUM', p_po_number, false);
491 
492         x_error_status_out := x_error_status_out || fnd_message.get;
493 
494         x_error_id_out := 2;
495         return;
496 
497 	when others then
498 	  x_error_status_out := x_error_status_out ||
499 	                        'Error at finding the line info.' || SQLERRM;
500 	  x_error_id_out := 2;
501           return;
502     end;
503 
504 
505      --Validate if there is a quantity change
506      if (p_quantity is not null) then
507         /*
508           PO_LN_QTY_INVALID = 'Changing the quantity at
509                                the line level is invalid';
510         */
511        	  x_error_id_out := 2;
512 	  x_error_status_out := x_error_status_out ||
513 	             	        fnd_message.get_string('PO',
514 	             	                               'PO_LN_QTY_INVALID');
515      	return;
516      end if;
517 
518      --Validate there is no change in the currency
519      if (p_price_currency is not null and
520          l_po_curr <> p_price_currency) then
521          /*
522 	    PO_CURRENCY_CHG_NOT_ALLOWED = 'Existing currency  OLD_CUR is not allowed to change to  NEW_CUR.  Changing currency is not allowed.'
523 	  */
524 	  x_error_id_out := 2;
525 	  fnd_message.set_name('PO', 'PO_CURRENCY_CHG_NOT_ALLOWED');
526 	  fnd_message.set_token('OLD_CUR', l_po_curr, false);
527 	  fnd_message.set_token('NEW_CUR', p_price_currency, false);
528           x_error_status_out := x_error_status_out || fnd_message.get;
529           return;
530       end if;
531 
532 
533      --Validate price change request
534      --Price change is allowed at the line level only for standard po type
535      if (p_po_type = 'RELEASE' and p_price is not null) then
536        /*
537          PO_REL_PRICE_CHANGE_INVALID = 'At line level price cannot be
538                                         changed for PO Releases.'
539        */
540          x_error_id_out := 2;
541          x_error_status_out := x_error_status_out ||
542        	                      fnd_message.get_string('PO',
543        	                                 'PO_REL_PRICE_CHANGE_INVALID');
544       	return;
545 
546        end if;
547 
548      if (p_price is not null and p_price = 0) then
549       /*
550         PO_NEW_PRICE_ZERO_INVALID = 'Price cannot be changed to zero.'
551       */
552 	x_error_id_out := 2;
553 	x_error_status_out := x_error_status_out ||
554 			       fnd_message.get_string('PO',
555 			                 'PO_NEW_PRICE_ZERO_INVALID');
556 	return;
557 
558       end if;
559 
560       if (p_price is not null and p_price < 0) then
561 	/*
562          PO_PRICE_LT_ZERO = 'The new quantity PRICE is less than
563                               zero and it is not allowed.';
564         */
565         fnd_message.set_name('PO', 'PO_PRICE_LT_ZERO');
566         fnd_message.set_token('PRICE', p_price, false);
567         x_error_status_out := x_error_status_out || fnd_message.get;
568 
569 	x_error_id_out := 2;
570 	return;
571        end if;
572 
573        --validate the status of the po_line.
574        -- We cannot 'isLineChangable' proc as we need err msg.
575        if (l_cancel_flag is not null and l_cancel_flag = 'Y') then
576          /*
577 	  PO_CHN_API_LINE_CANCELED = 'The requested line LINENUM for PO
578 	                              PONUM is already cancelled.  No change
579 	                              is allowed at this stage.'
580 	 */
581 	 x_error_id_out := 2;
582 	 fnd_message.set_name('PO', 'PO_CHN_API_LINE_CANCELED');
583  	 fnd_message.set_token('LINENUM', p_line_num, false);
584 	 fnd_message.set_token('PONUM',  p_po_number, false);
585 
586 
590        end if;
587 	 x_error_status_out := x_error_status_out || fnd_message.get;
588 	 return;
589 
591 
592 
593 
594        if (l_closed_flag is not null and
595           (l_closed_code = 'CLOSED' or l_closed_code = 'FINALLY CLOSED' or
596            l_closed_code = 'CLOSED FOR RECEIVING' or
597            l_closed_code = 'CLOSED FOR INVOICING')) then
598          /*
599 	  PO_CHN_API_LINE_CLOSED_CODE = 'The requested line LINENUM for PO
600 	                                 PONUM is in the status CLOSEDCODE.
601 	                                 No change is allowed at this stage.'
602 	 */
603 	 x_error_id_out := 2;
604 	 fnd_message.set_name('PO', 'PO_CHN_API_LINE_CLOSED_CODE');
605 	 fnd_message.set_token('LINENUM', p_line_num, false);
606 	 fnd_message.set_token('PONUM',  p_po_number, false);
607 	 fnd_message.set_token('CLOSEDCODE',  l_closed_code, false);
608        end if;
609        if (l_closed_flag is not null and l_closed_flag = 'Y') then
610          /*
611        	  PO_CHN_API_LINE_CLOSED_FLAG = 'The requested line
612        	                                LINENUM for PO PONUM is already Closed.
613        	                                No change is allowed at this stage.'
614        	 */
615        	 x_error_id_out := 2;
616        	 fnd_message.set_name('PO', 'PO_CHN_API_LINE_CLOSED_FLAG');
617         	 fnd_message.set_token('LINENUM', p_line_num, false);
618        	 fnd_message.set_token('PONUM',  p_po_number, false);
619 
620        	 x_error_status_out := x_error_status_out || fnd_message.get;
621        	 return;
622 
623        end if;
624 
625        /* commnt: If it is RELEASE do not allow changes to supplier_item_number  */
626               if (p_po_type = 'RELEASE' and p_supplier_part_num is not null) then
627                /*
628        	          PO_CHNAPI_RLS_INVALID_PARTNUM = 'The supplier part number
629        	                                           cannot be
630        	                                           changed to SUPPPARTNUM
631        	                                           for a release.';
632        	        */
633        	fnd_message.set_name('PO', 'PO_CHNAPI_RLS_INVALID_PARTNUM');
634        	fnd_message.set_token('SUPPPARTNUM', p_supplier_part_num, false);
635        	x_error_status_out := x_error_status_out || fnd_message.get;
636 
637        	x_error_id_out := 2;
638        	return;
639        end if;
640 
641        if (p_supplier_part_num is not null and
642            l_old_supplier_part_num <> p_supplier_part_num) then
643            p_is_change := 1;
644            l_new_supplier_part_num := p_supplier_part_num;
645        else
646            l_new_supplier_part_num := null;
647            l_old_supplier_part_num := null;
648        end if;
649 
650        if (p_price is not null and l_old_price <> p_price) then
651          p_is_change := 1;
652          l_new_price := p_price;
653        else
654          l_new_price := null;
655          l_old_price := null;
656        end if;
657 
658        /*  Check if there is a change request pending for that line*/
659        if (l_req_status = 'PENDING' or l_req_status = 'BUYER_APP' or
660            l_req_status = 'WAIT_MGR_APP') then
661           /*
662        	  PO_CHN_API_LINE_CHN_PEN = 'A change request for line LINENUM for
663        	                             PO PONUM is pending.  No change is
664        	                             allowed at this stage.'
665        	 */
666        	 x_error_id_out := 2;
667        	 fnd_message.set_name('PO', 'PO_CHN_API_LINE_CHN_PEN');
668          fnd_message.set_token('LINENUM', p_line_num, false);
669        	 fnd_message.set_token('PONUM',  p_po_number, false);
670 
671        	 x_error_status_out := x_error_status_out || fnd_message.get;
672        	 return;
673 
674        end if;
675 
676 
677        /************** Store Request *********************/
678 
679       if (p_is_change = 0 or x_error_id_out <> 0) then
680         return;  --There is no change or there is error.
681       end if;
682 
683       /*  Ignore the revision number sent as requested by CLN team.  */
684       select max(REVISION_NUM)
685       into l_max_rev
686       from po_headers_archive_all
687       where PO_HEADER_ID = l_po_header_id;
688 
689       if (upper(p_po_type) = 'STANDARD') then
690         l_po_type := 'PO';
691       else
692         l_po_type := p_po_type;
693       end if;
694 
695       l_req_status := 'PENDING';  --'PENDING' state, initially.
696       l_stage := 'Store';
697       g_po_change_table.extend(1);
698       l_rec_cur_index := g_po_change_table.last;
699       /*  Note N/U in the following comments stands for not
700           used in case of supplier change
701           N/A stands for not applicable in case of LINE level.
702        */
703 
704       g_po_change_table(l_rec_cur_index) := PO_CHG_REQUEST_PVT.create_pos_change_rec(
705       p_Action_Type => 'MODIFICATION',
706       p_Initiator => 'SUPPLIER',
707       p_Request_Reason => p_reason,
708       p_Document_Type => l_po_type,
709       p_Request_Level => 'LINE',
710       p_Request_Status => l_req_status,
711       p_Document_Header_Id => l_po_header_id,
712       p_PO_Release_Id => null,
713       p_Document_Num => p_po_number,
717       p_Old_Supplier_Part_Number => l_old_supplier_part_num,
714       p_Document_Revision_Num => l_max_rev,
715       p_Document_Line_Id => l_line_id,
716       p_Document_Line_Number => p_line_num,
718       p_New_Supplier_Part_Number => l_new_supplier_part_num,
719       p_Old_Price => l_Old_Price,
720       p_New_Price => l_new_price
721       );
722 
723 
724        exception
725          when others then
726            x_error_id_out := 2;
727            x_error_status_out := x_error_status_out ||
728                                 'in validating the line :' || l_stage ||
729                                 ': ' || SQLERRM;
730 
731 
732 end validate_line_change;
733 
734 
735 
736 /********
737   Note this procedure will not check if there is a change pending
738        already in the change tables as if there is a change pending
739        already it would have been validated in the validate header.
740 ********/
741 
742 -- Bug 7287009
743 /*Added vendor id and vendor site id in the signature of the procedure
744 Added l_org_id variable to capture org_id*/
745 procedure validate_shipment_change (
746        p_po_number IN  varchar2,  --PO # of the PO being modified or the Blanket's PO #
747        p_release_number IN  number,   -- Release number if the PO Type is release or null
748        p_po_type IN  varchar2,  --  RELEASE or STANDARD.
749        p_revision_num IN  number,   -- Revision number of the PO or the release
750        p_tp_id  IN  number,      --  vendor_id
751        p_tp_site_id     IN  number,  --  vendor_site_id
752        p_line_num IN  number,    -- Line number being modified
753        p_shipment_num IN  number,    -- Shipment number (can be null if the change is at the line)
754        p_quantity IN  number,    -- The new quantity (can be null)
755        p_quantity_uom IN  varchar2,  -- The UOM of the new quantity
756        p_price IN  number,    -- The new price value (can be null)
757        p_price_currency IN  varchar2,  -- The currency code of the new price (can be null)
758        p_price_uom IN  varchar2,   -- The UOM code of the new price (can be null)
759        p_promised_date IN  date,         -- The new promised date (can be null)
760        p_reason  IN  varchar2,
761        p_ack_type  IN  varchar2,     -- 'ACCEPT' or 'REJECT' or 'MODIFICATION'
762        p_so_line_number IN varchar2,
763        p_is_change IN OUT NOCOPY number,
764        x_error_id_out IN OUT NOCOPY number,
765        x_error_status_out IN OUT NOCOPY varchar2,
766        p_parent_shipment_number  number default NULL,
767        p_SUPPLIER_DOC_REF       varchar2 default NULL,
768        p_SUPPLIER_LINE_REF      varchar2 default NULL,
769        p_SUPPLIER_SHIPMENT_REF  varchar2 default NULL
770 )
771 is
772 l_old_quantity  number;
773 l_new_quantity  number;
774 l_old_promised_date  date;
775 l_new_promised_date  date;
776 l_old_price number;
777 l_new_price number;
778 l_old_uom  varchar2 (10);
779 l_old_price_currency varchar2(10);
780 l_line_price_ovrride varchar2(2);
781 l_line_id number;
782 l_release_id number;
783 l_line_location_id number;
784 l_po_header_id  number;
785 l_max_rev  number;
786 l_rec_cur_index number := 0;
787 l_qt_recieved number := 0;
788 l_qt_billed number := 0;
789 l_closed_code  varchar2 (30);
790 l_closed_flag varchar2(1);
791 l_ack_type varchar2 (30) := null;
792 l_old_so_line_number varchar2(25);
793 l_new_so_line_number varchar2(25);
794 l_req_status  varchar2(30);
795 l_po_type varchar2(25);
796 l_shipment_number  number;
797 l_parent_line_location_id number;
798 l_shipment_type  varchar2(25);
799 l_drop_ship_flag varchar2(1);
800 l_return_status  varchar2(1);
801 l_err_msg  varchar2(2000);
802 l_po_curr  varchar2(10);
803 l_org_id   number;
804 
805 begin
806 
807      if (p_parent_shipment_number is null) then
808        l_shipment_number := p_shipment_num;
809      else
810        l_shipment_number := p_parent_shipment_number;
811      end if;
812 
813      if (p_po_type = 'RELEASE') then
814       begin
815       -- Bug 7287009 - Start
816       /*Used vendor id and vendor site id combination to fetch org_id.
817       Org_id is used in the second query's where clause to restrict
818       mutiple records fetch.*/
819 
820       SELECT org_id
821       into   l_org_id
822       FROM   po_vendor_sites_all
823       WHERE  vendor_id = p_tp_id
824              AND vendor_site_id  = p_tp_site_id;
825       select
826             PLLA.po_release_id, PLLA.LINE_LOCATION_ID,
827             PLLA.PO_LINE_ID, PHA.PO_HEADER_ID,
828             (PLLA.QUANTITY - PLLA.QUANTITY_CANCELLED) ORDERED_QUANTITY,
829             PLLA.QUANTITY_RECEIVED, PLLA.QUANTITY_BILLED,
830             --MUOMTL.UOM_CODE UOM,
831             FSPA.PAYMENT_CURRENCY_CODE BUYING_ORG_CURRENCY,
832             NVL(PLLA.PROMISED_DATE, PLLA.NEED_BY_DATE) PROMISED_DATE,
833             PLLA.PRICE_OVERRIDE PRICE_OVERRIDE,
834             PLLA.CLOSED_CODE,PLLA.CLOSED_FLAG, PLLA.SUPPLIER_ORDER_LINE_NUMBER,
835             POCR.REQUEST_STATUS, PLA.ALLOW_PRICE_OVERRIDE_FLAG,
836             SHIPMENT_TYPE, DROP_SHIP_FLAG, PHA.CURRENCY_CODE
837             into l_release_id, l_line_location_id, l_line_id, l_po_header_id,
838             l_old_quantity, l_qt_recieved, l_qt_billed,
839             --l_old_uom,
840             l_old_price_currency,
844             l_shipment_type, l_drop_ship_flag, l_po_curr
841             l_old_promised_date, l_old_price,
842             l_closed_code, l_closed_flag, l_old_so_line_number,
843             l_req_status, l_line_price_ovrride,
845          FROM
846               PO_LINE_LOCATIONS_ALL PLLA,
847               PO_LINES_ALL PLA,
848               FINANCIALS_SYSTEM_PARAMS_ALL FSPA,
849             --  MTL_UNITS_OF_MEASURE_TL MUOMTL,
850               PO_RELEASES_ALL PRAA, PO_HEADERS_ALL PHA,
851               PO_CHANGE_REQUESTS POCR
852            WHERE
853               PLA.PO_Line_id= PLLA.PO_Line_ID and
854               (PLLA.QUANTITY - PLLA.QUANTITY_CANCELLED) > 0 AND
855               FSPA.ORG_ID = PLLA.ORG_ID AND
856               plla.po_release_id = praa.po_release_id and
857               pha.po_header_id = praa.po_header_id and
858               pha.segment1 = p_po_number and
859               pha.org_id = l_org_id AND
860               praa.release_num = p_release_number and
861               plla.shipment_num = l_shipment_number and
862               PLLA.PO_HEADER_ID        = POCR.DOCUMENT_HEADER_ID (+)  AND
863 	      PLLA.LINE_LOCATION_ID    = POCR.DOCUMENT_LINE_LOCATION_ID (+) AND
864 	      POCR.REQUEST_LEVEL	(+)= 'SHIPMENT' AND
865               POCR.CHANGE_ACTIVE_FLAG (+)= 'Y';
866       -- Bug 7287009 - End
867 
868           exception
869             when no_data_found then
870                 -- Check if the line number/shipment number valid.
871                 /*
872                   PO_RLS_SHIP_NUM_INVALID = 'The shipment number SHIPNUM for
873                                              the release number RELNUM of the
874                                              blanket PO PONUM does not exists'.
875                 */
876                  fnd_message.set_name('PO', 'PO_RLS_SHIP_NUM_INVALID');
877                  fnd_message.set_token('SHIPNUM', l_shipment_number, false);
878    	         fnd_message.set_token('PONUM', p_po_number, false);
879    	         fnd_message.set_token('RELNUM', p_release_number, false);
880 
881    	         x_error_status_out := x_error_status_out || fnd_message.get;
882 
883                  x_error_id_out := 2;
884                  return;
885 
886             when others then
887                 x_error_status_out := x_error_status_out ||
888                                     'Error at finding the release old info.' ||
889                                     SQLERRM;
890    	        x_error_id_out := 2;
891               return;
892 
893            end;
894 
895 
896      else -- (p_po_type = 'STANDARD')
897        begin
898          -- Bug 7287009 - Start
899          /*Used vendor id and vendor site id combination to fetch org_id.
900          Org_id is used in the second query's where clause to restrict
901          mutiple records fetch.*/
902 
903          SELECT org_id
904          into   l_org_id
905          FROM   po_vendor_sites_all
906          WHERE  vendor_id = p_tp_id
907                 AND vendor_site_id  = p_tp_site_id;
908 
909          select
910                   null, PLLA.LINE_LOCATION_ID, PLLA.PO_LINE_ID,
911                   PHA.PO_HEADER_ID,
912                   (PLLA.QUANTITY - PLLA.QUANTITY_CANCELLED) ORDERED_QUANTITY,
913                   PLLA.QUANTITY_RECEIVED, PLLA.QUANTITY_BILLED,
914                   FSPA.PAYMENT_CURRENCY_CODE BUYING_ORG_CURRENCY,
915                   NVL(PLLA.PROMISED_DATE, PLLA.NEED_BY_DATE) PROMISED_DATE,
916                   PLLA.PRICE_OVERRIDE PRICE_OVERRIDE,
917                   PLLA.CLOSED_CODE,PLLA.CLOSED_FLAG,
918                   PLLA.SUPPLIER_ORDER_LINE_NUMBER,
919                   POCR.REQUEST_STATUS,
920                   SHIPMENT_TYPE, DROP_SHIP_FLAG, PHA.CURRENCY_CODE
921                   into l_release_id, l_line_location_id, l_line_id,
922                        l_po_header_id, l_old_quantity, l_qt_recieved,
923                        l_qt_billed, l_old_price_currency,
924                        l_old_promised_date, l_old_price,
925                        l_closed_code, l_closed_flag, l_old_so_line_number,
926                        l_req_status,
927                        l_shipment_type, l_drop_ship_flag, l_po_curr
928                FROM
929                     PO_LINE_LOCATIONS_ALL PLLA,
930                     PO_LINES_ALL PLA,
931                     FINANCIALS_SYSTEM_PARAMS_ALL FSPA,
932                     PO_HEADERS_ALL PHA,
933                     PO_CHANGE_REQUESTS POCR
934                  WHERE
935                     PLA.PO_Line_id= PLLA.PO_Line_ID and
936                     (PLLA.QUANTITY - PLLA.QUANTITY_CANCELLED) > 0 AND
937                     FSPA.ORG_ID = PLLA.ORG_ID AND
938                     pha.po_header_id = PLLA.PO_HEADER_ID and
939                     pha.segment1 = p_po_number and
940                     pha.org_id = l_org_id AND
941                     pha.TYPE_LOOKUP_CODE NOT IN ('QUOTATION','RFQ') and
942                     plla.shipment_num = l_shipment_number and
943                     PLA.line_num = p_line_num and
944                     PLLA.PO_HEADER_ID = POCR.DOCUMENT_HEADER_ID (+)  AND
945 		    PLLA.LINE_LOCATION_ID = POCR.DOCUMENT_LINE_LOCATION_ID (+) AND
946 		    POCR.REQUEST_LEVEL	(+)= 'SHIPMENT' AND
947                     POCR.CHANGE_ACTIVE_FLAG (+)= 'Y';
948          -- Bug 7287009 - End
949          exception
950                  when no_data_found then
954                                                PO PONUM and the line number
951                  -- Check if the line number/shipment number valid.
952                  /*
953                     PO_STN_SHIP_NUM_INVALID = 'The shipment number SHIPNUM for the
955                                                LINENUM does not exists'.
956                  */
957                  fnd_message.set_name('PO', 'PO_STN_SHIP_NUM_INVALID');
958                  fnd_message.set_token('SHIPNUM', l_shipment_number, false);
959          	      fnd_message.set_token('PONUM', p_po_number, false);
960          	      fnd_message.set_token('LINENUM', p_line_num, false);
961 
962          	      x_error_status_out := x_error_status_out || fnd_message.get;
963 
964                    x_error_id_out := 2;
965                    return;
966 
967                  when others then
968                    x_error_status_out := x_error_status_out ||
969                                   'Error at finding the standard old info.' ||
970                                   SQLERRM;
971          	   x_error_id_out := 2;
972                    return;
973 
974            end;
975      end if;
976 
977 
978 
979      if (p_quantity is not null and p_quantity < 0) then
980         /*
981 	   PO_QTY_LT_ZERO = 'The new quantity QUANTITY is less
982 	                     than zero and it is not allowed.';
983 	*/
984 	fnd_message.set_name('PO', 'PO_QTY_LT_ZERO');
985 	fnd_message.set_token('QUANTITY', p_quantity, false);
986 
987 	x_error_status_out := x_error_status_out || fnd_message.get;
988 
989         x_error_id_out := 2;
990         return;
991      end if;
992 
993      if (p_quantity is not null and
994          (p_quantity < l_qt_recieved or p_quantity < l_qt_billed)) then
995        /*
996 	  PO_QTY_LT_RECVD_OR_BILLED = 'The new quantity QUANTITY is less
997 	                               than QTYRECIEVED or QTYBILLED and
998 	                               it is not allowed.';
999        */
1000        fnd_message.set_name('PO', 'PO_QTY_LT_RECVD_OR_BILLED');
1001        fnd_message.set_token('QUANTITY', p_quantity, false);
1002        fnd_message.set_token('QTYRECIEVED', l_qt_recieved, false);
1003        fnd_message.set_token('QTYBILLED', l_qt_billed, false);
1004        x_error_status_out := x_error_status_out || fnd_message.get;
1005 
1006        x_error_id_out := 2;
1007        return;
1008      end if;
1009 
1010      /***
1011         If p_quantity is zero we need to treat this as cancel?
1012         no commitment fro cln.
1013         If the new quantity  of a shipment is zero then change the
1014         action_type to CANCELLATION?.  No not a good idea.-FPJ.
1015         Also at this point check if the request has any other changes,
1016         like date, price, etc. then reject.
1017      ***/
1018 
1019      if (p_quantity is not null and p_quantity <> l_old_quantity
1020                        and p_ack_type <> 'CANCELLATION') then  -- added last condition for Bug# 5574841
1021         p_is_change := 1;
1022         l_new_quantity := p_quantity;
1023 
1024      else -- if the quantities are same
1025          l_old_quantity := null;
1026          l_new_quantity := null;
1027 
1028      end if;  -- End of Quantity validations.
1029 
1030      -- Check if the price and currency is being changed.
1031      --Validate there is no change in the currency
1032           if (p_price_currency is not null and
1033               l_po_curr <> p_price_currency) then
1034               /*
1035      	    PO_CURRENCY_CHG_NOT_ALLOWED = 'Existing currency  OLD_CUR is not allowed to change to  NEW_CUR.  Changing currency is not allowed.'
1036      	  */
1037      	  x_error_id_out := 2;
1038      	  fnd_message.set_name('PO', 'PO_CURRENCY_CHG_NOT_ALLOWED');
1039      	  fnd_message.set_token('OLD_CUR', l_po_curr, false);
1040      	  fnd_message.set_token('NEW_CUR', p_price_currency, false);
1041                x_error_status_out := x_error_status_out || fnd_message.get;
1042            return;
1043       end if;
1044 
1045      if (p_price is not null and p_price <> l_old_price) then
1046        p_is_change := 1;
1047 
1048 
1049        /*
1050          check if the po type is STANDARD, raise error.
1051          Price at the shipment level can be changed only for releases.
1052        */
1053        if (p_po_type <> 'RELEASE') then
1054          /*
1055            PO_STN_PRICE_CHANGE_INVALID = 'At shipment level price cannot
1056                                           be changed for STANDARD POs.'
1057          */
1058          x_error_id_out := 2;
1059          x_error_status_out := x_error_status_out ||
1060          fnd_message.get_string('PO', 'PO_STN_PRICE_CHANGE_INVALID');
1061      	 return;
1062 
1063        end if;
1064 
1065        if (p_po_type = 'RELEASE' and l_line_price_ovrride = 'N' and
1066            p_price is not null and p_price <> l_old_price
1067            ) then
1068             /*
1069 	      PO_RLS_PRICE_CHANGE_INVALID = 'At shipment level price cannot
1070 	                                     be changed for RELEASES POs as price
1071 	                                     override flag is set to no.'
1072 	    */
1073 	    x_error_id_out := 2;
1074 	    x_error_status_out := x_error_status_out ||
1075    	           fnd_message.get_string('PO', 'PO_RLS_PRICE_CHANGE_INVALID');
1076 	    return;
1077 
1081          /*
1078        end if;
1079 
1080        if (p_price is not null and p_price = 0) then
1082           PO_NEW_PRICE_ZERO_INVALID = 'Price cannot be changed to zero.'
1083          */
1084            x_error_id_out := 2;
1085            x_error_status_out := x_error_status_out ||
1086                       fnd_message.get_string('PO', 'PO_NEW_PRICE_ZERO_INVALID');
1087            return;
1088 
1089        end if;
1090 
1091        if (p_price is not null and p_price < 0) then
1092 	  /*
1093 	      PO_PRICE_LT_ZERO = 'The new quantity PRICE is less than
1094 	                          zero and it is not allowed.';
1095 	   */
1096 	   fnd_message.set_name('PO', 'PO_PRICE_LT_ZERO');
1097 	   fnd_message.set_token('PRICE', p_price, false);
1098            x_error_status_out := x_error_status_out || fnd_message.get;
1099 
1100 	  x_error_id_out := 2;
1101           return;
1102        end if;
1103        l_new_price := p_price;
1104      else  -- if the price is same
1105        l_old_price := null;
1106        l_new_price := null;
1107 
1108   end if;
1109 
1110   -- Check if the promised date is valid; Doc Submission program will
1111   -- validates this against need-by.
1112   if (p_promised_date is not null) then
1113     p_is_change := 1;
1114     if (p_promised_date < sysdate) then
1115       /*
1116          PO_NEW_PROM_DATE_IS_PAST = 'The requested date NEWPROMDATE is past;
1117                                      Promised Date should be a future date'
1118        */
1119         x_error_id_out := 2;
1120         fnd_message.set_name('PO', 'PO_NEW_PROM_DATE_IS_PAST');
1121 	fnd_message.set_token('NEWPROMDATE',
1122 	                      to_char(p_promised_date, 'MM/DD/YY HH:MI:SS AM'),
1123 	                      false);
1124 
1125         x_error_status_out := x_error_status_out || fnd_message.get;
1126         return;
1127 
1128     end if;
1129     l_new_promised_date := p_promised_date;
1130   end if;
1131 
1132   if (p_promised_date is null or p_promised_date = l_old_promised_date) then
1133     l_new_promised_date := null;
1134     l_old_promised_date := null;
1135   end if;
1136 
1137   --Validate if the ack type is accept or reject do not allow changes
1138   if (p_ack_type is null) then
1139     l_ack_type := 'MODIFICATION';
1140   else
1141     l_ack_type := p_ack_type;
1142   end if;
1143 
1144 
1145    --Validate the shipment status if changes are allowed
1146    if (l_closed_code = 'CLOSED FOR INVOICE' or
1147        l_closed_code = 'CLOSED FOR RECEIVING') then
1148       /*
1149        PO_SHIPMENT_CLOSED_CODE = 'Shipment SHIPMENT for line LINENUM PO PONUM
1150                                   is closed for invoicing or receiving; Changes
1151                                   are not allowed at this stage.'
1152       */
1153 	x_error_id_out := 2;
1154 	fnd_message.set_name('PO', 'PO_SHIPMENT_CLOSED_CODE');
1155 	fnd_message.set_token('SHIPMENT', l_shipment_number, false);
1156 	fnd_message.set_token('LINENUM', p_line_num, false);
1157 	fnd_message.set_token('PONUM', p_po_number, false);
1158 	x_error_status_out := x_error_status_out || fnd_message.get;
1159 
1160        return;
1161    end if;
1162 
1163    if (l_closed_flag is not null and  l_closed_flag = 'Y') then
1164       /*
1165        PO_SHIPMENT_CLOSED_FLAG = 'Shipment SHIPMENT for line LINENUM PO PONUM
1166                                   is closed; Changes are not allowed
1167                                   at this stage.'
1168       */
1169      	x_error_id_out := 2;
1170      	fnd_message.set_name('PO', 'PO_SHIPMENT_CLOSED_FLAG');
1171 	    fnd_message.set_token('SHIPMENT', l_shipment_number, false);
1172 	    fnd_message.set_token('LINENUM', p_line_num, false);
1173 	    fnd_message.set_token('PONUM', p_po_number, false);
1174 	    x_error_status_out := x_error_status_out || fnd_message.get;
1175        return;
1176    end if;
1177 
1178    if (p_so_line_number is not null and
1179        p_so_line_number <> l_old_so_line_number) then
1180        p_is_change := 1;
1181        l_new_so_line_number := p_so_line_number;
1182    else
1183        l_new_so_line_number := null;
1184        l_old_so_line_number := null;
1185 
1186    end if;
1187 
1188    /*  Check if there is a change request pending for that line*/
1189    if (l_req_status = 'PENDING' or l_req_status = 'BUYER_APP' or
1190         l_req_status = 'WAIT_MGR_APP') then
1191    /*
1192      PO_CHN_API_SHIP_CHN_PEN = 'A change request for shipment SHIPNUM line
1193                                 LINENUM for PO PONUM is pending.  No change
1194                                 is allowed at this stage.'
1195    */
1196       x_error_id_out := 2;
1197       fnd_message.set_name('PO', 'PO_CHN_API_SHIP_CHN_PEN');
1198       fnd_message.set_token('SHIPNUM', l_shipment_number, false);
1199       fnd_message.set_token('LINENUM', p_line_num, false);
1200       fnd_message.set_token('PONUM',  p_po_number, false);
1201 
1202       x_error_status_out := x_error_status_out || fnd_message.get;
1203       return;
1204 
1205    end if;
1206 
1207   if ((l_ack_type = 'ACCEPT' or l_ack_type = 'REJECT')
1208        and p_is_change = 1) then
1209        /*
1210           PO_ACK_N_CHN_INVALID = 'A Shipment cannot be both acknowledged
1214       	x_error_status_out := x_error_status_out ||
1211                                   and changed at the same time.'
1212        */
1213       	x_error_id_out := 2;
1215       	fnd_message.get_string('PO', 'PO_ACK_N_CHN_INVALID');
1216         return;
1217     elsif ((l_ack_type = 'ACCEPT' or l_ack_type = 'REJECT') and
1218             p_is_change = 0) then
1219             p_is_change := 2;
1220     end if;
1221 
1222     if(p_parent_shipment_number is not null and
1223        (l_shipment_type = 'PRICE BREAK' or l_drop_ship_flag = 'Y')) then
1224        /*
1225          PO_INVALID_SHIPMENT_TYPE = 'A split request is not allowed for shipment SHIPNUM line
1226                                 LINENUM for PO PONUM as it is a drop ship or has price break.'
1227        */
1228        x_error_id_out := 2;
1229       fnd_message.set_name('PO', 'PO_INVALID_SHIPMENT_TYPE');
1230       fnd_message.set_token('SHIPNUM', l_shipment_number, false);
1231       fnd_message.set_token('LINENUM', p_line_num, false);
1232       fnd_message.set_token('PONUM',  p_po_number, false);
1233 
1234       x_error_status_out := x_error_status_out || fnd_message.get;
1235       return;
1236 
1237    end if;
1238 
1239    --Validate request for cancellation of a shipment
1240    if (l_ack_type = 'CANCELLATION' and p_is_change <> 0) then
1241       /*
1242         PO_CANCEL_N_CHANGE_ERR = 'Both change and cancel request for Shipment SHIPNUM, line LINENUM, PO PONUM is not allowed.'
1243       */
1244       x_error_id_out := 2;
1245       fnd_message.set_name('PO', 'PO_CANCEL_N_CHANGE_ERR ');
1246       fnd_message.set_token('SHIPNUM', l_shipment_number, false);
1247       fnd_message.set_token('LINENUM', p_line_num, false);
1248       fnd_message.set_token('PONUM',  p_po_number, false);
1249 
1250       x_error_status_out := x_error_status_out || fnd_message.get;
1251       return;
1252    end if;
1253 
1254    if (l_ack_type = 'CANCELLATION') then
1255        validateCancelRequest(    p_api_version => 1.0,
1256            p_init_msg_list  => FND_API.G_FALSE,
1257            x_return_status  => l_return_status,
1258            p_po_header_id   => l_po_header_id,
1259            p_po_release_id  => l_release_id
1260            , p_po_line_location_id => l_line_location_id
1261            );
1262 
1263 
1264            if (l_return_status <>  FND_API.g_ret_sts_success) then
1265            /*
1266             PO_CHECK_CANCEL_ERR = 'There was an error ERRCODE in validating the cancel request for
1267                                    shipment SHIPNUM, line LINENUM, PO PONUM. The error message is: ERRMSG'
1268            */
1269 
1270             x_error_id_out := 2;
1271             l_err_msg := FND_MSG_PUB.Get(p_msg_index => 1,p_encoded => 'F');
1272             fnd_message.set_name('PO', 'PO_CHECK_CANCEL_ERR');
1273             fnd_message.set_token('ERRCODE', l_return_status, false);
1274             fnd_message.set_token('SHIPNUM', l_shipment_number, false);
1275             fnd_message.set_token('LINENUM', p_line_num, false);
1276             fnd_message.set_token('PONUM',  p_po_number, false);
1277             fnd_message.set_token('ERRMSG', l_err_msg, false);
1278 
1279             x_error_status_out := x_error_status_out || fnd_message.get;
1280 
1281             return;
1282 
1283         end if;
1284    end if;
1285 
1286 
1287 
1288   /*
1289      Note:  1.  No need to check if line is canceled or closed, etc.
1290                If so, the shipments are also automatically canceled or closed.
1291             2.  No need to check if there is a change pending here.
1292                 If so, validate header would have raised the error.
1293     */
1294       /************** Store Request *********************/
1295       if ( x_error_id_out <> 0) then
1296         return;
1297       end if;
1298       if (p_is_change = 0 and l_ack_type <> 'CANCELLATION') then
1299         return;  --There is no change or there is error.
1300         end if;
1301 
1302       select max(REVISION_NUM)
1303       into l_max_rev
1304       from po_headers_archive_all
1305       where PO_HEADER_ID = l_po_header_id;
1306 
1307       if (upper(p_po_type) = 'STANDARD') then
1308               l_po_type := 'PO';
1309             else
1310               l_po_type := p_po_type;
1311       end if;
1312 
1313       l_req_status := 'PENDING';  -- 'PENDING' state, initially.
1314       g_po_change_table.extend(1);
1315       l_rec_cur_index := g_po_change_table.last;
1316             /*  Note N/U in the following comments stands
1317                 for not used in case of supplier change
1318                 N/A stands for not applicable in case of SHIPMENT level.
1319              */
1320 
1321               /*  Added in FPJ for split
1322 	           If p_parent_shipment_number is not null, then we are splitting.
1323 	           so, l_document_line_location_id is the parent's line_location_id.
1324 	           In that case we will pass the
1325 	           l_document_line_location_id as l_parent_line_location_id.
1326 	           l_document_line_location_id as null,
1327 	           set the old values for qt, price, promised date to null
1328 	           get new value for l_document_shipment_number
1329 	        */
1330 	        if (p_parent_shipment_number is not null) then
1331 	          l_parent_line_location_id := l_line_location_id;
1332 	          l_line_location_id := null;
1333 	          --l_shipment_number := null;
1337 	          l_old_promised_date := null;
1334 	          getNewShipmentNumber (l_line_id, l_shipment_number);
1335 	          l_old_price := null;
1336 	          l_old_quantity := null;
1338 	          l_old_so_line_number := null;
1339               end if;
1340 
1341 
1342       g_po_change_table(l_rec_cur_index) := PO_CHG_REQUEST_PVT.create_pos_change_rec(
1343             p_Action_Type => l_ack_type,
1344             p_Initiator => 'SUPPLIER',
1345             p_Request_Reason => p_reason,
1346             p_Document_Type => l_po_type,
1347             p_Request_Level => 'SHIPMENT',
1348             p_Request_Status => l_req_status,
1349             p_Document_Header_Id => l_po_header_id,
1350             p_PO_Release_Id => l_release_id,
1351             p_Document_Num => p_po_number,
1352             p_Document_Revision_Num => l_max_rev,
1353             p_Document_Line_Id => l_line_id,
1354             p_Document_Line_Number => p_line_num,
1355             p_Document_Line_Location_Id => l_line_location_id,
1356             p_Document_Shipment_Number => l_shipment_number ,
1357             p_Parent_Line_Location_Id => l_parent_line_location_id,
1358             p_Old_Quantity => l_old_quantity,
1359             p_New_Quantity => l_new_quantity,
1360             p_Old_Promised_Date => l_old_promised_date,
1361             p_New_Promised_Date => l_new_promised_date,
1362             p_Old_Price => l_Old_Price,
1363             p_New_Price => l_new_price,
1364             p_Old_Supplier_Order_Line_Num => l_old_so_line_number,
1365             p_New_Supplier_Order_Line_Num => l_new_so_line_number,
1366             p_SUPPLIER_DOC_REF => p_SUPPLIER_DOC_REF,
1367             p_SUPPLIER_LINE_REF => p_SUPPLIER_LINE_REF,
1368             p_SUPPLIER_SHIPMENT_REF => p_SUPPLIER_SHIPMENT_REF
1369 
1370       );
1371 
1372 
1373   exception
1374   when others then
1375     x_error_id_out := 2;
1376     x_error_status_out := x_error_status_out || SQLERRM;
1377 
1378 
1379 end validate_shipment_change;
1380 
1381 
1382 /***********************   PUBLIC APIs  ****************************/
1383 
1384 /*
1385   This procedure needs to be called first to initialize an inbound transaction.
1386   This will initialize some global variables.  This should be called from the
1387   pre-process of the root node.  No errors should occur here lest there is any
1388   weird error, processing should not continue, as it has not been
1389   initialized properly.
1390 */
1391 procedure  initialize_chn_ack_inbound (
1392    	p_requestor	IN  varchar2,
1393 	p_int_cont_num	IN  varchar2,  -- ECX's ICN.
1394 	p_request_origin	IN  varchar2,  -- '9iAS'
1395 	p_tp_id	IN  number,    --  vendor_id
1396 	p_tp_site_id	IN  number,    --  vendor_site_id
1397 	x_error_id	OUT NOCOPY number,
1398 	x_error_status	OUT NOCOPY VARCHAR2
1399 
1400 
1401 ) is
1402 l_user_id   number;
1403 begin
1404   x_error_id := 0;
1405   x_error_status := '';
1406   g_int_cont_num := p_int_cont_num;
1407   g_requestor := p_requestor;
1408   g_request_origin  := p_request_origin;
1409 
1410    --ideally we should check if the requestor belongs to the tp_id and tp_site_id provided.
1411    begin
1412         select user_id
1413         into l_user_id
1414         from fnd_user
1415         where user_name = p_requestor;  --ideally it should be 'XML_USER'
1416       exception when others then
1417         /*
1418           PO_CHN_XML_USER_INVALID = "The  USERNAME is not a valid user
1419                                      in the system.
1420                                      Please consult your system administrator."
1421         */
1422         fnd_message.set_name('PO', 'PO_CHN_XML_USER_INVALID ');
1423         fnd_message.set_token('USERNAME', p_requestor, false);
1424         x_error_status := x_error_status || fnd_message.get;
1425         x_error_id := 2;
1426         return;
1427 
1428       end;
1429 
1430 
1431   if (g_po_change_table is not null) then
1432       g_po_change_table.delete;
1433       g_po_change_table := null;
1434   end if;
1435   --reinitilize the global variable.
1436   g_po_change_table := pos_chg_rec_tbl();
1437   g_po_type := null;
1438   g_po_number := null;
1439   g_release_number := null;
1440   g_tp_id := null;
1441   g_tp_site_id := null;
1442 
1443   exception
1444   when others then
1445    x_error_id := 2;
1446   	x_error_status := x_error_status || SQLERRM;
1447 
1448 end initialize_chn_ack_inbound;
1449 
1450 
1451 
1452 
1453 /*
1454   This API should be called from the in process of the header level.
1455   This will validate the header, if the PO #/Release  mentioned belongs
1456   to the vendor and vendor site id,
1457 */
1458 procedure validate_header (
1459    	p_requestor	IN  varchar2,
1460 	p_int_cont_num	IN  varchar2,
1461 	p_request_origin	IN  varchar2,  -- XML/OTA/9iAS/OPEN
1462 	p_request_type	IN  varchar2,    -- 'CHANGE' or 'ACKNOWLEDGE' or CANCELLATION
1463 	p_tp_id	IN  number,    --  vendor_id
1464 	p_tp_site_id	IN  number,
1465 	p_po_number	IN  varchar2,
1466 	p_release_number	IN  number,
1467 	p_po_type 	IN  varchar2,
1468 	p_revision_num	IN  number,
1469 	x_error_id_in	IN  number,
1470 	x_error_status_in IN  VARCHAR2,
1471 	x_error_id_out	OUT NOCOPY number,
1472 	x_error_status_out OUT NOCOPY VARCHAR2 -- Error message
1473 
1477 l_rel_status varchar2(25);
1474 ) is
1475 l_count  number := 0;
1476 l_po_status  varchar2(25);
1478 l_po_header_id number;
1479 l_release_id number := null;
1480 l_org_id number;
1481 --l_can_cancel_status varchar2 (2000) := null;
1482 begin
1483   x_error_id_out := x_error_id_in;
1484   x_error_status_out := x_error_status_in;
1485 
1486   -- Bug 7287009 - Start
1487   /*Used vendor id and vendor site id combination to fetch org_id.
1488   Org_id is used in the second query's where clause to restrict
1489   mutiple records fetch.*/
1490 
1491   SELECT org_id
1492   into   l_org_id
1493   FROM   po_vendor_sites_all
1494   WHERE  vendor_id = p_tp_id
1495          AND vendor_site_id  = p_tp_site_id;
1496 
1497   -- Bug 7287009 - End
1498 
1499 
1500   --Check if the given release  exists and belongs to the given TP
1501   if ('RELEASE' = upper(p_po_type) ) then
1502     select count(1) into l_count
1503     from po_releases_all pra, po_headers_all pha
1504     where pra.po_header_id = pha.po_header_id
1505     and pra.release_num = p_release_number
1506     and pha.segment1 = p_po_number
1507     and pha.org_id = l_org_id
1508     and pha.TYPE_LOOKUP_CODE NOT IN ('QUOTATION','RFQ');
1509 
1510     if (l_count < 1) then
1511      /*
1512        PO_REL_NUM_NOT_FOUND = "The  RELNUMBER with the blanket  PONUMBER
1513                                 does not belong to the given supplier."
1514      */
1515      --Check: Lets not worry about providing the supplier name.
1516      fnd_message.set_name('PO', 'PO_REL_NUM_NOT_FOUND');
1517      fnd_message.set_token('PONUMBER', p_po_number, false);
1518      fnd_message.set_token('RELNUMBER', p_release_number	, false);
1519      x_error_status_out := x_error_status_out || fnd_message.get;
1520      x_error_id_out := 2;
1521      return;
1522     end if;
1523 
1524   else -- assume that it is a STANDARD PO
1525   --Check if the given PO  exists and belongs to the given TP
1526     select count(1) into l_count
1527       from po_headers_all pha
1528       where pha.segment1 = p_po_number
1529       and pha.org_id = l_org_id
1530       AND pha.TYPE_LOOKUP_CODE NOT IN ('QUOTATION','RFQ');
1531 
1532     if (l_count < 1) then
1533     /*
1534       PO_PO_NUM_NOT_FOUND = "The PO number  PONUMBER does not belong to the given supplier."
1535     */
1536      fnd_message.set_name('PO', 'PO_PO_NUM_NOT_FOUND');
1537      fnd_message.set_token('PONUMBER', p_po_number, false);
1538      x_error_status_out := x_error_status_out || fnd_message.get;
1539      x_error_id_out := 2;
1540      return;
1541     end if;
1542  end if;
1543 
1544    -- There is a corner case where the same segment1 can
1545    -- belong to more than one org.  In that case return error.
1546    if (l_count > 1) then
1547    /*
1548          PO_PO_NUM_AMBIGUOUS = "The PO number  PONUMBER is ambiguous.
1549           Please contact system admin."?
1550     */
1551      fnd_message.set_name('PO', 'PO_PO_NUM_AMBIGUOUS');
1552      fnd_message.set_token('PONUMBER', p_po_number, false);
1553      x_error_status_out := x_error_status_out || fnd_message.get;
1554      x_error_id_out := 2;
1555      return;
1556    end if;
1557 
1558  --From here onwards PO is Valid
1559 
1560  --Check to see if the given PO or Release is in the right status
1561  --to recieve change or acknowledge.
1562 
1563  select authorization_status, po_header_id, last_update_date
1564    into l_po_status, l_po_header_id, g_last_upd_date
1565  from po_headers_all
1566  where segment1 = p_po_number
1567        and org_id = l_org_id
1568        and TYPE_LOOKUP_CODE NOT IN ('QUOTATION','RFQ');
1569 
1570  --Common validation for STANDARD and BLANKET PO for both CHANGE and ACKNOWLEDGE
1571  if (l_po_status in ('CANCELLED', 'CLOSED', 'FINALLY CLOSED',
1572                      'CLOSED FOR INVOICE', 'CLOSED FOR RECEIVING',
1573                      'SUPPLIER_CHANGE_PENDING', 'FROZEN',
1574                      'ON HOLD', 'PARTIALLY_ACKNOWLEDGED',
1575                      'INTERNAL CHANGE', 'REJECTED',
1576                      'IN PROCESS')) then
1577  --billOnlyFlag.equals("Y") ||^M
1578  --!(gaValid.equals("Y")) ||^M)
1579       /*
1580           PO_INVALID_STATUS_CODE = "The PO  PONUMBER is currently in
1581                                     POSTATUSCODE.  At this stage no
1582                                     modifictions to the PO is allowd."
1583       */
1584        fnd_message.set_name('PO', 'PO_INVALID_STATUS_CODE');
1585        fnd_message.set_token('PONUMBER', p_po_number, false);
1586        fnd_message.set_token('POSTATUSCODE', l_po_status, false);
1587 
1588        x_error_status_out := x_error_status_out || fnd_message.get;
1589 
1590        x_error_id_out := 2;
1591      return;
1592    end if;
1593 
1594  if (upper(p_request_type) = 'CHANGE') then
1595     if (l_po_status = 'ACK_REQUIRED') then
1596          /*
1597              PO_STD_INVALID_STATUS_CODE = "The PO  PONUMBER is currently in
1598                                            POSTATUSCODE.  At this stage no
1599                                            modifictions to the PO is allowed."
1600          */
1601           fnd_message.set_name('PO', 'PO_STD_INVALID_STATUS_CODE');
1602           fnd_message.set_token('PONUMBER', p_po_number, false);
1603           fnd_message.set_token('POSTATUSCODE', l_po_status, false);
1604 
1608           return;
1605           x_error_status_out := x_error_status_out || fnd_message.get;
1606 
1607           x_error_id_out := 2;
1609     end if;
1610  elsif (upper(p_request_type) = 'ACKNOWLEDGE') then
1611  null;  -- The common validations should be enough
1612 
1613  elsif (upper(p_request_type) = 'CANCELLATION') then
1614     --This will be handled as header level changes.
1615     null;
1616  else
1617    /*
1618        PO_INVALID_REQUEST_TYPE = "The request type REQUESTTYPE is not valid.
1619                                   It should be CHANGE or ACKNOWLEDGE"
1620    */
1621     fnd_message.set_name('PO', 'PO_INVALID_REQUEST_TYPE');
1622     fnd_message.set_token('REQUESTTYPE', p_request_type, false);
1623     x_error_status_out := x_error_status_out || fnd_message.get;
1624     x_error_id_out := 2;
1625     return;
1626 
1627  end if;
1628 
1629    /***  Validate the releases  ***/
1630    if ('RELEASE' = upper(p_po_type) ) then
1631 
1632       select authorization_status, po_release_id, last_update_date
1633       into l_rel_status, l_release_id, g_last_upd_date
1634       from po_releases_all
1635       where po_header_id = l_po_header_id and release_num = p_release_number;
1636 
1637        --Common validation for RELEASE for both CHANGE and ACKNOWLEDGE
1638       if (l_rel_status in ('CANCELLED', 'CLOSED', 'FINALLY CLOSED',
1639                            'CLOSED FOR INVOICE', 'CLOSED FOR RECEIVING',
1640                            'SUPPLIER_CHANGE_PENDING', 'FROZEN',
1641                            'ON HOLD',  'PARTIALLY_ACKNOWLEDGED',
1642                            'INTERNAL CHANGE', 'REJECTED',
1643                            'IN PROCESS')) then
1644     --billOnlyFlag.equals("Y") ||^M
1645     --!(gaValid.equals("Y")) ||^M)
1646          /*
1647              PO_INVALID_STATUS_CODE_REL = "The Release RELNUM for PO  PONUMBER
1648                                            is currently in  RELSTATUSCODE.
1649                                            At this stage no modifictions to
1650                                            the PO is allowed."
1651          */
1652 
1653           fnd_message.set_name('PO', 'PO_INVALID_STATUS_CODE_REL');
1654           fnd_message.set_token('RELNUM', p_release_number, false);
1655           fnd_message.set_token('PONUMBER', p_po_number, false);
1656           fnd_message.set_token('RELSTATUSCODE', l_rel_status, false);
1657 
1658           x_error_status_out := x_error_status_out || fnd_message.get;
1659 
1660           x_error_id_out := 2;
1661         return;
1662       end if;
1663 
1664     if (upper(p_request_type) = 'CHANGE') then
1665         if (l_po_status = 'ACK_REQUIRED') then
1666           /*
1667 	    PO_INVALID_STATUS_CODE_REL = "The Release RELNUM for PO  PONUMBER
1668 	                                  is currently in  RELSTATUSCODE.
1669 	                                  At this stage no modifictions
1670 	                                  to the PO is allowed."
1671 	  */
1672 
1673 	  fnd_message.set_name('PO', 'PO_INVALID_STATUS_CODE_REL');
1674 	  fnd_message.set_token('RELNUM', p_release_number, false);
1675 	  fnd_message.set_token('PONUMBER', p_po_number, false);
1676           fnd_message.set_token('RELSTATUSCODE', l_po_status, false);
1677 
1678           x_error_status_out := x_error_status_out || fnd_message.get;
1679 
1680           x_error_id_out := 2;
1681           return;
1682          end if;
1683      elsif (upper(p_request_type) = 'ACKNOWLEDGE') then
1684         null;  -- The common validations for release should be enough
1685      elsif (upper(p_request_type) = 'CANCELLATION') then
1686          --this will be handled as a header level change.
1687               null;
1688 
1689      else
1690       /*
1691           PO_INVALID_REQUEST_TYPE = "The request type REQUESTTYPE is not valid.
1692                                      It should be CHANGE or ACKNOWLEDGE"
1693       */
1694        fnd_message.set_name('PO', 'PO_INVALID_REQUEST_TYPE');
1695        fnd_message.set_token('REQUESTTYPE', p_request_type, false);
1696        x_error_status_out := x_error_status_out || fnd_message.get;
1697        x_error_id_out := 2;
1698        return;
1699 
1700       end if;
1701 
1702 
1703    end if; -- if p_po_type = 'RELEASE'
1704 
1705 
1706    --update the global variables
1707    g_po_type := p_po_type;
1708    g_po_number := p_po_number;
1709    g_release_number := p_release_number;
1710    g_tp_id := p_tp_id;
1711    g_tp_site_id := p_tp_site_id;
1712 
1713    /***  Handle Sales Order Change  ***/
1714 
1715 
1716   exception
1717   when others then
1718    x_error_id_out := 2;
1719    x_error_status_out := x_error_status_out || SQLERRM;
1720 
1721 
1722 end;
1723 
1724 /*
1725   This API should be called from the in process of the lines.
1726   This procedure needs to be called in the following scenarios:
1727 1.	Modifications to a PO at the shipment level
1728 2.	Modifications to a PO at the line level
1729 3.	Acknowledgment at the shipment level
1730 4.	Canceling at the shipment level
1731    Calls to this API will be stored in a pl/sql table and will
1732    not be processed immediately.
1733    Call process_supplier_request to process the request.
1734 */
1735 procedure store_supplier_request (
1736 	p_requestor	IN  varchar2,
1737 	p_int_cont_num	IN  varchar2,
1741 	p_level         IN varchar2,
1738 	p_request_type	IN  varchar2,
1739 	p_tp_id	IN  number,
1740 	p_tp_site_id	IN  number,
1742         p_po_number	IN  varchar2,
1743         p_release_number IN  number,
1744 	p_po_type 	IN  varchar2,
1745         p_revision_num	IN  number,
1746 	p_line_num	IN  number,
1747 	p_reason	IN  varchar2,
1748 	p_shipment_num	IN  number,
1749 	p_quantity	IN  number,
1750 	p_quantity_uom	IN  varchar2,
1751 	p_price	IN  number,
1752 	p_price_currency IN  varchar2,
1753 	p_price_uom	IN  varchar2,
1754         p_promised_date	IN  date,
1755 	p_supplier_part_num IN  varchar2,
1756 	p_so_number	IN  varchar2,
1757 	p_so_line_number IN  varchar2,
1758 	p_ack_type      IN  varchar2,
1759         x_error_id_in	IN     number,
1760   	x_error_status_in IN   varchar2,
1761         x_error_id_out	OUT NOCOPY number,
1762         x_error_status_out OUT NOCOPY varchar2,
1763         p_parent_shipment_number  number default NULL,
1764 	p_SUPPLIER_DOC_REF       varchar2 default NULL,
1765 	p_SUPPLIER_LINE_REF      varchar2 default NULL,
1766         p_SUPPLIER_SHIPMENT_REF  varchar2 default NULL
1767 ) is
1768 l_is_change  number :=0;
1769 l_reason varchar2(2000);
1770 begin
1771   x_error_id_out := x_error_id_in;
1772   x_error_status_out := x_error_status_in;
1773 
1774   -- validate parameters with the global variables.
1775 
1776   if ( p_int_cont_num	<> g_int_cont_num OR
1777        p_po_number <> g_po_number OR
1778        p_po_type <> g_po_type OR
1779        p_tp_id <> g_tp_id OR
1780        p_tp_site_id <> g_tp_site_id) then
1781   	x_error_id_out := 2;
1782   	x_error_status_out := x_error_status_out ||
1783   	           fnd_message.get_string('PO', 'PO_CHG_API_CALL_NOT_SYNC');
1784   	return;
1785   end if;
1786 
1787   /************** Validations ***********************/
1788   --Check the length of the reason;
1789   --it should not be more than 2000 bytes; if so truncate it.
1790   if (p_reason is null) then
1791 
1792        if (p_level = 'SHIPMENT') then
1793           /*
1794                PO_CHG_API_SH_REASON_IS_NULL = Reason cannot be null for
1795                                               line LINENUM and shipment SHIPNUM
1796            */
1797             fnd_message.set_name('PO', 'PO_CHG_API_SH_REASON_IS_NULL');
1798             fnd_message.set_token('LINENUM', p_line_num, false);
1799             fnd_message.set_token('SHIPNUM', p_shipment_num, false);
1800         elsif (p_level = 'LINE') then
1801             /*
1802             PO_CHG_API_LN_REASON_IS_NULL = Reason cannot be null for
1803                                            line LINENUM
1804             */
1805             fnd_message.set_name('PO', 'PO_CHG_API_LN_REASON_IS_NULL');
1806             fnd_message.set_token('LINENUM', p_line_num, false);
1807          else --if p_level = HEADER
1808          /*
1809             PO_CHG_API_REASON_IS_NULL Reason cannot be null for PONUM
1810           */
1811             fnd_message.set_name('PO', 'PO_CHG_API_REASON_IS_NULL');
1812             fnd_message.set_token('PONUM', p_po_number, false);
1813         end if;
1814 
1815         x_error_status_out := x_error_status_out || fnd_message.get;
1816         x_error_id_out := 2;
1817 
1818 
1819         return;
1820 
1821   end if;
1822 
1823 
1824   if (p_reason is not null) then
1825     l_reason := substr(ltrim(rtrim(p_reason, ' , 	'), ' ,	'), 1, 2000);
1826   else
1827      l_reason := p_reason;
1828   end if;
1829 
1830   -- For shipment level validations
1831   -- Bug 7287009 - Start
1832   /*Added vendor id and vendor site id in the parameter list*/
1833   if (p_level = 'SHIPMENT') then
1834     validate_shipment_change (p_po_number, p_release_number,
1835                               p_po_type, p_revision_num,
1836                               p_tp_id, p_tp_site_id,
1837                               p_line_num, p_shipment_num, p_quantity,
1838                               p_quantity_uom, p_price, p_price_currency,
1839                               p_price_uom, p_promised_date, l_reason,
1840                               p_ack_type, p_so_line_number, l_is_change,
1841     			      x_error_id_out, x_error_status_out,
1842     			      p_parent_shipment_number,
1843 			      p_SUPPLIER_DOC_REF, p_SUPPLIER_LINE_REF,
1844                               p_SUPPLIER_SHIPMENT_REF
1845     			     );
1846     -- Bug 7287009 - End
1847     if (x_error_id_out <> 0) then
1848       return;
1849     end if;
1850   end if;
1851 
1852   -- Bug 7287009 - Start
1853   /*Added vendor id and vendor site id in the parameter list*/
1854   if (p_level = 'LINE') then
1855     validate_line_change(p_po_number, p_release_number,
1856                          p_po_type, p_revision_num,
1857                          p_tp_id, p_tp_site_id,
1858     		         p_line_num, p_quantity,
1859     			 p_quantity_uom, p_price, p_price_currency, p_price_uom,
1860     			 p_supplier_part_num, l_reason,
1861     			 l_is_change, x_error_id_out, x_error_status_out
1862     				);
1863     -- Bug 7287009 - End
1864 
1865     if (x_error_id_out <> 0) then
1866       return;
1867     end if;
1868   end if;
1869 
1870   -- Bug 7287009 - Start
1871   /*Added vendor id and vendor site id in the parameter list*/
1872 
1873   if (p_level = 'HEADER') then
1874     handle_header_level_requests(p_po_number, p_release_number,
1878     			       l_is_change, x_error_id_out, x_error_status_out
1875                                p_po_type, p_revision_num,
1876                                p_tp_id, p_tp_site_id,
1877     			       p_reason, p_ack_type, p_so_number,
1879                                );
1880     -- Bug 7287009 - End
1881 
1882   end if;
1883 
1884 
1885 
1886 
1887   exception
1888   when others then
1889    x_error_id_out := 2;
1890   	x_error_status_out := x_error_status_out || SQLERRM;
1891 
1892 end store_supplier_request;
1893 
1894 /*
1895   Call this procedure from the post-process before calling the wind-up API
1896   only if the error_id from the earlier calls is 0.  This API should not
1897   be called if the request is for header level acknowledgment.
1898   This API will place the supplier request in the change request
1899   table and kicks-off the workflow for the approval of the change request.
1900 */
1901 procedure process_supplier_request (
1902 	p_int_cont_num	IN varchar2,
1903 	x_error_id_in   IN number,
1904 	x_error_status_in IN varchar2,
1905 	x_error_id_out	OUT NOCOPY number,
1906 	x_error_status_out OUT NOCOPY VARCHAR2
1907 ) is
1908 l_pos_errors POS_ERR_TYPE;
1909 l_po_header_id  number;
1910 l_po_release_id  number;
1911 l_revision_num number;
1912 l_online_report_id number := 0;
1913 i number;
1914 l_po_tbl_varchar2000 po_tbl_varchar2000 := null;
1915 l_err_count   number := 0;
1916 l_user_id     number;
1917 
1918 begin
1919   x_error_id_out := x_error_id_in;
1920   x_error_status_out := x_error_status_in;
1921 
1922  --dbms_output.put_line('x_error_status_out inside1 : ' || x_error_status_out);
1923 
1924  --validate the global information
1925 
1926  if ( p_int_cont_num	<> g_int_cont_num ) then
1927        x_error_id_out := 2;
1928        x_error_status_out := x_error_status_out ||
1929        fnd_message.get_string('PO', 'PO_CHG_API_CALL_NOT_SYNC');
1930        return;
1931   end if;
1932 
1933 
1934   if ( g_po_change_table is null OR g_po_change_table.count = 0) then
1935     x_error_id_out := 0;  --No change found.Do not error;but do not process.
1936     x_error_status_out := x_error_status_out ||
1937     fnd_message.get_string('PO', 'PO_CHG_API_NO_CHANGE_FOUND');
1938     return;
1939   end if;
1940 
1941   --dbms_output.put_line('x_error_status_out inside2 : ' || x_error_status_out);
1942 
1943  l_po_header_id := g_po_change_table(g_po_change_table.FIRST).Document_Header_Id;
1944  l_po_release_id := g_po_change_table(g_po_change_table.FIRST).PO_Release_Id;
1945  l_revision_num := g_po_change_table(g_po_change_table.FIRST).Document_Revision_Num;
1946  select user_id
1947         into l_user_id
1948         from fnd_user
1949         where user_name = g_requestor;
1950 
1951  --dbms_output.put_line('x_error_status_out inside3 : ' || x_error_status_out);
1952  PO_CHG_REQUEST_PVT.process_supplier_request (
1953              p_po_header_id  =>l_po_header_id,
1954              p_po_release_id  => l_po_release_id,
1955              p_revision_num   =>l_revision_num,
1956              p_po_change_requests => g_po_change_table,
1957              x_online_report_id  => l_online_report_id,
1958              x_pos_errors        => l_pos_errors,
1959              p_chn_int_cont_num  => g_int_cont_num,
1960              p_chn_source    => g_request_origin,
1961              p_chn_requestor_username  => g_requestor,
1962              p_user_id  =>  l_user_id,
1963              p_login_id  => l_user_id,
1964              p_last_upd_date => g_last_upd_date) ;
1965 
1966 
1967 
1968 /*
1969  FOR i IN l_pos_errors.FIRST..l_pos_errors.LAST LOOP
1970     x_error_id_out := 2;
1971     x_error_status_out := x_error_status_out ||
1972                           l_pos_errors(i).text_line; --buffer overflow?
1973  end loop;
1974  */
1975 
1976  if (l_pos_errors is not null) then
1977    l_po_tbl_varchar2000 := l_pos_errors.text_line;
1978 
1979    --dbms_output.put_line('x_error_status_out inside5 : '
1980    --|| x_error_status_out);
1981    if (l_po_tbl_varchar2000 is not null ) then
1982    --dbms_output.put_line('x_error_status_out inside5^ : '
1983    --|| x_error_status_out);
1984      l_err_count := l_po_tbl_varchar2000.count;
1985    end if;
1986 
1987    if (l_err_count > 0) then
1988    --dbms_output.put_line('x_error_status_out inside5^^ : '
1989    --|| x_error_status_out);
1990 
1991    FOR i IN 1..l_err_count LOOP
1992        x_error_id_out := 2;
1993        --dbms_output.put_line('x_error_status_out inside6 : '
1994        --|| x_error_status_out);
1995 
1996        x_error_status_out := x_error_status_out || l_po_tbl_varchar2000(i);
1997        --dbms_output.put_line('x_error_status_out inside7 : '
1998        --|| x_error_status_out);
1999      end loop;
2000    end if;
2001 end if;
2002  --dbms_output.put_line('x_error_status_out inside8 : '
2003  --|| x_error_status_out);
2004    exception
2005     when others then
2006      x_error_id_out := 2;
2007 
2008 
2009    begin
2010    --dbms_output.put_line('x_error_status_out inside9 : ' ||
2011    -- x_error_status_out);
2012      x_error_status_out := x_error_status_out || SQLERRM;
2013      --dbms_output.put_line('x_error_status_out inside10 : ' ||
2014      --x_error_status_out);
2015      exception  --may errorout due to bufferoverflow.
2016        when others then
2017        return;
2018    end;
2019 
2020 
2021 end process_supplier_request;
2022 
2023 /*
2024   This procedure needs to be called from Acknowledge PO inbound
2025   at in_process of the header, only when the PO is acknowledged
2026   at the header level.  In case of shipment level acknowledgement
2027   this procedure should not be called.  The acknowledge po request
2028   will be processed immediately and only once per transaction.
2032 	p_requestor	IN  varchar2,
2029   So, no need for error_id_in and error_id_out etc.
2030 */
2031 procedure acknowledge_po(
2033 	p_int_cont_num	IN  varchar2,
2034 	p_request_type	IN  varchar2,
2035 	p_tp_id	IN  number,
2036 	p_tp_site_id	IN  number,
2037         p_po_number	IN  varchar2,
2038         p_release_number	IN  number,
2039 	p_po_type 	IN  varchar2,
2040         p_revision_num	IN  number,
2041 	p_ack_code	IN  number,   -- 0 for accept 2 reject
2042 	p_ack_reason	IN  varchar2,
2043 	x_error_id	OUT NOCOPY number,
2044 	x_error_status	OUT NOCOPY VARCHAR2
2045 
2046 ) is
2047  l_po_header_id     VARCHAR2(30);
2048  l_po_release_id     VARCHAR2(30) := null;
2049  l_po_buyer_id       VARCHAR2(30);
2050  l_po_accept_reject  VARCHAR2(30);
2051  l_po_acc_type_code  VARCHAR2(30);
2052  l_po_ack_comments   VARCHAR2(2000);
2053  l_user_id           VARCHAR2(30);
2054  l_org_id            number;
2055 
2056  --Bug 6850595
2057  /*Added the follwoing variables.
2058  l_last_update_date is added to check the concurrency when the same PO is modified in different places.
2059  x_error is added to check if there are any concurrency issues. If x_error is true then it will raise
2060  concurrency exception.
2061  l_concurrency_exception is added to raise the exception in case if there are any concurrency issues. */
2062 
2063  l_last_update_date po_headers_all.last_update_date%type;
2064  x_error VARCHAR2(30);
2065  l_concurrency_exception EXCEPTION;
2066 
2067 begin
2068 
2069 	/*
2070 	  Note: The header is validated already at the validate_header stage.
2071 	*/
2072         -- Bug 7287009 - Start
2073         /*Used vendor id and vendor site id combination to fetch org_id.
2074         Org_id is used in the second query's where clause to restrict
2075         mutiple records fetch.*/
2076 
2077         SELECT org_id
2078         into   l_org_id
2079         FROM   po_vendor_sites_all
2080         WHERE  vendor_id = p_tp_id
2081                AND vendor_site_id  = p_tp_site_id;
2082 
2083 	select to_char(po_header_id), to_char(agent_id), LAST_UPDATE_DATE
2084 	into l_po_header_id, l_po_buyer_id, l_last_update_date
2085 	from po_headers_all
2086 	where segment1 = p_po_number
2087               and org_id = l_org_id
2088               AND TYPE_LOOKUP_CODE NOT IN ('QUOTATION','RFQ');
2089         -- Bug 7287009 - End
2090 
2091 	select to_char(user_id)
2092 	into l_user_id
2093 	from fnd_user
2094         where user_name = p_requestor;
2095 
2096 	if (p_po_type = 'RELEASE') then
2097 	  select to_char(po_release_id), to_char(agent_id), LAST_UPDATE_DATE
2098 	  into l_po_release_id, l_po_buyer_id, l_last_update_date
2099 	  from po_releases_all praa
2100 	  where po_header_id = l_po_header_id
2101 	        and RELEASE_NUM = p_release_number;
2102 	end if;
2103 
2104 	if (p_ack_code = 0) then
2105 	  l_po_accept_reject := 'Y';
2106 	elsif (p_ack_code = 2) then
2107 	  l_po_accept_reject := 'N';
2108 	elsif (p_ack_code = 1) then
2109 	 /*
2110 	  PO_CHN_API_ACK_CODE_1 = 'Accept with changes is not supported
2111 	                           through this API; Context: PONUM'
2112 	 */
2116 
2113 	 x_error_id := 2;
2114 	 fnd_message.set_name('PO', 'PO_CHN_API_ACK_CODE_1');
2115 	 fnd_message.set_token('PONUM',  p_po_number, false);
2117 	 x_error_status := x_error_status || fnd_message.get;
2118        	 return;
2119 	else
2120 	  /*
2121 	  PO_CHN_API_ACK_CODE_INVALID = 'AckCode of ACKCODE is invalid.
2122 	                                 It shoule either 0 for ACCEPT
2123 	                                 or 2 for REJECT; Context: PONUM'
2124 	 */
2125 	 x_error_id := 2;
2126 	 fnd_message.set_name('PO', 'PO_CHN_API_ACK_CODE_INVALID');
2127 	 fnd_message.set_token('ACKCODE',  p_po_number, false);
2128 	 fnd_message.set_token('PONUM',  p_po_number, false);
2129 
2130 	 x_error_status := x_error_status || fnd_message.get;
2131        	 return;
2132 	end if;
2133 
2134         --Bug 6850595
2135         /* l_last_update_date is passed as an input parameter to check the
2136         concurrency issue. x_error is an out variable, which captures errors
2137         if there are any exceptions. */
2138 
2139 	POS_ACK_PO.ACKNOWLEDGE_PO (
2140 	     l_po_header_id,
2141 	     l_po_release_id,
2142 	     l_po_buyer_id,
2143 	     l_po_accept_reject,
2144 	     l_po_acc_type_code,  --Should be always null from FPI.
2145 	     p_ack_reason,
2146 	     l_user_id,
2147              l_last_update_date,
2148              x_error);
2149 
2150         IF x_error = 'true' THEN
2151           RAISE l_concurrency_exception;
2152         END IF;
2153 
2154 exception
2155   when others then
2156    x_error_id := 2;
2157   	x_error_status := x_error_status || SQLERRM;
2158 end acknowledge_po;
2159 
2160 /*
2161   	Call this procedure at the post process stage as the last action.
2162   	At this point the pl/sql table will be 'delete'd.  Call this
2163   	procedure even if there were errors in the earlier calls.
2164 */
2165 procedure  windup_chn_ack_inbound (
2166    	p_requestor	IN  varchar2,
2167 	p_int_cont_num	IN  varchar2,
2168 	p_request_origin IN  varchar2,
2169 	p_tp_id	IN  number,
2170 	p_tp_site_id	IN  number,
2171        x_error_id_in	IN  number,
2172   	x_error_status_in IN   varchar2,
2173 	x_error_id_out	OUT NOCOPY number,
2174 	x_error_status_out OUT NOCOPY VARCHAR2
2175 ) is
2176 begin
2177 /*  We have no use of these global variables; so erase them;
2178 */
2179 
2180   x_error_id_out := x_error_id_in;
2181   x_error_status_out := x_error_status_in;
2182 
2183   g_int_cont_num := null;
2184 
2185   if (g_po_change_table is not null) then
2186       g_po_change_table.delete;
2187       g_po_change_table := null;
2188   end if;
2189 
2190   g_po_type := null;
2191   g_po_number := null;
2192   g_release_number := null;
2193   g_tp_id := null;
2194   g_tp_site_id := null;
2195 
2196 exception
2197   when others then
2198    x_error_id_out := 2;
2199    x_error_status_out := x_error_status_out || SQLERRM;
2200 end windup_chn_ack_inbound;
2201 
2202 end PO_CHG_REQUEST_GRP;
2203 
2204 
2205