DBA Data[Home] [Help]

PACKAGE BODY: APPS.PO_PDOI_HEADER_GROUPING_PVT

Source


1 PACKAGE BODY PO_PDOI_HEADER_GROUPING_PVT AS
2 /* $Header: PO_PDOI_HEADER_GROUPING_PVT.plb 120.12 2012/01/13 12:12:07 sbontala ship $ */
3 
4 d_pkg_name CONSTANT VARCHAR2(50) :=
5   PO_LOG.get_package_base('PO_PDOI_HEADER_GROUPING_PVT');
6 
7 -------------------------------------------------------
8 ----------- PRIVATE PROCEDURES PROTOTYPE --------------
9 -------------------------------------------------------
10 
11 PROCEDURE assign_round_num
12 ( x_all_headers_processed OUT NOCOPY VARCHAR2
13 );
14 
15 PROCEDURE assign_draft_id;
16 
17 PROCEDURE expire_lines_by_catalog_name;
18 
19 PROCEDURE init_doc_info_tbl
20 ( p_intf_header_id_tbl PO_TBL_NUMBER
21 );
22 
23 PROCEDURE check_new_draft_needed
24 ( p_draft_id IN NUMBER,
25   p_status   IN VARCHAR2,
26   x_new_draft_needed OUT NOCOPY VARCHAR2
27 );
28 
29 -------------------------------------------------------
30 -------------- PUBLIC PROCEDURES ----------------------
31 -------------------------------------------------------
32 
33 -----------------------------------------------------------------------
34 --Start of Comments
35 --Name: process
36 --Function:
37 --  Main process for header grouping
38 --Parameters:
39 --IN:
40 --IN OUT:
41 --OUT:
42 --x_all_headers_processed
43 --  FND_API.G_TRUE if all the headers are processed
44 --  FND_API.G_FALSE otherwise
45 --End of Comments
46 ------------------------------------------------------------------------
47 PROCEDURE process
48 ( x_all_headers_processed OUT NOCOPY VARCHAR2
49 ) IS
50 
51 d_api_name CONSTANT VARCHAR2(30) := 'process';
52 d_module CONSTANT VARCHAR2(255) := d_pkg_name || d_api_name || '.';
53 d_position NUMBER;
54 
55 BEGIN
56   d_position := 0;
57 
58   IF (PO_LOG.d_proc) THEN
59     PO_LOG.proc_begin (d_module);
60   END IF;
61 
62   PO_TIMING_UTL.start_time(PO_PDOI_CONSTANTS.g_T_HEADER_GROUPING);
63 
64   d_position := 10;
65 
66   -- set round number for interface records that will be processed in
67   -- current round
68   assign_round_num
69   ( x_all_headers_processed => x_all_headers_processed );
70 
71   d_position := 20;
72 
73   -- create draft for records that will be processed in current round
74   IF (x_all_headers_processed = FND_API.G_FALSE) THEN
75     assign_draft_id;
76 
77     d_position := 30;
78 
79     -- If lines for a particular catalog name will get expired, move those
80     -- records to draft table and set expiration date for those lines
81     IF (PO_PDOI_PARAMS.g_request.calling_module =
82           PO_PDOI_CONSTANTS.g_CALL_MOD_CATALOG_UPLOAD
83         AND
84         PO_PDOI_PARAMS.g_request.catalog_to_expire IS NOT NULL) THEN
85 
86       expire_lines_by_catalog_name;
87     END IF;
88   END IF;
89 
90   d_position := 40;
91 
92   PO_INTERFACE_ERRORS_UTL.flush_errors_tbl;
93 
94   d_position := 50;
95 
96   PO_PDOI_UTL.commit_work;
97 
98   PO_TIMING_UTL.stop_time(PO_PDOI_CONSTANTS.g_T_HEADER_GROUPING);
99 
100   IF (PO_LOG.d_proc) THEN
101     PO_LOG.proc_end (d_module);
102   END IF;
103 
104 EXCEPTION
105 WHEN OTHERS THEN
106   PO_MESSAGE_S.add_exc_msg
107   ( p_pkg_name => d_pkg_name,
108     p_procedure_name => d_api_name || '.' || d_position
109   );
110   RAISE;
111 END process;
112 
113 
114 -------------------------------------------------------
115 -------------- PRIVATE PROCEDURES ---------------------
116 -------------------------------------------------------
117 
118 -----------------------------------------------------------------------
119 --Start of Comments
120 --Name: assign_round_num
121 --Function:
122 --  For documents that can be processed in the same round, stamp those
123 --  record with processing_round_num = current_round_num so that they
124 --  will be processed later on
125 --Parameters:
126 --IN:
127 --IN OUT:
128 --OUT:
129 --x_all_headers_processed
130 --  FND_API.G_TRUE if all the headers are processed
131 --  FND_API.G_FALSE otherwise
132 --End of Comments
133 ------------------------------------------------------------------------
134 PROCEDURE assign_round_num
135 ( x_all_headers_processed OUT NOCOPY VARCHAR2
136 ) IS
137 
138 d_api_name CONSTANT VARCHAR2(30) := 'assign_round_num';
139 d_module CONSTANT VARCHAR2(255) := d_pkg_name || d_api_name || '.';
140 d_position NUMBER;
141 
142 l_process_update_replace BOOLEAN := FALSE;
143 
144 l_intf_header_id_tbl PO_TBL_NUMBER;
145 l_po_header_id_tbl PO_TBL_NUMBER;
146 
147 l_process_list DBMS_SQL.NUMBER_TABLE;
148 
149 BEGIN
150   d_position := 0;
151 
152   IF (PO_LOG.d_proc) THEN
153     PO_LOG.proc_begin (d_module);
154   END IF;
155 
156   x_all_headers_processed := FND_API.G_FALSE;
157 
158   -- Increment round number
159   PO_PDOI_PARAMS.g_current_round_num := PO_PDOI_PARAMS.g_current_round_num + 1;
160 
161   IF (PO_LOG.d_stmt) THEN
162     PO_LOG.stmt(d_module, d_position, 'Current Round Number: ' ||
163                 PO_PDOI_PARAMS.g_current_round_num);
164   END IF;
165 
166   IF (PO_PDOI_PARAMS.g_original_doc_processed = FND_API.G_FALSE) THEN
167     d_position := 10;
168 
169     -- First, we need to process NEW documents
170 
171     SELECT interface_header_id
172     BULK COLLECT
173     INTO l_intf_header_id_tbl
174     FROM (SELECT interface_header_id
175           FROM   po_headers_interface
176           WHERE  processing_round_num IS NULL
177           AND    processing_id = PO_PDOI_PARAMS.g_processing_id
178           AND    action IN (PO_PDOI_CONSTANTS.g_action_ORIGINAL,
179                             PO_PDOI_CONSTANTS.g_action_ADD)
180           ORDER BY interface_header_id)
181     WHERE rownum <= PO_PDOI_PARAMS.g_request.batch_size;
182 
183     IF (SQL%ROWCOUNT = 0) THEN
184       d_position := 20;
185 
186       -- mark g_original_doc_processed to TRUE so that we won't process
187       -- NEW documents the next time we come here
188       PO_PDOI_PARAMS.g_original_doc_processed := FND_API.G_TRUE;
189 
190       IF (PO_LOG.d_stmt) THEN
191         PO_LOG.stmt(d_module, d_position, 'Finished progressing doc with ' ||
192                     'action = original ');
193       END IF;
194 
195       -- IF there is no new doucment to create, we can go ahead and look for
196       -- documents to update/replace
197       l_process_update_replace := TRUE;
198     ELSE
199 
200       d_position := 30;
201 
202       FORALL i IN 1..l_intf_header_id_tbl.COUNT
203         UPDATE po_headers_interface
204         SET    processing_round_num = PO_PDOI_PARAMS.g_current_round_num
205         WHERE  interface_header_id = l_intf_header_id_tbl(i);
206 
207       IF (PO_LOG.d_stmt) THEN
208         PO_LOG.stmt(d_module, d_position, 'updated ' || SQL%ROWCOUNT ||
209                     'rows with current round number ');
210       END IF;
211     END IF;
212 
213   ELSE
214     d_position := 40;
215 
216     l_process_update_replace := TRUE;
217   END IF;
218 
219 
220   IF (l_process_update_replace) THEN
221     d_position := 50;
222 
223     -- if there are multiple records in headers interface, they can be processed
224     -- together only if they are not acting on the same document.
225 
226     SELECT interface_header_id,
227            po_header_id
228     BULK COLLECT
229     INTO l_intf_header_id_tbl,
230          l_po_header_id_tbl
231     FROM po_headers_interface
232     WHERE processing_round_num IS NULL
233     AND processing_id = PO_PDOI_PARAMS.g_processing_id
234     AND po_header_id IS NOT NULL
235     AND action IN (PO_PDOI_CONSTANTS.g_action_UPDATE,
236                    PO_PDOI_CONSTANTS.g_action_REPLACE)
237     ORDER BY interface_header_id;
238 
239     d_position := 60;
240 
241     FOR i IN 1..l_intf_header_id_tbl.COUNT LOOP
242       -- Use an associative array to figure out whether there is already
243       -- another header interface record in the same round that tries to
244       -- update the same document. If so, defer the current update to the
245       -- next round.
246 
247       IF (l_po_header_id_tbl IS NOT NULL AND
248           NOT l_process_list.EXISTS(l_po_header_id_tbl(i))) THEN
249         l_process_list(l_po_header_id_tbl(i)) := l_intf_header_id_tbl(i);
250       END IF;
251 
252       IF (l_process_list.COUNT >= PO_PDOI_PARAMS.g_request.batch_size) THEN
253         IF (PO_LOG.d_stmt) THEN
254           PO_LOG.stmt(d_module, d_position, '# of documents to process has ' ||
255                       'reached the limit. Wait for the next round');
256         END IF;
257 
258         -- exit the loop if the number of document to process exceeds
259         -- the specified limit
260         EXIT;
261       END IF;
262     END LOOP;
263 
264     d_position := 70;
265 
266     IF (l_process_list.COUNT > 0) THEN
267       -- assign round number for those in process list
268       FORALL i IN INDICES OF l_process_list
269         UPDATE po_headers_interface
270         SET    processing_round_num = PO_PDOI_PARAMS.g_current_round_num
271         WHERE  interface_header_id = l_process_list(i);
272 
273       IF (PO_LOG.d_stmt) THEN
274         PO_LOG.stmt(d_module, d_position, 'updated ' || SQL%ROWCOUNT ||
275                     'rows with current round number ');
276       END IF;
277 
278     ELSE
279 
280       IF (PO_LOG.d_stmt) THEN
281         PO_LOG.stmt(d_module, d_position, '** No more doc to process ***');
282       END IF;
283 
284       x_all_headers_processed := FND_API.G_TRUE;
285     END IF;
286 
287   END IF;
288 
289   IF (PO_LOG.d_proc) THEN
290     PO_LOG.proc_end (d_module);
291   END IF;
292 
293 EXCEPTION
294 WHEN OTHERS THEN
295   PO_MESSAGE_S.add_exc_msg
296   ( p_pkg_name => d_pkg_name,
297     p_procedure_name => d_api_name || '.' || d_position
298   );
299   RAISE;
300 END assign_round_num;
301 
302 
303 
304 -----------------------------------------------------------------------
305 --Start of Comments
306 --Name: assign_draft_id
307 --Function:
308 --  Stamp header interface records with draft ids. If the document the
309 --  interface record tries to process already has a draft version, reuse
310 --  the draft; otherwise, create a new draft
311 --Parameters:
312 --IN:
313 --IN OUT:
314 --OUT:
315 --End of Comments
316 ------------------------------------------------------------------------
317 PROCEDURE assign_draft_id IS
318 
319 d_api_name CONSTANT VARCHAR2(30) := 'assign_draft_id';
320 d_module CONSTANT VARCHAR2(255) := d_pkg_name || d_api_name || '.';
321 d_position NUMBER;
322 
323 l_draft_id_tbl         PO_TBL_NUMBER := PO_TBL_NUMBER();
324 l_reject_list          PO_TBL_NUMBER := PO_TBL_NUMBER();
325 
326 l_new_dft_idx_tbl      PO_PDOI_UTL.pls_integer_tbl_type :=
327                          PO_PDOI_UTL.pls_integer_tbl_type();
328 l_existing_dft_idx_tbl PO_PDOI_UTL.pls_integer_tbl_type :=
329                          PO_PDOI_UTL.pls_integer_tbl_type();
330 
331 l_intf_header_id_tbl   PO_TBL_NUMBER;
332 l_po_header_id_tbl     PO_TBL_NUMBER;
333 l_action_tbl           PO_TBL_VARCHAR30;
334 l_revision_num_tbl     PO_TBL_NUMBER;
335 
336 l_tmp_draft_id         PO_DRAFTS.draft_id%TYPE;
337 l_tmp_draft_status     PO_DRAFTS.status%TYPE;
338 l_tmp_draft_owner_role PO_DRAFTS.owner_role%TYPE;
339 l_new_draft_needed     VARCHAR2(1);
340 l_return_status        VARCHAR2(1);
341 
342 l_status      PO_DRAFTS.status%TYPE := PO_DRAFTS_PVT.g_status_PDOI_PROCESSING;
343 
344 l_locking_allowed VARCHAR2(1);
345 l_message VARCHAR2(30);
346 
347 l_intf_hdr_id          NUMBER; -- bug5129752
348 l_temp                 NUMBER;
349 BEGIN
350   d_position := 0;
351 
352   IF (PO_LOG.d_proc) THEN
353     PO_LOG.proc_begin (d_module);
354   END IF;
355 
356   --SQL What: get all records that will be processed in current round. It also
357   --          locks the po_Headers of documents that are being updated
358   --SQL Why:  For each of this record, we need to find out whether we can
359   --          reuse an existing draft or have to create a new draft
360   SELECT PHI.interface_header_id,
361          PHI.po_header_id,
362          PHI.action,
363          NVL(PH.revision_num, 0)
364   BULK COLLECT
365   INTO   l_intf_header_id_tbl,
366          l_po_header_id_tbl,
367          l_action_tbl,
368          l_revision_num_tbl
369   FROM   po_headers_interface PHI,
370          po_headers_all PH
371   WHERE  PHI.processing_id = PO_PDOI_PARAMS.g_processing_id
372   AND    PHI.processing_round_num = PO_PDOI_PARAMS.g_current_round_num
373   AND    PHI.po_header_id = PH.po_header_id(+);
374   --For Bug: 11794764.Refer bug for reference.
375   --FOR UPDATE OF PH.po_header_id;
376 
377   FOR i IN 1 .. l_po_header_id_tbl.count LOOP
378      ---BEGIN BUG: 13588901 : Adding the no data found exception handler code
379    BEGIN
380       SELECT PO_HEADER_ID
381       INTO   l_temp
382       FROM   po_headers_all
383       WHERE  po_header_id = l_po_header_id_tbl(i)
384       FOR UPDATE OF po_header_id;
385 
386 
387    EXCEPTION
388    WHEN NO_DATA_FOUND THEN
389    NULL;
390    END;
391    ---END BUG : 13588901
392    END LOOP;
393 
394   d_position := 10;
395 
396   -- initialize structure that stores additional information for each
397   -- interface header record
398 
399   init_doc_info_tbl
400   ( p_intf_header_id_tbl => l_intf_header_id_tbl
401   );
402 
403   -- allocate space to store draft ids
404   l_draft_id_tbl.extend(l_intf_header_id_tbl.COUNT);
405 
406   FOR i IN 1..l_intf_header_id_tbl.COUNT LOOP
407     IF (l_action_tbl(i) = PO_PDOI_CONSTANTS.g_action_UPDATE) THEN
408       d_position := 20;
409 
410       -- If we are updating a document, a draft for the document may or may
411       -- not exist. if the draft exists, reuse it; if not, create a new
412       -- draft
413 
414       PO_DRAFTS_PVT.find_draft
415       ( p_po_header_id     => l_po_header_id_tbl(i),
416         x_draft_id         => l_tmp_draft_id,
417         x_draft_status     => l_tmp_draft_status,
418         x_draft_owner_role => l_tmp_draft_owner_role
419       );
420 
421       d_position := 30;
422 
423       IF (l_tmp_draft_id IS NULL) THEN
424         IF (PO_LOG.d_stmt) THEN
425           PO_LOG.stmt(d_module, d_position, 'draft id not found');
426         END IF;
427 
428         d_position := 40;
429 
430         -- need to create a new draft
431         l_new_dft_idx_tbl.extend;
432         l_new_dft_idx_tbl(l_new_dft_idx_tbl.COUNT) := i;
433         l_draft_id_tbl(i) := PO_DRAFTS_PVT.draft_id_nextval;
434 
435       ELSE
436         IF (l_tmp_draft_status IN (PO_DRAFTS_PVT.g_status_PDOI_PROCESSING,
437                                    PO_DRAFTS_PVT.g_status_PDOI_ERROR)) THEN
438 
439           d_position := 50;
440 
441           IF (PO_LOG.d_stmt) THEN
442             PO_LOG.stmt(d_module, d_position, 'existing draft is processed ' ||
443                         'by PDOI. check whether the previous PDOI is still ' ||
444                         'working on it');
445           END IF;
446 
447           -- check whether the existing draft is still valid, or it is just
448           -- data corruption caused by incomplete execution of the previous
449           -- PDOI run.
450           check_new_draft_needed
451           ( p_draft_id => l_tmp_draft_id,
452             p_status   => l_tmp_draft_status,
453             x_new_draft_needed => l_new_draft_needed
454           );
455 
456           d_position := 60;
457 
458 
459           IF (l_new_draft_needed = FND_API.G_TRUE) THEN
460             d_position := 70;
461 
462             IF (PO_LOG.d_stmt) THEN
463               PO_LOG.stmt(d_module, d_position, 'old draft can be removed. ' ||
464                           'Creating a new one');
465             END IF;
466 
467             PO_DRAFTS_PVT.remove_draft_changes
468             ( p_draft_id => l_tmp_draft_id,
469               p_exclude_ctrl_tbl => FND_API.G_FALSE,
470               x_return_status => l_return_status
471             );
472 
473             -- new draft to be created
474             l_new_dft_idx_tbl.EXTEND;
475             l_new_dft_idx_tbl(l_new_dft_idx_tbl.COUNT) := i;
476             l_draft_id_tbl(i) := PO_DRAFTS_PVT.draft_id_nextval;
477           ELSE
478             d_position := 80;
479 
480             IF (PO_LOG.d_stmt) THEN
481               PO_LOG.stmt(d_module, d_position, 'old draft is still being ' ||
482                           'worked on. Fail the current intf record');
483             END IF;
484 
485             PO_PDOI_ERR_UTL.add_fatal_error
486             ( p_interface_header_id => l_intf_header_id_tbl(i),
487               p_error_message_name => 'PO_LOCKED_OR_INVALID_STS',
488               p_table_name => 'PO_HEADERS_INTERFACE',
489               p_column_name => 'DRAFT_ID',
490               p_column_value => l_tmp_draft_id
491             );
492 
493             -- the existing draft is still running. Need to reject the interface
494             -- record for the current run as it cannot be processed
495             l_reject_list.EXTEND;
496             l_reject_list(l_reject_list.COUNT) := l_intf_header_id_tbl(i);
497           END IF;
498 
499         ELSE
500 
501           d_position := 90;
502 
503           IF (PO_LOG.d_stmt) THEN
504             PO_LOG.stmt(d_module, d_position, 'draft with id ' ||
505 						            l_tmp_draft_id || ' can be reused.');
506           END IF;
507 
508           -- other draft status -- reuse the draft
509           l_draft_id_tbl(i) := l_tmp_draft_id;
510           l_existing_dft_idx_tbl.extend;
511           l_existing_dft_idx_tbl(l_existing_dft_idx_tbl.COUNT) := i;
512         END IF;
513       END IF;
514 
515     ELSE
516       d_position := 100;
517 
518       -- actions that cause new documents to be created
519       l_new_dft_idx_tbl.extend;
520       l_new_dft_idx_tbl(l_new_dft_idx_tbl.COUNT) := i;
521       l_draft_id_tbl(i) := PO_DRAFTS_PVT.draft_id_nextval;
522     END IF;
523   END LOOP;
524 
525   d_position := 110;
526 
527   PO_PDOI_UTL.reject_headers_intf
528   ( p_id_param_type => PO_PDOI_CONSTANTS.g_INTERFACE_HEADER_ID,
529     p_id_tbl        => l_reject_list,
530     p_cascade       => FND_API.G_TRUE
531   );
532 
533   d_position := 120;
534 
535   -- stamp draft_id value to interface table
536   FORALL i IN 1..l_intf_header_id_tbl.COUNT
537     UPDATE po_headers_interface
538     SET    draft_id = l_draft_id_tbl(i)
539     WHERE  interface_header_id = l_intf_header_id_tbl(i)
540     AND    processing_id = PO_PDOI_PARAMS.g_processing_id;
541 
542   d_position := 130;
543 
544   -- Since DB 10g (bug4340345) has probems using VALUES OF against EMPTY
545   -- COLLECTION, Check the collection and call FORALL only if it's not empty
546 
547   IF (l_new_dft_idx_tbl.COUNT > 0) THEN
548     d_position := 140;
549     -- Create new drafts
550     FORALL i IN VALUES OF l_new_dft_idx_tbl
551       INSERT INTO po_drafts
552       ( draft_id,
553         document_id,
554         revision_num,
555         owner_user_id,
556         owner_role,
557         status,
558         last_update_date,
559         last_updated_by,
560         last_update_login,
561         creation_date,
562         created_by,
563         request_id
564       )
565       VALUES
566       ( l_draft_id_tbl(i),
567         l_po_header_id_tbl(i),
568         l_revision_num_tbl(i),
569         FND_GLOBAL.user_id,
570         PO_PDOI_PARAMS.g_request.role,
571         l_status,
572         SYSDATE,
573         FND_GLOBAL.user_id,
574         FND_GLOBAL.login_id,
575         SYSDATE,
576         FND_GLOBAL.user_id,
577         FND_GLOBAL.conc_request_id
578       );
579 
580   END IF;
581 
582   -- bug5129752
583   -- Update new draft flag
584   FOR i IN 1..l_new_dft_idx_tbl.COUNT LOOP
585     -- get the interface header id that creates the new draft, and set
586     -- the new draft flag
587     l_intf_hdr_id := l_intf_header_id_tbl ( l_new_dft_idx_tbl(i) );
588     PO_PDOI_PARAMS.g_docs_info(l_intf_hdr_id).new_draft := FND_API.G_TRUE;
589 
590   END LOOP;
591 
592   d_position := 150;
593 
594   IF (PO_LOG.d_stmt) THEN
595     PO_LOG.stmt(d_module, d_position,
596                 'Number of existing drafts: ' || l_existing_dft_idx_tbl.COUNT);
597   END IF;
598 
599   -- Since DB 10g has probems using VALUES OF against EMPTYCOLLECTION,
600   -- Check the collection and call FORALL only if it's not empty
601 
602   IF (l_existing_dft_idx_tbl.COUNT > 0) THEN
603     d_position := 160;
604     -- If we are updating an existing draft, we need to temporarily set the
605     -- status to PDOI_PROCESSING
606     FORALL i IN VALUES OF l_existing_dft_idx_tbl
607       UPDATE po_drafts
608       SET    status = l_status,
609              request_id = FND_GLOBAL.conc_request_id,
610              last_update_date = SYSDATE,
611              last_updated_by = FND_GLOBAL.user_id
612       WHERE  draft_id = l_draft_id_tbl(i);
613   END IF;
614 
615   IF (PO_LOG.d_proc) THEN
616     PO_LOG.proc_end (d_module);
617   END IF;
618 
619 EXCEPTION
620 WHEN OTHERS THEN
621   PO_MESSAGE_S.add_exc_msg
622   ( p_pkg_name => d_pkg_name,
623     p_procedure_name => d_api_name || '.' || d_position
624   );
625   RAISE;
626 END assign_draft_id;
627 
628 -----------------------------------------------------------------------
629 --Start of Comments
630 --Name: expire_lines_by_catalog_name
631 --Function:
632 --  Expire all the lines that match the catalog name specified in the parameter.
633 --  This involves bringing the lines to draft table.
634 --Parameters:
635 --IN:
636 --IN OUT:
637 --OUT:
638 --End of Comments
639 ------------------------------------------------------------------------
640 PROCEDURE expire_lines_by_catalog_name IS
641 
642 d_api_name CONSTANT VARCHAR2(30) := 'expire_lines_by_catalog_name';
643 d_module CONSTANT VARCHAR2(255) := d_pkg_name || d_api_name || '.';
644 d_position NUMBER;
645 
646 l_draft_id_tbl PO_TBL_NUMBER;
647 l_line_id_tbl PO_TBL_NUMBER;
648 l_delete_flag_tbl PO_TBL_VARCHAR1 := PO_TBL_VARCHAR1();
649 
650 l_record_exist_tbl PO_TBL_VARCHAR1;
651 BEGIN
652   d_position := 0;
653 
654   IF (PO_LOG.d_proc) THEN
655     PO_LOG.proc_begin (d_module);
656   END IF;
657 
658   --SQL What: Get all the existing lines that match the category name given
659   --          Make sure that the lines are not cancelled, closed or expired
660   --SQL Why: All those lines need to be expired.
661   SELECT PHI.draft_id,
662          POL.po_line_id
663   BULK COLLECT
664   INTO   l_draft_id_tbl,
665          l_line_id_tbl
666   FROM   po_headers_interface PHI,
667          po_lines_all POL
668   WHERE  PHI.processing_id = PO_PDOI_PARAMS.g_processing_id
669   AND    PHI.processing_round_num = PO_PDOI_PARAMS.g_current_round_num
670   AND    PHI.po_header_id = POL.po_header_id
671   AND    POL.catalog_name = PO_PDOI_PARAMS.g_request.catalog_to_expire
672   AND    NVL(POL.cancel_flag, 'N') = 'N'
673   AND    NVL(POL.closed_code, 'OPEN') <> 'FINALLY CLOSED'
674   AND    NVL(POL.expiration_date, SYSDATE+1) > SYSDATE;
675 
676   IF (PO_LOG.d_stmt) THEN
677     PO_LOG.stmt(d_module, d_position, 'Number of lines to expire',
678                 l_line_id_tbl.COUNT);
679   END IF;
680 
681   IF (l_line_id_tbl.COUNT > 0) THEN
682     d_position := 10;
683 
684     l_delete_flag_tbl.EXTEND(l_line_id_tbl.COUNT);
685 
686     -- Bring all lines with matching catalog name to draft table
687     PO_LINES_DRAFT_PKG.sync_draft_from_txn
688     ( p_po_line_id_tbl => l_line_id_tbl,
689       p_draft_id_tbl => l_draft_id_tbl,
690       p_delete_flag_tbl => l_delete_flag_tbl,
691       x_record_already_exist_tbl => l_record_exist_tbl
692     );
693 
694     d_position := 20;
695 
696     -- set expiration date of the lines
697     FORALL i IN 1..l_line_id_tbl.COUNT
698     UPDATE po_lines_draft_all
699     SET    expiration_date = TRUNC(SYSDATE-1)
700     WHERE  po_line_id = l_line_id_tbl(i)
701     AND    draft_id = l_draft_id_tbl(i);
702 
703   END IF;
704 
705   IF (PO_LOG.d_proc) THEN
706     PO_LOG.proc_end (d_module);
707   END IF;
708 
709 EXCEPTION
710 WHEN OTHERS THEN
711   PO_MESSAGE_S.add_exc_msg
712   ( p_pkg_name => d_pkg_name,
713     p_procedure_name => d_api_name || '.' || d_position
714   );
715   RAISE;
716 END expire_lines_by_catalog_name;
717 
718 -----------------------------------------------------------------------
719 --Start of Comments
720 --Name: init_doc_info_tbl
721 --Function:
722 --  initialize a structure that holds extra header interface record information
723 --  such has number of processed lines, whether there are lines to notify, etc.
724 --Parameters:
725 --IN:
726 --p_intf_header_id_tbl
727 --  list of interface header ids
728 --IN OUT:
729 --OUT:
730 --End of Comments
731 ------------------------------------------------------------------------
732 PROCEDURE init_doc_info_tbl
733 ( p_intf_header_id_tbl PO_TBL_NUMBER
734 ) IS
735 
736 d_api_name CONSTANT VARCHAR2(30) := 'init_doc_info_tbl';
737 d_module CONSTANT VARCHAR2(255) := d_pkg_name || d_api_name || '.';
738 d_position NUMBER;
739 
740 l_id PO_HEADERS_INTERFACE.interface_header_id%TYPE;
741 
742 
743 -- bug5215871 START
744 l_reject_count NUMBER;
745 -- bug5215871 END
746 
747 BEGIN
748   d_position := 0;
749 
750   IF (PO_LOG.d_proc) THEN
751     PO_LOG.proc_begin (d_module);
752   END IF;
753 
754   PO_PDOI_PARAMS.g_docs_info.DELETE;
755 
756   d_position := 10;
757 
758   FOR i IN 1..p_intf_header_id_tbl.COUNT LOOP
759     l_id := p_intf_header_id_tbl(i);
760 
761     -- bug5215871
762     -- Count the number of the lines that are already rejected before
763     -- PDOI processes them. We need to include them processed and errored
764     -- out.
765     SELECT count(*)
766     INTO   l_reject_count
767     FROM   po_lines_interface PLI
768     WHERE  PLI.interface_header_id = p_intf_header_id_tbl(i)
769     AND    PLI.process_code = PO_PDOI_CONSTANTS.g_PROCESS_CODE_REJECTED;
770 
771     PO_PDOI_PARAMS.g_docs_info(l_id).number_of_processed_lines :=
772       l_reject_count;
773     PO_PDOI_PARAMS.g_docs_info(l_id).number_of_errored_lines :=
774       l_reject_count;
775     PO_PDOI_PARAMS.g_docs_info(l_id).number_of_valid_lines := 0;
776     PO_PDOI_PARAMS.g_docs_info(l_id).err_tolerance_exceeded := FND_API.G_FALSE;
777     PO_PDOI_PARAMS.g_docs_info(l_id).has_errors := FND_API.G_FALSE;
778     PO_PDOI_PARAMS.g_docs_info(l_id).has_lines_to_notify := FND_API.G_FALSE;
779     PO_PDOI_PARAMS.g_docs_info(l_id).new_draft := FND_API.G_FALSE; -- bug5129752
780   END LOOP;
781 
782   IF (PO_LOG.d_proc) THEN
783     PO_LOG.proc_end (d_module);
784   END IF;
785 
786 EXCEPTION
787 WHEN OTHERS THEN
788   PO_MESSAGE_S.add_exc_msg
789   ( p_pkg_name => d_pkg_name,
790     p_procedure_name => d_api_name || '.' || d_position
791   );
792   RAISE;
793 END init_doc_info_tbl;
794 
795 
796 -----------------------------------------------------------------------
797 --Start of Comments
798 --Name: check_new_draft_needed
799 --Function:
800 --  Check whether the previous draft is still being processed by PDOI.
801 --  If not, then return a flag telling the caller to create a new draft,
802 --  as the existing one is no longer being processed.
803 --Parameters:
804 --IN:
805 --p_draft_id
806 --  draft unique identifier
807 --p_status
808 --  status of the draft. (status will be PDOI related. Possible values:
809 --  PDOI_PROCESSING, PDOI_ERROR
810 --IN OUT:
811 --OUT:
812 --x_new_draft_needed
813 --  FND_API.G_TRUE if a new draft needs to be created
814 --  FND_API.G_FALSE if the old draft is still effective
815 --End of Comments
816 ------------------------------------------------------------------------
817 PROCEDURE check_new_draft_needed
818 ( p_draft_id IN NUMBER,
819   p_status   IN VARCHAR2,
820   x_new_draft_needed OUT NOCOPY VARCHAR2
821 ) IS
822 
823 d_api_name CONSTANT VARCHAR2(30) := 'check_new_draft_needed';
824 d_module CONSTANT VARCHAR2(255) := d_pkg_name || d_api_name || '.';
825 d_position NUMBER;
826 
827 l_dft_request_id PO_DRAFTS.request_id%TYPE;
828 l_cur_request_id NUMBER;
829 
830 
831 BEGIN
832   d_position := 0;
833 
834   IF (PO_LOG.d_proc) THEN
835     PO_LOG.proc_begin (d_module, 'p_draft_id', p_draft_id);
836     PO_LOG.proc_begin (d_module, 'p_status', p_status);
837   END IF;
838 
839   x_new_draft_needed := FND_API.G_FALSE;
840 
841   IF (p_status = PO_DRAFTS_PVT.g_status_PDOI_ERROR) THEN
842     d_position := 10;
843 
844     x_new_draft_needed := FND_API.G_TRUE;
845 
846   ELSIF (p_status = PO_DRAFTS_PVT.g_status_PDOI_PROCESSING) THEN
847     d_position := 20;
848 
849     l_cur_request_id := FND_GLOBAL.conc_request_id;
850 
851     PO_DRAFTS_PVT.get_request_id
852     ( p_draft_id => p_draft_id,
853       x_request_id => l_dft_request_id
854     );
855 
856     x_new_draft_needed := PO_PDOI_UTL.is_old_request_complete
857                           ( p_old_request_id => l_dft_request_id
858                           );
859 
860   END IF;  -- if status = p_status = PO_DRAFTS_PVT.g_status_PDOI_ERROR
861 
862   IF (PO_LOG.d_proc) THEN
863     PO_LOG.proc_end (d_module, 'x_new_draft_needed', x_new_draft_needed);
864   END IF;
865 
866 EXCEPTION
867 WHEN OTHERS THEN
868   PO_MESSAGE_S.add_exc_msg
869   ( p_pkg_name => d_pkg_name,
870     p_procedure_name => d_api_name || '.' || d_position
871   );
872   RAISE;
873 END check_new_draft_needed;
874 
875 
876 
877 
878 END PO_PDOI_HEADER_GROUPING_PVT;