DBA Data[Home] [Help]

PACKAGE BODY: APPS.PO_R12_CAT_UPG_VAL_PVT

Source


1 PACKAGE BODY PO_R12_CAT_UPG_VAL_PVT AS
2 /* $Header: PO_R12_CAT_UPG_VAL_PVT.plb 120.15 2006/12/19 11:09:07 bao noship $ */
3 
4 g_pkg_name CONSTANT VARCHAR2(30) := 'PO_R12_CAT_UPG_VAL_PVT';
5 g_module_prefix CONSTANT VARCHAR2(100) := 'po.plsql.' || g_pkg_name || '.';
6 
7 g_debug BOOLEAN := PO_R12_CAT_UPG_DEBUG.is_logging_enabled;
8 g_err_num NUMBER := PO_R12_CAT_UPG_PVT.g_application_err_num;
9 
10 -- Value of PO_LINE_ID and REQ_TEMPLATE_LINE_NUM if they are not
11 -- required in Attr/TLP tables.
12 g_NOT_REQUIRED_ID CONSTANT NUMBER := PO_R12_CAT_UPG_PVT.g_NOT_REQUIRED_ID;
13 -- Value of REQ_TEMPLATE_NAME if it is not required in Attr/TLP tables.
14 g_NOT_REQUIRED_REQ_TEMPLATE CONSTANT VARCHAR2(30) := PO_R12_CAT_UPG_PVT.g_NOT_REQUIRED_REQ_TEMPLATE ;
15 
16 -- If the value of a column (vendor_id, site_id, etc.) in the interface table
17 -- is -2, then treat it as NULL for validation routines.
18 g_NULL_COLUMN_VALUE NUMBER := -2;
19 
20 --------------------------------------------------------------------------------
21 --Start of Comments
22 --Name: validate_org_ids
23 --Pre-reqs:
24 --  The iP catalog data is populated in input pl/sql tables.
25 --Modifies:
26 --  a) Interface tables.
27 --  b) FND_MSG_PUB on unhandled exceptions.
28 --Locks:
29 --  None.
30 --Function:
31 --  Validates org_id. It can not be NULL or -2.
32 --  (For Operating Unit (org_id), iProc defined a values of -2 for 'All Orgs'.
33 --   This value will now fail validation in migration program.)
34 --  This procedure also validates the org_id against the HR_OPERATING_UNITS
35 --  table. The org_id must exist in this table and must not be end-dated.
36 --
37 --Parameters:
38 --IN:
39 --p_batch_id
40 --  Key used to identify all records to be processed in the interface tables.
41 --p_batch_size
42 --  The size of the batch that should be processed in each commit cycle.
43 --p_validate_only_mode
44 --  If set to Y, the cascading of errors to lower levels will not happen.
45 --OUT:
46 --  None
47 --End of Comments
48 --------------------------------------------------------------------------------
49 PROCEDURE validate_org_ids
50 (
51   p_batch_id           IN NUMBER
52 , p_batch_size         IN NUMBER
53 , p_validate_only_mode IN VARCHAR2
54 )
55 IS
56   l_api_name      CONSTANT VARCHAR2(30) := 'validate_org_ids';
57   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
58   l_progress      VARCHAR2(3) := '000';
59 
60   l_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
61   l_org_ids              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
62 
63   l_err_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
64   l_err_org_ids              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
65   i NUMBER;
66 
67   l_ou_name HR_ALL_ORGANIZATION_UNITS_TL.name%TYPE;
68 
69   -- iProc defined value for org_id if item is valid for All OU's.
70   g_OU_REQD CONSTANT NUMBER := -2;
71 
72   CURSOR load_org_ids_csr(p_batch_id NUMBER) IS
73     SELECT interface_header_id
74          , org_id
75     FROM PO_HEADERS_INTERFACE
76     WHERE batch_id = p_batch_id
77       AND process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_NEW;
78 
79 BEGIN
80   l_progress := '010';
81   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
82 
83   OPEN load_org_ids_csr(p_batch_id);
84 
85   l_progress := '020';
86   LOOP
87     BEGIN -- block to handle SNAPSHOT_TOO_OLD exception
88 
89       l_progress := '030';
90       FETCH load_org_ids_csr
91       BULK COLLECT INTO l_interface_header_ids
92                       , l_org_ids
93       LIMIT p_batch_size;
94 
95       l_progress := '040';
96 
97       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_interface_header_ids.COUNT='||l_interface_header_ids.COUNT); END IF;
98 
99       IF (l_interface_header_ids.COUNT > 0) THEN
100         IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_interface_header_ids(1)='||l_interface_header_ids(1)); END IF;
101         IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_org_ids(1)='||l_org_ids(1)); END IF;
102       END IF;
103 
104       l_progress := '050';
105       EXIT WHEN l_interface_header_ids.COUNT = 0;
106 
107       -- ECO bug 5584556: Add new messages
108       l_progress := '060';
109       -- SQL What: Bulk validate org_id -- it should not be NULL or -2.
110       --           Also validates the org_id against HR_OPERATING_UNITS.
111       --           Gets the errored rows into GT table.
112       -- SQL Why : It will be used to mark the record in interface tables as rejected.
113       -- SQL Join: interface_header_id
114       FORALL i IN 1 .. l_interface_header_ids.COUNT
115         UPDATE PO_HEADERS_INTERFACE
116            SET process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
117          WHERE interface_header_id = l_interface_header_ids(i)
118            AND (l_org_ids(i) IS NULL
119                 OR l_org_ids(i) = g_OU_REQD -- where g_OU_REQD is -2 (iProc defined this value)
120                 OR NOT EXISTS
121                   (SELECT 'ORG_ID exists'
122                    FROM HR_ALL_ORGANIZATION_UNITS HAOU
123                    WHERE HAOU.organization_id = l_org_ids(i)
124                    ))
125         RETURNING interface_header_id, org_id
126         BULK COLLECT INTO l_err_interface_header_ids, l_err_org_ids;
127 
128       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
129 
130       l_progress := '070';
131       -- Mark the error records
132       FOR i IN 1 .. l_err_interface_header_ids.COUNT
133       LOOP
134         IF (l_err_org_ids(i) = g_OU_REQD) THEN
135           -- ICX_CAT_ALL_BUYERS_DEPRECATED:
136           -- "Provide an Operating Unit. 'All Buyers' has been deprecated."
137           PO_R12_CAT_UPG_UTL.add_fatal_error(
138                   p_interface_header_id => l_err_interface_header_ids(i),
139                   --p_error_message_name  => 'PO_R12_CAT_UPG_OU_REQD',
140                   p_error_message_name  => 'ICX_CAT_ALL_BUYERS_DEPRECATED',
141                   p_table_name          => 'PO_HEADERS_INTERFACE',
142                   p_column_name         => 'ORG_ID',
143                   p_column_value        => l_err_org_ids(i) -- debug purposes only, not used in the msg
144                   );
145         ELSE -- if org_id is NULL or if ID does not exist in table.
146           -- ICX_CAT_OU_REQD:
147           -- "Operating unit is missing."
148           PO_R12_CAT_UPG_UTL.add_fatal_error(
149                   p_interface_header_id => l_err_interface_header_ids(i),
150                   p_error_message_name  => 'ICX_CAT_OU_REQD',
151                   p_table_name          => 'PO_HEADERS_INTERFACE',
152                   p_column_name         => 'ORG_ID',
153                   p_column_value        => l_err_org_ids(i)
154                   );
155         END IF;
156 
157         l_progress := '080';
158         -- Cascade errors down to lower levels
159         -- Skip cascading of errors in Validate Only mode (iP Requirement - all errors should be reported)
160         IF (p_validate_only_mode <> FND_API.G_TRUE) THEN
161           PO_R12_CAT_UPG_UTL.reject_headers_intf('INTERFACE_HEADER_ID', l_err_interface_header_ids, 'Y');
162         END IF;
163       END LOOP;
164       -- ECO bug 5584556: End
165 
166       l_progress := '090';
167       -- SQL What: Bulk validate org_id.
168       --           Validate the org_id against HR_OPERATING_UNITS.
169       --           Gets the errored rows into GT table.
170       -- SQL Why : It will be used to mark the record in interface tables as rejected.
171       -- SQL Join: interface_header_id
172       FORALL i IN 1 .. l_interface_header_ids.COUNT
173         UPDATE PO_HEADERS_INTERFACE
174            SET process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
175          WHERE interface_header_id = l_interface_header_ids(i)
176            -- ECO bug 5584556: Skip the validations covered above
177            AND l_org_ids(i) IS NOT NULL
178            AND l_org_ids(i) <> g_OU_REQD -- where g_OU_REQD is -2 (iProc defined this value)
179            AND EXISTS
180                    (SELECT 'ORG_ID exists'
181                     FROM HR_ALL_ORGANIZATION_UNITS HAOU
182                     WHERE HAOU.organization_id = l_org_ids(i)
183                    )
184            -- ECO bug 5584556: End
185            AND (
186                 NOT EXISTS
187                   (SELECT 'Valid Operating Unit ID'
188                    FROM HR_OPERATING_UNITS HROU
189                    WHERE HROU.organization_id = l_org_ids(i)
190                      -- Bug 5060582: Dont need the date checks
191                      --AND sysdate BETWEEN
192                      --        nvl(HROU.date_from, sysdate-1)
193                      --    AND nvl(HROU.date_to, sysdate+1)
194                    )
195                 -- ECO bug 5584556: Add new messages
196                 -- This check is done as part of UT'ing this ECO.
197                 -- We found a case where the PSP row does not exist for the org_id.
198                 -- The migration program would die for such cases. The following query
199                 -- is copied from init_sys_parameters() where it was failing.
200                 OR
201                 NOT EXISTS
202                 ( SELECT 'Valid OU references in FSP, PSP, SOB and RCV'
203                   FROM  FINANCIALS_SYSTEM_PARAMS_ALL FSPA,
204                         GL_SETS_OF_BOOKS             SOB,
205                         PO_SYSTEM_PARAMETERS_ALL     PSPA,
206                         RCV_PARAMETERS               RCV
207                   WHERE FSPA.set_of_books_id = SOB.set_of_books_id
208                     AND RCV.organization_id (+) = FSPA.inventory_organization_id
209                     AND PSPA.org_id = l_org_ids(i)
210                     AND FSPA.org_id = l_org_ids(i)
211                 )
212                 -- ECO bug 5584556: End
213                )
214         RETURNING interface_header_id, org_id
215         BULK COLLECT INTO l_err_interface_header_ids, l_err_org_ids;
216 
217       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
218 
219       l_progress := '100';
220       -- Mark the error records
221       FOR i IN 1 .. l_err_interface_header_ids.COUNT
222       LOOP
223         -- ECO bug 5584556: id-to-name conversion for new message
224         -- Get the Operating Unit name
225         BEGIN
226           SELECT name
227           INTO l_ou_name
228           FROM HR_ALL_ORGANIZATION_UNITS_TL HAOUTL
229           WHERE HAOUTL.organization_id = l_err_org_ids(i)
230             AND language = userenv('LANG');
231         EXCEPTION
232           WHEN OTHERS THEN
233             l_ou_name := to_char(l_err_org_ids(i));
234         END;
235         -- ECO bug 5584556: End
236 
237         -- ICX_CAT_INVALID_OU:
238         -- "Operating Unit (VALUE) is invalid or inactive."
239         PO_R12_CAT_UPG_UTL.add_fatal_error(
240                   p_interface_header_id => l_err_interface_header_ids(i),
241                   --p_error_message_name  => 'PO_R12_CAT_UPG_INVALID_OU',
242                   p_error_message_name  => 'ICX_CAT_INVALID_OU',
243                   p_table_name          => 'PO_HEADERS_INTERFACE',
244                   p_column_name         => 'ORG_ID',
245                   p_column_value        => l_ou_name, -- ECO bug 5584556
246                   p_token1_name         => 'VALUE',
247                   p_token1_value        => l_err_org_ids(i)
248                   );
249 
250         l_progress := '110';
251         -- Cascade errors down to lower levels
252         -- Skip cascading of errors in Validate Only mode (iP Requirement - all errors should be reported)
253         IF (p_validate_only_mode <> FND_API.G_TRUE) THEN
254           PO_R12_CAT_UPG_UTL.reject_headers_intf('INTERFACE_HEADER_ID', l_err_interface_header_ids, 'Y');
255         END IF;
256       END LOOP;
257 
258       l_progress := '120';
259       COMMIT;
260 
261       l_progress := '130';
262       IF (l_interface_header_ids.COUNT < p_batch_size) THEN
263         EXIT;
264       END IF;
265       l_progress := '140';
266     EXCEPTION
267       WHEN g_SNAPSHOT_TOO_OLD THEN
268         IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'EXCEPTION: SNAPSHOT_TOO_OLD. Now commiting and re-opening the load_org_ids_csr'); END IF;
269 
270         -- Commit and re-open the cursor
271         l_progress := '150';
272         COMMIT;
273 
274         l_progress := '160';
275         CLOSE load_org_ids_csr;
276 
277         l_progress := '170';
278         OPEN load_org_ids_csr(p_batch_id);
279         l_progress := '180';
280      END; -- block to handle SNAPSHOT_TOO_OLD exception
281   END LOOP; -- batch loop
282 
283   l_progress := '190';
284   IF (load_org_ids_csr%ISOPEN) THEN
285     CLOSE load_org_ids_csr;
286   END IF;
287 
288   l_progress := '200';
289   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
290 EXCEPTION
291   WHEN OTHERS THEN
292     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
293     IF (load_org_ids_csr%ISOPEN) THEN
294       CLOSE load_org_ids_csr;
295     END IF;
296     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
297 END validate_org_ids;
298 
299 --------------------------------------------------------------------------------
300 --Start of Comments
301 --Name: validate_expiration_date
302 --Pre-reqs:
303 --  The iP catalog data is populated in input pl/sql tables.
304 --Modifies:
305 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
306 --  b) FND_MSG_PUB on unhandled exceptions.
307 --Locks:
308 --  None.
309 --Function:
310 --  End date cannot be earlier than start date. This procedure validates this.
311 --Parameters:
312 --IN/OUT:
313 --p_headers_rec
314 --  A record of plsql tables containing a batch of headers. If this validation
315 --  fails, the 'has_errors' column is set to 'Y'.
316 --OUT:
317 --End of Comments
318 --------------------------------------------------------------------------------
319 PROCEDURE validate_expiration_date
320 (
321   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
322 )
323 IS
324   l_api_name      CONSTANT VARCHAR2(30) := 'validate_expiration_date';
325   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
326   l_progress      VARCHAR2(3) := '000';
327 
328   i NUMBER;
329 BEGIN
330   l_progress := '010';
331   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
332 
333   FOR i IN 1 .. p_headers_rec.expiration_date.COUNT
334   LOOP
335     l_progress := '020';
336     IF (--p_headers_rec.has_errors(i) = 'N' AND
337         p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create AND --Bug#5018883
338         p_headers_rec.effective_date(i) IS NOT NULL AND
339         p_headers_rec.expiration_date(i) IS NOT NULL AND
340         p_headers_rec.effective_date(i) > p_headers_rec.expiration_date(i)) THEN
341 
342       l_progress := '030';
343       p_headers_rec.has_errors(i) := 'Y';
344 
345       -- Add error message into INTERFACE_ERRORS table
346       -- PO_PDOI_INVALID_START_DATE:
347       -- "Effective Date (VALUE =VALUE) specified should be less than the end date specified."
348       PO_R12_CAT_UPG_UTL.add_fatal_error(
349             p_interface_header_id => p_headers_rec.interface_header_id(i),
350             p_error_message_name  => 'PO_PDOI_INVALID_START_DATE',
351             p_table_name          => 'PO_HEADERS_INTERFACE',
352             p_column_name         => 'EXPIRATION_DATE',
353             p_column_value        => p_headers_rec.expiration_date(i),
354             p_token1_name         => 'VALUE',
355             p_token1_value        => p_headers_rec.effective_date(i)
356             );
357     END IF;
358   END LOOP;
359 
360   l_progress := '040';
361   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
362 EXCEPTION
363   WHEN OTHERS THEN
364     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
365     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
366 END validate_expiration_date;
367 
368 --------------------------------------------------------------------------------
369 --Start of Comments
370 --Name: validate_buyer
371 --Pre-reqs:
372 --  The iP catalog data is populated in input pl/sql tables.
373 --Modifies:
374 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
375 --  b) FND_MSG_PUB on unhandled exceptions.
376 --Locks:
377 --  None.
378 --Function:
379 --  agent_id can not be null.
380 --Parameters:
381 --IN/OUT:
382 --p_headers_rec
383 --  A record of plsql tables containing a batch of headers. If this validation
384 --  fails, the 'has_errors' column is set to 'Y'.
385 --OUT:
386 --End of Comments
387 --------------------------------------------------------------------------------
388 PROCEDURE validate_buyer
389 (
390   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
391 )
392 IS
393   l_api_name      CONSTANT VARCHAR2(30) := 'validate_buyer';
394   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
395   l_progress      VARCHAR2(3) := '000';
396 
397   i NUMBER;
398 BEGIN
399   l_progress := '010';
400   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
401 
402   FOR i IN 1 .. p_headers_rec.agent_id.COUNT
403   LOOP
404     l_progress := '020';
405     IF (--p_headers_rec.has_errors(i) = 'N' AND
406         p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create AND --Bug#5018883
407         p_headers_rec.agent_id(i) IS NULL) THEN
408 
409       l_progress := '030';
410       p_headers_rec.has_errors(i) := 'Y';
411 
412       -- Add error message into INTERFACE_ERRORS table
413       -- ICX_CAT_BUYER_REQD:
414       -- "The system cannot obtain the default value for the buyer."
415       PO_R12_CAT_UPG_UTL.add_fatal_error(
416             p_interface_header_id => p_headers_rec.interface_header_id(i),
417             p_error_message_name  => 'ICX_CAT_BUYER_REQD', -- ECO bug 5584556: changed from ICX_CAT_NO_BUYER
418             p_table_name          => 'PO_HEADERS_INTERFACE',
419             p_column_name         => 'AGENT_ID',
420             p_column_value        => p_headers_rec.agent_id(i),
421             p_token1_name         => 'VALUE',
422             p_token1_value        => p_headers_rec.agent_id(i)
423             );
424     END IF;
425   END LOOP;
426 
427   l_progress := '040';
428   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
429 EXCEPTION
430   WHEN OTHERS THEN
431     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
432     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
433 END validate_buyer;
434 
435 --------------------------------------------------------------------------------
436 --Start of Comments
437 --Name: validate_currency_code
438 --Pre-reqs:
439 --  The iP catalog data is populated in input pl/sql tables.
440 --Modifies:
441 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
442 --  b) FND_MSG_PUB on unhandled exceptions.
443 --Locks:
444 --  None.
445 --Function:
446 --  Validates currency_code not null and against FND_CURRENCIES.
447 --Parameters:
448 --IN:
449 --p_key
450 --  Key used to access records in PO_SESSION_GT table.
451 --IN/OUT:
452 --p_headers_rec
453 --  A record of plsql tables containing a batch of headers. If this validation
454 --  fails, the 'has_errors' column is set to 'Y'.
455 --OUT:
456 --End of Comments
457 --------------------------------------------------------------------------------
458 PROCEDURE validate_currency_code
459 (
460   p_key         IN NUMBER,
461   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
462 )
463 IS
464   l_api_name      CONSTANT VARCHAR2(30) := 'validate_currency_code';
465   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
466   l_progress      VARCHAR2(3) := '000';
467 
468   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
469 
470   l_interface_header_ids   PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
471   l_indexes                PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
472   l_err_currency_code_list PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR15;
473 
474   l_index NUMBER;
475   i NUMBER;
476   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
477 BEGIN
478   l_progress := '010';
479   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
480 
481   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.currency_code.COUNT);
482 
483   IF (p_headers_rec.currency_code.COUNT > 0) THEN
484     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.currency_code(1)='||p_headers_rec.currency_code(1)); END IF;
485     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
486     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
487   END IF;
488 
489   -- ECO bug 5584556: Add new messages
490   FOR i IN 1 .. p_headers_rec.currency_code.COUNT
491   LOOP
492     IF ( (p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create) AND
493          (p_headers_rec.currency_code(i) IS NULL) ) THEN
494       p_headers_rec.has_errors(i) := 'Y';
495 
496       -- Add error message into INTERFACE_ERRORS table
497       -- ICX_CAT_CURRENCY_REQD:
498       -- "Currency code is missing."
499       PO_R12_CAT_UPG_UTL.add_fatal_error(
500               p_interface_header_id => l_interface_header_ids(i),
501               p_error_message_name  => 'ICX_CAT_CURRENCY_REQD',
502               p_table_name          => 'PO_HEADERS_INTERFACE',
503               p_column_name         => 'CURRENCY_CODE',
504               p_column_value        => p_headers_rec.currency_code(i)
505               );
506     END IF;
507   END LOOP;
508   -- ECO bug 5584556: End
509 
510   l_progress := '020';
511   -- SQL What: Bulk validate currency_code not null and against FND_CURRENCIES.
512   --           Get the errored rows into GT table.
513   -- SQL Why : It will be used to mark the record in plsql table as error.
514   -- SQL Join: currency_code
515   FORALL i IN 1 .. p_headers_rec.currency_code.COUNT
516     INSERT INTO PO_SESSION_GT(key,
517                               num1,
518                               num2,
519                               index_char1)
520     SELECT p_key
521          , l_subscript_array(i)
522          , p_headers_rec.interface_header_id(i)
523          , p_headers_rec.currency_code(i)
524     FROM DUAL
525     WHERE --p_headers_rec.has_errors(i) = 'N'
526     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
527     -- ECO bug 5584556: Start
528     -- The following validation check is already done above.
529     -- So adding these additional where-clauses to skip those cases.
530     AND p_headers_rec.currency_code(i) IS NOT NULL
531     -- ECO bug 5584556: End
532     AND NOT EXISTS(SELECT 1
533                    FROM FND_CURRENCIES CUR
534                    WHERE p_headers_rec.currency_code(i) = CUR.currency_code
535                      AND CUR.enabled_flag = 'Y'
536                      AND sysdate BETWEEN
537                                  nvl(CUR.start_date_active, sysdate-1)
538                              AND nvl(CUR.end_date_active, sysdate+1));
539 
540   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
541 
542   l_progress := '030';
543   -- SQL What: Transfer from session GT table to local arrays
544   -- SQL Why : It will be used to mark the error records.
545   -- SQL Join: key
546   DELETE FROM PO_SESSION_GT
547   WHERE  key = p_key
548   RETURNING num1, num2, index_char1
549   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_currency_code_list;
550 
551   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
552 
553   l_progress := '040';
554   -- Mark the error records
555   FOR i IN 1 .. l_indexes.COUNT
556   LOOP
557     l_index := l_indexes(i);
558     p_headers_rec.has_errors(l_index) := 'Y';
559 
560     -- Add error message into INTERFACE_ERRORS table
561     -- ICX_CAT_INVALID_CURRENCY:
562     -- "Currency code (VALUE) is inactive or invalid."
563     PO_R12_CAT_UPG_UTL.add_fatal_error(
564             p_interface_header_id => l_interface_header_ids(i),
565             --p_error_message_name  => 'PO_PDOI_INVALID_CURRENCY',
566             p_error_message_name  => 'ICX_CAT_INVALID_CURRENCY',
567             p_table_name          => 'PO_HEADERS_INTERFACE',
568             p_column_name         => 'CURRENCY_CODE',
569             p_column_value        => l_err_currency_code_list(i),
570             p_token1_name         => 'VALUE',
571             p_token1_value        => l_err_currency_code_list(i)
572             );
573   END LOOP;
574 
575   l_progress := '050';
576   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
577 EXCEPTION
578   WHEN OTHERS THEN
579     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
580     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
581 END validate_currency_code;
582 
583 --------------------------------------------------------------------------------
584 --Start of Comments
585 --Name: validate_vendor_info
586 --Pre-reqs:
587 --  The iP catalog data is populated in input pl/sql tables.
588 --Modifies:
589 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
590 --  b) FND_MSG_PUB on unhandled exceptions.
591 --Locks:
592 --  None.
593 --Function:
594 -- validate vendorId is Not Null
595 -- validate vendorSiteId is Not Null
596 -- validate vendor_id using po_suppliers_val_v
597 -- validate vendor_site_id using po_supplier_sites_val_v
598 -- validate vendor_contact_id using po_vendor_contacts
599 -- validate vendor site CCR if approval status is APPROVED.
600 --Parameters:
601 --IN:
602 --p_key
603 --  Key used to access records in PO_SESSION_GT table.
604 --IN/OUT:
605 --p_headers_rec
606 --  A record of plsql tables containing a batch of headers. If this validation
607 --  fails, the 'has_errors' column is set to 'Y'.
608 --OUT:
609 --End of Comments
610 --------------------------------------------------------------------------------
611 PROCEDURE validate_vendor_info
612 (
613   p_key         IN NUMBER,
614   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
615 )
616 IS
617   l_api_name      CONSTANT VARCHAR2(30) := 'validate_vendor_info';
618   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
619   l_progress      VARCHAR2(3) := '000';
620 
621   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
622 
623   l_interface_header_ids   PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
624   l_indexes                PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
625   l_vendor_id_list         PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
626   l_vendor_name_list       PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR240;
627   l_vendor_site_id_list    PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
628   l_vendor_site_code_list  PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR15;
629   l_vendor_contact_id_list PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
630 
631   l_return_status VARCHAR2(1);
632   l_msg_count     NUMBER;
633   l_msg_data      VARCHAR2(2000);
634   l_ccr_status    VARCHAR2(1);
635   l_error_code    NUMBER;
636 
637   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
638   l_index NUMBER;
639   i NUMBER;
640 
641   -- If the profile option 'Enable Transaction Code' is set to 'Yes',
642   -- then it is a Federal instance.
643   l_federal_instance VARCHAR2(1) :=
644                       NVL(FND_PROFILE.value('USSGL_OPTION'), 'N');
645   x_temp_val BOOLEAN;
646 BEGIN
647   l_progress := '010';
648   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
649 
650   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.vendor_id.COUNT);
651 
652   ----------------------------------------------------------------------------
653   -- Validate vendor_id
654   ----------------------------------------------------------------------------
655 
656   -- ECO bug 5584556: Add new messages
657   l_progress := '020';
658   -- SQL What: Bulk validate vendor_id. Check that the ID is not NULL and it exists
659   --           in PO_VENDORS table.
660   --           Insert the error rows into GT table.
661   -- SQL Why : It will be used to mark the record in plsql table as error.
662   -- SQL Join: vendor_id
663   FORALL i IN 1 .. p_headers_rec.vendor_id.COUNT
664     INSERT INTO PO_SESSION_GT(key,
665                               num1,
666                               num2,
667                               num3,
668                               char1)
669     SELECT p_key
670          , l_subscript_array(i)
671          , p_headers_rec.interface_header_id(i)
672          , p_headers_rec.vendor_id(i)
673          , p_headers_rec.vendor_name(i)
674     FROM DUAL
675     WHERE --p_headers_rec.has_errors(i) = 'N'
676     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
677     AND (p_headers_rec.vendor_id(i) IS NULL
678          OR p_headers_rec.vendor_id(i) = g_NULL_COLUMN_VALUE -- -2
679          OR NOT EXISTS(SELECT 1
680                        FROM PO_VENDORS PV
681                        WHERE p_headers_rec.vendor_id(i) = PV.vendor_id));
682 
683   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
684 
685   l_progress := '030';
686   -- SQL What: Transfer from session GT table to local arrays
687   -- SQL Why : It will be used to mark the error records.
688   -- SQL Join: key
689   DELETE FROM PO_SESSION_GT
690   WHERE  key = p_key
691   RETURNING num1, num2, num3, char1
692   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_vendor_id_list, l_vendor_name_list;
693 
694   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
695 
696   l_progress := '040';
697   -- Mark the error records
698   FOR i IN 1 .. l_indexes.COUNT
699   LOOP
700     l_index := l_indexes(i);
701     p_headers_rec.has_errors(l_index) := 'Y';
702 
703     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: vendor_id does not exist'||', vendor_id='||l_vendor_id_list(i)); END IF;
704 
705     -- Add error message into INTERFACE_ERRORS table
706     -- ICX_CAT_SUPPLIER_REQD:
707     -- "Supplier is missing."
708     PO_R12_CAT_UPG_UTL.add_fatal_error(
709             p_interface_header_id => l_interface_header_ids(i),
710             p_error_message_name  => 'ICX_CAT_SUPPLIER_REQD',
711             p_table_name          => 'PO_HEADERS_INTERFACE',
712             p_column_name         => 'VENDOR_ID',
713             p_column_value        => l_vendor_id_list(i)
714             );
715   END LOOP;
716   -- ECO bug 5584556: End
717 
718   l_progress := '050';
719   -- SQL What: Bulk validate vendor_id.
720   --           Insert the error rows into GT table.
721   -- SQL Why : It will be used to mark the record in plsql table as error.
722   -- SQL Join: vendor_id
723   FORALL i IN 1 .. p_headers_rec.vendor_id.COUNT
724     INSERT INTO PO_SESSION_GT(key,
725                               num1,
726                               num2,
727                               num3,
728                               char1)
729     SELECT p_key
730          , l_subscript_array(i)
731          , p_headers_rec.interface_header_id(i)
732          , p_headers_rec.vendor_id(i)
733          , p_headers_rec.vendor_name(i)
734     FROM DUAL
735     WHERE --p_headers_rec.has_errors(i) = 'N'
736     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
737     -- ECO bug 5584556: Start
738     -- The following 3 validation checks are already done above.
739     -- So adding these additional where-clauses to skip those cases.
740     AND p_headers_rec.vendor_id(i) IS NOT NULL
741     AND p_headers_rec.vendor_id(i) <> g_NULL_COLUMN_VALUE -- -2
742     AND EXISTS(SELECT 1
743                FROM PO_VENDORS PV
744                WHERE p_headers_rec.vendor_id(i) = PV.vendor_id)
745     -- ECO bug 5584556: End
746     AND NOT EXISTS(SELECT 1
747                    FROM PO_SUPPLIERS_VAL_V PSV
748                    WHERE p_headers_rec.vendor_id(i) = PSV.vendor_id);
749 
750   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
751 
752   l_progress := '060';
753   -- SQL What: Transfer from session GT table to local arrays
754   -- SQL Why : It will be used to mark the error records.
755   -- SQL Join: key
756   DELETE FROM PO_SESSION_GT
757   WHERE  key = p_key
758   RETURNING num1, num2, num3, char1
759   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_vendor_id_list, l_vendor_name_list;
760 
761   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
762 
763   l_progress := '070';
764   -- Mark the error records
765   FOR i IN 1 .. l_indexes.COUNT
766   LOOP
767     l_index := l_indexes(i);
768     p_headers_rec.has_errors(l_index) := 'Y';
769 
770     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: vendor_name='||l_vendor_name_list(i)||', vendor_id='||l_vendor_id_list(i)); END IF;
771 
772     -- Add error message into INTERFACE_ERRORS table
773     -- ICX_CAT_INVALID_SUPPLIER:
774     -- "Supplier (VALUE) is inactive or invalid."
775     PO_R12_CAT_UPG_UTL.add_fatal_error(
776             p_interface_header_id => l_interface_header_ids(i),
777             --p_error_message_name  => 'PO_PDOI_INVALID_VENDOR',
778             p_error_message_name  => 'ICX_CAT_INVALID_SUPPLIER',
779             p_table_name          => 'PO_HEADERS_INTERFACE',
780             p_column_name         => 'VENDOR_NAME',
781             p_column_value        => l_vendor_name_list(i),
782             p_token1_name         => 'VALUE',
783             p_token1_value        => l_vendor_id_list(i) -- debug only
784             );
785   END LOOP;
786 
787   ----------------------------------------------------------------------------
788   -- Validate vendor_site_id
789   ----------------------------------------------------------------------------
790 
791   -- ECO bug 5584556: Start: Add new messages
792   l_progress := '080';
793   -- SQL What: Bulk validate vendor_site_id. Check that it is not NULL or -2.
794   --           Also check that the ID exists in PO_VENDOR_SITES_ALL table.
795   --           Insert the error rows into GT table.
796   -- SQL Why : It will be used to mark the record in plsql table as error.
797   -- SQL Join: vendor_site_id
798   FORALL i IN 1 .. p_headers_rec.vendor_site_id.COUNT
799     INSERT INTO PO_SESSION_GT(key,
800                               num1,
801                               num2,
802                               num3,
803                               char1)
804     SELECT p_key
805          , l_subscript_array(i)
806          , p_headers_rec.interface_header_id(i)
807          , p_headers_rec.vendor_site_id(i)
808          , p_headers_rec.vendor_site_code(i)
809     FROM DUAL
810     WHERE --p_headers_rec.has_errors(i) = 'N'
811       p_headers_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_header_create, 'UPDATE')
812       AND
813       (
814         (
815           -- Handle null Supplier Sites for Create action only
816           p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create
817           AND (p_headers_rec.vendor_site_id(i) IS NULL
818                 OR p_headers_rec.vendor_site_id(i) = g_NULL_COLUMN_VALUE)
819         )
820         OR
821         (
822           -- Handle invalid Supplier Site id for Create/update action
823           p_headers_rec.vendor_site_id(i) IS NOT NULL
824           AND p_headers_rec.vendor_site_id(i) <> g_NULL_COLUMN_VALUE
825           AND NOT EXISTS( SELECT 1
826                          FROM PO_VENDOR_SITES_ALL PVSA
827                          WHERE p_headers_rec.vendor_site_id(i) = PVSA.vendor_site_id)
828         )
829       );
830 
831   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
832 
833   l_progress := '090';
834   -- SQL What: Transfer from session GT table to local arrays
835   -- SQL Why : It will be used to mark the error records.
836   -- SQL Join: key
837   DELETE FROM PO_SESSION_GT
838   WHERE  key = p_key
839   RETURNING num1, num2, num3, char1
840   BULK COLLECT INTO l_indexes, l_interface_header_ids,
841                     l_vendor_site_id_list, l_vendor_site_code_list;
842 
843   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
844 
845   l_progress := '100';
846   -- Mark the error records
847   FOR i IN 1 .. l_indexes.COUNT
848   LOOP
849     l_index := l_indexes(i);
850     p_headers_rec.has_errors(l_index) := 'Y';
851 
852     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: vendor_site_id='||l_vendor_site_id_list(i)); END IF;
853 
854     -- Add error message into INTERFACE_ERRORS table
855     -- ICX_CAT_SUPPLIER_SITE_REQD:
856     -- "Supplier site is missing."
857     PO_R12_CAT_UPG_UTL.add_fatal_error(
858             p_interface_header_id => l_interface_header_ids(i),
859             p_error_message_name  => 'ICX_CAT_SUPPLIER_SITE_REQD',
860             p_table_name          => 'PO_HEADERS_INTERFACE',
861             p_column_name         => 'VENDOR_SITE_ID',
862             p_column_value        => l_vendor_site_id_list(i)
863             );
864   END LOOP;
865   -- ECO bug 5584556: End
866 
867   l_progress := '110';
868   -- SQL What: Bulk validate vendor_site_id. Check that the site is not inactive.
869   --           Insert the error rows into GT table.
870   -- SQL Why : It will be used to mark the record in plsql table as error.
871   -- SQL Join: vendor_site_id
872   FORALL i IN 1 .. p_headers_rec.vendor_site_id.COUNT
873     INSERT INTO PO_SESSION_GT(key,
874                               num1,
875                               num2,
876                               num3,
877                               char1)
878     SELECT p_key
879          , l_subscript_array(i)
880          , p_headers_rec.interface_header_id(i)
881          , p_headers_rec.vendor_site_id(i)
882          , p_headers_rec.vendor_site_code(i)
883     FROM DUAL
884     WHERE --p_headers_rec.has_errors(i) = 'N'
885       p_headers_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_header_create, 'UPDATE')
886       -- ECO bug 5584556: Start
887       -- The following 3 validation checks are already done above.
888       -- So adding these additional where-clauses to skip those cases.
889       AND p_headers_rec.vendor_site_id(i) IS NOT NULL
890       AND p_headers_rec.vendor_site_id(i) <> g_NULL_COLUMN_VALUE
891       AND EXISTS(SELECT 1
892                  FROM PO_VENDOR_SITES_ALL PVSA
893                  WHERE p_headers_rec.vendor_site_id(i) = PVSA.vendor_site_id)
894       -- ECO bug 5584556: End
895       AND NOT EXISTS(SELECT 1
896                      FROM PO_SUPPLIER_SITES_VAL_V PSSV
897                      WHERE p_headers_rec.vendor_site_id(i) = PSSV.vendor_site_id);
898 
899   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
900 
901   l_progress := '120';
902   -- SQL What: Transfer from session GT table to local arrays
903   -- SQL Why : It will be used to mark the error records.
904   -- SQL Join: key
905   DELETE FROM PO_SESSION_GT
906   WHERE  key = p_key
907   RETURNING num1, num2, num3, char1
908   BULK COLLECT INTO l_indexes, l_interface_header_ids,
909                     l_vendor_site_id_list, l_vendor_site_code_list;
910 
911   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
912 
913   l_progress := '130';
914   -- Mark the error records
915   FOR i IN 1 .. l_indexes.COUNT
916   LOOP
917     l_index := l_indexes(i);
918     p_headers_rec.has_errors(l_index) := 'Y';
919 
920     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: vendor_site_code='||l_vendor_site_code_list(i)||', vendor_site_id='||l_vendor_site_id_list(i)); END IF;
921 
922     -- Add error message into INTERFACE_ERRORS table
923     -- ICX_CAT_INVALID_SUPPLIER_SITE:
924     -- "Supplier site (VALUE) is not an active and valid purchasing supplier site."
925     PO_R12_CAT_UPG_UTL.add_fatal_error(
926             p_interface_header_id => l_interface_header_ids(i),
927             --p_error_message_name  => 'PO_INVALID_VENDOR_SITE_ID',
928             p_error_message_name  => 'ICX_CAT_INVALID_SUPPLIER_SITE',
929             p_table_name          => 'PO_HEADERS_INTERFACE',
930             p_column_name         => 'VENDOR_SITE_ID',
931             p_column_value        => l_vendor_site_code_list(i),
932             p_token1_name         => 'VALUE',
933             p_token1_value        => l_vendor_site_code_list(i)
934             );
935   END LOOP;
936 
937   ----------------------------------------------------------------------------
938   -- Validate vendor_contact_id
939   ----------------------------------------------------------------------------
940 
941   l_progress := '140';
942   -- SQL What: Bulk validate vendor_contact_id.
943   --           Insert the error rows into GT table.
944   -- SQL Why : It will be used to mark the record in plsql table as error.
945   -- SQL Join: vendor_id
946   FORALL i IN 1 .. p_headers_rec.vendor_contact_id.COUNT
947     INSERT INTO PO_SESSION_GT(key,
948                               num1,
949                               num2,
950                               num3)
951     SELECT p_key
952          , l_subscript_array(i)
953          , p_headers_rec.interface_header_id(i)
954          , p_headers_rec.vendor_contact_id(i)
955     FROM DUAL
956     WHERE --p_headers_rec.has_errors(i) = 'N'
957       p_headers_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_header_create, 'UPDATE')
958       AND p_headers_rec.vendor_id(i) IS NOT NULL
959       AND p_headers_rec.vendor_site_id(i) IS NOT NULL
960       AND p_headers_rec.vendor_contact_id(i) IS NOT NULL
961       AND NOT EXISTS(SELECT 1
962                      FROM PO_VENDOR_CONTACTS PVC
963                      WHERE p_headers_rec.vendor_site_id(i) = PVC.vendor_site_id
964                        AND p_headers_rec.vendor_contact_id(i) = PVC.vendor_contact_id);
965 
966   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
967 
968   l_progress := '150';
969   -- SQL What: Transfer from session GT table to local arrays
970   -- SQL Why : It will be used to mark the error records.
971   -- SQL Join: key
972   DELETE FROM PO_SESSION_GT
973   WHERE  key = p_key
974   RETURNING num1, num2, num3
975   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_vendor_contact_id_list;
976 
977   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
978 
979   l_progress := '160';
980   -- Mark the error records
981   FOR i IN 1 .. l_indexes.COUNT
982   LOOP
983     l_index := l_indexes(i);
984 
985     -- No need to error out. Just NULL out the vendor contact and proceed
986     --p_headers_rec.has_errors(l_index) := 'Y';
987     p_headers_rec.vendor_contact_id(l_index) := NULL;
988 
989     -- Add error message into INTERFACE_ERRORS table
990     -- PO_PDOI_INVALID_VDR_CNTCT:
991     -- "Supplier Contact (VALUE=VALUE) is not an active and valid contact for the specified supplier site."
992     --PO_R12_CAT_UPG_UTL.add_fatal_error(
993     --        p_interface_header_id => l_interface_header_ids(i),
994     --        p_error_message_name  => 'PO_PDOI_INVALID_VDR_CNTCT',
995     --        p_table_name          => 'PO_HEADERS_INTERFACE',
996     --        p_column_name         => 'VENDOR_CONTACT_ID',
997     --        p_column_value        => l_vendor_contact_id_list(i),
998     --        p_token1_name         => 'VALUE',
999     --        p_token1_value        => l_vendor_contact_id_list(i)
1000     --        );
1001   END LOOP;
1002 
1003   ----------------------------------------------------------------------------
1004   -- Validate vendor_site_id for CCR status
1005   ----------------------------------------------------------------------------
1006 
1007   -- The PO_FV_INTEGRATION_PVT.val_vendor_site_ccr_regis() API is not
1008   -- available in 11.5.9. It was coded as part of the JFMIP project in 11.5.10
1009 
1010   -- validate vendor site CCR if approval status is APPROVED.
1011   l_progress := '170';
1012   IF (l_federal_instance = 'Y') THEN
1013     FOR i IN 1 .. p_headers_rec.vendor_site_id.COUNT
1014     LOOP
1015 
1016       IF (p_headers_rec.vendor_id(i) IS NOT NULL AND
1017           p_headers_rec.vendor_id(i) <> g_NULL_COLUMN_VALUE AND -- -2
1018           p_headers_rec.vendor_site_id(i) IS NOT NULL AND
1019           p_headers_rec.vendor_site_id(i) <> g_NULL_COLUMN_VALUE AND -- -2
1020           p_headers_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_header_create, 'UPDATE') --AND
1021           --p_headers_rec.has_errors(i) = 'N'
1022          ) THEN
1023 
1024           l_progress := '180';
1025           -- Call PO_FV_INTEGRATION_PVT.val_vendor_site_ccr_regis to check the
1026           -- Central Contractor Registration (CCR) status of the vendor site
1027           x_temp_val := PO_FV_INTEGRATION_PVT.val_vendor_site_ccr_regis(
1028                                 p_vendor_id      => p_headers_rec.vendor_id(i),
1029                                 p_vendor_site_id => p_headers_rec.vendor_site_id(i));
1030 
1031           IF (x_temp_val = FALSE) THEN
1032             p_headers_rec.has_errors(i) := 'Y';
1033 
1034             l_progress := '190';
1035             IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: vendor_site_code='||p_headers_rec.vendor_site_code(i)||', vendor_site_id='||p_headers_rec.vendor_site_id(i)||
1036                                                                                                 ', vendor_name='||p_headers_rec.vendor_name(i)||', vendor_id='||p_headers_rec.vendor_id(i)); END IF;
1037 
1038             -- Add error message into INTERFACE_ERRORS table
1039             -- ICX_CAT_SUPPLIER_SITE_CCR_INV:
1040             -- "Supplier site (VENDOR_SITE) is assigned to a CCR supplier
1041             --      (VENDOR_NAME) with an expired or deleted registration."
1042             PO_R12_CAT_UPG_UTL.add_fatal_error(
1043                     p_interface_header_id => p_headers_rec.interface_header_id(i),
1044                     --p_error_message_name  => 'PO_PDOI_VENDOR_SITE_CCR_INV',
1045                     p_error_message_name  => 'ICX_CAT_SUPPLIER_SITE_CCR_INV',
1046                     p_table_name          => 'PO_HEADERS_INTERFACE',
1047                     p_column_name         => 'VENDOR_SITE_ID',
1048                     p_column_value        => p_headers_rec.vendor_site_code(i),
1049                     p_token1_name         => 'VENDOR_SITE_ID',
1050                     p_token1_value        => p_headers_rec.vendor_site_id(i),
1051                     p_token2_name         => 'VENDOR_NAME',
1052                     p_token2_value        => p_headers_rec.vendor_name(i)
1053                     );
1054           END IF;
1055        END IF;
1056     END LOOP;
1057   END IF; -- IF (l_federal_instance = 'Y')
1058 
1059   l_progress := '200';
1060   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
1061 EXCEPTION
1062   WHEN OTHERS THEN
1063     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
1064     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
1065 END validate_vendor_info;
1066 
1067 --------------------------------------------------------------------------------
1068 --Start of Comments
1069 --Name: get_hr_location_name_from_id
1070 --Pre-reqs:
1071 --  None
1072 --Modifies:
1073 --  None
1074 --Locks:
1075 --  None.
1076 --Function:
1077 -- Performs the id-to-name conversion for location_id.
1078 -- Used when logging validation errors.
1079 --Parameters:
1080 --IN:
1081 --p_category_id
1082 --  The LOCATION_ID for which we want the name
1083 --OUT:
1084 --p_category_name
1085 --  The outut name for the given ID.
1086 --OUT:
1087 --End of Comments
1088 --------------------------------------------------------------------------------
1089 PROCEDURE get_hr_location_name_from_id
1090 (
1091   p_location_id   IN NUMBER,
1092   x_location_name OUT NOCOPY VARCHAR2
1093 )
1094 IS
1095   l_api_name      CONSTANT VARCHAR2(30) := 'get_hr_location_name_from_id';
1096   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
1097   l_progress      VARCHAR2(3) := '000';
1098 BEGIN
1099   l_progress := '010';
1100   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
1101 
1102   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_location_id='||p_location_id); END IF;
1103 
1104   -- ECO bug 5584556: id-to-name conversion for new message
1105   -- Get the category name
1106   l_progress := '020';
1107   BEGIN
1108     SELECT location_code
1109     INTO x_location_name
1110     FROM HR_LOCATIONS_ALL_TL
1111     WHERE location_id = p_location_id
1112       AND language = userenv('LANG');
1113   EXCEPTION
1114     WHEN OTHERS THEN
1115       l_progress := '030';
1116       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Exception while getting name from HR_LOCATIONS_ALL_TL: '||SQLERRM); END IF;
1117 
1118       x_location_name := p_location_id;
1119   END;
1120   -- ECO bug 5584556: End
1121 
1122   l_progress := '040';
1123   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'location_name='||x_location_name); END IF;
1124 
1125   l_progress := '050';
1126   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
1127 EXCEPTION
1128   WHEN OTHERS THEN
1129     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
1130     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
1131 END get_hr_location_name_from_id;
1132 
1133 --------------------------------------------------------------------------------
1134 --Start of Comments
1135 --Name: validate_ship_to_location_id
1136 --Pre-reqs:
1137 --  The iP catalog data is populated in input pl/sql tables.
1138 --Modifies:
1139 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
1140 --  b) FND_MSG_PUB on unhandled exceptions.
1141 --Locks:
1142 --  None.
1143 --Function:
1144 --  Validates ship_to_location_id not null and against HR_LOCATIONS.
1145 --Parameters:
1146 --IN:
1147 --p_key
1148 --  Key used to access records in PO_SESSION_GT table.
1149 --IN/OUT:
1150 --p_headers_rec
1151 --  A record of plsql tables containing a batch of headers. If this validation
1152 --  fails, the 'has_errors' column is set to 'Y'.
1153 --OUT:
1154 --End of Comments
1155 --------------------------------------------------------------------------------
1156 PROCEDURE validate_ship_to_location_id
1157 (
1158   p_key         IN NUMBER,
1159   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
1160 )
1161 IS
1162   l_api_name      CONSTANT VARCHAR2(30) := 'validate_ship_to_location_id';
1163   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
1164   l_progress      VARCHAR2(3) := '000';
1165 
1166   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
1167 
1168   l_interface_header_ids    PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1169   l_indexes                 PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1170   l_err_ship_to_loc_id_list PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1171 
1172   l_index NUMBER;
1173   i NUMBER;
1174   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1175 
1176   l_location_name HR_LOCATIONS_ALL_TL.location_code%TYPE;
1177 BEGIN
1178   l_progress := '010';
1179   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
1180 
1181   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.ship_to_location_id.COUNT);
1182 
1183   IF (p_headers_rec.currency_code.COUNT > 0) THEN
1184     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.ship_to_location_id(1)='||p_headers_rec.ship_to_location_id(1)); END IF;
1185     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
1186     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
1187   END IF;
1188 
1189   l_progress := '020';
1190   -- ECO bug 5584556: Start
1191   -- Add a separate message to check for null values and id's that dont exist
1192 
1193   -- SQL What: Bulk validate ship_to_location_id not null and against HR_LOCATIONS_ALL.
1194   --           Get the errored rows into GT table.
1195   -- SQL Why : It will be used to mark the record in plsql table as error.
1196   -- SQL Join: ship_to_location_id
1197   FORALL i IN 1 .. p_headers_rec.ship_to_location_id.COUNT
1198     INSERT INTO PO_SESSION_GT(key,
1199                               num1,
1200                               num2,
1201                               num3)
1202     SELECT p_key
1203          , l_subscript_array(i)
1204          , p_headers_rec.interface_header_id(i)
1205          , p_headers_rec.ship_to_location_id(i)
1206     FROM DUAL
1207     WHERE --p_headers_rec.has_errors(i) = 'N'
1208     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
1209     AND   (p_headers_rec.ship_to_location_id(i) IS NULL OR
1210            NOT EXISTS(SELECT 1
1211                       FROM HR_LOCATIONS_ALL HRLA
1212                       WHERE p_headers_rec.ship_to_location_id(i) = HRLA.location_id));
1213 
1214   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
1215 
1216   l_progress := '030';
1217   -- SQL What: Transfer from session GT table to local arrays
1218   -- SQL Why : It will be used to mark the error records.
1219   -- SQL Join: key
1220   DELETE FROM PO_SESSION_GT
1221   WHERE  key = p_key
1222   RETURNING num1, num2, num3
1223   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_ship_to_loc_id_list;
1224 
1225   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
1226 
1227   l_progress := '040';
1228   -- Mark the error records
1229   FOR i IN 1 .. l_indexes.COUNT
1230   LOOP
1231     l_index := l_indexes(i);
1232     p_headers_rec.has_errors(l_index) := 'Y';
1233 
1234     -- Add error message into INTERFACE_ERRORS table
1235     -- ICX_CAT_SHIP_LOC_REQD:
1236     -- "The system cannot obtain the default value for the ship to location."
1237     PO_R12_CAT_UPG_UTL.add_fatal_error(
1238             p_interface_header_id => l_interface_header_ids(i),
1239             p_error_message_name  => 'ICX_CAT_SHIP_LOC_REQD',
1240             p_table_name          => 'PO_HEADERS_INTERFACE',
1241             p_column_name         => 'SHIP_TO_LOCATION_ID',
1242             p_column_value        => l_err_ship_to_loc_id_list(i)
1243             );
1244   END LOOP;
1245   -- ECO bug 5584556: End
1246 
1247   l_progress := '050';
1248   -- SQL What: Bulk validate ship_to_location_id against HR_LOCATIONS.
1249   --           Check if it is an active location.
1250   --           Get the errored rows into GT table.
1251   -- SQL Why : It will be used to mark the record in plsql table as error.
1252   -- SQL Join: ship_to_location_id
1253   FORALL i IN 1 .. p_headers_rec.ship_to_location_id.COUNT
1254     INSERT INTO PO_SESSION_GT(key,
1255                               num1,
1256                               num2,
1257                               num3)
1258     SELECT p_key
1259          , l_subscript_array(i)
1260          , p_headers_rec.interface_header_id(i)
1261          , p_headers_rec.ship_to_location_id(i)
1262     FROM DUAL
1263     WHERE --p_headers_rec.has_errors(i) = 'N'
1264     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
1265     -- ECO bug 5584556: Start
1266     -- The following validation checks are already done above.
1267     -- So adding these additional where-clauses to skip those cases.
1268     AND p_headers_rec.ship_to_location_id(i) IS NOT NULL
1269     AND EXISTS(SELECT 'ID exists'
1270                FROM HR_LOCATIONS_ALL HRLA
1271                WHERE p_headers_rec.ship_to_location_id(i) = HRLA.location_id)
1272     -- ECO bug 5584556: End
1273     AND NOT EXISTS(SELECT 'Active ship-to-location'
1274                    FROM HR_LOCATIONS HRL
1275                    WHERE HRL.ship_to_site_flag = 'Y'
1276                      AND p_headers_rec.ship_to_location_id(i) = HRL.location_id
1277                      AND SYSDATE < NVL(HRL.inactive_date, SYSDATE + 1));
1278 
1279   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
1280 
1281   l_progress := '060';
1282   -- SQL What: Transfer from session GT table to local arrays
1283   -- SQL Why : It will be used to mark the error records.
1284   -- SQL Join: key
1285   DELETE FROM PO_SESSION_GT
1286   WHERE  key = p_key
1287   RETURNING num1, num2, num3
1288   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_ship_to_loc_id_list;
1289 
1290   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
1291 
1292   l_progress := '070';
1293   -- Mark the error records
1294   FOR i IN 1 .. l_indexes.COUNT
1295   LOOP
1296     l_index := l_indexes(i);
1297     p_headers_rec.has_errors(l_index) := 'Y';
1298 
1299     -- ECO bug 5584556: id-to-name conversion for new message
1300     l_progress := '080';
1301     get_hr_location_name_from_id
1302     (
1303       p_location_id   => l_err_ship_to_loc_id_list(i)
1304     , x_location_name => l_location_name
1305     );
1306     -- ECO bug 5584556: End
1307 
1308     -- Add error message into INTERFACE_ERRORS table
1309     -- ICX_CAT_INVALID_SHIP_LOC:
1310     -- "Default ship to location (VALUE) is inactive or invalid."
1311     PO_R12_CAT_UPG_UTL.add_fatal_error(
1312             p_interface_header_id => l_interface_header_ids(i),
1313             --p_error_message_name  => 'PO_PDOI_INVALID_SHIP_LOC_ID',
1314             p_error_message_name  => 'ICX_CAT_INVALID_SHIP_LOC',
1315             p_table_name          => 'PO_HEADERS_INTERFACE',
1316             p_column_name         => 'SHIP_TO_LOCATION_ID',
1317             p_column_value        => l_location_name, -- ECO bug 5584556
1318             p_token1_name         => 'VALUE',
1319             p_token1_value        => l_err_ship_to_loc_id_list(i)
1320             );
1321   END LOOP;
1322 
1323   l_progress := '090';
1324   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
1325 EXCEPTION
1326   WHEN OTHERS THEN
1327     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
1328     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
1329 END validate_ship_to_location_id;
1330 
1331 --------------------------------------------------------------------------------
1332 --Start of Comments
1333 --Name: validate_bill_to_location_id
1334 --Pre-reqs:
1335 --  The iP catalog data is populated in input pl/sql tables.
1336 --Modifies:
1337 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
1338 --  b) FND_MSG_PUB on unhandled exceptions.
1339 --Locks:
1340 --  None.
1341 --Function:
1342 --  Validates bill_to_location_id not null and against HR_LOCATIONS.
1343 --Parameters:
1344 --IN:
1345 --p_key
1346 --  Key used to access records in PO_SESSION_GT table.
1347 --IN/OUT:
1348 --p_headers_rec
1349 --  A record of plsql tables containing a batch of headers. If this validation
1350 --  fails, the 'has_errors' column is set to 'Y'.
1351 --OUT:
1352 --End of Comments
1353 --------------------------------------------------------------------------------
1354 PROCEDURE validate_bill_to_location_id
1355 (
1356   p_key         IN NUMBER,
1357   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
1358 )
1359 IS
1360   l_api_name      CONSTANT VARCHAR2(30) := 'validate_bill_to_location_id';
1361   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
1362   l_progress      VARCHAR2(3) := '000';
1363 
1364   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
1365 
1366   l_interface_header_ids    PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1367   l_indexes                 PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1368   l_err_bill_to_loc_id_list PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1369 
1370   l_index NUMBER;
1371   i NUMBER;
1372   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1373 
1374   l_location_name HR_LOCATIONS_ALL_TL.location_code%TYPE;
1375 BEGIN
1376   l_progress := '010';
1377   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
1378 
1379   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.bill_to_location_id.COUNT);
1380 
1381   IF (p_headers_rec.currency_code.COUNT > 0) THEN
1382     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.bill_to_location_id(1)='||p_headers_rec.bill_to_location_id(1)); END IF;
1383     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
1384     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
1385   END IF;
1386 
1387   l_progress := '020';
1388   -- SQL What: Bulk validate bill_to_location_id not null and against HR_LOCATIONS_ALL.
1389   --           Get the errored rows into GT table.
1390   -- SQL Why : It will be used to mark the record in plsql table as error.
1391   -- SQL Join: bill_to_location_id
1392   FORALL i IN 1 .. p_headers_rec.bill_to_location_id.COUNT
1393     INSERT INTO PO_SESSION_GT(key,
1394                               num1,
1395                               num2,
1396                               num3)
1397     SELECT p_key
1398          , l_subscript_array(i)
1399          , p_headers_rec.interface_header_id(i)
1400          , p_headers_rec.bill_to_location_id(i)
1401     FROM DUAL
1402     WHERE --p_headers_rec.has_errors(i) = 'N'
1403     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
1404     AND   (p_headers_rec.bill_to_location_id(i) IS NULL OR
1405            NOT EXISTS(SELECT 1
1406                       FROM HR_LOCATIONS_ALL HRLA
1407                       WHERE p_headers_rec.bill_to_location_id(i) = HRLA.location_id));
1408 
1409   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
1410 
1411   l_progress := '030';
1412   -- SQL What: Transfer from session GT table to local arrays
1413   -- SQL Why : It will be used to mark the error records.
1414   -- SQL Join: key
1415   DELETE FROM PO_SESSION_GT
1416   WHERE  key = p_key
1417   RETURNING num1, num2, num3
1418   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_bill_to_loc_id_list;
1419 
1420   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
1421 
1422   l_progress := '040';
1423   -- Mark the error records
1424   FOR i IN 1 .. l_indexes.COUNT
1425   LOOP
1426     l_index := l_indexes(i);
1427     p_headers_rec.has_errors(l_index) := 'Y';
1428 
1429     -- Add error message into INTERFACE_ERRORS table
1430     -- ICX_CAT_BILL_LOC_REQD:
1431     -- "The system cannot obtain the default value for the bill to location."
1432     PO_R12_CAT_UPG_UTL.add_fatal_error(
1433             p_interface_header_id => l_interface_header_ids(i),
1434             p_error_message_name  => 'ICX_CAT_BILL_LOC_REQD',
1435             p_table_name          => 'PO_HEADERS_INTERFACE',
1436             p_column_name         => 'BILL_TO_LOCATION_ID',
1437             p_column_value        => l_err_bill_to_loc_id_list(i)
1438             );
1439   END LOOP;
1440 
1441   l_progress := '050';
1442   -- SQL What: Bulk validate bill_to_location_id against HR_LOCATIONS.
1443   --           Check if it is an active location.
1444   --           Get the errored rows into GT table.
1445   -- SQL Why : It will be used to mark the record in plsql table as error.
1446   -- SQL Join: bill_to_location_id
1447   FORALL i IN 1 .. p_headers_rec.bill_to_location_id.COUNT
1448     INSERT INTO PO_SESSION_GT(key,
1449                               num1,
1450                               num2,
1451                               num3)
1452     SELECT p_key
1453          , l_subscript_array(i)
1454          , p_headers_rec.interface_header_id(i)
1455          , p_headers_rec.bill_to_location_id(i)
1456     FROM DUAL
1457     WHERE --p_headers_rec.has_errors(i) = 'N'
1458     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
1459     -- ECO bug 5584556: Start
1460     -- The following validation checks are already done above.
1461     -- So adding these additional where-clauses to skip those cases.
1462     AND p_headers_rec.bill_to_location_id(i) IS NOT NULL
1463     AND EXISTS(SELECT 'ID exists'
1464                FROM HR_LOCATIONS_ALL HRLA
1465                WHERE p_headers_rec.bill_to_location_id(i) = HRLA.location_id)
1466     -- ECO bug 5584556: End
1467     AND NOT EXISTS(SELECT 1
1468                    FROM HR_LOCATIONS HRL
1469                    WHERE HRL.bill_to_site_flag = 'Y'
1470                      AND p_headers_rec.bill_to_location_id(i) = HRL.location_id
1471                      AND SYSDATE < NVL(HRL.inactive_date, SYSDATE + 1));
1472 
1473   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
1474 
1475   l_progress := '060';
1476   -- SQL What: Transfer from session GT table to local arrays
1477   -- SQL Why : It will be used to mark the error records.
1478   -- SQL Join: key
1479   DELETE FROM PO_SESSION_GT
1480   WHERE  key = p_key
1481   RETURNING num1, num2, num3
1482   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_bill_to_loc_id_list;
1483 
1484   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
1485 
1486   l_progress := '070';
1487   -- Mark the error records
1488   FOR i IN 1 .. l_indexes.COUNT
1489   LOOP
1490     l_index := l_indexes(i);
1491     p_headers_rec.has_errors(l_index) := 'Y';
1492 
1493     -- ECO bug 5584556: id-to-name conversion for new message
1494     l_progress := '080';
1495     get_hr_location_name_from_id
1496     (
1497       p_location_id   => l_err_bill_to_loc_id_list(i)
1498     , x_location_name => l_location_name
1499     );
1500     -- ECO bug 5584556: End
1501 
1502     -- Add error message into INTERFACE_ERRORS table
1503     -- ICX_CAT_INVALID_BILL_LOC:
1504     -- "Default bill to location (VALUE) is inactive or invalid."
1505     PO_R12_CAT_UPG_UTL.add_fatal_error(
1506             p_interface_header_id => l_interface_header_ids(i),
1507             --p_error_message_name  => 'PO_PDOI_INVALID_BILL_LOC_ID',
1508             p_error_message_name  => 'ICX_CAT_INVALID_BILL_LOC',
1509             p_table_name          => 'PO_HEADERS_INTERFACE',
1510             p_column_name         => 'BILL_TO_LOCATION_ID',
1511             p_column_value        => l_location_name, -- ECO bug 5584556
1512             p_token1_name         => 'VALUE',
1513             p_token1_value        => l_err_bill_to_loc_id_list(i)
1514             );
1515   END LOOP;
1516 
1517   l_progress := '090';
1518   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
1519 EXCEPTION
1520   WHEN OTHERS THEN
1521     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
1522     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
1523 END validate_bill_to_location_id;
1524 
1525 --------------------------------------------------------------------------------
1526 --Start of Comments
1527 --Name: get_lookup_name_from_code
1528 --Pre-reqs:
1529 --  None
1530 --Modifies:
1531 --  None
1532 --Locks:
1533 --  None.
1534 --Function:
1535 -- Performs the id-to-name conversion for PO_LOOKUP_CODES.
1536 -- Used when logging validation errors.
1537 --Parameters:
1538 --IN:
1539 --p_po_lookup_code
1540 --  The LOOKUP_CODE for which we want the meaning
1541 --p_po_lookup_type
1542 --  The LOOKUP_TYPE for which we want the meaning
1543 --OUT:
1544 --x_lookup_meaning
1545 --  The outut name for the given code.
1546 --OUT:
1547 --End of Comments
1548 --------------------------------------------------------------------------------
1549 PROCEDURE get_lookup_name_from_code
1550 (
1551   p_po_lookup_code IN VARCHAR2,
1552   p_po_lookup_type IN VARCHAR2,
1553   x_lookup_meaning OUT NOCOPY VARCHAR2
1554 )
1555 IS
1556   l_api_name      CONSTANT VARCHAR2(30) := 'get_lookup_name_from_code';
1557   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
1558   l_progress      VARCHAR2(3) := '000';
1559 BEGIN
1560   l_progress := '010';
1561   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
1562 
1563   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_po_lookup_code='||p_po_lookup_code); END IF;
1564 
1565   -- ECO bug 5584556: id-to-name conversion for new message
1566   -- Get the lookup meaning
1567   l_progress := '020';
1568   BEGIN
1569     SELECT displayed_field
1570     INTO x_lookup_meaning
1571     FROM PO_LOOKUP_CODES
1572     WHERE lookup_code = p_po_lookup_code
1573       AND lookup_type = p_po_lookup_type;
1574       -- The PO_LOOKUP_CODES is a view on top of FND_LOOKUP_VALUES with a userenv('LANG') join
1575       --AND language = userenv('LANG');
1576   EXCEPTION
1577     WHEN OTHERS THEN
1578       l_progress := '030';
1579       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Exception while getting name from PO_LOOKUP_CODES: '||SQLERRM); END IF;
1580 
1581       x_lookup_meaning := p_po_lookup_code;
1582   END;
1583   -- ECO bug 5584556: End
1584 
1585   l_progress := '040';
1586   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'x_lookup_meaning='||x_lookup_meaning); END IF;
1587 
1588   l_progress := '050';
1589   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
1590 EXCEPTION
1591   WHEN OTHERS THEN
1592     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
1593     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
1594 END get_lookup_name_from_code;
1595 
1596 --------------------------------------------------------------------------------
1597 --Start of Comments
1598 --Name: validate_fob_lookup_code
1599 --Pre-reqs:
1600 --  The iP catalog data is populated in input pl/sql tables.
1601 --Modifies:
1602 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
1603 --  b) FND_MSG_PUB on unhandled exceptions.
1604 --Locks:
1605 --  None.
1606 --Function:
1607 --  Validates fob_lookup_code against PO_LOOKUP_CODES.
1608 --Parameters:
1609 --IN:
1610 --p_key
1611 --  Key used to access records in PO_SESSION_GT table.
1612 --IN/OUT:
1613 --p_headers_rec
1614 --  A record of plsql tables containing a batch of headers. If this validation
1615 --  fails, the 'has_errors' column is set to 'Y'.
1616 --OUT:
1617 --End of Comments
1618 --------------------------------------------------------------------------------
1619 PROCEDURE validate_fob_lookup_code
1620 (
1621   p_key         IN NUMBER,
1622   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
1623 )
1624 IS
1625   l_api_name      CONSTANT VARCHAR2(30) := 'validate_fob_lookup_code';
1626   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
1627   l_progress      VARCHAR2(3) := '000';
1628 
1629   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
1630 
1631   l_interface_header_ids     PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1632   l_indexes                  PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1633   l_err_fob_lookup_code_list PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR25;
1634 
1635   l_index NUMBER;
1636   i NUMBER;
1637   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1638 
1639   l_lookup_meaning PO_LOOKUP_CODES.displayed_field%TYPE;
1640 BEGIN
1641   l_progress := '010';
1642   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
1643   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Validating a defaulted field -- FOB_LOOKUP_CODE'); END IF;
1644 
1645   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.fob.COUNT);
1646 
1647   IF (p_headers_rec.fob.COUNT > 0) THEN
1648     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.fob(1)='||p_headers_rec.fob(1)); END IF;
1649     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
1650     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
1651   END IF;
1652 
1653   l_progress := '020';
1654   -- SQL What: Bulk validate fob_lookup_code not null and against PO_LOOKUP_CODES.
1655   --           Get the errored rows into GT table.
1656   -- SQL Why : It will be used to mark the record in plsql table as error.
1657   -- SQL Join: bill_to_location_id
1658   FORALL i IN 1 .. p_headers_rec.fob.COUNT
1659     INSERT INTO PO_SESSION_GT(key,
1660                               num1,
1661                               num2,
1662                               char1)
1663     SELECT p_key
1664          , l_subscript_array(i)
1665          , p_headers_rec.interface_header_id(i)
1666          , p_headers_rec.fob(i)
1667     FROM DUAL
1668     WHERE --p_headers_rec.has_errors(i) = 'N'
1669           p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
1670       AND p_headers_rec.fob(i) IS NOT NULL
1671       AND NOT EXISTS(SELECT 1
1672                        FROM PO_LOOKUP_CODES PLC
1673                       WHERE p_headers_rec.fob(i) = PLC.lookup_code
1674                         AND PLC.lookup_type = 'FOB'
1675                         AND SYSDATE < NVL(PLC.inactive_date, SYSDATE + 1));
1676 
1677   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
1678 
1679   l_progress := '030';
1680   -- SQL What: Transfer from session GT table to local arrays
1681   -- SQL Why : It will be used to mark the error records.
1682   -- SQL Join: key
1683   DELETE FROM PO_SESSION_GT
1684   WHERE  key = p_key
1685   RETURNING num1, num2, char1
1686   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_fob_lookup_code_list;
1687 
1688   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
1689 
1690   l_progress := '040';
1691   -- Mark the error records
1692   FOR i IN 1 .. l_indexes.COUNT
1693   LOOP
1694     l_index := l_indexes(i);
1695     p_headers_rec.has_errors(l_index) := 'Y';
1696 
1697     -- ECO bug 5584556: id-to-name conversion
1698     l_progress := '050';
1699     get_lookup_name_from_code
1700     (
1701       p_po_lookup_code => l_err_fob_lookup_code_list(i)
1702     , p_po_lookup_type => 'FOB'
1703     , x_lookup_meaning => l_lookup_meaning
1704     );
1705     -- ECO bug 5584556: End
1706 
1707     l_progress := '060';
1708     -- Add error message into INTERFACE_ERRORS table
1709     -- ICX_CAT_INVALID_FOB:
1710     -- "Default FOB carrier (VALUE) is inactive or invalid."
1711     PO_R12_CAT_UPG_UTL.add_fatal_error(
1712             p_interface_header_id => l_interface_header_ids(i),
1713             --p_error_message_name  => 'ICX_CAT_INVALID_FOB_CODE',
1714             p_error_message_name  => 'ICX_CAT_INVALID_FOB', -- Bug 5461235
1715             p_table_name          => 'PO_HEADERS_INTERFACE',
1716             p_column_name         => 'FOB_LOOKUP_CODE',
1717             p_column_value        => l_lookup_meaning, -- ECO Bug 5584556
1718             p_token1_name         => 'VALUE',
1719             p_token1_value        => l_err_fob_lookup_code_list(i)
1720             );
1721   END LOOP;
1722 
1723   l_progress := '070';
1724   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
1725 EXCEPTION
1726   WHEN OTHERS THEN
1727     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
1728     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
1729 END validate_fob_lookup_code;
1730 
1731 --------------------------------------------------------------------------------
1732 --Start of Comments
1733 --Name: validate_ship_via_luc
1734 --Pre-reqs:
1735 --  The iP catalog data is populated in input pl/sql tables.
1736 --Modifies:
1737 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
1738 --  b) FND_MSG_PUB on unhandled exceptions.
1739 --Locks:
1740 --  None.
1741 --Function:
1742 --  Validates ship_via_lookup_code against ORG_FREIGHTS.
1743 --Parameters:
1744 --IN:
1745 --p_key
1746 --  Key used to access records in PO_SESSION_GT table.
1747 --IN/OUT:
1748 --p_headers_rec
1749 --  A record of plsql tables containing a batch of headers. If this validation
1750 --  fails, the 'has_errors' column is set to 'Y'.
1751 --OUT:
1752 --End of Comments
1753 --------------------------------------------------------------------------------
1754 PROCEDURE validate_ship_via_luc
1755 (
1756   p_key         IN NUMBER,
1757   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
1758 )
1759 IS
1760   l_api_name      CONSTANT VARCHAR2(30) := 'validate_ship_via_luc';
1761   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
1762   l_progress      VARCHAR2(3) := '000';
1763 
1764   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
1765 
1766   l_interface_header_ids  PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1767   l_indexes               PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1768   l_err_ship_via_luc_list PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR25;
1769 
1770   l_index NUMBER;
1771   i NUMBER;
1772   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1773 BEGIN
1774   l_progress := '010';
1775   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
1776   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Validating a defaulted field -- SHIP_VIA_LOOKUP_CODE (freight_carrier)'); END IF;
1777 
1778   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.freight_carrier.COUNT);
1779 
1780   IF (p_headers_rec.freight_carrier.COUNT > 0) THEN
1781     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.freight_carrier(1)='||p_headers_rec.freight_carrier(1)); END IF;
1782     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
1783     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
1784   END IF;
1785 
1786   l_progress := '020';
1787   -- SQL What: Bulk validate ship_via_lookup_code against ORG_FREIGHT.
1788   --           Get the errored rows into GT table.
1789   -- SQL Why : It will be used to mark the record in plsql table as error.
1790   -- SQL Join: ship_via_lookup_code
1791 
1792   -- bug5601416: use default inv org id instead of master org
1793 
1794   FORALL i IN 1 .. p_headers_rec.freight_carrier.COUNT
1795     INSERT INTO PO_SESSION_GT(key,
1796                               num1,
1797                               num2,
1798                               char1)
1799     SELECT p_key
1800          , l_subscript_array(i)
1801          , p_headers_rec.interface_header_id(i)
1802          , p_headers_rec.freight_carrier(i)
1803     FROM DUAL
1804     WHERE --p_headers_rec.has_errors(i) = 'N'
1805     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
1806     AND p_headers_rec.freight_carrier(i) IS NOT NULL
1807     AND NOT EXISTS(SELECT 1
1808                    FROM ORG_FREIGHT OFR
1809                    WHERE p_headers_rec.freight_carrier(i) = OFR.freight_code
1810                    AND NVL(OFR.disable_date, SYSDATE + 1) > SYSDATE
1811                    AND OFR.organization_id = PO_R12_CAT_UPG_PVT.g_sys.inv_org_id);
1812 
1813   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
1814 
1815   l_progress := '030';
1816   -- SQL What: Transfer from session GT table to local arrays
1817   -- SQL Why : It will be used to mark the error records.
1818   -- SQL Join: key
1819   DELETE FROM PO_SESSION_GT
1820   WHERE  key = p_key
1821   RETURNING num1, num2, char1
1822   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_ship_via_luc_list;
1823 
1824   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
1825 
1826   l_progress := '040';
1827   -- Mark the error records
1828   FOR i IN 1 .. l_indexes.COUNT
1829   LOOP
1830     l_index := l_indexes(i);
1831     p_headers_rec.has_errors(l_index) := 'Y';
1832 
1833     -- Add error message into INTERFACE_ERRORS table
1834     -- ICX_CAT_INVALID_FREIGHT_CAR:
1835     -- "Default freight carrier (VALUE) is inactive or invalid."
1836     PO_R12_CAT_UPG_UTL.add_fatal_error(
1837             p_interface_header_id => l_interface_header_ids(i),
1838             p_error_message_name  => 'ICX_CAT_INVALID_FREIGHT_CAR', -- ECO bug 5584556: 'ICX_CAT_INVALID_SHIP_VIA_CODE',
1839             p_table_name          => 'PO_HEADERS_INTERFACE',
1840             p_column_name         => 'SHIP_VIA_LOOKUP_CODE',
1841             p_column_value        => l_err_ship_via_luc_list(i),
1842             p_token1_name         => 'VALUE',
1843             p_token1_value        => l_err_ship_via_luc_list(i)
1844             );
1845   END LOOP;
1846 
1847   l_progress := '050';
1848   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
1849 EXCEPTION
1850   WHEN OTHERS THEN
1851     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
1852     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
1853 END validate_ship_via_luc;
1854 
1855 --------------------------------------------------------------------------------
1856 --Start of Comments
1857 --Name: validate_freight_terms
1858 --Pre-reqs:
1859 --  The iP catalog data is populated in input pl/sql tables.
1860 --Modifies:
1861 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
1862 --  b) FND_MSG_PUB on unhandled exceptions.
1863 --Locks:
1864 --  None.
1865 --Function:
1866 --  Validates freight_terms_lookup_code against PO_LOOKUP_CODES.
1867 --Parameters:
1868 --IN:
1869 --p_key
1870 --  Key used to access records in PO_SESSION_GT table.
1871 --IN/OUT:
1872 --p_headers_rec
1873 --  A record of plsql tables containing a batch of headers. If this validation
1874 --  fails, the 'has_errors' column is set to 'Y'.
1875 --OUT:
1876 --End of Comments
1877 --------------------------------------------------------------------------------
1878 PROCEDURE validate_freight_terms
1879 (
1880   p_key         IN NUMBER,
1881   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
1882 )
1883 IS
1884   l_api_name      CONSTANT VARCHAR2(30) := 'validate_freight_terms';
1885   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
1886   l_progress      VARCHAR2(3) := '000';
1887 
1888   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
1889 
1890   l_interface_header_ids   PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1891   l_indexes                PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1892   l_err_freight_terms_list PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR25;
1893 
1894   l_index NUMBER;
1895   i NUMBER;
1896   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
1897 
1898   l_lookup_meaning PO_LOOKUP_CODES.displayed_field%TYPE;
1899 BEGIN
1900   l_progress := '010';
1901   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
1902   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Validating a defaulted field -- SHIP_VIA_LOOKUP_CODE (freight_carrier)'); END IF;
1903 
1904   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.freight_terms.COUNT);
1905 
1906   IF (p_headers_rec.freight_terms.COUNT > 0) THEN
1907     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.freight_terms(1)='||p_headers_rec.freight_terms(1)); END IF;
1908     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
1909     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
1910   END IF;
1911 
1912   l_progress := '020';
1913   -- SQL What: Bulk validate freight_terms_lookup_code against PO_LOOKUP_CODES.
1914   --           Get the errored rows into GT table.
1915   -- SQL Why : It will be used to mark the record in plsql table as error.
1916   -- SQL Join: ship_via_lookup_code
1917   FORALL i IN 1 .. p_headers_rec.freight_terms.COUNT
1918     INSERT INTO PO_SESSION_GT(key,
1919                               num1,
1920                               num2,
1921                               char1)
1922     SELECT p_key
1923          , l_subscript_array(i)
1924          , p_headers_rec.interface_header_id(i)
1925          , p_headers_rec.freight_terms(i)
1926     FROM DUAL
1927     WHERE --p_headers_rec.has_errors(i) = 'N'
1928     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
1929     AND p_headers_rec.freight_terms(i) IS NOT NULL
1930     AND NOT EXISTS(
1931           SELECT 1
1932             FROM PO_LOOKUP_CODES PLC
1933            WHERE p_headers_rec.freight_terms(i) = PLC.lookup_code
1934              AND PLC.lookup_type = 'FREIGHT TERMS'
1935              AND SYSDATE < NVL(PLC.inactive_date, SYSDATE + 1));
1936 
1937   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
1938 
1939   l_progress := '030';
1940   -- SQL What: Transfer from session GT table to local arrays
1941   -- SQL Why : It will be used to mark the error records.
1942   -- SQL Join: key
1943   DELETE FROM PO_SESSION_GT
1944   WHERE  key = p_key
1945   RETURNING num1, num2, char1
1946   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_freight_terms_list;
1947 
1948   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
1949 
1950   l_progress := '040';
1951   -- Mark the error records
1952   FOR i IN 1 .. l_indexes.COUNT
1953   LOOP
1954     l_index := l_indexes(i);
1955     p_headers_rec.has_errors(l_index) := 'Y';
1956 
1957     -- ECO bug 5584556: id-to-name conversion
1958     l_progress := '050';
1959     get_lookup_name_from_code
1960     (
1961       p_po_lookup_code => l_err_freight_terms_list(i)
1962     , p_po_lookup_type => 'FREIGHT TERMS'
1963     , x_lookup_meaning => l_lookup_meaning
1964     );
1965     -- ECO bug 5584556: End
1966 
1967     l_progress := '060';
1968     -- Add error message into INTERFACE_ERRORS table
1969     -- ICX_CAT_INVALID_FREIGHT_TERMS:
1970     -- "Default freight terms (VALUE) is inactive or invalid."
1971     PO_R12_CAT_UPG_UTL.add_fatal_error(
1972             p_interface_header_id => l_interface_header_ids(i),
1973             p_error_message_name  => 'ICX_CAT_INVALID_FREIGHT_TERMS',
1974             p_table_name          => 'PO_HEADERS_INTERFACE',
1975             p_column_name         => 'FREIGHT_TERMS_LOOKUP_CODE',
1976             p_column_value        => l_lookup_meaning, -- ECO bug 5584556
1977             p_token1_name         => 'VALUE',
1978             p_token1_value        => l_err_freight_terms_list(i)
1979             );
1980   END LOOP;
1981 
1982   l_progress := '070';
1983   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
1984 EXCEPTION
1985   WHEN OTHERS THEN
1986     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
1987     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
1988 END validate_freight_terms;
1989 
1990 --------------------------------------------------------------------------------
1991 --Start of Comments
1992 --Name: get_category_name_from_id
1993 --Pre-reqs:
1994 --  None
1995 --Modifies:
1996 --  None
1997 --Locks:
1998 --  None.
1999 --Function:
2000 -- Performs the id-to-name conversion for AP's terms_id.
2001 -- Used when logging validation errors.
2002 --Parameters:
2003 --IN:
2004 --p_terms_id
2005 --  The TERMS_ID for which we want the name
2006 --OUT:
2007 --p_terms_name
2008 --  The outut name for the given ID.
2009 --OUT:
2010 --End of Comments
2011 --------------------------------------------------------------------------------
2012 PROCEDURE get_ap_terms_name_from_id
2013 (
2014   p_terms_id   IN NUMBER,
2015   x_terms_name OUT NOCOPY VARCHAR2
2016 )
2017 IS
2018   l_api_name      CONSTANT VARCHAR2(30) := 'get_ap_terms_name_from_id';
2019   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
2020   l_progress      VARCHAR2(3) := '000';
2021 BEGIN
2022   l_progress := '010';
2023   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
2024 
2025   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_terms_id='||p_terms_id); END IF;
2026 
2027   -- ECO bug 5584556: id-to-name conversion for new message
2028   -- Get the category name
2029   l_progress := '020';
2030   BEGIN
2031     SELECT name
2032     INTO x_terms_name
2033     FROM AP_TERMS_TL
2034     WHERE term_id = p_terms_id
2035       AND language = userenv('LANG');
2036   EXCEPTION
2037     WHEN OTHERS THEN
2038       l_progress := '030';
2039       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Exception while getting name from AP_TERMS_TL: '||SQLERRM); END IF;
2040 
2041       x_terms_name := p_terms_id;
2042   END;
2043   -- ECO bug 5584556: End
2044 
2045   l_progress := '040';
2046   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'terms_name='||x_terms_name); END IF;
2047 
2048   l_progress := '050';
2049   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
2050 EXCEPTION
2051   WHEN OTHERS THEN
2052     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
2053     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
2054 END get_ap_terms_name_from_id;
2055 
2056 --------------------------------------------------------------------------------
2057 --Start of Comments
2058 --Name: validate_terms_id
2059 --Pre-reqs:
2060 --  The iP catalog data is populated in input pl/sql tables.
2061 --Modifies:
2062 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
2063 --  b) FND_MSG_PUB on unhandled exceptions.
2064 --Locks:
2065 --  None.
2066 --Function:
2067 --  Validates terms_id against AP_TERMS.
2068 --Parameters:
2069 --IN:
2070 --p_key
2071 --  Key used to access records in PO_SESSION_GT table.
2072 --IN/OUT:
2073 --p_headers_rec
2074 --  A record of plsql tables containing a batch of headers. If this validation
2075 --  fails, the 'has_errors' column is set to 'Y'.
2076 --OUT:
2077 --End of Comments
2078 --------------------------------------------------------------------------------
2079 PROCEDURE validate_terms_id
2080 (
2081   p_key         IN NUMBER,
2082   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
2083 )
2084 IS
2085   l_api_name      CONSTANT VARCHAR2(30) := 'validate_terms_id';
2086   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
2087   l_progress      VARCHAR2(3) := '000';
2088 
2089   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
2090 
2091   l_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2092   l_indexes              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2093   l_err_terms_id_list    PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2094 
2095   l_index NUMBER;
2096   i NUMBER;
2097   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2098 
2099   l_terms_name AP_TERMS_TL.name%TYPE;
2100 BEGIN
2101   l_progress := '010';
2102   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
2103   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Validating a defaulted field -- SHIP_VIA_LOOKUP_CODE (freight_carrier)'); END IF;
2104 
2105   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.terms_id.COUNT);
2106 
2107   IF (p_headers_rec.terms_id.COUNT > 0) THEN
2108     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.terms_id(1)='||p_headers_rec.terms_id(1)); END IF;
2109     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
2110     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
2111   END IF;
2112 
2113   l_progress := '020';
2114   -- SQL What: Bulk validate terms_id against AP_TERMS.
2115   --           Get the errored rows into GT table.
2116   -- SQL Why : It will be used to mark the record in plsql table as error.
2117   -- SQL Join: ship_via_lookup_code
2118   FORALL i IN 1 .. p_headers_rec.terms_id.COUNT
2119     INSERT INTO PO_SESSION_GT(key,
2120                               num1,
2121                               num2,
2122                               num3)
2123     SELECT p_key
2124          , l_subscript_array(i)
2125          , p_headers_rec.interface_header_id(i)
2126          , p_headers_rec.terms_id(i)
2127     FROM DUAL
2128     WHERE --p_headers_rec.has_errors(i) = 'N'
2129     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
2130     AND p_headers_rec.terms_id(i) IS NOT NULL
2131     AND NOT EXISTS
2132           (SELECT 1
2133            FROM AP_TERMS APT
2134            WHERE p_headers_rec.terms_id(i) = APT.term_id
2135              AND sysdate BETWEEN
2136                     nvl(APT.start_date_active, sysdate - 1) AND
2137                     nvl(APT.end_date_active, sysdate + 1));
2138 
2139   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
2140 
2141   l_progress := '030';
2142   -- SQL What: Transfer from session GT table to local arrays
2143   -- SQL Why : It will be used to mark the error records.
2144   -- SQL Join: key
2145   DELETE FROM PO_SESSION_GT
2146   WHERE  key = p_key
2147   RETURNING num1, num2, num3
2148   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_terms_id_list;
2149 
2150   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
2151 
2152   l_progress := '040';
2153   -- Mark the error records
2154   FOR i IN 1 .. l_indexes.COUNT
2155   LOOP
2156     l_index := l_indexes(i);
2157     p_headers_rec.has_errors(l_index) := 'Y';
2158 
2159     -- ECO bug 5584556: convert id to name
2160     l_progress := '050';
2161     get_ap_terms_name_from_id
2162     (
2163       p_terms_id   => l_err_terms_id_list(i)
2164     , x_terms_name => l_terms_name
2165     );
2166     -- ECO bug 5584556: End
2167 
2168     l_progress := '060';
2169     -- Add error message into INTERFACE_ERRORS table
2170     -- ICX_CAT_INVALID_PAY_TERMS
2171     -- "Default payment terms (VALUE) is inactive or invalid."
2172     PO_R12_CAT_UPG_UTL.add_fatal_error(
2173             p_interface_header_id => l_interface_header_ids(i),
2174             --p_error_message_name  => 'ICX_CAT_INVALID_TERMS_ID',
2175             p_error_message_name  => 'ICX_CAT_INVALID_PAY_TERMS', -- Bug 5461235
2176             p_table_name          => 'PO_HEADERS_INTERFACE',
2177             p_column_name         => 'TERMS_ID',
2178             p_column_value        => l_terms_name, -- ECO bug 5584556
2179             p_token1_name         => 'VALUE',
2180             p_token1_value        => l_err_terms_id_list(i)
2181             );
2182   END LOOP;
2183 
2184   l_progress := '070';
2185   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
2186 EXCEPTION
2187   WHEN OTHERS THEN
2188     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
2189     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
2190 END validate_terms_id;
2191 
2192 --------------------------------------------------------------------------------
2193 --Start of Comments
2194 --Name: validate_shipping_control
2195 --Pre-reqs:
2196 --  The iP catalog data is populated in input pl/sql tables.
2197 --Modifies:
2198 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
2199 --  b) FND_MSG_PUB on unhandled exceptions.
2200 --Locks:
2201 --  None.
2202 --Function:
2203 --  Validates shipping_control against PO_LOOKUP_CODES.
2204 --Parameters:
2205 --IN:
2206 --p_key
2207 --  Key used to access records in PO_SESSION_GT table.
2208 --IN/OUT:
2209 --p_headers_rec
2210 --  A record of plsql tables containing a batch of headers. If this validation
2211 --  fails, the 'has_errors' column is set to 'Y'.
2212 --OUT:
2213 --End of Comments
2214 --------------------------------------------------------------------------------
2215 PROCEDURE validate_shipping_control
2216 (
2217   p_key         IN NUMBER,
2218   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
2219 )
2220 IS
2221   l_api_name      CONSTANT VARCHAR2(30) := 'validate_shipping_control';
2222   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
2223   l_progress      VARCHAR2(3) := '000';
2224 
2225   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
2226 
2227   l_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2228   l_indexes              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2229   l_err_shipping_control_list PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR30;
2230 
2231   l_index NUMBER;
2232   i NUMBER;
2233   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2234 
2235   l_lookup_meaning PO_LOOKUP_CODES.displayed_field%TYPE;
2236 BEGIN
2237   l_progress := '010';
2238   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
2239   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Validating a defaulted field -- SHIP_VIA_LOOKUP_CODE (freight_carrier)'); END IF;
2240 
2241   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.shipping_control.COUNT);
2242 
2243   IF (p_headers_rec.shipping_control.COUNT > 0) THEN
2244     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.shipping_control(1)='||p_headers_rec.shipping_control(1)); END IF;
2245     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
2246     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
2247   END IF;
2248 
2249   l_progress := '020';
2250   -- SQL What: Bulk validate shipping_control against AP_TERMS.
2251   --           Get the errored rows into GT table.
2252   -- SQL Why : It will be used to mark the record in plsql table as error.
2253   -- SQL Join: ship_via_lookup_code
2254   FORALL i IN 1 .. p_headers_rec.shipping_control.COUNT
2255     INSERT INTO PO_SESSION_GT(key,
2256                               num1,
2257                               num2,
2258                               char1)
2259     SELECT p_key
2260          , l_subscript_array(i)
2261          , p_headers_rec.interface_header_id(i)
2262          , p_headers_rec.shipping_control(i)
2263     FROM DUAL
2264     WHERE --p_headers_rec.has_errors(i) = 'N'
2265     p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
2266     AND p_headers_rec.shipping_control(i) IS NOT NULL
2267     AND NOT EXISTS(
2268         SELECT 1
2269           FROM PO_LOOKUP_CODES PLC
2270          WHERE p_headers_rec.shipping_control(i) = PLC.lookup_code
2271            AND PLC.lookup_type = 'SHIPPING CONTROL'
2272            AND SYSDATE < NVL(PLC.inactive_date, SYSDATE + 1));
2273 
2274   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
2275 
2276   l_progress := '030';
2277   -- SQL What: Transfer from session GT table to local arrays
2278   -- SQL Why : It will be used to mark the error records.
2279   -- SQL Join: key
2280   DELETE FROM PO_SESSION_GT
2281   WHERE  key = p_key
2282   RETURNING num1, num2, char1
2283   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_shipping_control_list;
2284 
2285   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
2286 
2287   l_progress := '040';
2288   -- Mark the error records
2289   FOR i IN 1 .. l_indexes.COUNT
2290   LOOP
2291     l_index := l_indexes(i);
2292     p_headers_rec.has_errors(l_index) := 'Y';
2293 
2294     -- ECO bug 5584556: id-to-name conversion
2295     l_progress := '050';
2296     get_lookup_name_from_code
2297     (
2298       p_po_lookup_code => l_err_shipping_control_list(i)
2299     , p_po_lookup_type => 'SHIPPING CONTROL'
2300     , x_lookup_meaning => l_lookup_meaning
2301     );
2302     -- ECO bug 5584556: End
2303 
2304     l_progress := '060';
2305     -- Add error message into INTERFACE_ERRORS table
2306     -- ICX_CAT_INVALID_SHIPPING_CTRL:
2307     -- "Default shipping control (VALUE) is inactive or invalid."
2308     PO_R12_CAT_UPG_UTL.add_fatal_error(
2309             p_interface_header_id => l_interface_header_ids(i),
2310             p_error_message_name  => 'ICX_CAT_INVALID_SHIPPING_CTRL', -- ECO bug 5584556 'ICX_CAT_INVALID_SHIP_CONTROL'
2311             p_table_name          => 'PO_HEADERS_INTERFACE',
2312             p_column_name         => 'SHIPPING_CONTROL',
2313             p_column_value        => l_lookup_meaning, -- ECO bug 5584556
2314             p_token1_name         => 'VALUE',
2315             p_token1_value        => l_err_shipping_control_list(i)
2316             );
2317   END LOOP;
2318 
2319   l_progress := '070';
2320   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
2321 EXCEPTION
2322   WHEN OTHERS THEN
2323     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
2324     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
2325 END validate_shipping_control;
2326 
2327 -- Bug 5461235: Start
2328 --------------------------------------------------------------------------------
2329 --Start of Comments
2330 --Name: validate_rate_type_code
2331 --Pre-reqs:
2332 --  The iP catalog data is populated in input pl/sql tables.
2333 --Modifies:
2334 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
2335 --  b) FND_MSG_PUB on unhandled exceptions.
2336 --Locks:
2337 --  None.
2338 --Function:
2339 --  Validates rate_type_code against GL_DAILY_CONVERSION_TYPES_V.
2340 --Parameters:
2341 --IN:
2342 --p_key
2343 --  Key used to access records in PO_SESSION_GT table.
2344 --IN/OUT:
2345 --p_headers_rec
2346 --  A record of plsql tables containing a batch of headers. If this validation
2347 --  fails, the 'has_errors' column is set to 'Y'.
2348 --OUT:
2349 --End of Comments
2350 --------------------------------------------------------------------------------
2351 PROCEDURE validate_rate_type_code
2352 (
2353   p_key         IN NUMBER,
2354   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
2355 )
2356 IS
2357   l_api_name      CONSTANT VARCHAR2(30) := 'validate_rate_type_code';
2358   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
2359   l_progress      VARCHAR2(3) := '000';
2360 
2361   l_size NUMBER := p_headers_rec.interface_header_id.COUNT;
2362 
2363   l_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2364   l_indexes              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2365   l_err_rate_type_code_list PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR30;
2366 
2367   l_index NUMBER;
2368   i NUMBER;
2369   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2370 BEGIN
2371   l_progress := '010';
2372   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
2373 
2374   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_headers_rec.rate_type_code.COUNT);
2375 
2376   IF (p_headers_rec.rate_type_code.COUNT > 0) THEN
2377     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.rate_type_code(1)='||p_headers_rec.rate_type_code(1)); END IF;
2378     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.action(1)='||p_headers_rec.action(1)); END IF;
2379     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_headers_rec.has_errors(1)='||p_headers_rec.has_errors(1)); END IF;
2380   END IF;
2381 
2382   -- ECO bug 5584556: added new message
2383   -- Add a separate message for NULL value of rate_type_code
2384   l_progress := '020';
2385   FOR i IN 1 .. p_headers_rec.rate_type_code.COUNT
2386   LOOP
2387     IF ( (p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create)
2388      AND (p_headers_rec.currency_code(i) <> PO_R12_CAT_UPG_PVT.g_sys.currency_code)
2389      AND (p_headers_rec.rate_type_code(i) IS NULL) ) THEN
2390       -- ICX_CAT_RATE_TYPE_REQD:
2391       -- "The system cannot obtain the default value for the rate type."
2392       PO_R12_CAT_UPG_UTL.add_fatal_error(
2393               p_interface_header_id => p_headers_rec.interface_header_id(i),
2394               p_error_message_name  => 'ICX_CAT_RATE_TYPE_REQD',
2395               p_table_name          => 'PO_HEADERS_INTERFACE',
2396               p_column_name         => 'RATE_TYPE',
2397               p_column_value        => NULL,
2398               -- debug purposes only
2399               p_token1_name         => 'HEADER_CURRENCY',
2400               p_token1_value        => p_headers_rec.currency_code(i),
2401               p_token2_name         => 'FUNCTIONAL_CURRENCY',
2402               p_token2_value        => PO_R12_CAT_UPG_PVT.g_sys.currency_code
2403               );
2404     END IF;
2405   END LOOP;
2406   -- ECO bug 5584556: End
2407 
2408   l_progress := '030';
2409   -- SQL What: Bulk validate rate_type_code against GL_DAILY_CONVERSION_TYPES_V.
2410   --           Get the errored rows into GT table.
2411   -- SQL Why : It will be used to mark the record in plsql table as error.
2412   -- SQL Join: rate_type
2413   FORALL i IN 1 .. p_headers_rec.rate_type_code.COUNT
2414     INSERT INTO PO_SESSION_GT(key,
2415                               num1,
2416                               num2,
2417                               char1)
2418     SELECT p_key
2419          , l_subscript_array(i)
2420          , p_headers_rec.interface_header_id(i)
2421          , p_headers_rec.rate_type_code(i)
2422     FROM DUAL
2423     WHERE --p_headers_rec.has_errors(i) = 'N'
2424         p_headers_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_header_create --Bug#5018883
2425     AND p_headers_rec.currency_code(i) <> PO_R12_CAT_UPG_PVT.g_sys.currency_code
2426     AND p_headers_rec.rate_type_code(i) IS NOT NULL
2427     AND NOT EXISTS(
2428         SELECT 'Rate type exists'
2429           FROM GL_DAILY_CONVERSION_TYPES_V GLDCT
2430          WHERE GLDCT.conversion_type = p_headers_rec.rate_type_code(i));
2431 
2432   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
2433 
2434   l_progress := '040';
2435   -- SQL What: Transfer from session GT table to local arrays
2436   -- SQL Why : It will be used to mark the error records.
2437   -- SQL Join: key
2438   DELETE FROM PO_SESSION_GT
2439   WHERE  key = p_key
2440   RETURNING num1, num2, char1
2441   BULK COLLECT INTO l_indexes, l_interface_header_ids, l_err_rate_type_code_list;
2442 
2443   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
2444 
2445   l_progress := '050';
2446   -- Mark the error records
2447   FOR i IN 1 .. l_indexes.COUNT
2448   LOOP
2449     l_index := l_indexes(i);
2450     p_headers_rec.has_errors(l_index) := 'Y';
2451 
2452     -- Add error message into INTERFACE_ERRORS table
2453     -- ICX_CAT_INVALID_RATE_TYPE:
2454     -- "Default rate type (VALUE) is inactive or invalid."
2455     PO_R12_CAT_UPG_UTL.add_fatal_error(
2456             p_interface_header_id => l_interface_header_ids(i),
2457             p_error_message_name  => 'ICX_CAT_INVALID_RATE_TYPE',
2458             p_table_name          => 'PO_HEADERS_INTERFACE',
2459             p_column_name         => 'RATE_TYPE',
2460             p_column_value        => l_err_rate_type_code_list(i),
2461             p_token1_name         => 'VALUE',
2462             p_token1_value        => l_err_rate_type_code_list(i)
2463             );
2464   END LOOP;
2465 
2466   l_progress := '060';
2467   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
2468 EXCEPTION
2469   WHEN OTHERS THEN
2470     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
2471     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
2472 END validate_rate_type_code;
2473 -- Bug 5461235: End
2474 
2475 --------------------------------------------------------------------------------
2476 --Start of Comments
2477 --Name: validate_headers
2478 --Pre-reqs:
2479 --  The iP catalog data is populated in input pl/sql tables.
2480 --Modifies:
2481 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
2482 --  b) FND_MSG_PUB on unhandled exceptions.
2483 --Locks:
2484 --  None.
2485 --Function:
2486 --  This is the main function to validate headers. It calls the following
2487 --  procedures:
2488 --
2489 --     validate_buyer
2490 --     validate_currency_code
2491 --     validate_vendor_info
2492 --     validate_expiration_date
2493 --     validate_ship_to_location_id
2494 --     validate_bill_to_location_id
2495 --     validate_fob_lookup_code
2496 --     validate_ship_via_luc
2497 --     validate_freight_terms
2498 --     validate_terms_id
2499 --     validate_shipping_control
2500 --     validate_rate_type_code
2501 --
2502 --Parameters:
2503 --IN/OUT:
2504 --p_headers_rec
2505 --  A record of plsql tables containing a batch of headers. If this validation
2506 --  fails, the 'has_errors' column is set to 'Y'.
2507 --OUT:
2508 --End of Comments
2509 --------------------------------------------------------------------------------
2510 PROCEDURE validate_headers
2511 (
2512   p_headers_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_headers_type
2513 )
2514 IS
2515   l_api_name      CONSTANT VARCHAR2(30) := 'validate_headers';
2516   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
2517   l_progress      VARCHAR2(3) := '000';
2518 
2519   l_key PO_SESSION_GT.key%TYPE;
2520   i NUMBER;
2521 BEGIN
2522   l_progress := '010';
2523   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
2524 
2525   -- pick a new key from temp table which will be used in all validate logic
2526   SELECT PO_SESSION_GT_S.nextval
2527   INTO l_key
2528   FROM DUAL;
2529 
2530   l_progress := '020';
2531   -- validate that agent_id is not null
2532   validate_buyer
2533   (
2534     p_headers_rec => p_headers_rec
2535   );
2536 
2537   l_progress := '030';
2538   -- validate currency_code not null and against FND_CURRENCIES.
2539   validate_currency_code
2540   (
2541     p_key         => l_key,
2542     p_headers_rec => p_headers_rec
2543   );
2544 
2545   l_progress := '040';
2546   -- validate vendorId is Not Null
2547   -- validate vendorSiteId is Not Null
2548   -- validate vendor_id using PO_SUPPLIERS_VAL_V
2549   -- validate vendor_site_id using PO_SUPPLIER_SITES_VAL_V
2550   -- validate vendor_contact_id using PO_VENDOR_CONTACTS
2551   -- validate vendor site CCR if approval status is APPROVED.
2552   validate_vendor_info
2553   (
2554     p_key         => l_key,
2555     p_headers_rec => p_headers_rec
2556   );
2557 
2558   l_progress := '050';
2559   -- validate that end_date is greater than the start_date
2560   validate_expiration_date
2561   (
2562     p_headers_rec => p_headers_rec
2563   );
2564 
2565   l_progress := '060';
2566   -- validate ship_to_location_id not null and against HR_LOCATIONS.
2567   validate_ship_to_location_id
2568   (
2569     p_key         => l_key,
2570     p_headers_rec => p_headers_rec
2571   );
2572 
2573   l_progress := '070';
2574   -- validate bill_to_location_id not null and against HR_LOCATIONS.
2575   validate_bill_to_location_id
2576   (
2577     p_key         => l_key,
2578     p_headers_rec => p_headers_rec
2579   );
2580 
2581   l_progress := '080';
2582   validate_fob_lookup_code
2583   (
2584     p_key         => l_key,
2585     p_headers_rec => p_headers_rec
2586   );
2587 
2588   l_progress := '090';
2589   validate_ship_via_luc
2590   (
2591     p_key         => l_key,
2592     p_headers_rec => p_headers_rec
2593   );
2594 
2595   l_progress := '100';
2596   validate_freight_terms
2597   (
2598     p_key         => l_key,
2599     p_headers_rec => p_headers_rec
2600   );
2601 
2602   l_progress := '110';
2603   validate_terms_id
2604   (
2605     p_key         => l_key,
2606     p_headers_rec => p_headers_rec
2607   );
2608 
2609   l_progress := '120';
2610   validate_shipping_control
2611   (
2612     p_key         => l_key,
2613     p_headers_rec => p_headers_rec
2614   );
2615 
2616   l_progress := '130';
2617   -- Bug 5461235
2618   validate_rate_type_code
2619   (
2620     p_key         => l_key,
2621     p_headers_rec => p_headers_rec
2622   );
2623 
2624   l_progress := '140';
2625   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
2626 EXCEPTION
2627   WHEN OTHERS THEN
2628     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
2629     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
2630 END validate_headers;
2631 
2632 --------------------------------------------------------------------------------
2633 --Start of Comments
2634 --Name: validate_item
2635 --Pre-reqs:
2636 --  The iP catalog data is populated in input pl/sql tables.
2637 --Modifies:
2638 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
2639 --  b) FND_MSG_PUB on unhandled exceptions.
2640 --Locks:
2641 --  None.
2642 --Function:
2643 --  Checks that if item id is not null, that it exists in
2644 --  MTL_SYSTEM_ITEMS table.
2645 --Parameters:
2646 --IN:
2647 --p_key
2648 --  Key used to access records in PO_SESSION_GT table.
2649 --IN/OUT:
2650 --p_lines_rec
2651 --  A record of plsql tables containing a batch of lines. If this validation
2652 --  fails, the 'has_errors' column is set to 'Y'.
2653 --OUT:
2654 --End of Comments
2655 --------------------------------------------------------------------------------
2656 PROCEDURE validate_item
2657 (
2658   p_key       IN NUMBER,
2659   p_lines_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_lines_type
2660 )
2661 IS
2662   l_api_name      CONSTANT VARCHAR2(30) := 'validate_item';
2663   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
2664   l_progress      VARCHAR2(3) := '000';
2665 
2666   l_size NUMBER := p_lines_rec.interface_line_id.COUNT;
2667 
2668   l_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2669   l_interface_line_ids   PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2670   l_indexes              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2671   l_item_id_list         PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2672 
2673   l_index NUMBER;
2674   i NUMBER;
2675   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2676 BEGIN
2677   l_progress := '010';
2678   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
2679 
2680   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_lines_rec.item_id.COUNT);
2681 
2682   l_progress := '020';
2683   -- SQL What: Bulk validate item_id. If item id is not null, it has to exist
2684   --           in mtl_system_items table.
2685   --           Insert the error rows into GT table.
2686   -- SQL Why : It will be used to mark the record in plsql table as error.
2687   -- SQL Join: item_id
2688   FORALL i IN 1 .. p_lines_rec.item_id.COUNT
2689     INSERT INTO PO_SESSION_GT(key,
2690                               num1,
2691                               num2,
2692                               num3,
2693                               num4)
2694     SELECT p_key
2695          , l_subscript_array(i)
2696          , p_lines_rec.interface_header_id(i)
2697          , p_lines_rec.interface_line_id(i)
2698          , p_lines_rec.item_id(i)
2699     FROM PO_LINE_TYPES_B PLT
2700     WHERE --p_lines_rec.has_errors(i) = 'N'
2701       p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE')
2702       AND p_lines_rec.item_id(i) is not null
2703       AND p_lines_rec.line_type_id(i) is not null
2704       AND p_lines_rec.line_type_id(i)= PLT.line_type_id
2705       AND PLT.outside_operation_flag is not null
2706       AND NOT EXISTS (SELECT 1
2707                FROM MTL_SYSTEM_ITEMS MSI
2708                WHERE MSI.inventory_item_id = p_lines_rec.item_id(i)
2709                AND MSI.organization_id = PO_R12_CAT_UPG_PVT.g_sys.inv_org_id
2710                AND MSI.enabled_flag = 'Y'
2711                AND MSI.purchasing_item_flag = 'Y'
2712                AND MSI.purchasing_enabled_flag = 'Y'
2713                AND MSI.outside_operation_flag = PLT.outside_operation_flag
2714                AND TRUNC(nvl(MSI.start_date_active, sysdate))<= TRUNC(sysdate)
2715                AND TRUNC(nvl(MSI.end_date_active, sysdate)) >= TRUNC(sysdate));
2716 
2717   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
2718 
2719   l_progress := '030';
2720   -- SQL What: Transfer from session GT table to local arrays
2721   -- SQL Why : It will be used to mark the error records.
2722   -- SQL Join: key
2723   DELETE FROM PO_SESSION_GT
2724   WHERE  key = p_key
2725   RETURNING num1, num2, num3, num4
2726   BULK COLLECT INTO l_indexes, l_interface_header_ids,
2727                     l_interface_line_ids, l_item_id_list;
2728 
2729   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
2730 
2731   l_progress := '040';
2732   -- Mark the error records
2733   FOR i IN 1 .. l_indexes.COUNT
2734   LOOP
2735     l_index := l_indexes(i);
2736 
2737     -- For bulkloaded items, there is no issue since there is no item number.
2738     -- For extracted item, the item is in a PO document. Whatever happens to
2739     -- the item, the document is still valid. User is not going to fix
2740     -- existing PO documents for invalid items. Keep item as it is and dont
2741     -- give any exception.
2742     --p_lines_rec.has_errors(l_index) := 'Y';
2743 
2744     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Ignoring validation error in ITEM_ID='||l_item_id_list(i)); END IF;
2745 
2746     -- Add error message into INTERFACE_ERRORS table
2747     -- PO_PDOI_INVALID_ITEM_ID:
2748     -- "ITEM ID (VALUE =VALUE) is not a valid purchasable item."
2749     --PO_R12_CAT_UPG_UTL.add_fatal_error(
2750     --        p_interface_header_id => l_interface_header_ids(i),
2751     --        p_interface_line_id   => l_interface_line_ids(i),
2752     --        p_error_message_name  => 'PO_PDOI_INVALID_ITEM_ID',
2753     --        p_table_name          => 'PO_LINES_INTERFACE',
2754     --        p_column_name         => 'ITEM_ID',
2755     --        p_column_value        => l_item_id_list(i),
2756     --        p_token1_name         => 'VALUE',
2757     --        p_token1_value        => l_item_id_list(i)
2758     --        );
2759   END LOOP;
2760 
2761   l_progress := '050';
2762   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
2763 EXCEPTION
2764   WHEN OTHERS THEN
2765     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
2766     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
2767 END validate_item;
2768 
2769 
2770 --------------------------------------------------------------------------------
2771 --Start of Comments
2772 --Name: validate_item_description
2773 --Pre-reqs:
2774 --  The iP catalog data is populated in input pl/sql tables.
2775 --Modifies:
2776 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
2777 --  b) FND_MSG_PUB on unhandled exceptions.
2778 --Locks:
2779 --  None.
2780 --Function:
2781 -- Make sure that the item_description is populated, and also need to find out
2782 -- if it is different from what is setup for the item.
2783 --Parameters:
2784 --IN:
2785 --p_key
2786 --  Key used to access records in PO_SESSION_GT table.
2787 --IN/OUT:
2788 --p_lines_rec
2789 --  A record of plsql tables containing a batch of lines. If this validation
2790 --  fails, the 'has_errors' column is set to 'Y'.
2791 --OUT:
2792 --End of Comments
2793 --------------------------------------------------------------------------------
2794 PROCEDURE validate_item_description
2795 (
2796   p_key       IN NUMBER,
2797   p_lines_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_lines_type
2798 )
2799 IS
2800   l_api_name      CONSTANT VARCHAR2(30) := 'validate_item_description';
2801   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
2802   l_progress      VARCHAR2(3) := '000';
2803 
2804   l_size NUMBER := p_lines_rec.interface_line_id.COUNT;
2805 
2806   l_interface_header_ids  PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2807   l_interface_line_ids    PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2808   l_indexes               PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2809   l_item_description_list PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR240;
2810 
2811   l_index NUMBER;
2812   i NUMBER;
2813   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2814 BEGIN
2815   l_progress := '010';
2816   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
2817 
2818   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_lines_rec.item_id.COUNT);
2819 
2820   l_progress := '020';
2821   -- SQL What: Bulk validate item_description. Make sure that the
2822   --           item_description is populated, and also need to find out if it
2823   --           is different from what is setup for the item.
2824   --           Insert the error rows into GT table.
2825   -- SQL Why : It will be used to mark the record in plsql table as error.
2826   -- SQL Join: item_id
2827   FORALL i IN 1 .. p_lines_rec.item_id.COUNT
2828     INSERT INTO PO_SESSION_GT(key,
2829                               num1,
2830                               num2,
2831                               num3,
2832                               char1)
2833     SELECT p_key
2834          , l_subscript_array(i)
2835          , p_lines_rec.interface_header_id(i)
2836          , p_lines_rec.interface_line_id(i)
2837          , p_lines_rec.item_description(i)
2838     FROM DUAL
2839     WHERE --p_lines_rec.has_errors(i) = 'N'
2840       p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE')
2841       AND (p_lines_rec.item_description(i) is null OR
2842           (p_lines_rec.item_id(i) is not null AND
2843            EXISTS (SELECT 1
2844                   FROM MTL_SYSTEM_ITEMS MSI
2845                   WHERE MSI.inventory_item_id = p_lines_rec.item_id(i)
2846                   AND MSI.organization_id = PO_R12_CAT_UPG_PVT.g_sys.inv_org_id
2847                   AND MSI.allow_item_desc_update_flag = 'N'
2848                   AND p_lines_rec.item_description(i) <> MSI.description)));
2849                   --AND create_or_update_item_flag = 'N'))); its a parameter to PDOI, For catalog migration, it would always be 'N'
2850 
2851   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
2852 
2853   l_progress := '030';
2854   -- SQL What: Transfer from session GT table to local arrays
2855   -- SQL Why : It will be used to mark the error records.
2856   -- SQL Join: key
2857   DELETE FROM PO_SESSION_GT
2858   WHERE  key = p_key
2859   RETURNING num1, num2, num3, char1
2860   BULK COLLECT INTO l_indexes, l_interface_header_ids,
2861                     l_interface_line_ids, l_item_description_list;
2862 
2863   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
2864 
2865   l_progress := '040';
2866   -- Mark the error records
2867   FOR i IN 1 .. l_indexes.COUNT
2868   LOOP
2869     l_index := l_indexes(i);
2870 
2871     -- Do not give an error. In this case, ignore the description that comes from iP.
2872     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Ignoring the validation error of item description for ITEM_ID='||p_lines_rec.item_id(l_index)||'. Also ignoring the item description from interface table'); END IF;
2873     p_lines_rec.item_description(l_index) := NULL;
2874 
2875     --p_lines_rec.has_errors(l_index) := 'Y';
2876 
2877     -- Add error message into INTERFACE_ERRORS table
2878     -- PO_PDOI_DIFF_ITEM_DESC:
2879     -- "Pre-defined item description cannot be changed for this item."
2880     --PO_R12_CAT_UPG_UTL.add_fatal_error(
2881     --        p_interface_header_id => l_interface_header_ids(i),
2882     --        p_interface_line_id   => l_interface_line_ids(i),
2883     --        p_error_message_name  => 'PO_PDOI_DIFF_ITEM_DESC',
2884     --        p_table_name          => 'PO_LINES_INTERFACE',
2885     --        p_column_name         => 'ITEM_DESCRIPTION',
2886     --        p_column_value        => l_item_description_list(i)
2887     --        );
2888   END LOOP;
2889 
2890   l_progress := '050';
2891   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
2892 EXCEPTION
2893   WHEN OTHERS THEN
2894     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
2895     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
2896 END validate_item_description;
2897 
2898 --------------------------------------------------------------------------------
2899 --Start of Comments
2900 --Name: validate_uom
2901 --Pre-reqs:
2902 --  The iP catalog data is populated in input pl/sql tables.
2903 --Modifies:
2904 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
2905 --  b) FND_MSG_PUB on unhandled exceptions.
2906 --Locks:
2907 --  None.
2908 --Function:
2909 -- check to see if unit_meas_lookup_code is valid in mtl_item_uoms_view
2910 --Parameters:
2911 --IN:
2912 --p_key
2913 --  Key used to access records in PO_SESSION_GT table.
2914 --IN/OUT:
2915 --p_lines_rec
2916 --  A record of plsql tables containing a batch of lines. If this validation
2917 --  fails, the 'has_errors' column is set to 'Y'.
2918 --OUT:
2919 --End of Comments
2920 --------------------------------------------------------------------------------
2921 PROCEDURE validate_uom
2922 (
2923   p_key       IN NUMBER,
2924   p_lines_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_lines_type
2925 )
2926 IS
2927   l_api_name      CONSTANT VARCHAR2(30) := 'validate_uom';
2928   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
2929   l_progress      VARCHAR2(3) := '000';
2930 
2931   l_size NUMBER := p_lines_rec.interface_line_id.COUNT;
2932 
2933   l_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2934   l_interface_line_ids   PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2935   l_indexes              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2936   l_unit_of_measure_list PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR25;
2937   l_uom_code_list        PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR3;
2938 
2939   l_index NUMBER;
2940   i NUMBER;
2941   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
2942 BEGIN
2943   l_progress := '010';
2944   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
2945 
2946   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_lines_rec.item_id.COUNT);
2947 
2948   IF (p_lines_rec.unit_of_measure.COUNT > 0) THEN
2949     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_lines_rec.unit_of_measure(1)='||p_lines_rec.unit_of_measure(1)); END IF;
2950     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_lines_rec.uom_code(1)='||p_lines_rec.uom_code(1)); END IF;
2951   END IF;
2952 
2953   -- ECO bug 5584556: Add new messages
2954   -- uom_code must not be NULL. iP populates uom_code.
2955   FOR i IN 1 .. p_lines_rec.uom_code.COUNT
2956   LOOP
2957     l_progress := '050';
2958     IF (--p_lines_rec.has_errors(i) = 'N' AND
2959 
2960         -- Bug 5060582: UNIT_OF_MEASURE is updatable when CREATED_BY = -12.
2961         -- If it is specified as NULL in INTF table, then the column
2962         -- remains unchanged in TXN table. This is handled via a DECODE in the
2963         -- UPDATE statement, later in the flow. So allow NULL value in UPDATE flow
2964         -- where CREATED_BY is NOT -12.
2965         --p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE') AND
2966         (   p_lines_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_line_create
2967          OR
2968             (p_lines_rec.action(i) = 'UPDATE' AND
2969              p_lines_rec.created_by(i) = PO_R12_CAT_UPG_PVT.g_R12_UPGRADE_USER)
2970         )
2971         AND
2972         p_lines_rec.uom_code(i) IS NULL) THEN
2973 
2974       l_progress := '060';
2975       p_lines_rec.has_errors(i) := 'Y';
2976 
2977       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'CREATED_BY='||p_lines_rec.created_by(i)||', ACTION='||p_lines_rec.action(i)); END IF;
2978 
2979       -- Add error message into INTERFACE_ERRORS table
2980       -- ECO bug 5584556: Add new messages
2981       -- ICX_CAT_UOM_CODE_REQD:
2982       -- "Unit of measure is missing for one or more lines."
2983       PO_R12_CAT_UPG_UTL.add_fatal_error(
2984             p_interface_header_id => p_lines_rec.interface_header_id(i),
2985             p_interface_line_id   => p_lines_rec.interface_line_id(i),
2986             p_error_message_name  => 'ICX_CAT_UOM_CODE_REQD',
2987             p_table_name          => 'PO_LINES_INTERFACE',
2988             p_column_name         => 'UOM_CODE',
2989             p_column_value        => p_lines_rec.uom_code(i)
2990             );
2991     END IF;
2992   END LOOP;
2993   -- ECO bug 5584556: End
2994 
2995   -- Derive unit_of_measure from uom_code
2996   FOR i IN 1 .. p_lines_rec.uom_code.COUNT
2997   LOOP
2998     l_progress := '020';
2999     IF (--p_lines_rec.has_errors(i) = 'N' AND
3000         p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE') AND
3001         p_lines_rec.unit_of_measure(i) IS NULL AND
3002         p_lines_rec.uom_code(i) IS NOT NULL) THEN
3003 
3004       l_progress := '030';
3005       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Deriving unit_of_measure for uom_code='||p_lines_rec.uom_code(i)); END IF;
3006 
3007       BEGIN
3008         SELECT unit_of_measure
3009           INTO p_lines_rec.unit_of_measure(i)
3010           FROM PO_UNITS_OF_MEASURE_VAL_V
3011          WHERE uom_code = p_lines_rec.uom_code(i)
3012            -- ECO bug 5584556: This validation is already done above.
3013            -- So skip these cases.
3014            AND uom_code IS NOT NULL;
3015            -- ECO bug 5584556: End
3016       EXCEPTION
3017         WHEN OTHERS THEN
3018           p_lines_rec.unit_of_measure(i) := NULL;
3019       END;
3020 
3021       l_progress := '040';
3022       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'unit_of_measure='||p_lines_rec.unit_of_measure(i)); END IF;
3023     END IF;
3024   END LOOP;
3025 
3026   -- unit_of_measure must not be NULL
3027   FOR i IN 1 .. p_lines_rec.unit_of_measure.COUNT
3028   LOOP
3029     l_progress := '050';
3030     IF (--p_lines_rec.has_errors(i) = 'N' AND
3031 
3032         -- Bug 5060582: UNIT_OF_MEASURE is updatable when CREATED_BY = -12.
3033         -- If it is specified as NULL in INTF table, then the column
3034         -- remains unchanged in TXN table. This is handled via a DECODE in the
3035         -- UPDATE statement, later in the flow. So allow NULL value in UPDATE flow
3036         -- where CREATED_BY is NOT -12.
3037         --p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE') AND
3038         (   p_lines_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_line_create
3039          OR
3040             (p_lines_rec.action(i) = 'UPDATE' AND
3041              p_lines_rec.created_by(i) = PO_R12_CAT_UPG_PVT.g_R12_UPGRADE_USER)
3042         )
3043         AND p_lines_rec.unit_of_measure(i) IS NULL
3044         -- ECO bug 5584556: This validation is already done above.
3045         -- So skip these cases.
3046         AND p_lines_rec.uom_code(i) IS NOT NULL) THEN
3047         -- ECO bug 5584556: End
3048 
3049       l_progress := '060';
3050       p_lines_rec.has_errors(i) := 'Y';
3051 
3052       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'CREATED_BY='||p_lines_rec.created_by(i)||', ACTION='||p_lines_rec.action(i)); END IF;
3053 
3054       -- Add error message into INTERFACE_ERRORS table
3055       -- ECO bug 5584556: Add new messages
3056       -- ICX_CAT_INVALID_UOM_CODE:
3057       -- "The following unit of measure codes are inactive or invalid: VALUE, VALUE"
3058       PO_R12_CAT_UPG_UTL.add_fatal_error(
3059             p_interface_header_id => p_lines_rec.interface_header_id(i),
3060             p_interface_line_id   => p_lines_rec.interface_line_id(i),
3061             p_error_message_name  => 'ICX_CAT_INVALID_UOM_CODE',
3062             p_table_name          => 'PO_LINES_INTERFACE',
3063             p_column_name         => 'UOM_CODE',
3064             p_column_value        => p_lines_rec.uom_code(i),
3065             p_token1_name         => 'VALUE',
3066             p_token1_value        => p_lines_rec.uom_code(i)
3067             );
3068     END IF;
3069   END LOOP;
3070 
3071   l_progress := '070';
3072   -- SQL What: Bulk validate UOM. Check if unit_meas_lookup_code is valid
3073   --           in MTL_ITEM_UOMS_VIEW.
3074   --           Insert the error rows into GT table.
3075   -- SQL Why : It will be used to mark the record in plsql table as error.
3076   -- SQL Join: item_id, unit_of_measure, inv_org_id
3077   FORALL i IN 1 .. p_lines_rec.item_id.COUNT
3078     INSERT INTO PO_SESSION_GT(key,
3079                               num1,
3080                               num2,
3081                               num3,
3082                               char1,
3083                               char2)
3084     SELECT p_key
3085          , l_subscript_array(i)
3086          , p_lines_rec.interface_header_id(i)
3087          , p_lines_rec.interface_line_id(i)
3088          , p_lines_rec.unit_of_measure(i)
3089          , p_lines_rec.uom_code(i)
3090     FROM DUAL
3091     WHERE --p_lines_rec.has_errors(i) = 'N'
3092     p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE')
3093     AND p_lines_rec.unit_of_measure(i) is not null
3094     AND p_lines_rec.uom_code(i) is not null
3095     AND ( (p_lines_rec.item_id(i) is not null
3096            AND NOT EXISTS (SELECT 1
3097                              FROM MTL_ITEM_UOMS_VIEW MIUV
3098                             WHERE MIUV.inventory_item_id = p_lines_rec.item_id(i)
3099                               AND MIUV.organization_id = PO_R12_CAT_UPG_PVT.g_sys.inv_org_id
3100                               AND MIUV.unit_of_measure = p_lines_rec.unit_of_measure(i)))
3101          OR
3102           (p_lines_rec.item_id(i) is null
3103            AND NOT EXISTS (SELECT 1
3104                              FROM MTL_UNITS_OF_MEASURE MUOM
3105                             WHERE MUOM.unit_of_measure = p_lines_rec.unit_of_measure(i)
3106                               AND sysdate < NVL(disable_date, sysdate+1))));
3107 
3108   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
3109 
3110   l_progress := '080';
3111   -- SQL What: Transfer from session GT table to local arrays
3112   -- SQL Why : It will be used to mark the error records.
3113   -- SQL Join: key
3114   DELETE FROM PO_SESSION_GT
3115   WHERE  key = p_key
3116   RETURNING num1, num2, num3, char1, char2
3117   BULK COLLECT INTO l_indexes, l_interface_header_ids,
3118                     l_interface_line_ids, l_unit_of_measure_list, l_uom_code_list;
3119 
3120   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
3121 
3122   l_progress := '090';
3123   -- Mark the error records
3124   FOR i IN 1 .. l_indexes.COUNT
3125   LOOP
3126     l_index := l_indexes(i);
3127     p_lines_rec.has_errors(l_index) := 'Y';
3128 
3129     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: unit_of_measure='||l_unit_of_measure_list(i)||', uom_code='||l_uom_code_list(i)); END IF;
3130 
3131     -- Add error message into INTERFACE_ERRORS table
3132     -- ICX_CAT_INVALID_UOM_CODE:
3133     -- "The following unit of measure codes are inactive or invalid: VALUE, VALUE"
3134     PO_R12_CAT_UPG_UTL.add_fatal_error(
3135             p_interface_header_id => l_interface_header_ids(i),
3136             p_interface_line_id   => l_interface_line_ids(i),
3137             --p_error_message_name  => 'PO_PDOI_INVALID_UOM_CODE',
3138             p_error_message_name  => 'ICX_CAT_INVALID_UOM_CODE',
3139             p_table_name          => 'PO_LINES_INTERFACE',
3140             p_column_name         => 'UOM_CODE',
3141             p_column_value        => l_uom_code_list(i),
3142             p_token1_name         => 'VALUE',
3143             p_token1_value        => l_uom_code_list(i)
3144             );
3145   END LOOP;
3146 
3147   l_progress := '100';
3148   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
3149 EXCEPTION
3150   WHEN OTHERS THEN
3151     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
3152     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
3153 END validate_uom;
3154 
3155 --------------------------------------------------------------------------------
3156 --Start of Comments
3157 --Name: validate_item_revision
3158 --Pre-reqs:
3159 --  The iP catalog data is populated in input pl/sql tables.
3160 --Modifies:
3161 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
3162 --  b) FND_MSG_PUB on unhandled exceptions.
3163 --Locks:
3164 --  None.
3165 --Function:
3166 -- If order_type_lookup_code is FIXED PRICE or RATE, or item id is null,
3167 -- then item revision has to be NULL
3168 -- Check to see if the item_revision exists in mtl_item_revisions table
3169 --Parameters:
3170 --IN:
3171 --p_key
3172 --  Key used to access records in PO_SESSION_GT table.
3173 --IN/OUT:
3174 --p_lines_rec
3175 --  A record of plsql tables containing a batch of lines. If this validation
3176 --  fails, the 'has_errors' column is set to 'Y'.
3177 --OUT:
3178 --End of Comments
3179 --------------------------------------------------------------------------------
3180 PROCEDURE validate_item_revision
3181 (
3182   p_key       IN NUMBER,
3183   p_lines_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_lines_type
3184 )
3185 IS
3186   l_api_name      CONSTANT VARCHAR2(30) := 'validate_item_revision';
3187   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
3188   l_progress      VARCHAR2(3) := '000';
3189 
3190   l_size NUMBER := p_lines_rec.interface_line_id.COUNT;
3191 
3192   l_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3193   l_interface_line_ids   PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3194   l_indexes              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3195   l_item_id_list         PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3196   l_item_revision_list   PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR3;
3197 
3198   l_index NUMBER;
3199   i NUMBER;
3200   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3201 BEGIN
3202   l_progress := '010';
3203   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
3204 
3205   -- if item id is null, then item revision has to be NULL
3206   FOR i IN 1 .. p_lines_rec.item_revision.COUNT
3207   LOOP
3208     l_progress := '020';
3209     IF (--p_lines_rec.has_errors(i) = 'N' AND
3210         p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE') AND
3211         p_lines_rec.item_id(i) IS NULL AND
3212         p_lines_rec.item_revision(i) IS NOT NULL) THEN
3213 
3214       l_progress := '030';
3215 
3216       -- If this happens, ignore the revision for a non-inventory item. Dont give any exception.
3217       --p_lines_rec.has_errors(i) := 'Y';
3218       p_lines_rec.item_revision(i) := NULL;
3219 
3220       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Ignoring item_revision for interface_lien-id='||p_lines_rec.interface_line_id(i)||' because item_id is NULL'); END IF;
3221 
3222       -- Add error message into INTERFACE_ERRORS table
3223       --PO_R12_CAT_UPG_UTL.add_fatal_error(
3224       --      p_interface_header_id => p_lines_rec.interface_header_id(i),
3225       --      p_interface_line_id   => p_lines_rec.interface_line_id(i),
3226       --      p_error_message_name  => 'PO_COLUMN_NOT_NULL',
3227       --      p_table_name          => 'PO_LINES_INTERFACE',
3228       --      p_column_name         => 'ITEM_REVISION',
3229       --      p_column_value        => p_lines_rec.item_revision(i)
3230       --      );
3231     END IF;
3232   END LOOP;
3233 
3234   l_progress := '040';
3235   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_lines_rec.item_id.COUNT);
3236 
3237   l_progress := '050';
3238   -- SQL What: Bulk validate item revision. Check to see if the item_revision
3239   --           exists in MTL_ITEM_REVISIONS table.
3240   --           Insert the error rows into GT table.
3241   -- SQL Why : It will be used to mark the record in plsql table as error.
3242   -- SQL Join: item_id, item_revision
3243   FORALL i IN 1 .. p_lines_rec.item_id.COUNT
3244     INSERT INTO PO_SESSION_GT(key,
3245                               num1,
3246                               num2,
3247                               num3,
3248                               num4,
3249                               char1)
3250     SELECT p_key
3251          , l_subscript_array(i)
3252          , p_lines_rec.interface_header_id(i)
3253          , p_lines_rec.interface_line_id(i)
3254          , p_lines_rec.item_id(i)
3255          , p_lines_rec.item_revision(i)
3256     FROM DUAL
3257     WHERE --p_lines_rec.has_errors(i) = 'N'
3258       p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE')
3259       AND p_lines_rec.item_revision(i) is not null
3260       AND p_lines_rec.item_id(i) is not null
3261       AND NOT EXISTS (SELECT 1
3262                      FROM MTL_ITEM_REVISIONS MIR
3263                      WHERE MIR.inventory_item_id = p_lines_rec.item_id(i)
3264                        AND MIR.revision = p_lines_rec.item_revision(i));
3265 
3266   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
3267 
3268   l_progress := '060';
3269   -- SQL What: Transfer from session GT table to local arrays
3270   -- SQL Why : It will be used to mark the error records.
3271   -- SQL Join: key
3272   DELETE FROM PO_SESSION_GT
3273   WHERE  key = p_key
3274   RETURNING num1, num2, num3, num4, char1
3275   BULK COLLECT INTO l_indexes, l_interface_header_ids,
3276                     l_interface_line_ids, l_item_id_list, l_item_revision_list;
3277 
3278   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
3279 
3280   l_progress := '070';
3281   -- Mark the error records
3282   FOR i IN 1 .. l_indexes.COUNT
3283   LOOP
3284     l_index := l_indexes(i);
3285 
3286     -- Same as item ID. Keep item as it is and dont give any exception
3287     --p_lines_rec.has_errors(l_index) := 'Y';
3288     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Ignoring the validation error of Item Revision '|| l_item_revision_list(i) ||' for ITEM_ID='||l_item_id_list(i)); END IF;
3289 
3290     -- Add error message into INTERFACE_ERRORS table
3291     -- PO_PDOI_ITEM_RELATED_INFO:
3292     -- "COLUMN_NAME (VALUE=VALUE) specified is inactive or invalid for item_id (VALUE=ITEM)."
3293     --PO_R12_CAT_UPG_UTL.add_fatal_error(
3294     --        p_interface_header_id => l_interface_header_ids(i),
3295     --        p_interface_line_id   => l_interface_line_ids(i),
3296     --        p_error_message_name  => 'PO_PDOI_ITEM_RELATED_INFO',
3297     --        p_table_name          => 'PO_LINES_INTERFACE',
3298     --        p_column_name         => 'ITEM_REVISION',
3299     --        p_column_value        => l_item_revision_list(i),
3300     --        p_token1_name         => 'COLUMN_NAME',
3301     --        p_token1_value        => 'ITEM_REVISION',
3302     --        p_token2_name         => 'VALUE',
3303     --        p_token2_value        => l_item_revision_list(i),
3304     --        p_token3_name         => 'ITEM',
3305     --        p_token4_value        => l_item_id_list(i)
3306     --        );
3307   END LOOP;
3308 
3309   l_progress := '080';
3310   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
3311 EXCEPTION
3312   WHEN OTHERS THEN
3313     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
3314     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
3315 END validate_item_revision;
3316 
3317 --------------------------------------------------------------------------------
3318 --Start of Comments
3319 --Name: get_category_name_from_id
3320 --Pre-reqs:
3321 --  None
3322 --Modifies:
3323 --  None
3324 --Locks:
3325 --  None.
3326 --Function:
3327 -- Performs the id-to-name conversion for category_id.
3328 -- Used when logging validation errors.
3329 --Parameters:
3330 --IN:
3331 --p_category_id
3332 --  The CATEGORY_ID for which we want the name
3333 --OUT:
3334 --p_category_name
3335 --  The outut name for the given ID.
3336 --OUT:
3337 --End of Comments
3338 --------------------------------------------------------------------------------
3339 PROCEDURE get_category_name_from_id
3340 (
3341   p_category_id   IN NUMBER,
3342   x_category_name OUT NOCOPY VARCHAR2
3343 )
3344 IS
3345   l_api_name      CONSTANT VARCHAR2(30) := 'get_category_name_from_id';
3346   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
3347   l_progress      VARCHAR2(3) := '000';
3348 BEGIN
3349   l_progress := '010';
3350   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
3351 
3352   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_category_id='||p_category_id); END IF;
3353 
3354   -- ECO bug 5584556: id-to-name conversion for new message
3355   -- Get the category name
3356   l_progress := '020';
3357   BEGIN
3358     SELECT concatenated_segments
3359     INTO x_category_name
3360     FROM MTL_CATEGORIES_B_KFV
3361     WHERE category_id = p_category_id;
3362   EXCEPTION
3363     WHEN OTHERS THEN
3364       l_progress := '030';
3365       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Exception while getting name from MTL_CATEGORIES_B_KFV: '||SQLERRM); END IF;
3366 
3367       x_category_name := p_category_id;
3368   END;
3369   -- ECO bug 5584556: End
3370 
3371   l_progress := '040';
3372   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'category_name='||x_category_name); END IF;
3373 
3374   l_progress := '050';
3375   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
3376 EXCEPTION
3377   WHEN OTHERS THEN
3378     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
3379     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
3380 END get_category_name_from_id;
3381 
3382 --------------------------------------------------------------------------------
3383 --Start of Comments
3384 --Name: get_ip_catgeory_name
3385 --Pre-reqs:
3386 --  None
3387 --Modifies:
3388 --  None
3389 --Locks:
3390 --  None.
3391 --Function:
3392 -- Performs the id-to-name conversion for ip_category_id.
3393 -- Used when logging validation errors.
3394 --Parameters:
3395 --IN:
3396 --p_ip_category_id
3397 --  The IP_CATEGORY_ID for which we want the name
3398 --OUT:
3399 --x_ip_category_name
3400 --  The outut name for the given ID.
3401 --OUT:
3402 --End of Comments
3403 --------------------------------------------------------------------------------
3404 PROCEDURE get_ip_catgeory_name
3405 (
3406   p_ip_category_id      IN NUMBER,
3407   p_interface_header_id IN NUMBER,
3408   p_interface_line_id   IN NUMBER,
3409   x_ip_category_name  OUT NOCOPY VARCHAR2,
3410   x_ip_catgeory_found OUT NOCOPY VARCHAR2
3411 )
3412 IS
3413   l_api_name      CONSTANT VARCHAR2(30) := 'get_ip_catgeory_name';
3414   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
3415   l_progress      VARCHAR2(3) := '000';
3416 BEGIN
3417   l_progress := '010';
3418   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
3419 
3420   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'p_ip_category_id='||p_ip_category_id); END IF;
3421 
3422   x_ip_catgeory_found := 'Y';
3423   -- ECO bug 5584556: id-to-name conversion for new message
3424   -- Get the category name
3425   l_progress := '020';
3426   BEGIN
3427     SELECT category_name
3428     INTO x_ip_category_name
3429     FROM ICX_CAT_CATEGORIES_V
3430     WHERE rt_category_id = p_ip_category_id
3431       AND language = userenv('LANG');
3432   EXCEPTION
3433     WHEN OTHERS THEN
3434       -- If the shopping category does not exist, or other cases.
3435       l_progress := '030';
3436       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Exception while getting IP ctageory_name using ICX_CAT_CATEGORIES_V view: '||SQLERRM); END IF;
3437 
3438       x_ip_catgeory_found := 'N';
3439   END;
3440   -- ECO bug 5584556: End
3441 
3442   IF ( (x_ip_category_name IS NULL) OR
3443        (x_ip_catgeory_found = 'N') ) THEN
3444 
3445     x_ip_category_name := p_ip_category_id;
3446     x_ip_catgeory_found := 'N';
3447 
3448     l_progress := '040';
3449     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Could not find IP category name'); END IF;
3450 
3451     -- Add error message into INTERFACE_ERRORS table
3452     -- ICX_CAT_SHOP_CATEG_REQD:
3453     -- "Shopping category is missing for one or more lines."
3454     PO_R12_CAT_UPG_UTL.add_fatal_error(
3455             p_interface_header_id => p_interface_header_id,
3456             p_interface_line_id   => p_interface_line_id,
3457             p_error_message_name  => 'ICX_CAT_SHOP_CATEG_REQD',
3458             p_table_name          => 'PO_LINES_INTERFACE',
3459             p_column_name         => 'IP_CATEGORY_ID',
3460             p_column_value        => p_ip_category_id
3461             );
3462   END IF;
3463 
3464   l_progress := '050';
3465   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'x_ip_category_name='||x_ip_category_name); END IF;
3466 
3467   l_progress := '060';
3468   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
3469 EXCEPTION
3470   WHEN OTHERS THEN
3471     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
3472     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
3473 END get_ip_catgeory_name;
3474 
3475 --------------------------------------------------------------------------------
3476 --Start of Comments
3477 --Name: validate_category
3478 --Pre-reqs:
3479 --  The iP catalog data is populated in input pl/sql tables.
3480 --Modifies:
3481 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
3482 --  b) FND_MSG_PUB on unhandled exceptions.
3483 --Locks:
3484 --  None.
3485 --Function:
3486 -- validate and make sure category_id is a valid category within the default
3487 -- category set for Purchasing. Validate if category_id belong to the item.
3488 -- Check if the Purchasing Category set has 'Validate flag' ON. If Yes, we
3489 -- will validate the Category to exist in the 'Valid Category List'. If No,
3490 -- we will just validate if the category is Enable and Active.
3491 --Parameters:
3492 --IN:
3493 --p_key
3494 --  Key used to access records in PO_SESSION_GT table.
3495 --IN/OUT:
3496 --p_lines_rec
3497 --  A record of plsql tables containing a batch of lines. If this validation
3498 --  fails, the 'has_errors' column is set to 'Y'.
3499 --OUT:
3500 --End of Comments
3501 --------------------------------------------------------------------------------
3502 PROCEDURE validate_category
3503 (
3504   p_key       IN NUMBER,
3505   p_lines_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_lines_type
3506 )
3507 IS
3508   l_api_name      CONSTANT VARCHAR2(30) := 'validate_category';
3509   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
3510   l_progress      VARCHAR2(3) := '000';
3511 
3512   l_size NUMBER := p_lines_rec.interface_line_id.COUNT;
3513 
3514   l_interface_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3515   l_interface_line_ids   PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3516   l_indexes              PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3517   l_item_id_list         PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3518   l_category_id_list     PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3519   l_category_name_list   PO_R12_CAT_UPG_TYPES.PO_TBL_VARCHAR2000;
3520 
3521   l_index NUMBER;
3522   i NUMBER;
3523   l_subscript_array PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
3524 
3525   l_validate_flag MTL_CATEGORY_SETS_V.validate_flag%TYPE;
3526   l_category_set_id MTL_CATEGORY_SETS_V.category_set_id%TYPE;
3527 
3528   l_category_name MTL_CATEGORIES_B_KFV.concatenated_segments%TYPE;
3529 
3530   l_ip_category_name ICX_CAT_CATEGORIES_V.category_name%TYPE;
3531   l_ip_catgeory_found VARCHAR2(1);
3532 BEGIN
3533   l_progress := '010';
3534   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
3535 
3536   -- category_id must not be NULL
3537   FOR i IN 1 .. p_lines_rec.category_id.COUNT
3538   LOOP
3539     l_progress := '020';
3540     IF (--p_lines_rec.has_errors(i) = 'N' AND
3541 
3542         -- Bug 5060582: CATEGORY_ID is updatable when CREATED_BY = -12.
3543         -- If it is specified as NULL in INTF table, then the column
3544         -- remains unchanged in TXN table. This is handled via a DECODE in the
3545         -- UPDATE statement, later in the flow. So allow NULL value in UPDATE flow
3546         -- where CREATED_BY is NOT -12.
3547         --p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE') AND
3548         (   p_lines_rec.action(i) = PO_R12_CAT_UPG_PVT.g_action_line_create
3549          OR
3550             (p_lines_rec.action(i) = 'UPDATE' AND
3551              p_lines_rec.created_by(i) = PO_R12_CAT_UPG_PVT.g_R12_UPGRADE_USER)
3552         )
3553         AND
3554         (p_lines_rec.category_id(i) IS NULL
3555          OR p_lines_rec.category_id(i) = g_NULL_COLUMN_VALUE)) -- -2
3556     THEN
3557 
3558       l_progress := '030';
3559       p_lines_rec.has_errors(i) := 'Y';
3560 
3561       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: category_name='||p_lines_rec.category(i)||', category_id='||p_lines_rec.category_id(i)); END IF;
3562       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'CREATED_BY='||p_lines_rec.created_by(i)||', ACTION='||p_lines_rec.action(i)); END IF;
3563 
3564       -- ECO bug 5584556: Get the IP category name, that will be the token in th err msg
3565       l_progress := '035';
3566       get_ip_catgeory_name
3567       (
3568         p_ip_category_id      => p_lines_rec.ip_category_id(i)
3569       , p_interface_header_id => p_lines_rec.interface_header_id(i)
3570       , p_interface_line_id   => p_lines_rec.interface_line_id(i)
3571       , x_ip_category_name    => l_ip_category_name
3572       , x_ip_catgeory_found   => l_ip_catgeory_found
3573       );
3574       -- ECO bug 5584556: End
3575 
3576       IF (l_ip_catgeory_found = 'Y') THEN
3577         -- Add error message into INTERFACE_ERRORS table
3578         -- ICX_CAT_CATEGORY_REQD:
3579         -- "The following categories cannot be mapped to a valid purchasing category: VALUE, VALUE"
3580         PO_R12_CAT_UPG_UTL.add_fatal_error(
3581               p_interface_header_id => p_lines_rec.interface_header_id(i),
3582               p_interface_line_id   => p_lines_rec.interface_line_id(i),
3583               --p_error_message_name  => 'PO_COLUMN_IS_NULL',
3584               p_error_message_name  => 'ICX_CAT_CATEGORY_REQD',
3585               p_table_name          => 'PO_LINES_INTERFACE',
3586               p_column_name         => 'CATEGORY',
3587               p_column_value        => l_ip_category_name, -- ECO bug 5584556
3588               p_token1_name         => 'PO_CATEGORY_ID',
3589               p_token1_value        => p_lines_rec.category(i), -- debug only, this is NULL here
3590               p_token2_name         => 'IP_CATGEORY_ID',
3591               p_token2_value        => p_lines_rec.ip_category_id(i) -- debug only
3592               );
3593       END IF; -- IF (l_ip_catgeory_found='Y')
3594     END IF;
3595   END LOOP;
3596 
3597   l_progress := '040';
3598   -- Find out the default category_set_id and validate_flag for function_area
3599   -- of PURCHASING".
3600   SELECT validate_flag, category_set_id
3601   INTO l_validate_flag, l_category_set_id
3602   FROM MTL_CATEGORY_SETS_V
3603   WHERE category_set_id =
3604        (SELECT   category_set_id
3605         FROM     MTL_DEFAULT_CATEGORY_SETS
3606         WHERE    functional_area_id = 2) ; -- Purchasing
3607 
3608   l_progress := '050';
3609   l_subscript_array := PO_R12_CAT_UPG_UTL.construct_subscript_array(p_lines_rec.item_id.COUNT);
3610 
3611   l_progress := '060';
3612   -- SQL What: Bulk validate category. Validate if category_id belongs to the
3613   --           item.
3614   --           Insert the error rows into GT table.
3615   -- SQL Why : It will be used to mark the record in plsql table as error.
3616   -- SQL Join: item_id, category_id
3617   FORALL i IN 1 .. p_lines_rec.item_id.COUNT
3618     INSERT INTO PO_SESSION_GT(key,
3619                               num1,
3620                               num2,
3621                               num3,
3622                               num4,
3623                               num5,
3624                               char1)
3625     SELECT p_key
3626          , l_subscript_array(i)
3627          , p_lines_rec.interface_header_id(i)
3628          , p_lines_rec.interface_line_id(i)
3629          , p_lines_rec.item_id(i)
3630          , p_lines_rec.category_id(i)
3631          , p_lines_rec.category(i) -- category name
3632     FROM DUAL
3633     WHERE --p_lines_rec.has_errors(i) = 'N'
3634       p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE')
3635       AND p_lines_rec.item_id(i) is not null
3636       AND p_lines_rec.category_id(i) is not null
3637       AND p_lines_rec.category_id(i) <> g_NULL_COLUMN_VALUE -- -2
3638       AND NOT EXISTS (SELECT 1
3639                      FROM MTL_ITEM_CATEGORIES MIC,
3640                           MTL_CATEGORIES MCS
3641                      WHERE
3642                          MIC.category_id = MCS.category_id
3643                      AND MIC.category_set_id = l_category_set_id
3644                      AND MIC.category_id = p_lines_rec.category_id(i)
3645                      AND MIC.inventory_item_id = p_lines_rec.item_id(i)
3646                      AND MIC.organization_id = PO_R12_CAT_UPG_PVT.g_sys.inv_org_id
3647                      AND sysdate < nvl(MCS.disable_date, sysdate+1)
3648                      AND MCS.enabled_flag = 'Y');
3649 
3650   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
3651 
3652   l_progress := '070';
3653   -- SQL What: Transfer from session GT table to local arrays
3654   -- SQL Why : It will be used to mark the error records.
3655   -- SQL Join: key
3656   DELETE FROM PO_SESSION_GT
3657   WHERE  key = p_key
3658   RETURNING num1, num2, num3, num4, num5, char1
3659   BULK COLLECT INTO l_indexes, l_interface_header_ids,
3660                     l_interface_line_ids, l_item_id_list,
3661                     l_category_id_list, l_category_name_list;
3662 
3663   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
3664 
3665   l_progress := '080';
3666   -- Mark the error records
3667   FOR i IN 1 .. l_indexes.COUNT
3668   LOOP
3669     l_index := l_indexes(i);
3670     p_lines_rec.has_errors(l_index) := 'Y';
3671 
3672     -- ECO bug 5584556: id-to-name conversion for new message
3673     l_progress := '085';
3674     get_category_name_from_id
3675     (
3676       p_category_id   => l_category_id_list(i)
3677     , x_category_name => l_category_name
3678     );
3679     -- ECO bug 5584556: End
3680 
3681     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: category_name='||l_category_name_list(i)||', category_id='||l_category_id_list(i)||', item_id='||l_item_id_list(i)); END IF;
3682 
3683     -- Add error message into INTERFACE_ERRORS table
3684     -- ICX_CAT_INVALID_CATEGORY:
3685     -- "The following purchasing categories are inactive or invalid: VALUE, VALUE"
3686     PO_R12_CAT_UPG_UTL.add_fatal_error(
3687             p_interface_header_id => l_interface_header_ids(i),
3688             p_interface_line_id   => l_interface_line_ids(i),
3689             --p_error_message_name  => 'PO_PDOI_ITEM_RELATED_INFO',
3690             p_error_message_name  => 'ICX_CAT_INVALID_CATEGORY',
3691             p_table_name          => 'PO_LINES_INTERFACE',
3692             p_column_name         => 'CATEGORY_ID',
3693             p_column_value        => l_category_name, -- ECO bug 5584556
3694             p_token1_name         => 'VALUE',
3695             p_token1_value        => l_category_id_list(i),
3696             p_token2_name         => 'ITEM',
3697             p_token2_value        => l_item_id_list(i)
3698             );
3699   END LOOP;
3700 
3701   l_progress := '090';
3702   IF l_validate_flag = 'Y' THEN
3703     l_progress := '100';
3704     -- SQL What: Bulk validate category. Validate category_id against
3705     --           MTL_CATEGORY_SET_VALID_CATS.
3706     --           Insert the error rows into GT table.
3707     -- SQL Why : It will be used to mark the record in plsql table as error.
3708     -- SQL Join: category_id
3709     FORALL i IN 1 .. p_lines_rec.item_id.COUNT
3710       INSERT INTO PO_SESSION_GT(key,
3711                                 num1,
3712                                 num2,
3713                                 num3,
3714                                 num4,
3715                                 char1)
3716       SELECT p_key
3717            , l_subscript_array(i)
3718            , p_lines_rec.interface_header_id(i)
3719            , p_lines_rec.interface_line_id(i)
3720            , p_lines_rec.category_id(i)
3721            , p_lines_rec.category(i) -- category name
3722       FROM DUAL
3723       WHERE --p_lines_rec.has_errors(i) = 'N'
3724       p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE')
3725       AND p_lines_rec.item_id(i) is null
3726       AND p_lines_rec.category_id(i) is not null
3727       AND p_lines_rec.category_id(i) <> g_NULL_COLUMN_VALUE -- -2
3728       AND NOT EXISTS
3729           (SELECT 'Y'
3730            FROM MTL_CATEGORIES_VL MCS,
3731                 MTL_CATEGORY_SET_VALID_CATS MCSVC
3732           WHERE MCS.category_id = p_lines_rec.category_id(i)
3733             AND MCS.category_id = MCSVC.category_id
3734             AND MCSVC.category_set_id = l_category_set_id
3735             AND sysdate < nvl(MCS.disable_date, sysdate+1)
3736             AND MCS.enabled_flag = 'Y');
3737 
3738     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
3739 
3740     l_progress := '110';
3741     -- SQL What: Transfer from session GT table to local arrays
3742     -- SQL Why : It will be used to mark the error records.
3743     -- SQL Join: key
3744     DELETE FROM PO_SESSION_GT
3745     WHERE  key = p_key
3746     RETURNING num1, num2, num3, num4, char1
3747     BULK COLLECT INTO l_indexes, l_interface_header_ids,
3748                       l_interface_line_ids,
3749                       l_category_id_list, l_category_name_list;
3750 
3751     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
3752 
3753     l_progress := '120';
3754     -- Mark the error records
3755     FOR i IN 1 .. l_indexes.COUNT
3756     LOOP
3757       l_index := l_indexes(i);
3758       p_lines_rec.has_errors(l_index) := 'Y';
3759 
3760       -- ECO bug 5584556: id-to-name conversion for new message
3761       l_progress := '125';
3762       get_category_name_from_id
3763       (
3764         p_category_id   => l_category_id_list(i)
3765       , x_category_name => l_category_name
3766       );
3767       -- ECO bug 5584556: End
3768 
3769       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: category_name='||l_category_name_list(i)||', category_id='||l_category_id_list(i)); END IF;
3770 
3771       -- Add error message into INTERFACE_ERRORS table
3772       -- ICX_CAT_INVALID_CATEGORY:
3773       -- "The following purchasing categories are inactive or invalid: VALUE, VALUE"
3774       PO_R12_CAT_UPG_UTL.add_fatal_error(
3775               p_interface_header_id => l_interface_header_ids(i),
3776               p_interface_line_id   => l_interface_line_ids(i),
3777               --p_error_message_name  => 'PO_PDOI_INVALID_CATEGORY_ID',
3778               p_error_message_name  => 'ICX_CAT_INVALID_CATEGORY',
3779               p_table_name          => 'PO_LINES_INTERFACE',
3780               p_column_name         => 'CATEGORY_ID',
3781               p_column_value        => l_category_name, -- ECO bug 5584556
3782               p_token1_name         => 'VALUE',
3783               p_token1_value        => l_category_id_list(i)
3784               );
3785     END LOOP;
3786 
3787     l_progress := '130';
3788 
3789   ELSE -- IF l_validate_flag <> 'Y' THEN
3790 
3791     l_progress := '140';
3792     -- SQL What: Bulk validate category. Validate category_id against
3793     --           MTL_CATEGORIES_VL.
3794     --           Insert the error rows into GT table.
3795     -- SQL Why : It will be used to mark the record in plsql table as error.
3796     -- SQL Join: category_id
3797     FORALL i IN 1 .. p_lines_rec.item_id.COUNT
3798       INSERT INTO PO_SESSION_GT(key,
3799                                 num1,
3800                                 num2,
3801                                 num3,
3802                                 num4,
3803                                 char1)
3804       SELECT p_key
3805            , l_subscript_array(i)
3806            , p_lines_rec.interface_header_id(i)
3807            , p_lines_rec.interface_line_id(i)
3808            , p_lines_rec.category_id(i)
3809            , p_lines_rec.category(i) -- category name
3810       FROM DUAL
3811       WHERE --p_lines_rec.has_errors(i) = 'N'
3812       p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE')
3813       AND p_lines_rec.item_id(i) is null
3814       AND p_lines_rec.category_id(i) is not null
3815       AND p_lines_rec.category_id(i) <> g_NULL_COLUMN_VALUE -- -2
3816       AND NOT EXISTS
3817           (SELECT 1
3818            FROM MTL_CATEGORIES_VL MCS
3819            WHERE MCS.category_id = p_lines_rec.category_id(i)
3820              AND sysdate < nvl(MCS.disable_date, sysdate+1)
3821              AND MCS.enabled_flag = 'Y');
3822 
3823     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows insert into GT table='||SQL%rowcount); END IF;
3824 
3825     l_progress := '150';
3826     -- SQL What: Transfer from session GT table to local arrays
3827     -- SQL Why : It will be used to mark the error records.
3828     -- SQL Join: key
3829     DELETE FROM PO_SESSION_GT
3830     WHERE  key = p_key
3831     RETURNING num1, num2, num3, num4, char1
3832     BULK COLLECT INTO l_indexes, l_interface_header_ids,
3833                       l_interface_line_ids,
3834                       l_category_id_list, l_category_name_list;
3835 
3836     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of rows deleted from GT table='||SQL%rowcount); END IF;
3837 
3838     l_progress := '160';
3839     -- Mark the error records
3840     FOR i IN 1 .. l_indexes.COUNT
3841     LOOP
3842       l_progress := '170';
3843 
3844       l_index := l_indexes(i);
3845       p_lines_rec.has_errors(l_index) := 'Y';
3846 
3847       -- ECO bug 5584556: id-to-name conversion for new message
3848       l_progress := '175';
3849       get_category_name_from_id
3850       (
3851         p_category_id   => l_category_id_list(i)
3852       , x_category_name => l_category_name
3853       );
3854       -- ECO bug 5584556: End
3855 
3856       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'VALIDATION ERROR: category_name='||l_category_name_list(i)||', category_id='||l_category_id_list(i)); END IF;
3857 
3858       -- Add error message into INTERFACE_ERRORS table
3859       -- ICX_CAT_INVALID_CATEGORY:
3860       -- "The following purchasing categories are inactive or invalid: VALUE, VALUE"
3861       PO_R12_CAT_UPG_UTL.add_fatal_error(
3862               p_interface_header_id => l_interface_header_ids(i),
3863               p_interface_line_id   => l_interface_line_ids(i),
3864               --p_error_message_name  => 'PO_PDOI_INVALID_CATEGORY_ID',
3865               p_error_message_name  => 'ICX_CAT_INVALID_CATEGORY',
3866               p_table_name          => 'PO_LINES_INTERFACE',
3867               p_column_name         => 'CATEGORY_ID',
3868               p_column_value        => l_category_name, -- ECO bug 5584556
3869               p_token1_name         => 'VALUE',
3870               p_token1_value        => l_category_id_list(i)
3871               );
3872     END LOOP;
3873   END IF; -- IF x_validate_flag = 'Y'
3874 
3875   l_progress := '180';
3876   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
3877 EXCEPTION
3878   WHEN OTHERS THEN
3879     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
3880     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
3881 END validate_category;
3882 
3883 --------------------------------------------------------------------------------
3884 --Start of Comments
3885 --Name: validate_unit_price
3886 --Pre-reqs:
3887 --  The iP catalog data is populated in input pl/sql tables.
3888 --Modifies:
3889 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
3890 --  b) FND_MSG_PUB on unhandled exceptions.
3891 --Locks:
3892 --  None.
3893 --Function:
3894 -- If order_type_lookup_code is not 'FIXED PRICE', unit_price cannot be null
3895 -- and cannot be less than zero.
3896 --Parameters:
3897 --IN:
3898 --p_key
3899 --  Key used to access records in PO_SESSION_GT table.
3900 --IN/OUT:
3901 --p_lines_rec
3902 --  A record of plsql tables containing a batch of lines. If this validation
3903 --  fails, the 'has_errors' column is set to 'Y'.
3904 --OUT:
3905 --End of Comments
3906 --------------------------------------------------------------------------------
3907 PROCEDURE validate_unit_price
3908 (
3909   p_lines_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_lines_type
3910 )
3911 IS
3912   l_api_name      CONSTANT VARCHAR2(30) := 'validate_unit_price';
3913   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
3914   l_progress      VARCHAR2(3) := '000';
3915 
3916   i NUMBER;
3917 BEGIN
3918   l_progress := '010';
3919   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
3920 
3921   FOR i IN 1 .. p_lines_rec.unit_price.COUNT
3922   LOOP
3923     l_progress := '020';
3924 
3925     IF (--p_lines_rec.has_errors(i) = 'N' AND
3926         -- Bug 5060582: UNIT_PRICE is updatable when CREATED_BY = -12.
3927         -- If it is specified as NULL in INTF table, then the column
3928         -- remains unchanged in TXN table. This is handled via a DECODE in the
3929         -- UPDATE statement, later in the flow. So allow NULL value in UPDATE flow
3930         -- where CREATED_BY is NOT -12.
3931         --p_lines_rec.action(i) IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE') AND
3932         (    p_lines_rec.action(i) =PO_R12_CAT_UPG_PVT.g_action_line_create
3933          OR
3934             (p_lines_rec.action(i) = 'UPDATE' AND
3935              p_lines_rec.created_by(i) = PO_R12_CAT_UPG_PVT.g_R12_UPGRADE_USER)
3936         )
3937         AND
3938         (p_lines_rec.unit_price(i) IS NULL OR
3939          p_lines_rec.unit_price(i) < 0)) THEN
3940 
3941       l_progress := '030';
3942 
3943       p_lines_rec.has_errors(i) := 'Y';
3944       IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'CREATED_BY='||p_lines_rec.created_by(i)||', ACTION='||p_lines_rec.action(i)); END IF;
3945 
3946       -- Add error message into INTERFACE_ERRORS table
3947       -- PO_PDOI_LT_ZERO:
3948       -- "COLUMN_NAME (VALUE =VALUE) specified is less than zero."
3949       PO_R12_CAT_UPG_UTL.add_fatal_error(
3950             p_interface_header_id => p_lines_rec.interface_header_id(i),
3951             p_interface_line_id   => p_lines_rec.interface_line_id(i),
3952             --p_error_message_name  => 'PO_PDOI_LT_ZERO',
3953             p_error_message_name  => 'ICX_CAT_INVALID_PRICE',
3954             p_table_name          => 'PO_LINES_INTERFACE',
3955             p_column_name         => 'UNIT_PRICE',
3956             p_column_value        => p_lines_rec.unit_price(i),
3957             p_token1_name         => 'COLUMN_NAME',
3958             p_token1_value        => 'UNIT_PRICE',
3959             p_token2_name         => 'VALUE',
3960             p_token2_value        => p_lines_rec.unit_price(i)
3961             );
3962     END IF;
3963   END LOOP;
3964 
3965   l_progress := '040';
3966   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
3967 EXCEPTION
3968   WHEN OTHERS THEN
3969     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
3970     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
3971 END validate_unit_price;
3972 
3973 --------------------------------------------------------------------------------
3974 --Start of Comments
3975 --Name: validate_lines
3976 --Pre-reqs:
3977 --  The iP catalog data is populated in input pl/sql tables.
3978 --Modifies:
3979 --  a) Input pl/sql table: May set the value of 'has_errors' to 'Y'.
3980 --  b) FND_MSG_PUB on unhandled exceptions.
3981 --Locks:
3982 --  None.
3983 --Function:
3984 --  This is the main function to validate lines. It calls the following
3985 --  procedures:
3986 --
3987 --     validate_item
3988 --     validate_item_revision
3989 --     validate_item_description
3990 --     validate_uom
3991 --     validate_category
3992 --     validate_unit_price
3993 --
3994 --  UN_NUMBERID, HAZARD_CLASS_ID: These are 2 more defaulted fields
3995 --  (from vendor/site) that IP will not provide in Interface table. However,
3996 --  for these 2 fields, the only validation in PDOI is that if the line
3997 --  type is TEMP LABOR, then these fields must be NULL. Since in IP catalog
3998 --  migration, the line type is always GOODS we do not need these validations.
3999 --
4000 --Parameters:
4001 --IN/OUT:
4002 --p_lines_rec
4003 --  A record of plsql tables containing a batch of lines. If this validation
4004 --  fails, the 'has_errors' column is set to 'Y'.
4005 --OUT:
4006 --End of Comments
4007 --------------------------------------------------------------------------------
4008 PROCEDURE validate_lines
4009 (
4010   p_lines_rec IN OUT NOCOPY PO_R12_CAT_UPG_PVT.record_of_lines_type
4011 )
4012 IS
4013   l_api_name      CONSTANT VARCHAR2(30) := 'validate_lines';
4014   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
4015   l_progress      VARCHAR2(3) := '000';
4016 
4017   l_key PO_SESSION_GT.key%TYPE;
4018   i NUMBER;
4019 BEGIN
4020   l_progress := '010';
4021   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
4022 
4023   -- pick a new key from temp table which will be used in all validate logic
4024   SELECT PO_SESSION_GT_S.nextval
4025   INTO l_key
4026   FROM DUAL;
4027 
4028   l_progress := '020';
4029   -- if item id is not null, it has to exist in mtl_system_items table
4030   validate_item
4031   (
4032     p_key       => l_key,
4033     p_lines_rec => p_lines_rec
4034   );
4035 
4036   l_progress := '030';
4037   -- if order_type_lookup_code is FIXED PRICE or RATE, or item id is null,
4038   -- then item revision has to be NULL
4039   -- check to see if there are x_item_revision exists in mtl_item_revisions table
4040   validate_item_revision
4041   (
4042     p_key       => l_key,
4043     p_lines_rec => p_lines_rec
4044   );
4045 
4046   l_progress := '040';
4047   -- Make sure that the item_description is populated, and also need to find out
4048   -- if it is different from what is setup for the item.
4049   validate_item_description
4050   (
4051     p_key       => l_key,
4052     p_lines_rec => p_lines_rec
4053   );
4054 
4055   l_progress := '050';
4056   --  check to see if unit_meas_lookup_code is valid in mtl_item_uoms_view
4057   validate_uom
4058   (
4059     p_key       => l_key,
4060     p_lines_rec => p_lines_rec
4061   );
4062 
4063   l_progress := '060';
4064   -- validate and make sure category_id is a valid category within the default
4065   -- category set for Purchasing. Validate if category_id belong to the item.
4066   -- Check if the Purchasing Category set has 'Validate flag' ON. If Yes, we
4067   -- will validate the Category to exist in the 'Valid Category List'. If No,
4068   -- we will just validate if the category is Enable and Active.
4069   validate_category
4070   (
4071     p_key       => l_key,
4072     p_lines_rec => p_lines_rec
4073   );
4074 
4075   l_progress := '070';
4076   -- If order_type_lookup_code is not 'FIXED PRICE', unit_price cannot be null
4077   -- and cannot be less than zero.
4078   validate_unit_price
4079   (
4080     p_lines_rec => p_lines_rec
4081   );
4082 
4083   l_progress := '080';
4084   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
4085 EXCEPTION
4086   WHEN OTHERS THEN
4087     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
4088     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
4089 END validate_lines;
4090 
4091 
4092 --------------------------------------------------------------------------------
4093 -- Validate ACTIONS in pre-process
4094 --------------------------------------------------------------------------------
4095 
4096 
4097 --------------------------------------------------------------------------------
4098 --Start of Comments
4099   --Name: validate_create_action
4100   --Pre-reqs:
4101   --  The iP catalog data is populated in PO Interface tables.
4102   --Modifies:
4103   --  a) PO_INTERFACE_ERRORS table: Inserts error messages for those rows that
4104   --     failed validation.
4105   --  b) FND_MSG_PUB on unhandled exceptions.
4106   --Locks:
4107   --  None.
4108   --Function:
4109   --  Validates CREATE actions at line, attribute and TLP levels
4110   --     * For Lines,
4111   --         checks that INTERFACE_HEADER_ID is provided where the line needs to be added to
4112   --     * For Attributes,
4113   --         checks that INTERFACE_LINE_ID is provided for which the attribute needs to be created for.
4114   --     * For Attributes TLP,
4115   --         checks that INTERFACE_LINE_ID is provided for which the attribute TLP needs to be created for
4116   --
4117   --  This API should be called during the upgrade phase only.
4118   --Parameters:
4119   --IN:
4120   --p_validate_only_mode
4121   --  Indicates if the API is being called in a Validate Only mode or not
4122   --OUT:
4123   -- None
4124   --
4125 --End of Comments
4126 --------------------------------------------------------------------------------
4127 PROCEDURE validate_create_action
4128 (
4129   p_validate_only_mode           IN VARCHAR2 default FND_API.G_FALSE
4130 )
4131 IS
4132   l_api_name      CONSTANT VARCHAR2(30) := 'validate_create_action';
4133   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
4134   l_progress      VARCHAR2(3) := '000';
4135 
4136   l_err_line_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4137   l_err_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4138   l_err_attr_values_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4139   l_err_attr_values_tlp_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4140 BEGIN
4141   l_progress := '010';
4142   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
4143 
4144   -----------------------------------------------------------------------------
4145   -- CREATE action validations for Lines
4146   -----------------------------------------------------------------------------
4147 
4148   l_progress := '040';
4149   -- For Lines,
4150   --   ORIGINAL action is not allowed at line level. Use ADD action (to conform
4151   --   to PDOI style of action names).
4152 
4153   -- SQL What: validate create action at line level
4154   -- SQL Why : To find incorrect action
4155   -- SQL Join: processing_id, action, interface_header_id
4156   UPDATE PO_LINES_INTERFACE POLI
4157   SET POLI.processing_id = -POLI.processing_id,
4158       POLI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4159   WHERE POLI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4160     AND POLI.action = 'ORIGINAL'
4161   RETURNING POLI.interface_line_id, POLI.interface_header_id
4162   BULK COLLECT INTO l_err_line_ids, l_err_header_ids;
4163 
4164   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid CREATE action at Line level='||SQL%rowcount); END IF;
4165 
4166   l_progress := '050';
4167   -- Add error message into INTERFACE_ERRORS table
4168   FOR i in 1..l_err_line_ids.COUNT
4169   LOOP
4170     PO_R12_CAT_UPG_UTL.add_fatal_error(
4171           p_interface_header_id => l_err_header_ids(i),
4172           p_interface_line_id   => l_err_line_ids(i),
4173           p_error_message_name  => 'PO_CAT_UPG_ORIG_NOT_ALLOWED',
4174           p_table_name          => 'PO_LINES_INTERFACE',
4175           p_column_name         => 'ACTION'
4176           );
4177   END LOOP;
4178 
4179   l_progress := '060';
4180   -- Cascade errors down to attribute and TLP levels
4181   -- Skip cascading of errors in Validate Only mode (iP Requirement - all errors should be reported)
4182   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
4183     PO_R12_CAT_UPG_UTL.reject_attr_values_intf('INTERFACE_LINE_ID', l_err_line_ids);
4184     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
4185   END IF;
4186 
4187   -----------------------------------------------------------------------------
4188   -- CREATE action validations for Attribute Values
4189   -----------------------------------------------------------------------------
4190   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'PO_R12_CAT_UPG_PVT.g_action_line_create='||PO_R12_CAT_UPG_PVT.g_action_line_create); END IF;
4191   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'PO_R12_CAT_UPG_PVT.g_action_attr_create='||PO_R12_CAT_UPG_PVT.g_action_attr_create); END IF;
4192 
4193   -- Clear the error arrays
4194   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_header_ids.COUNT='||l_err_header_ids.COUNT); END IF;
4195   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_line_ids.COUNT='||l_err_line_ids.COUNT); END IF;
4196   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_attr_values_ids.COUNT='||l_err_attr_values_ids.COUNT); END IF;
4197 
4198   l_err_attr_values_ids.DELETE;
4199   l_err_line_ids.DELETE;
4200   l_err_header_ids.DELETE;
4201 
4202   l_progress := '070';
4203   -- For Attributes,
4204   --   check that INTERFACE_LINE_ID is provided for which the attribute needs to be created for
4205 
4206   -- SQL What: validate create action at attr level
4207   -- SQL Why : To find incorrect action
4208   -- SQL Join: processing_id, action, interface_line_id
4209   UPDATE PO_ATTR_VALUES_INTERFACE POAI
4210   SET POAI.processing_id = -POAI.processing_id,
4211       POAI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4212   WHERE POAI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4213     AND POAI.action = PO_R12_CAT_UPG_PVT.g_action_attr_create
4214     AND (
4215            POAI.interface_line_id IS NULL
4216          OR
4217             -- the following are NOT NULL columns in the TXN table, so they must
4218             -- have a not null value in the INTF table as well.
4219            (
4220             --POAI.po_line_id IS NULL OR
4221             POAI.req_template_name IS NULL OR
4222             POAI.req_template_line_num IS NULL OR
4223             POAI.org_id IS NULL OR
4224             POAI.inventory_item_id IS NULL OR
4225             POAI.ip_category_id IS NULL
4226            )
4227         )
4228   RETURNING POAI.interface_attr_values_id, POAI.interface_line_id, POAI.interface_header_id
4229   BULK COLLECT INTO l_err_attr_values_ids, l_err_line_ids, l_err_header_ids;
4230 
4231   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid CREATE action at Attr level='||SQL%rowcount); END IF;
4232 
4233   l_progress := '080';
4234   -- Add error message into INTERFACE_ERRORS table
4235   FOR i in 1..l_err_attr_values_ids.COUNT
4236   LOOP
4237     PO_R12_CAT_UPG_UTL.add_fatal_error(
4238           p_interface_header_id => l_err_header_ids(i),
4239           p_interface_line_id   => l_err_line_ids(i),
4240           p_interface_attr_values_id => l_err_attr_values_ids(i),
4241           p_error_message_name  => 'PO_CAT_UPG_NULL_IDS',
4242           p_table_name          => 'PO_ATTR_VALUES_INTERFACE',
4243           p_column_name         => 'INTERFACE_ATTR_VALUES_ID'
4244           );
4245   END LOOP;
4246 
4247   l_progress := '090';
4248   -- Cascade errors down to TLP level
4249   -- Skip cascading of errors in Validate Only mode.
4250   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
4251     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
4252   END IF;
4253 
4254 ----------------------------------------------------------------------------------
4255   -- Clear the error arrays
4256   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_header_ids.COUNT='||l_err_header_ids.COUNT); END IF;
4257   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_line_ids.COUNT='||l_err_line_ids.COUNT); END IF;
4258   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_attr_values_ids.COUNT='||l_err_attr_values_ids.COUNT); END IF;
4259 
4260   l_err_attr_values_ids.DELETE;
4261   l_err_line_ids.DELETE;
4262   l_err_header_ids.DELETE;
4263 
4264   l_progress := '071';
4265   UPDATE PO_ATTR_VALUES_INTERFACE POAI
4266   SET POAI.processing_id = -POAI.processing_id,
4267       POAI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4268   WHERE POAI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4269     AND POAI.action = PO_R12_CAT_UPG_PVT.g_action_attr_create
4270     AND (EXISTS
4271               (SELECT 'Invalid relationship with Line Level'
4272                FROM PO_LINES_INTERFACE POLI
4273                WHERE POLI.interface_line_id = POAI.interface_line_id
4274                  AND (  -- Attribute Row for GBPA must have appr action at line level
4275                         (POAI.req_template_name = g_NOT_REQUIRED_REQ_TEMPLATE AND
4276                          POAI.req_template_line_num = g_NOT_REQUIRED_ID AND
4277                          POLI.action NOT IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE', 'DELETE'))
4278         )))
4279   RETURNING POAI.interface_attr_values_id, POAI.interface_line_id, POAI.interface_header_id
4280   BULK COLLECT INTO l_err_attr_values_ids, l_err_line_ids, l_err_header_ids;
4281 
4282   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid CREATE action at Attr level='||SQL%rowcount); END IF;
4283 
4284   l_progress := '072';
4285   -- Add error message into INTERFACE_ERRORS table
4286   FOR i in 1..l_err_attr_values_ids.COUNT
4287   LOOP
4288     PO_R12_CAT_UPG_UTL.add_fatal_error(
4289           p_interface_header_id => l_err_header_ids(i),
4290           p_interface_line_id   => l_err_line_ids(i),
4291           p_interface_attr_values_id => l_err_attr_values_ids(i),
4292           p_error_message_name  => 'PO_CAT_UPG_INV_LINE_ACTION_BL',
4293           p_table_name          => 'PO_ATTR_VALUES_INTERFACE',
4294           p_column_name         => 'INTERFACE_ATTR_VALUES_ID'
4295           );
4296   END LOOP;
4297 
4298   -- Clear the error arrays
4299   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_header_ids.COUNT='||l_err_header_ids.COUNT); END IF;
4300   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_line_ids.COUNT='||l_err_line_ids.COUNT); END IF;
4301   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_attr_values_ids.COUNT='||l_err_attr_values_ids.COUNT); END IF;
4302 
4303   l_err_attr_values_ids.DELETE;
4304   l_err_line_ids.DELETE;
4305   l_err_header_ids.DELETE;
4306 
4307   l_progress := '071';
4308   -- Clear the error arrays
4309   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_header_ids.COUNT='||l_err_header_ids.COUNT); END IF;
4310   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_line_ids.COUNT='||l_err_line_ids.COUNT); END IF;
4311   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_attr_values_ids.COUNT='||l_err_attr_values_ids.COUNT); END IF;
4312 
4313   l_err_attr_values_ids.DELETE;
4314   l_err_line_ids.DELETE;
4315   l_err_header_ids.DELETE;
4316 
4317   l_progress := '07';
4318   UPDATE PO_ATTR_VALUES_INTERFACE POAI
4319   SET POAI.processing_id = -POAI.processing_id,
4320       POAI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4321   WHERE POAI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4322     AND POAI.action = PO_R12_CAT_UPG_PVT.g_action_attr_create
4323     AND (EXISTS
4324               (SELECT 'Invalid relationship with Line Level'
4325                FROM PO_LINES_INTERFACE POLI
4326                WHERE POLI.interface_line_id = POAI.interface_line_id
4327                  AND (  -- Attribute Row for ReqTemplate must have action as REQTEMPALTE at line level
4328                         ((POAI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE OR
4329                           POAI.req_template_line_num <> g_NOT_REQUIRED_ID) AND
4330                           POLI.action NOT IN ('REQTEMPLATE'))
4331         )))
4332   RETURNING POAI.interface_attr_values_id, POAI.interface_line_id, POAI.interface_header_id
4333   BULK COLLECT INTO l_err_attr_values_ids, l_err_line_ids, l_err_header_ids;
4334 
4335   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid CREATE action at Attr level='||SQL%rowcount); END IF;
4336 
4337   l_progress := '072';
4338   -- Add error message into INTERFACE_ERRORS table
4339   FOR i in 1..l_err_attr_values_ids.COUNT
4340   LOOP
4341     PO_R12_CAT_UPG_UTL.add_fatal_error(
4342           p_interface_header_id => l_err_header_ids(i),
4343           p_interface_line_id   => l_err_line_ids(i),
4344           p_interface_attr_values_id => l_err_attr_values_ids(i),
4345           p_error_message_name  => 'PO_CAT_UPG_INV_LINE_ACTION_RT',
4346           p_table_name          => 'PO_ATTR_VALUES_INTERFACE',
4347           p_column_name         => 'INTERFACE_ATTR_VALUES_ID'
4348           );
4349   END LOOP;
4350 
4351   -- Clear the error arrays
4352   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_header_ids.COUNT='||l_err_header_ids.COUNT); END IF;
4353   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_line_ids.COUNT='||l_err_line_ids.COUNT); END IF;
4354   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_attr_values_ids.COUNT='||l_err_attr_values_ids.COUNT); END IF;
4355 
4356   l_err_attr_values_ids.DELETE;
4357   l_err_line_ids.DELETE;
4358   l_err_header_ids.DELETE;
4359 
4360   l_progress := '073';
4361   UPDATE PO_ATTR_VALUES_INTERFACE POAI
4362   SET POAI.processing_id = -POAI.processing_id,
4363       POAI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4364   WHERE POAI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4365     AND POAI.action = PO_R12_CAT_UPG_PVT.g_action_attr_create
4366     AND (
4367            ( -- For ReqTemplates, ALL the 3 columns must be given
4368              (POAI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE AND
4369               (POAI.req_template_line_num = g_NOT_REQUIRED_ID OR
4370                POAI.org_id = g_NOT_REQUIRED_ID))
4371              OR
4372              (POAI.req_template_line_num <> g_NOT_REQUIRED_ID AND
4373               (POAI.req_template_name = g_NOT_REQUIRED_REQ_TEMPLATE OR
4374                POAI.org_id = g_NOT_REQUIRED_ID))
4375            )
4376         )
4377   RETURNING POAI.interface_attr_values_id, POAI.interface_line_id, POAI.interface_header_id
4378   BULK COLLECT INTO l_err_attr_values_ids, l_err_line_ids, l_err_header_ids;
4379 
4380   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid CREATE action at Attr level='||SQL%rowcount); END IF;
4381 
4382   l_progress := '074';
4383   -- Add error message into INTERFACE_ERRORS table
4384   FOR i in 1..l_err_attr_values_ids.COUNT
4385   LOOP
4386     PO_R12_CAT_UPG_UTL.add_fatal_error(
4387           p_interface_header_id => l_err_header_ids(i),
4388           p_interface_line_id   => l_err_line_ids(i),
4389           p_interface_attr_values_id => l_err_attr_values_ids(i),
4390           p_error_message_name  => 'PO_CAT_UPG_ALL_3_FOR_REQT',
4391           p_table_name          => 'PO_ATTR_VALUES_INTERFACE',
4392           p_column_name         => 'INTERFACE_ATTR_VALUES_ID'
4393           );
4394   END LOOP;
4395 
4396   -- Clear the error arrays
4397   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_header_ids.COUNT='||l_err_header_ids.COUNT); END IF;
4398   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_line_ids.COUNT='||l_err_line_ids.COUNT); END IF;
4399   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_attr_values_ids.COUNT='||l_err_attr_values_ids.COUNT); END IF;
4400 
4401   l_err_attr_values_ids.DELETE;
4402   l_err_line_ids.DELETE;
4403   l_err_header_ids.DELETE;
4404 
4405   l_progress := '075';
4406   UPDATE PO_ATTR_VALUES_INTERFACE POAI
4407   SET POAI.processing_id = -POAI.processing_id,
4408       POAI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4409   WHERE POAI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4410     AND POAI.action = PO_R12_CAT_UPG_PVT.g_action_attr_create
4411     AND (
4412            (-- For ReqTemplates, the ReqTemplate Line must exist in Txn tables
4413             POAI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE AND
4414             POAI.req_template_line_num <> g_NOT_REQUIRED_ID AND
4415             POAI.org_id <> g_NOT_REQUIRED_ID AND
4416             NOT EXISTS
4417               (SELECT 'ReqTemplate Line in txn tables'
4418                FROM PO_REQEXPRESS_LINES_ALL PORT
4419                WHERE PORT.express_name = POAI.req_template_name
4420                  AND PORT.sequence_num = POAI.req_template_line_num
4421                  AND PORT.org_id = POAI.org_id)
4422            )
4423         )
4424   RETURNING POAI.interface_attr_values_id, POAI.interface_line_id, POAI.interface_header_id
4425   BULK COLLECT INTO l_err_attr_values_ids, l_err_line_ids, l_err_header_ids;
4426 
4427   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid CREATE action at Attr level='||SQL%rowcount); END IF;
4428 
4429   l_progress := '076';
4430   -- Add error message into INTERFACE_ERRORS table
4431   FOR i in 1..l_err_attr_values_ids.COUNT
4432   LOOP
4433     PO_R12_CAT_UPG_UTL.add_fatal_error(
4434           p_interface_header_id => l_err_header_ids(i),
4435           p_interface_line_id   => l_err_line_ids(i),
4436           p_interface_attr_values_id => l_err_attr_values_ids(i),
4437           p_error_message_name  => 'PO_CAT_UPG_ALL_NO_REQTEMP',
4438           p_table_name          => 'PO_ATTR_VALUES_INTERFACE',
4439           p_column_name         => 'INTERFACE_ATTR_VALUES_ID'
4440           );
4441   END LOOP;
4442 
4443 ----------------------------------------------------------------------------------
4444 
4445   l_progress := '080';
4446   -- Add error message into INTERFACE_ERRORS table
4447   FOR i in 1..l_err_attr_values_ids.COUNT
4448   LOOP
4449     PO_R12_CAT_UPG_UTL.add_fatal_error(
4450           p_interface_header_id => l_err_header_ids(i),
4451           p_interface_line_id   => l_err_line_ids(i),
4452           p_interface_attr_values_id => l_err_attr_values_ids(i),
4453           p_error_message_name  => 'PO_CAT_UPG_INVALID_ATTR_ROW',
4454           p_table_name          => 'PO_ATTR_VALUES_INTERFACE',
4455           p_column_name         => 'INTERFACE_ATTR_VALUES_ID'
4456           );
4457   END LOOP;
4458 
4459   l_progress := '090';
4460   -- Cascade errors down to TLP level
4461   -- Skip cascading of errors in Validate Only mode.
4462   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
4463     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
4464   END IF;
4465 
4466   -----------------------------------------------------------------------------
4467   -- CREATE action validations for Attribute Values TLP
4468   -----------------------------------------------------------------------------
4469   -- Clear the error arrays
4470   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_header_ids.COUNT='||l_err_header_ids.COUNT); END IF;
4471   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_line_ids.COUNT='||l_err_line_ids.COUNT); END IF;
4472   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_attr_values_ids.COUNT='||l_err_attr_values_ids.COUNT); END IF;
4473   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'l_err_attr_values_tlp_ids.COUNT='||l_err_attr_values_tlp_ids.COUNT); END IF;
4474 
4475   l_err_attr_values_ids.DELETE;
4476   l_err_attr_values_tlp_ids.DELETE;
4477   l_err_line_ids.DELETE;
4478   l_err_header_ids.DELETE;
4479 
4480   l_progress := '100';
4481   -- For Attribute Values TLP,
4482   --   check that INTERFACE_LINE_ID is provided for which the attribute TLP needs to be created for
4483 
4484   -- SQL What: validate create action at attr TLP level
4485   -- SQL Why : To find incorrect action
4486   -- SQL Join: processing_id, action, interface_line_id
4487   UPDATE PO_ATTR_VALUES_TLP_INTERFACE POATI
4488   SET POATI.processing_id = -POATI.processing_id,
4489       POATI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4490   WHERE POATI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4491     AND POATI.action = PO_R12_CAT_UPG_PVT.g_action_tlp_create
4492     AND (
4493            POATI.language IS NULL
4494          OR
4495            POATI.interface_line_id IS NULL
4496          OR
4497             -- the following are NOT NULL columns in the TXN table, so they must
4498             -- have a not null value in the INTF table as well.
4499            (
4500             --POATI.po_line_id IS NULL OR
4501             POATI.req_template_name IS NULL OR
4502             POATI.req_template_line_num IS NULL OR
4503             POATI.org_id IS NULL OR
4504             POATI.inventory_item_id IS NULL OR
4505             POATI.ip_category_id IS NULL OR
4506             POATI.description IS NULL
4507            )
4508          OR
4509            (EXISTS
4510               (SELECT 'Invalid relationship with Line Level'
4511                FROM PO_LINES_INTERFACE POLI
4512                WHERE POLI.interface_line_id = POATI.interface_line_id
4513                  AND (  -- Attribute Row for GBPA must have appr action at line level
4514                         (POATI.req_template_name = g_NOT_REQUIRED_REQ_TEMPLATE AND
4515                          POATI.req_template_line_num = g_NOT_REQUIRED_ID AND
4516                          POLI.action NOT IN (PO_R12_CAT_UPG_PVT.g_action_line_create, 'UPDATE', 'DELETE'))
4517                       OR
4518                         -- Attribute Row for ReqTemplate must have action as REQTEMPALTE at line level
4519                         ((POATI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE OR
4520                           POATI.req_template_line_num <> g_NOT_REQUIRED_ID) AND
4521                          POLI.action NOT IN ('REQTEMPLATE'))
4522                      )
4523               )
4524            )
4525          OR
4526            ( -- For ReqTemplates, ALL the 3 columns must be given
4527              (POATI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE AND
4528               (POATI.req_template_line_num = g_NOT_REQUIRED_ID OR
4529                POATI.org_id = g_NOT_REQUIRED_ID))
4530              OR
4531              (POATI.req_template_line_num <> g_NOT_REQUIRED_ID AND
4532               (POATI.req_template_name = g_NOT_REQUIRED_REQ_TEMPLATE OR
4533                POATI.org_id = g_NOT_REQUIRED_ID))
4534            )
4535          OR
4536            (-- For ReqTemplates, the ReqTemplate Line must exist in Txn tables
4537             POATI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE AND
4538             POATI.req_template_line_num <> g_NOT_REQUIRED_ID AND
4539             POATI.org_id <> g_NOT_REQUIRED_ID AND
4540             NOT EXISTS
4541               (SELECT 'ReqTemplate Line in txn tables'
4542                FROM PO_REQEXPRESS_LINES_ALL PORT
4543                WHERE PORT.express_name = POATI.req_template_name
4544                  AND PORT.sequence_num = POATI.req_template_line_num
4545                  AND PORT.org_id = POATI.org_id)
4546            )
4547         )
4548   RETURNING POATI.interface_attr_values_tlp_id, POATI.interface_line_id, POATI.interface_header_id
4549   BULK COLLECT INTO l_err_attr_values_tlp_ids, l_err_line_ids, l_err_header_ids;
4550 
4551   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid CREATE action at TLP level='||SQL%rowcount); END IF;
4552 
4553   -- TODO: Similar SQL will be used to validate Artributes TLP for Req Templates
4554 
4555   l_progress := '110';
4556   -- Add error message into INTERFACE_ERRORS table
4557   FOR i in 1..l_err_attr_values_tlp_ids.COUNT
4558   LOOP
4559     PO_R12_CAT_UPG_UTL.add_fatal_error(
4560           p_interface_header_id => l_err_header_ids(i),
4561           p_interface_line_id   => l_err_line_ids(i),
4562           p_interface_attr_values_tlp_id => l_err_attr_values_tlp_ids(i),
4563           p_error_message_name  => 'PO_CAT_UPG_INVALID_TLP_ROW',
4564           p_table_name          => 'PO_ATTR_VALUES_INTERFACE',
4565           p_column_name         => 'INTERFACE_ATTR_VALUES_TLP_ID'
4566           );
4567   END LOOP;
4568 
4569   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
4570 EXCEPTION
4571   WHEN OTHERS THEN
4572     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
4573     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
4574 END validate_create_action;
4575 
4576 --------------------------------------------------------------------------------
4577 --Start of Comments
4578   --Name: validate_add_action
4579   --Pre-reqs:
4580   --  The iP catalog data is populated in PO Interface tables.
4581   --Modifies:
4582   --  a) PO_INTERFACE_ERRORS table: Inserts error messages for those rows that
4583   --     failed validation.
4584   --  b) FND_MSG_PUB on unhandled exceptions.
4585   --Locks:
4586   --  None.
4587   --Function:
4588   --  Validates ADD actions at line, attribute and TLP levels
4589   --     * For Headers,
4590   --         ADD action is not allowed.
4591   --     * For Lines,
4592   --         org_id check same as above for headers
4593   --         checks that a PO_HEADER_ID is provided where the line needs to be added to
4594   --         checks that the header document exists and was created by the Migration program
4595   --     * For Attributes,
4596   --         checks that a PO_LINE_ID is provided for which the attribute needs to be created for.
4597   --         checks that the document line exists for the given po_line_id
4598   --     * For Attributes TLP,
4599   --         checks that a PO_LINE_ID is provided for which the attribute TLP needs to be created for
4600   --         checks that the document line exists for the given po_line_id
4601   --         checks that the TLP row for that lang does not already exist
4602   --
4603   --  This API should be called during the upgrade phase only.
4604   --Parameters:
4605   --IN:
4606   --p_validate_only_mode
4607   --  Indicates if the API is being called in a Validate Only mode or not
4608   --OUT:
4609   -- None
4610   --
4611 --End of Comments
4612 --------------------------------------------------------------------------------
4613 PROCEDURE validate_add_action
4614 (
4615   p_validate_only_mode           IN VARCHAR2 default FND_API.G_FALSE
4616 )
4617 IS
4618   l_api_name      CONSTANT VARCHAR2(30) := 'validate_add_action';
4619   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
4620   l_progress      VARCHAR2(3) := '000';
4621 
4622   l_err_line_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4623   l_err_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4624   l_err_attr_values_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4625   l_err_attr_values_tlp_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4626 BEGIN
4627   l_progress := '010';
4628   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
4629 
4630   -----------------------------------------------------------------------------
4631   -- ADD action validations for Headers
4632   -----------------------------------------------------------------------------
4633 
4634   -- For Headers,
4635   --   ADD action is not allowed. Use ORIGINAL.
4636 
4637   -- SQL What: validate add action at header level
4638   -- SQL Why : To find incorrect action
4639   -- SQL Join: processing_id, action
4640   UPDATE PO_HEADERS_INTERFACE POHI
4641   SET POHI.processing_id = -POHI.processing_id,
4642       POHI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4643   WHERE POHI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4644     AND POHI.action = 'ADD'
4645   RETURNING POHI.interface_header_id
4646   BULK COLLECT INTO l_err_header_ids;
4647 
4648   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid ADD action at Header level='||SQL%rowcount); END IF;
4649 
4650   l_progress := '020';
4651   -- Add error message into INTERFACE_ERRORS table
4652   FOR i in 1..l_err_header_ids.COUNT
4653   LOOP
4654     PO_R12_CAT_UPG_UTL.add_fatal_error(
4655           p_interface_header_id => l_err_header_ids(i),
4656           p_error_message_name  => 'PO_CAT_UPG_ADD_NOT_ALLOWED',
4657           p_table_name          => 'PO_HEADERS_INTERFACE',
4658           p_column_name         => 'ACTION'
4659           );
4660   END LOOP;
4661 
4662   l_progress := '030';
4663   -- Cascade errors down to attribute and TLP levels
4664   -- Skip cascading of errors in Validate Only mode (iP Requirement - all errors should be reported)
4665   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
4666     PO_R12_CAT_UPG_UTL.reject_headers_intf('INTERFACE_HEADER_ID', l_err_header_ids, 'Y');
4667   END IF;
4668 
4669   -----------------------------------------------------------------------------
4670   -- ADD action validations for Lines
4671   -----------------------------------------------------------------------------
4672 
4673   l_progress := '040';
4674   -- For Lines,
4675   --   check that a PO_HEADER_ID is provided where the line needs to be added to
4676   --   (The Line may be added to a Line created by -12, or a pre-existing Header)
4677 
4678   -- SQL What: validate ADD action at line level
4679   -- SQL Why : To find incorrect action
4680   -- SQL Join: processing_id, action, po_header_id
4681   UPDATE PO_LINES_INTERFACE POLI
4682   SET POLI.processing_id = -POLI.processing_id,
4683       POLI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4684   WHERE POLI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4685     AND POLI.action = PO_R12_CAT_UPG_PVT.g_action_line_create -- ADD
4686     AND (POLI.interface_header_id IS NULL OR
4687          (POLI.po_header_id IS NOT NULL AND
4688           NOT EXISTS
4689            (SELECT 'PO_HEADER_ID points to valid doc'
4690             FROM PO_HEADERS_ALL POH
4691             WHERE POH.po_header_id = POLI.po_header_id)))
4692   RETURNING POLI.interface_line_id, POLI.interface_header_id
4693   BULK COLLECT INTO l_err_line_ids, l_err_header_ids;
4694 
4695   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid ADD action at Line level='||SQL%rowcount); END IF;
4696 
4697   l_progress := '050';
4698   -- Add error message into INTERFACE_ERRORS table
4699   FOR i in 1..l_err_line_ids.COUNT
4700   LOOP
4701     PO_R12_CAT_UPG_UTL.add_fatal_error(
4702           p_interface_header_id => l_err_header_ids(i),
4703           p_interface_line_id   => l_err_line_ids(i),
4704           p_error_message_name  => 'PO_CAT_UPG_INVALID_HEADER_ID',
4705           p_table_name          => 'PO_LINES_INTERFACE',
4706           p_column_name         => 'PO_HEADER_ID'
4707           );
4708   END LOOP;
4709 
4710   l_progress := '060';
4711   -- Cascade errors down to attribute and TLP levels
4712   -- Skip cascading of errors in Validate Only mode (iP Requirement - all errors should be reported)
4713   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
4714     PO_R12_CAT_UPG_UTL.reject_attr_values_intf('INTERFACE_LINE_ID', l_err_line_ids);
4715     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
4716   END IF;
4717 
4718   -----------------------------------------------------------------------------
4719   -- ORIGINAL action validations for Attribute Values
4720   -----------------------------------------------------------------------------
4721 
4722   l_progress := '070';
4723   -- For Attributes,
4724   --   ORIGINAL action is not allowed. Use ADD.
4725 
4726   -- SQL What: validate create action at attr level
4727   -- SQL Why : To find incorrect action
4728   -- SQL Join: processing_id, action, po_line_id
4729   UPDATE PO_ATTR_VALUES_INTERFACE POAI
4730   SET POAI.processing_id = -POAI.processing_id,
4731       POAI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4732   WHERE POAI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4733     AND POAI.action = 'ORIGINAL'
4734   RETURNING POAI.interface_attr_values_id, POAI.interface_line_id, POAI.interface_header_id
4735   BULK COLLECT INTO l_err_attr_values_ids, l_err_line_ids, l_err_header_ids;
4736 
4737   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid ORIGINAL action at Attr level='||SQL%rowcount); END IF;
4738 
4739   -- TODO: Similar SQL will be used to validate Artributes for Req Templates
4740 
4741   l_progress := '080';
4742   -- Add error message into INTERFACE_ERRORS table
4743   FOR i in 1..l_err_attr_values_ids.COUNT
4744   LOOP
4745     PO_R12_CAT_UPG_UTL.add_fatal_error(
4746           p_interface_header_id => l_err_header_ids(i),
4747           p_interface_line_id   => l_err_line_ids(i),
4748           p_interface_attr_values_id => l_err_attr_values_ids(i),
4749           p_error_message_name  => 'PO_CAT_UPG_ORIG_NOT_ALLOWED',
4750           p_table_name          => 'PO_ATTR_VALUES_INTERFACE',
4751           p_column_name         => 'ACTION'
4752           );
4753   END LOOP;
4754 
4755   l_progress := '090';
4756   -- Cascade errors down to TLP level
4757   -- Skip cascading of errors in Validate Only mode.
4758   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
4759     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
4760   END IF;
4761 
4762   -----------------------------------------------------------------------------
4763   -- ORIGINAL action validations for Attribute Values TLP
4764   -----------------------------------------------------------------------------
4765 
4766   l_progress := '100';
4767   -- For Attribute Values TLP,
4768   --   ORIGINAL action is not allowed. Use ADD.
4769 
4770   -- SQL What: validate create action at attr TLP level
4771   -- SQL Why : To find incorrect action
4772   -- SQL Join: processing_id, action, po_line_id
4773   UPDATE PO_ATTR_VALUES_TLP_INTERFACE POATI
4774   SET POATI.processing_id = -POATI.processing_id,
4775       POATI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4776   WHERE POATI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4777     AND POATI.action = 'ORIGINAL'
4778   RETURNING POATI.interface_attr_values_tlp_id, POATI.interface_line_id, POATI.interface_header_id
4779   BULK COLLECT INTO l_err_attr_values_tlp_ids, l_err_line_ids, l_err_header_ids;
4780 
4781   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid ORIGINAL action at TLP level='||SQL%rowcount); END IF;
4782 
4783   -- TODO: Similar SQL will be used to validate Artributes TLP for Req Templates
4784 
4785   l_progress := '110';
4786   -- Add error message into INTERFACE_ERRORS table
4787   FOR i in 1..l_err_attr_values_tlp_ids.COUNT
4788   LOOP
4789     PO_R12_CAT_UPG_UTL.add_fatal_error(
4790           p_interface_header_id => l_err_header_ids(i),
4791           p_interface_line_id   => l_err_line_ids(i),
4792           p_interface_attr_values_tlp_id => l_err_attr_values_tlp_ids(i),
4793           p_error_message_name  => 'PO_CAT_UPG_ORIG_NOT_ALLOWED',
4794           p_table_name          => 'PO_ATTR_VALUES_TLP_INTERFACE',
4795           p_column_name         => 'ACTION'
4796           );
4797   END LOOP;
4798 
4799   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
4800 EXCEPTION
4801   WHEN OTHERS THEN
4802     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
4803     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
4804 END validate_add_action;
4805 
4806 --------------------------------------------------------------------------------
4807 --Start of Comments
4808   --Name: validate_update_action
4809   --Pre-reqs:
4810   --  The iP catalog data is populated in PO Interface tables.
4811   --Modifies:
4812   --  a) PO_INTERFACE_ERRORS table: Inserts error messages for those rows that
4813   --     failed validation.
4814   --  b) FND_MSG_PUB on unhandled exceptions.
4815   --Locks:
4816   --  None.
4817   --Function:
4818   --  Validates UPDATE actions at header, line, attribute and TLP levels
4819   --     * For Headers,
4820   --         check that the ORG_ID is provided (used for defaulting from PSP, etc.)
4821   --         checks that a PO_HEADER_ID is provided that needs to be updated
4822   --         checks that the po_header_id points to a valid document
4823   --     * For Lines,
4824   --         checks that a PO_LINE_ID is provided that needs to be updated
4825   --         checks that the po_line_id points to a valid document
4826   --     * For Attributes,
4827   --         checks that a PO_LINE_ID is provided for which attr needs to be updated
4828   --         checks that the po_line_id points to a valid document
4829   --     * For Attributes TLP,
4830   --         checks that a PO_LINE_ID is provided for which TLP needs to be updated
4831   --         checks that the po_line_id points to a valid document
4832   --         check that a TLP row for the given language exists for updation
4833   --
4834   --  This API should be called during the upgrade phase only.
4835   --Parameters:
4836   --IN:
4837   --p_validate_only_mode
4838   --  Indicates if the API is being called in a Validate Only mode or not
4839   --OUT:
4840   -- None
4841   --
4842 --End of Comments
4843 --------------------------------------------------------------------------------
4844 PROCEDURE validate_update_action
4845 (
4846   p_validate_only_mode           IN VARCHAR2 default FND_API.G_FALSE
4847 )
4848 IS
4849   l_api_name      CONSTANT VARCHAR2(30) := 'validate_update_action';
4850   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
4851   l_progress      VARCHAR2(3) := '000';
4852 
4853   l_err_line_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4854   l_err_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4855   l_err_attr_values_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4856   l_err_attr_values_tlp_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
4857 BEGIN
4858   l_progress := '010';
4859   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
4860 
4861   -----------------------------------------------------------------------------
4862   -- UPDATE action validations for Headers
4863   -----------------------------------------------------------------------------
4864 
4865   -- For Headers,
4866   --   check that a PO_HEADER_ID is provided that needs to be updated
4867   --   check that the po_header_id points to an existing document
4868 
4869   -- SQL What: validate update action at Header level
4870   -- SQL Why : To find incorrect action
4871   -- SQL Join: processing_id, action, po_header_id
4872   UPDATE PO_HEADERS_INTERFACE POHI
4873   SET POHI.processing_id = -POHI.processing_id,
4874       POHI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4875   WHERE POHI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4876     AND POHI.action = 'UPDATE'
4877     AND (POHI.po_header_id is null
4878          OR NOT EXISTS
4879            (SELECT 'document exists'
4880             FROM PO_HEADERS_ALL POH
4881             WHERE POH.po_header_id = POHI.po_header_id))
4882   RETURNING POHI.interface_header_id
4883   BULK COLLECT INTO l_err_header_ids;
4884 
4885   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid UPDATE action at Header level='||SQL%rowcount); END IF;
4886 
4887   l_progress := '020';
4888   -- Add error message into INTERFACE_ERRORS table
4889   FOR i in 1..l_err_header_ids.COUNT
4890   LOOP
4891     PO_R12_CAT_UPG_UTL.add_fatal_error(
4892           p_interface_header_id => l_err_header_ids(i),
4893           p_error_message_name  => 'PO_CAT_UPG_INVALID_HEADER_ID',
4894           p_table_name          => 'PO_HEADERS_INTERFACE',
4895           p_column_name         => 'PO_HEADER_ID'
4896           );
4897   END LOOP;
4898 
4899   l_progress := '030';
4900   -- Cascade errors down to attribute and TLP levels
4901   -- Skip cascading of errors in Validate Only mode.
4902   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
4903     PO_R12_CAT_UPG_UTL.reject_lines_intf(p_id_param_type => 'INTERFACE_HEADER_ID',
4904                                          p_id_tbl        => l_err_header_ids,
4905                                          p_cascade       => 'Y');
4906   END IF;
4907 
4908   -----------------------------------------------------------------------------
4909   -- UPDATE action validations for Lines
4910   -----------------------------------------------------------------------------
4911 
4912   -- For Lines,
4913   --   check that a PO_LINE_ID is provided that needs to be updated
4914   --   check that the po_line_id points to an existing document
4915 
4916   -- SQL What: validate update action at Line level
4917   -- SQL Why : To find incorrect action
4918   -- SQL Join: processing_id, action, po_line_id
4919   UPDATE PO_LINES_INTERFACE POLI
4920   SET POLI.processing_id = -POLI.processing_id,
4921       POLI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4922   WHERE POLI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4923     AND POLI.action = 'UPDATE'
4924     AND (POLI.po_line_id is null
4925          OR NOT EXISTS
4926            (SELECT 'line exists'
4927             FROM PO_LINES_ALL POL
4928             WHERE POL.po_line_id = POLI.po_line_id))
4929   RETURNING POLI.interface_line_id, POLI.interface_header_id
4930   BULK COLLECT INTO l_err_line_ids, l_err_header_ids;
4931 
4932   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid UPDATE action at Line level='||SQL%rowcount); END IF;
4933 
4934   l_progress := '040';
4935   -- Add error message into INTERFACE_ERRORS table
4936   FOR i in 1..l_err_line_ids.COUNT
4937   LOOP
4938     PO_R12_CAT_UPG_UTL.add_fatal_error(
4939           p_interface_header_id => l_err_header_ids(i),
4940           p_interface_line_id   => l_err_line_ids(i),
4941           p_error_message_name  => 'PO_CAT_UPG_INVALID_LINE_ID',
4942           p_table_name          => 'po_lines_interface',
4943           p_column_name         => 'PO_LINE_ID'
4944           );
4945   END LOOP;
4946 
4947   l_progress := '050';
4948   -- Cascade errors down to attribute and TLP levels
4949   -- Skip cascading of errors in Validate Only mode.
4950   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
4951     PO_R12_CAT_UPG_UTL.reject_attr_values_intf('INTERFACE_LINE_ID', l_err_line_ids);
4952     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
4953   END IF;
4954 
4955   -----------------------------------------------------------------------------
4956   -- UPDATE action validations for Attribute Values
4957   -----------------------------------------------------------------------------
4958 
4959   l_progress := '060';
4960   -- For Attributes,
4961   -- If all 3 Primary Keys are NULL, its an error
4962   -- We need at least one PK reference to update in txn tables
4963   -- If PO_LINE_ID is given then RT keys must be null
4964   -- IF PO_LINE_ID is given, then Attr for line must exist
4965   -- IF RT keys is given, then Attr for RT line must exist
4966 
4967   -- SQL What: validate update action at attr level
4968   -- SQL Why : To find incorrect action
4969   -- SQL Join: processing_id, action, po_line_id
4970   UPDATE PO_ATTR_VALUES_INTERFACE POAI
4971   SET POAI.processing_id = -POAI.processing_id,
4972       POAI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
4973   WHERE POAI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
4974     AND POAI.action = 'UPDATE'
4975     AND (
4976             -- the following are NOT NULL columns in the TXN table, so they must
4977             -- have a not null value in the INTF table as well.
4978            (
4979             POAI.po_line_id IS NULL OR
4980             POAI.req_template_name IS NULL OR
4981             POAI.req_template_line_num IS NULL OR
4982             POAI.org_id IS NULL OR
4983             POAI.inventory_item_id IS NULL
4984             --OR POAI.ip_category_id IS NULL
4985            )
4986          OR
4987           -- If all 3 Primary Keys are -2, its an error
4988           -- We need at least one PK reference to update in txn tables
4989            (POAI.po_line_id = g_NOT_REQUIRED_ID
4990             AND (POAI.req_template_name = g_NOT_REQUIRED_REQ_TEMPLATE
4991                  OR POAI.req_template_line_num = g_NOT_REQUIRED_ID))
4992 
4993          ---------------------------------------------------
4994          -- If PO_LINE_ID is given then RT keys must be null
4995          OR
4996            (POAI.po_line_id <> g_NOT_REQUIRED_ID
4997             AND (POAI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE
4998                  OR POAI.req_template_line_num <> g_NOT_REQUIRED_ID))
4999          ---------------------------------------------------
5000 
5001          -- IF PO_LINE_ID is given, then Attr for line must exist
5002          OR
5003            (POAI.po_line_id <> g_NOT_REQUIRED_ID
5004             AND NOT EXISTS
5005               (SELECT 'Attribute row exists for PO Line'
5006                FROM PO_ATTRIBUTE_VALUES POAV
5007                WHERE POAV.po_line_id = POAI.po_line_id))
5008          -- IF RT keys is given, then Attr for RT line must exist
5009          OR
5010            (POAI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE
5011             AND POAI.req_template_line_num <> g_NOT_REQUIRED_ID
5012             AND NOT EXISTS
5013               (SELECT 'Attribute row exists for Req Template Line'
5014                FROM PO_ATTRIBUTE_VALUES POAV
5015                WHERE POAV.req_template_name = POAI.req_template_name
5016                  AND POAV.req_template_line_num = POAI.req_template_line_num))
5017         )
5018   RETURNING POAI.interface_attr_values_id, POAI.interface_line_id, POAI.interface_header_id
5019   BULK COLLECT INTO l_err_attr_values_ids, l_err_line_ids, l_err_header_ids;
5020 
5021   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid UPDATE action at Attr level='||SQL%rowcount); END IF;
5022 
5023   l_progress := '070';
5024   -- Add error message into INTERFACE_ERRORS table
5025   FOR i in 1..l_err_attr_values_ids.COUNT
5026   LOOP
5027     PO_R12_CAT_UPG_UTL.add_fatal_error(
5028           p_interface_header_id => l_err_header_ids(i),
5029           p_interface_line_id   => l_err_line_ids(i),
5030           p_interface_attr_values_id => l_err_attr_values_ids(i),
5031           p_error_message_name  => 'PO_CAT_UPG_INVALID_LINE_ID',
5032           p_table_name          => 'po_attr_values_interface',
5033           p_column_name         => 'PO_LINE_ID'
5034           );
5035   END LOOP;
5036 
5037   l_progress := '080';
5038   -- Cascade errors down to TLP level
5039   -- Skip cascading of errors in Validate Only mode.
5040   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
5041     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
5042   END IF;
5043 
5044   -----------------------------------------------------------------------------
5045   -- UPDATE action validations for Attribute Values TLP
5046   -----------------------------------------------------------------------------
5047 
5048   l_progress := '090';
5049   -- For Attribute Values TLP,
5050   -- If all 3 Primary Keys are NULL, its an error
5051   -- We need at least one PK reference to update in txn tables
5052   -- If language is NULL, it is an error.
5053   -- If PO_LINE_ID is given then RT keys must be null
5054   -- IF PO_LINE_ID is given, then Attr for line must exist
5055   -- IF RT keys is given, then Attr for RT line must exist
5056 
5057   -- SQL What: validate update action at attr TLP level
5058   -- SQL Why : To find incorrect action
5059   -- SQL Join: processing_id, action, po_line_id
5060   UPDATE PO_ATTR_VALUES_TLP_INTERFACE POATI
5061   SET POATI.processing_id = -POATI.processing_id,
5062       POATI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
5063   WHERE POATI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
5064     AND POATI.action = 'UPDATE'
5065     AND (
5066             -- the following are NOT NULL columns in the TXN table, so they must
5067             -- have a not null value in the INTF table as well.
5068            (
5069             POATI.po_line_id IS NULL OR
5070             POATI.req_template_name IS NULL OR
5071             POATI.req_template_line_num IS NULL OR
5072             POATI.org_id IS NULL OR
5073             POATI.inventory_item_id IS NULL OR
5074             POATI.ip_category_id IS NULL --OR
5075             --POATI.description IS NULL
5076            )
5077 
5078          OR POATI.language IS NULL
5079 
5080          OR
5081          -- If all 3 Primary Keys are NULL, its an error
5082          -- We need at least one PK reference to update in txn tables
5083            (POATI.po_line_id = g_NOT_REQUIRED_ID
5084             AND (POATI.req_template_name = g_NOT_REQUIRED_REQ_TEMPLATE
5085                  OR POATI.req_template_line_num = g_NOT_REQUIRED_ID))
5086 
5087          ---------------------------------------------------
5088          -- If PO_LINE_ID is given then RT keys must be null
5089          OR
5090            (POATI.po_line_id <> g_NOT_REQUIRED_ID
5091             AND (POATI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE
5092                  OR POATI.req_template_line_num <> g_NOT_REQUIRED_ID))
5093          ---------------------------------------------------
5094 
5095          -- IF PO_LINE_ID is given, then Attr for line must exist
5096          OR
5097            (POATI.po_line_id <> g_NOT_REQUIRED_ID
5098             AND NOT EXISTS
5099               (SELECT 'Attribute TLP row exists for PO Line'
5100                FROM PO_ATTRIBUTE_VALUES_TLP POTLP
5101                WHERE POTLP.po_line_id = POATI.po_line_id
5102                  AND POTLP.language = POATI.language))
5103          -- IF RT keys is given, then:
5104          --   1. ORG_ID must be given
5105          --   2. TLP row for RT line must exist
5106          OR
5107            (POATI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE
5108             AND POATI.req_template_line_num <> g_NOT_REQUIRED_ID
5109             AND (POATI.org_id = g_NOT_REQUIRED_ID OR
5110                  NOT EXISTS
5111                   (SELECT 'Attribute row exists for Req Template Line'
5112                    FROM PO_ATTRIBUTE_VALUES_TLP POTLP
5113                    WHERE POTLP.req_template_name = POATI.req_template_name
5114                      AND POTLP.req_template_line_num = POATI.req_template_line_num
5115                      AND POTLP.org_id = POATI.org_id
5116                      AND POTLP.language = POATI.language)))
5117         )
5118   RETURNING POATI.interface_attr_values_tlp_id, POATI.interface_line_id, POATI.interface_header_id
5119   BULK COLLECT INTO l_err_attr_values_tlp_ids, l_err_line_ids, l_err_header_ids;
5120 
5121   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid UPDATE action at TLP level='||SQL%rowcount); END IF;
5122 
5123   l_progress := '100';
5124   -- Add error message into INTERFACE_ERRORS table
5125   FOR i in 1..l_err_attr_values_tlp_ids.COUNT
5126   LOOP
5127     PO_R12_CAT_UPG_UTL.add_fatal_error(
5128           p_interface_header_id => l_err_header_ids(i),
5129           p_interface_line_id   => l_err_line_ids(i),
5130           p_interface_attr_values_tlp_id => l_err_attr_values_tlp_ids(i),
5131           p_error_message_name  => 'PO_CAT_UPG_INVALID_LINE_ID',
5132           p_table_name          => 'po_attr_values_tlp_interface',
5133           p_column_name         => 'PO_LINE_ID'
5134           );
5135   END LOOP;
5136 
5137   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
5138 EXCEPTION
5139   WHEN OTHERS THEN
5140     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
5141     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
5142 END validate_update_action;
5143 
5144 --------------------------------------------------------------------------------
5145 --Start of Comments
5146   --Name: validate_delete_action
5147   --Pre-reqs:
5148   --  The iP catalog data is populated in PO Interface tables.
5149   --Modifies:
5150   --  a) PO_INTERFACE_ERRORS table: Inserts error messages for those rows that
5151   --     failed validation.
5152   --  b) FND_MSG_PUB on unhandled exceptions.
5153   --Locks:
5154   --  None.
5155   --Function:
5156   --  Validates DELETE action at header, line, attribute and TLP levels
5157   --     * For Headers,
5158   --         checks that a PO_HEADER_ID is provided that needs to be deleted
5159   --         checks that the document exists and was created by the Migration program
5160   --     * For Lines,
5161   --         checks that a PO_LINE_ID is provided that needs to be deleted
5162   --         checks that the document exists and was created by the Migration program
5163   --     * For Attributes,
5164   --         Never allow deletion of attribute row.
5165   --     * For Attributes TLP,
5166   --         checks that a PO_LINE_ID is provided for which TLP needs to be deleted
5167   --         Never allow deletion of TLP for for the created_lang
5168   --         check that a TLP row for the given language exists for deletion
5169   --
5170   --  This API should be called during the upgrade phase only.
5171   --Parameters:
5172   --IN:
5173   --p_validate_only_mode
5174   --  Indicates if the API is being called in a Validate Only mode or not
5175   --OUT:
5176   -- None
5177   --
5178 --End of Comments
5179 --------------------------------------------------------------------------------
5180 PROCEDURE validate_delete_action
5181 (
5182   p_validate_only_mode           IN VARCHAR2 default FND_API.G_FALSE
5183 )
5184 IS
5185   l_api_name      CONSTANT VARCHAR2(30) := 'validate_delete_action';
5186   l_log_head      CONSTANT VARCHAR2(100) := g_module_prefix || l_api_name;
5187   l_progress      VARCHAR2(3) := '000';
5188 
5189   l_err_line_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
5190   l_err_header_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
5191   l_err_attr_values_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
5192   l_err_attr_values_tlp_ids PO_R12_CAT_UPG_TYPES.PO_TBL_NUMBER;
5193 
5194   l_base_language FND_LANGUAGES.language_code%TYPE;
5195 BEGIN
5196   l_progress := '010';
5197   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'START'); END IF;
5198 
5199   -----------------------------------------------------------------------------
5200   -- DELETE action validations for Headers
5201   -----------------------------------------------------------------------------
5202 
5203   -- For Headers,
5204   --   check that a PO_HEADER_ID is provided that needs to be deleted
5205   --   check that the po_header_id points to a valid document
5206 
5207   -- SQL What: validate delete action at header level
5208   -- SQL Why : To find incorrect action
5209   -- SQL Join: processing_id, action, po_header_id
5210   UPDATE PO_HEADERS_INTERFACE POHI
5211   SET POHI.processing_id = -POHI.processing_id,
5212       POHI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
5213   WHERE POHI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
5214     AND POHI.action = 'DELETE'
5215     AND (POHI.po_header_id is null
5216          OR EXISTS
5217            (SELECT 'document not created by migration program'
5218             FROM PO_HEADERS_ALL POH
5219             WHERE POH.po_header_id = POHI.po_header_id
5220               AND POH.created_by <> PO_R12_CAT_UPG_PVT.g_R12_UPGRADE_USER))
5221   RETURNING POHI.interface_header_id
5222   BULK COLLECT INTO l_err_header_ids;
5223 
5224   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid DELETE action at Header level='||SQL%rowcount); END IF;
5225 
5226   l_progress := '020';
5227   -- Add error message into INTERFACE_ERRORS table
5228   FOR i in 1..l_err_header_ids.COUNT
5229   LOOP
5230     PO_R12_CAT_UPG_UTL.add_fatal_error(
5231           p_interface_header_id => l_err_header_ids(i),
5232           p_error_message_name  => 'PO_CAT_UPG_INVALID_HEADER_ID',
5233           p_table_name          => 'po_headers_interface',
5234           p_column_name         => 'PO_HEADER_ID'
5235           );
5236   END LOOP;
5237 
5238   l_progress := '030';
5239   -- Cascade errors down to attribute and TLP levels
5240   -- Skip cascading of errors in Validate Only mode.
5241   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
5242     PO_R12_CAT_UPG_UTL.reject_lines_intf(p_id_param_type => 'INTERFACE_HEADER_ID',
5243                                          p_id_tbl        => l_err_header_ids,
5244                                          p_cascade       => 'Y');
5245   END IF;
5246 
5247   -----------------------------------------------------------------------------
5248   -- DELETE action validations for Lines
5249   -----------------------------------------------------------------------------
5250 
5251   -- For Lines,
5252   --   check that a PO_LINE_ID is provided that needs to be deleted
5253   --   check that the document was created by the Migration program
5254 
5255   -- SQL What: validate delete action at line level
5256   -- SQL Why : To find incorrect action
5257   -- SQL Join: processing_id, action, po_line_id
5258   UPDATE PO_LINES_INTERFACE POLI
5259   SET POLI.processing_id = -POLI.processing_id,
5260       POLI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
5261   WHERE POLI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
5262     AND POLI.action = 'DELETE'
5263     AND (POLI.po_line_id is null
5264          OR EXISTS
5265            (SELECT 'line not created by migration program'
5266             FROM PO_LINES_ALL POL
5267             WHERE POL.po_line_id = POLI.po_line_id
5268               AND POL.created_by <> PO_R12_CAT_UPG_PVT.g_R12_UPGRADE_USER))
5269   RETURNING POLI.interface_line_id, POLI.interface_header_id
5270   BULK COLLECT INTO l_err_line_ids, l_err_header_ids;
5271 
5272   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid DELETE action at Line level='||SQL%rowcount); END IF;
5273 
5274   l_progress := '040';
5275   -- Add error message into INTERFACE_ERRORS table
5276   FOR i in 1..l_err_line_ids.COUNT
5277   LOOP
5278     PO_R12_CAT_UPG_UTL.add_fatal_error(
5279           p_interface_header_id => l_err_header_ids(i),
5280           p_interface_line_id   => l_err_line_ids(i),
5281           p_error_message_name  => 'PO_CAT_UPG_INVALID_LINE_ID',
5282           p_table_name          => 'po_lines_interface',
5283           p_column_name         => 'PO_LINE_ID'
5284           );
5285   END LOOP;
5286 
5287   l_progress := '050';
5288   -- Cascade errors down to attribute and TLP levels
5289   -- Skip cascading of errors in Validate Only mode.
5290   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
5291     PO_R12_CAT_UPG_UTL.reject_attr_values_intf('INTERFACE_LINE_ID', l_err_line_ids);
5292     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
5293   END IF;
5294 
5295   -----------------------------------------------------------------------------
5296   -- DELETE action validations for Attribute Values
5297   -----------------------------------------------------------------------------
5298 
5299   l_progress := '060';
5300   -- For Attributes,
5301   --   Never allow deletion of attribute row
5302   --   If required for Lines created by -12, the Line level delete would delete
5303   --   the Attr row also.
5304   --   For ReqTemplates you may only UPDATE an Attr row, you may not
5305   --   delete it.
5306 
5307   -- SQL What: validate delete action at attr level
5308   -- SQL Why : To find incorrect action
5309   -- SQL Join: processing_id, action
5310   UPDATE PO_ATTR_VALUES_INTERFACE POAI
5311   SET POAI.processing_id = -POAI.processing_id,
5312       POAI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
5313   WHERE POAI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
5314     AND POAI.action = 'DELETE'
5315   RETURNING POAI.interface_attr_values_id, POAI.interface_line_id, POAI.interface_header_id
5316   BULK COLLECT INTO l_err_attr_values_ids, l_err_line_ids, l_err_header_ids;
5317 
5318   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid DELETE action at Attr level='||SQL%rowcount); END IF;
5319 
5320   l_progress := '070';
5321   -- Add error message into INTERFACE_ERRORS table
5322   FOR i in 1..l_err_attr_values_ids.COUNT
5323   LOOP
5324     PO_R12_CAT_UPG_UTL.add_fatal_error(
5325           p_interface_header_id => l_err_header_ids(i),
5326           p_interface_line_id   => l_err_line_ids(i),
5327           p_interface_attr_values_id => l_err_attr_values_ids(i),
5328           p_error_message_name  => 'PO_CAT_UPG_CANT_DEL_ATTR',
5329           p_table_name          => 'po_attr_values_interface',
5330           p_column_name         => 'ATTRIBUTE_VALUE_ID'
5331           );
5332   END LOOP;
5333 
5334   l_progress := '080';
5335   -- Cascade errors down to TLP level
5336   -- Skip cascading of errors in Validate Only mode.
5337   IF (p_validate_only_mode = FND_API.G_FALSE) THEN
5338     PO_R12_CAT_UPG_UTL.reject_attr_values_tlp_intf('INTERFACE_LINE_ID', l_err_line_ids);
5339   END IF;
5340 
5341   -----------------------------------------------------------------------------
5342   -- DELETE action validations for Attribute Values TLP
5343   -----------------------------------------------------------------------------
5344 
5345   l_progress := '090';
5346   l_base_language := PO_R12_CAT_UPG_UTL.get_base_lang;
5347 
5348   -- For Attribute Values TLP,
5349   --   Check that a Unique Key is provided for which the attribute TLP needs to be deleted
5350   --   Unique key for TLP table is:
5351   --
5352   --         LANGUAGE
5353   --         PO_LINE_ID
5354   --         (REQ_TEMPLATE_NAME, REQ_TEMPLATE_LINE_NUM, ORG_ID)
5355   --
5356   --   For GBPA/BPA/Quotations:
5357   --     Never allow deletion of TLP row for created_language
5358   --   For ReqTemplates:
5359   --     Never allow deletion of TLP row for base_language.
5360   --
5361   --   Check that a TLP row for the given language exists for deletion
5362   --
5363   --   Note: If required for Lines created by -12, the Line level delete would delete
5364   --   the Attr TLP row also.
5365   --   For GBPA/BPA/Quotations you may only UPDATE an Attr row with the created_language
5366   --   you may not delete it.
5367   --   For ReqTemplates s you may only UPDATE an Attr row with the base_language
5368   --   you may not delete it.
5369 
5370   -- SQL What: validate delete action at attr TLP level
5371   -- SQL Why : To find incorrect action
5372   -- SQL Join: processing_id, action, ppo_line_id
5373   UPDATE PO_ATTR_VALUES_TLP_INTERFACE POATI
5374   SET POATI.processing_id = -POATI.processing_id,
5375       POATI.process_code = PO_R12_CAT_UPG_PVT.g_PROCESS_CODE_REJECTED
5376   WHERE POATI.processing_id = PO_R12_CAT_UPG_PVT.g_processing_id
5377     AND POATI.action = 'DELETE'
5378     AND (
5379             -- the following are NOT NULL columns in the TXN table, so they must
5380             -- have a not null value in the INTF table as well.
5381            (
5382             POATI.po_line_id IS NULL OR
5383             POATI.req_template_name IS NULL OR
5384             POATI.req_template_line_num IS NULL OR
5385             POATI.org_id IS NULL
5386            )
5387 
5388          OR POATI.language IS NULL
5389 
5390          OR
5391          -- If all 3 Primary Keys are NULL, its an error
5392          -- We need at least one PK reference to update in txn tables
5393            (POATI.po_line_id = g_NOT_REQUIRED_ID
5394             AND (POATI.req_template_name = g_NOT_REQUIRED_REQ_TEMPLATE
5395                  OR POATI.req_template_line_num = g_NOT_REQUIRED_ID))
5396 
5397          ---------------------------------------------------
5398          -- If PO_LINE_ID is given then RT keys must be null
5399          OR
5400            (POATI.po_line_id <> g_NOT_REQUIRED_ID
5401             AND (POATI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE
5402                  OR POATI.req_template_line_num <> g_NOT_REQUIRED_ID))
5403          ---------------------------------------------------
5404 
5405          -- IF PO_LINE_ID is given, then Attr for line must exist
5406          OR
5407            (POATI.po_line_id <> g_NOT_REQUIRED_ID
5408             AND NOT EXISTS
5409               (SELECT 'Attribute TLP row exists for PO Line'
5410                FROM PO_ATTRIBUTE_VALUES_TLP POTLP
5411                WHERE POTLP.po_line_id = POATI.po_line_id
5412                  AND POTLP.language = POATI.language))
5413          -- IF RT keys is given, then:
5414          --    1. ORG_ID must be given
5415          --    2. TLP row for RT line must exist
5416          OR
5417            (POATI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE
5418             AND POATI.req_template_line_num <> g_NOT_REQUIRED_ID
5419             AND (POATI.org_id = g_NOT_REQUIRED_ID OR
5420                  NOT EXISTS
5421                   (SELECT 'Attribute row exists for Req Template Line'
5422                    FROM PO_ATTRIBUTE_VALUES_TLP POTLP
5423                    WHERE POTLP.req_template_name = POATI.req_template_name
5424                      AND POTLP.req_template_line_num = POATI.req_template_line_num
5425                      AND POTLP.org_id = POATI.org_id
5426                      AND POTLP.language = POATI.language)))
5427          ---------------------------------------------------
5428 
5429          -- For GBPA/BPA/Quotations, you can not delete TLP row for created_language
5430          OR (POATI.po_line_id <> g_NOT_REQUIRED_ID
5431              AND EXISTS
5432               (SELECT 'TLP row for deletion is specified for created_lang'
5433                FROM PO_LINES_ALL POL,
5434                     PO_HEADERS_ALL POH
5435                WHERE POL.po_line_id = POATI.po_line_id
5436                  AND POH.po_header_id = POL.po_header_id
5437                  AND POH.created_language = POATI.language))
5438          -- For ReqTemplates, you can not delete TLP row for base_language
5439          OR (POATI.req_template_name <> g_NOT_REQUIRED_REQ_TEMPLATE AND
5440              POATI.req_template_line_num <> g_NOT_REQUIRED_ID AND
5441              POATI.language = l_base_language)
5442         )
5443   RETURNING POATI.interface_attr_values_tlp_id, POATI.interface_line_id, POATI.interface_header_id
5444   BULK COLLECT INTO l_err_attr_values_tlp_ids, l_err_line_ids, l_err_header_ids;
5445 
5446   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Number of invalid DELETE action at TLP level='||SQL%rowcount); END IF;
5447 
5448   l_progress := '100';
5449   -- Add error message into INTERFACE_ERRORS table
5450   FOR i in 1..l_err_attr_values_tlp_ids.COUNT
5451   LOOP
5452     PO_R12_CAT_UPG_UTL.add_fatal_error(
5453           p_interface_header_id => l_err_header_ids(i),
5454           p_interface_line_id   => l_err_line_ids(i),
5455           p_interface_attr_values_tlp_id => l_err_attr_values_tlp_ids(i),
5456           p_error_message_name  => 'PO_CAT_UPG_INVALID_LINE_ID',
5457           p_table_name          => 'po_attr_values_tlp_interface',
5458           p_column_name         => 'PO_LINE_ID'
5459           );
5460     END LOOP;
5461 
5462   IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'END'); END IF;
5463 EXCEPTION
5464   WHEN OTHERS THEN
5465     IF g_debug THEN PO_R12_CAT_UPG_DEBUG.log_stmt(l_log_head,l_progress,'Unexpected exception'); END IF;
5466     RAISE_APPLICATION_ERROR(g_err_num,l_log_head||','||l_progress || ','|| SQLERRM);
5467 END validate_delete_action;
5468 
5469 
5470 END PO_R12_CAT_UPG_VAL_PVT;