[Home] [Help]
PACKAGE BODY: APPS.PO_DOCUMENT_UPDATE_PVT
Source
1 PACKAGE BODY PO_DOCUMENT_UPDATE_PVT AS
2 /* $Header: POXVCPOB.pls 120.43.12010000.2 2008/08/22 21:00:55 rarajar ship $*/
3
4 -- Read the profile option that enables/disables the debug log
5 g_fnd_debug VARCHAR2(1) := NVL(FND_PROFILE.VALUE('AFLOG_ENABLED'),'N');
6
7 g_application_id CONSTANT NUMBER := 201;
8 g_pkg_name CONSTANT VARCHAR2(30) := 'PO_DOCUMENT_UPDATE_PVT';
9 g_module_prefix CONSTANT VARCHAR2(40) := 'po.plsql.' || g_pkg_name || '.';
10
11 -- Submission Checks rounds to 10 places, so we will round to 10 as well:
12 g_qty_precision CONSTANT NUMBER := 10;
13
14 g_user_id NUMBER := fnd_global.user_id;
15 g_login_id NUMBER := fnd_global.login_id;
16 g_business_group_id NUMBER := NVL(hr_general.get_business_group_id, -99);
17 g_retroactive_price_change VARCHAR2(1);
18 g_opm_installed BOOLEAN;
19 g_gml_common_rcv_installed BOOLEAN;
20
21 g_api_errors PO_API_ERRORS_REC_TYPE;
22 g_update_source VARCHAR2(100);
23
24 g_document_id PO_HEADERS.po_header_id%TYPE;
25 g_document_type PO_DOCUMENT_TYPES_ALL_B.document_type_code%TYPE;
26 g_document_subtype PO_DOCUMENT_TYPES_ALL_B.document_subtype%TYPE;
27 g_po_header_id PO_HEADERS.po_header_id%TYPE;
28 g_po_release_id PO_RELEASES.po_release_id%TYPE;
29
30 g_archive_mode PO_DOCUMENT_TYPES.archive_external_revision_code%TYPE;
31 g_pcard_id PO_HEADERS.pcard_id%TYPE;
32 g_revision_num PO_HEADERS.revision_num%TYPE;
33 g_min_accountable_unit FND_CURRENCIES.minimum_accountable_unit%TYPE;
34 g_precision FND_CURRENCIES.precision%TYPE;
35 g_agent_id PO_HEADERS.agent_id%TYPE;
36 g_approved_date PO_HEADERS.approved_date%TYPE;
37 g_sec_qty_grade_only_chge_doc VARCHAR2(1); --sschinch 09.08.04 INVCONV
38
39 -- For performance, we maintain several indexes of the changes:
40
41 TYPE indexed_tbl_number IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
42
43 -- Index of line changes by PO_LINE_ID
44 -- Key: PO_LINE_ID; Value: Subscript of the line change
45 g_line_changes_index INDEXED_TBL_NUMBER;
46
47 -- Index of shipment changes by LINE_LOCATION_ID
48 -- Key: LINE_LOCATION_ID; Value: Subscript of the shipment change
49 g_ship_changes_index INDEXED_TBL_NUMBER;
50
51 -- Index of line changes by PO_DISTRIBUTION_ID
52 -- Key: PO_DISTRIBUTION_ID; Value: Subscript of the distribution change
53 g_dist_changes_index INDEXED_TBL_NUMBER;
54
55 -- Table of split shipment changes
56 -- Value: Subscript of the split shipment change
57 g_split_ship_changes_tbl PO_TBL_NUMBER;
58
59 -- Table of split distribution changes
60 -- Value: Subscript of the split distribution change
61 g_split_dist_changes_tbl PO_TBL_NUMBER;
62
63 --<Complex work project for R12 :Global variable to store the Complex work PO type>
64 g_is_complex_work_po boolean;
65 g_is_financing_po boolean;
66
67 --<R12 eTax Integration> Determines which documents tax is calculated for
68 g_calculate_tax_flag VARCHAR2(1);
69 g_calculate_tax_status VARCHAR2(1);
70 /*Bug 7278327 Global variable to store the concurrent request ID*/
71 g_request_id PO_HEADERS.request_id%TYPE := fnd_global.conc_request_id;
72
73 -- START Forward declarations for package private procedures:
74 PROCEDURE log_changes (
75 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
76 );
77
78 PROCEDURE init_globals (
79 p_chg IN PO_CHANGES_REC_TYPE,
80 p_update_source IN VARCHAR2
81 );
82
83 PROCEDURE process_inputs (
84 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
85 x_return_status OUT NOCOPY VARCHAR2,
86 p_approval_background_flag IN VARCHAR2,
87 p_mass_update_releases IN VARCHAR2 -- Bug 3373453
88 );
89
90 PROCEDURE preprocess_changes (
91 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
92 x_return_status OUT NOCOPY VARCHAR2
93 );
94
95 PROCEDURE verify_inputs (
96 p_chg IN PO_CHANGES_REC_TYPE,
97 x_return_status OUT NOCOPY VARCHAR2
98 );
99
100 PROCEDURE check_type_specific_fields (
101 p_chg IN PO_CHANGES_REC_TYPE,
102 x_return_status OUT NOCOPY VARCHAR2
103 );
104
105 PROCEDURE check_new_qty_price_amt (
106 p_chg IN PO_CHANGES_REC_TYPE,
107 p_entity_type IN VARCHAR2,
108 i IN NUMBER,
109 x_return_status OUT NOCOPY VARCHAR2
110 );
111
112 FUNCTION is_split_shipment_num_unique (
113 p_chg IN PO_CHANGES_REC_TYPE,
114 i IN NUMBER
115 ) RETURN BOOLEAN;
116
117 FUNCTION line_has_qty_amt_change (
118 p_chg IN PO_CHANGES_REC_TYPE,
119 i IN NUMBER
120 ) RETURN BOOLEAN;
121
122 FUNCTION ship_has_qty_amt_change (
123 p_chg IN PO_CHANGES_REC_TYPE,
124 i IN NUMBER
125 ) RETURN BOOLEAN;
126
127 FUNCTION dist_has_qty_amt_change (
128 p_chg IN PO_CHANGES_REC_TYPE,
129 i IN NUMBER
130 ) RETURN BOOLEAN;
131
132 FUNCTION line_has_ship_qty_amt_change (
133 p_chg IN PO_CHANGES_REC_TYPE,
134 i IN NUMBER
135 ) RETURN BOOLEAN;
136
137 FUNCTION ship_has_dist_qty_amt_change (
138 p_chg IN PO_CHANGES_REC_TYPE,
139 i IN NUMBER
140 ) RETURN BOOLEAN;
141
142 PROCEDURE derive_changes (
143 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
144 x_return_status OUT NOCOPY VARCHAR2
145 );
146
147 PROCEDURE derive_secondary_quantity (
148 p_chg IN PO_CHANGES_REC_TYPE,
149 p_entity_type IN VARCHAR2,
150 p_entity_id IN NUMBER,
151 x_derived_quantity2 OUT NOCOPY PO_LINES.secondary_quantity%TYPE,
152 x_return_status OUT NOCOPY VARCHAR2
153 );
154
155 PROCEDURE get_release_break_price (
156 p_line_location_id IN PO_LINE_LOCATIONS.line_location_id%TYPE,
157 p_quantity IN PO_LINE_LOCATIONS.quantity%TYPE,
158 p_ship_to_location_id IN PO_LINE_LOCATIONS.ship_to_location_id%TYPE,
159 p_need_by_date IN PO_LINE_LOCATIONS.need_by_date%TYPE,
160 x_price OUT NOCOPY PO_LINES.unit_price%TYPE
161 );
162
163 PROCEDURE get_po_break_price (
164 p_po_line_id IN PO_LINES.po_line_id%TYPE,
165 p_quantity IN PO_LINES.quantity%TYPE,
166 p_line_location_id IN PO_LINE_LOCATIONS.line_location_id%TYPE,
167 p_ship_to_location_id IN PO_LINE_LOCATIONS.ship_to_location_id%TYPE,
168 p_need_by_date IN PO_LINE_LOCATIONS.need_by_date%TYPE,
169 x_price_break_id OUT NOCOPY PO_LINES.from_line_location_id%TYPE,
170 x_price OUT NOCOPY PO_LINES.unit_price%TYPE,
171 -- <FPJ Advanced Price>
172 x_base_unit_price OUT NOCOPY PO_LINES.base_unit_price%TYPE
173 );
174
175 FUNCTION get_min_shipment_id (
176 p_po_line_id IN PO_LINES.po_line_id%TYPE
177 ) RETURN NUMBER;
178
179 PROCEDURE derive_qty_amt_rollups (
180 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
181 );
182
183 PROCEDURE derive_qty_amt_rolldowns (
184 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
185 );
186
187 PROCEDURE validate_changes (
188 p_chg IN PO_CHANGES_REC_TYPE,
189 p_run_submission_checks IN VARCHAR2,
190 x_return_status OUT NOCOPY VARCHAR2
191 );
192
193 PROCEDURE validate_line_changes (
194 p_chg IN PO_CHANGES_REC_TYPE,
195 x_return_status OUT NOCOPY VARCHAR2
196 );
197
198 PROCEDURE validate_shipment_changes (
199 p_chg IN PO_CHANGES_REC_TYPE,
200 x_return_status OUT NOCOPY VARCHAR2
201 );
202
203 PROCEDURE validate_distribution_changes (
204 p_chg IN PO_CHANGES_REC_TYPE,
205 x_return_status OUT NOCOPY VARCHAR2
206 );
207
208 PROCEDURE apply_changes (
209 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
210 p_override_date IN DATE,
211 p_buyer_id IN PO_HEADERS.agent_id%TYPE,
212 x_return_status OUT NOCOPY VARCHAR2
213 );
214
215 PROCEDURE create_split_shipments (
216 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
217 );
218
219 PROCEDURE create_split_distributions (
220 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
221 );
222
223 PROCEDURE delete_records (
224 p_chg IN PO_CHANGES_REC_TYPE
225 );
226
227 PROCEDURE calculate_taxes (
228 p_chg IN PO_CHANGES_REC_TYPE
229 );
230 -- END Forward declarations for package private procedures
231
232 -------------------------------------------------------------------------------
233 --Start of Comments
234 --Name: update_document
235 --Function:
236 -- Validates and applies the requested changes and any derived
237 -- changes to the Purchase Order, Purchase Agreement, or Release.
238 --Pre-reqs:
239 -- The Applications context must be set before calling this API - i.e.:
240 -- FND_GLOBAL.apps_initialize ( user_id => <user ID>,
241 -- resp_id => <responsibility ID>,
242 -- resp_appl_id => 201 );
243 --Modifies:
244 -- If all validations are successful, the requested and derived changes
245 -- will be applied to the database tables (ex. PO_HEADERS_ALL,
246 -- PO_LINES_ALL, etc.).
247 -- p_changes will be updated with all of the derived changes, including
248 -- the new LINE_LOCATION_ID and PO_DISTRIBUTION_ID for each split shipment
249 -- and split distribution.
250 --Locks:
251 -- Locks the PO, PA, or release being modified.
252 --Parameters:
253 --IN:
254 --p_api_version
255 -- API version number expected by the caller
256 --p_init_msg_list
257 -- If FND_API.G_TRUE, the API will initialize the standard API message list.
258 --p_changes
259 -- object with the changes to make to the document
260 --p_run_submission_checks
261 -- FND_API.G_TRUE: The API will perform field-level validations as well as
262 -- the PO submission checks. If any of them fail, it will not apply any
263 -- changes to the document.
264 -- Therefore, the changes will only be applied if the document is approvable
265 -- with these changes.
266 -- FND_API.G_FALSE: The API will only perform field-level validations.
267 -- If any of them fail, it will not apply any changes to the document.
268 -- Therefore, it is possible for the changes to be applied even if the
269 -- document is not approvable with the changes.
270 --p_launch_approvals_flag
271 -- FND_API.G_TRUE: Launch the PO Approval workflow after applying the changes
272 -- to the document.
273 -- FND_API.G_FALSE: Do not launch the PO Approval workflow.
274 --p_buyer_id
275 -- Specifies the buyer to use for unreserving the document and launching
276 -- the PO Approval workflow; if NULL, the API will use the buyer (AGENT_ID) on
277 -- the document.
278 --p_update_source
279 -- Used to select different program logic (i.e. validation, derivation)
280 -- based on the source of the update; pass in NULL for the standard logic.
281 -- Use the G_UPDATE_SOURCE_XXX constants (ex. G_UPDATE_SOURCE_OM).
282 --p_override_date
283 -- Date that will be used to unreserve the document; only used if the
284 -- document is encumbered.
285 --p_approval_background_flag := NULL
286 -- Only used if p_launch_approvals_flag = FND_API.G_TRUE.
287 -- PO_CORE_S.G_PARAMETER_NO or NULL: Launch the PO Approval Workflow in
288 -- synchronous mode, where we issue a commit and launch the workflow.
289 -- Control does not return to the caller until the workflow completes or
290 -- reaches a wait node (ex. when it sends a notification to the approver).
291 -- PO_CORE_S.G_PARAMETER_YES: Launch the PO Approval Workflow in background
292 -- mode, where we start the workflow in the background and return
293 -- immediately, without issuing any commits.
294 --p_mass_update_releases := NULL
295 -- (Bug 3373453)
296 -- Only used for Blanket PAs, and if p_launch_approvals_flag = FND_API.G_TRUE.
297 -- PO_CORE_S.G_PARAMETER_YES: Launch the PO Approval Workflow with a request
298 -- to retroactively update the POs/releases with the price from the Blanket.
299 -- PO_CORE_S.G_PARAMETER_NO or NULL: Launch the PO Approval Workflow without
300 -- retroactively pricing the POs/releases of the Blanket.
301 --OUT:
302 --x_return_status
303 -- FND_API.G_RET_STS_SUCCESS if the API succeeded and the changes are applied.
304 -- FND_API.G_RET_STS_ERROR if one or more validations failed.
305 -- FND_API.G_RET_STS_UNEXP_ERROR if an unexpected error occurred.
306 --x_api_errors: If x_return_status is not FND_API.G_RET_STS_SUCCESS, this
307 -- PL/SQL object will contain all the error messages, including field-level
308 -- validation errors, submission checks errors, and unexpected errors.
309 --Notes:
310 -- This API performs quantity/amount proration (shipments to distributions) and
311 -- rollups (distributions to shipments, and shipments to lines) as needed.
312 -- It also derives new prices from the price breaks as needed.
313 -- This API errors out at the document level. If any of the changes have
314 -- errors, none of the changes will be applied.
315 --End of Comments
316 -------------------------------------------------------------------------------
317 PROCEDURE update_document (
318 p_api_version IN NUMBER,
319 p_init_msg_list IN VARCHAR2,
320 x_return_status OUT NOCOPY VARCHAR2,
321 p_changes IN OUT NOCOPY PO_CHANGES_REC_TYPE,
322 p_run_submission_checks IN VARCHAR2,
323 p_launch_approvals_flag IN VARCHAR2,
324 p_buyer_id IN NUMBER,
325 p_update_source IN VARCHAR2,
326 p_override_date IN DATE,
327 x_api_errors OUT NOCOPY PO_API_ERRORS_REC_TYPE,
328 p_approval_background_flag IN VARCHAR2,
329 p_mass_update_releases IN VARCHAR2 -- Bug 3373453
330 ) IS
331 l_api_name CONSTANT VARCHAR2(30) := 'UPDATE_DOCUMENT';
332 l_api_version CONSTANT NUMBER := 1.0;
333 l_last_msg_list_index NUMBER := 0;
334 l_return_status VARCHAR2(1);
335 BEGIN
336 IF (g_fnd_debug = 'Y') THEN
337 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
338 FND_LOG.string ( log_level => FND_LOG.LEVEL_PROCEDURE,
339 module => g_module_prefix || l_api_name,
340 message => 'Entering ' || l_api_name
341 || '; run submission checks: ' || p_run_submission_checks
342 || ' launch approvals: ' || p_launch_approvals_flag
343 || ' buyer ID: ' || p_buyer_id
344 || ' update source: ' || p_update_source
345 || ' override date: ' || p_override_date
346 || ' approval background: '||p_approval_background_flag
347 || ' mass update releases: '||p_mass_update_releases
348 || ' concurrent request ID: '||g_request_id); --bug 7278327
349 END IF;
350 log_changes(p_changes); -- Print the changes for statement-level logging.
351 END IF;
352
353 SAVEPOINT PO_DOCUMENT_UPDATE_PVT_SP;
354 x_return_status := FND_API.G_RET_STS_SUCCESS;
355
356 -- Standard API initialization:
357 IF NOT FND_API.compatible_api_call (
358 p_current_version_number => l_api_version,
359 p_caller_version_number => p_api_version,
360 p_api_name => l_api_name,
361 p_pkg_name => g_pkg_name ) THEN
362 RAISE FND_API.g_exc_unexpected_error;
363 END IF;
364
365 IF (FND_API.to_boolean(p_init_msg_list)) THEN
366 FND_MSG_PUB.initialize();
367 END IF;
368
369 /* BEGIN INVCONV sschinch */
370 g_sec_qty_grade_only_chge_doc := po_document_update_grp.g_process_param_chge_only;
371 /* END INVCONV sschinch */
372
373 l_last_msg_list_index := FND_MSG_PUB.count_msg();
374
375 -- Initialize some global package variables.
376 init_globals (p_changes, p_update_source);
377
378 -- Preprocess the inputs and verify that they make sense.
379
380 process_inputs ( p_changes,
381 x_return_status,
382 p_approval_background_flag,
383 p_mass_update_releases );
384 if (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
385 RAISE FND_API.G_EXC_ERROR;
386 END IF;
387
388 -- Derive additional changes based on the requested changes.
389
390 derive_changes (p_changes, x_return_status);
391 if (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
392 RAISE FND_API.G_EXC_ERROR;
393 END IF;
394
395 -- Validate all the changes.
396
397 validate_changes (p_changes, p_run_submission_checks, x_return_status);
398 if (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
399 RAISE FND_API.G_EXC_ERROR;
400 END IF;
401
402 -- Apply all the changes to the database tables.
403
404 apply_changes (p_changes, p_override_date, p_buyer_id, x_return_status);
405
406 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
407 RAISE FND_API.G_EXC_ERROR;
408 END IF;
409
410 -- INVCONV If only secondary quantity or grade has changed on the shipment(s), don't launch the PO approval workflow
411 --<R12 eTax Integration Start>
412 IF g_calculate_tax_status <> FND_API.G_RET_STS_SUCCESS THEN
413 FOR i IN 1..po_tax_interface_pvt.G_TAX_ERRORS_TBL.MESSAGE_TEXT.COUNT
414 LOOP
415 add_error (
416 p_api_errors => g_api_errors,
417 x_return_status => x_return_status,
418 p_message_name => NULL,
419 p_message_text => po_tax_interface_pvt.G_TAX_ERRORS_TBL.MESSAGE_TEXT(i),
420 p_entity_type => G_ENTITY_TYPE_CHANGES
421 );
422 END LOOP;
423 END IF;
424 --<R12 eTax Integration End>
425
426 IF g_sec_qty_grade_only_chge_doc = 'N' THEN /* INVCONV sschinch 09/07/04*/
427 -- Launch the PO approval workflow if requested.
428 IF (FND_API.to_boolean(p_launch_approvals_flag)) THEN
429 IF g_calculate_tax_status <> FND_API.G_RET_STS_SUCCESS THEN --<R12 eTax Integration>
430 --
431 -- Do nothing here as per new ECO Bug 4643026
432 -- Get the changes, but do not lanuch approval workflow
433 -- as the tax calculation has failed
434 --
435 NULL;
436 ELSE --<R12 eTax Integration>
437 -- Bug 3605355 START
438 launch_po_approval_wf (
439 p_api_version => 1.0,
440 p_init_msg_list => FND_API.G_FALSE,
441 x_return_status => l_return_status,
442 p_document_id => g_document_id,
443 p_document_type => g_document_type,
444 p_document_subtype => g_document_subtype,
445 p_preparer_id => p_buyer_id,
446 p_approval_background_flag => p_approval_background_flag,
447 p_mass_update_releases => p_mass_update_releases,
448 p_retroactive_price_change => g_retroactive_price_change
449 );
450 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
451 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
452 END IF;
453 -- Bug 3605355 END
454 END IF; --<R12 eTax Integration>
455 END IF;
456 END IF; /* INVCONV sschinch 09/07/04 */
457
458 IF (g_fnd_debug = 'Y') THEN
459 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
460 FND_LOG.string ( log_level => FND_LOG.LEVEL_PROCEDURE,
461 module => g_module_prefix || l_api_name,
462 message => 'Exiting ' || l_api_name );
463 END IF;
464 log_changes(p_changes); -- Print the changes for statement-level logging.
465 END IF;
466 EXCEPTION
467 WHEN FND_API.G_EXC_ERROR THEN
468 ROLLBACK TO PO_DOCUMENT_UPDATE_PVT_SP;
469 x_return_status := FND_API.G_RET_STS_ERROR;
470 x_api_errors := g_api_errors;
471 log_changes(p_changes); -- Print the changes for statement-level logging.
472 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
473 ROLLBACK TO PO_DOCUMENT_UPDATE_PVT_SP;
474 -- Add the errors on the API message list to g_api_errors.
475 add_message_list_errors ( p_api_errors => g_api_errors,
476 x_return_status => x_return_status,
477 p_start_index => l_last_msg_list_index + 1 );
478 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
479 x_api_errors := g_api_errors;
480 log_changes(p_changes); -- Print the changes for statement-level logging.
481 WHEN OTHERS THEN
482 ROLLBACK TO PO_DOCUMENT_UPDATE_PVT_SP;
483 -- Add the unexpected error to the API message list.
484 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
485 p_proc_name => l_api_name );
486 -- Add the errors on the API message list to g_api_errors.
487 add_message_list_errors ( p_api_errors => g_api_errors,
488 x_return_status => x_return_status,
489 p_start_index => l_last_msg_list_index + 1 );
490 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
491 x_api_errors := g_api_errors;
492 log_changes(p_changes); -- Print the changes for statement-level logging.
493 END update_document;
494
495 -------------------------------------------------------------------------------
496 --Start of Comments
497 --Name: log_changes
498 --Function:
499 -- If logging is turned on at the statement level, prints out the contents
500 -- of the change object to the FND log.
501 --Pre-reqs:
502 -- None.
503 --Modifies:
504 -- None.
505 --Locks:
506 -- None.
507 --End of Comments
508 -------------------------------------------------------------------------------
509 PROCEDURE log_changes (
510 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
511 ) IS
512 BEGIN
513 IF (g_fnd_debug = 'Y')
514 AND (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_STATEMENT) THEN
515 p_chg.dump_to_log;
516 END IF;
517 END log_changes;
518
519 -------------------------------------------------------------------------------
520 --Start of Comments
521 --Name: init_globals
522 --Function:
523 -- Initialize some general global variables.
524 --Pre-reqs:
525 -- None.
526 --Modifies:
527 -- Package global variables, such as g_api_errors, etc.
528 --Locks:
529 -- None.
530 --End of Comments
531 -------------------------------------------------------------------------------
532 PROCEDURE init_globals (
533 p_chg IN PO_CHANGES_REC_TYPE,
534 p_update_source IN VARCHAR2
535 ) IS
536 l_proc_name CONSTANT VARCHAR2(30) := 'INIT_GLOBALS';
537 l_result BOOLEAN;
538 l_dummy VARCHAR2(30);
539 l_opm_install_status VARCHAR2(1);
540 BEGIN
541 g_api_errors := PO_API_ERRORS_REC_TYPE.create_object();
542 g_update_source := p_update_source;
543 g_retroactive_price_change := NULL;
544
545 g_po_header_id := p_chg.po_header_id;
546 g_po_release_id := p_chg.po_release_id;
547 IF (g_po_header_id IS NOT NULL) AND (g_po_release_id IS NOT NULL) THEN
548 -- If both po_header_id and po_release_id are provided, ignore the
549 -- po_header_id.
550 g_po_header_id := NULL;
551 END IF;
552
553 g_document_id := NVL(g_po_release_id, g_po_header_id);
554
555 --<Complex work project for R12 :Global variable to store the Complex work PO type>
556
557 IF (g_po_header_id IS NOT NULL) THEN
558 g_is_complex_work_po := PO_COMPLEX_WORK_PVT.is_complex_work_po(g_po_header_id);
559 g_is_financing_po := PO_COMPLEX_WORK_PVT.is_financing_po (g_po_header_id);
560 END IF;
561
562 -- Clear the change indexes, in case this API is called multiple times in
563 -- the same session.
564 init_change_indexes;
565
566 -- Check whether OPM and Common Receiving are installed.
567
568 /** INVCONV no need to check OPM and common receiving is installed or not
569 *l_result := FND_INSTALLATION.get_app_info (
570 * application_short_name => 'GMI',
571 * status => l_opm_install_status,
572 * industry => l_dummy,
573 * oracle_schema => l_dummy );
574 * g_opm_installed := (l_opm_install_status = 'I');
575 * g_gml_common_rcv_installed := GML_PO_FOR_PROCESS.check_po_for_proc();
576 * END INVCONV SSCHINCH 09/07/04*/
577 EXCEPTION
578 WHEN FND_API.g_exc_unexpected_error THEN
579 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
580 p_proc_name => l_proc_name,
581 p_add_to_msg_list => FALSE );
582 RAISE FND_API.g_exc_unexpected_error;
583 WHEN OTHERS THEN
584 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
585 p_proc_name => l_proc_name );
586 RAISE FND_API.g_exc_unexpected_error;
587 END init_globals;
588
589 -------------------------------------------------------------------------------
590 --Start of Comments
591 --Name: init_document_globals
592 --Function:
593 -- Populate some global variables for the document, including the document
594 -- type/subtype, the revision, etc.
595 --Pre-reqs:
596 -- None.
597 --Modifies:
598 -- Package global variables, such as g_document_type, etc.
599 --Locks:
600 -- None.
601 --End of Comments
602 -------------------------------------------------------------------------------
603 PROCEDURE init_document_globals IS
604 l_proc_name CONSTANT VARCHAR2(30) := 'INIT_DOCUMENT_GLOBALS';
605 l_currency_code PO_HEADERS_ALL.currency_code%TYPE;
606 BEGIN
607 -- Retrieve header information: document subtype, revision, etc.
608 IF (g_po_header_id IS NOT NULL) THEN -- PO or PA
609
610 SELECT POH.type_lookup_code,
611 POH.revision_num,
612 POH.pcard_id,
613 POH.currency_code,
614 POH.agent_id,
615 POH.approved_date
616 INTO g_document_subtype,
617 g_revision_num,
618 g_pcard_id,
619 l_currency_code,
620 g_agent_id,
621 g_approved_date
622 FROM po_headers POH
623 WHERE POH.po_header_id = g_po_header_id;
624
625 IF (g_document_subtype IN ('BLANKET','CONTRACT')) THEN
626 g_document_type := 'PA';
627 ELSE
628 g_document_type := 'PO';
629 g_calculate_tax_flag := 'Y'; --<R12 eTax Integration>
630 END IF;
631
632 ELSE -- Release
633
634 SELECT POR.release_type,
635 POR.revision_num,
636 POR.pcard_id,
637 POH.currency_code,
638 POR.agent_id,
639 POR.approved_date
640 INTO g_document_subtype,
641 g_revision_num,
642 g_pcard_id,
643 l_currency_code,
644 g_agent_id,
645 g_approved_date
646 FROM po_releases POR, po_headers POH
647 WHERE POR.po_release_id = g_po_release_id
648 AND POR.po_header_id = POH.po_header_id; -- JOIN
649
650 g_document_type := 'RELEASE';
651 g_calculate_tax_flag := 'Y'; --<R12 eTax Integration>
652
653 END IF; -- release ID is null
654
655 IF (g_fnd_debug = 'Y') THEN
656 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
657 FND_LOG.string( log_level => FND_LOG.LEVEL_EVENT,
658 module => g_module_prefix || l_proc_name,
659 message => 'Document ID: ' || g_document_id
660 || '; document type: ' || g_document_type
661 || ', subtype: ' || g_document_subtype );
662 END IF;
663 END IF;
664
665 -- Retrieve the minimum accountable unit and precision, which are needed
666 -- for rounding the amount.
667 SELECT CUR.minimum_accountable_unit, CUR.precision
668 INTO g_min_accountable_unit, g_precision
669 FROM fnd_currencies CUR
670 WHERE CUR.currency_code = l_currency_code;
671
672 -- Retrieve the archive mode, which is needed for the validations.
673 SELECT archive_external_revision_code
674 INTO g_archive_mode
675 FROM po_document_types
676 WHERE document_type_code = g_document_type
677 AND document_subtype = g_document_subtype;
678
679 EXCEPTION
680 WHEN FND_API.g_exc_unexpected_error THEN
681 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
682 p_proc_name => l_proc_name,
683 p_add_to_msg_list => FALSE );
684 RAISE FND_API.g_exc_unexpected_error;
685 WHEN OTHERS THEN
686 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
687 p_proc_name => l_proc_name );
688 RAISE FND_API.g_exc_unexpected_error;
689 END init_document_globals;
690
691 -------------------------------------------------------------------------------
692 --Start of Comments
693 --Name: verify_document_ids
694 --Function:
695 -- Verifies that the document IDs (ex. PO_HEADER_ID, PO_LINE_ID, etc.)
696 -- in the change object are correct.
697 --Pre-reqs:
698 -- None.
699 --Modifies:
700 -- Writes any errors to g_api_errors.
701 --Locks:
702 -- None.
703 --End of Comments
704 -------------------------------------------------------------------------------
705 PROCEDURE verify_document_ids (
706 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
707 x_return_status OUT NOCOPY VARCHAR2
708 ) IS
709 l_dummy NUMBER;
710 l_proc_name CONSTANT VARCHAR2(30) := 'VERIFY_DOCUMENT_IDS';
711 BEGIN
712 IF (g_fnd_debug = 'Y') THEN
713 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
714 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
715 module => g_module_prefix || l_proc_name,
716 message => 'Entering ' || l_proc_name );
717 END IF;
718 END IF;
719
720 x_return_status := FND_API.G_RET_STS_SUCCESS;
721
722 -- Make sure that the po_header_id / po_release_id is valid.
723 IF (g_po_header_id IS NOT NULL) THEN -- PO / PA
724 BEGIN
725 SELECT 1
726 INTO l_dummy
727 FROM po_headers
728 WHERE po_header_id = g_po_header_id;
729 EXCEPTION
730 WHEN NO_DATA_FOUND THEN -- Error: po_header_id is invalid.
731 add_error (
732 p_api_errors => g_api_errors,
733 x_return_status => x_return_status,
734 p_message_name => 'PO_INVALID_DOC_IDS',
735 p_table_name => 'PO_HEADERS_ALL',
736 p_column_name => 'PO_HEADER_ID',
737 p_entity_type => G_ENTITY_TYPE_CHANGES
738 );
739 RETURN; -- Do not continue with the remaining checks.
740 END;
741 ELSIF (g_po_release_id IS NOT NULL) THEN -- Release
742 BEGIN
743 SELECT 1
744 INTO l_dummy
745 FROM po_releases
746 WHERE po_release_id = g_po_release_id;
747 EXCEPTION
748 WHEN NO_DATA_FOUND THEN -- Error: po_release_id is invalid.
749 add_error (
750 p_api_errors => g_api_errors,
751 x_return_status => x_return_status,
752 p_message_name => 'PO_INVALID_DOC_IDS',
753 p_table_name => 'PO_RELEASES_ALL',
754 p_column_name => 'PO_RELEASE_ID',
755 p_entity_type => G_ENTITY_TYPE_CHANGES
756 );
757 RETURN; -- Do not continue with the remaining checks.
758 END;
759 ELSE -- Error: Both po_header_id and po_release_id are null.
760 add_error ( p_api_errors => g_api_errors,
761 x_return_status => x_return_status,
762 p_message_name => 'PO_INVALID_DOC_IDS',
763 p_entity_type => G_ENTITY_TYPE_CHANGES );
764 RETURN; -- Do not continue with the remaining checks.
765 END IF;
766
767 -- Make sure that the po_line_id is valid for each line change.
768 FOR i IN 1..p_chg.line_changes.get_count LOOP
769 BEGIN
770 IF (g_po_header_id IS NOT NULL) THEN -- PO / PA
771 SELECT 1
772 INTO l_dummy
773 FROM po_lines
774 WHERE po_header_id = g_po_header_id
775 AND po_line_id = p_chg.line_changes.po_line_id(i);
776 END IF;
777 EXCEPTION
778 WHEN NO_DATA_FOUND THEN -- Error: po_line_id is invalid.
779 add_error (
780 p_api_errors => g_api_errors,
781 x_return_status => x_return_status,
782 p_message_name => 'PO_INVALID_DOC_IDS',
783 p_table_name => 'PO_LINES_ALL',
784 p_column_name => 'PO_LINE_ID',
785 p_entity_type => G_ENTITY_TYPE_LINES,
786 p_entity_id => i
787 );
788 END;
789 END LOOP;
790
791 -- Make sure that the po_line_location_id or parent_line_location_id (split
792 -- shipment) is valid for each shipment change.
793 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
794
795 -- A split shipment change must not have a po_line_location_id.
796 IF (p_chg.shipment_changes.po_line_location_id(i) IS NOT NULL) AND
797 ((p_chg.shipment_changes.parent_line_location_id(i) IS NOT NULL) OR
798 (p_chg.shipment_changes.split_shipment_num(i) IS NOT NULL)) THEN
799 add_error (
800 p_api_errors => g_api_errors,
801 x_return_status => x_return_status,
802 p_message_name => 'PO_GENERIC_ERROR',
803 p_table_name => 'PO_LINE_LOCATIONS_ALL',
804 p_token_name1 => 'ERROR_TEXT',
805 p_token_value1 => 'You cannot specify both po_line_location_id and parent_line_location_id / split_shipment_num for a shipment change.',
806 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
807 p_entity_id => i
808 );
809 END IF;
810
811 BEGIN
812 IF (g_po_header_id IS NOT NULL) THEN -- PO / PA
813 SELECT 1
814 INTO l_dummy
815 FROM po_line_locations
816 WHERE po_header_id = g_po_header_id
817 AND line_location_id =
818 NVL(p_chg.shipment_changes.po_line_location_id(i),
819 p_chg.shipment_changes.parent_line_location_id(i));
820 ELSE -- release
821 SELECT 1
822 INTO l_dummy
823 FROM po_line_locations
824 WHERE po_release_id = g_po_release_id
825 AND line_location_id =
826 NVL(p_chg.shipment_changes.po_line_location_id(i),
827 p_chg.shipment_changes.parent_line_location_id(i));
828 END IF; -- po_header_id is not null
829 EXCEPTION
830 WHEN NO_DATA_FOUND THEN
831 -- Error: po_line_location_id / parent_line_location_id is invalid.
832 add_error (
833 p_api_errors => g_api_errors,
834 x_return_status => x_return_status,
835 p_message_name => 'PO_INVALID_DOC_IDS',
836 p_table_name => 'PO_LINE_LOCATIONS_ALL',
837 p_column_name => 'LINE_LOCATION_ID',
838 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
839 p_entity_id => i
840 );
841 END;
842 END LOOP;
843
844 -- Make sure that the po_distribution_id or parent_distribution_id (split
845 -- distribution) is valid for each distribution change.
846 FOR i IN 1..p_chg.distribution_changes.get_count LOOP
847
848 -- A split distribution change must not have a po_distribution_id.
849 IF (p_chg.distribution_changes.po_distribution_id(i) IS NOT NULL) AND
850 ((p_chg.distribution_changes.parent_distribution_id(i) IS NOT NULL) OR
851 (p_chg.distribution_changes.split_shipment_num(i) IS NOT NULL)) THEN
852 add_error (
853 p_api_errors => g_api_errors,
854 x_return_status => x_return_status,
855 p_message_name => 'PO_GENERIC_ERROR',
856 p_table_name => 'PO_DISTRIBUTIONS_ALL',
857 p_token_name1 => 'ERROR_TEXT',
858 p_token_value1 => 'You cannot specify both po_distribution_id and parent_distribution_id / split_shipment_num for a distribution change.',
859 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
860 p_entity_id => i
861 );
862 END IF;
863
864 BEGIN
865 IF (g_po_header_id IS NOT NULL) THEN -- PO / PA
866 SELECT 1
867 INTO l_dummy
868 FROM po_distributions
869 WHERE po_header_id = g_po_header_id
870 AND po_distribution_id =
871 NVL(p_chg.distribution_changes.po_distribution_id(i),
872 p_chg.distribution_changes.parent_distribution_id(i));
873 ELSE -- release
874 SELECT 1
875 INTO l_dummy
876 FROM po_distributions
877 WHERE po_release_id = g_po_release_id
878 AND po_distribution_id =
879 NVL(p_chg.distribution_changes.po_distribution_id(i),
880 p_chg.distribution_changes.parent_distribution_id(i));
881 END IF; -- po_header_id is not null
882 EXCEPTION
883 WHEN NO_DATA_FOUND THEN
884 -- Error: po_distribution_id / parent_distribution_id is invalid.
885 add_error (
886 p_api_errors => g_api_errors,
887 x_return_status => x_return_status,
888 p_message_name => 'PO_INVALID_DOC_IDS',
889 p_table_name => 'PO_DISTRIBUTIONS_ALL',
890 p_column_name => 'PO_DISTRIBUTION_ID',
891 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
892 p_entity_id => i
893 );
894 END;
895 END LOOP;
896
897 EXCEPTION
898 WHEN FND_API.g_exc_unexpected_error THEN
899 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
900 p_proc_name => l_proc_name,
901 p_add_to_msg_list => FALSE );
902 RAISE FND_API.g_exc_unexpected_error;
903 WHEN OTHERS THEN
904 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
905 p_proc_name => l_proc_name );
906 RAISE FND_API.g_exc_unexpected_error;
907 END verify_document_ids;
908
909 -------------------------------------------------------------------------------
910 --Start of Comments
911 --Name: process_inputs
912 --Function:
913 -- Checks that the document is in a status that allows changes and that
914 -- the requested changes make sense. Also performs preprocessing on the
915 -- changes (cached database values, UOM quantity conversions, etc).
916 --Pre-reqs:
917 -- None.
918 --Modifies:
919 -- During preprocessing, modifies p_chg with cached values, UOM converted
920 -- quantities, etc.
921 -- Writes any errors to g_api_errors.
922 --Locks:
923 -- Locks the document to be modified.
924 --End of Comments
925 -------------------------------------------------------------------------------
926 PROCEDURE process_inputs (
927 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
928 x_return_status OUT NOCOPY VARCHAR2,
929 p_approval_background_flag IN VARCHAR2,
930 p_mass_update_releases IN VARCHAR2 -- Bug 3373453
931 ) IS
932 l_proc_name CONSTANT VARCHAR2(30) := 'PROCESS_INPUTS';
933 l_progress VARCHAR2(3) := '000';
934
935 l_return_status VARCHAR2(1);
936 l_status_rec_type PO_STATUS_REC_TYPE;
937 l_last_msg_list_index NUMBER;
938 BEGIN
939 IF (g_fnd_debug = 'Y') THEN
940 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
941 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
942 module => g_module_prefix || l_proc_name,
943 message => 'Entering ' || l_proc_name );
944 END IF;
945 END IF;
946
947 x_return_status := FND_API.G_RET_STS_SUCCESS;
948
949 -- Verify that the passed in document IDs (ex. po_header_id,
950 -- po_line_id, etc.) are valid.
951 verify_document_ids (p_chg, x_return_status);
952 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
953 RETURN;
954 END IF;
955
956 -- Next, retrieve some global variables for the document, such as
957 -- document type/subtype, revision, etc.
958 init_document_globals;
959
960 -- Check that the requested changes are for a supported document type.
961 -- (standard PO, planned PO, blanket PA, scheduled release, blanket release)
962 l_progress := '010';
963
964 IF (g_document_type = 'PO'
965 AND g_document_subtype IN ('STANDARD','PLANNED')) OR
966 (g_document_type = 'PA' AND g_document_subtype = 'BLANKET') OR
967 (g_document_type = 'RELEASE'
968 AND g_document_subtype IN ('SCHEDULED','BLANKET')) THEN
969 null;
970 ELSE -- unsupported document type
971 add_error ( p_api_errors => g_api_errors,
972 x_return_status => x_return_status,
973 p_message_name => 'PO_CHNG_WRONG_DOC_TYPE',
974 p_entity_type => G_ENTITY_TYPE_CHANGES );
975 RETURN;
976 END IF; -- document type
977
978 -- Verify that the other input parameters are valid.
979
980 --------------------------------------------------------------------------
981 -- Check: Verify that the following parameters have values Y, N, or null.
982 --------------------------------------------------------------------------
983 PO_CORE_S.validate_yes_no_param (
984 x_return_status => x_return_status,
985 p_parameter_name => 'p_approval_background_flag',
986 p_parameter_value => p_approval_background_flag );
987 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
988 RAISE FND_API.g_exc_unexpected_error;
989 END IF;
990
991 PO_CORE_S.validate_yes_no_param (
992 x_return_status => x_return_status,
993 p_parameter_name => 'p_mass_update_releases',
994 p_parameter_value => p_mass_update_releases );
995 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
996 RAISE FND_API.g_exc_unexpected_error;
997 END IF;
998
999 --------------------------------------------------------------------------
1000 -- Check: p_mass_update_releases can only be set to Y for Blankets.
1001 --------------------------------------------------------------------------
1002 IF (p_mass_update_releases = G_PARAMETER_YES)
1003 AND (g_document_type <> 'PA') THEN
1004
1005 FND_MESSAGE.set_name('PO', 'PO_INVALID_MASS_UPDATE_REL');
1006 FND_MSG_PUB.add;
1007 RAISE FND_API.g_exc_unexpected_error;
1008 END IF;
1009
1010 l_progress := '020';
1011
1012 -- Call the PO Status Check API to check if the document is in a status
1013 -- that allows modifications. Lock the document to prevent others from
1014 -- modifying it during our derivations and validations.
1015
1016 IF (g_fnd_debug = 'Y') THEN
1017 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_STATEMENT) THEN
1018 FND_LOG.string( log_level => FND_LOG.LEVEL_STATEMENT,
1019 module => g_module_prefix || l_proc_name,
1020 message => 'Calling the PO Status Check API' );
1021 END IF;
1022 END IF;
1023
1024 l_last_msg_list_index := FND_MSG_PUB.count_msg();
1025
1026 PO_DOCUMENT_CHECKS_GRP.po_status_check (
1027 p_api_version => 1.0,
1028 p_header_id => g_po_header_id,
1029 p_release_id => g_po_release_id,
1030 p_document_type => g_document_type,
1031 p_document_subtype => g_document_subtype,
1032 p_mode => 'CHECK_UPDATEABLE',
1033 p_lock_flag => 'Y', -- Lock the document
1034 x_po_status_rec => l_status_rec_type,
1035 x_return_status => l_return_status
1036 );
1037
1038 IF (g_fnd_debug = 'Y') THEN
1039 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_STATEMENT) THEN
1040 FND_LOG.string( log_level => FND_LOG.LEVEL_STATEMENT,
1041 module => g_module_prefix || l_proc_name,
1042 message => 'Status Check API result: '||l_return_status);
1043 END IF;
1044 END IF;
1045
1046 l_progress := '030';
1047
1048 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1049 -- Add the errors on the message list to the API errors object.
1050 add_message_list_errors ( p_api_errors => g_api_errors,
1051 x_return_status => x_return_status,
1052 p_start_index => l_last_msg_list_index + 1 );
1053 RETURN;
1054 ELSIF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1055 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1056 END IF;
1057
1058 IF (l_status_rec_type.updatable_flag(1) <> 'Y') THEN
1059 -- The document status does not allow updates.
1060 add_error ( p_api_errors => g_api_errors,
1061 x_return_status => x_return_status,
1062 p_message_name => 'PO_CHNG_CANNOT_OPEN_DOC' );
1063 RETURN;
1064 END IF;
1065
1066 -- Perform some preprocessing on the change object, such as UOM quantity
1067 -- conversions and populating the cached fields.
1068 l_progress := '040';
1069 preprocess_changes (p_chg, x_return_status);
1070 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1071 RETURN;
1072 END IF;
1073
1074 -- Check that the requested changes make sense.
1075 l_progress := '050';
1076 verify_inputs (p_chg, x_return_status);
1077
1078 EXCEPTION
1079 WHEN FND_API.g_exc_unexpected_error THEN
1080 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1081 p_proc_name => l_proc_name,
1082 p_progress => l_progress,
1083 p_add_to_msg_list => FALSE );
1084 RAISE FND_API.g_exc_unexpected_error;
1085 WHEN OTHERS THEN
1086 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1087 p_proc_name => l_proc_name,
1088 p_progress => l_progress );
1089 RAISE FND_API.g_exc_unexpected_error;
1090 END process_inputs;
1091
1092 -------------------------------------------------------------------------------
1093 --Start of Comments
1094 --Name: populate_line_cached_fields
1095 --Function:
1096 -- For the given line, retrieves all the database field values that will be
1097 -- needed in the derivation and validation steps and caches them in the
1098 -- change object. This improves performance by reducing database access.
1099 --Pre-reqs:
1100 -- None.
1101 --Modifies:
1102 -- Modifies p_chg with the cached values.
1103 --Locks:
1104 -- None.
1105 --End of Comments
1106 -------------------------------------------------------------------------------
1107 PROCEDURE populate_line_cached_fields (
1108 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
1109 i IN NUMBER
1110 ) IS
1111 l_org_id NUMBER;
1112 BEGIN
1113 -- SQL What: Retrieve all the database field values that will be needed
1114 -- in the derivation and validation steps and cache them in the
1115 -- change object.
1116 -- SQL Why: This reduces database access and improves performance, since
1117 -- we only need one SELECT statement here rather than many
1118 -- SELECT statements in the later steps.
1119 SELECT POL.quantity,
1120 POL.unit_meas_lookup_code,
1121 POL.item_id,
1122 POL.from_header_id,
1123 POL.from_line_id,
1124 NVL(POHA.global_agreement_flag, 'N'),
1125 NVL(POL.cancel_flag, 'N'),
1126 NVL(POL.closed_code, 'OPEN'),
1127 PLT.order_type_lookup_code, -- value basis
1128 PLT.purchase_basis,
1129 POL.amount,
1130 POL.start_date,
1131 POL.expiration_date,
1132 POL.unit_price,
1133 POL.from_line_location_id,
1134 POL.secondary_quantity,
1135 POL.secondary_unit_of_measure,
1136 MSI.segment1, -- item_number
1137 POL.manual_price_change_flag, -- <Manual Price Override FPJ>
1138 POL.preferred_grade --INVCONV
1139 INTO p_chg.line_changes.c_quantity(i),
1140 p_chg.line_changes.c_unit_meas_lookup_code(i),
1141 p_chg.line_changes.c_item_id(i),
1142 p_chg.line_changes.c_from_header_id(i),
1143 p_chg.line_changes.c_from_line_id(i),
1144 p_chg.line_changes.c_has_ga_reference(i),
1145 p_chg.line_changes.c_cancel_flag(i),
1146 p_chg.line_changes.c_closed_code(i),
1147 p_chg.line_changes.c_value_basis(i),
1148 p_chg.line_changes.c_purchase_basis(i),
1149 p_chg.line_changes.c_amount(i),
1150 p_chg.line_changes.c_start_date(i),
1151 p_chg.line_changes.c_expiration_date(i),
1152 p_chg.line_changes.c_unit_price(i),
1153 p_chg.line_changes.c_from_line_location_id(i),
1154 p_chg.line_changes.c_secondary_quantity(i),
1155 p_chg.line_changes.c_secondary_uom(i),
1156 p_chg.line_changes.c_item_number(i),
1157 -- <Manual Price Override FPJ>:
1158 p_chg.line_changes.t_manual_price_change_flag(i),
1159 p_chg.line_changes.c_preferred_grade(i) --INVCONV
1160 FROM po_lines POL,
1161 po_line_types PLT,
1162 po_headers_all POHA,
1163 mtl_system_items_b MSI,
1164 financials_system_parameters FSP
1165 WHERE POL.po_line_id = p_chg.line_changes.po_line_id(i)
1166 AND PLT.line_type_id = POL.line_type_id -- JOIN
1167 AND POHA.po_header_id(+) = POL.from_header_id -- JOIN
1168 AND MSI.inventory_item_id(+) = POL.item_id -- JOIN
1169 AND NVL(MSI.organization_id, FSP.inventory_organization_id)
1170 = FSP.inventory_organization_id; -- JOIN
1171
1172 EXCEPTION
1173 WHEN FND_API.g_exc_unexpected_error THEN
1174 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1175 p_proc_name => 'POPULATE_LINE_CACHED_FIELDS',
1176 p_add_to_msg_list => FALSE );
1177 RAISE FND_API.g_exc_unexpected_error;
1178 WHEN OTHERS THEN
1179 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1180 p_proc_name => 'POPULATE_LINE_CACHED_FIELDS' );
1181 RAISE FND_API.g_exc_unexpected_error;
1182 END populate_line_cached_fields;
1183
1184 -------------------------------------------------------------------------------
1185 --Start of Comments
1186 --Name: populate_ship_cached_fields
1187 --Function:
1188 -- For the given shipment, retrieves all the database field values that will
1189 -- be needed in the derivation and validation steps and caches them in the
1190 -- change object. This improves performance by reducing database access.
1191 --Pre-reqs:
1192 -- None.
1193 --Modifies:
1194 -- Modifies p_chg with the cached values.
1195 --Locks:
1196 -- None.
1197 --End of Comments
1198 -------------------------------------------------------------------------------
1199 PROCEDURE populate_ship_cached_fields (
1200 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
1201 i IN NUMBER
1202 ) IS
1203 l_parent_line_loc_id PO_LINE_LOCATIONS.line_location_id%TYPE;
1204 BEGIN
1205 l_parent_line_loc_id := p_chg.shipment_changes.parent_line_location_id(i);
1206
1207 -- SQL What: Retrieve all the database field values that will be needed
1208 -- in the derivation and validation steps and cache them in the
1209 -- change object.
1210 -- SQL Why: This reduces database access and improves performance, since
1211 -- we only need one SELECT statement here rather than many
1212 -- SELECT statements in the later steps.
1213 SELECT PLL.po_line_id,
1214 -- quantity:
1215 decode (l_parent_line_loc_id, null,
1216 PLL.quantity, -- existing shipment
1217 0), -- split shipment
1218 --POL.unit_meas_lookup_code, <Complex work project for R12>
1219 PLL.unit_meas_lookup_code,
1220 -- cancel_flag:
1221 decode (l_parent_line_loc_id, null,
1222 NVL(PLL.cancel_flag, 'N'), -- existing shipment
1223 'N'), -- split shipment
1224 -- closed_code:
1225 decode (l_parent_line_loc_id, null,
1226 NVL(PLL.closed_code, 'OPEN'), -- existing shipment
1227 'OPEN'), -- split shipment
1228 POL.item_id,
1229 PLL.ship_to_organization_id,
1230 NVL(PLL.drop_ship_flag, 'N'),
1231 -- quantity_received:
1232 decode (l_parent_line_loc_id, null,
1233 NVL(PLL.quantity_received, 0), -- existing shipment
1234 0), -- split shipment
1235 -- quantity_billed:
1236 decode (l_parent_line_loc_id, null,
1237 NVL(PLL.quantity_billed, 0), -- existing shipment
1238 0), -- split shipment
1239 -- amount_received: Bug 3524527
1240 decode (l_parent_line_loc_id, null,
1241 NVL(PLL.amount_received, 0), -- existing shipment
1242 0), -- split shipment
1243 -- amount_billed: Bug 3524527
1244 decode (l_parent_line_loc_id, null,
1245 NVL(PLL.amount_billed, 0), -- existing shipment
1246 0), -- split shipment
1247 NVL(PLL.accrue_on_receipt_flag, 'N'),
1248 --PLT.order_type_lookup_code, -- value basis <Complex work project for R12 >
1249 PLL.value_basis, --<Complex work project for R12>
1250 PLT.purchase_basis,
1251 -- amount:
1252 decode (l_parent_line_loc_id, null,
1253 PLL.amount, -- existing shipment
1254 0), -- split shipment
1255 PLL.price_override,
1256 -- parent_quantity:
1257 decode (l_parent_line_loc_id, null,
1258 null, -- existing shipment
1259 PLL.quantity), -- split shipment
1260 -- parent_amount:
1261 decode (l_parent_line_loc_id, null,
1262 null, -- existing shipment
1263 PLL.amount), -- split shipment
1264 -- secondary_quantity:
1265 decode (l_parent_line_loc_id, null,
1266 PLL.secondary_quantity, -- existing shipment
1267 null), -- split shipment
1268 PLL.secondary_unit_of_measure,
1269 MSI.segment1, -- item_number
1270 -- approved_date:
1271 decode (l_parent_line_loc_id, null,
1272 PLL.approved_date, -- existing shipment
1273 null), -- split shipment
1274 -- encumbered_flag:
1275 decode (l_parent_line_loc_id, null,
1276 NVL(PLL.encumbered_flag, 'N'), -- existing shipment
1277 'N'), -- split shipment
1278 PLL.shipment_type,
1279 -- quantity_shipped:
1280 decode (l_parent_line_loc_id, null,
1281 NVL(PLL.quantity_shipped,0), -- existing shipment
1282 0), -- split shipment
1283 PLL.manual_price_change_flag, -- <Manual Price Override FPJ>
1284 PLL.preferred_grade -- INVCONV sschinch 09/07/04
1285 --PLL.PAYMENT_TYPE -- Progress Payment type <Complex work project for R12>
1286 INTO p_chg.shipment_changes.c_po_line_id(i),
1287 p_chg.shipment_changes.c_quantity(i),
1288 p_chg.shipment_changes.c_unit_meas_lookup_code(i),
1289 p_chg.shipment_changes.c_cancel_flag(i),
1290 p_chg.shipment_changes.c_closed_code(i),
1291 p_chg.shipment_changes.c_item_id(i),
1292 p_chg.shipment_changes.c_ship_to_organization_id(i),
1293 p_chg.shipment_changes.c_drop_ship_flag(i),
1294 p_chg.shipment_changes.c_quantity_received(i),
1295 p_chg.shipment_changes.c_quantity_billed(i),
1296 p_chg.shipment_changes.c_amount_received(i), -- Bug 3524527
1297 p_chg.shipment_changes.c_amount_billed(i), -- Bug 3524527
1298 p_chg.shipment_changes.c_accrue_on_receipt_flag(i),
1299 p_chg.shipment_changes.c_value_basis(i),
1300 p_chg.shipment_changes.c_purchase_basis(i),
1301 p_chg.shipment_changes.c_amount(i),
1302 p_chg.shipment_changes.c_price_override(i),
1303 p_chg.shipment_changes.c_parent_quantity(i),
1304 p_chg.shipment_changes.c_parent_amount(i),
1305 p_chg.shipment_changes.c_secondary_quantity(i),
1306 p_chg.shipment_changes.c_secondary_uom(i),
1307 p_chg.shipment_changes.c_item_number(i),
1308 p_chg.shipment_changes.c_approved_date(i),
1309 p_chg.shipment_changes.c_encumbered_flag(i),
1310 p_chg.shipment_changes.c_shipment_type(i),
1311 p_chg.shipment_changes.c_quantity_shipped(i),
1312 -- <Manual Price Override FPJ>:
1313 p_chg.shipment_changes.t_manual_price_change_flag(i),
1314 p_chg.shipment_changes.c_preferred_grade(i) -- INVCONV sschinch 09/07/04
1315 --p_chg.shipment_changes.c_payment_type(i)
1316 FROM po_line_locations PLL,
1317 po_lines POL,
1318 po_line_types PLT,
1319 mtl_system_items_b MSI,
1320 financials_system_parameters FSP
1321 WHERE PLL.line_location_id =
1322 NVL( p_chg.shipment_changes.parent_line_location_id(i), -- split shipment
1323 p_chg.shipment_changes.po_line_location_id(i) ) -- existing shipment
1324 AND POL.po_line_id = PLL.po_line_id -- JOIN
1325 AND PLT.line_type_id = POL.line_type_id -- JOIN
1326 AND MSI.inventory_item_id(+) = POL.item_id -- JOIN
1327 AND NVL(MSI.organization_id, FSP.inventory_organization_id)
1328 = FSP.inventory_organization_id; -- JOIN
1329
1330 EXCEPTION
1331 WHEN FND_API.g_exc_unexpected_error THEN
1332 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1333 p_proc_name => 'POPULATE_SHIP_CACHED_FIELDS',
1334 p_add_to_msg_list => FALSE );
1335 RAISE FND_API.g_exc_unexpected_error;
1336 WHEN OTHERS THEN
1337 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1338 p_proc_name => 'POPULATE_SHIP_CACHED_FIELDS' );
1339 RAISE FND_API.g_exc_unexpected_error;
1340 END populate_ship_cached_fields;
1341
1342 -------------------------------------------------------------------------------
1343 --Start of Comments
1344 --Name: populate_dist_cached_fields
1345 --Function:
1346 -- For the given distribution, retrieves all the database field values that
1347 -- will be needed in the derivation and validation steps and caches them in
1348 -- the change object. This improves performance by reducing database access.
1349 --Pre-reqs:
1350 -- None.
1351 --Modifies:
1352 -- Modifies p_chg with the cached values.
1353 --Locks:
1354 -- None.
1355 --End of Comments
1356 -------------------------------------------------------------------------------
1357 PROCEDURE populate_dist_cached_fields (
1358 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
1359 i IN NUMBER
1360 ) IS
1361 l_parent_dist_id PO_DISTRIBUTIONS.po_distribution_id%TYPE;
1362 BEGIN
1363 l_parent_dist_id := p_chg.distribution_changes.parent_distribution_id(i);
1364
1365 -- SQL What: Retrieve all the database field values that will be needed
1366 -- in the derivation and validation steps and cache them in the
1367 -- change object.
1368 -- SQL Why: This reduces database access and improves performance, since
1369 -- we only need one SELECT statement here rather than many
1370 -- SELECT statements in the later steps.
1371 SELECT POD.po_line_id,
1372 -- line_location_id:
1373 decode (l_parent_dist_id, null,
1374 POD.line_location_id, -- existing distribution
1375 null), -- split distribution
1376 -- quantity_ordered:
1377 decode (l_parent_dist_id, null,
1378 POD.quantity_ordered, -- existing distribution
1379 0), -- split distribution
1380 PLL.unit_meas_lookup_code, -- <Complex work project for R12>
1381 POL.item_id,
1382 -- quantity_delivered:
1383 decode (l_parent_dist_id, null,
1384 NVL(POD.quantity_delivered, 0), -- existing distribution
1385 0), -- split distribution
1386 -- quantity_billed:
1387 decode (l_parent_dist_id, null,
1388 NVL(POD.quantity_billed, 0), -- existing distribution
1389 0), -- split distribution
1390 -- amount_delivered: Bug 3524527
1391 decode (l_parent_dist_id, null,
1392 NVL(POD.amount_delivered, 0), -- existing distribution
1393 0), -- split distribution
1394 -- amount_billed: Bug 3524527
1395 decode (l_parent_dist_id, null,
1396 NVL(POD.amount_billed, 0), -- existing distribution
1397 0), -- split distribution
1398 -- value basis:
1399 -- PLT.order_type_lookup_code, -- <Complex work project for R12>
1400 PLL.value_basis,
1401 PLT.purchase_basis,
1402 -- amount_ordered:
1403 decode (l_parent_dist_id, null,
1404 POD.amount_ordered, -- existing distribution
1405 0), -- split distribution
1406 -- parent_line_location_id:
1407 decode (l_parent_dist_id, null,
1408 null, -- existing distribution
1409 POD.line_location_id), -- split distribution
1410 POD.award_id,
1411 POD.project_id,
1412 POD.task_id,
1413 POD.distribution_num,
1414 -- encumbered_flag:
1415 decode (l_parent_dist_id, null,
1416 NVL(POD.encumbered_flag,'N'), -- existing distribution
1417 'N'), -- split distribution
1418 POD.req_distribution_id,
1419 -- creation_date:
1420 decode (l_parent_dist_id, null,
1421 POD.creation_date, -- existing distribution
1422 NULL) -- split distribution
1423 INTO p_chg.distribution_changes.c_po_line_id(i),
1424 p_chg.distribution_changes.c_line_location_id(i),
1425 p_chg.distribution_changes.c_quantity_ordered(i),
1426 p_chg.distribution_changes.c_unit_meas_lookup_code(i),
1427 p_chg.distribution_changes.c_item_id(i),
1428 p_chg.distribution_changes.c_quantity_delivered(i),
1429 p_chg.distribution_changes.c_quantity_billed(i),
1430 p_chg.distribution_changes.c_amount_delivered(i), -- Bug 3524527
1431 p_chg.distribution_changes.c_amount_billed(i), -- Bug 3524527
1432 p_chg.distribution_changes.c_value_basis(i),
1433 p_chg.distribution_changes.c_purchase_basis(i),
1434 p_chg.distribution_changes.c_amount_ordered(i),
1435 p_chg.distribution_changes.c_parent_line_location_id(i),
1436 p_chg.distribution_changes.c_award_id(i),
1437 p_chg.distribution_changes.c_project_id(i),
1438 p_chg.distribution_changes.c_task_id(i),
1439 p_chg.distribution_changes.c_distribution_num(i),
1440 p_chg.distribution_changes.c_encumbered_flag(i),
1441 p_chg.distribution_changes.c_req_distribution_id(i),
1442 p_chg.distribution_changes.c_creation_date(i)
1443 FROM po_distributions POD, po_lines POL, po_line_types PLT,po_line_locations_all PLL -- <Complex work project for R12
1444 WHERE POD.po_distribution_id =
1445 NVL( p_chg.distribution_changes.parent_distribution_id(i), -- split dist
1446 p_chg.distribution_changes.po_distribution_id(i) ) -- existing dist
1447 AND POL.po_line_id = POD.po_line_id -- JOIN
1448 AND PLT.line_type_id = POL.line_type_id -- JOIN
1449 AND POL.po_line_id = PLL.po_line_id -- <Complex work project for R12
1450 AND POD.LINE_LOCATION_ID= PLL.LINE_LOCATION_ID
1451 ;
1452
1453
1454 EXCEPTION
1455 WHEN FND_API.g_exc_unexpected_error THEN
1456 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1457 p_proc_name => 'POPULATE_DIST_CACHED_FIELDS',
1458 p_add_to_msg_list => FALSE );
1459 RAISE FND_API.g_exc_unexpected_error;
1460 WHEN OTHERS THEN
1461 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1462 p_proc_name => 'POPULATE_DIST_CACHED_FIELDS' );
1463 RAISE FND_API.g_exc_unexpected_error;
1464 END populate_dist_cached_fields;
1465
1466 -------------------------------------------------------------------------------
1467 --Start of Comments
1468 --Name: preprocess_changes
1469 --Function:
1470 -- Performs preprocessing on the change object, such as retrieving the
1471 -- cached database fields, performing UOM quantity conversions, etc.
1472 --Pre-reqs:
1473 -- None.
1474 --Modifies:
1475 -- Modifies p_chg with cached database values, UOM converted quantities, etc.
1476 -- Writes any errors to g_api_errors.
1477 --Locks:
1478 -- None.
1479 --End of Comments
1480 -------------------------------------------------------------------------------
1481 PROCEDURE preprocess_changes (
1482 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
1483 x_return_status OUT NOCOPY VARCHAR2
1484 ) IS
1485 l_proc_name CONSTANT VARCHAR2(20) := 'PREPROCESS_CHANGES';
1486 l_progress VARCHAR2(3) := '000';
1487
1488 l_request_uom PO_LINES.unit_meas_lookup_code%TYPE;
1489 l_document_uom PO_LINES.unit_meas_lookup_code%TYPE;
1490 l_new_qty PO_LINES.quantity%TYPE;
1491 l_converted_qty PO_LINES.quantity%TYPE;
1492 l_item_id PO_LINES.item_id%TYPE;
1493 BEGIN
1494 IF (g_fnd_debug = 'Y') THEN
1495 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
1496 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
1497 module => g_module_prefix || l_proc_name,
1498 message => 'Entering ' || l_proc_name );
1499 END IF;
1500 END IF;
1501
1502 x_return_status := FND_API.G_RET_STS_SUCCESS;
1503 l_progress := '010';
1504
1505 -- Line changes
1506 FOR i IN 1..p_chg.line_changes.get_count LOOP
1507
1508 -- Preprocessing #1: For performance, cache some database field values
1509 -- that will be needed in the derivation and validation steps.
1510 populate_line_cached_fields(p_chg, i);
1511 add_line_change_to_index(p_chg, i);
1512
1513 -- Preprocessing #2: UOM Quantity Conversion
1514 -- If the change object has a request UOM that is different from the
1515 -- UOM on the document, convert the new quantity in the change object
1516 -- to the UOM of the document.
1517 l_request_uom := p_chg.line_changes.request_unit_of_measure(i);
1518 l_document_uom := p_chg.line_changes.c_unit_meas_lookup_code(i);
1519 l_item_id := p_chg.line_changes.c_item_id(i);
1520 l_new_qty := p_chg.line_changes.quantity(i);
1521
1522 IF (l_request_uom IS NOT NULL) AND (l_request_uom <> l_document_uom)
1523 AND (l_new_qty IS NOT NULL) THEN
1524 BEGIN
1525 PO_UOM_S.uom_convert(l_new_qty, l_request_uom, l_item_id,
1526 l_document_uom, l_converted_qty);
1527 p_chg.line_changes.set_quantity(i, l_converted_qty);
1528
1529 IF (g_fnd_debug = 'Y') THEN
1530 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
1531 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
1532 module => g_module_prefix || l_proc_name,
1533 message => 'Line change on '
1534 || p_chg.line_changes.po_line_id(i)
1535 || ': Converted quantity change from '
1536 || l_new_qty || ' ' || l_request_uom || ' to '
1537 || l_converted_qty || ' ' || l_document_uom );
1538 END IF;
1539 END IF;
1540 EXCEPTION
1541 WHEN OTHERS THEN
1542 add_error ( p_api_errors => g_api_errors,
1543 x_return_status => x_return_status,
1544 p_message_name => 'PO_CHNG_INVALID_UOM_CONVERSION',
1545 p_table_name => 'PO_LINES_ALL',
1546 p_column_name => 'UNIT_MEAS_LOOKUP_CODE',
1547 p_entity_type => G_ENTITY_TYPE_LINES,
1548 p_entity_id => i );
1549 RETURN;
1550 END;
1551
1552 END IF; -- request UOM
1553
1554 END LOOP; -- line changes
1555 l_progress := '020';
1556
1557 -- Shipment changes
1558 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
1559 -- Preprocessing #1: For performance, cache some database field values.
1560 populate_ship_cached_fields(p_chg, i);
1561 add_ship_change_to_index(p_chg, i);
1562
1563 -- Preprocessing #2: UOM Quantity Conversion
1564 l_request_uom := p_chg.shipment_changes.request_unit_of_measure(i);
1565 l_document_uom := p_chg.shipment_changes.c_unit_meas_lookup_code(i);
1566 l_item_id := p_chg.shipment_changes.c_item_id(i);
1567 l_new_qty := p_chg.shipment_changes.quantity(i);
1568
1569 IF (l_request_uom IS NOT NULL) AND (l_request_uom <> l_document_uom)
1570 AND (l_new_qty IS NOT NULL) THEN
1571 BEGIN
1572 PO_UOM_S.uom_convert(l_new_qty, l_request_uom, l_item_id,
1573 l_document_uom, l_converted_qty);
1574 p_chg.shipment_changes.set_quantity(i, l_converted_qty);
1575
1576 IF (g_fnd_debug = 'Y') THEN
1577 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
1578 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
1579 module => g_module_prefix || l_proc_name,
1580 message => 'Shipment change on '
1581 || p_chg.shipment_changes.po_line_location_id(i)
1582 || ': Converted quantity change from '
1583 || l_new_qty || ' ' || l_request_uom || ' to '
1584 || l_converted_qty || ' ' || l_document_uom );
1585 END IF;
1586 END IF;
1587 EXCEPTION
1588 WHEN OTHERS THEN
1589 add_error ( p_api_errors => g_api_errors,
1590 x_return_status => x_return_status,
1591 p_message_name => 'PO_CHNG_INVALID_UOM_CONVERSION',
1592 p_table_name => 'PO_LINES_ALL',
1593 p_column_name => 'UNIT_MEAS_LOOKUP_CODE',
1594 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
1595 p_entity_id => i );
1596 RETURN;
1597 END;
1598
1599 END IF; -- request UOM
1600
1601 END LOOP; -- shipment changes
1602 l_progress := '030';
1603
1604 -- Distribution changes
1605 FOR i IN 1..p_chg.distribution_changes.get_count LOOP
1606 -- Preprocessing #1: For performance, cache some database field values.
1607 populate_dist_cached_fields(p_chg, i);
1608 add_dist_change_to_index(p_chg, i);
1609
1610 -- Preprocessing #2: UOM Quantity Conversion
1611 l_request_uom := p_chg.distribution_changes.request_unit_of_measure(i);
1612 l_document_uom := p_chg.distribution_changes.c_unit_meas_lookup_code(i);
1613 l_item_id := p_chg.distribution_changes.c_item_id(i);
1614 l_new_qty := p_chg.distribution_changes.quantity_ordered(i);
1615
1616 IF (l_request_uom IS NOT NULL) AND (l_request_uom <> l_document_uom)
1617 AND (l_new_qty IS NOT NULL) THEN
1618 BEGIN
1619 PO_UOM_S.uom_convert(l_new_qty, l_request_uom, l_item_id,
1620 l_document_uom, l_converted_qty);
1621 p_chg.distribution_changes.set_quantity_ordered(i, l_converted_qty);
1622
1623 IF (g_fnd_debug = 'Y') THEN
1624 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
1625 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
1626 module => g_module_prefix || l_proc_name,
1627 message => 'Distribution change on '
1628 || p_chg.distribution_changes.po_distribution_id(i)
1629 || ': Converted quantity change from '
1630 || l_new_qty || ' ' || l_request_uom || ' to '
1631 || l_converted_qty || ' ' || l_document_uom );
1632 END IF;
1633 END IF;
1634 EXCEPTION
1635 WHEN OTHERS THEN
1636 add_error ( p_api_errors => g_api_errors,
1637 x_return_status => x_return_status,
1638 p_message_name => 'PO_CHNG_INVALID_UOM_CONVERSION',
1639 p_table_name => 'PO_LINES_ALL',
1640 p_column_name => 'UNIT_MEAS_LOOKUP_CODE',
1641 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
1642 p_entity_id => i );
1643 RETURN;
1644 END;
1645
1646 END IF; -- request UOM
1647 END LOOP; -- distribution changes
1648
1649 l_progress := '040';
1650
1651 EXCEPTION
1652 WHEN FND_API.g_exc_unexpected_error THEN
1653 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1654 p_proc_name => l_proc_name,
1655 p_progress => l_progress,
1656 p_add_to_msg_list => FALSE );
1657 RAISE FND_API.g_exc_unexpected_error;
1658 WHEN OTHERS THEN
1659 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
1660 p_proc_name => l_proc_name,
1661 p_progress => l_progress );
1662 RAISE FND_API.g_exc_unexpected_error;
1663 END preprocess_changes;
1664
1665 -------------------------------------------------------------------------------
1666 --Start of Comments
1667 --Name: verify_inputs
1668 --Function:
1669 -- Performs checks to verify that the requested changes make sense.
1670 --Pre-reqs:
1671 -- None.
1672 --Modifies:
1673 -- Writes any errors to g_api_errors.
1674 --Locks:
1675 -- None.
1676 --Notes:
1677 -- The PO Change API has two validation procedures:
1678 -- 1. verify_inputs: called before the derivations (derive_changes)
1679 -- 2. validate_changes: called after the derivations (derive_changes)
1680 --
1681 -- Most validations should be placed in validate_changes, allowing them to
1682 -- validate both requested and derived changes.
1683 -- However, there are certain checks that should be performed *before*
1684 -- derivation (ex. to prevent changes to fields that do not exist on the given
1685 -- document type); these checks should be placed in verify_inputs.
1686 --End of Comments
1687 -------------------------------------------------------------------------------
1688 PROCEDURE verify_inputs (
1689 p_chg IN PO_CHANGES_REC_TYPE,
1690 x_return_status OUT NOCOPY VARCHAR2
1691 ) IS
1692 l_proc_name CONSTANT VARCHAR2(30) := 'VERIFY_INPUTS';
1693 l_progress VARCHAR2(3) := '000';
1694
1695 l_shipment_count NUMBER;
1696 l_return_status VARCHAR2(1);
1697 l_grade_control_flag MTL_SYSTEM_ITEMS.GRADE_CONTROL_FLAG%TYPE; /* INVCONV sschinch 09.08.04*/
1698 l_dual_uom_ind MTL_SYSTEM_ITEMS.TRACKING_QUANTITY_IND%TYPE; /* INVCONV sschinch 11.11.04 */
1699 l_secondary_default_ind MTL_SYSTEM_ITEMS.SECONDARY_DEFAULT_IND%TYPE; /* INVCONV */
1700 BEGIN
1701 IF (g_fnd_debug = 'Y') THEN
1702 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
1703 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
1704 module => g_module_prefix || l_proc_name,
1705 message => 'Entering ' || l_proc_name );
1706 END IF;
1707 END IF;
1708
1709 x_return_status := FND_API.G_RET_STS_SUCCESS;
1710
1711 -- Check if there are changes to fields that are not applicable for the
1712 -- requested document type or line type.
1713 l_progress := '010';
1714 check_type_specific_fields ( p_chg, x_return_status );
1715 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1716 return; -- Do not continue if any type-specific fields checks failed.
1717 END IF;
1718
1719 -- Line changes
1720 FOR i IN 1..p_chg.line_changes.get_count LOOP
1721
1722 --------------------------------------------------------------------------
1723 -- Line Check: Basic checks on the new quantity, price, and amount.
1724 --------------------------------------------------------------------------
1725
1726 -- Note: We do these checks in verify_inputs instead of validate_changes
1727 -- to avoid performing derivations with nonsensical values - ex. to avoid
1728 -- rolling down negative quantities to the shipments and distributions.
1729 l_progress := '020';
1730 check_new_qty_price_amt(p_chg,G_ENTITY_TYPE_LINES,i,l_return_status);
1731 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1732 x_return_status := l_return_status;
1733 END IF;
1734
1735 --------------------------------------------------------------------------
1736 -- Line Check: For a line with multiple active (i.e. not cancelled
1737 -- or finally cloesd) shipments, it is an error to have a line
1738 -- quantity/amount change without any shipment quantity/amount changes.
1739 -- Note: This is because we do not prorate from a line to multiple
1740 -- shipments.
1741 --------------------------------------------------------------------------
1742 l_progress := '040';
1743 IF (g_document_type = 'PO') THEN
1744
1745 IF (line_has_qty_amt_change(p_chg, i))
1746 AND (NOT line_has_ship_qty_amt_change(p_chg, i)) THEN
1747 -- The line has a quantity/amount change, but none of its shipments
1748 -- have quantity/amount changes.
1749
1750 -- SQL What: Returns the number of standard/planned shipments
1751 -- for this line that are not cancelled or finally closed.
1752 SELECT count(*)
1753 INTO l_shipment_count
1754 FROM po_line_locations
1755 WHERE po_line_id = p_chg.line_changes.po_line_id(i)
1756 AND shipment_type in ('STANDARD', 'PLANNED')
1757 AND nvl(cancel_flag,'N') <> 'Y'
1758 AND NVL(closed_code,'OPEN') <> 'FINALLY CLOSED';
1759
1760 IF (l_shipment_count > 1) THEN -- The line has multiple shipments
1761 add_error ( p_api_errors => g_api_errors,
1762 x_return_status => x_return_status,
1763 p_message_name => 'PO_CHNG_QTY_AMT_MULTI_SHIP',
1764 p_table_name => 'PO_LINES_ALL',
1765 p_column_name => null,
1766 p_entity_type => G_ENTITY_TYPE_LINES,
1767 p_entity_id => i );
1768 END IF; -- l_num_shipments
1769 END IF; -- new line quantity / amount
1770
1771 END IF; -- document type is PO
1772
1773 --------------------------------------------------------------------------
1774 -- Line Check: It is an error to specify a secondary quantity change
1775 -- on a line that does not have a secondary UOM.
1776 --------------------------------------------------------------------------
1777 l_progress := '050';
1778 IF (p_chg.line_changes.secondary_quantity(i) IS NOT NULL)
1779 AND (p_chg.line_changes.c_secondary_uom(i) IS NULL) THEN
1780
1781 add_error ( p_api_errors => g_api_errors,
1782 x_return_status => x_return_status,
1783 p_message_name => 'PO_CHNG_QTY2_NO_UOM2',
1784 p_table_name => 'PO_LINES_ALL',
1785 p_column_name => 'SECONDARY_QUANTITY',
1786 p_entity_type => G_ENTITY_TYPE_LINES,
1787 p_entity_id => i );
1788 END IF;
1789
1790 --------------------------------------------------------------------------
1791 -- Line Check: We currently do not support changes to the secondary
1792 -- quantity without a change to the primary quantity.
1793 --------------------------------------------------------------------------
1794
1795 l_progress := '060';
1796 /*IF (p_chg.line_changes.secondary_quantity(i) IS NOT NULL)
1797 AND (p_chg.line_changes.quantity(i) IS NULL)
1798 THEN
1799
1800 add_error ( p_api_errors => g_api_errors,
1801 x_return_status => x_return_status,
1802 p_message_name => 'PO_CHNG_QTY2_NO_QTY',
1803 p_table_name => 'PO_LINES_ALL',
1804 p_column_name => 'SECONDARY_QUANTITY',
1805 p_entity_type => G_ENTITY_TYPE_LINES,
1806 p_entity_id => i );
1807 END IF;
1808 */
1809
1810 /* BEGIN INVCONV SSCHINCH 11/11/04*/
1811 l_progress := '070';
1812 -- Change grade at PO Line Level only if PO Line number is specified
1813 -- because we cannot update grade on both lines and shipment lines together
1814 -- since one of them can be non grade controlled.
1815
1816 IF ( p_chg.line_changes.c_preferred_grade(i) IS NULL AND
1817 p_chg.line_changes.preferred_grade(i) IS NOT NULL AND
1818 p_chg.shipment_changes.get_count = 0) THEN
1819
1820 SELECT NVL(mtl.grade_control_flag,'N')
1821 INTO l_grade_control_flag
1822 FROM mtl_system_items_b mtl,
1823 financials_system_parameters fsp
1824 WHERE mtl.inventory_item_id = p_chg.line_changes.c_item_id(i)
1825 AND mtl.organization_id = fsp.inventory_organization_id;
1826
1827 IF l_grade_control_flag = 'N' THEN
1828 add_error ( p_api_errors => g_api_errors,
1829 x_return_status => x_return_status,
1830 p_message_name => 'INV_ITEM_NOT_GRADE_CTRL_EXP',
1831 p_table_name => 'PO_LINES_ALL',
1832 p_column_name => 'PREFERRED_GRADE',
1833 p_entity_type => G_ENTITY_TYPE_LINES,
1834 p_entity_id => i);
1835 END IF;
1836 END IF;
1837
1838 l_progress := '080';
1839 IF ( p_chg.line_changes.secondary_quantity(i) IS NOT NULL AND
1840 p_chg.line_changes.c_secondary_quantity(i) IS NULL AND
1841 p_chg.shipment_changes.get_count = 0) THEN
1842
1843 IF p_chg.line_changes.c_item_id(i) IS NOT NULL THEN
1844 SELECT msi.tracking_quantity_ind,msi.secondary_default_ind
1845 INTO l_dual_uom_ind,l_secondary_default_ind
1846 FROM mtl_system_items_b msi,
1847 financials_system_parameters fsp
1848 WHERE msi.inventory_item_id = p_chg.line_changes.c_item_id(i)
1849 AND msi.organization_id = fsp.inventory_organization_id;
1850 ELSE
1851 l_dual_uom_ind := 'P';
1852 END IF;
1853
1854 IF (l_dual_uom_ind = 'P') THEN
1855 add_error ( p_api_errors => g_api_errors,
1856 x_return_status => x_return_status,
1857 p_message_name => 'PO_CHNG_NON_DUAL_ITEM',
1858 p_table_name => 'PO_LINES_ALL',
1859 p_column_name => 'SECONDARY_QUANTITY',
1860 p_entity_type => G_ENTITY_TYPE_LINES,
1861 p_entity_id => i );
1862
1863
1864 ELSIF (l_secondary_default_ind = 'F') THEN
1865 PO_DOCUMENT_UPDATE_PVT.add_error (
1866 p_api_errors => g_api_errors,
1867 x_return_status => l_return_status,
1868 p_message_name => 'PO_DUALFIXED_NO_CONVERSION',
1869 p_token_name1 => 'PQTY',
1870 p_token_value1 => p_chg.shipment_changes.c_quantity(i),
1871 p_token_name2 => 'SQTY',
1872 p_token_value2 => p_chg.line_changes.secondary_quantity(i));
1873 x_return_status := FND_API.G_RET_STS_ERROR;
1874 RETURN;
1875 END IF;
1876 END IF;
1877
1878 l_progress := '090';
1879 IF ( p_chg.line_changes.secondary_quantity(i) IS NOT NULL AND
1880 p_chg.line_changes.c_secondary_quantity(i) IS NOT NULL AND
1881 p_chg.shipment_changes.get_count = 0) THEN
1882
1883 IF p_chg.line_changes.c_item_id(i) IS NOT NULL THEN
1884 SELECT msi.tracking_quantity_ind,msi.secondary_default_ind
1885 INTO l_dual_uom_ind,l_secondary_default_ind
1886 FROM mtl_system_items_b msi,
1887 financials_system_parameters fsp
1888 WHERE msi.inventory_item_id = p_chg.line_changes.c_item_id(i)
1889 AND msi.organization_id = fsp.inventory_organization_id;
1890 ELSE
1891 l_dual_uom_ind := 'P';
1892 END IF;
1893
1894 IF (l_dual_uom_ind = 'P') THEN
1895 add_error ( p_api_errors => g_api_errors,
1896 x_return_status => x_return_status,
1897 p_message_name => 'PO_CHNG_NON_DUAL_ITEM',
1898 p_table_name => 'PO_LINES_ALL',
1899 p_column_name => 'SECONDARY_QUANTITY',
1900 p_entity_type => G_ENTITY_TYPE_LINES,
1901 p_entity_id => i );
1902
1903 END IF;
1904 END IF;
1905
1906 /* END INVCONV SSCHINCH 11/11/04*/
1907
1908 END LOOP; -- line changes
1909 l_grade_control_flag := NULL; --INVCONV
1910 -- Shipment changes
1911 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
1912
1913 --------------------------------------------------------------------------
1914 -- Shipment Check: Basic checks on the new quantity, price, and amount.
1915 --------------------------------------------------------------------------
1916 l_progress := '100';
1917 check_new_qty_price_amt(p_chg,G_ENTITY_TYPE_SHIPMENTS,i,l_return_status);
1918 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1919 x_return_status := l_return_status;
1920 END IF;
1921
1922 --------------------------------------------------------------------------
1923 -- Shipment Check: It is an error to specify a secondary quantity change
1924 -- on a shipment that does not have a secondary UOM.
1925 --------------------------------------------------------------------------
1926 /* INVCONV sschinch 09/07/04
1927 *Need to remove the following validation
1928 *-- We currently do not support changes to the secondary quantity without a change to the primary quantity.
1929 *
1930 *l_progress := '110';
1931 *IF (p_chg.shipment_changes.secondary_quantity(i) IS NOT NULL)
1932 * AND (p_chg.shipment_changes.c_secondary_uom(i) IS NULL) THEN
1933 *
1934 * add_error ( p_api_errors => g_api_errors,
1935 * x_return_status => x_return_status,
1936 * p_message_name => 'PO_CHNG_QTY2_NO_UOM2',
1937 * p_table_name => 'PO_LINE_LOCATIONS_ALL',
1938 * p_column_name => 'SECONDARY_QUANTITY',
1939 * p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
1940 * p_entity_id => i );
1941 *END IF;
1942 *
1943 **/
1944
1945 /** BEGIN INVCONV we don't support secondary qty / grade for price breaks **/
1946 IF (p_chg.shipment_changes.secondary_quantity(i) IS NOT NULL OR
1947 p_chg.shipment_changes.preferred_grade(i) IS NOT NULL) AND
1948 g_document_type = 'PA' THEN
1949 add_error ( p_api_errors => g_api_errors,
1950 x_return_status => x_return_status,
1951 p_message_name => 'PO_CHNG_QTY2_GRADE_PA',
1952 p_table_name => 'PO_LINE_LOCATIONS_ALL',
1953 p_column_name => 'SECONDARY_QUANTITY',
1954 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
1955 p_entity_id => i );
1956 END IF;
1957
1958 /* If Item is not grade control and grade is specified error out */
1959
1960 IF ( p_chg.shipment_changes.preferred_grade(i) IS NOT NULL)
1961 AND (p_chg.shipment_changes.c_item_id(i) IS NOT NULL) THEN
1962
1963 SELECT NVL(grade_control_flag,'N') INTO l_grade_control_flag
1964 FROM mtl_system_items
1965 WHERE inventory_item_id = p_chg.shipment_changes.c_item_id(i)
1966 AND organization_id = p_chg.shipment_changes.c_ship_to_organization_id(i) ;
1967
1968 IF l_grade_control_flag = 'N' THEN
1969 add_error ( p_api_errors => g_api_errors,
1970 x_return_status => x_return_status,
1971 p_message_name => ' INV_ITEM_NOT_GRADE_CTRL_EXP',
1972 p_table_name => 'PO_LINE_LOCATIONS_ALL',
1973 p_column_name => 'PREFERRED_GRADE',
1974 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
1975 p_entity_id => i);
1976 END IF;
1977 END IF;
1978
1979 /* END INVCONV SSCHINCH 09/07/04*/
1980 --------------------------------------------------------------------------
1981 -- Shipment Check: We currently do not support changes to the secondary
1982 -- quantity without a change to the primary quantity.
1983 --------------------------------------------------------------------------
1984 /*l_progress := '120'; INVCONV sschinch
1985 IF (p_chg.shipment_changes.secondary_quantity(i) IS NOT NULL)
1986 AND (p_chg.shipment_changes.quantity(i) IS NULL) THEN
1987
1988 add_error ( p_api_errors => g_api_errors,
1989 x_return_status => x_return_status,
1990 p_message_name => 'PO_CHNG_QTY2_NO_QTY',
1991 p_table_name => 'PO_LINE_LOCATIONS_ALL',
1992 p_column_name => 'SECONDARY_QUANTITY',
1993 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
1994 p_entity_id => i );
1995 END IF;
1996 INVCONV */
1997
1998 --------------------------------------------------------------------------
1999 -- Split shipment checks:
2000 --------------------------------------------------------------------------
2001 IF (p_chg.shipment_changes.parent_line_location_id(i) IS NOT NULL) THEN
2002
2003 ------------------------------------------------------------------------
2004 -- Check: Split shipments must have quantity or amount.
2005 ------------------------------------------------------------------------
2006 l_progress := '150';
2007 IF (p_chg.shipment_changes.quantity(i) IS NULL)
2008 AND (p_chg.shipment_changes.amount(i) IS NULL) THEN
2009 add_error ( p_api_errors => g_api_errors,
2010 x_return_status => x_return_status,
2011 p_message_name => 'PO_CHNG_SPLIT_SHIP_QTY_AMT',
2012 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2013 p_column_name => NULL,
2014 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2015 p_entity_id => i );
2016 END IF;
2017
2018 ------------------------------------------------------------------------
2019 -- Check: Each split shipment must have a split shipment number.
2020 ------------------------------------------------------------------------
2021 l_progress := '155';
2022 IF (p_chg.shipment_changes.split_shipment_num(i) IS NULL) THEN
2023 add_error ( p_api_errors => g_api_errors,
2024 x_return_status => x_return_status,
2025 p_message_name => 'PO_CHNG_UNIQUE_SPLIT_SHIP_NUM',
2026 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2027 p_column_name => NULL,
2028 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2029 p_entity_id => i );
2030 END IF;
2031
2032 ------------------------------------------------------------------------
2033 -- Check: Split shipment numbers must be unique (i.e. there cannot be any
2034 -- existing shipments or split shipment changes for the line with the
2035 -- same shipment number.)
2036 ------------------------------------------------------------------------
2037 l_progress := '160';
2038 IF (p_chg.shipment_changes.split_shipment_num(i) IS NOT NULL) THEN
2039 -- SQL What: Returns 1 if a shipment exists for this PO line and
2040 -- release with the given split shipment number, 0 otherwise.
2041 -- SQL Why: To determine if the given split shipment number is unique.
2042 SELECT count(*)
2043 INTO l_shipment_count
2044 FROM po_line_locations
2045 WHERE po_line_id = p_chg.shipment_changes.c_po_line_id(i)
2046 AND shipment_num = p_chg.shipment_changes.split_shipment_num(i)
2047 AND NVL(po_release_id,-1) = NVL(g_po_release_id,-1);
2048
2049 IF (l_shipment_count > 0)
2050 OR (NOT is_split_shipment_num_unique(p_chg,i)) THEN
2051 add_error ( p_api_errors => g_api_errors,
2052 x_return_status => x_return_status,
2053 p_message_name => 'PO_CHNG_UNIQUE_SPLIT_SHIP_NUM',
2054 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2055 p_column_name => NULL,
2056 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2057 p_entity_id => i );
2058 END IF;
2059 END IF; -- split_shipment_num
2060
2061 ------------------------------------------------------------------------
2062 -- Check: You cannot delete a split shipment.
2063 ------------------------------------------------------------------------
2064 l_progress := '165';
2065 IF (p_chg.shipment_changes.delete_record(i) = G_PARAMETER_YES) THEN
2066 add_error ( p_api_errors => g_api_errors,
2067 x_return_status => x_return_status,
2068 p_message_name => 'PO_CHNG_SPLIT_SHIP_NO_DELETE',
2069 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2070 p_column_name => NULL,
2071 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2072 p_entity_id => i );
2073 END IF; -- delete_record
2074
2075 END IF; -- split shipment
2076
2077 END LOOP; -- shipment changes
2078
2079 -- Distribution changes
2080 FOR i IN 1..p_chg.distribution_changes.get_count LOOP
2081
2082 --------------------------------------------------------------------------
2083 -- Distribution Check: Basic checks on the new quantity and amount.
2084 --------------------------------------------------------------------------
2085 l_progress := '200';
2086 check_new_qty_price_amt(p_chg,G_ENTITY_TYPE_DISTRIBUTIONS, i,
2087 l_return_status);
2088 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
2089 x_return_status := l_return_status;
2090 END IF;
2091
2092 --------------------------------------------------------------------------
2093 -- Split distribution checks:
2094 --------------------------------------------------------------------------
2095 IF (p_chg.distribution_changes.parent_distribution_id(i) IS NOT NULL) THEN
2096
2097 ------------------------------------------------------------------------
2098 -- Check: Split distributions must have quantity or amount.
2099 ------------------------------------------------------------------------
2100 l_progress := '250';
2101 IF (p_chg.distribution_changes.quantity_ordered(i) IS NULL)
2102 AND (p_chg.distribution_changes.amount_ordered(i) IS NULL) THEN
2103 add_error ( p_api_errors => g_api_errors,
2104 x_return_status => x_return_status,
2105 p_message_name => 'PO_CHNG_SPLIT_DIST_QTY_AMT',
2106 p_table_name => 'PO_DISTRIBUTIONS_ALL',
2107 p_column_name => NULL,
2108 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
2109 p_entity_id => i );
2110 END IF;
2111
2112 ------------------------------------------------------------------------
2113 -- Check: Each split distribution must have a corresponding split
2114 -- shipment change.
2115 ------------------------------------------------------------------------
2116 l_progress := '255';
2117 IF ((p_chg.distribution_changes.split_shipment_num(i) IS NULL) OR
2118 (get_split_ship_change ( p_chg,
2119 p_chg.distribution_changes.c_po_line_id(i),
2120 p_chg.distribution_changes.c_parent_line_location_id(i),
2121 p_chg.distribution_changes.split_shipment_num(i) ) IS NULL)) THEN
2122
2123 add_error ( p_api_errors => g_api_errors,
2124 x_return_status => x_return_status,
2125 p_message_name => 'PO_CHNG_SPLIT_DIST_SHIP_NUM',
2126 p_table_name => 'PO_DISTRIBUTIONS_ALL',
2127 p_column_name => NULL,
2128 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
2129 p_entity_id => i );
2130 END IF;
2131
2132 ------------------------------------------------------------------------
2133 -- Check: You cannot delete a split distribution.
2134 ------------------------------------------------------------------------
2135 l_progress := '260';
2136 IF (p_chg.distribution_changes.delete_record(i) = G_PARAMETER_YES) THEN
2137 add_error ( p_api_errors => g_api_errors,
2138 x_return_status => x_return_status,
2139 p_message_name => 'PO_CHNG_SPLIT_DIST_NO_DELETE',
2140 p_table_name => 'PO_DISTRIBUTIONS_ALL',
2141 p_column_name => NULL,
2142 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
2143 p_entity_id => i );
2144 END IF; -- delete_record
2145
2146 END IF; -- split distribution
2147
2148 END LOOP; -- distribution changes
2149
2150 l_progress := '500';
2151
2152 EXCEPTION
2153 WHEN FND_API.g_exc_unexpected_error THEN
2154 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2155 p_proc_name => l_proc_name,
2156 p_progress => l_progress,
2157 p_add_to_msg_list => FALSE );
2158 RAISE FND_API.g_exc_unexpected_error;
2159 WHEN OTHERS THEN
2160 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2161 p_proc_name => l_proc_name,
2162 p_progress => l_progress );
2163 RAISE FND_API.g_exc_unexpected_error;
2164 END verify_inputs;
2165
2166 -------------------------------------------------------------------------------
2167 --Start of Comments
2168 --Name: check_type_specific_fields
2169 --Function:
2170 -- Returns an error if there are changes to fields that are only allowed
2171 -- for certain document types or line types.
2172 --Pre-reqs:
2173 -- None.
2174 --Modifies:
2175 -- Writes any errors to g_api_errors.
2176 --Locks:
2177 -- None.
2178 --End of Comments
2179 -------------------------------------------------------------------------------
2180 PROCEDURE check_type_specific_fields (
2181 p_chg IN PO_CHANGES_REC_TYPE,
2182 x_return_status OUT NOCOPY VARCHAR2
2183 ) IS
2184 l_proc_name CONSTANT VARCHAR2(30) := 'CHECK_TYPE_SPECIFIC_FIELDS';
2185 l_progress VARCHAR2(3) := '000';
2186 BEGIN
2187 IF (g_fnd_debug = 'Y') THEN
2188 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
2189 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
2190 module => g_module_prefix || l_proc_name,
2191 message => 'Entering ' || l_proc_name );
2192 END IF;
2193 END IF;
2194
2195 l_progress := '010';
2196 x_return_status := FND_API.G_RET_STS_SUCCESS;
2197
2198 ----------------------------------------------------------------------------
2199 -- Blanket PA checks:
2200 ----------------------------------------------------------------------------
2201 IF g_document_type='PA' AND g_document_subtype='BLANKET' THEN
2202
2203 -- Line changes
2204 l_progress := '020';
2205 FOR i IN 1..p_chg.line_changes.get_count LOOP
2206 ------------------------------------------------------------------------
2207 -- Check: A blanket cannot have any line quantity or amount changes.
2208 ------------------------------------------------------------------------
2209 IF (p_chg.line_changes.quantity(i) IS NOT NULL)
2210 OR (p_chg.line_changes.amount(i) IS NOT NULL) THEN
2211 add_error ( p_api_errors => g_api_errors,
2212 x_return_status => x_return_status,
2213 p_message_name => 'PO_CHNG_BLKT_LINE_BAD_FIELD',
2214 p_table_name => 'PO_LINES_ALL',
2215 p_column_name => 'QUANTITY',
2216 p_token_name1 => 'COLUMN_NAME',
2217 p_token_value1 => 'QUANTITY',
2218 p_entity_type => G_ENTITY_TYPE_LINES,
2219 p_entity_id => i );
2220 END IF;
2221 END LOOP; -- line changes
2222
2223 -- Shipment changes
2224 l_progress := '030';
2225 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
2226
2227 ------------------------------------------------------------------------
2228 -- Check: A blanket cannot have any promised date, need-by date,
2229 -- or split shipment changes.
2230 ------------------------------------------------------------------------
2231 IF (p_chg.shipment_changes.promised_date(i) IS NOT NULL) THEN
2232 add_error ( p_api_errors => g_api_errors,
2233 x_return_status => x_return_status,
2234 p_message_name => 'PO_CHNG_BLKT_SHIP_BAD_FIELD',
2235 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2236 p_column_name => 'PROMISED_DATE',
2237 p_token_name1 => 'COLUMN_NAME',
2238 p_token_value1 => 'PROMISED_DATE',
2239 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2240 p_entity_id => i );
2241 END IF;
2242
2243 IF (p_chg.shipment_changes.need_by_date(i) IS NOT NULL) THEN
2244 add_error ( p_api_errors => g_api_errors,
2245 x_return_status => x_return_status,
2246 p_message_name => 'PO_CHNG_BLKT_SHIP_BAD_FIELD',
2247 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2248 p_column_name => 'NEED_BY_DATE',
2249 p_token_name1 => 'COLUMN_NAME',
2250 p_token_value1 => 'NEED_BY_DATE',
2251 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2252 p_entity_id => i );
2253 END IF;
2254
2255 IF (p_chg.shipment_changes.parent_line_location_id(i) IS NOT NULL) THEN
2256 add_error ( p_api_errors => g_api_errors,
2257 x_return_status => x_return_status,
2258 p_message_name => 'PO_CHNG_BLKT_NO_SPLIT_SHIP',
2259 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2260 p_column_name => null,
2261 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2262 p_entity_id => i );
2263 END IF;
2264 END LOOP; -- shipment changes
2265
2266 --------------------------------------------------------------------------
2267 -- Check: A blanket cannot have any distribution changes.
2268 --------------------------------------------------------------------------
2269 l_progress := '040';
2270 IF (p_chg.distribution_changes.get_count > 0) THEN
2271 add_error ( p_api_errors => g_api_errors,
2272 x_return_status => x_return_status,
2273 p_message_name => 'PO_CHNG_BLKT_NO_DISTS',
2274 p_table_name => 'PO_DISTRIBUTIONS_ALL',
2275 p_column_name => null,
2276 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS );
2277 END IF;
2278
2279 END IF; -- document type is blanket
2280
2281 l_progress := '050';
2282
2283 ----------------------------------------------------------------------------
2284 -- Check: A release cannot have any line changes.
2285 ----------------------------------------------------------------------------
2286 IF (g_document_type = 'RELEASE') AND (p_chg.line_changes.get_count > 0) THEN
2287 add_error ( p_api_errors => g_api_errors,
2288 x_return_status => x_return_status,
2289 p_message_name => 'PO_CHNG_RELEASE_NO_LINES',
2290 p_table_name => 'PO_LINES_ALL',
2291 p_column_name => null,
2292 p_entity_type => G_ENTITY_TYPE_LINES );
2293 END IF;
2294
2295 ----------------------------------------------------------------------------
2296 -- Check: A standard/planned PO cannot have any shipment price changes.
2297 ----------------------------------------------------------------------------
2298 IF (g_document_type = 'PO') THEN
2299 IF (g_is_complex_work_po=FALSE) THEN --<Complex work project for R12
2300 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
2301 IF (p_chg.shipment_changes.price_override(i) IS NOT NULL) THEN
2302
2303 add_error ( p_api_errors => g_api_errors,
2304 x_return_status => x_return_status,
2305 p_message_name => 'PO_CHNG_PO_NO_SHIP_PRICE',
2306 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2307 p_column_name => 'PRICE_OVERRIDE',
2308 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2309 p_entity_id => G_ENTITY_TYPE_LINES );
2310 END IF;
2311 END LOOP; -- shipment changes
2312 END IF; --complex PO changes
2313 END IF; -- standard/planned PO
2314
2315 ----------------------------------------------------------------------------
2316 -- Checks for Services Procurement fields and line types:
2317 ----------------------------------------------------------------------------
2318
2319 -- Line changes
2320 FOR i IN 1..p_chg.line_changes.get_count LOOP
2321
2322 --< BUG 5406211 START >
2323 l_progress := '055';
2324
2325 IF (p_chg.line_changes.c_value_basis(i) = 'FIXED PRICE') THEN
2326 ------------------------------------------------------------------------
2327 -- Prevent Price changes on lines whose Line Type is Fixed Price.
2328 ------------------------------------------------------------------------
2329
2330 IF (p_chg.line_changes.unit_price(i) IS NOT NULL ) THEN
2331 add_error( p_api_errors => g_api_errors,x_return_status => x_return_status,
2332 p_message_name => 'PO_NO_PRICE_CHNG_FP_LINES',
2333 p_table_name => 'PO_LINES_ALL',p_column_name => 'PRICE',
2334 p_entity_type => g_entity_type_lines,p_entity_id => i);
2335 END IF;
2336 ELSIF (p_chg.line_changes.c_value_basis(i) = 'AMOUNT') THEN
2337 ------------------------------------------------------------------------
2338 -- Prevent Price changes on lines whose Line Type is Amount.
2339 ------------------------------------------------------------------------
2340
2341 IF (p_chg.line_changes.unit_price(i) IS NOT NULL ) THEN
2342 add_error( p_api_errors => g_api_errors,x_return_status => x_return_status,
2343 p_message_name => 'PO_NO_PRICE_CHNG_AMT_LINES',
2344 p_table_name => 'PO_LINES_ALL',p_column_name => 'PRICE',
2345 p_entity_type => g_entity_type_lines,p_entity_id => i);
2346 END IF;
2347 END IF;
2348 --< BUG 5406211 END >
2349
2350 l_progress := '060';
2351
2352 IF (p_chg.line_changes.c_value_basis(i) IN ('RATE', 'FIXED PRICE')) THEN
2353
2354 ------------------------------------------------------------------------
2355 -- Services Check: Prevent quantity changes on lines whose value basis
2356 -- is Rate or Fixed Price.
2357 ------------------------------------------------------------------------
2358 IF (p_chg.line_changes.quantity(i) IS NOT NULL) THEN
2359 add_error ( p_api_errors => g_api_errors,
2360 x_return_status => x_return_status,
2361 p_message_name => 'PO_SVC_NO_QTY',
2362 p_table_name => 'PO_LINES_ALL',
2363 p_column_name => 'QUANTITY',
2364 p_entity_type => G_ENTITY_TYPE_LINES,
2365 p_entity_id => i );
2366 END IF;
2367
2368 ELSE -- Value basis is not Rate or Fixed Price
2369
2370 ------------------------------------------------------------------------
2371 -- Services Check: Prevent amount changes on lines whose value basis
2372 -- is not Rate or Fixed Price.
2373 ------------------------------------------------------------------------
2374 IF (p_chg.line_changes.amount(i) IS NOT NULL) THEN
2375 add_error ( p_api_errors => g_api_errors,
2376 x_return_status => x_return_status,
2377 p_message_name => 'PO_SVC_NO_AMT',
2378 p_table_name => 'PO_LINES_ALL',
2379 p_column_name => 'AMOUNT',
2380 p_entity_type => G_ENTITY_TYPE_LINES,
2381 p_entity_id => i );
2382 END IF;
2383
2384 END IF; -- value basis
2385
2386 --------------------------------------------------------------------------
2387 -- Services Check: Only allow start date and end date changes for
2388 -- lines with a purchase basis of Temp Labor on standard POs.
2389 --------------------------------------------------------------------------
2390 l_progress := '070';
2391 IF NOT ((g_document_type = 'PO') AND (g_document_subtype = 'STANDARD')
2392 AND (p_chg.line_changes.c_purchase_basis(i) = 'TEMP LABOR')) THEN
2393 -- This is not a Temp Labor line on a standard PO.
2394
2395 IF (p_chg.line_changes.start_date(i) IS NOT NULL) THEN
2396 add_error ( p_api_errors => g_api_errors,
2397 x_return_status => x_return_status,
2398 p_message_name => 'PO_SVC_NO_START_END_DATE',
2399 p_table_name => 'PO_LINES_ALL',
2400 p_column_name => 'START_DATE',
2401 p_entity_type => G_ENTITY_TYPE_LINES,
2402 p_entity_id => i );
2403 END IF;
2404
2405 IF (p_chg.line_changes.expiration_date(i) IS NOT NULL) THEN
2406 add_error ( p_api_errors => g_api_errors,
2407 x_return_status => x_return_status,
2408 p_message_name => 'PO_SVC_NO_START_END_DATE',
2409 p_table_name => 'PO_LINES_ALL',
2410 p_column_name => 'EXPIRATION_DATE',
2411 p_entity_type => G_ENTITY_TYPE_LINES,
2412 p_entity_id => i );
2413 END IF;
2414 END IF; -- document type = 'PO'
2415
2416 END LOOP; -- line changes
2417
2418 -- Shipment changes
2419 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
2420
2421 --< BUG 5406211 START >
2422 l_progress := '075';
2423
2424 IF (p_chg.shipment_changes.c_value_basis(i) = 'FIXED PRICE') THEN
2425 ------------------------------------------------------------------------
2426 -- Prevent Price changes on Shipments whose Line Type is Fixed Price.
2427 ------------------------------------------------------------------------
2428
2429 IF (p_chg.shipment_changes.price_override(i) IS NOT NULL ) THEN
2430 add_error( p_api_errors => g_api_errors,x_return_status => x_return_status,
2431 p_message_name => 'PO_NO_PRICE_CHNG_FP_LINES',
2432 p_table_name => 'PO_LINE_LOCATIONS_ALL',p_column_name => 'PRICE',
2433 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,p_entity_id => i);
2434 END IF;
2435 ELSIF (p_chg.shipment_changes.c_value_basis(i) = 'AMOUNT') THEN
2436 ------------------------------------------------------------------------
2437 -- Prevent Price changes on Shipments whose Line Type is Amount.
2438 ------------------------------------------------------------------------
2439
2440 IF (p_chg.shipment_changes.price_override(i) IS NOT NULL ) THEN
2441 add_error( p_api_errors => g_api_errors,x_return_status => x_return_status,
2442 p_message_name => 'PO_NO_PRICE_CHNG_AMT_LINES',
2443 p_table_name => 'PO_LINE_LOCATIONS_ALL',p_column_name => 'PRICE',
2444 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,p_entity_id => i);
2445 END IF;
2446 END IF;
2447 --< BUG 5406211 END >
2448
2449 IF p_chg.shipment_changes.c_value_basis(i) IN ('RATE', 'FIXED PRICE') THEN
2450
2451 ------------------------------------------------------------------------
2452 -- Services Check: Prevent quantity changes on shipments with
2453 -- value basis of Rate or Fixed Price.
2454 ------------------------------------------------------------------------
2455 l_progress := '080';
2456 IF (g_is_complex_work_po=FALSE) THEN --<Complex work project for R12
2457 IF (p_chg.shipment_changes.quantity(i) IS NOT NULL) THEN
2458 add_error ( p_api_errors => g_api_errors,
2459 x_return_status => x_return_status,
2460 p_message_name => 'PO_SVC_NO_QTY',
2461 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2462 p_column_name => 'QUANTITY',
2463 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2464 p_entity_id => i );
2465 END IF;
2466 END IF;
2467
2468 ELSE -- Value basis is not Rate or Fixed Price
2469
2470 ------------------------------------------------------------------------
2471 -- Services Check: Prevent amount changes on shipments whose
2472 -- value basis is not Rate or Fixed Price.
2473 ------------------------------------------------------------------------
2474 l_progress := '090';
2475 IF (p_chg.shipment_changes.amount(i) IS NOT NULL) THEN
2476 add_error ( p_api_errors => g_api_errors,
2477 x_return_status => x_return_status,
2478 p_message_name => 'PO_SVC_NO_AMT',
2479 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2480 p_column_name => 'AMOUNT',
2481 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2482 p_entity_id => i );
2483 END IF;
2484 END IF; -- value basis
2485
2486 --------------------------------------------------------------------------
2487 -- Services Check: Prevent need-by date and promised date changes on
2488 -- lines with a purchase basis of Temp Labor.
2489 --------------------------------------------------------------------------
2490 l_progress := '100';
2491 IF (g_is_complex_work_po=FALSE) THEN
2492 IF (p_chg.shipment_changes.c_purchase_basis(i) = 'TEMP LABOR') THEN
2493 IF (p_chg.shipment_changes.need_by_date(i) IS NOT NULL) THEN
2494 add_error ( p_api_errors => g_api_errors,
2495 x_return_status => x_return_status,
2496 p_message_name => 'PO_SVC_NO_NEED_PROMISE_DATE',
2497 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2498 p_column_name => 'NEED_BY_DATE',
2499 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2500 p_entity_id => i );
2501 END IF;
2502
2503 IF (p_chg.shipment_changes.promised_date(i) IS NOT NULL) THEN
2504 add_error ( p_api_errors => g_api_errors,
2505 x_return_status => x_return_status,
2506 p_message_name => 'PO_SVC_NO_NEED_PROMISE_DATE',
2507 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2508 p_column_name => 'PROMISED_DATE',
2509 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2510 p_entity_id => i );
2511 END IF;
2512 END IF;
2513
2514 --------------------------------------------------------------------------
2515 -- Services Check: Prevent split shipment changes on the shipments of
2516 -- lines with a purchase basis of Temp Labor.
2517 --------------------------------------------------------------------------
2518 l_progress := '110';
2519
2520 IF (p_chg.shipment_changes.parent_line_location_id(i) IS NOT NULL)
2521 AND (p_chg.shipment_changes.c_purchase_basis(i) = 'TEMP LABOR') THEN
2522 add_error ( p_api_errors => g_api_errors,
2523 x_return_status => x_return_status,
2524 p_message_name => 'PO_SVC_NO_SPLIT_SHIPMENT',
2525 p_table_name => 'PO_LINE_LOCATIONS_ALL',
2526 p_column_name => null,
2527 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
2528 p_entity_id => i );
2529 END IF; -- parent line location ID is not null
2530
2531 END IF; --Complex work pay items are supported on Fixed Price Temp Labor lines <Complex work project for R12
2532
2533 END LOOP; -- shipment changes
2534
2535 -- Distribution changes
2536 FOR i IN 1..p_chg.distribution_changes.get_count LOOP
2537
2538 IF p_chg.distribution_changes.c_value_basis(i)
2539 IN ('RATE', 'FIXED PRICE') THEN
2540
2541 ------------------------------------------------------------------------
2542 -- Services Check: Prevent quantity changes on distributions of lines
2543 -- with value basis of Rate or Fixed Price.
2544 ------------------------------------------------------------------------
2545 l_progress := '120';
2546 IF (g_is_complex_work_po=FALSE) THEN --<Complex work project for R12
2547 IF (p_chg.distribution_changes.quantity_ordered(i) IS NOT NULL) THEN
2548 add_error ( p_api_errors => g_api_errors,
2549 x_return_status => x_return_status,
2550 p_message_name => 'PO_SVC_NO_QTY',
2551 p_table_name => 'PO_DISTRIBUTIONS_ALL',
2552 p_column_name => 'QUANTITY',
2553 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
2554 p_entity_id => i );
2555 END IF;
2556 END IF;
2557
2558 ELSE -- Value basis is not Rate or Fixed Price
2559
2560 ------------------------------------------------------------------------
2561 -- Services Check: Prevent amount changes on distributions of lines
2562 -- whose value basis is not Rate or Fixed Price.
2563 ------------------------------------------------------------------------
2564 l_progress := '130';
2565 IF (p_chg.distribution_changes.amount_ordered(i) IS NOT NULL) THEN
2566 add_error ( p_api_errors => g_api_errors,
2567 x_return_status => x_return_status,
2568 p_message_name => 'PO_SVC_NO_AMT',
2569 p_table_name => 'PO_DISTRIBUTIONS_ALL',
2570 p_column_name => 'AMOUNT',
2571 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
2572 p_entity_id => i );
2573 END IF;
2574 END IF; -- value basis
2575
2576 END LOOP; -- distribution changes
2577
2578 EXCEPTION
2579 WHEN FND_API.g_exc_unexpected_error THEN
2580 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2581 p_proc_name => l_proc_name,
2582 p_progress => l_progress,
2583 p_add_to_msg_list => FALSE );
2584 RAISE FND_API.g_exc_unexpected_error;
2585 WHEN OTHERS THEN
2586 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2587 p_proc_name => l_proc_name,
2588 p_progress => l_progress );
2589 RAISE FND_API.g_exc_unexpected_error;
2590 END check_type_specific_fields;
2591
2592 -------------------------------------------------------------------------------
2593 --Start of Comments
2594 --Name: check_new_qty_price_amt
2595 --Function:
2596 -- Performs simple checks on the new quantity, price, and amount.
2597 --Pre-reqs:
2598 -- None.
2599 --Modifies:
2600 -- Writes any errors to g_api_errors.
2601 --Locks:
2602 -- None.
2603 --End of Comments
2604 -------------------------------------------------------------------------------
2605 PROCEDURE check_new_qty_price_amt (
2606 p_chg IN PO_CHANGES_REC_TYPE,
2607 p_entity_type IN VARCHAR2,
2608 i IN NUMBER,
2609 x_return_status OUT NOCOPY VARCHAR2
2610 ) IS
2611 l_table_name VARCHAR2(30);
2612 l_qty_column_name VARCHAR2(30);
2613 l_price_column_name VARCHAR2(30);
2614 l_amt_column_name VARCHAR2(30);
2615 l_new_quantity NUMBER;
2616 l_new_price NUMBER;
2617 l_new_amount NUMBER;
2618 l_new_secondary_quantity NUMBER; -- sschinch 09.08.04 INVCONV
2619 l_sec_qty_column_name VARCHAR2(30); -- sschinch 09.08.04 INVCONV
2620 BEGIN
2621 x_return_status := FND_API.G_RET_STS_SUCCESS;
2622
2623 -- Retrieve the new quantity, price, and amount, based on the entity type.
2624 IF (p_entity_type = G_ENTITY_TYPE_LINES) THEN
2625 l_new_quantity := p_chg.line_changes.quantity(i);
2626 l_new_price := p_chg.line_changes.unit_price(i);
2627 l_new_amount := p_chg.line_changes.amount(i);
2628
2629 l_table_name := 'PO_LINES_ALL';
2630 l_qty_column_name := 'QUANTITY';
2631 l_price_column_name := 'UNIT_PRICE';
2632 l_amt_column_name := 'AMOUNT';
2633 ELSIF (p_entity_type = G_ENTITY_TYPE_SHIPMENTS) THEN
2634 l_new_quantity := p_chg.shipment_changes.quantity(i);
2635 l_new_price := p_chg.shipment_changes.price_override(i);
2636 l_new_amount := p_chg.shipment_changes.amount(i);
2637
2638 /*BEGIN INVCONV sschinch 09/07/04 */
2639 l_new_secondary_quantity := p_chg.shipment_changes.secondary_quantity(i);
2640 l_sec_qty_column_name := 'SECONDARY_QUANTITY';
2641 /*END INVCONV sschinch 09/07/04 */
2642
2643 l_table_name := 'PO_LINE_LOCATIONS_ALL';
2644 l_qty_column_name := 'QUANTITY';
2645 l_price_column_name := 'PRICE_OVERRIDE';
2646 l_amt_column_name := 'AMOUNT';
2647 ELSE -- PO_DISTRIBUTIONS_REC_TYPE
2648 l_new_quantity := p_chg.distribution_changes.quantity_ordered(i);
2649 l_new_price := NULL;
2650 l_new_amount := p_chg.distribution_changes.amount_ordered(i);
2651
2652 l_table_name := 'PO_DISTRIBUTIONS_ALL';
2653 l_qty_column_name := 'QUANTITY_ORDERED';
2654 l_amt_column_name := 'AMOUNT_ORDERED';
2655 END IF; -- p_entity_type
2656
2657
2658
2659 ----------------------------------------------------------------------------
2660 -- Check: Quantity must be > 0.
2661 ----------------------------------------------------------------------------
2662 IF (l_new_quantity IS NOT NULL) AND (l_new_quantity <= 0) THEN
2663 add_error ( p_api_errors => g_api_errors,
2664 x_return_status => x_return_status,
2665 p_message_name => 'PO_ALL_ENTER_VALUE_GT_ZERO',
2666 p_table_name => l_table_name,
2667 p_column_name => l_qty_column_name,
2668 p_entity_type => p_entity_type,
2669 p_entity_id => i );
2670 END IF; -- p_new_quantity
2671
2672 ----------------------------------------------------------------------------
2673 -- Check: Price must be >= 0.
2674 ----------------------------------------------------------------------------
2675 IF (l_new_price IS NOT NULL) AND (l_new_price < 0) THEN
2676 add_error ( p_api_errors => g_api_errors,
2677 x_return_status => x_return_status,
2678 p_message_name => 'PO_ALL_ENTER_VALUE_GE_ZERO',
2679 p_table_name => l_table_name,
2680 p_column_name => l_price_column_name,
2681 p_entity_type => p_entity_type,
2682 p_entity_id => i );
2683 END IF; -- p_new_price
2684
2685 ----------------------------------------------------------------------------
2686 -- Check: Amount must be > 0.
2687 ----------------------------------------------------------------------------
2688 IF (l_new_amount IS NOT NULL) AND (l_new_amount <= 0) THEN
2689 add_error ( p_api_errors => g_api_errors,
2690 x_return_status => x_return_status,
2691 p_message_name => 'PO_ALL_ENTER_VALUE_GT_ZERO',
2692 p_table_name => l_table_name,
2693 p_column_name => l_amt_column_name,
2694 p_entity_type => p_entity_type,
2695 p_entity_id => i );
2696 END IF; -- p_new_amount
2697
2698 ----------------------------------------------------------------------------
2699 -- INVCONV sschinch 09/07/04
2700 ----------------------------------------------------------------------------
2701
2702 IF (l_new_secondary_quantity IS NOT NULL) AND (l_new_secondary_quantity <= 0) THEN
2703 add_error ( p_api_errors => g_api_errors,
2704 x_return_status => x_return_status,
2705 p_message_name => 'PO_ALL_ENTER_VALUE_GT_ZERO',
2706 p_table_name => l_table_name,
2707 p_column_name => l_sec_qty_column_name,
2708 p_entity_type => p_entity_type,
2709 p_entity_id => i );
2710 END IF;
2711 /* END INVCONV */
2712
2713 EXCEPTION
2714 WHEN OTHERS THEN
2715 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2716 p_proc_name => 'CHECK_NEW_QTY_PRICE_AMT' );
2717 RAISE FND_API.g_exc_unexpected_error;
2718 END check_new_qty_price_amt;
2719
2720 -------------------------------------------------------------------------------
2721 --Start of Comments
2722 --Name: is_split_shipment_num_unique
2723 --Function:
2724 -- Returns TRUE if there are no other split shipments for this line with the
2725 -- same split shipment number as the i-th shipment change, FALSE otherwise.
2726 --Pre-reqs:
2727 -- The i-th shipment change must be a split shipment.
2728 --Modifies:
2729 -- None.
2730 --Locks:
2731 -- None.
2732 --End of Comments
2733 -------------------------------------------------------------------------------
2734 FUNCTION is_split_shipment_num_unique (
2735 p_chg IN PO_CHANGES_REC_TYPE,
2736 i IN NUMBER
2737 ) RETURN BOOLEAN IS
2738 l_po_line_id PO_LINES.po_line_id%TYPE;
2739 l_split_shipment_num PO_LINE_LOCATIONS.shipment_num%TYPE;
2740 l_ship_chg_i NUMBER;
2741 BEGIN
2742 -- Get the PO_LINE_ID and split shipment num for the i-th shipment change.
2743 l_po_line_id := p_chg.shipment_changes.c_po_line_id(i);
2744 l_split_shipment_num := p_chg.shipment_changes.split_shipment_num(i);
2745
2746 -- Loop through the split shipment changes.
2747 FOR l_split_ship_tbl_i IN 1..g_split_ship_changes_tbl.COUNT LOOP
2748 l_ship_chg_i := g_split_ship_changes_tbl(l_split_ship_tbl_i);
2749 IF (l_ship_chg_i <> i) -- different split shipment change
2750 AND (p_chg.shipment_changes.c_po_line_id(l_ship_chg_i) = l_po_line_id)
2751 AND (p_chg.shipment_changes.split_shipment_num(l_ship_chg_i)
2752 = l_split_shipment_num) THEN
2753 -- Another split shipment for this line with the same shipment number
2754 RETURN FALSE;
2755 END IF;
2756 END LOOP; -- split shipment changes
2757
2758 RETURN TRUE;
2759
2760 EXCEPTION
2761 WHEN OTHERS THEN
2762 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2763 p_proc_name => 'IS_SPLIT_SHIPMENT_NUM_UNIQUE' );
2764 RAISE FND_API.g_exc_unexpected_error;
2765 END is_split_shipment_num_unique;
2766
2767 -------------------------------------------------------------------------------
2768 --Start of Comments
2769 --Name: line_has_qty_amt_change
2770 --Function:
2771 -- Returns true if the i-th line change has quantity or amount changes,
2772 -- false otherwise.
2773 --Pre-reqs:
2774 -- None.
2775 --Modifies:
2776 -- None.
2777 --Locks:
2778 -- None.
2779 --End of Comments
2780 -------------------------------------------------------------------------------
2781 FUNCTION line_has_qty_amt_change (
2782 p_chg IN PO_CHANGES_REC_TYPE,
2783 i IN NUMBER
2784 ) RETURN BOOLEAN IS
2785 BEGIN
2786 RETURN (p_chg.line_changes.quantity(i) IS NOT NULL)
2787 OR (p_chg.line_changes.amount(i) IS NOT NULL);
2788 EXCEPTION
2789 WHEN OTHERS THEN
2790 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2791 p_proc_name => 'LINE_HAS_QTY_AMT_CHANGE' );
2792 RAISE FND_API.g_exc_unexpected_error;
2793 END line_has_qty_amt_change;
2794
2795 -------------------------------------------------------------------------------
2796 --Start of Comments
2797 --Name: ship_has_qty_amt_change
2798 --Function:
2799 -- Returns true if the i-th shipment change has quantity or amount changes,
2800 -- false otherwise.
2801 --Pre-reqs:
2802 -- None.
2803 --Modifies:
2804 -- None.
2805 --Locks:
2806 -- None.
2807 --End of Comments
2808 -------------------------------------------------------------------------------
2809 FUNCTION ship_has_qty_amt_change (
2810 p_chg IN PO_CHANGES_REC_TYPE,
2811 i IN NUMBER
2812 ) RETURN BOOLEAN IS
2813 BEGIN
2814 RETURN (p_chg.shipment_changes.quantity(i) IS NOT NULL)
2815 OR (p_chg.shipment_changes.amount(i) IS NOT NULL)
2816 OR (p_chg.shipment_changes.price_override(i) IS NOT NULL); --<Complex work project for R12
2817 EXCEPTION
2818 WHEN OTHERS THEN
2819 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2820 p_proc_name => 'SHIP_HAS_QTY_AMT_CHANGE' );
2821 RAISE FND_API.g_exc_unexpected_error;
2822 END ship_has_qty_amt_change;
2823
2824 -------------------------------------------------------------------------------
2825 --Start of Comments
2826 --Name: dist_has_qty_amt_change
2827 --Function:
2828 -- Returns true if the i-th distribution change has quantity or amount
2829 -- changes, false otherwise.
2830 --Pre-reqs:
2831 -- None.
2832 --Modifies:
2833 -- None.
2834 --Locks:
2835 -- None.
2836 --End of Comments
2837 -------------------------------------------------------------------------------
2838 FUNCTION dist_has_qty_amt_change (
2839 p_chg IN PO_CHANGES_REC_TYPE,
2840 i IN NUMBER
2841 ) RETURN BOOLEAN IS
2842 BEGIN
2843 RETURN (p_chg.distribution_changes.quantity_ordered(i) IS NOT NULL)
2844 OR (p_chg.distribution_changes.amount_ordered(i) IS NOT NULL);
2845 EXCEPTION
2846 WHEN OTHERS THEN
2847 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2848 p_proc_name => 'DIST_HAS_QTY_AMT_CHANGE' );
2849 RAISE FND_API.g_exc_unexpected_error;
2850 END dist_has_qty_amt_change;
2851
2852 -------------------------------------------------------------------------------
2853 --Start of Comments
2854 --Name: line_has_ship_qty_amt_change
2855 --Function:
2856 -- Returns true if the i-th line change has any shipments with
2857 -- quantity or amount changes, false otherwise.
2858 --Pre-reqs:
2859 -- None.
2860 --Modifies:
2861 -- None.
2862 --Locks:
2863 -- None.
2864 --End of Comments
2865 -------------------------------------------------------------------------------
2866 FUNCTION line_has_ship_qty_amt_change (
2867 p_chg IN PO_CHANGES_REC_TYPE,
2868 i IN NUMBER
2869 ) RETURN BOOLEAN IS
2870 l_po_line_id NUMBER;
2871 BEGIN
2872 l_po_line_id := p_chg.line_changes.po_line_id(i);
2873
2874 -- Loop through the shipment changes.
2875 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
2876
2877 -- Find a shipment for the given line with quantity/amount changes.
2878 IF (p_chg.shipment_changes.c_po_line_id(i) = l_po_line_id)
2879 AND (ship_has_qty_amt_change(p_chg, i)) THEN
2880 RETURN TRUE;
2881 END IF;
2882
2883 END LOOP; -- shipment changes
2884
2885 RETURN FALSE;
2886 EXCEPTION
2887 WHEN OTHERS THEN
2888 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2889 p_proc_name => 'LINE_HAS_SHIP_QTY_AMT_CHANGE' );
2890 RAISE FND_API.g_exc_unexpected_error;
2891 END line_has_ship_qty_amt_change;
2892
2893 -------------------------------------------------------------------------------
2894 --Start of Comments
2895 --Name: ship_has_dist_qty_amt_change
2896 --Function:
2897 -- Returns true if the i-th shipment change has any distributions with
2898 -- quantity or amount changes, false otherwise.
2899 --Pre-reqs:
2900 -- None.
2901 --Modifies:
2902 -- None.
2903 --Locks:
2904 -- None.
2905 --End of Comments
2906 -------------------------------------------------------------------------------
2907 FUNCTION ship_has_dist_qty_amt_change (
2908 p_chg IN PO_CHANGES_REC_TYPE,
2909 i IN NUMBER
2910 ) RETURN BOOLEAN IS
2911 l_line_location_id PO_LINE_LOCATIONS.line_location_id%TYPE;
2912 l_parent_line_loc_id PO_LINE_LOCATIONS.line_location_id%TYPE;
2913 l_split_shipment_num PO_LINE_LOCATIONS.shipment_num%TYPE;
2914 l_dist_chg_i NUMBER;
2915 BEGIN
2916 l_line_location_id := p_chg.shipment_changes.po_line_location_id(i);
2917
2918 IF (l_line_location_id IS NOT NULL) THEN -- existing shipment
2919
2920 -- Loop through the distribution changes.
2921 FOR i IN 1..p_chg.distribution_changes.get_count LOOP
2922
2923 -- Find a distribution for the given shipment with qty/amount changes.
2924 IF (p_chg.distribution_changes.c_line_location_id(i)
2925 = l_line_location_id)
2926 AND (dist_has_qty_amt_change(p_chg,i)) THEN
2927 RETURN TRUE;
2928 END IF;
2929
2930 END LOOP; -- distribution changes
2931
2932 ELSE -- split shipment
2933 l_parent_line_loc_id := p_chg.shipment_changes.parent_line_location_id(i);
2934 l_split_shipment_num := p_chg.shipment_changes.split_shipment_num(i);
2935
2936 -- Loop through the split distribution changes.
2937 FOR l_split_dist_tbl_i IN 1..g_split_dist_changes_tbl.COUNT LOOP
2938 l_dist_chg_i := g_split_dist_changes_tbl(l_split_dist_tbl_i);
2939
2940 -- Find a split distribution for the given split shipment with
2941 -- quantity/amount changes.
2942 IF (p_chg.distribution_changes.c_parent_line_location_id(l_dist_chg_i)
2943 = l_parent_line_loc_id)
2944 AND (p_chg.distribution_changes.split_shipment_num(l_dist_chg_i)
2945 = l_split_shipment_num)
2946 AND (dist_has_qty_amt_change(p_chg,l_dist_chg_i)) THEN
2947 RETURN TRUE;
2948 END IF;
2949
2950 END LOOP; -- split distribution changes
2951
2952 END IF; -- l_line_location_id
2953
2954 RETURN FALSE;
2955 EXCEPTION
2956 WHEN OTHERS THEN
2957 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
2958 p_proc_name => 'SHIP_HAS_DIST_QTY_AMT_CHANGE' );
2959 RAISE FND_API.g_exc_unexpected_error;
2960 END ship_has_dist_qty_amt_change;
2961
2962 -------------------------------------------------------------------------------
2963 --Start of Comments
2964 --Name: derive_changes
2965 --Function:
2966 -- Derives additional changes based on the requested changes in p_chg.
2967 --Pre-reqs:
2968 -- None.
2969 --Modifies:
2970 -- Updates p_chg with any derived changes.
2971 --Locks:
2972 -- None.
2973 --End of Comments
2974 -------------------------------------------------------------------------------
2975 PROCEDURE derive_changes (
2976 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
2977 x_return_status OUT NOCOPY VARCHAR2
2978
2979
2980 ) IS
2981 l_proc_name CONSTANT VARCHAR2(30) := 'DERIVE_CHANGES';
2982 l_progress VARCHAR2(3) := '000';
2983
2984 -- SQL What: Retrieves all the lines of the given PO that refer to
2985 -- a global agrement or quotation.
2986 -- SQL Why: To retrieve the lines on a standard/planned PO that may
2987 -- need to be re-priced from the price breaks.
2988 CURSOR po_line_ref_csr (p_po_header_id PO_HEADERS.po_header_id%TYPE) IS
2989 SELECT po_line_id, manual_price_change_flag
2990 FROM po_lines POL
2991 WHERE POL.po_header_id = p_po_header_id
2992 AND (POL.from_header_id IS NOT NULL OR
2993 -- <FPJ Advanced Price>
2994 POL.contract_id IS NOT NULL);
2995
2996 -- SQL What: Retrieves all the standard/planned shipments of the
2997 -- given PO line that are not cancelled or finally closed.
2998 -- SQL Why: To roll down a line price change on a standard/planned PO
2999 -- to the shipments of that line.
3000 CURSOR po_shipment_csr (p_po_line_id PO_LINES.po_line_id%TYPE) IS
3001 SELECT line_location_id
3002 FROM po_line_locations
3003 WHERE po_line_id = p_po_line_id
3004 AND (NVL(cancel_flag,'N') <> 'Y')
3005 AND (NVL(closed_code,'OPEN') <> 'FINALLY CLOSED')
3006 AND shipment_type IN ('PLANNED','STANDARD');
3007
3008 l_po_line_id PO_LINES.po_line_id%TYPE;
3009 l_line_location_id PO_LINE_LOCATIONS.line_location_id%TYPE;
3010 l_new_price PO_LINE_LOCATIONS.price_override%TYPE;
3011 l_new_qty PO_LINE_LOCATIONS.quantity%TYPE;
3012 l_new_need_by_date PO_LINE_LOCATIONS.need_by_date%TYPE;
3013 l_new_ship_to_loc_id PO_LINE_LOCATIONS.ship_to_location_id%TYPE;
3014 l_price_break_id PO_LINES.from_line_location_id%TYPE;
3015 l_cur_uom2 PO_LINES.secondary_unit_of_measure%TYPE;
3016 l_derived_qty2 PO_LINES.secondary_quantity%TYPE;
3017 -- <FPJ Advanced Price>
3018 l_base_unit_price PO_LINES.base_unit_price%TYPE;
3019
3020 l_ship_chg_i NUMBER;
3021 l_line_chg_i NUMBER;
3022
3023 l_price_updateable VARCHAR2(1); -- Bug 3337426
3024 l_retro_price_change VARCHAR2(1); -- Bug 3337426
3025 -- <Manual Price Override FPJ START>
3026 l_manual_price_change PO_LINES.manual_price_change_flag%TYPE;
3027 l_current_price PO_LINE_LOCATIONS.price_override%TYPE;
3028 -- <Manual Price Override FPJ END>
3029
3030
3031 l_return_status VARCHAR2(1);
3032 /* INVCONV sschinch 09/07/04 */
3033 l_dual_um_ind MTL_SYSTEM_ITEMS.TRACKING_QUANTITY_IND%TYPE;
3034 l_secondary_default_ind MTL_SYSTEM_ITEMS.SECONDARY_DEFAULT_IND%TYPE ; --INVCONV sschinch
3035 l_secondary_qty PO_LINE_LOCATIONS.quantity%TYPE;
3036 l_fsp_org_id NUMBER;
3037 x_count NUMBER;
3038 x_data VARCHAR2(100);
3039 l_derived_sec_qty PO_LINE_LOCATIONS.quantity%TYPE;
3040 l_document_uom PO_LINES.secondary_unit_of_measure%TYPE;
3041 l_item_id MTL_SYSTEM_ITEMS_B.inventory_item_id%TYPE;
3042 l_document_sec_uom PO_LINES.secondary_unit_of_measure%TYPE;
3043 l_new_secondary_qty PO_LINE_LOCATIONS.quantity%TYPE;
3044
3045 l_new_amt NUMBER;
3046 l_new_promised_date DATE;
3047 l_delete_record VARCHAR2(1);
3048 l_new_preferred_grade mtl_grades.grade_code%TYPE;
3049 l_new_preferred_qty PO_LINE_LOCATIONS.quantity%TYPE;
3050 l_shipment_changes po_shipments_rec_type;
3051
3052 l_new_sec_uom PO_LINES.secondary_unit_of_measure%TYPE;
3053 l_count NUMBER := 0;
3054 /* END INVCONV */
3055
3056 BEGIN
3057 IF (g_fnd_debug = 'Y') THEN
3058 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
3059 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
3060 module => g_module_prefix || l_proc_name,
3061 message => 'Entering ' || l_proc_name );
3062 END IF;
3063 END IF;
3064
3065 l_progress := '010';
3066 x_return_status := FND_API.G_RET_STS_SUCCESS;
3067
3068 -- Derivation #1: Derive quantity/amount rollups and rolldowns (prorations).
3069 IF (g_document_type <> 'PA') THEN
3070 derive_qty_amt_rollups ( p_chg );
3071 derive_qty_amt_rolldowns ( p_chg );
3072 END IF;
3073
3074 l_progress := '020';
3075
3076 -- Derivation #2: For a blanket release, if no new price is specified, and
3077 -- there are quantity, need-by date, or ship-to location changes,
3078 -- get a new price from the price break.
3079
3080 IF (g_document_type = 'RELEASE') AND (g_document_subtype = 'BLANKET') THEN
3081 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
3082
3083 l_new_price := p_chg.shipment_changes.price_override(i);
3084 l_new_qty := p_chg.shipment_changes.quantity(i);
3085 l_new_need_by_date := p_chg.shipment_changes.need_by_date(i);
3086 l_new_ship_to_loc_id := p_chg.shipment_changes.ship_to_location_id(i);
3087
3088 -- <Manual Price Override FPJ START>
3089 l_current_price := p_chg.shipment_changes.c_price_override(i);
3090 l_manual_price_change := p_chg.shipment_changes.t_manual_price_change_flag(i);
3091
3092 IF (l_new_price IS NOT NULL) THEN -- New price is specified.
3093
3094 -- If the new price is different from the current price, record a
3095 -- Manual Price Change.
3096 IF (l_new_price <> l_current_price) THEN
3097 p_chg.shipment_changes.t_manual_price_change_flag(i) := 'Y';
3098 END IF;
3099
3100 -- No new price is specified:
3101 ELSIF (NVL(l_manual_price_change,'N') = 'N')
3102 -- <Manual Price Override FPJ END>
3103 AND ((l_new_qty IS NOT NULL) OR
3104 (l_new_need_by_date IS NOT NULL) OR
3105 (l_new_ship_to_loc_id IS NOT NULL)) THEN
3106 -- Re-price, since the price has not been manually overriden, and
3107 -- there is a quantity, need-by date, or ship-to location change.
3108
3109 l_line_location_id :=
3110 NVL ( p_chg.shipment_changes.po_line_location_id(i),
3111 -- Price split shipments using the information from the
3112 -- parent shipment:
3113 P_chg.shipment_changes.parent_line_location_id(i) );
3114
3115 -- Bug 3337426 START
3116 -- For non-split shipments, check whether price updates are allowed.
3117 If (p_chg.shipment_changes.po_line_location_id(i) IS NOT NULL) THEN
3118
3119 PO_DOCUMENT_CHECKS_GRP.check_rel_price_updateable (
3120 p_api_version => 1.0,
3121 x_return_status => l_return_status,
3122 p_line_location_id => l_line_location_id,
3123 p_from_price_break => G_PARAMETER_YES,
3124 p_add_reasons_to_msg_list => G_PARAMETER_NO,
3125 x_price_updateable => l_price_updateable,
3126 x_retroactive_price_change => l_retro_price_change
3127 );
3128
3129 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
3130 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
3131 END IF;
3132
3133 ELSE -- Split shipment - always allow price updates.
3134 l_price_updateable := G_PARAMETER_YES;
3135 END IF;
3136
3137 -- If price updates are allowed, call the Pricing API to get a
3138 -- new price from the price break.
3139 IF (l_price_updateable = G_PARAMETER_YES) THEN
3140 -- Bug 3337426 END
3141
3142 -- Call the Pricing API to get a new price from the price break.
3143 get_release_break_price (
3144 p_line_location_id => l_line_location_id,
3145 p_quantity => l_new_qty,
3146 p_ship_to_location_id => l_new_ship_to_loc_id,
3147 p_need_by_date => l_new_need_by_date,
3148 x_price => l_new_price
3149 );
3150 p_chg.shipment_changes.price_override(i) := l_new_price;
3151
3152 -- Remember that this price was obtained from a price break.
3153 p_chg.shipment_changes.t_from_price_break(i) := G_PARAMETER_YES;
3154
3155 IF (g_fnd_debug = 'Y') THEN
3156 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3157 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3158 module => g_module_prefix||l_proc_name,
3159 message => 'Shipment change on '
3160 ||l_line_location_id
3161 ||': New price from price break: '||l_new_price
3162 ||' (based on new quantity '||l_new_qty
3163 ||' new ship-to location '||l_new_ship_to_loc_id
3164 ||' new need-by date '||l_new_need_by_date||')');
3165 END IF;
3166 END IF;
3167
3168 -- Bug 3337426 START
3169 ELSE -- l_price_updateable = G_PARAMETER_NO
3170 IF (g_fnd_debug = 'Y') THEN
3171 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3172 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3173 module => g_module_prefix||l_proc_name,
3174 message => 'Shipment change on '
3175 ||l_line_location_id
3176 ||': Skip the call to the Pricing API because'
3177 ||' price is not updateable on this shipment.' );
3178 END IF;
3179 END IF;
3180 END IF; -- l_price_updateable
3181 -- Bug 3337426 END
3182
3183 END IF; -- new price
3184
3185 END LOOP; -- shipment changes
3186 END IF; -- document type is release
3187
3188 l_progress := '030';
3189
3190 -- Derivation #3: For a Standard PO sourced to a quotation, GA, or contract,
3191 -- if no new line price is specified, and there are quantity changes
3192 -- on a line, or need-by date or ship-to location changes on the first
3193 -- shipment of a line, get a new price from the price break.
3194
3195 IF (g_document_type = 'PO') AND (g_document_subtype = 'STANDARD') THEN
3196
3197 -- Loop through the lines that reference a quotation, GA, or contract.
3198 OPEN po_line_ref_csr ( g_po_header_id );
3199 LOOP
3200 FETCH po_line_ref_csr INTO l_po_line_id, l_manual_price_change;
3201 EXIT WHEN po_line_ref_csr%NOTFOUND;
3202
3203 l_line_chg_i := get_line_change(l_po_line_id);
3204 IF (l_line_chg_i IS NULL) THEN
3205 l_new_qty := NULL;
3206 l_new_price := NULL;
3207 ELSE
3208 l_new_qty := p_chg.line_changes.quantity(l_line_chg_i);
3209 l_new_price := p_chg.line_changes.unit_price(l_line_chg_i);
3210 END IF;
3211
3212 -- <Manual Price Override FPJ START>
3213 IF (l_new_price IS NOT NULL) THEN -- New price is specified.
3214
3215 -- If the new price is different from the current price, record a
3216 -- Manual Price Change.
3217 IF (l_new_price <> p_chg.line_changes.c_unit_price(l_line_chg_i)) THEN
3218 p_chg.line_changes.t_manual_price_change_flag(l_line_chg_i) := 'Y';
3219 END IF;
3220
3221 -- No new price is specified.
3222 ELSIF (NVL(l_manual_price_change,'N') = 'N') THEN
3223 -- Consider repricing, since the price has not been manually overriden.
3224 -- <Manual Price Override FPJ END>
3225
3226 -- Find the change on the first shipment of the line.
3227 l_line_location_id := get_min_shipment_id(l_po_line_id);
3228 l_ship_chg_i := get_ship_change(l_line_location_id);
3229
3230 -- Get the need-by date and ship-to location changes on the shipment.
3231 IF (l_ship_chg_i IS NULL) THEN
3232 l_new_need_by_date := NULL;
3233 l_new_ship_to_loc_id := NULL;
3234 ELSE
3235 l_new_need_by_date :=
3236 p_chg.shipment_changes.need_by_date(l_ship_chg_i);
3237 l_new_ship_to_loc_id :=
3238 p_chg.shipment_changes.ship_to_location_id(l_ship_chg_i);
3239 END IF;
3240
3241 IF (l_line_location_id IS NOT NULL)
3242 AND ((l_new_qty IS NOT NULL)
3243 OR (l_new_need_by_date IS NOT NULL)
3244 OR (l_new_ship_to_loc_id IS NOT NULL)) THEN
3245 -- Re-price, since there is a line quantity change, and/or
3246 -- need-by date or ship-to location changes on the first shipment.
3247
3248 -- Bug 3337426 START
3249 -- Check whether price updates are allowed on the PO line.
3250 PO_DOCUMENT_CHECKS_GRP.check_std_po_price_updateable (
3251 p_api_version => 1.0,
3252 x_return_status => l_return_status,
3253 p_po_line_id => l_po_line_id,
3254 p_from_price_break => G_PARAMETER_YES,
3255 p_add_reasons_to_msg_list => G_PARAMETER_NO,
3256 x_price_updateable => l_price_updateable,
3257 x_retroactive_price_change => l_retro_price_change
3258 );
3259
3260 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
3261 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
3262 END IF;
3263
3264 -- If price updates are allowed, call the Pricing API to get a
3265 -- new price from the price break.
3266 IF (l_price_updateable = G_PARAMETER_YES) THEN
3267 -- Bug 3337426 END
3268
3269 -- begin bug 3331197:
3270 -- if there is a need-by date or ship-to location change but no
3271 -- price change,
3272 -- then l_line_chg_i is null, and we need to initialize it
3273 -- because we have to change the price on the line
3274 -- after calling the pricing API with the changed shipment info
3275 IF(l_line_chg_i IS NULL) THEN
3276 l_line_chg_i := find_line_change(p_chg,l_po_line_id);
3277 END IF;
3278 -- end bug 3331197
3279
3280 get_po_break_price (
3281 p_po_line_id => l_po_line_id,
3282 p_quantity => l_new_qty,
3283 p_line_location_id => l_line_location_id,
3284 p_ship_to_location_id => l_new_ship_to_loc_id,
3285 p_need_by_date => l_new_need_by_date,
3286 x_price_break_id => l_price_break_id,
3287 x_price => l_new_price,
3288 -- <FPJ Advanced Price>
3289 x_base_unit_price => l_base_unit_price
3290 );
3291
3292 p_chg.line_changes.unit_price(l_line_chg_i) := l_new_price;
3293 -- <FPJ Advanced Price>
3294 p_chg.line_changes.t_base_unit_price(l_line_chg_i) := l_base_unit_price;
3295
3296 p_chg.line_changes.t_from_line_location_id(l_line_chg_i)
3297 := nvl ( l_price_break_id, G_NULL_NUM );
3298 -- G_NULL_NUM means that we will set FROM_LINE_LOCATION_ID to NULL.
3299
3300 -- Remember that this price was obtained from a price break.
3301 p_chg.line_changes.t_from_price_break(l_line_chg_i)
3302 := G_PARAMETER_YES;
3303
3304 IF (g_fnd_debug = 'Y') THEN
3305 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3306 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3307 module => g_module_prefix||l_proc_name,
3308 message => 'Line change on ' || l_po_line_id
3309 ||': New price from price break: '||l_new_price
3310 ||' ; based on new quantity '||l_new_qty
3311 ||' new ship-to location '||l_new_ship_to_loc_id
3312 ||' new need-by date '||l_new_need_by_date );
3313 END IF;
3314 END IF;
3315
3316 -- Bug 3337426 START
3317 ELSE -- l_price_updateable = G_PARAMETER_NO
3318 IF (g_fnd_debug = 'Y') THEN
3319 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3320 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3321 module => g_module_prefix||l_proc_name,
3322 message => 'Line change on ' || l_po_line_id
3323 ||': Skip the call to the Pricing API because'
3324 ||' price is not updateable on this line.' );
3325 END IF;
3326 END IF;
3327 END IF; -- l_price_updateable
3328 -- Bug 3337426 END
3329 END IF; -- new quantity, need-by date, or ship-to location
3330
3331 END IF; -- l_new_price
3332
3333 END LOOP; -- PO lines with a GA or quotation reference
3334 CLOSE po_line_ref_csr;
3335 END IF; -- document type is standard PO or planned PO
3336
3337 l_progress := '040';
3338
3339 -- Derivation #4: For a standard or planned PO, roll down any line
3340 -- price changes to all shipments that are not finally closed or cancelled.
3341
3342 IF (g_document_type = 'PO') and (g_is_complex_work_po=FALSE ) THEN
3343 FOR i IN 1..p_chg.line_changes.get_count LOOP
3344 l_po_line_id := p_chg.line_changes.po_line_id(i);
3345 l_new_price := p_chg.line_changes.unit_price(i);
3346
3347 IF (l_new_price IS NOT NULL) THEN
3348
3349 -- Roll down to existing shipments of this line.
3350 OPEN po_shipment_csr ( l_po_line_id );
3351 LOOP
3352 FETCH po_shipment_csr INTO l_line_location_id;
3353 EXIT WHEN po_shipment_csr%NOTFOUND;
3354 l_ship_chg_i := find_ship_change(p_chg, l_line_location_id);
3355 p_chg.shipment_changes.set_price_override(l_ship_chg_i, l_new_price);
3356
3357 IF (g_fnd_debug = 'Y') THEN
3358 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3359 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3360 module => g_module_prefix||l_proc_name,
3361 message => 'Shipment change on '
3362 || l_line_location_id
3363 || ': Price rolldown from line: '||l_new_price);
3364 END IF;
3365 END IF;
3366 END LOOP; -- shipments
3367 CLOSE po_shipment_csr;
3368
3369 -- Also roll down to any split shipments of this line.
3370 FOR l_split_ship_tbl_i IN 1..g_split_ship_changes_tbl.COUNT LOOP
3371 l_ship_chg_i := g_split_ship_changes_tbl(l_split_ship_tbl_i);
3372
3373 IF (p_chg.shipment_changes.c_po_line_id(l_ship_chg_i)
3374 = l_po_line_id) THEN
3375 p_chg.shipment_changes.set_price_override(l_ship_chg_i,
3376 l_new_price);
3377
3378 IF (g_fnd_debug = 'Y') THEN
3379 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3380 FND_LOG.string( log_level => FND_LOG.LEVEL_EVENT,
3381 module => g_module_prefix||l_proc_name,
3382 message => 'Split shipment change on '
3383 ||p_chg.shipment_changes.parent_line_location_id(l_ship_chg_i)
3384 ||','||p_chg.shipment_changes.split_shipment_num(l_ship_chg_i)
3385 ||': Price rolldown from line: '||l_new_price );
3386 END IF;
3387 END IF;
3388 END IF;
3389
3390 END LOOP; -- split shipment changes
3391
3392 END IF; -- new price is not null
3393 END LOOP; -- line changes
3394 END IF; -- document type is standard PO or planned PO
3395
3396
3397 -- BEGIN INVCONV sschinch 09/07/04
3398 /** l_progress := '050';
3399 *
3400 * -- Derivation #5: If OPM and Common Receiving are installed, and there is a
3401 * -- quantity change, call the OPM API to derive/validate the secondary
3402 * -- quantity.
3403 *IF (g_opm_installed AND g_gml_common_rcv_installed) THEN
3404 *
3405 * -- Process the lines with quantity change and a secondary UOM.
3406 * FOR i IN 1..p_chg.line_changes.get_count LOOP
3407 * l_new_qty := p_chg.line_changes.quantity(i);
3408 * l_cur_uom2 := p_chg.line_changes.c_secondary_uom(i);
3409 * IF (l_new_qty IS NOT NULL) AND (l_cur_uom2 IS NOT NULL) THEN
3410 *
3411 * derive_secondary_quantity ( p_chg => p_chg,
3412 * p_entity_type => G_ENTITY_TYPE_LINES,
3413 * p_entity_id => i,
3414 * x_derived_quantity2 => l_derived_qty2,
3415 * x_return_status => l_return_status );
3416 * IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
3417 * -- OPM validation error.
3418 * x_return_status := FND_API.G_RET_STS_ERROR;
3419 * ELSE
3420 * p_chg.line_changes.secondary_quantity(i) := l_derived_qty2;
3421 * END IF;
3422 *
3423 * END IF;
3424 *
3425 * END LOOP; -- line changes
3426 *
3427 *
3428 * -- Process the shipments with quantity change and a secondary UOM.
3429 * FOR i IN 1..p_chg.shipment_changes.get_count LOOP
3430 * l_new_qty := p_chg.shipment_changes.quantity(i);
3431 * l_cur_uom2 := p_chg.shipment_changes.c_secondary_uom(i);
3432 * IF (l_new_qty IS NOT NULL) AND (l_cur_uom2 IS NOT NULL) THEN
3433 *
3434 * derive_secondary_quantity ( p_chg => p_chg,
3435 * p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
3436 * p_entity_id => i,
3437 * x_derived_quantity2 => l_derived_qty2,
3438 * x_return_status => l_return_status );
3439 * IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
3440 * -- OPM validation error.
3441 * x_return_status := FND_API.G_RET_STS_ERROR;
3442 * ELSE
3443 * p_chg.shipment_changes.secondary_quantity(i) := l_derived_qty2;
3444 * END IF;
3445 * END IF;
3446 * END LOOP; -- shipment changes
3447 ***/
3448
3449 SELECT fsp.inventory_organization_id
3450 INTO l_fsp_org_id
3451 FROM financials_system_parameters fsp;
3452
3453 --g_sec_qty_grade_only_chge_doc := 'N' ;
3454
3455 FOR i IN 1..p_chg.line_changes.get_count LOOP
3456 l_new_qty := p_chg.line_changes.quantity(i);
3457 l_cur_uom2 := p_chg.line_changes.c_secondary_uom(i);
3458
3459 /* begin INVCONV 11/11/04 */
3460 l_new_preferred_grade := p_chg.line_changes.preferred_grade(i);
3461 l_new_secondary_qty := p_chg.line_changes.secondary_quantity(i);
3462 l_new_price := p_chg.line_changes.amount(i);
3463
3464
3465 IF (l_new_secondary_qty IS NOT NULL AND
3466 p_chg.shipment_changes.get_count = 0 AND
3467 p_chg.line_changes.c_secondary_quantity IS NOT NULL AND
3468 l_new_qty IS NULL ) THEN
3469
3470 IF p_chg.line_changes.c_item_id(i) IS NOT NULL THEN
3471 SELECT msi.tracking_quantity_ind,secondary_default_ind,secondary_uom_code
3472 INTO l_dual_um_ind,l_secondary_default_ind,l_new_sec_uom
3473 FROM mtl_system_items_b msi
3474 WHERE msi.inventory_item_id = p_chg.line_changes.c_item_id(i)
3475 AND msi.organization_id = l_fsp_org_id;
3476 ELSE
3477 l_dual_um_ind := 'P';
3478 END IF;
3479
3480 IF (l_dual_um_ind = 'PS' AND l_secondary_default_ind <> 'F') THEN
3481 SELECT muom.unit_of_measure
3482 INTO l_new_sec_uom
3483 FROM mtl_units_of_measure muom
3484 WHERE uom_code = l_new_sec_uom;
3485
3486 l_secondary_qty := l_new_secondary_qty;
3487
3488 IF (l_new_sec_uom <> l_cur_uom2 AND
3489 l_new_sec_uom IS NOT NULL AND
3490 l_cur_uom2 IS NOT NULL) THEN
3491
3492 l_secondary_qty := inv_convert.inv_um_convert(
3493 item_id => p_chg.line_changes.c_item_id(i),
3494 lot_number => NULL,
3495 organization_id => l_fsp_org_id,
3496 precision => 6,
3497 from_quantity => l_new_secondary_qty,
3498 from_name => l_cur_uom2,
3499 to_name => l_new_sec_uom,
3500 from_unit => NULL,
3501 to_unit => NULL);
3502 END IF;
3503 IF (l_secondary_qty < 0 ) THEN
3504 x_return_status := FND_API.G_RET_STS_ERROR;
3505 RETURN;
3506 END IF;
3507 IF (l_secondary_qty > 0) THEN
3508 l_return_status := inv_convert.within_deviation(
3509 p_organization_id => l_fsp_org_id,
3510 p_inventory_item_id => p_chg.line_changes.c_item_id(i),
3511 p_lot_number => NULL,
3512 p_precision => 6,
3513 p_quantity => p_chg.line_changes.c_quantity(i),
3514 p_unit_of_measure1 => p_chg.line_changes.c_unit_meas_lookup_code(i),
3515 p_quantity2 => l_secondary_qty,
3516 p_unit_of_measure2 => l_new_sec_uom,
3517 p_uom_code1 => NULL,
3518 p_uom_code2 => NULL
3519 );
3520 IF (l_return_status = 0) THEN
3521
3522 x_data := FND_MSG_PUB.Get( 1,'F');
3523
3524 PO_DOCUMENT_UPDATE_PVT.add_error (
3525 p_api_errors => g_api_errors,
3526 x_return_status => l_return_status,
3527 p_message_name => NULL,
3528 p_message_text => x_data);
3529
3530 IF (g_fnd_debug = 'Y') THEN
3531 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3532 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3533 module => g_module_prefix||l_proc_name,
3534 message => 'Line change on ' || l_po_line_id
3535 ||': '||x_data);
3536 END IF;
3537 END IF;
3538
3539 x_return_status := FND_API.G_RET_STS_ERROR;
3540 RETURN;
3541 END IF;
3542 p_chg.line_changes.secondary_quantity(i) := l_secondary_qty;
3543
3544 IF (l_new_sec_uom <> l_cur_uom2) THEN
3545 p_chg.line_changes.t_new_secondary_uom(i) := l_new_sec_uom;
3546 END IF;
3547 END IF;
3548 END IF;
3549 /* INVCONV sschinch 11/11/04 */
3550
3551 ELSIF (l_new_qty IS NOT NULL) AND (l_cur_uom2 IS NOT NULL) THEN
3552
3553 IF p_chg.line_changes.c_item_id(i) IS NOT NULL THEN
3554 SELECT msi.tracking_quantity_ind,secondary_default_ind
3555 INTO l_dual_um_ind,l_secondary_default_ind
3556 FROM mtl_system_items_b msi
3557 WHERE msi.inventory_item_id = p_chg.line_changes.c_item_id(i)
3558 AND msi.organization_id = l_fsp_org_id;
3559 ELSE
3560 l_dual_um_ind := 'P';
3561 END IF;
3562
3563 -- Check if item and FSP org combination is dual uom control.
3564 IF (l_dual_um_ind = 'P') THEN
3565 p_chg.line_changes.secondary_quantity(i) := NULL;
3566 ELSIF (l_dual_um_ind = 'PS') THEN
3567 IF (p_chg.line_changes.secondary_quantity(i) IS NOT NULL) THEN
3568 l_return_status := inv_convert.within_deviation(
3569 p_organization_id => l_fsp_org_id,
3570 p_inventory_item_id => p_chg.line_changes.c_item_id(i),
3571 p_lot_number => NULL,
3572 p_precision => 6,
3573 p_quantity => l_new_qty,
3574 p_unit_of_measure1 => p_chg.line_changes.c_unit_meas_lookup_code(i),
3575 p_quantity2 => p_chg.line_changes.secondary_quantity(i),
3576 p_unit_of_measure2 => p_chg.line_changes.c_secondary_uom(i),
3577 p_uom_code1 => NULL,
3578 p_uom_code2 => NULL
3579 );
3580 IF (l_return_status = 0) THEN
3581 x_data := FND_MSG_PUB.Get( 1,'F');
3582 PO_DOCUMENT_UPDATE_PVT.add_error (
3583 p_api_errors => g_api_errors,
3584 x_return_status => l_return_status,
3585 p_message_name => NULL,
3586 p_message_text => x_data);
3587
3588 IF (g_fnd_debug = 'Y') THEN
3589 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3590 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3591 module => g_module_prefix||l_proc_name,
3592 message => 'Line change on ' || l_po_line_id
3593 ||': '||x_data);
3594 END IF;
3595 END IF;
3596 x_return_status := FND_API.G_RET_STS_ERROR;
3597 RETURN;
3598 END IF;
3599 ELSE
3600 --Derive secondary quantity based on default conversion
3601 l_secondary_qty := inv_convert.inv_um_convert(
3602 item_id => p_chg.line_changes.c_item_id(i),
3603 lot_number => NULL,
3604 organization_id => l_fsp_org_id,
3605 precision => 6,
3606 from_quantity => l_new_qty,
3607 from_name => p_chg.line_changes.c_unit_meas_lookup_code(i),
3608 to_name => p_chg.line_changes.c_secondary_uom(i),
3609 from_unit => NULL,
3610 to_unit => NULL);
3611
3612 IF (l_secondary_qty > 0) THEN
3613 p_chg.line_changes.secondary_quantity(i) := l_secondary_qty;
3614 END IF;
3615 END IF;
3616 END IF;
3617 END IF;
3618
3619 END LOOP; -- line changes
3620
3621
3622 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
3623 l_document_uom := p_chg.shipment_changes.c_unit_meas_lookup_code(i);
3624 l_item_id := p_chg.shipment_changes.c_item_id(i);
3625 l_new_qty := p_chg.shipment_changes.quantity(i);
3626 l_document_sec_uom := p_chg.shipment_changes.c_secondary_uom(i);
3627 l_new_secondary_qty := p_chg.shipment_changes.secondary_quantity(i);
3628
3629 l_new_amt := p_chg.shipment_changes.amount(i);
3630 l_new_ship_to_loc_id := p_chg.shipment_changes.ship_to_location_id(i);
3631 l_new_price := p_chg.shipment_changes.price_override(i);
3632 l_new_promised_date := p_chg.shipment_changes.promised_date(i);
3633 l_new_need_by_date := p_chg.shipment_changes.need_by_date(i);
3634 l_delete_record := p_chg.shipment_changes.delete_record(i);
3635 l_new_preferred_qty := p_chg.shipment_changes.amount(i);
3636 l_new_preferred_grade := p_chg.shipment_changes.preferred_grade(i);
3637 l_fsp_org_id := p_chg.shipment_changes.c_ship_to_organization_id(i);
3638
3639 IF p_chg.shipment_changes.c_item_id(i) IS NOT NULL THEN
3640 SELECT msi.tracking_quantity_ind,secondary_default_ind
3641 INTO l_dual_um_ind,l_secondary_default_ind
3642 FROM mtl_system_items_b msi
3643 WHERE msi.inventory_item_id = p_chg.shipment_changes.c_item_id(i)
3644 AND msi.organization_id = l_fsp_org_id;
3645 ELSE
3646 l_secondary_default_ind := NULL;
3647 END IF;
3648
3649
3650 IF p_chg.line_changes.get_count = 0 AND p_chg.distribution_changes.get_count = 0 THEN
3651
3652 IF l_new_secondary_qty IS NOT NULL or l_new_preferred_grade IS NOT NULL THEN
3653 IF l_new_qty IS NULL OR
3654 l_new_promised_date IS NULL
3655 OR l_new_price IS NULL
3656 OR l_new_need_by_date IS NULL
3657 OR l_new_ship_to_loc_id IS NULL OR l_new_amt IS NULL
3658 OR (l_delete_record IS NULL OR l_delete_record = G_PARAMETER_NO) THEN
3659 g_sec_qty_grade_only_chge_doc := 'Y' ; /* Bug 5366883 Moved this here from outer If statement */
3660 p_chg.shipment_changes.set_grade_flag(i,'Y');
3661 ELSE
3662 p_chg.shipment_changes.set_grade_flag(i,'N');
3663 g_sec_qty_grade_only_chge_doc := 'N';
3664 END IF;
3665 END IF;
3666 END IF;
3667 /* sschinch INVCONV added this line to clear secondary quantity if a value is passed */
3668
3669 IF (l_secondary_default_ind IS NULL AND p_chg.shipment_changes.secondary_quantity(i) IS NOT NULL) THEN
3670 p_chg.shipment_changes.secondary_quantity(i) := NULL;
3671 PO_DOCUMENT_UPDATE_PVT.add_error(p_api_errors => g_api_errors,
3672 x_return_status => l_return_status,
3673 p_message_name => 'PO_SECONDARY_QTY_NOT_REQUIRED');
3674 x_return_Status := FND_API.G_RET_STS_ERROR;
3675 RETURN;
3676 END IF;
3677 /* End sschinch INVCONV */
3678
3679 IF (l_secondary_default_ind IS NOT NULL) THEN
3680
3681 IF (l_new_qty IS NULL AND l_new_secondary_qty IS NOT NULL AND
3682 l_secondary_default_ind = 'F') THEN
3683 PO_DOCUMENT_UPDATE_PVT.add_error (
3684 p_api_errors => g_api_errors,
3685 x_return_status => l_return_status,
3686 p_message_name => 'PO_DUALFIXED_NO_CONVERSION',
3687 p_token_name1 => 'PQTY',
3688 p_token_value1 => p_chg.shipment_changes.c_quantity(i),
3689 p_token_name2 => 'SQTY',
3690 p_token_value2 => l_new_secondary_qty);
3691 x_return_status := FND_API.G_RET_STS_ERROR;
3692 RETURN;
3693 END IF;
3694 /** If item is dual uom control and quantity is specified and secondary qty is not specified
3695 then derive the secondary quantity **/
3696
3697 /*
3698 PO_UOM_S.uom_convert(l_new_qty, l_document_uom,
3699 l_item_id, l_document_sec_uom, l_derived_sec_qty);
3700 p_chg.shipment_changes.secondary_quantity(i) := l_derived_sec_qty;
3701 */
3702 IF (l_new_qty IS NOT NULL AND l_new_secondary_qty IS NULL) THEN
3703 l_derived_sec_qty := inv_convert.inv_um_convert(
3704 item_id => l_item_id,
3705 lot_number => NULL,
3706 organization_id => l_fsp_org_id,
3707 precision => 6,
3708 from_quantity => l_new_qty,
3709 from_name => l_document_uom,
3710 to_name => l_document_sec_uom,
3711 from_unit => NULL,
3712 to_unit => NULL);
3713 IF (l_derived_sec_qty > 0) THEN
3714 p_chg.shipment_changes.secondary_quantity(i) := l_derived_sec_qty;
3715 END IF;
3716 ELSIF l_new_qty IS NOT NULL AND l_new_secondary_qty IS NOT NULL THEN
3717
3718 -- Call API to validate deviation between new quantity and new secondary qty.
3719 -- Error out in case it is out of deviation
3720
3721 l_return_status := inv_convert.within_deviation(
3722 p_organization_id => l_fsp_org_id,
3723 p_inventory_item_id => l_item_id,
3724 p_precision => 6,
3725 p_quantity => l_new_qty,
3726 p_unit_of_measure1 => l_document_uom,
3727 p_quantity2 => l_new_secondary_qty,
3728 p_unit_of_measure2 => l_document_sec_uom,
3729 p_uom_code1 => NULL,
3730 p_uom_code2 => NULL
3731 );
3732 IF (l_return_status = 0) THEN
3733 x_data := FND_MSG_PUB.Get( 1,'F');
3734
3735 PO_DOCUMENT_UPDATE_PVT.add_error (
3736 p_api_errors => g_api_errors,
3737 x_return_status => l_return_status,
3738 p_message_name => NULL,
3739 p_message_text => x_data);
3740
3741 IF (g_fnd_debug = 'Y') THEN
3742 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3743 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3744 module => g_module_prefix||l_proc_name,
3745 message => 'Line change on ' || l_po_line_id
3746 ||': '||x_data);
3747 END IF;
3748
3749
3750 END IF;
3751 x_return_status := FND_API.G_RET_STS_ERROR;
3752 RETURN;
3753 END IF;
3754 ELSIF l_new_qty IS NULL AND l_new_secondary_qty IS NOT NULL THEN
3755 -- Call API to validate deviation between database quantity and new secondary qty.
3756 -- Error out in case it is out of deviation
3757
3758 l_return_status := inv_convert.within_deviation(
3759 p_organization_id => l_fsp_org_id,
3760 p_inventory_item_id => l_item_id,
3761 p_precision => 6,
3762 p_quantity => p_chg.shipment_changes.c_quantity(i),
3763 p_unit_of_measure1 => l_document_uom,
3764 p_quantity2 => l_new_secondary_qty,
3765 p_unit_of_measure2 => l_document_sec_uom,
3766 p_uom_code1 => NULL,
3767 p_uom_code2 => NULL
3768 );
3769 IF (l_return_status = 0) THEN
3770 x_data := FND_MSG_PUB.Get( 1,'F');
3771
3772 PO_DOCUMENT_UPDATE_PVT.add_error (
3773 p_api_errors => g_api_errors,
3774 x_return_status => l_return_status,
3775 p_message_name => NULL,
3776 p_message_text => x_data);
3777
3778 IF (g_fnd_debug = 'Y') THEN
3779 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3780 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
3781 module => g_module_prefix||l_proc_name,
3782 message => 'Shipment Line changes : '||x_data);
3783 END IF;
3784 END IF; -- g_fnd_debug
3785 x_return_status := FND_API.G_RET_STS_ERROR;
3786 RETURN;
3787 END IF; -- l_return_status
3788 END IF;
3789 END IF; -- l_secondary_default_ind IS NOT NULL
3790 END LOOP ; --shipment changes
3791 /* END INVCONV */
3792 EXCEPTION
3793 WHEN FND_API.g_exc_unexpected_error THEN
3794 IF po_line_ref_csr%ISOPEN THEN
3795 CLOSE po_line_ref_csr;
3796 END IF;
3797
3798 IF po_shipment_csr%ISOPEN THEN
3799 CLOSE po_shipment_csr;
3800 END IF;
3801
3802 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
3803 p_proc_name => l_proc_name,
3804 p_progress => l_progress,
3805 p_add_to_msg_list => FALSE );
3806 RAISE FND_API.g_exc_unexpected_error;
3807 WHEN OTHERS THEN
3808 IF po_line_ref_csr%ISOPEN THEN
3809 CLOSE po_line_ref_csr;
3810 END IF;
3811
3812 IF po_shipment_csr%ISOPEN THEN
3813 CLOSE po_shipment_csr;
3814 END IF;
3815
3816 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
3817 p_proc_name => l_proc_name,
3818 p_progress => l_progress );
3819 RAISE FND_API.g_exc_unexpected_error;
3820 END derive_changes;
3821
3822 -------------------------------------------------------------------------------
3823 --Start of Comments
3824 --Name: derive_secondary_quantity
3825 --Function:
3826 -- Calls an OPM API to derive/validate the secondary quantity based on the
3827 -- primary quantity.
3828 --Pre-reqs:
3829 -- None.
3830 --Modifies:
3831 -- None.
3832 --Locks:
3833 -- None.
3834 --End of Comments
3835 -------------------------------------------------------------------------------
3836 PROCEDURE derive_secondary_quantity (
3837 p_chg IN PO_CHANGES_REC_TYPE,
3838 p_entity_type IN VARCHAR2,
3839 p_entity_id IN NUMBER,
3840 x_derived_quantity2 OUT NOCOPY PO_LINES.secondary_quantity%TYPE,
3841 x_return_status OUT NOCOPY VARCHAR2
3842 ) IS
3843 l_proc_name VARCHAR2(30) := 'derive_secondary_quantity';
3844 l_progress VARCHAR2(3) := '000';
3845
3846 i NUMBER := p_entity_id;
3847 l_new_quantity PO_LINES.quantity%TYPE;
3848 l_new_quantity2 PO_LINES.secondary_quantity%TYPE;
3849 l_cur_quantity2 PO_LINES.secondary_quantity%TYPE;
3850 l_request_uom PO_LINES.unit_meas_lookup_code%TYPE;
3851 l_cur_uom PO_LINES.unit_meas_lookup_code%TYPE;
3852 l_request_uom2 PO_LINES.secondary_unit_of_measure%TYPE;
3853 l_cur_uom2 PO_LINES.secondary_unit_of_measure%TYPE;
3854 l_item_number MTL_SYSTEM_ITEMS.segment1%TYPE;
3855 l_qty2 PO_LINES.secondary_quantity%TYPE;
3856 l_opm_validate_ind VARCHAR2(1);
3857
3858 l_last_msg_list_index NUMBER;
3859 l_return_status VARCHAR2(1);
3860 l_msg_data VARCHAR2(2000);
3861 l_msg_count NUMBER;
3862 BEGIN
3863 IF (g_fnd_debug = 'Y') THEN
3864 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
3865 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
3866 module => g_module_prefix || l_proc_name,
3867 message => 'Entering ' || l_proc_name );
3868 END IF;
3869 END IF;
3870
3871 x_return_status := FND_API.G_RET_STS_SUCCESS;
3872
3873 -- Retrieve some values from the line or shipment.
3874 IF (p_entity_type = G_ENTITY_TYPE_LINES) THEN
3875 l_new_quantity := p_chg.line_changes.quantity(i);
3876 l_new_quantity2 := p_chg.line_changes.secondary_quantity(i);
3877 l_cur_quantity2 := p_chg.line_changes.c_secondary_quantity(i);
3878 l_request_uom := p_chg.line_changes.request_unit_of_measure(i);
3879 l_cur_uom := p_chg.line_changes.c_unit_meas_lookup_code(i);
3880 l_request_uom2 := p_chg.line_changes.request_secondary_uom(i);
3881 l_cur_uom2 := p_chg.line_changes.c_secondary_uom(i);
3882 l_item_number := p_chg.line_changes.c_item_number(i);
3883 ELSE -- G_ENTITY_TYPE_SHIPMENTS
3884 l_new_quantity := p_chg.shipment_changes.quantity(i);
3885 l_new_quantity2 := p_chg.shipment_changes.secondary_quantity(i);
3886 l_cur_quantity2 := p_chg.shipment_changes.c_secondary_quantity(i);
3887 l_request_uom := p_chg.shipment_changes.request_unit_of_measure(i);
3888 l_cur_uom := p_chg.shipment_changes.c_unit_meas_lookup_code(i);
3889 l_request_uom2 := p_chg.shipment_changes.request_secondary_uom(i);
3890 l_cur_uom2 := p_chg.shipment_changes.c_secondary_uom(i);
3891 l_item_number := p_chg.shipment_changes.c_item_number(i);
3892 END IF;
3893
3894 IF ((l_request_uom IS NULL) OR (l_request_uom = l_cur_uom)) AND
3895 ((l_request_uom2 IS NULL) OR (l_request_uom2 = l_cur_uom2)) THEN
3896 -- UOM1 and UOM2 are the same between the request and the document.
3897
3898 IF (g_update_source = G_UPDATE_SOURCE_OM) THEN
3899 -- For OM (Drop Ship Integration), use the requested Qty2 if it is
3900 -- present. Otherwise, call the OPM API to derive a new Qty2.
3901 IF (l_new_quantity2 IS NOT NULL) THEN
3902
3903 IF (g_fnd_debug = 'Y') THEN
3904 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3905 FND_LOG.string (
3906 log_level => FND_LOG.LEVEL_EVENT,
3907 module => g_module_prefix||l_proc_name,
3908 message => 'UOM1 and UOM2 are the same between the request and '||
3909 'the document. We do not need to call the OPM API.' );
3910 END IF;
3911 END IF;
3912
3913 x_derived_quantity2 := l_new_quantity2; -- Use the requested Qty2.
3914 RETURN; -- Do not need to call the OPM API.
3915
3916 ELSE -- There is no requested Qty2.
3917 -- Call the OPM API to derive a new Qty2.
3918 l_opm_validate_ind := 'N';
3919 l_qty2 := null;
3920 END IF;
3921
3922 ELSE -- Not OM Drop Ship
3923 -- Call the OPM API to validate/derive Qty2.
3924 l_opm_validate_ind := 'Y';
3925 l_qty2 := NVL ( l_new_quantity2, l_cur_quantity2 );
3926 END IF;
3927
3928 ELSE -- UOM1 and/or UOM2 differ between the request and the document.
3929 -- Call the OPM API to derive a new Qty2.
3930 l_opm_validate_ind := 'N';
3931 l_qty2 := NULL;
3932 END IF;
3933
3934 l_progress := '010';
3935 l_last_msg_list_index := FND_MSG_PUB.count_msg();
3936
3937 GML_ValidateDerive_GRP.secondary_qty (
3938 p_api_version => 1.0,
3939 p_init_msg_list => FND_API.G_FALSE,
3940 p_validate_ind => l_opm_validate_ind,
3941 p_item_no => l_item_number,
3942 p_unit_of_measure => l_cur_uom,
3943 p_quantity => l_new_quantity,
3944 p_lot_id => NULL,
3945 p_secondary_unit_of_measure => l_cur_uom2,
3946 p_secondary_quantity => l_qty2,
3947 x_return_status => l_return_status,
3948 x_msg_count => l_msg_count,
3949 x_msg_data => l_msg_data
3950 );
3951 IF (g_fnd_debug = 'Y') THEN
3952 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
3953 FND_LOG.string( log_level => FND_LOG.LEVEL_EVENT,
3954 module => g_module_prefix||l_proc_name,
3955 message => 'OPM API return_status: ' || l_return_status
3956 || ', secondary_quantity: ' || l_qty2 );
3957 END IF;
3958 END IF;
3959
3960 l_progress := '020';
3961
3962 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
3963 -- The OPM API returned some validation errors.
3964 add_message_list_errors ( p_api_errors => g_api_errors,
3965 x_return_status => x_return_status,
3966 p_start_index => l_last_msg_list_index + 1,
3967 p_entity_type => p_entity_type,
3968 p_entity_id => p_entity_id );
3969 RETURN;
3970 ELSIF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
3971 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
3972 END IF;
3973
3974 x_derived_quantity2 := l_qty2; -- Return the Quantity2 derived by the API.
3975 EXCEPTION
3976 WHEN FND_API.g_exc_unexpected_error THEN
3977 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
3978 p_proc_name => l_proc_name,
3979 p_progress => l_progress,
3980 p_add_to_msg_list => FALSE );
3981 RAISE FND_API.g_exc_unexpected_error;
3982 WHEN OTHERS THEN
3983 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
3984 p_proc_name => l_proc_name,
3985 p_progress => l_progress );
3986 RAISE FND_API.g_exc_unexpected_error;
3987 END derive_secondary_quantity;
3988
3989 -------------------------------------------------------------------------------
3990 --Start of Comments
3991 --Name: get_release_break_price
3992 --Function:
3993 -- Returns the price from the price break for a release shipment.
3994 --Pre-reqs:
3995 -- None.
3996 --Modifies:
3997 -- None.
3998 --Locks:
3999 -- None.
4000 --End of Comments
4001 -------------------------------------------------------------------------------
4002 PROCEDURE get_release_break_price (
4003 p_line_location_id IN PO_LINE_LOCATIONS.line_location_id%TYPE,
4004 p_quantity IN PO_LINE_LOCATIONS.quantity%TYPE,
4005 p_ship_to_location_id IN PO_LINE_LOCATIONS.ship_to_location_id%TYPE,
4006 p_need_by_date IN PO_LINE_LOCATIONS.need_by_date%TYPE,
4007 x_price OUT NOCOPY PO_LINES.unit_price%TYPE
4008 ) IS
4009 l_quantity PO_LINE_LOCATIONS.quantity%TYPE;
4010 l_ship_to_location_id PO_LINE_LOCATIONS.ship_to_location_id%TYPE;
4011 l_ship_to_org_id PO_LINE_LOCATIONS.ship_to_organization_id%TYPE;
4012 l_need_by_date PO_LINE_LOCATIONS.need_by_date%TYPE;
4013 l_po_line_id PO_LINE_LOCATIONS.po_line_id%TYPE;
4014 l_price_break_type PO_LINES.price_break_lookup_code %TYPE;
4015 l_cumulative_flag BOOLEAN;
4016 l_price_break_id PO_LINE_LOCATIONS.line_location_id%TYPE;
4017 l_return_status VARCHAR2(1);
4018
4019 BEGIN
4020 -- For quantity, ship-to location, and need-by date, use the new value
4021 -- if provided; otherwise retrieve the existing value from the database.
4022
4023 SELECT NVL(p_quantity, PLL.quantity),
4024 NVL(p_ship_to_location_id, PLL.ship_to_location_id),
4025 NVL(p_need_by_date, NVL(PLL.need_by_date, sysdate)),
4026 PLL.ship_to_organization_id,
4027 PLL.po_line_id,
4028 POL.price_break_lookup_code
4029 INTO l_quantity,
4030 l_ship_to_location_id,
4031 l_need_by_date,
4032 l_ship_to_org_id,
4033 l_po_line_id,
4034 l_price_break_type
4035 FROM po_line_locations PLL, po_lines POL
4036 WHERE PLL.line_location_id = p_line_location_id
4037 AND PLL.po_line_id = POL.po_line_id; -- JOIN
4038
4039 -- True if price break type is CUMULATIVE, false otherwise:
4040 l_cumulative_flag := (l_price_break_type = 'CUMULATIVE');
4041
4042 PO_SOURCING2_SV.get_break_price(
4043 p_api_version => 1.0,
4044 p_order_quantity => l_quantity,
4045 p_ship_to_org => l_ship_to_org_id,
4046 p_ship_to_loc => l_ship_to_location_id,
4047 p_po_line_id => l_po_line_id,
4048 p_cum_flag => l_cumulative_flag,
4049 p_need_by_date => l_need_by_date,
4050 p_line_location_id => p_line_location_id,
4051 x_price_break_id => l_price_break_id,
4052 x_price => x_price,
4053 x_return_status => l_return_status
4054 );
4055
4056 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4057 RAISE FND_API.g_exc_unexpected_error;
4058 END IF;
4059
4060 EXCEPTION
4061 WHEN FND_API.g_exc_unexpected_error THEN
4062 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4063 p_proc_name => 'GET_RELEASE_BREAK_PRICE',
4064 p_add_to_msg_list => FALSE );
4065 RAISE FND_API.g_exc_unexpected_error;
4066 WHEN OTHERS THEN
4067 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4068 p_proc_name => 'GET_RELEASE_BREAK_PRICE' );
4069 RAISE FND_API.g_exc_unexpected_error;
4070 END get_release_break_price;
4071
4072 -------------------------------------------------------------------------------
4073 --Start of Comments
4074 --Name: get_po_break_price
4075 --Function:
4076 -- Returns the price from the price break for a PO line.
4077 --Pre-reqs:
4078 -- None.
4079 --Modifies:
4080 -- None.
4081 --Locks:
4082 -- None.
4083 --End of Comments
4084 -------------------------------------------------------------------------------
4085 PROCEDURE get_po_break_price (
4086 p_po_line_id IN PO_LINES.po_line_id%TYPE,
4087 p_quantity IN PO_LINES.quantity%TYPE,
4088 p_line_location_id IN PO_LINE_LOCATIONS.line_location_id%TYPE,
4089 p_ship_to_location_id IN PO_LINE_LOCATIONS.ship_to_location_id%TYPE,
4090 p_need_by_date IN PO_LINE_LOCATIONS.need_by_date%TYPE,
4091 x_price_break_id OUT NOCOPY PO_LINES.from_line_location_id%TYPE,
4092 x_price OUT NOCOPY PO_LINES.unit_price%TYPE,
4093 -- <FPJ Advanced Price>
4094 x_base_unit_price OUT NOCOPY PO_LINES.base_unit_price%TYPE
4095 ) IS
4096 l_quantity PO_LINES.quantity%TYPE;
4097 l_ship_to_location_id PO_LINE_LOCATIONS.ship_to_location_id%TYPE;
4098 l_ship_to_org_id PO_LINE_LOCATIONS.ship_to_organization_id%TYPE;
4099 l_need_by_date PO_LINE_LOCATIONS.need_by_date%TYPE;
4100 l_from_line_id PO_LINES.from_line_id%TYPE;
4101 l_return_status VARCHAR2(1);
4102
4103 -- <FPJ Advanced Price START>
4104 l_org_id po_lines.org_id%TYPE;
4105 l_contract_id po_lines.contract_id%TYPE;
4106 l_order_header_id po_lines.po_header_id%TYPE;
4107 l_order_line_id po_lines.po_line_id%TYPE;
4108 l_creation_date po_lines.creation_date%TYPE;
4109 l_item_id po_lines.item_id%TYPE;
4110 l_item_revision po_lines.item_revision%TYPE;
4111 l_category_id po_lines.category_id%TYPE;
4112 l_line_type_id po_lines.line_type_id%TYPE;
4113 l_vendor_product_num po_lines.vendor_product_num%TYPE;
4114 l_vendor_id po_headers.vendor_id%TYPE;
4115 l_vendor_site_id po_headers.vendor_site_id%TYPE;
4116 l_uom po_lines.unit_meas_lookup_code%TYPE;
4117 l_in_unit_price po_lines.unit_price%TYPE;
4118 l_base_unit_price po_lines.base_unit_price%TYPE;
4119 l_currency_code po_headers.currency_code%TYPE;
4120 -- <FPJ Advanced Price END>
4121
4122 BEGIN
4123 -- For quantity, ship-to location, and need-by date, use the new value
4124 -- if provided; otherwise retrieve the existing value from the database.
4125
4126 SELECT NVL(p_quantity,POL.quantity),
4127 POL.from_line_id,
4128 NVL(p_ship_to_location_id, PLL.ship_to_location_id),
4129 NVL(p_need_by_date, NVL(PLL.need_by_date, sysdate)),
4130 PLL.ship_to_organization_id,
4131 -- <FPJ Advanced Price START>
4132 POL.org_id,
4133 POL.contract_id,
4134 POL.po_header_id,
4135 POL.po_line_id,
4136 POL.creation_date,
4137 POL.item_id,
4138 POL.item_revision,
4139 POL.category_id,
4140 POL.line_type_id,
4141 POL.vendor_product_num,
4142 POH.vendor_id,
4143 POH.vendor_site_id,
4144 POL.unit_meas_lookup_code,
4145 -- Bug 3417479
4146 -- NVL(POL.base_unit_price, POL.unit_price)
4147 POL.base_unit_price,
4148 POH.currency_code
4149 -- <FPJ Advanced Price END>
4150 INTO l_quantity,
4151 l_from_line_id,
4152 l_ship_to_location_id,
4153 l_need_by_date,
4154 l_ship_to_org_id,
4155 -- <FPJ Advanced Price START>
4156 l_org_id,
4157 l_contract_id,
4158 l_order_header_id,
4159 l_order_line_id,
4160 l_creation_date,
4161 l_item_id,
4162 l_item_revision,
4163 l_category_id,
4164 l_line_type_id,
4165 l_vendor_product_num,
4166 l_vendor_id,
4167 l_vendor_site_id,
4168 l_uom,
4169 l_in_unit_price,
4170 l_currency_code -- Bug 3564863
4171 -- <FPJ Advanced Price END>
4172 FROM po_line_locations PLL, po_lines POL,
4173 -- <FPJ Advanced Price>
4174 po_headers POH
4175 WHERE PLL.line_location_id = p_line_location_id
4176 AND POL.po_line_id = PLL.po_line_id -- JOIN
4177 -- <FPJ Advanced Price>
4178 AND POH.po_header_id = POL.po_header_id;
4179
4180 PO_SOURCING2_SV.get_break_price
4181 ( p_api_version => 1.0
4182 , p_order_quantity => l_quantity
4183 , p_ship_to_org => l_ship_to_org_id
4184 , p_ship_to_loc => l_ship_to_location_id
4185 , p_po_line_id => l_from_line_id
4186 , p_cum_flag => FALSE
4187 , p_need_by_date => l_need_by_date
4188 , p_line_location_id => p_line_location_id
4189 -- <FPJ Advanced Price START>
4190 , p_contract_id => l_contract_id
4191 , p_org_id => l_org_id
4192 , p_supplier_id => l_vendor_id
4193 , p_supplier_site_id => l_vendor_site_id
4194 , p_creation_date => l_creation_date
4195 , p_order_header_id => l_order_header_id
4196 , p_order_line_id => l_order_line_id
4197 , p_line_type_id => l_line_type_id
4198 , p_item_revision => l_item_revision
4199 , p_item_id => l_item_id
4200 , p_category_id => l_category_id
4201 , p_supplier_item_num => l_vendor_product_num
4202 , p_in_price => l_in_unit_price
4203 , p_uom => l_uom
4204 , p_currency_code => l_currency_code -- Bug 3564863
4205 , x_base_unit_price => x_base_unit_price
4206 -- <FPJ Advanced Price END>
4207 , x_price_break_id => x_price_break_id
4208 , x_price => x_price
4209 , x_return_status => l_return_status
4210 );
4211
4212 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4213 RAISE FND_API.g_exc_unexpected_error;
4214 END IF;
4215
4216 EXCEPTION
4217 WHEN FND_API.g_exc_unexpected_error THEN
4218 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4219 p_proc_name => 'GET_PO_BREAK_PRICE',
4220 p_add_to_msg_list => FALSE );
4221 RAISE FND_API.g_exc_unexpected_error;
4222 WHEN OTHERS THEN
4223 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4224 p_proc_name => 'GET_PO_BREAK_PRICE' );
4225 RAISE FND_API.g_exc_unexpected_error;
4226 END get_po_break_price;
4227
4228 -------------------------------------------------------------------------------
4229 --Start of Comments
4230 --Name: get_min_shipment_id
4231 --Function:
4232 -- Returns the LINE_LOCATION_ID of the first shipment of the given PO line.
4233 --Pre-reqs:
4234 -- None.
4235 --Modifies:
4236 -- None.
4237 --Locks:
4238 -- None.
4239 --End of Comments
4240 -------------------------------------------------------------------------------
4241 FUNCTION get_min_shipment_id (
4242 p_po_line_id IN PO_LINES.po_line_id%TYPE
4243 ) RETURN NUMBER IS
4244 l_min_shipment_num NUMBER;
4245 l_line_location_id NUMBER;
4246 BEGIN
4247 PO_SOURCING2_SV.get_min_shipment_num (
4248 p_po_line_id => p_po_line_id,
4249 x_min_shipment_num => l_min_shipment_num
4250 );
4251
4252 IF (l_min_shipment_num IS NULL) THEN
4253 RETURN NULL;
4254 END IF;
4255
4256 SELECT line_location_id
4257 INTO l_line_location_id
4258 FROM po_line_locations
4259 WHERE po_line_id = p_po_line_id
4260 AND shipment_num = l_min_shipment_num
4261 AND shipment_type IN ('STANDARD','PLANNED');
4262
4263 RETURN l_line_location_id;
4264 EXCEPTION
4265 WHEN FND_API.g_exc_unexpected_error THEN
4266 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4267 p_proc_name => 'GET_MIN_SHIPMENT_ID',
4268 p_add_to_msg_list => FALSE );
4269 RAISE FND_API.g_exc_unexpected_error;
4270 WHEN OTHERS THEN
4271 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4272 p_proc_name => 'GET_MIN_SHIPMENT_ID' );
4273 RAISE FND_API.g_exc_unexpected_error;
4274 END get_min_shipment_id;
4275
4276 -------------------------------------------------------------------------------
4277 --Start of Comments
4278 --Name: derive_qty_amt_rollups
4279 --Function:
4280 -- Performs quantity/amount rollups as needed, from distributions to shipments,
4281 -- and from shipments to lines.
4282 --Pre-reqs:
4283 -- The document is not a blanket.
4284 --Modifies:
4285 -- Updates p_chg with any derived changes.
4286 --Locks:
4287 -- None.
4288 --End of Comments
4289 -------------------------------------------------------------------------------
4290 PROCEDURE derive_qty_amt_rollups (
4291 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
4292 ) IS
4293 l_proc_name CONSTANT VARCHAR2(30) := 'DERIVE_QTY_AMT_ROLLUPS';
4294 l_progress VARCHAR2(3) := '000';
4295
4296 l_ship_rollup_started INDEXED_TBL_NUMBER;
4297 l_line_rollup_started INDEXED_TBL_NUMBER;
4298
4299 l_po_line_id PO_LINES.po_line_id%TYPE;
4300 l_line_location_id PO_LINE_LOCATIONS.line_location_id%TYPE;
4301
4302 l_cur_line_qty_amt PO_LINES.quantity%TYPE;
4303 l_new_line_qty_amt PO_LINES.quantity%TYPE;
4304 l_cur_ship_qty_amt PO_LINE_LOCATIONS.quantity%TYPE;
4305 l_exist_ship_qty_amt PO_LINE_LOCATIONS.quantity%TYPE;
4306 l_new_ship_qty_amt PO_LINE_LOCATIONS.quantity%TYPE;
4307 l_exist_dist_qty_amt PO_DISTRIBUTIONS.quantity_ordered%TYPE;
4308 l_new_dist_qty_amt PO_DISTRIBUTIONS.quantity_ordered%TYPE;
4309
4310 --<R12 complex work>
4311 l_cur_line_amt PO_LINES.amount%type;
4312 l_exist_ship_amt PO_LINE_LOCATIONS.amount%type;
4313 l_new_ship_amt PO_LINE_LOCATIONS.amount%TYPE;
4314 l_new_line_amt PO_LINES.amount%TYPE;
4315 l_new_line_price PO_LINES.unit_price%TYPE;
4316
4317 l_ship_chg_i NUMBER;
4318 l_line_chg_i NUMBER;
4319 l_amt_based BOOLEAN;
4320 BEGIN
4321 IF (g_fnd_debug = 'Y') THEN
4322 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
4323 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
4324 module => g_module_prefix || l_proc_name,
4325 message => 'Entering ' || l_proc_name );
4326 END IF;
4327 END IF;
4328
4329 l_progress := '010';
4330
4331 -- Roll up any distribution quantity/amount changes to the
4332 -- shipment quantity/amount, if needed.
4333
4334 -- Note: We do not need to rollup from split distributions to split
4335 -- shipments, because split shipment changes must include quantity or amount.
4336
4337 FOR i IN 1..p_chg.distribution_changes.get_count LOOP
4338 IF (p_chg.distribution_changes.parent_distribution_id(i) IS NULL)
4339 AND (dist_has_qty_amt_change(p_chg,i)) THEN
4340
4341 l_progress := '020';
4342
4343 -- Get the shipment change for this distribution.
4344 l_line_location_id := p_chg.distribution_changes.c_line_location_id(i);
4345 l_ship_chg_i := find_ship_change(p_chg,l_line_location_id);
4346
4347 -- Rollup if we have already started to rollup to this shipment,
4348 -- or if the shipment does not have a quantity/amount change.
4349 IF l_ship_rollup_started.EXISTS(l_line_location_id)
4350 OR (NOT ship_has_qty_amt_change(p_chg,l_ship_chg_i)) THEN
4351
4352 l_progress := '030';
4353
4354 -- TRUE if the line is amount-based, FALSE if it is quantity-based:
4355 l_amt_based := (p_chg.shipment_changes.c_value_basis(l_ship_chg_i)
4356 IN ('RATE','FIXED PRICE'));
4357
4358 -- Get the current shipment quantity/amount (l_cur_ship_qty_amt)
4359 -- and the existing (l_exist_dist_qty_amt) and new (l_new_dist_qty_amt)
4360 -- distribution quantities/amounts.
4361 IF (l_amt_based) THEN -- amount-based line
4362 l_cur_ship_qty_amt :=
4363 NVL( p_chg.shipment_changes.amount(l_ship_chg_i),
4364 p_chg.shipment_changes.c_amount(l_ship_chg_i) );
4365 l_exist_dist_qty_amt := p_chg.distribution_changes.c_amount_ordered(i);
4366 l_new_dist_qty_amt := p_chg.distribution_changes.amount_ordered(i);
4367 ELSE -- quantity-based line
4368 l_cur_ship_qty_amt :=
4369 NVL ( p_chg.shipment_changes.quantity(l_ship_chg_i),
4370 p_chg.shipment_changes.c_quantity(l_ship_chg_i) );
4371 l_exist_dist_qty_amt := p_chg.distribution_changes.c_quantity_ordered(i);
4372 l_new_dist_qty_amt := p_chg.distribution_changes.quantity_ordered(i);
4373 END IF;
4374
4375 l_progress := '035';
4376
4377 -- new shipment Q = current shipment Q + change in distribution Q
4378 l_new_ship_qty_amt :=
4379 l_cur_ship_qty_amt + (l_new_dist_qty_amt - l_exist_dist_qty_amt);
4380
4381 -- Only roll up if the resulting quantity/amount is greater than 0.
4382 IF (l_new_ship_qty_amt > 0) THEN
4383
4384 IF (l_amt_based) THEN -- amount-based line
4385 p_chg.shipment_changes.set_amount(l_ship_chg_i,
4386 l_new_ship_qty_amt);
4387 ELSE -- quantity-based line
4388 p_chg.shipment_changes.set_quantity(l_ship_chg_i,
4389 l_new_ship_qty_amt);
4390 END IF;
4391
4392 -- Mark this as a shipment that we are rolling up to.
4393 l_ship_rollup_started(l_line_location_id) := 1;
4394
4395 IF (g_fnd_debug = 'Y') THEN
4396 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4397 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4398 module => g_module_prefix||l_proc_name,
4399 message => 'Ship change on ' || l_line_location_id
4400 ||': Quantity/amount rollup from distribution: '
4401 ||l_new_ship_qty_amt || ', change '
4402 ||(l_new_dist_qty_amt-l_exist_dist_qty_amt));
4403 END IF;
4404 END IF;
4405
4406 ELSE -- l_new_ship_qty_amt <= 0
4407 -- Note: This is possible if the API is called when the distribution
4408 -- quantities/amounts do not sum up to the shipment quantity/amount.
4409
4410 IF (g_fnd_debug = 'Y') THEN
4411 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4412 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4413 module => g_module_prefix||l_proc_name,
4414 message => 'Ship change on '||l_line_location_id
4415 ||': Not rolling up quantity/amount from '
4416 ||'distribution because it would be <= 0: '
4417 ||l_new_ship_qty_amt || ', change '
4418 ||(l_new_dist_qty_amt-l_exist_dist_qty_amt));
4419 END IF;
4420 END IF;
4421 END IF; -- l_new_ship_qty_amt
4422
4423 END IF; -- l_ship_rollup_started
4424 END IF; -- new distribution quantity/amount exists
4425 END LOOP; -- distribution changes
4426
4427 l_progress := '050';
4428
4429 -- For a standard or planned PO, roll up any shipment quantity/amount
4430 -- changes to the line quantity/amount, if needed.
4431 IF g_document_type = 'PO' THEN
4432
4433 -- Rollup each shipment quantity/amount change (including split shipments)
4434 -- to the corresponding line quantity/amount change.
4435 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
4436 IF (ship_has_qty_amt_change(p_chg,i)) THEN
4437
4438 l_progress := '060';
4439
4440 -- Get the line change for this shipment.
4441 l_po_line_id := p_chg.shipment_changes.c_po_line_id(i);
4442 l_line_chg_i := find_line_change(p_chg,l_po_line_id);
4443
4444 -- Rollup if we have already started to rollup to this line, or if
4445 -- the line does not have a quantity/amount change.
4446 IF l_line_rollup_started.EXISTS(l_po_line_id)
4447 OR (NOT line_has_qty_amt_change(p_chg,l_line_chg_i)) THEN
4448
4449 l_progress := '070';
4450
4451 -- TRUE if the line is amount-based, FALSE if it is quantity-based:
4452 l_amt_based := (p_chg.line_changes.c_value_basis(l_line_chg_i)
4453 IN ('RATE','FIXED PRICE')); -- Bug 3256850
4454 /* << Complex work changes for R12 >> */
4455 IF (g_is_complex_work_po=FALSE ) then
4456 --{
4457
4458 -- Get the current line quantity/amount (l_cur_line_qty_amt) and
4459 -- the existing (l_exist_ship_qty_amt) and new (l_new_ship_qty_amt)
4460 -- shipment quantities/amounts.
4461 IF (l_amt_based) THEN -- amount-based line
4462 l_cur_line_qty_amt :=
4463 NVL ( p_chg.line_changes.amount(l_line_chg_i),
4464 p_chg.line_changes.c_amount(l_line_chg_i) );
4465 l_exist_ship_qty_amt := p_chg.shipment_changes.c_amount(i);
4466 l_new_ship_qty_amt := p_chg.shipment_changes.amount(i);
4467 ELSE -- quantity-based line
4468 l_cur_line_qty_amt :=
4469 NVL ( p_chg.line_changes.quantity(l_line_chg_i),
4470 p_chg.line_changes.c_quantity(l_line_chg_i) );
4471 l_exist_ship_qty_amt := p_chg.shipment_changes.c_quantity(i);
4472 l_new_ship_qty_amt := p_chg.shipment_changes.quantity(i);
4473 END IF;
4474
4475 l_progress := '075';
4476
4477 -- new line Q = current line Q + change in shipment Q
4478 l_new_line_qty_amt :=
4479 l_cur_line_qty_amt + (l_new_ship_qty_amt - l_exist_ship_qty_amt);
4480
4481 -- Only roll up if the resulting quantity/amount is greater than 0.
4482 IF (l_new_line_qty_amt > 0) THEN
4483
4484 IF (l_amt_based) THEN -- amount-based line
4485 p_chg.line_changes.set_amount(l_line_chg_i, l_new_line_qty_amt);
4486 ELSE -- quantity-based line
4487 p_chg.line_changes.set_quantity(l_line_chg_i, l_new_line_qty_amt);
4488 END IF;
4489
4490 -- Mark this as a line that we are rolling up to.
4491 l_line_rollup_started(l_po_line_id) := 1;
4492
4493 IF (g_fnd_debug = 'Y') THEN
4494 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4495 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4496 module => g_module_prefix||l_proc_name,
4497 message => 'Line change on ' || l_po_line_id
4498 ||': Quantity/amount rollup from shipment: '
4499 ||l_new_line_qty_amt || ', change '
4500 ||(l_new_ship_qty_amt-l_exist_ship_qty_amt));
4501 END IF;
4502 END IF;
4503 ELSE -- l_new_line_qty_amt <= 0
4504 -- Note: This is possible if the API is called when the shipment
4505 -- quantities/amounts do not sum up to the line quantity/amount.
4506
4507 IF (g_fnd_debug = 'Y') THEN
4508 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4509 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4510 module => g_module_prefix||l_proc_name,
4511 message => 'Line change on '||l_po_line_id
4512 ||': Not rolling up quantity/amount from '
4513 ||'shipment because it would be <= 0: '
4514 ||l_new_line_qty_amt || ', change '
4515 ||(l_new_ship_qty_amt-l_exist_ship_qty_amt));
4516 END IF;
4517 END IF;
4518 END IF;-- l_new_line_qty_amt
4519 --}
4520 ELSIF (g_is_complex_work_po=TRUE ) and (g_is_financing_po=FALSE) then
4521 --{
4522 If (l_amt_based=FALSE) then
4523 l_cur_line_amt := nvl(p_chg.line_changes.unit_price(l_line_chg_i),p_chg.line_changes.c_unit_price(l_line_chg_i)) *
4524 p_chg.line_changes.c_quantity(l_line_chg_i);
4525 else
4526 l_cur_line_amt :=nvl(p_chg.line_changes.amount(l_line_chg_i),p_chg.line_changes.c_amount(l_line_chg_i));
4527 end if;
4528
4529 if ((nvl(p_chg.shipment_changes.payment_type(i),'')='RATE') or
4530 (p_chg.shipment_changes.c_value_basis(i) not in ('RATE','FIXED PRICE'))) then
4531 l_exist_ship_amt := p_chg.shipment_changes.c_price_override(i) *
4532 p_chg.shipment_changes.c_quantity(i);
4533
4534 l_new_ship_amt := NVL(p_chg.shipment_changes.price_override(i),
4535 p_chg.shipment_changes.c_price_override(i)) *
4536 NVL(p_chg.shipment_changes.quantity(i),
4537 p_chg.shipment_changes.c_quantity(i)) ;
4538 l_new_line_amt := l_cur_line_amt + (l_new_ship_amt - nvl(l_exist_ship_amt,0));
4539 else
4540 l_exist_ship_amt := p_chg.shipment_changes.c_amount(i) ;
4541 l_new_ship_amt := p_chg.shipment_changes.amount(i) ;
4542 l_new_line_amt := l_cur_line_amt + (l_new_ship_amt - l_exist_ship_amt);
4543 end if;
4544
4545
4546 IF (l_new_line_amt> 0) THEN
4547
4548 if (l_amt_based=FALSE) then
4549 l_new_line_price :=l_new_line_amt/p_chg.line_changes.c_quantity(l_line_chg_i);
4550 p_chg.line_changes.set_unit_price(l_line_chg_i, l_new_line_price);
4551 else
4552 p_chg.line_changes.set_amount(l_line_chg_i,l_new_line_amt);
4553 end if;
4554
4555 -- Mark this as a line that we are rolling up to.
4556 l_line_rollup_started(l_po_line_id) := 1;
4557
4558 IF (g_fnd_debug = 'Y') THEN
4559 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4560 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4561 module => g_module_prefix||l_proc_name,
4562 message => 'Line change on ' || l_po_line_id
4563 ||': Quantity/amount rollup from shipment: '
4564 ||l_new_line_price|| ', change '
4565 ||(l_new_ship_amt-l_exist_ship_amt));
4566 END IF;
4567 END IF;
4568 ELSE -- l_new_line_qty_amt <= 0
4569 -- Note: This is possible if the API is called when the shipment
4570 -- quantities/amounts do not sum up to the line quantity/amount.
4571
4572 IF (g_fnd_debug = 'Y') THEN
4573 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4574 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4575 module => g_module_prefix||l_proc_name,
4576 message => 'Line change on '||l_po_line_id
4577 ||': Not rolling up quantity/amount from '
4578 ||'shipment because it would be <= 0: '
4579 ||l_new_line_price|| ', change '
4580 ||(l_new_ship_amt-l_exist_ship_amt));
4581 END IF;
4582 END IF;
4583 END IF; -- l_new_line_qty_amt
4584
4585 --}
4586
4587 END IF; --Complex work
4588 END IF; -- l_line_rollup_started
4589
4590 END IF; -- ship_has_qty_amt_change
4591 END LOOP; -- shipment changes
4592
4593 END IF; -- document type is standard PO or planned PO
4594
4595 EXCEPTION
4596 WHEN FND_API.g_exc_unexpected_error THEN
4597 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4598 p_proc_name => l_proc_name,
4599 p_progress => l_progress,
4600 p_add_to_msg_list => FALSE );
4601 RAISE FND_API.g_exc_unexpected_error;
4602 WHEN OTHERS THEN
4603 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4604 p_proc_name => l_proc_name,
4605 p_progress => l_progress );
4606 RAISE FND_API.g_exc_unexpected_error;
4607 END derive_qty_amt_rollups;
4608
4609 -------------------------------------------------------------------------------
4610 --Start of Comments
4611 --Name: round_amount
4612 --Function:
4613 -- Rounds the given amount to the Minimum Accountable Unit (MAU),
4614 -- if available, or otherwise to the Precision.
4615 --Pre-reqs:
4616 -- None.
4617 --Modifies:
4618 -- None.
4619 --Locks:
4620 -- None.
4621 --End of Comments
4622 -------------------------------------------------------------------------------
4623 FUNCTION round_amount (
4624 p_amount IN PO_LINES.amount%TYPE
4625 ) RETURN NUMBER IS
4626 BEGIN
4627 IF (g_min_accountable_unit IS NOT NULL) THEN -- Round to the MAU.
4628 RETURN round (p_amount / g_min_accountable_unit) * g_min_accountable_unit;
4629 ELSE -- MAU not available. Round to the Precision.
4630 RETURN round (p_amount, g_precision);
4631 END IF;
4632 END round_amount;
4633
4634 -------------------------------------------------------------------------------
4635 --Start of Comments
4636 --Name: derive_qty_amt_rolldowns
4637 --Function:
4638 -- Performs quantity/amount rolldowns from lines to shipments, as needed.
4639 -- Performs quantity/amount prorations from shipments to distributions,
4640 -- as needed.
4641 --Pre-reqs:
4642 -- The document is not a blanket.
4643 --Modifies:
4644 -- Updates p_chg with any derived changes.
4645 --Locks:
4646 -- None.
4647 --End of Comments
4648 -------------------------------------------------------------------------------
4649 PROCEDURE derive_qty_amt_rolldowns (
4650 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
4651 ) IS
4652 l_proc_name CONSTANT VARCHAR2(30) := 'DERIVE_QTY_AMT_ROLLDOWNS';
4653 l_progress VARCHAR2(3) := '000';
4654
4655 -- SQL What: Retrieves all the distributions of a given shipment.
4656 -- SQL Why: To prorate shipment quantity/amount changes to the distributions.
4657 CURSOR po_distribution_csr (
4658 p_line_location_id PO_DISTRIBUTIONS.line_location_id%TYPE
4659 ) IS
4660 SELECT po_distribution_id, distribution_num, quantity_ordered, amount_ordered
4661 FROM po_distributions
4662 WHERE line_location_id = p_line_location_id
4663 ORDER by distribution_num ASC;
4664
4665 l_po_line_id PO_LINES.po_line_id%TYPE;
4666 l_line_location_id PO_LINE_LOCATIONS.line_location_id%TYPE;
4667 l_parent_line_loc_id PO_LINE_LOCATIONS.line_location_id%TYPE;
4668 l_po_distribution_id PO_DISTRIBUTIONS.po_distribution_id%TYPE;
4669
4670 l_exist_line_qty_amt PO_LINES.quantity%TYPE;
4671 l_new_line_qty_amt PO_LINES.quantity%TYPE;
4672 l_exist_ship_qty_amt PO_LINE_LOCATIONS.quantity%TYPE;
4673 l_new_ship_qty_amt PO_LINE_LOCATIONS.quantity%TYPE;
4674 l_cum_qty_amt PO_LINE_LOCATIONS.quantity%TYPE;
4675 l_split_shipment_num PO_LINE_LOCATIONS.shipment_num%TYPE;
4676 l_exist_dist_qty PO_DISTRIBUTIONS.quantity_ordered%TYPE;
4677 l_exist_dist_amt PO_DISTRIBUTIONS.amount_ordered%TYPE;
4678 l_exist_dist_qty_amt PO_DISTRIBUTIONS.quantity_ordered%TYPE;
4679 l_new_dist_qty_amt PO_DISTRIBUTIONS.quantity_ordered%TYPE;
4680 l_remain_qty_amt PO_DISTRIBUTIONS.quantity_ordered%TYPE;
4681 l_dist_num PO_DISTRIBUTIONS.distribution_num%TYPE;
4682 l_max_dist_num PO_DISTRIBUTIONS.distribution_num%TYPE;
4683
4684 l_ship_chg_i NUMBER;
4685 l_dist_chg_i NUMBER;
4686 l_amt_based BOOLEAN;
4687 l_ratio NUMBER;
4688 BEGIN
4689 IF (g_fnd_debug = 'Y') THEN
4690 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
4691 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
4692 module => g_module_prefix || l_proc_name,
4693 message => 'Entering ' || l_proc_name );
4694 END IF;
4695 END IF;
4696
4697 l_progress := '010';
4698
4699 -- Rolldown any line quantity/amount changes to the shipment
4700 -- quantity/amount, if needed (i.e. if none of its shipments have a
4701 -- quantity/amount change).
4702 FOR i IN 1..p_chg.line_changes.get_count LOOP
4703 l_progress := '020';
4704
4705 -- Only rolldown if the line has a quantity/amount change,
4706 -- but none of its shipments have quantity/amount changes.
4707 IF line_has_qty_amt_change(p_chg,i)
4708 AND NOT (line_has_ship_qty_amt_change(p_chg,i)) THEN
4709
4710 BEGIN
4711 -- SQL What: Retrieve the one active (i.e. not cancelled or finally
4712 -- closed) shipment for this line.
4713 -- (Note: The checks in verify_inputs ensure that there can
4714 -- only be one active shipment for this line.)
4715 SELECT line_location_id
4716 INTO l_line_location_id
4717 FROM po_line_locations
4718 WHERE po_line_id = p_chg.line_changes.po_line_id(i)
4719 AND shipment_type in ('STANDARD', 'PLANNED')
4720 AND NVL(cancel_flag,'N') <> 'Y'
4721 AND NVL(closed_code,'OPEN') <> 'FINALLY CLOSED';
4722
4723 l_ship_chg_i := find_ship_change(p_chg, l_line_location_id);
4724 EXCEPTION
4725 WHEN NO_DATA_FOUND THEN
4726 l_ship_chg_i := NULL; -- No active shipment found.
4727 END;
4728
4729 IF (l_ship_chg_i IS NOT NULL) THEN -- There is an active shipment.
4730
4731 -- TRUE if the line is amount-based, FALSE if it is quantity-based:
4732 l_amt_based := (p_chg.line_changes.c_value_basis(i)
4733 IN ('RATE','FIXED PRICE'));
4734
4735 IF (l_amt_based) THEN -- amount-based line
4736 l_exist_line_qty_amt := p_chg.line_changes.c_amount(i);
4737 l_new_line_qty_amt := p_chg.line_changes.amount(i);
4738 l_exist_ship_qty_amt := p_chg.shipment_changes.c_amount(l_ship_chg_i);
4739 ELSE -- quantity-based line
4740 l_exist_line_qty_amt := p_chg.line_changes.c_quantity(i);
4741 l_new_line_qty_amt := p_chg.line_changes.quantity(i);
4742 l_exist_ship_qty_amt := p_chg.shipment_changes.c_quantity(l_ship_chg_i);
4743 END IF;
4744
4745 l_progress := '030';
4746
4747 -- new shipment Q = existing shipment Q + change in line Q
4748 l_new_ship_qty_amt :=
4749 l_exist_ship_qty_amt + (l_new_line_qty_amt - l_exist_line_qty_amt);
4750
4751 -- Only roll down if the resulting quantity/amount is greater than 0.
4752 IF (l_new_ship_qty_amt > 0) THEN
4753 IF (l_amt_based) THEN -- amount-based line
4754 -- Bug 3256850 Fixed to use l_ship_chg_i instead of i as subscript.
4755 p_chg.shipment_changes.set_amount(l_ship_chg_i, l_new_ship_qty_amt);
4756 ELSE -- quantity-based line
4757 -- Bug 3256850 Fixed to use l_ship_chg_i instead of i as subscript.
4758 p_chg.shipment_changes.set_quantity(l_ship_chg_i, l_new_ship_qty_amt);
4759 END IF;
4760
4761 IF (g_fnd_debug = 'Y') THEN
4762 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4763 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4764 module => g_module_prefix||l_proc_name,
4765 message => 'Shipment change on '||l_line_location_id
4766 ||': Quantity/amount rolldown from line: '
4767 ||l_new_ship_qty_amt );
4768 END IF;
4769 END IF;
4770
4771 ELSE -- l_new_ship_qty_amt < 0
4772 -- Note: This is possible if the API is called when the shipment
4773 -- quantities/amounts do not sum up to the line quantity/amount.
4774
4775 IF (g_fnd_debug = 'Y') THEN
4776 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4777 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4778 module => g_module_prefix||l_proc_name,
4779 message => 'Shipment change on '||l_line_location_id
4780 ||': Not rolling down quantity/amount from line '
4781 ||'because it would be <= 0: '
4782 ||l_new_ship_qty_amt );
4783 END IF;
4784 END IF;
4785 END IF; -- l_new_ship_qty_amt
4786
4787 END IF; -- l_ship_chg_i
4788
4789 END IF; -- new line quantity/amount exists
4790 END LOOP; -- line changes
4791
4792 l_progress := '040';
4793
4794 -- Prorate any shipment quantity/amount changes to the distribution
4795 -- quantities/amounts, if needed (i.e. if none of its distributions
4796 -- have a quantity/amount change).
4797 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
4798
4799 -- Only prorate if the shipment has a quantity/amount change and none
4800 -- of its distributions have quantity/amount changes.
4801 IF (ship_has_qty_amt_change(p_chg,i))
4802 AND (NOT ship_has_dist_qty_amt_change(p_chg,i)) THEN
4803
4804 l_line_location_id := p_chg.shipment_changes.po_line_location_id(i);
4805 l_parent_line_loc_id := p_chg.shipment_changes.parent_line_location_id(i);
4806 l_split_shipment_num := p_chg.shipment_changes.split_shipment_num(i);
4807
4808 l_progress := '050';
4809
4810 -- TRUE if the line is amount-based, FALSE if it is quantity-based:
4811 l_amt_based := (p_chg.shipment_changes.c_value_basis(i)
4812 IN ('RATE','FIXED PRICE'));
4813
4814 IF (l_amt_based) THEN -- amount-based line
4815 l_new_ship_qty_amt := p_chg.shipment_changes.amount(i);
4816 IF (l_parent_line_loc_id IS NULL) THEN -- existing shipment
4817 l_exist_ship_qty_amt := p_chg.shipment_changes.c_amount(i);
4818 ELSE -- split shipment
4819 l_exist_ship_qty_amt := p_chg.shipment_changes.c_parent_amount(i);
4820 END IF;
4821
4822 ELSE -- quantity-based line
4823 l_new_ship_qty_amt := p_chg.shipment_changes.quantity(i);
4824 IF (l_parent_line_loc_id IS NULL) THEN -- existing shipment
4825 l_exist_ship_qty_amt := p_chg.shipment_changes.c_quantity(i);
4826 ELSE -- split shipment
4827 l_exist_ship_qty_amt := p_chg.shipment_changes.c_parent_quantity(i);
4828 END IF;
4829
4830 END IF;
4831
4832 l_progress := '055';
4833
4834 -- We will prorate using the following ratio:
4835 l_ratio := l_new_ship_qty_amt / l_exist_ship_qty_amt;
4836 l_cum_qty_amt := 0;
4837
4838 IF (g_fnd_debug = 'Y') THEN
4839 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4840 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4841 module => g_module_prefix||l_proc_name,
4842 message => 'Prorate from shipment '||l_line_location_id
4843 ||': old qty/amt: '||l_exist_ship_qty_amt
4844 ||' new qty/amt: '||l_new_ship_qty_amt
4845 ||' ratio: '||l_ratio );
4846 END IF;
4847 END IF;
4848
4849 -- SQL What: Retrieve the maximum distribution number of this shipment.
4850 SELECT max(distribution_num)
4851 INTO l_max_dist_num
4852 FROM po_distributions
4853 WHERE line_location_id = NVL(l_parent_line_loc_id, l_line_location_id);
4854
4855 -- Loop through the distributions of this shipment.
4856 OPEN po_distribution_csr (NVL(l_line_location_id, l_parent_line_loc_id));
4857 LOOP
4858 l_progress := '060';
4859
4860 FETCH po_distribution_csr INTO l_po_distribution_id, l_dist_num,
4861 l_exist_dist_qty, l_exist_dist_amt;
4862 EXIT WHEN po_distribution_csr%NOTFOUND;
4863
4864 IF (l_amt_based) THEN -- Amount-based line
4865 l_exist_dist_qty_amt := l_exist_dist_amt;
4866 ELSE -- Quantity-based line
4867 l_exist_dist_qty_amt := l_exist_dist_qty;
4868 END IF;
4869
4870 IF (l_dist_num <> l_max_dist_num) THEN
4871 -- Not the last distribution, so prorate.
4872 l_new_dist_qty_amt := l_exist_dist_qty_amt * l_ratio;
4873
4874 -- Round if it is an amount; truncate if it is a quantity.
4875 IF (l_amt_based) THEN -- Amount-based line
4876 l_new_dist_qty_amt := round_amount ( l_new_dist_qty_amt );
4877 ELSE -- Quantity-based line
4878 -- Truncate the quantity to an integer, unless it results in 0.
4879 IF (trunc(l_new_dist_qty_amt) <> 0) THEN
4880 l_new_dist_qty_amt := trunc (l_new_dist_qty_amt);
4881 ELSE
4882 -- Truncation results in 0 quantity, which is not allowed.
4883 -- Use the fractional quantity instead.
4884 l_new_dist_qty_amt := round(l_new_dist_qty_amt, G_QTY_PRECISION);
4885 END IF;
4886 END IF; -- l_amt_based
4887
4888 -- Maintain the cumulative quantity assigned to distributions:
4889 l_cum_qty_amt := l_cum_qty_amt + l_new_dist_qty_amt;
4890
4891 ELSE -- The last distribution gets the remaining quantity/amount.
4892
4893 -- Calculate the remainder.
4894 IF (l_amt_based) THEN -- Amount-based line
4895 l_remain_qty_amt :=
4896 round_amount(l_new_ship_qty_amt) - l_cum_qty_amt;
4897 ELSE -- Quantity-based line
4898 l_remain_qty_amt :=
4899 round(l_new_ship_qty_amt, G_QTY_PRECISION) - l_cum_qty_amt;
4900 END IF;
4901
4902 IF (l_remain_qty_amt > 0) THEN
4903 l_new_dist_qty_amt := l_remain_qty_amt;
4904 ELSE -- The remainder is <= 0.
4905 l_new_dist_qty_amt := NULL;
4906 END IF;
4907
4908 END IF; -- l_dist_num <> l_max_dist_num
4909
4910 IF (l_parent_line_loc_id IS NULL) THEN -- Existing distribution
4911 l_dist_chg_i := find_dist_change (p_chg, l_po_distribution_id);
4912 ELSE -- Split distribution
4913 l_dist_chg_i := find_split_dist_change (p_chg, l_po_distribution_id,
4914 l_parent_line_loc_id, l_split_shipment_num );
4915 END IF;
4916
4917 IF (l_amt_based) THEN -- amount-based line
4918 p_chg.distribution_changes.set_amount_ordered (l_dist_chg_i,
4919 l_new_dist_qty_amt);
4920 ELSE -- quantity-based line
4921 p_chg.distribution_changes.set_quantity_ordered (l_dist_chg_i,
4922 l_new_dist_qty_amt);
4923 END IF;
4924
4925 IF (g_fnd_debug = 'Y') THEN
4926 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
4927 FND_LOG.string ( log_level => FND_LOG.LEVEL_EVENT,
4928 module => g_module_prefix||l_proc_name,
4929 message => 'Distribution change on '||l_po_distribution_id
4930 ||': qty/amt prorated from shipment: '||l_new_dist_qty_amt );
4931 END IF;
4932 END IF;
4933
4934 END LOOP; -- po_distribution_csr
4935 CLOSE po_distribution_csr;
4936
4937 END IF; -- new shipment quantity/amount exists
4938 END LOOP; -- shipment changes
4939
4940 l_progress := '070';
4941
4942 EXCEPTION
4943 WHEN FND_API.g_exc_unexpected_error THEN
4944 IF (po_distribution_csr%ISOPEN) THEN
4945 CLOSE po_distribution_csr;
4946 END IF;
4947
4948 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4949 p_proc_name => l_proc_name,
4950 p_progress => l_progress,
4951 p_add_to_msg_list => FALSE );
4952 RAISE FND_API.g_exc_unexpected_error;
4953 WHEN OTHERS THEN
4954 IF (po_distribution_csr%ISOPEN) THEN
4955 CLOSE po_distribution_csr;
4956 END IF;
4957
4958 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
4959 p_proc_name => l_proc_name,
4960 p_progress => l_progress );
4961 RAISE FND_API.g_exc_unexpected_error;
4962 END derive_qty_amt_rolldowns;
4963
4964 -------------------------------------------------------------------------------
4965 --Start of Comments
4966 --Name: validate_changes
4967 --Function:
4968 -- Performs field-level validations and optionally runs the PO submission
4969 -- checks on all the requested and derived changes.
4970 --Pre-reqs:
4971 -- None.
4972 --Modifies:
4973 -- None.
4974 --Locks:
4975 -- None.
4976 --End of Comments
4977 -------------------------------------------------------------------------------
4978 PROCEDURE validate_changes (
4979 p_chg IN PO_CHANGES_REC_TYPE,
4980 p_run_submission_checks IN VARCHAR2,
4981 x_return_status OUT NOCOPY VARCHAR2
4982 ) IS
4983 l_proc_name CONSTANT VARCHAR2(30) := 'VALIDATE_CHANGES';
4984 l_progress VARCHAR2(3) := '000';
4985
4986 l_return_status VARCHAR2(1);
4987 l_sub_check_status VARCHAR2(1);
4988 l_doc_check_errors DOC_CHECK_RETURN_TYPE;
4989 l_online_report_id PO_ONLINE_REPORT_TEXT.online_report_id%TYPE;
4990 l_msg_data VARCHAR2(2000);
4991
4992
4993
4994 BEGIN
4995 IF (g_fnd_debug = 'Y') THEN
4996 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
4997 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
4998 module => g_module_prefix || l_proc_name,
4999 message => 'Entering ' || l_proc_name );
5000 END IF;
5001 END IF;
5002
5003 l_progress := '010';
5004 x_return_status := FND_API.G_RET_STS_SUCCESS;
5005
5006 -- Line validations:
5007 IF (g_document_type <> 'RELEASE') THEN
5008 validate_line_changes (p_chg, l_return_status);
5009 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5010 x_return_status := l_return_status;
5011 END IF;
5012 END IF; -- document type is not release
5013
5014 l_progress := '020';
5015
5016 -- Shipment validations:
5017 validate_shipment_changes (p_chg, l_return_status);
5018 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5019 x_return_status := l_return_status;
5020 END IF;
5021
5022 l_progress := '030';
5023
5024 -- Distribution validations:
5025 IF (g_document_type <> 'PA') THEN
5026 validate_distribution_changes (p_chg, l_return_status);
5027 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5028 x_return_status := l_return_status;
5029 END IF;
5030 END IF; -- document type is not blanket
5031
5032 -- Do not continue if one or more of the field-level validations failed.
5033 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5034 RETURN;
5035 END IF;
5036
5037
5038 l_progress := '040';
5039
5040 -- Call the PO Submission Checks if requested by the caller.
5041 IF g_sec_qty_grade_only_chge_doc = 'N' THEN --sschinch 09/08/04 INVCONV
5042
5043 IF ( FND_API.to_boolean(p_run_submission_checks) ) THEN
5044
5045 IF (g_fnd_debug = 'Y') THEN
5046 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
5047 FND_LOG.string( log_level => FND_LOG.LEVEL_EVENT,
5048 module => g_module_prefix || l_proc_name,
5049 message => 'Calling Submission Checks' );
5050 END IF;
5051 END IF;
5052
5053 PO_DOCUMENT_CHECKS_GRP.po_submission_check (
5054 p_api_version => 1.0,
5055 p_action_requested => 'DOC_SUBMISSION_CHECK',
5056 p_document_type => g_document_type,
5057 p_document_subtype => g_document_subtype,
5058 p_document_id => g_document_id,
5059 p_org_id => NULL, -- org context is already set.
5060 p_requested_changes => p_chg,
5061 x_return_status => l_return_status,
5062 x_sub_check_status => l_sub_check_status,
5063 x_msg_data => l_msg_data,
5064 x_online_report_id => l_online_report_id,
5065 x_doc_check_error_record => l_doc_check_errors
5066 );
5067
5068 IF (g_fnd_debug = 'Y') THEN
5069 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
5070 FND_LOG.string( log_level => FND_LOG.LEVEL_EVENT,
5071 module => g_module_prefix || l_proc_name,
5072 message =>
5073 'Submission Checks return_status: '||l_return_status
5074 ||', sub_check_status: '||l_sub_check_status );
5075 END IF;
5076 END IF;
5077
5078
5079 l_progress := '050';
5080
5081 IF ( l_return_status <> FND_API.G_RET_STS_SUCCESS ) THEN
5082 -- PO Submission Checks had a program failure.
5083 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
5084 ELSIF ( l_sub_check_status <> FND_API.G_RET_STS_SUCCESS ) THEN
5085 -- PO Submission Checks found some validation errors.
5086 -- Copy the errors from l_doc_check_errors into g_api_errors.
5087 FOR i IN 1..l_doc_check_errors.online_report_id.COUNT LOOP
5088
5089 -- Since PO Submission Checks do not currently handle split
5090 -- distributions, we should ignore any "shipment has no distribution"
5091 -- errors.
5092 IF (l_doc_check_errors.message_name(i)
5093 NOT IN ('PO_SUB_SHIP_NO_DIST','PO_SUB_REL_SHIP_NO_DIST')) THEN
5094 add_error ( p_api_errors => g_api_errors,
5095 x_return_status => l_return_status,
5096 p_message_name => l_doc_check_errors.message_name(i),
5097 p_message_text => l_doc_check_errors.text_line(i),
5098 p_message_type => l_doc_check_errors.message_type(i) );
5099
5100 -- If the message is not a warning, set the return status to error.
5101 IF (NVL(l_doc_check_errors.message_type(i),'E') <> 'W') THEN
5102 x_return_status := FND_API.G_RET_STS_ERROR;
5103 END IF;
5104 END IF; -- l_doc_check_errors.message_name
5105 END LOOP; -- l_doc_check_errors
5106 END IF; -- l_return_status
5107 END IF; -- p_run_submission_checks
5108 END IF; --g_sec_qty_grade_only_chge_doc check sschinch 09/08/04 INVCONV
5109
5110 EXCEPTION
5111 WHEN FND_API.g_exc_unexpected_error THEN
5112 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
5113 p_proc_name => l_proc_name,
5114 p_progress => l_progress,
5115 p_add_to_msg_list => FALSE );
5116 RAISE FND_API.g_exc_unexpected_error;
5117 WHEN OTHERS THEN
5118 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
5119 p_proc_name => l_proc_name,
5120 p_progress => l_progress );
5121 RAISE FND_API.g_exc_unexpected_error;
5122 END validate_changes;
5123
5124 -------------------------------------------------------------------------------
5125 --Start of Comments
5126 --Name: validate_line_changes
5127 --Function:
5128 -- Performs field-level validations on the line changes.
5129 --Pre-reqs:
5130 -- None.
5131 --Modifies:
5132 -- None.
5133 --Locks:
5134 -- None.
5135 --End of Comments
5136 -------------------------------------------------------------------------------
5137 PROCEDURE validate_line_changes (
5138 p_chg IN PO_CHANGES_REC_TYPE,
5139 x_return_status OUT NOCOPY VARCHAR2
5140 ) IS
5141 l_proc_name CONSTANT VARCHAR2(30) := 'VALIDATE_LINE_CHANGES';
5142 l_progress VARCHAR2(3) := '000';
5143
5144 /* sschinch 09/08/04 begin INVCONV */
5145
5146 CURSOR Cur_val_grade(p_grade VARCHAR2) IS
5147 SELECT grade_code
5148 FROM mtl_grades
5149 WHERE grade_code = p_grade;
5150 /* sschinch 09/08/04 end INVCONV */
5151
5152 l_has_ga_ref PO_HEADERS.global_agreement_flag%TYPE;
5153 l_po_line_id PO_LINES.po_line_id%TYPE;
5154 l_new_qty PO_LINES.quantity%TYPE;
5155 l_qty_received PO_LINE_LOCATIONS.quantity_received%TYPE;
5156 l_qty_billed PO_LINE_LOCATIONS.quantity_billed%TYPE;
5157 l_amt_received PO_LINE_LOCATIONS.amount_received%TYPE;
5158 l_amt_billed PO_LINE_LOCATIONS.amount_billed%TYPE;
5159 l_new_price PO_LINES.unit_price%TYPE;
5160 l_current_price PO_LINES.unit_price%TYPE;
5161 l_new_start_date PO_LINES.start_date%TYPE;
5162 l_new_end_date PO_LINES.expiration_date%TYPE;
5163 l_new_amount PO_LINES.amount%TYPE;
5164 l_timecard_amount_sum PO_LINES.amount%TYPE;
5165 l_timecard_exists BOOLEAN;
5166 l_ship_count NUMBER;
5167 l_last_msg_list_index NUMBER;
5168 l_return_status VARCHAR2(1);
5169 l_price_updateable VARCHAR2(1);
5170 l_retroactive_price_change VARCHAR2(1);
5171 l_grade MTL_GRADES.grade_code%TYPE ; -- sschinch INVCONV
5172 l_new_preferred_grade MTL_GRADES.grade_code%TYPE; -- sschinch INVCONV
5173 l_advance_amount PO_LINE_LOCATIONS_ALL.AMOUNT%TYPE; /* << Complex work changes for R12 >> */
5174 BEGIN
5175 IF (g_fnd_debug = 'Y') THEN
5176 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
5177 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
5178 module => g_module_prefix || l_proc_name,
5179 message => 'Entering ' || l_proc_name );
5180 END IF;
5181 END IF;
5182
5183 x_return_status := FND_API.G_RET_STS_SUCCESS;
5184
5185 FOR i IN 1..p_chg.line_changes.get_count LOOP
5186 l_progress := '010';
5187 l_po_line_id := p_chg.line_changes.po_line_id(i);
5188 l_new_qty := p_chg.line_changes.quantity(i);
5189 l_new_price := p_chg.line_changes.unit_price(i);
5190 l_current_price := p_chg.line_changes.c_unit_price(i);
5191 l_has_ga_ref := p_chg.line_changes.c_has_ga_reference(i);
5192 l_new_start_date := p_chg.line_changes.start_date(i);
5193 l_new_end_date := p_chg.line_changes.expiration_date(i);
5194 l_new_amount := p_chg.line_changes.amount(i);
5195 l_new_preferred_grade := p_chg.line_changes.preferred_grade(i); -- sschinch INVCONV
5196
5197 /* << Complex work changes for R12 >> */
5198
5199 IF (g_is_complex_work_po=TRUE) then
5200
5201 BEGIN
5202
5203 select amount
5204 into l_advance_amount
5205 from po_line_locations_all
5206 where payment_type = 'ADVANCE'
5207 and po_line_id =l_po_line_id ;
5208
5209 EXCEPTION
5210 When others then
5211 l_advance_amount :=0;
5212 END;
5213
5214 END IF;
5215
5216
5217 --------------------------------------------------------------------------
5218 -- Check: For complex work Pos Line amount must be greater than or equal
5219 -- to the Advance amount.
5220 --------------------------------------------------------------------------
5221 l_progress := '015';
5222 /* << Complex work changes for R12 >> */
5223
5224 IF (g_is_complex_work_po=TRUE) then
5225
5226 if (l_new_amount < nvl(l_advance_amount,0)) THEN
5227 add_error ( p_api_errors => g_api_errors,
5228 x_return_status => x_return_status,
5229 p_message_name => 'PO_CHNG_AMT_LESS_ADV',
5230 --Line amount must be greater than or equal to the Advance amount.
5231 p_table_name => 'PO_LINES_ALL',
5232 p_entity_type => G_ENTITY_TYPE_LINES,
5233 p_entity_id => i );
5234 end if;
5235 END IF;
5236
5237
5238 --------------------------------------------------------------------------
5239 -- Check: Do not allow any changes to a line if it is cancelled or
5240 -- finally closed.
5241 --------------------------------------------------------------------------
5242 l_progress := '020';
5243 IF (p_chg.line_changes.c_cancel_flag(i) = 'Y')
5244 OR (p_chg.line_changes.c_closed_code(i) = 'FINALLY CLOSED') THEN
5245 add_error ( p_api_errors => g_api_errors,
5246 x_return_status => x_return_status,
5247 p_message_name => 'PO_CHNG_CANNOT_MODIFY_LINE',
5248 p_table_name => 'PO_LINES_ALL',
5249 p_entity_type => G_ENTITY_TYPE_LINES,
5250 p_entity_id => i );
5251 END IF;
5252
5253 --------------------------------------------------------------------------
5254 -- Check: If updating line quantity, the new quantity must be
5255 -- greater than or equal to the total quantity received of all
5256 -- shipments as well as the total quantity billed of all shipments.
5257 --------------------------------------------------------------------------
5258 l_progress := '030';
5259 IF (l_new_qty IS NOT NULL) THEN
5260
5261 /* << Complex work changes for R12 >> */
5262 IF (g_is_complex_work_po = FALSE) then
5263 -- SQL What: Retrieve the total quantity received and quantity billed
5264 -- of all the shipments of this line.
5265 SELECT SUM(NVL(quantity_received,0)),
5266 SUM(NVL(quantity_billed,0))
5267 INTO l_qty_received,
5268 l_qty_billed
5269 FROM po_line_locations
5270 WHERE po_line_id = l_po_line_id
5271 AND shipment_type IN ('STANDARD', 'PLANNED');
5272
5273 IF (l_new_qty < greatest(l_qty_received, l_qty_billed)) THEN
5274 add_error ( p_api_errors => g_api_errors,
5275 x_return_status => x_return_status,
5276 p_message_name => 'PO_CHNG_QTY_RESTRICTED',
5277 p_table_name => 'PO_LINES_ALL',
5278 p_column_name => 'QUANTITY',
5279 p_entity_type => G_ENTITY_TYPE_LINES,
5280 p_entity_id => i );
5281 END IF;
5282
5283 ELSE --<Complex work project for R12
5284
5285 SELECT Max(NVL(quantity_received,0)),
5286 Max(NVL(quantity_billed,0))
5287 INTO l_qty_received,
5288 l_qty_billed
5289 FROM po_line_locations
5290 WHERE po_line_id = l_po_line_id
5291 AND shipment_type IN ('STANDARD', 'PLANNED','PREPAYMENT');
5292
5293 IF (l_new_qty < greatest(l_qty_received, l_qty_billed)) THEN
5294 add_error ( p_api_errors => g_api_errors,
5295 x_return_status => x_return_status,
5296 p_message_name => 'PO_CHNG_QTY_RESTRICTED',
5297 p_table_name => 'PO_LINES_ALL',
5298 p_column_name => 'QUANTITY',
5299 p_entity_type => G_ENTITY_TYPE_LINES,
5300 p_entity_id => i );
5301 END IF;
5302 END IF;
5303
5304 /* << Complex work changes for R12 >> */
5305
5306 END IF; -- l_new_qty
5307
5308 -- Bug 3312906 START
5309 --------------------------------------------------------------------------
5310 -- Check: If there is a Standard PO price change, call an API to
5311 -- determine whether price updates are allowed for this line.
5312 --------------------------------------------------------------------------
5313 l_progress := '040';
5314 IF (g_document_type = 'PO') AND (g_document_subtype='STANDARD')
5315 AND (l_new_price <> l_current_price) THEN
5316
5317 l_last_msg_list_index := FND_MSG_PUB.count_msg;
5318
5319 PO_DOCUMENT_CHECKS_GRP.check_std_po_price_updateable (
5320 p_api_version => 1.0,
5321 x_return_status => l_return_status,
5322 p_po_line_id => l_po_line_id,
5323 p_from_price_break => p_chg.line_changes.t_from_price_break(i),
5324 p_add_reasons_to_msg_list => G_PARAMETER_YES,
5325 x_price_updateable => l_price_updateable,
5326 x_retroactive_price_change => l_retroactive_price_change
5327 );
5328
5329 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5330 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
5331 END IF;
5332
5333 -- If price updates are not allowed, add the error messages to the
5334 -- API errors object.
5335 IF (l_price_updateable = G_PARAMETER_NO) THEN
5336 add_message_list_errors (
5337 p_api_errors => g_api_errors,
5338 x_return_status => x_return_status,
5339 p_start_index => l_last_msg_list_index + 1,
5340 p_entity_type => G_ENTITY_TYPE_LINES,
5341 p_entity_id => i
5342 );
5343 END IF;
5344
5345 IF (l_retroactive_price_change = G_PARAMETER_YES) THEN
5346 -- Remember that this is a retroactive price change.
5347 g_retroactive_price_change := G_PARAMETER_YES;
5348 PO_LINES_SV2.retroactive_change(l_po_line_id);
5349 END IF;
5350
5351 END IF; -- document type is standard PO
5352 -- Bug 3312906 END
5353
5354 --------------------------------------------------------------------------
5355 -- Check: (Services) Validate that the start date is not later than
5356 -- the end date.
5357 --------------------------------------------------------------------------
5358 l_progress := '060';
5359 IF ((l_new_start_date IS NOT NULL) OR (l_new_end_date IS NOT NULL))
5360 AND (NVL(l_new_start_date, p_chg.line_changes.c_start_date(i))
5361 > NVL(l_new_end_date, p_chg.line_changes.c_expiration_date(i))) THEN
5362
5363 add_error ( p_api_errors => g_api_errors,
5364 x_return_status => x_return_status,
5365 p_message_name => 'PO_SVC_END_GE_START',
5366 p_table_name => 'PO_LINES_ALL',
5367 p_entity_type => G_ENTITY_TYPE_LINES,
5368 p_entity_id => i );
5369 END IF;
5370
5371 --------------------------------------------------------------------------
5372 -- Services Check: If updating line amt , the new amt must be
5373 -- greater than or equal to the total amount received of all
5374 -- shipments as well as the total amount billed of all shipments.
5375 -- Bug 3524527
5376 --------------------------------------------------------------------------
5377 l_progress := '030';
5378 IF (l_new_amount IS NOT NULL) THEN
5379
5380 IF (g_is_complex_work_po=TRUE) AND (g_is_financing_po=TRUE) then --<Complex work project for R12
5381
5382 -- SQL What: Retrieve the total amt received and amt billed
5383 -- of all the shipments of this line.
5384 SELECT SUM(NVL(amount_received,0)),
5385 SUM(NVL(amount_billed,0))
5386 INTO l_amt_received,
5387 l_amt_billed
5388 FROM po_line_locations
5389 WHERE po_line_id = l_po_line_id
5390 AND shipment_type = 'PREPAYMENT';
5391
5392 IF (l_new_amount < greatest(l_amt_received, l_amt_billed)) THEN
5393 add_error ( p_api_errors => g_api_errors,
5394 x_return_status => x_return_status,
5395 p_message_name => 'PO_CHNG_AMT_RESTRICTED',
5396 p_table_name => 'PO_LINES_ALL',
5397 p_column_name => 'AMOUNT',
5398 p_entity_type => G_ENTITY_TYPE_LINES,
5399 p_entity_id => i );
5400 END IF;
5401
5402
5403
5404 ELSE
5405 -- SQL What: Retrieve the total amt received and amt billed
5406 -- of all the shipments of this line.
5407 SELECT SUM(NVL(amount_received,0)),
5408 SUM(NVL(amount_billed,0))
5409 INTO l_amt_received,
5410 l_amt_billed
5411 FROM po_line_locations
5412 WHERE po_line_id = l_po_line_id
5413 AND shipment_type = 'STANDARD';
5414
5415 IF (l_new_amount < greatest(l_amt_received, l_amt_billed)) THEN
5416 add_error ( p_api_errors => g_api_errors,
5417 x_return_status => x_return_status,
5418 p_message_name => 'PO_CHNG_AMT_RESTRICTED',
5419 p_table_name => 'PO_LINES_ALL',
5420 p_column_name => 'AMOUNT',
5421 p_entity_type => G_ENTITY_TYPE_LINES,
5422 p_entity_id => i );
5423 END IF;
5424 END IF;--Complex Work PO <Complex work project for R12
5425
5426 END IF; -- l_new_amount
5427
5428 -- <SERVICES OTL FPJ START>
5429 l_progress := '200';
5430 --------------------------------------------------------------------------
5431 -- (Services) Perform OTL-related checks for Rate-Based Temp Labor lines
5432 -- on standard POs.
5433 --------------------------------------------------------------------------
5434 IF (g_document_type = 'PO') AND (g_document_subtype = 'STANDARD')
5435 AND (p_chg.line_changes.c_value_basis(i) = 'RATE')
5436 AND (p_chg.line_changes.c_purchase_basis(i) = 'TEMP LABOR') THEN
5437
5438 l_progress := '210';
5439 ------------------------------------------------------------------------
5440 -- OTL Check: Do not allow changes in price or price differentials if
5441 -- there are submitted/approved timecards for the line.
5442 ------------------------------------------------------------------------
5443 IF ((l_new_price <> l_current_price)
5444 OR (p_chg.line_changes.t_from_line_location_id(i)
5445 <> p_chg.line_changes.c_from_line_location_id(i))) THEN
5446
5447 -- Bug 3537441 Call the new interface package.
5448 PO_HXC_INTERFACE_PVT.check_timecard_exists (
5449 p_api_version => 1.0,
5450 x_return_status => l_return_status,
5451 p_field_name => PO_HXC_INTERFACE_PVT.g_field_PO_LINE_ID,
5452 p_field_value => l_po_line_id,
5453 p_end_date => NULL,
5454 x_timecard_exists => l_timecard_exists
5455 );
5456 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5457 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
5458 END IF;
5459
5460 IF (l_timecard_exists) THEN
5461 add_error ( p_api_errors => g_api_errors,
5462 x_return_status => x_return_status,
5463 p_message_name => 'PO_CHNG_OTL_NO_PRICE_CHANGE',
5464 p_table_name => 'PO_LINES_ALL',
5465 p_column_name => 'UNIT_PRICE',
5466 p_entity_type => G_ENTITY_TYPE_LINES,
5467 p_entity_id => i );
5468 END IF; -- l_timecard_exists
5469
5470 END IF; -- l_new_price
5471
5472 l_progress := '220';
5473 ------------------------------------------------------------------------
5474 -- OTL Check: Do not allow the amount to be decreased below the sum of
5475 -- all timecard amounts.
5476 ------------------------------------------------------------------------
5477 IF (l_new_amount IS NOT NULL) THEN
5478
5479 -- Bug 3537441 Call the new interface package.
5480 PO_HXC_INTERFACE_PVT.get_timecard_amount (
5481 p_api_version => 1.0,
5482 x_return_status => l_return_status,
5483 p_po_line_id => l_po_line_id,
5484 x_amount => l_timecard_amount_sum
5485 );
5486 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5487 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
5488 END IF;
5489
5490 IF (l_new_amount < l_timecard_amount_sum) THEN
5491 add_error ( p_api_errors => g_api_errors,
5492 x_return_status => x_return_status,
5493 p_message_name => 'PO_CHNG_OTL_INVALID_AMOUNT',
5494 p_table_name => 'PO_LINES_ALL',
5495 p_column_name => 'AMOUNT',
5496 -- PBWC Message Change Impact: Adding a token.
5497 p_token_name1 => 'TOTAL_AMT',
5498 p_token_value1 => to_char(l_timecard_amount_sum),
5499 p_entity_type => G_ENTITY_TYPE_LINES,
5500 p_entity_id => i );
5501 END IF;
5502
5503 END IF; -- l_new_amount
5504
5505 l_progress := '230';
5506 ------------------------------------------------------------------------
5507 -- OTL Check: The assignment end date must be after the
5508 -- latest end date on submitted/approved timecards.
5509 ------------------------------------------------------------------------
5510 IF (l_new_end_date IS NOT NULL) THEN
5511
5512 -- Bug 3537441 Call the new interface package.
5513 PO_HXC_INTERFACE_PVT.check_timecard_exists (
5514 p_api_version => 1.0,
5515 x_return_status => l_return_status,
5516 p_field_name => PO_HXC_INTERFACE_PVT.g_field_PO_LINE_ID,
5517 p_field_value => l_po_line_id,
5518 p_end_date => l_new_end_date,
5519 x_timecard_exists => l_timecard_exists
5520 );
5521 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5522 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
5523 END IF;
5524
5525 IF (l_timecard_exists) THEN
5526 add_error ( p_api_errors => g_api_errors,
5527 x_return_status => x_return_status,
5528 p_message_name => 'PO_CHNG_OTL_INVALID_END_DATE',
5529 p_table_name => 'PO_LINES_ALL',
5530 p_column_name => 'EXPIRATION_DATE',
5531 p_entity_type => G_ENTITY_TYPE_LINES,
5532 p_entity_id => i );
5533 END IF; -- l_timecard_exists
5534
5535 END IF; -- l_new_end_date
5536
5537 l_progress := '240';
5538 ------------------------------------------------------------------------
5539 -- OTL Check: The new assignment start date cannot be later than the
5540 -- old start date on a PO line with submitted/approved timecards.
5541 -- Bug 3559249
5542 ------------------------------------------------------------------------
5543 IF (l_new_start_date IS NOT NULL) THEN
5544
5545 PO_HXC_INTERFACE_PVT.check_timecard_exists (
5546 p_api_version => 1.0,
5547 x_return_status => l_return_status,
5548 p_field_name => PO_HXC_INTERFACE_PVT.g_field_PO_LINE_ID,
5549 p_field_value => l_po_line_id,
5550 p_end_date => null,
5551 x_timecard_exists => l_timecard_exists
5552 );
5553 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5554 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
5555 END IF;
5556
5557 IF (l_timecard_exists) and
5558 (l_new_start_date > p_chg.line_changes.c_start_date(i)) THEN
5559
5560 add_error ( p_api_errors => g_api_errors,
5561 x_return_status => x_return_status,
5562 p_message_name => 'PO_CHNG_OTL_INVALID_START_DATE',
5563 p_table_name => 'PO_LINES_ALL',
5564 p_column_name => 'START_DATE',
5565 p_entity_type => G_ENTITY_TYPE_LINES,
5566 p_entity_id => i );
5567
5568 END IF; -- l_timecard_exists and start dt greater
5569
5570 END IF; -- l_new_start_date
5571
5572 END IF; -- g_document_type
5573 -- <SERVICES OTL FPJ END>
5574
5575 --------------------------------------------------------------------------
5576 -- Deletion Checks:
5577 --------------------------------------------------------------------------
5578 l_progress := '500';
5579 IF (p_chg.line_changes.delete_record(i) = G_PARAMETER_YES) THEN
5580
5581 ------------------------------------------------------------------------
5582 -- Check: Prevent line deletion on blankets if the header has been
5583 -- approved at least once.
5584 ------------------------------------------------------------------------
5585 IF (g_document_type = 'PA') THEN
5586 IF (g_approved_date IS NOT NULL) THEN
5587 add_error ( p_api_errors => g_api_errors,
5588 x_return_status => x_return_status,
5589 p_message_name => 'PO_PO_USE_CANCEL_ON_APRVD_PO2',
5590 p_table_name => 'PO_LINES_ALL',
5591 p_column_name => NULL,
5592 p_entity_type => G_ENTITY_TYPE_LINES,
5593 p_entity_id => i);
5594 END IF;
5595
5596 ELSE -- g_document_type <> 'PA'
5597
5598 ----------------------------------------------------------------------
5599 -- Check: Prevent delete if the line has shipments that have been
5600 -- approved at least once.
5601 ----------------------------------------------------------------------
5602 SELECT count(*)
5603 INTO l_ship_count
5604 FROM po_line_locations
5605 WHERE po_line_id = l_po_line_id
5606 AND approved_date IS NOT NULL;
5607
5608 IF (l_ship_count > 0) THEN
5609 add_error ( p_api_errors => g_api_errors,
5610 x_return_status => x_return_status,
5611 p_message_name => 'PO_PO_USE_CANCEL_ON_APRVD_PO2',
5612 p_table_name => 'PO_LINES_ALL',
5613 p_column_name => NULL,
5614 p_entity_type => G_ENTITY_TYPE_LINES,
5615 p_entity_id => i);
5616 END IF;
5617
5618 ----------------------------------------------------------------------
5619 -- Check: Prevent delete if the line has encumbered shipments.
5620 ----------------------------------------------------------------------
5621 SELECT count(*)
5622 INTO l_ship_count
5623 FROM po_line_locations
5624 WHERE po_line_id = l_po_line_id
5625 AND encumbered_flag = 'Y';
5626
5627 IF (l_ship_count > 0) THEN
5628 add_error ( p_api_errors => g_api_errors,
5629 x_return_status => x_return_status,
5630 p_message_name => 'PO_PO_USE_CANCEL_ON_ENCUMB_PO',
5631 p_table_name => 'PO_LINES_ALL',
5632 p_column_name => NULL,
5633 p_entity_type => G_ENTITY_TYPE_LINES,
5634 p_entity_id => i);
5635 END IF;
5636 END IF; -- g_document_type
5637 END IF; -- l_delete_record
5638
5639
5640 IF (l_new_preferred_grade IS NOT NULL) THEN
5641 OPEN Cur_val_grade(l_new_preferred_grade);
5642 FETCH Cur_val_grade INTO l_grade;
5643 CLOSE Cur_val_grade;
5644 IF (l_grade IS NULL) THEN
5645 add_error ( p_api_errors => g_api_errors,
5646 x_return_status => x_return_status,
5647 p_message_name => 'INV_INVALID_GRADE_CODE',
5648 p_table_name => 'MTL_GRADES',
5649 p_column_name => NULL,
5650 p_entity_type => G_ENTITY_TYPE_LINES,
5651 p_entity_id => i );
5652 END IF;
5653 END IF;
5654 /* sschinch 09/08 end INVCONV */
5655
5656 END LOOP; -- line changes
5657
5658 EXCEPTION
5659 WHEN FND_API.g_exc_unexpected_error THEN
5660 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
5661 p_proc_name => l_proc_name,
5662 p_progress => l_progress,
5663 p_add_to_msg_list => FALSE );
5664 RAISE FND_API.g_exc_unexpected_error;
5665 WHEN OTHERS THEN
5666 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
5667 p_proc_name => l_proc_name,
5668 p_progress => l_progress );
5669 RAISE FND_API.g_exc_unexpected_error;
5670 END validate_line_changes;
5671
5672 -------------------------------------------------------------------------------
5673 --Start of Comments
5674 --Name: validate_shipment_changes
5675 --Function:
5676 -- Performs field-level validations on the shipment changes.
5677 --Pre-reqs:
5678 -- None.
5679 --Modifies:
5680 -- None.
5681 --Locks:
5682 -- None.
5683 --End of Comments
5684 -------------------------------------------------------------------------------
5685 PROCEDURE validate_shipment_changes (
5686 p_chg IN PO_CHANGES_REC_TYPE,
5687 x_return_status OUT NOCOPY VARCHAR2
5688 ) IS
5689
5690 /* sschinch 09/08/04 begin INVCONV */
5691
5692 CURSOR Cur_val_grade(p_grade VARCHAR2) IS
5693 SELECT grade_code
5694 FROM mtl_grades
5695 WHERE grade_code = p_grade;
5696 /* sschinch 09/08/04 end INVCONV */
5697
5698 l_proc_name CONSTANT VARCHAR2(30) := 'VALIDATE_SHIPMENT_CHANGES';
5699 l_progress VARCHAR2(3) := '000';
5700
5701 l_new_qty PO_LINE_LOCATIONS.quantity%TYPE;
5702 l_exist_qty PO_LINE_LOCATIONS.quantity%TYPE;
5703 l_planned_qty PO_LINE_LOCATIONS.quantity%TYPE;
5704 l_scheduled_qty PO_LINE_LOCATIONS.quantity%TYPE;
5705 l_available_qty PO_LINE_LOCATIONS.quantity%TYPE;
5706 l_new_price PO_LINE_LOCATIONS.price_override%TYPE;
5707 l_current_price PO_LINE_LOCATIONS.price_override%TYPE;
5708 l_new_amt PO_LINE_LOCATIONS.amount%TYPE;
5709 l_line_location_id PO_LINE_LOCATIONS.line_location_id%TYPE;
5710 l_parent_line_loc_id PO_LINE_LOCATIONS.line_location_id%TYPE;
5711 l_qty_received PO_LINE_LOCATIONS.quantity_received%TYPE;
5712 l_qty_billed PO_LINE_LOCATIONS.quantity_billed%TYPE;
5713 l_amt_received PO_LINE_LOCATIONS.amount_received%TYPE;
5714 l_amt_billed PO_LINE_LOCATIONS.amount_billed%TYPE;
5715 l_qty_shipped PO_LINE_LOCATIONS.quantity_shipped%TYPE;
5716 l_new_ship_to_loc_id PO_LINE_LOCATIONS.ship_to_location_id%TYPE;
5717 l_ship_to_org_id PO_LINE_LOCATIONS.ship_to_organization_id%TYPE;
5718 l_new_promised_date PO_LINE_LOCATIONS.need_by_date%TYPE;
5719 l_new_need_by_date PO_LINE_LOCATIONS.promised_date%TYPE;
5720 l_approved_date PO_LINE_LOCATIONS.approved_date%TYPE;
5721 l_encumbered_flag PO_LINE_LOCATIONS.encumbered_flag%TYPE;
5722 l_shipment_type PO_LINE_LOCATIONS.shipment_type%TYPE;
5723 l_pending_rcv_transactions NUMBER;
5724 l_allow_price_override PO_LINES.allow_price_override_flag%TYPE;
5725 l_ship_to_loc_valid NUMBER;
5726 l_message_name VARCHAR2(30);
5727 l_new_sales_order_update_date PO_LINE_LOCATIONS.sales_order_update_date%TYPE;
5728
5729 l_is_split_shipment BOOLEAN;
5730 l_is_drop_ship BOOLEAN;
5731 l_last_msg_list_index NUMBER;
5732 l_return_status VARCHAR2(1);
5733 l_price_updateable VARCHAR2(1);
5734 l_retroactive_price_change VARCHAR2(1);
5735
5736 l_grade MTL_GRADES.grade_code%TYPE ; -- sschinch INVCONV
5737 l_new_preferred_grade MTL_GRADES.grade_code%TYPE; -- INVCONV
5738 l_new_secondary_qty PO_LINE_LOCATIONS.SECONDARY_QUANTITY%TYPE; -- INVCONV
5739
5740 BEGIN
5741 IF (g_fnd_debug = 'Y') THEN
5742 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
5743 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
5744 module => g_module_prefix || l_proc_name,
5745 message => 'Entering ' || l_proc_name );
5746 END IF;
5747 END IF;
5748
5749 x_return_status := FND_API.G_RET_STS_SUCCESS;
5750
5751 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
5752 l_progress := '010';
5753 l_line_location_id := p_chg.shipment_changes.po_line_location_id(i);
5754 l_parent_line_loc_id := p_chg.shipment_changes.parent_line_location_id(i);
5755 l_new_qty := p_chg.shipment_changes.quantity(i);
5756 l_new_amt := p_chg.shipment_changes.amount(i);
5757 l_new_ship_to_loc_id := p_chg.shipment_changes.ship_to_location_id(i);
5758 l_qty_received := p_chg.shipment_changes.c_quantity_received(i);
5759 l_qty_billed := p_chg.shipment_changes.c_quantity_billed(i);
5760 l_amt_received := p_chg.shipment_changes.c_amount_received(i);
5761 l_amt_billed := p_chg.shipment_changes.c_amount_billed(i);
5762 l_qty_shipped := p_chg.shipment_changes.c_quantity_shipped(i);
5763 l_new_price := p_chg.shipment_changes.price_override(i);
5764 l_current_price := p_chg.shipment_changes.c_price_override(i);
5765 l_new_promised_date := p_chg.shipment_changes.promised_date(i);
5766 l_new_need_by_date := p_chg.shipment_changes.need_by_date(i);
5767 l_approved_date := p_chg.shipment_changes.c_approved_date(i);
5768 l_encumbered_flag := p_chg.shipment_changes.c_encumbered_flag(i);
5769 l_shipment_type := p_chg.shipment_changes.c_shipment_type(i);
5770 l_new_sales_order_update_date :=
5771 p_chg.shipment_changes.sales_order_update_date(i);
5772
5773 l_is_split_shipment := (l_parent_line_loc_id IS NOT NULL);
5774 l_is_drop_ship := (p_chg.shipment_changes.c_drop_ship_flag(i) = 'Y');
5775
5776 /* sschinch 09/08/04 BEGIN INVCONV */
5777 l_new_secondary_qty := p_chg.shipment_changes.secondary_quantity(i);
5778 l_new_preferred_grade := p_chg.shipment_changes.preferred_grade(i);
5779 /* sschinch 09/08/04 END INVCONV */
5780 --------------------------------------------------------------------------
5781 -- Check: Do not allow any changes to a shipment if it is cancelled or
5782 -- finally closed.
5783 --------------------------------------------------------------------------
5784 l_progress := '020';
5785 IF (p_chg.shipment_changes.c_cancel_flag(i) = 'Y')
5786 OR (p_chg.shipment_changes.c_closed_code(i) = 'FINALLY CLOSED') THEN
5787 add_error ( p_api_errors => g_api_errors,
5788 x_return_status => x_return_status,
5789 p_message_name => 'PO_CHNG_CANNOT_MODIFY_SHIPMENT',
5790 p_table_name => 'PO_LINE_LOCATIONS_ALL',
5791 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
5792 p_entity_id => i );
5793 END IF;
5794
5795 --------------------------------------------------------------------------
5796 -- Check: If updating shipment quantity, the new quantity must be
5797 -- greater than or equal to the quantity received as well as the
5798 -- quantity billed.
5799 --------------------------------------------------------------------------
5800 l_progress := '030';
5801 IF (g_document_type <> 'PA')
5802 AND (l_new_qty IS NOT NULL) AND (NOT l_is_split_shipment)
5803 AND (l_new_qty < greatest(l_qty_received, l_qty_billed)) THEN
5804
5805 add_error ( p_api_errors => g_api_errors,
5806 x_return_status => x_return_status,
5807 p_message_name => 'PO_CHNG_QTY_RESTRICTED',
5808 p_table_name => 'PO_LINE_LOCATIONS_ALL',
5809 p_column_name => 'QUANTITY',
5810 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
5811 p_entity_id => i );
5812 END IF; -- l_new_qty
5813
5814 --------------------------------------------------------------------------
5815 -- Services Check: If updating shipment amt, the new amt must be
5816 -- greater than or equal to the amount received as well as the
5817 -- amount billed. Bug 3524527
5818 --------------------------------------------------------------------------
5819 l_progress := '035';
5820 IF (g_document_type <> 'PA')
5821 AND (l_new_amt IS NOT NULL) AND (NOT l_is_split_shipment)
5822 AND (l_new_amt < greatest(l_amt_received, l_amt_billed)) THEN
5823
5824 add_error ( p_api_errors => g_api_errors,
5825 x_return_status => x_return_status,
5826 p_message_name => 'PO_CHNG_AMT_RESTRICTED',
5827 p_table_name => 'PO_LINE_LOCATIONS_ALL',
5828 p_column_name => 'AMOUNT',
5829 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
5830 p_entity_id => i );
5831 END IF; -- l_new_amt
5832
5833 -- Bug 3312906 START
5834 --------------------------------------------------------------------------
5835 -- Check: If there is a release price change, call an API to determine
5836 -- whether price updates are allowed for this shipment.
5837 --------------------------------------------------------------------------
5838 l_progress := '040';
5839 IF (g_document_type = 'RELEASE')
5840 AND (l_new_price <> l_current_price) AND (NOT l_is_split_shipment) THEN
5841
5842 l_last_msg_list_index := FND_MSG_PUB.count_msg;
5843
5844 PO_DOCUMENT_CHECKS_GRP.check_rel_price_updateable (
5845 p_api_version => 1.0,
5846 x_return_status => l_return_status,
5847 p_line_location_id => l_line_location_id,
5848 p_from_price_break => p_chg.shipment_changes.t_from_price_break(i),
5849 p_add_reasons_to_msg_list => G_PARAMETER_YES,
5850 x_price_updateable => l_price_updateable,
5851 x_retroactive_price_change => l_retroactive_price_change
5852 );
5853
5854 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5855 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
5856 END IF;
5857
5858 -- If price updates are not allowed, add the error messages to the
5859 -- API errors object.
5860 IF (l_price_updateable = G_PARAMETER_NO) THEN
5861 add_message_list_errors (
5862 p_api_errors => g_api_errors,
5863 x_return_status => x_return_status,
5864 p_start_index => l_last_msg_list_index + 1,
5865 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
5866 p_entity_id => i
5867 );
5868 END IF;
5869
5870 IF (l_retroactive_price_change = G_PARAMETER_YES) THEN
5871 -- Remember that this is a retroactive price change.
5872 g_retroactive_price_change := G_PARAMETER_YES;
5873 PO_LINES_SV2.retro_change_shipment(l_line_location_id);
5874 END IF;
5875
5876 END IF; -- document type is release
5877 -- Bug 3312906 END
5878
5879 --------------------------------------------------------------------------
5880 -- Check: For a planned PO, if updating the shipment quantity,
5881 -- the new quantity must be greater than or equal to the total released
5882 -- quantity.
5883 --------------------------------------------------------------------------
5884 l_progress := '050';
5885 IF (g_document_type = 'PO') AND (g_document_subtype = 'PLANNED')
5886 AND (l_new_qty IS NOT NULL) AND (NOT l_is_split_shipment) THEN
5887
5888 -- Get the total released quantity.
5889 l_scheduled_qty := PO_SHIPMENTS_SV1.get_sched_released_qty (
5890 x_source_id => l_line_location_id,
5891 x_entity_level => 'SHIPMENT',
5892 x_shipment_type => 'SCHEDULED' );
5893
5894 IF (l_new_qty < NVL(l_scheduled_qty, 0)) THEN
5895 add_error ( p_api_errors => g_api_errors,
5896 x_return_status => x_return_status,
5897 p_message_name => 'PO_PO_REL_EXCEEDS_QTY',
5898 p_table_name => 'PO_LINE_LOCATIONS_ALL',
5899 p_column_name => 'QUANTITY',
5900 p_token_name1 => 'SCHEDULED_QTY',
5901 p_token_value1 => TO_CHAR(l_scheduled_qty),
5902 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
5903 p_entity_id => i );
5904 END IF;
5905 END IF; -- document type is planned PO
5906
5907 --------------------------------------------------------------------------
5908 -- Check: For a scheduled release, if updating the shipment quantity,
5909 -- the new quantity must not cause the total released quantity
5910 -- to exceed the planned PO's quantity.
5911 --------------------------------------------------------------------------
5912 l_progress := '060';
5913 IF (g_document_type = 'RELEASE') AND (g_document_subtype='SCHEDULED')
5914 AND (l_new_qty IS NOT NULL) AND (NOT l_is_split_shipment) THEN
5915
5916 -- SQL What: Retrieve the quantity of the planned PO shipment for this
5917 -- release shipment.
5918 SELECT NVL(PLAN.quantity, 0) - NVL(PLAN.quantity_cancelled, 0)
5919 INTO l_planned_qty
5920 FROM po_line_locations REL, po_line_locations PLAN
5921 WHERE REL.line_location_id = l_line_location_id
5922 AND REL.source_shipment_id = PLAN.line_location_id; -- JOIN
5923
5924 -- Get the total released quantity.
5925 l_scheduled_qty := NVL( PO_SHIPMENTS_SV1.get_sched_released_qty (
5926 x_source_id => l_line_location_id,
5927 x_entity_level => 'SHIPMENT',
5928 x_shipment_type => 'SCHEDULED' ), 0);
5929
5930 -- Get the existing quantity on the given shipment.
5931 l_exist_qty := p_chg.shipment_changes.c_quantity(i);
5932
5933 -- Get the available quantity to be released, disregarding the
5934 -- given shipment.
5935 l_available_qty := l_planned_qty - (l_scheduled_qty - l_exist_qty);
5936
5937 IF l_new_qty > l_available_qty THEN
5938 add_error ( p_api_errors => g_api_errors,
5939 x_return_status => x_return_status,
5940 p_message_name => 'PO_PO_QTY_EXCEEDS_UNREL',
5941 p_table_name => 'PO_LINE_LOCATIONS_ALL',
5942 p_column_name => 'QUANTITY',
5943 p_token_name1 => 'UNRELEASED',
5944 p_token_value1 => TO_CHAR(l_available_qty),
5945 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
5946 p_entity_id => i );
5947 END IF;
5948 END IF; -- document type is scheduled release
5949
5950 --------------------------------------------------------------------------
5951 -- Check: Check that the document does not have a PCARD if there
5952 -- are changes to quantity, price, or amount.
5953 --------------------------------------------------------------------------
5954 --Bug 5188524: Need to remove these checks, since we allow modification of
5955 --pcard po from the enter po form. PM inputs in the bug
5956 /*l_progress := '070';
5957 IF (g_pcard_id IS NOT NULL)
5958 AND ((l_new_qty IS NOT NULL) OR
5959 (l_new_price IS NOT NULL) OR
5960 (l_new_amt IS NOT NULL) ) THEN
5961
5962 add_error ( p_api_errors => g_api_errors,
5963 x_return_status => x_return_status,
5964 p_message_name => 'PO_CHNG_PCARD_RESTRICTED',
5965 p_table_name => 'PO_HEADERS_ALL',
5966 p_column_name => 'PCARD_ID',
5967 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
5968 p_entity_id => i );
5969 END IF; -- new quantity, new price, and PCARD*/
5970
5971 --------------------------------------------------------------------------
5972 -- Check: If the shipment is linked to a drop ship sales order and
5973 -- update source is not 'OM', prevent quantity, amount, and split shipment
5974 -- changes.
5975 --------------------------------------------------------------------------
5976 l_progress := '080';
5977 -- add secondary quantity and grade too sschinch INVCONV
5978 IF (l_is_drop_ship)
5979 AND (NVL(g_update_source,'DEFAULT') <> G_UPDATE_SOURCE_OM)
5980 AND ((l_new_qty IS NOT NULL) OR (l_new_amt is NOT NULL)
5981 OR (l_is_split_shipment)OR
5982 (l_new_secondary_qty IS NOT NULL) OR (l_new_preferred_grade IS NOT NULL)) THEN -- sschinch INVCONV
5983
5984 add_error ( p_api_errors => g_api_errors,
5985 x_return_status => x_return_status,
5986 p_message_name => 'PO_CHNG_CANNOT_MODIFY_DROPSHIP',
5987 p_table_name => 'PO_LINE_LOCATIONS_ALL',
5988 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
5989 p_entity_id => i );
5990 END IF; -- shipment is drop ship
5991
5992 /* sschinch 09/08 begin INVCONV */
5993 --------------------------------------------------------------------
5994 -- Check: add check for preferred grade too
5995 --------------------------------------------------------------------
5996 l_progress := '081';
5997
5998 IF (l_new_preferred_grade IS NOT NULL) THEN
5999 OPEN Cur_val_grade(l_new_preferred_grade);
6000 FETCH Cur_val_grade INTO l_grade;
6001 CLOSE Cur_val_grade;
6002 IF (l_grade IS NULL) THEN
6003 add_error ( p_api_errors => g_api_errors,
6004 x_return_status => x_return_status,
6005 p_message_name => 'INV_INVALID_GRADE_CODE',
6006 p_table_name => 'MTL_GRADES',
6007 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
6008 p_entity_id => i );
6009 END IF;
6010 END IF;
6011
6012 /* sschinch 09/08 end INVCONV */
6013
6014 --------------------------------------------------------------------------
6015 -- Check: If updating ship-to location, check that it is valid.
6016 -- For a non-drop-ship shipment, check that the new location is a valid
6017 -- internal location.
6018 -- For a drop ship shipment, check that the new location is a valid
6019 -- customer location.
6020 --------------------------------------------------------------------------
6021 l_progress := '090';
6022 IF (l_new_ship_to_loc_id IS NOT NULL) THEN
6023
6024 IF (NOT l_is_drop_ship) THEN
6025 -- Note: The following query is adapted from the ship-to location LOV
6026 -- (SHIP_TO_LOCATIONS_ALL record group) in the Enter PO/Release forms.
6027 l_ship_to_org_id :=
6028 NVL(p_chg.shipment_changes.c_ship_to_organization_id(i),-1);
6029
6030 -- SQL What: Returns 1 if the given is a valid internal ship-to
6031 -- location, 0 otherwise.
6032 SELECT count(*)
6033 INTO l_ship_to_loc_valid
6034 FROM hr_locations_all loc
6035 WHERE loc.location_id = l_new_ship_to_loc_id
6036 AND NVL(loc.business_group_id, g_business_group_id )
6037 = g_business_group_id
6038 AND loc.ship_to_site_flag = 'Y'
6039 AND NVL(loc.inventory_organization_id, l_ship_to_org_id)
6040 = l_ship_to_org_id
6041 AND sysdate < NVL(loc.inactive_date, sysdate+1);
6042
6043 ELSE -- drop ship
6044 -- Note: The following query is adapted from the ship-to location LOV
6045 -- (SHIP_TO_LOCATION_CUST record group) in the Enter PO/Release forms.
6046
6047 -- SQL What: Return 1 if the given is a valid customer ship-to
6048 -- location, 0 otherwise.
6049 /* SELECT count(*)
6050 INTO l_ship_to_loc_valid
6051 FROM hz_locations hz,
6052 hz_party_sites ps,
6053 hz_cust_site_uses_all su,
6054 hz_cust_acct_sites_all asa,
6055 hz_cust_accounts cu,
6056 oe_order_lines_all oel,
6057 oe_drop_ship_sources oedp
6058 WHERE hz.location_id = l_new_ship_to_loc_id
6059 AND oedp.line_location_id = l_line_location_id
6060 AND oedp.line_id = oel.line_id -- JOIN
6061 AND oel.sold_to_org_id = cu.party_id -- JOIN
6062 AND cu.cust_account_id = asa.cust_account_id -- JOIN
6063 AND asa.cust_acct_site_id = su.cust_acct_site_id -- JOIN
6064 AND su.site_use_code = 'SHIP_TO'
6065 AND asa.party_site_id = ps.party_site_id -- JOIN
6066 AND ps.location_id = hz.location_id; -- JOIN */
6067
6068 -- bug 6401009: changed the validation sql as under,
6069 -- after recommendationsfrom OM
6070
6071 SELECT count(*)
6072 into l_ship_to_loc_valid
6073 FROM hz_cust_site_uses_all site,
6074 hz_party_sites party_site,
6075 hz_locations loc,
6076 hz_cust_acct_sites_all acct_site ,
6077 oe_order_lines_all oel,
6078 oe_drop_ship_sources oedp
6079 WHERE oedp.line_location_id = l_line_location_id
6080 AND loc.location_id = l_new_ship_to_loc_id
6081 AND site.site_use_code = 'SHIP_TO'
6082 AND site.cust_acct_site_id = acct_site.cust_acct_site_id
6083 AND acct_site.party_site_id = party_site.party_site_id
6084 AND party_site.location_id = loc.location_id
6085 AND acct_site.cust_account_id = oel.sold_to_org_id
6086 AND oedp.line_id = oel.line_id
6087 AND site.status ='A'
6088 AND acct_site.status ='A' ;
6089
6090 --bug #6401009 added the below sql to validate ship_to location for related customer also.
6091 /* bug 6401009 in the below sql changed the hz_custacct_relate view to table by adding _all to it
6092 so that this sql cares for across OU validation of ship to location for related customer */
6093 IF (l_ship_to_loc_valid = 0) THEN
6094 SELECT Count(*)
6095 INTO l_ship_to_loc_valid
6096 FROM hz_cust_site_uses_all site,
6097 hz_party_sites party_site,
6098 hz_locations loc,
6099 hz_cust_acct_sites_all acct_site ,
6100 oe_order_lines_all oel,
6101 oe_drop_ship_sources oedp,
6102 hz_cust_acct_relate_all rel
6103 WHERE oedp.line_location_id = l_line_location_id
6104 AND loc.location_id = l_new_ship_to_loc_id
6105 AND site.site_use_code = 'SHIP_TO'
6106 AND site.cust_acct_site_id = acct_site.cust_acct_site_id
6107 AND acct_site.party_site_id = party_site.party_site_id
6108 AND party_site.location_id = loc.location_id
6109 AND acct_site.cust_account_id = rel.cust_account_id --bug 6401009
6110 AND rel.related_cust_account_id = oel.sold_to_org_id --bug 6401009
6111 AND rel.ship_to_flag = 'Y'
6112 AND rel.status = 'A'
6113 AND rel.org_id = acct_site.org_id
6114 AND oedp.line_id = oel.line_id
6115 AND site.status ='A'
6116 AND acct_site.status ='A' ;
6117
6118 END IF;
6119
6120 END IF; -- shipment is not drop ship
6121
6122 IF (l_ship_to_loc_valid = 0) THEN
6123 add_error ( p_api_errors => g_api_errors,
6124 x_return_status => x_return_status,
6125 p_message_name => 'PO_PO_SHIP_LOCN_INVALID',
6126 p_table_name => 'PO_LINE_LOCATIONS_ALL',
6127 p_column_name => 'SHIP_TO_LOCATION_ID',
6128 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
6129 p_entity_id => i );
6130 END IF;
6131 END IF; -- new ship-to location
6132
6133 --------------------------------------------------------------------------
6134 -- Check: For drop shipments, do not allow changes to Need-by Date,
6135 -- Ship-to Location, or Sales Order update date if the PO shipment has
6136 -- any received or shipped quantity.
6137 --------------------------------------------------------------------------
6138 l_progress := '110';
6139 IF (l_is_drop_ship) AND ((l_qty_received > 0) OR (l_qty_shipped > 0)) THEN
6140
6141 IF (l_new_need_by_date IS NOT NULL) THEN
6142 add_error ( p_api_errors => g_api_errors,
6143 x_return_status => x_return_status,
6144 p_message_name => 'PO_CHNG_DROPSHIP_RCV_SHIP_QTY',
6145 p_table_name => 'PO_LINE_LOCATIONS_ALL',
6146 p_column_name => 'NEED_BY_DATE',
6147 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
6148 p_entity_id => i );
6149 END IF;
6150
6151 IF (l_new_ship_to_loc_id IS NOT NULL) THEN
6152 add_error ( p_api_errors => g_api_errors,
6153 x_return_status => x_return_status,
6154 p_message_name => 'PO_CHNG_DROPSHIP_RCV_SHIP_QTY',
6155 p_table_name => 'PO_LINE_LOCATIONS_ALL',
6156 p_column_name => 'SHIP_TO_LOCATION',
6157 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
6158 p_entity_id => i );
6159 END IF;
6160
6161 IF (l_new_sales_order_update_date IS NOT NULL) THEN
6162 add_error ( p_api_errors => g_api_errors,
6163 x_return_status => x_return_status,
6164 p_message_name => 'PO_CHNG_DROPSHIP_RCV_SHIP_QTY',
6165 p_table_name => 'PO_LINE_LOCATIONS_ALL',
6166 p_column_name => 'SALES_ORDER_UPDATE_DATE',
6167 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
6168 p_entity_id => i );
6169 END IF;
6170
6171 END IF; -- l_is_drop_ship
6172
6173 --------------------------------------------------------------------------
6174 -- Deletion Checks:
6175 --------------------------------------------------------------------------
6176 l_progress := '500';
6177 IF (p_chg.shipment_changes.delete_record(i) = G_PARAMETER_YES) THEN
6178
6179 ------------------------------------------------------------------------
6180 -- Check: Prevent delete if the shipment has been approved at least once.
6181 ------------------------------------------------------------------------
6182 IF (l_approved_date IS NOT NULL) THEN
6183 IF (l_shipment_type = 'PRICE BREAK') THEN
6184 l_message_name := 'PO_CANT_DELETE_PB_ON_APRVD_PO';
6185 ELSE
6186 l_message_name := 'PO_PO_USE_CANCEL_ON_APRVD_PO2';
6187 END IF;
6188
6189 add_error ( p_api_errors => g_api_errors,
6190 x_return_status => x_return_status,
6191 p_message_name => l_message_name,
6192 p_table_name => 'PO_LINE_LOCATIONS_ALL',
6193 p_column_name => NULL,
6194 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
6195 p_entity_id => i);
6196 END IF;
6197
6198 ------------------------------------------------------------------------
6199 -- Check: Prevent delete if the shipment is encumbered.
6200 ------------------------------------------------------------------------
6201 IF (l_encumbered_flag = 'Y') THEN
6202 add_error ( p_api_errors => g_api_errors,
6203 x_return_status => x_return_status,
6204 p_message_name => 'PO_PO_USE_CANCEL_ON_ENCUMB_PO',
6205 p_table_name => 'PO_LINE_LOCATIONS_ALL',
6206 p_column_name => NULL,
6207 p_entity_type => G_ENTITY_TYPE_SHIPMENTS,
6208 p_entity_id => i);
6209 END IF;
6210 END IF; -- l_delete_record
6211
6212
6213
6214
6215 END LOOP; -- shipment changes
6216
6217 EXCEPTION
6218 WHEN FND_API.g_exc_unexpected_error THEN
6219 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
6220 p_proc_name => l_proc_name,
6221 p_progress => l_progress,
6222 p_add_to_msg_list => FALSE );
6223 RAISE FND_API.g_exc_unexpected_error;
6224 WHEN OTHERS THEN
6225 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
6226 p_proc_name => l_proc_name,
6227 p_progress => l_progress );
6228 RAISE FND_API.g_exc_unexpected_error;
6229 END validate_shipment_changes;
6230
6231 -------------------------------------------------------------------------------
6232 --Start of Comments
6233 --Name: validate_distribution_changes
6234 --Function:
6235 -- Performs field-level validations on the distribution changes.
6236 --Pre-reqs:
6237 -- None.
6238 --Modifies:
6239 -- None.
6240 --Locks:
6241 -- None.
6242 --End of Comments
6243 -------------------------------------------------------------------------------
6244 PROCEDURE validate_distribution_changes (
6245 p_chg IN PO_CHANGES_REC_TYPE,
6246 x_return_status OUT NOCOPY VARCHAR2
6247 ) IS
6248 l_proc_name CONSTANT VARCHAR2(30) := 'VALIDATE_DISTRIBUTION_CHANGES';
6249 l_progress VARCHAR2(3) := '000';
6250
6251 l_new_qty PO_DISTRIBUTIONS.quantity_ordered%TYPE;
6252 l_new_amt PO_DISTRIBUTIONS.amount_ordered%TYPE;
6253 l_qty_delivered PO_DISTRIBUTIONS.quantity_delivered%TYPE;
6254 l_qty_billed PO_DISTRIBUTIONS.quantity_billed%TYPE;
6255 l_amt_delivered PO_DISTRIBUTIONS.amount_delivered%TYPE;
6256 l_amt_billed PO_DISTRIBUTIONS.amount_billed%TYPE;
6257
6258 l_is_split_distribution BOOLEAN;
6259 BEGIN
6260 IF (g_fnd_debug = 'Y') THEN
6261 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
6262 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
6263 module => g_module_prefix || l_proc_name,
6264 message => 'Entering ' || l_proc_name );
6265 END IF;
6266 END IF;
6267
6268 x_return_status := FND_API.G_RET_STS_SUCCESS;
6269
6270 FOR i IN 1..p_chg.distribution_changes.get_count LOOP
6271 l_progress := '010';
6272 l_new_qty := p_chg.distribution_changes.quantity_ordered(i);
6273 l_new_amt := p_chg.distribution_changes.amount_ordered(i);
6274 l_amt_delivered := p_chg.distribution_changes.c_amount_delivered(i);
6275 l_amt_billed := p_chg.distribution_changes.c_amount_billed(i);
6276 l_is_split_distribution :=
6277 (p_chg.distribution_changes.parent_distribution_id(i) IS NOT NULL);
6278 l_qty_delivered := p_chg.distribution_changes.c_quantity_delivered(i);
6279 l_qty_billed := p_chg.distribution_changes.c_quantity_billed(i);
6280
6281 --------------------------------------------------------------------------
6282 -- Check: If updating distribution quantity, the new quantity must be
6283 -- greater than or equal to the quantity delivered as well as the
6284 -- quantity billed.
6285 --------------------------------------------------------------------------
6286 l_progress := '020';
6287 IF (l_new_qty IS NOT NULL) AND (NOT l_is_split_distribution)
6288 AND (l_new_qty < greatest(l_qty_delivered, l_qty_billed)) THEN
6289
6290 add_error ( p_api_errors => g_api_errors,
6291 x_return_status => x_return_status,
6292 p_message_name => 'PO_CHNG_QTY_RESTRICTED',
6293 p_table_name => 'PO_DISTRIBUTIONS_ALL',
6294 p_column_name => 'QUANTITY_ORDERED',
6295 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
6296 p_entity_id => i );
6297 END IF; -- l_new_qty
6298
6299 --------------------------------------------------------------------------
6300 -- Check: If updating distribution amount, the new amount must be
6301 -- greater than or equal to the amount delivered as well as the
6302 -- amount billed.Bug 3524527
6303 --------------------------------------------------------------------------
6304 l_progress := '020';
6305 IF (l_new_amt IS NOT NULL) AND (NOT l_is_split_distribution)
6306 AND (l_new_amt < greatest(l_amt_delivered, l_amt_billed)) THEN
6307
6308 add_error ( p_api_errors => g_api_errors,
6309 x_return_status => x_return_status,
6310 p_message_name => 'PO_CHNG_AMT_RESTRICTED',
6311 p_table_name => 'PO_DISTRIBUTIONS_ALL',
6312 p_column_name => 'AMOUNT_ORDERED',
6313 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
6314 p_entity_id => i );
6315 END IF; -- l_new_amt
6316
6317 --------------------------------------------------------------------------
6318 -- Deletion Checks:
6319 --------------------------------------------------------------------------
6320 l_progress := '500';
6321 IF (p_chg.distribution_changes.delete_record(i) = G_PARAMETER_YES) THEN
6322
6323 ------------------------------------------------------------------------
6324 -- Check: Prevent delete if the distribution was created before the
6325 -- last PO approval date.
6326 ------------------------------------------------------------------------
6327 IF (p_chg.distribution_changes.c_creation_date(i) <= g_approved_date) THEN
6328 add_error ( p_api_errors => g_api_errors,
6329 x_return_status => x_return_status,
6330 p_message_name => 'PO_CANT_DELETE_PB_ON_APRVD_PO',
6331 p_table_name => 'PO_DISTRIBUTIONS_ALL',
6332 p_column_name => NULL,
6333 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
6334 p_entity_id => i);
6335 END IF;
6336
6337 ------------------------------------------------------------------------
6338 -- Check: Prevent delete if the distribution is linked to a requisition.
6339 ------------------------------------------------------------------------
6340 IF (p_chg.distribution_changes.c_req_distribution_id(i) IS NOT NULL) THEN
6341 add_error ( p_api_errors => g_api_errors,
6342 x_return_status => x_return_status,
6343 p_message_name => 'PO_PO_DEL_DIST_ONLINE_REQ_NA',
6344 p_table_name => 'PO_DISTRIBUTIONS_ALL',
6345 p_column_name => NULL,
6346 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
6347 p_entity_id => i);
6348 END IF;
6349
6350 ------------------------------------------------------------------------
6351 -- Check: Prevent delete if the distribution is encumbered.
6352 ------------------------------------------------------------------------
6353 IF (p_chg.distribution_changes.c_encumbered_flag(i) = 'Y') THEN
6354 add_error ( p_api_errors => g_api_errors,
6355 x_return_status => x_return_status,
6356 p_message_name => 'PO_PO_USE_CANCEL_ON_ENCUMB_PO',
6357 p_table_name => 'PO_DISTRIBUTIONS_ALL',
6358 p_column_name => NULL,
6359 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
6360 p_entity_id => i);
6361 END IF;
6362
6363 ------------------------------------------------------------------------
6364 -- Check: Prevent delete if there is quantity or amt delivered.
6365 ------------------------------------------------------------------------
6366 IF (l_qty_delivered > 0) OR (l_amt_delivered > 0) THEN -- Bug 3524527
6367 add_error ( p_api_errors => g_api_errors,
6368 x_return_status => x_return_status,
6369 p_message_name => 'PO_PO_DELETE_DEL_DIST_NA',
6370 p_table_name => 'PO_DISTRIBUTIONS_ALL',
6371 p_column_name => NULL,
6372 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
6373 p_entity_id => i);
6374 END IF;
6375
6376 ------------------------------------------------------------------------
6377 -- Check: Prevent delete if there is quantity or amt billed.
6378 ------------------------------------------------------------------------
6379 IF (l_qty_billed > 0) OR (l_amt_billed > 0) THEN -- Bug 3524527
6380 add_error ( p_api_errors => g_api_errors,
6381 x_return_status => x_return_status,
6382 p_message_name => 'PO_PO_DELETE_DIST_BILLED_NA',
6383 p_table_name => 'PO_DISTRIBUTIONS_ALL',
6384 p_column_name => NULL,
6385 p_entity_type => G_ENTITY_TYPE_DISTRIBUTIONS,
6386 p_entity_id => i);
6387 END IF;
6388
6389 END IF; -- l_delete_record
6390
6391 END LOOP; -- distribution changes
6392
6393 EXCEPTION
6394 WHEN FND_API.g_exc_unexpected_error THEN
6395 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
6396 p_proc_name => l_proc_name,
6397 p_progress => l_progress,
6398 p_add_to_msg_list => FALSE );
6399 RAISE FND_API.g_exc_unexpected_error;
6400 WHEN OTHERS THEN
6401 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
6402 p_proc_name => l_proc_name,
6403 p_progress => l_progress );
6404 RAISE FND_API.g_exc_unexpected_error;
6405 END validate_distribution_changes;
6406
6407 -- Bug 3354712 START
6408 -------------------------------------------------------------------------------
6409 --Start of Comments
6410 --Name: unreserve_entity
6411 --Function:
6412 -- Unreserves the given PO line or release shipment.
6413 --Pre-reqs:
6414 -- Encumbrance is on.
6415 --Modifies:
6416 -- The line/shipment is unreserved.
6417 --Locks:
6418 -- None.
6419 --End of Comments
6420 -------------------------------------------------------------------------------
6421 PROCEDURE unreserve_entity
6422 ( p_doc_level IN VARCHAR2,
6423 p_doc_level_id IN NUMBER,
6424 p_override_date IN DATE,
6425 p_buyer_id IN PO_HEADERS.agent_id%TYPE,
6426 x_return_status OUT NOCOPY VARCHAR2
6427 ) IS
6428 l_proc_name CONSTANT VARCHAR2(30) := 'UNRESERVE';
6429 l_progress VARCHAR2(3) := '000';
6430
6431 l_return_status VARCHAR2(1);
6432 l_unreservable_flag VARCHAR2(1);
6433 l_online_report_id PO_ONLINE_REPORT_TEXT.online_report_id%TYPE;
6434 l_po_return_code VARCHAR2(10);
6435 l_enc_report_obj PO_FCOUT_TYPE;
6436 BEGIN
6437 IF (g_fnd_debug = 'Y') THEN
6438 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
6439 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
6440 module => g_module_prefix || l_proc_name,
6441 message => 'Entering ' || l_proc_name );
6442 END IF;
6443 END IF;
6444
6445 x_return_status := FND_API.G_RET_STS_SUCCESS;
6446
6447 -- Check whether this line/shipment is encumbered and needs to be unreserved.
6448 l_progress := '010';
6449 PO_DOCUMENT_FUNDS_PVT.is_unreservable (
6450 x_return_status => l_return_status,
6451 p_doc_type => g_document_type,
6452 p_doc_subtype => g_document_subtype,
6453 p_doc_level => p_doc_level,
6454 p_doc_level_id => p_doc_level_id,
6455 x_unreservable_flag => l_unreservable_flag
6456 );
6457 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6458 RAISE FND_API.g_exc_unexpected_error;
6459 END IF;
6460
6461 IF (NVL(l_unreservable_flag, PO_DOCUMENT_FUNDS_PVT.g_parameter_NO) <>
6462 PO_DOCUMENT_FUNDS_PVT.g_parameter_YES) THEN
6463 RETURN; -- Do not need to unreserve.
6464 END IF;
6465
6466 -- Unreserve the line/shipment.
6467 l_progress := '020';
6468 PO_DOCUMENT_FUNDS_PVT.do_unreserve (
6469 x_return_status => l_return_status,
6470 p_doc_type => g_document_type,
6471 p_doc_subtype => g_document_subtype,
6472 p_doc_level => p_doc_level,
6473 p_doc_level_id => p_doc_level_id,
6474 p_use_enc_gt_flag => PO_DOCUMENT_FUNDS_PVT.g_parameter_NO,
6475 p_validate_document => PO_DOCUMENT_FUNDS_PVT.g_parameter_YES,
6476 p_override_funds => PO_DOCUMENT_FUNDS_PVT.g_parameter_USE_PROFILE,
6477 p_use_gl_date => PO_DOCUMENT_FUNDS_PVT.g_parameter_USE_PROFILE,
6478 p_override_date => NVL(p_override_date, TRUNC(sysdate)),
6479 p_employee_id => NVL(p_buyer_id, g_agent_id),
6480 x_po_return_code => l_po_return_code,
6481 x_online_report_id => l_online_report_id
6482 );
6483 IF (g_fnd_debug = 'Y') THEN
6484 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
6485 FND_LOG.string( log_level => FND_LOG.LEVEL_EVENT,
6486 module => g_module_prefix || l_proc_name,
6487 message =>
6488 'Unreserve return_status: '||l_return_status
6489 ||', po_return_code: '||l_po_return_code );
6490 END IF;
6491 END IF;
6492
6493 IF (l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS,
6494 FND_API.G_RET_STS_ERROR) ) THEN
6495 RAISE FND_API.g_exc_unexpected_error;
6496 END IF;
6497
6498 -- If there were errors/warnings, copy them to the API errors object.
6499 l_progress := '030';
6500 IF (l_po_return_code <> PO_DOCUMENT_FUNDS_PVT.G_RETURN_SUCCESS) THEN
6501 PO_DOCUMENT_FUNDS_PVT.create_report_object (
6502 x_return_status => l_return_status,
6503 p_online_report_id => l_online_report_id,
6504 p_report_successes => PO_DOCUMENT_FUNDS_PVT.g_parameter_NO,
6505 x_report_object => l_enc_report_obj
6506 );
6507 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6508 RAISE FND_API.g_exc_unexpected_error;
6509 END IF;
6510
6511 FOR j IN 1..l_enc_report_obj.error_msg.count LOOP
6512 add_error ( p_api_errors => g_api_errors,
6513 x_return_status => l_return_status,
6514 p_message_name => NULL,
6515 p_message_text => l_enc_report_obj.error_msg(j),
6516 p_message_type => l_enc_report_obj.msg_type(j) );
6517 END LOOP;
6518
6519 IF (l_po_return_code <> PO_DOCUMENT_FUNDS_PVT.G_RETURN_WARNING) THEN
6520 x_return_status := FND_API.G_RET_STS_ERROR;
6521 END IF;
6522 END IF; -- l_po_return_code
6523
6524 IF (g_fnd_debug = 'Y') THEN
6525 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
6526 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
6527 module => g_module_prefix || l_proc_name,
6528 message => 'Exiting ' || l_proc_name );
6529 END IF;
6530 END IF;
6531 EXCEPTION
6532 WHEN FND_API.g_exc_unexpected_error THEN
6533 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
6534 p_proc_name => l_proc_name,
6535 p_progress => l_progress,
6536 p_add_to_msg_list => FALSE );
6537 RAISE FND_API.g_exc_unexpected_error;
6538 WHEN OTHERS THEN
6539 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
6540 p_proc_name => l_proc_name,
6541 p_progress => l_progress );
6542 RAISE FND_API.g_exc_unexpected_error;
6543 END unreserve_entity;
6544 -- Bug 3354712 END
6545
6546 -------------------------------------------------------------------------------
6547 --Start of Comments
6548 --Name: unreserve
6549 --Function:
6550 -- Unreserves the necessary PO lines or release shipments.
6551 --Pre-reqs:
6552 -- Encumbrance is on.
6553 --Modifies:
6554 -- The lines/shipments are unreserved.
6555 --Locks:
6556 -- None.
6557 --End of Comments
6558 -------------------------------------------------------------------------------
6559 PROCEDURE unreserve
6560 ( p_chg IN PO_CHANGES_REC_TYPE,
6561 p_override_date IN DATE,
6562 p_buyer_id IN PO_HEADERS.agent_id%TYPE,
6563 x_return_status OUT NOCOPY VARCHAR2
6564 ) IS
6565 l_proc_name CONSTANT VARCHAR2(30) := 'UNRESERVE';
6566 l_progress VARCHAR2(3) := '000';
6567
6568 l_return_status VARCHAR2(1);
6569 BEGIN
6570 IF (g_fnd_debug = 'Y') THEN
6571 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
6572 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
6573 module => g_module_prefix || l_proc_name,
6574 message => 'Entering ' || l_proc_name );
6575 END IF;
6576 END IF;
6577
6578 x_return_status := FND_API.G_RET_STS_SUCCESS;
6579
6580 -- For POs, unreserve the lines with quantity, price, or amount changes.
6581 IF (g_document_type = 'PO') THEN
6582 l_progress := '010';
6583
6584 FOR i IN 1..p_chg.line_changes.get_count LOOP
6585 IF ((p_chg.line_changes.quantity(i) IS NOT NULL)
6586 OR (p_chg.line_changes.unit_price(i) IS NOT NULL)
6587 OR (p_chg.line_changes.amount(i) IS NOT NULL)) THEN
6588
6589 -- Bug 3354712 START
6590 unreserve_entity (
6591 p_doc_level => PO_DOCUMENT_FUNDS_PVT.g_doc_level_LINE,
6592 p_doc_level_id => p_chg.line_changes.po_line_id(i),
6593 p_override_date => p_override_date,
6594 p_buyer_id => p_buyer_id,
6595 x_return_status => l_return_status
6596 );
6597
6598 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
6599 x_return_status := FND_API.G_RET_STS_ERROR;
6600 ELSIF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6601 RAISE FND_API.g_exc_unexpected_error;
6602 END IF;
6603 -- Bug 3354712 END
6604
6605 END IF; -- p_chg.line_changes.quantity
6606 END LOOP; -- line changes
6607
6608 -- Bug 3354712 START
6609 -- For releases, unreserve the non-split shipments with quantity, price,
6610 -- or amount changes.
6611 ELSIF (g_document_type = 'RELEASE') THEN
6612 l_progress := '020';
6613
6614 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
6615 IF (p_chg.shipment_changes.po_line_location_id(i) IS NOT NULL)
6616 AND ((p_chg.shipment_changes.quantity(i) IS NOT NULL)
6617 OR (p_chg.shipment_changes.price_override(i) IS NOT NULL)
6618 OR (p_chg.shipment_changes.amount(i) IS NOT NULL)) THEN
6619
6620 unreserve_entity (
6621 p_doc_level => PO_DOCUMENT_FUNDS_PVT.g_doc_level_SHIPMENT,
6622 p_doc_level_id => p_chg.shipment_changes.po_line_location_id(i),
6623 p_override_date => p_override_date,
6624 p_buyer_id => p_buyer_id,
6625 x_return_status => l_return_status
6626 );
6627
6628 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
6629 x_return_status := FND_API.G_RET_STS_ERROR;
6630 ELSIF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6631 RAISE FND_API.g_exc_unexpected_error;
6632 END IF;
6633
6634 END IF; -- p_chg.shipment_changes.po_line_location_id
6635 END LOOP; -- shipment changes
6636
6637 END IF; -- g_document_type = 'RELEASE'
6638 -- Bug 3354712 END
6639
6640 IF (g_fnd_debug = 'Y') THEN
6641 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
6642 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
6643 module => g_module_prefix || l_proc_name,
6644 message => 'Exiting ' || l_proc_name );
6645 END IF;
6646 END IF;
6647 EXCEPTION
6648 WHEN FND_API.g_exc_unexpected_error THEN
6649 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
6650 p_proc_name => l_proc_name,
6651 p_progress => l_progress,
6652 p_add_to_msg_list => FALSE );
6653 RAISE FND_API.g_exc_unexpected_error;
6654 WHEN OTHERS THEN
6655 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
6656 p_proc_name => l_proc_name,
6657 p_progress => l_progress );
6658 RAISE FND_API.g_exc_unexpected_error;
6659 END unreserve;
6660
6661 -------------------------------------------------------------------------------
6662 --Start of Comments
6663 --Name: apply_changes
6664 --Function:
6665 -- Applies the requested and derived changes to the database tables.
6666 --Pre-reqs:
6667 -- None.
6668 --Modifies:
6669 -- Updates PO_HEADERS_ALL, PO_RELEASES_ALL, PO_LINES_ALL,
6670 -- PO_LINE_LOCATIONS_ALL, PO_DISTRIBUTIONS_ALL with the changes.
6671 --Locks:
6672 -- None.
6673 --End of Comments
6674 -------------------------------------------------------------------------------
6675 PROCEDURE apply_changes (
6676 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
6677 p_override_date IN DATE,
6678 p_buyer_id IN PO_HEADERS.agent_id%TYPE,
6679 x_return_status OUT NOCOPY VARCHAR2
6680 ) IS
6681 l_proc_name CONSTANT VARCHAR2(30) := 'APPLY_CHANGES';
6682 l_progress VARCHAR2(3) := '000';
6683
6684 l_doc_encumbered NUMBER;
6685 l_return_status VARCHAR2(1);
6686 l_new_revision_num PO_HEADERS.revision_num%TYPE;
6687 l_acceptance_required_flag PO_HEADERS.acceptance_required_flag%TYPE := NULL;
6688 l_message VARCHAR2(50);
6689 l_new_from_line_loc_id PO_LINES.from_line_location_id%TYPE;
6690 l_ga_entity_type PO_PRICE_DIFFERENTIALS.entity_type%TYPE;
6691 l_ga_entity_id PO_PRICE_DIFFERENTIALS.entity_id%TYPE;
6692 l_po_entity_type PO_PRICE_DIFFERENTIALS.entity_type%TYPE;
6693 l_po_entity_id PO_PRICE_DIFFERENTIALS.entity_id%TYPE;
6694
6695 -- <HTML Agreement R12>
6696 l_new_auth_status PO_HEADERS_ALL.authorization_status%TYPE;
6697
6698 BEGIN
6699 IF (g_fnd_debug = 'Y') THEN
6700 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
6701 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
6702 module => g_module_prefix || l_proc_name,
6703 message => 'Entering ' || l_proc_name );
6704 END IF;
6705 END IF;
6706
6707 l_progress := '010';
6708 x_return_status := FND_API.G_RET_STS_SUCCESS;
6709
6710 -- For POs/releases, if encumbrance is on, unreserve before making changes.
6711 IF (g_document_type <> 'PA')
6712 AND (PO_CORE_S.is_encumbrance_on (
6713 p_doc_type => g_document_type,
6714 p_org_id => NULL )) THEN
6715
6716 unreserve ( p_chg, p_override_date, p_buyer_id, l_return_status );
6717 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6718 x_return_status := l_return_status;
6719 RETURN;
6720 END IF;
6721 END IF;
6722
6723 -- Create split shipments and their split distributions, if needed.
6724 l_progress := '020';
6725 IF (g_split_ship_changes_tbl.COUNT > 0) THEN -- there are split shipments
6726 create_split_shipments ( p_chg );
6727 END IF;
6728
6729 -- Apply the line changes to the database.
6730 l_progress := '030';
6731 FORALL i IN 1..p_chg.line_changes.get_count
6732 -- SQL What: Update PO_LINES with the requested/derived line changes.
6733 UPDATE po_lines
6734 SET last_update_date = sysdate,
6735 last_updated_by = g_user_id,
6736 request_id = decode(g_request_id,null,request_id,-1,request_id,g_request_id), /*bug 7278327, update the request_id with the concerned concurrent_request_id*/
6737 unit_price = nvl(p_chg.line_changes.unit_price(i), unit_price),
6738 -- <FPJ Advanced Price>
6739 base_unit_price = nvl(p_chg.line_changes.t_base_unit_price(i),
6740 base_unit_price),
6741
6742 vendor_product_num =
6743 nvl(p_chg.line_changes.vendor_product_num(i), vendor_product_num),
6744 quantity = nvl(p_chg.line_changes.quantity(i), quantity),
6745 start_date = nvl(p_chg.line_changes.start_date(i), start_date),
6746 expiration_date =
6747 nvl(p_chg.line_changes.expiration_date(i), expiration_date),
6748 amount = nvl(p_chg.line_changes.amount(i), amount),
6749 secondary_quantity =
6750 nvl(p_chg.line_changes.secondary_quantity(i), secondary_quantity),
6751
6752 -- t_from_line_location_id has the following meaning:
6753 -- NULL : no change
6754 -- G_NULL_NUM : Set from_line_location_id to NULL.
6755 -- any other value: Set from_line_location_id to that value.
6756 from_line_location_id =
6757 decode ( p_chg.line_changes.t_from_line_location_id(i),
6758 NULL, from_line_location_id,
6759 G_NULL_NUM, NULL,
6760 p_chg.line_changes.t_from_line_location_id(i) ),
6761
6762 -- <SVC_NOTIFICATIONS FPJ START>
6763 -- Reset the "Amount Billed notification sent" flag to NULL if there
6764 -- is an Amount change.
6765 svc_amount_notif_sent =
6766 decode ( p_chg.line_changes.amount(i),
6767 NULL, svc_amount_notif_sent, NULL ),
6768 -- Reset the "Assignment Completion notification sent" flag to NULL
6769 -- if there is an Assignment End Date change.
6770 svc_completion_notif_sent =
6771 decode ( p_chg.line_changes.expiration_date(i),
6772 NULL, svc_completion_notif_sent, NULL ),
6773 -- <SVC_NOTIFICATIONS FPJ END>
6774
6775 -- <Manual Price Override FPJ START>
6776 manual_price_change_flag =
6777 NVL(p_chg.line_changes.t_manual_price_change_flag(i),
6778 manual_price_change_flag),
6779 -- <Manual Price Override FPJ END>
6780 preferred_grade = nvl(p_chg.line_changes.preferred_grade(i),preferred_grade), --INVCONV sschinch
6781 secondary_unit_of_measure = NVL(p_chg.line_changes.t_new_secondary_uom(i),secondary_unit_of_measure) --INVCONV
6782 ,tax_attribute_update_code =
6783 NVL(tax_attribute_update_code,NVL2(g_calculate_tax_flag, 'UPDATE', null)) --<R12 eTax Integration>
6784 WHERE po_line_id = p_chg.line_changes.po_line_id(i);
6785
6786 -- Apply the shipment changes to the database.
6787 -- if only secondary quantity or grade is changed on the shipment , leave the approved_flag unchanged
6788 l_progress := '040';
6789
6790 FORALL i IN 1..p_chg.shipment_changes.get_count
6791
6792 -- SQL What: Update PO_LINE_LOCATIONS with the requested/derived shipment
6793 -- changes. If the approved flag is Y, update it to R.
6794 UPDATE po_line_locations PLL
6795 SET last_update_date = sysdate,
6796 last_updated_by = g_user_id,
6797 request_id = decode(g_request_id,null,PLL.request_id,-1,PLL.request_id,g_request_id), /*bug 7278327, update the request_id with the concerned concurrent_request_id*/
6798 -- approved_flag = decode(approved_flag, 'Y', 'R', approved_flag),
6799 approved_flag = decode(approved_flag, 'Y', decode(p_chg.shipment_changes.t_sec_qty_grade_change_only(i),'Y','Y','R'), approved_flag), /* sschinch 09/08 invconv */
6800
6801 quantity = nvl(p_chg.shipment_changes.quantity(i),quantity),
6802 promised_date =
6803 nvl(p_chg.shipment_changes.promised_date(i), promised_date),
6804 price_override =
6805 nvl(p_chg.shipment_changes.price_override(i), price_override),
6806 need_by_date =
6807 nvl(p_chg.shipment_changes.need_by_date(i), need_by_date),
6808 ship_to_location_id =
6809 nvl(p_chg.shipment_changes.ship_to_location_id(i),
6810 ship_to_location_id),
6811 sales_order_update_date =
6812 nvl(p_chg.shipment_changes.sales_order_update_date(i),
6813 sales_order_update_date),
6814 amount = nvl(p_chg.shipment_changes.amount(i), amount),
6815 secondary_quantity =
6816 nvl(p_chg.shipment_changes.secondary_quantity(i), secondary_quantity),
6817 -- <Manual Price Override FPJ START>
6818 manual_price_change_flag =
6819 NVL(p_chg.shipment_changes.t_manual_price_change_flag(i),
6820 manual_price_change_flag),
6821 -- <Manual Price Override FPJ END>
6822 preferred_grade = nvl(p_chg.shipment_changes.preferred_grade(i),preferred_grade) -- sschinch 09/08 INVCONV
6823 ,tax_attribute_update_code =
6824 NVL(tax_attribute_update_code,NVL2(g_calculate_tax_flag, 'UPDATE', null)) --<R12 eTax Integration>
6825 WHERE p_chg.shipment_changes.po_line_location_id(i) IS NOT NULL
6826 AND line_location_id = p_chg.shipment_changes.po_line_location_id(i);
6827
6828 -- Apply the distribution changes to the database.
6829 l_progress := '050';
6830
6831 FORALL i IN 1..p_chg.distribution_changes.get_count
6832
6833 -- SQL What: Update PO_DISTRIBUTIONS with the requested/derived
6834 -- distribution changes.
6835 UPDATE po_distributions
6836 SET last_update_date = sysdate,
6837 last_updated_by = g_user_id,
6838 request_id = decode(g_request_id,null,request_id,-1,request_id,g_request_id), /*bug 7278327, update the request_id with the concerned concurrent_request_id*/
6839 quantity_ordered =
6840 nvl(p_chg.distribution_changes.quantity_ordered(i), quantity_ordered),
6841 amount_ordered =
6842 nvl(p_chg.distribution_changes.amount_ordered(i), amount_ordered)
6843 ,tax_attribute_update_code =
6844 NVL(tax_attribute_update_code,NVL2(g_calculate_tax_flag, 'UPDATE', null)) --<R12 eTax Integration>
6845 WHERE p_chg.distribution_changes.po_distribution_id(i) IS NOT NULL
6846 AND po_distribution_id = p_chg.distribution_changes.po_distribution_id(i);
6847
6848 -- (Services) For standard PO, re-default the price differentials if needed.
6849 IF (g_document_type = 'PO') AND (g_document_subtype = 'STANDARD') THEN
6850
6851 FOR i IN 1..p_chg.line_changes.get_count LOOP
6852 l_new_from_line_loc_id := p_chg.line_changes.t_from_line_location_id(i);
6853
6854 -- If there is a new FROM_LINE_LOCATION_ID and it is different from
6855 -- the current FROM_LINE_LOCATION_ID, re-default the price differentials.
6856 IF (l_new_from_line_loc_id IS NOT NULL) AND
6857 (l_new_from_line_loc_id <>
6858 NVL(p_chg.line_changes.c_from_line_location_id(i), G_NULL_NUM)) THEN
6859
6860 l_po_entity_type := 'PO LINE';
6861 l_po_entity_id := p_chg.line_changes.po_line_id(i);
6862
6863 -- Determine the source of the price differentials
6864 IF (l_new_from_line_loc_id <> G_NULL_NUM) THEN
6865 l_ga_entity_type := 'PRICE BREAK';
6866 l_ga_entity_id := l_new_from_line_loc_id;
6867 ELSE
6868 l_ga_entity_type := 'BLANKET LINE';
6869 l_ga_entity_id := p_chg.line_changes.c_from_line_id(i);
6870 END IF;
6871
6872 -- Delete price differentials from Standard PO.
6873 PO_PRICE_DIFFERENTIALS_PVT.delete_price_differentials (
6874 p_entity_type => l_po_entity_type,
6875 p_entity_id => l_po_entity_id
6876 );
6877
6878 -- Copy price differentials from GA to Standard PO.
6879 PO_PRICE_DIFFERENTIALS_PVT.default_price_differentials (
6880 p_from_entity_type => l_ga_entity_type,
6881 p_from_entity_id => l_ga_entity_id,
6882 p_to_entity_type => l_po_entity_type,
6883 p_to_entity_id => l_po_entity_id
6884 );
6885 END IF;
6886 END LOOP; -- line changes
6887 END IF; -- g_document_type
6888
6889 -- Update some additional fields on Blanket PAs.
6890 l_progress := '055';
6891 IF (g_document_type = 'PA') THEN
6892
6893 -- Bug 3373453 START
6894 FORALL i IN 1..p_chg.line_changes.get_count
6895 -- SQL What: Update the retroactive date for line price changes on
6896 -- non-cumulative lines.
6897 UPDATE po_lines POL
6898 SET last_update_date = sysdate,
6899 last_updated_by = g_user_id,
6900 retroactive_date = sysdate
6901 WHERE POL.po_line_id = p_chg.line_changes.po_line_id(i)
6902 AND p_chg.line_changes.unit_price(i) IS NOT NULL
6903 AND NVL(POL.price_break_lookup_code,'NON CUMULATIVE')
6904 = 'NON CUMULATIVE';
6905
6906 FORALL i IN 1..p_chg.shipment_changes.get_count
6907 -- SQL What: Update the retroactive date for pricing attribute changes
6908 -- on price breaks of non-cumulative lines.
6909 UPDATE po_lines POL
6910 SET last_update_date = sysdate,
6911 last_updated_by = g_user_id,
6912 retroactive_date = sysdate
6913 WHERE POL.po_line_id = p_chg.shipment_changes.c_po_line_id(i)
6914 AND (p_chg.shipment_changes.price_override(i) IS NOT NULL
6915 OR p_chg.shipment_changes.quantity(i) IS NOT NULL
6916 OR p_chg.shipment_changes.ship_to_location_id(i) IS NOT NULL)
6917 AND NVL(POL.price_break_lookup_code,'NON CUMULATIVE')
6918 = 'NON CUMULATIVE';
6919 -- Bug 3373453 END
6920
6921 FORALL i IN 1..p_chg.shipment_changes.get_count
6922 -- SQL What: Re-calculate the price discount if there is a price break
6923 -- price change.
6924 UPDATE po_line_locations PLL
6925 SET last_update_date = sysdate,
6926 last_updated_by = g_user_id,
6927 price_discount =
6928 (SELECT (POL.unit_price - p_chg.shipment_changes.price_override(i))
6929 * 100 / POL.unit_price
6930 FROM po_lines POL
6931 WHERE POL.po_line_id = PLL.po_line_id
6932 AND POL.unit_price <> 0)
6933 WHERE PLL.line_location_id
6934 = p_chg.shipment_changes.po_line_location_id(i)
6935 AND p_chg.shipment_changes.price_override(i) IS NOT NULL;
6936
6937 END IF; -- g_document_type = 'PA'
6938
6939 -- Perform deletion on the requested records.
6940 delete_records ( p_chg );
6941
6942 -- Call the Revision API to check whether a new revision is needed.
6943 l_progress := '070';
6944 IF g_sec_qty_grade_only_chge_doc = 'N' THEN -- sschinch 09/08 INVCONV
6945 l_new_revision_num := g_revision_num;
6946 PO_DOCUMENT_REVISION_GRP.Check_New_Revision (
6947 p_api_version => 1.0,
6948 p_doc_type => g_document_type,
6949 p_doc_subtype => g_document_subtype,
6950 p_doc_id => g_document_id,
6951 p_table_name => 'ALL',
6952 x_return_status => l_return_status,
6953 x_doc_revision_num => l_new_revision_num,
6954 x_message => l_message
6955 );
6956
6957 IF (g_fnd_debug = 'Y') THEN
6958 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_EVENT) THEN
6959 FND_LOG.string( log_level => FND_LOG.LEVEL_EVENT,
6960 module => g_module_prefix || l_proc_name,
6961 message => 'Current revision: ' || g_revision_num
6962 || '; Revision API returned revision: '
6963 || l_new_revision_num );
6964 END IF;
6965 END IF;
6966
6967 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6968 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
6969 END IF;
6970 END IF; -- g_sec_qty_grade_only_chge_doc = 'N' INVCONV
6971
6972 -- Update the header-level fields.
6973 l_progress := '080';
6974 IF (g_document_type IN ('PO', 'PA')) THEN
6975
6976 -- <POC Contract Binding FPJ START>
6977 -- For a new revision of a standard PO or a PA, if signature was required
6978 -- on any of the previous revisions, then Acceptance Required should be
6979 -- set to Document and Signature ('S').
6980
6981 IF ((g_document_type = 'PO' AND g_document_subtype = 'STANDARD')
6982 OR (g_document_type = 'PA'))
6983 AND (l_new_revision_num <> g_revision_num) -- revision has changed
6984 AND PO_SIGNATURE_PVT.was_signature_required(g_po_header_id) THEN
6985
6986 l_acceptance_required_flag := 'S';
6987 END IF;
6988 -- <POC Binding FPJ END>
6989
6990 -- SQL What: Update PO_HEADERS with the last_update WHO values.
6991 -- If authorization status is Approved, change it to Requires Reapproval.
6992 -- If the approved flag is Y, change it to R.
6993 -- If this is a new revision, update the revised date to SYSDATE.
6994 -- Update the acceptance required flag if needed.
6995
6996 IF g_sec_qty_grade_only_chge_doc = 'N' THEN -- sschinch 09.08.04 INVCONV
6997 UPDATE po_headers
6998 SET last_update_date = sysdate,
6999 last_updated_by = g_user_id,
7000 authorization_status =
7001 decode(authorization_status,
7002 'APPROVED','REQUIRES REAPPROVAL', authorization_status),
7003 approved_flag = decode(approved_flag, 'Y', 'R', approved_flag),
7004 revision_num = l_new_revision_num,
7005 revised_date = decode(l_new_revision_num,
7006 g_revision_num, revised_date, sysdate),
7007
7008 -- <POC Binding FPJ START>
7009 acceptance_required_flag =
7010 NVL(l_acceptance_required_flag, acceptance_required_flag)
7011 -- <POC Binding FPJ END>
7012 WHERE po_header_id = g_po_header_id
7013 RETURNING authorization_status INTO l_new_auth_status; -- <HTML Agreement R12>
7014
7015 -- <HTML Agreement R12 START>
7016 -- If the status gets changed to REQUIRES REAPPROVAL, we need to lock the
7017 -- document if needed
7018 IF (l_new_auth_status = 'REQUIRES REAPPROVAL') THEN
7019 PO_DRAFTS_PVT.lock_document
7020 ( p_po_header_id => g_po_header_id,
7021 p_role => PO_GLOBAL.g_ROLE_BUYER,
7022 p_role_user_id => FND_GLOBAL.user_id,
7023 p_unlock_current => FND_API.G_FALSE
7024 );
7025 END IF;
7026 -- <HTML Agreement R12 END>
7027
7028 END IF; -- sschinch 09/08/04 INVCONV
7029
7030 ELSE -- release
7031
7032 -- SQL What: Update PO_RELEASES with the last_update WHO values.
7033 -- If authorization status is Approved, change it to Requires Reapproval.
7034 -- If the approved flag is Y, change it to R.
7035 -- If this is a new revision, update the revised date to SYSDATE.
7036 IF g_sec_qty_grade_only_chge_doc = 'N' THEN -- sschinch 09.08.04 INVCONV
7037 UPDATE po_releases
7038 SET last_update_date = sysdate,
7039 last_updated_by = g_user_id,
7040 authorization_status =
7041 decode(authorization_status,
7042 'APPROVED', 'REQUIRES REAPPROVAL', authorization_status),
7043 approved_flag = decode(approved_flag, 'Y', 'R', approved_flag),
7044 revision_num = l_new_revision_num,
7045 revised_date = decode(l_new_revision_num,
7046 g_revision_num, revised_date, sysdate)
7047 WHERE po_release_id = g_po_release_id;
7048 END IF; -- check g_sec_qty_grade_only_chge_doc sschinch 09.08.04 INVCONV
7049 END IF; -- document type
7050
7051 --<R12 eTax Integration Start> call_tax API
7052 IF (g_calculate_tax_flag = 'Y') THEN
7053 g_calculate_tax_status := NULL;
7054 IF (g_document_type = 'PO') THEN
7055 PO_TAX_INTERFACE_PVT.calculate_tax(p_po_header_id => g_po_header_id,
7056 p_po_release_id => NULL,
7057 p_calling_program => g_pkg_name,
7058 x_return_status => g_calculate_tax_status);
7059 ELSE
7060 PO_TAX_INTERFACE_PVT.calculate_tax(p_po_header_id => NULL,
7061 p_po_release_id => g_po_release_id,
7062 p_calling_program => g_pkg_name,
7063 x_return_status => g_calculate_tax_status);
7064 END IF;
7065 END IF;
7066 --<R12 eTax Integration End>
7067
7068 EXCEPTION
7069 WHEN FND_API.g_exc_unexpected_error THEN
7070 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
7071 p_proc_name => l_proc_name,
7072 p_progress => l_progress,
7073 p_add_to_msg_list => FALSE );
7074 RAISE FND_API.g_exc_unexpected_error;
7075 WHEN OTHERS THEN
7076 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
7077 p_proc_name => l_proc_name,
7078 p_progress => l_progress );
7079 RAISE FND_API.g_exc_unexpected_error;
7080 END apply_changes;
7081
7082 -------------------------------------------------------------------------------
7083 --Start of Comments
7084 --Name: create_split_shipments
7085 --Function:
7086 -- Creates split shipments and split distributions.
7087 --Pre-reqs:
7088 -- None.
7089 --Modifies:
7090 -- Inserts the split shipments into PO_LINE_LOCATIONS_ALL.
7091 -- Updates each split shipment change and split distribution change in p_chg
7092 -- with a new LINE_LOCATION_ID from the sequence.
7093 --Locks:
7094 -- None.
7095 --End of Comments
7096 -------------------------------------------------------------------------------
7097 PROCEDURE create_split_shipments (
7098 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
7099 ) IS
7100 l_proc_name CONSTANT VARCHAR2(30) := 'CREATE_SPLIT_SHIPMENTS';
7101 l_line_location_id PO_LINE_LOCATIONS.line_location_id%TYPE;
7102 l_parent_line_loc_id PO_LINE_LOCATIONS.line_location_id%TYPE;
7103 l_ship_chg_i NUMBER;
7104 BEGIN
7105 IF (g_fnd_debug = 'Y') THEN
7106 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
7107 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
7108 module => g_module_prefix || l_proc_name,
7109 message => 'Entering ' || l_proc_name );
7110 END IF;
7111 END IF;
7112
7113 -- Assign a new LINE_LOCATION_ID to each split shipment.
7114 FOR l_split_ship_tbl_i IN 1..g_split_ship_changes_tbl.COUNT LOOP
7115 l_ship_chg_i := g_split_ship_changes_tbl(l_split_ship_tbl_i);
7116 l_parent_line_loc_id :=
7117 p_chg.shipment_changes.parent_line_location_id(l_ship_chg_i);
7118
7119 IF (l_parent_line_loc_id IS NOT NULL) THEN -- This is a split shipment.
7120 -- Generate a new LINE_LOCATION_ID from the sequence.
7121 SELECT PO_LINE_LOCATIONS_S.nextval
7122 INTO l_line_location_id
7123 FROM dual;
7124
7125 -- Update the split shipment change with the new LINE_LOCATION_ID.
7126 p_chg.shipment_changes.po_line_location_id(l_ship_chg_i)
7127 := l_line_location_id;
7128 END IF; -- l_parent_line_loc_id
7129
7130 END LOOP; -- split shipment
7131
7132
7133 -- Bulk insert all the split shipments into PO_LINE_LOCATIONS_ALL,
7134 -- copying most of the field values from the parent shipments.
7135 FORALL i IN 1..p_chg.shipment_changes.po_line_location_id.COUNT
7136 INSERT INTO po_line_locations_all
7137 (
7138 LINE_LOCATION_ID ,
7139 LAST_UPDATE_DATE ,
7140 LAST_UPDATED_BY ,
7141 PO_HEADER_ID ,
7142 PO_LINE_ID ,
7143 LAST_UPDATE_LOGIN ,
7144 CREATION_DATE ,
7145 CREATED_BY ,
7146 QUANTITY ,
7147 QUANTITY_RECEIVED ,
7148 QUANTITY_ACCEPTED ,
7149 QUANTITY_REJECTED ,
7150 QUANTITY_BILLED ,
7151 QUANTITY_CANCELLED ,
7152 UNIT_MEAS_LOOKUP_CODE ,
7153 PO_RELEASE_ID ,
7154 SHIP_TO_LOCATION_ID ,
7155 SHIP_VIA_LOOKUP_CODE ,
7156 NEED_BY_DATE ,
7157 PROMISED_DATE ,
7158 LAST_ACCEPT_DATE ,
7159 PRICE_OVERRIDE ,
7160 ENCUMBERED_FLAG ,
7161 ENCUMBERED_DATE ,
7162 UNENCUMBERED_QUANTITY ,
7163 FOB_LOOKUP_CODE ,
7164 FREIGHT_TERMS_LOOKUP_CODE ,
7165 TAXABLE_FLAG ,
7166 ESTIMATED_TAX_AMOUNT ,
7167 FROM_HEADER_ID ,
7168 FROM_LINE_ID ,
7169 FROM_LINE_LOCATION_ID ,
7170 START_DATE ,
7171 END_DATE ,
7172 LEAD_TIME ,
7173 LEAD_TIME_UNIT ,
7174 PRICE_DISCOUNT ,
7175 TERMS_ID ,
7176 APPROVED_FLAG ,
7177 APPROVED_DATE ,
7178 CLOSED_FLAG ,
7179 CANCEL_FLAG ,
7180 CANCELLED_BY ,
7181 CANCEL_DATE ,
7182 CANCEL_REASON ,
7183 FIRM_STATUS_LOOKUP_CODE ,
7184 FIRM_DATE ,
7185 ATTRIBUTE_CATEGORY ,
7186 ATTRIBUTE1 ,
7187 ATTRIBUTE2 ,
7188 ATTRIBUTE3 ,
7189 ATTRIBUTE4 ,
7190 ATTRIBUTE5 ,
7191 ATTRIBUTE6 ,
7192 ATTRIBUTE7 ,
7193 ATTRIBUTE8 ,
7194 ATTRIBUTE9 ,
7195 ATTRIBUTE10 ,
7196 UNIT_OF_MEASURE_CLASS ,
7197 ENCUMBER_NOW ,
7198 ATTRIBUTE11 ,
7199 ATTRIBUTE12 ,
7200 ATTRIBUTE13 ,
7201 ATTRIBUTE14 ,
7202 ATTRIBUTE15 ,
7203 INSPECTION_REQUIRED_FLAG ,
7204 RECEIPT_REQUIRED_FLAG ,
7205 QTY_RCV_TOLERANCE ,
7206 QTY_RCV_EXCEPTION_CODE ,
7207 ENFORCE_SHIP_TO_LOCATION_CODE ,
7208 ALLOW_SUBSTITUTE_RECEIPTS_FLAG ,
7209 DAYS_EARLY_RECEIPT_ALLOWED ,
7210 DAYS_LATE_RECEIPT_ALLOWED ,
7211 RECEIPT_DAYS_EXCEPTION_CODE ,
7212 INVOICE_CLOSE_TOLERANCE ,
7213 RECEIVE_CLOSE_TOLERANCE ,
7214 SHIP_TO_ORGANIZATION_ID ,
7215 SHIPMENT_NUM ,
7216 SOURCE_SHIPMENT_ID ,
7217 SHIPMENT_TYPE ,
7218 CLOSED_CODE ,
7219 REQUEST_ID ,
7220 PROGRAM_APPLICATION_ID ,
7221 PROGRAM_ID ,
7222 PROGRAM_UPDATE_DATE ,
7223 GOVERNMENT_CONTEXT ,
7224 RECEIVING_ROUTING_ID ,
7225 ACCRUE_ON_RECEIPT_FLAG ,
7226 CLOSED_REASON ,
7227 CLOSED_DATE ,
7228 CLOSED_BY ,
7229 ORG_ID ,
7230 GLOBAL_ATTRIBUTE1 ,
7231 GLOBAL_ATTRIBUTE2 ,
7232 GLOBAL_ATTRIBUTE3 ,
7233 GLOBAL_ATTRIBUTE4 ,
7234 GLOBAL_ATTRIBUTE5 ,
7235 GLOBAL_ATTRIBUTE6 ,
7236 GLOBAL_ATTRIBUTE7 ,
7237 GLOBAL_ATTRIBUTE8 ,
7238 GLOBAL_ATTRIBUTE9 ,
7239 GLOBAL_ATTRIBUTE10 ,
7240 GLOBAL_ATTRIBUTE11 ,
7241 GLOBAL_ATTRIBUTE12 ,
7242 GLOBAL_ATTRIBUTE13 ,
7243 GLOBAL_ATTRIBUTE14 ,
7244 GLOBAL_ATTRIBUTE15 ,
7245 GLOBAL_ATTRIBUTE16 ,
7246 GLOBAL_ATTRIBUTE17 ,
7247 GLOBAL_ATTRIBUTE18 ,
7248 GLOBAL_ATTRIBUTE19 ,
7249 GLOBAL_ATTRIBUTE20 ,
7250 GLOBAL_ATTRIBUTE_CATEGORY ,
7251 QUANTITY_SHIPPED ,
7252 COUNTRY_OF_ORIGIN_CODE ,
7253 TAX_USER_OVERRIDE_FLAG ,
7254 MATCH_OPTION ,
7255 TAX_CODE_ID ,
7256 CALCULATE_TAX_FLAG ,
7257 CHANGE_PROMISED_DATE_REASON ,
7258 NOTE_TO_RECEIVER ,
7259 SECONDARY_QUANTITY ,
7260 SECONDARY_UNIT_OF_MEASURE ,
7261 PREFERRED_GRADE ,
7262 SECONDARY_QUANTITY_RECEIVED ,
7263 SECONDARY_QUANTITY_ACCEPTED ,
7264 SECONDARY_QUANTITY_REJECTED ,
7265 SECONDARY_QUANTITY_CANCELLED ,
7266 VMI_FLAG ,
7267 CONSIGNED_FLAG ,
7268 RETROACTIVE_DATE ,
7269 SUPPLIER_ORDER_LINE_NUMBER ,
7270 AMOUNT ,
7271 AMOUNT_RECEIVED ,
7272 AMOUNT_BILLED ,
7273 AMOUNT_CANCELLED ,
7274 AMOUNT_REJECTED ,
7275 AMOUNT_ACCEPTED ,
7276 DROP_SHIP_FLAG ,
7277 SALES_ORDER_UPDATE_DATE ,
7278 TRANSACTION_FLOW_HEADER_ID ,
7279 -- <Manual Price Override FPJ>:
7280 MANUAL_PRICE_CHANGE_FLAG ,
7281 -- <Complex work Changed for R12>
7282 PAYMENT_TYPE ,
7283 DESCRIPTION ,
7284 QUANTITY_FINANCED ,
7285 AMOUNT_FINANCED ,
7286 QUANTITY_RECOUPED ,
7287 AMOUNT_RECOUPED ,
7288 RETAINAGE_WITHHELD_AMOUNT ,
7289 RETAINAGE_RELEASED_AMOUNT,
7290 OUTSOURCED_ASSEMBLY,
7291 tax_attribute_update_code, --<R12 eTax Integration>
7292 original_shipment_id, --<R12 eTax Integration>
7293 MATCHING_BASIS, -- FPS Enhancement
7294 VALUE_BASIS -- FPS Enhancement
7295 )
7296 SELECT
7297 p_chg.shipment_changes.po_line_location_id(i), -- LINE_LOCATION_ID
7298 sysdate , -- LAST_UPDATE_DATE
7299 g_user_id , -- LAST_UPDATED_BY
7300 PO_HEADER_ID ,
7301 PO_LINE_ID ,
7302 LAST_UPDATE_LOGIN ,
7303 sysdate , -- CREATION_DATE
7304 g_user_id , -- CREATED_BY
7305 nvl(p_chg.shipment_changes.quantity(i),
7306 QUANTITY) , -- QUANTITY
7307 decode(quantity_received, null, null, 0) , -- QUANTITY_RECEIVED
7308 decode(quantity_accepted, null, null, 0) , -- QUANTITY_ACCEPTED
7309 decode(quantity_rejected, null, null, 0) , -- QUANTITY_REJECTED
7310 decode(quantity_billed, null, null, 0) , -- QUANTITY_BILLED
7311 decode(quantity_cancelled, null, null, 0) , -- QUANTITY_CANCELLED
7312 UNIT_MEAS_LOOKUP_CODE ,
7313 PO_RELEASE_ID ,
7314 nvl(p_chg.shipment_changes.ship_to_location_id(i),
7315 SHIP_TO_LOCATION_ID) , -- SHIP_TO_LOCATION_ID
7316 SHIP_VIA_LOOKUP_CODE ,
7317 nvl(p_chg.shipment_changes.need_by_date(i),
7318 NEED_BY_DATE) , -- NEED_BY_DATE
7319 nvl(p_chg.shipment_changes.promised_date(i),
7320 PROMISED_DATE) , -- PROMISED_DATE
7321 LAST_ACCEPT_DATE ,
7322 nvl(p_chg.shipment_changes.price_override(i),
7323 PRICE_OVERRIDE) , -- PRICE_OVERRIDE
7324 NULL , -- ENCUMBERED_FLAG
7325 NULL , -- ENCUMBERED_DATE
7326 NULL , -- UNENCUMBERED_QUANTITY
7327 FOB_LOOKUP_CODE ,
7328 FREIGHT_TERMS_LOOKUP_CODE ,
7329 TAXABLE_FLAG ,
7330 decode(estimated_tax_amount, null, null, 0) , -- ESTIMATED_TAX_AMOUNT
7331 FROM_HEADER_ID ,
7332 FROM_LINE_ID ,
7333 FROM_LINE_LOCATION_ID ,
7334 START_DATE ,
7335 END_DATE ,
7336 LEAD_TIME ,
7337 LEAD_TIME_UNIT ,
7338 PRICE_DISCOUNT ,
7339 TERMS_ID ,
7340 'N' , -- APPROVED_FLAG
7341 NULL , -- APPROVED_DATE
7342 NULL , -- CLOSED_FLAG
7343 'N' , -- CANCEL_FLAG
7344 NULL , -- CANCELLED_BY
7345 NULL , -- CANCEL_DATE
7346 NULL , -- CANCEL_REASON
7347 FIRM_STATUS_LOOKUP_CODE ,
7348 FIRM_DATE ,
7349 ATTRIBUTE_CATEGORY ,
7350 ATTRIBUTE1 ,
7351 ATTRIBUTE2 ,
7352 ATTRIBUTE3 ,
7353 ATTRIBUTE4 ,
7354 ATTRIBUTE5 ,
7355 ATTRIBUTE6 ,
7356 ATTRIBUTE7 ,
7357 ATTRIBUTE8 ,
7358 ATTRIBUTE9 ,
7359 ATTRIBUTE10 ,
7360 UNIT_OF_MEASURE_CLASS ,
7361 ENCUMBER_NOW ,
7362 ATTRIBUTE11 ,
7363 ATTRIBUTE12 ,
7364 ATTRIBUTE13 ,
7365 ATTRIBUTE14 ,
7366 ATTRIBUTE15 ,
7367 INSPECTION_REQUIRED_FLAG ,
7368 RECEIPT_REQUIRED_FLAG ,
7369 QTY_RCV_TOLERANCE ,
7370 QTY_RCV_EXCEPTION_CODE ,
7371 ENFORCE_SHIP_TO_LOCATION_CODE ,
7372 ALLOW_SUBSTITUTE_RECEIPTS_FLAG ,
7373 DAYS_EARLY_RECEIPT_ALLOWED ,
7374 DAYS_LATE_RECEIPT_ALLOWED ,
7375 RECEIPT_DAYS_EXCEPTION_CODE ,
7376 INVOICE_CLOSE_TOLERANCE ,
7377 RECEIVE_CLOSE_TOLERANCE ,
7378 SHIP_TO_ORGANIZATION_ID ,
7379 p_chg.shipment_changes.split_shipment_num(i), -- SHIPMENT_NUM
7380 SOURCE_SHIPMENT_ID ,
7381 SHIPMENT_TYPE ,
7382 'OPEN' , -- CLOSED_CODE
7383 NULL , -- REQUEST_ID
7384 NULL , -- PROGRAM_APPLICATION_ID
7385 NULL , -- PROGRAM_ID
7386 NULL , -- PROGRAM_UPDATE_DATE
7387 GOVERNMENT_CONTEXT ,
7388 RECEIVING_ROUTING_ID ,
7389 ACCRUE_ON_RECEIPT_FLAG ,
7390 NULL , -- CLOSED_REASON
7391 NULL , -- CLOSED_DATE
7392 NULL , -- CLOSED_BY
7393 ORG_ID ,
7394 GLOBAL_ATTRIBUTE1 ,
7395 GLOBAL_ATTRIBUTE2 ,
7396 GLOBAL_ATTRIBUTE3 ,
7397 GLOBAL_ATTRIBUTE4 ,
7398 GLOBAL_ATTRIBUTE5 ,
7399 GLOBAL_ATTRIBUTE6 ,
7400 GLOBAL_ATTRIBUTE7 ,
7401 GLOBAL_ATTRIBUTE8 ,
7402 GLOBAL_ATTRIBUTE9 ,
7403 GLOBAL_ATTRIBUTE10 ,
7404 GLOBAL_ATTRIBUTE11 ,
7405 GLOBAL_ATTRIBUTE12 ,
7406 GLOBAL_ATTRIBUTE13 ,
7407 GLOBAL_ATTRIBUTE14 ,
7408 GLOBAL_ATTRIBUTE15 ,
7409 GLOBAL_ATTRIBUTE16 ,
7410 GLOBAL_ATTRIBUTE17 ,
7411 GLOBAL_ATTRIBUTE18 ,
7412 GLOBAL_ATTRIBUTE19 ,
7413 GLOBAL_ATTRIBUTE20 ,
7414 GLOBAL_ATTRIBUTE_CATEGORY ,
7415 decode(quantity_shipped, null, null, 0) , -- QUANTITY_SHIPPED
7416 COUNTRY_OF_ORIGIN_CODE ,
7417 TAX_USER_OVERRIDE_FLAG ,
7418 MATCH_OPTION ,
7419 TAX_CODE_ID ,
7420 CALCULATE_TAX_FLAG ,
7421 CHANGE_PROMISED_DATE_REASON ,
7422 NOTE_TO_RECEIVER ,
7423 NVL(p_chg.shipment_changes.secondary_quantity(i),
7424 decode(secondary_quantity, NULL, NULL, 0)), -- SECONDARY_QUANTITY
7425 SECONDARY_UNIT_OF_MEASURE ,
7426 PREFERRED_GRADE ,
7427 decode(secondary_quantity_received,
7428 NULL, NULL, 0) , -- SECONDARY_QUANTITY_RECEIVED
7429 decode(secondary_quantity_accepted,
7430 NULL, NULL, 0) , -- SECONDARY_QUANTITY_ACCEPTED
7431 decode(secondary_quantity_rejected,
7432 NULL, NULL, 0) , -- SECONDARY_QUANTITY_REJECTED
7433 decode(secondary_quantity_cancelled,
7434 NULL, NULL, 0) , -- SECONDARY_QUANTITY_CANCELLED
7435 VMI_FLAG ,
7436 CONSIGNED_FLAG ,
7437 NULL , -- RETROACTIVE_DATE
7438 nvl(p_chg.shipment_changes.new_supp_order_line_no(i),
7439 SUPPLIER_ORDER_LINE_NUMBER),
7440
7441 p_chg.shipment_changes.amount(i) , -- AMOUNT
7442 decode(amount_received, null, null, 0) , -- AMOUNT_RECEIVED
7443 decode(amount_billed, null, null, 0) , -- AMOUNT_BILLED
7444 decode(amount_cancelled, null, null, 0) , -- AMOUNT_CANCELLED
7445 decode(amount_rejected, null, null, 0) , -- AMOUNT_REJECTED
7446 decode(amount_accepted, null, null, 0) , -- AMOUNT_ACCEPTED
7447 DROP_SHIP_FLAG ,
7448 NULL , -- SALES_ORDER_UPDATE_DATE
7449 TRANSACTION_FLOW_HEADER_ID ,
7450 -- <Manual Price Override FPJ>:
7451 p_chg.shipment_changes.t_manual_price_change_flag(i),
7452 -- <Complex work Changed for R12>
7453 nvl(p_chg.shipment_changes.payment_type(i),'') ,
7454 nvl(p_chg.shipment_changes.description(i),'') ,
7455 decode(quantity_financed,null,null,0) ,
7456 decode(amount_financed,null,null,0) ,
7457 decode(quantity_recouped,null,null,0) ,
7458 decode(amount_recouped,null,null,0) ,
7459 decode(retainage_withheld_amount,null,null,0) ,
7460 decode(retainage_released_amount,null,null,0),
7461 outsourced_assembly,
7462 nvl2(g_calculate_tax_flag, 'CREATE', null), --<R12 eTax Integration>
7463 line_location_id, --<R12 eTax Integration>
7464 decode(p_chg.shipment_changes.payment_type(i),'RATE','QUANTITY',matching_basis), -- FPS Enhancement
7465 decode(p_chg.shipment_changes.payment_type(i),'RATE','QUANTITY',value_basis) -- FPS Enhancement
7466 FROM po_line_locations
7467 WHERE p_chg.shipment_changes.parent_line_location_id(i) IS NOT NULL
7468 AND line_location_id = p_chg.shipment_changes.parent_line_location_id(i);
7469
7470 -- Now create all the split distributions.
7471 create_split_distributions ( p_chg );
7472
7473 EXCEPTION
7474 WHEN FND_API.g_exc_unexpected_error THEN
7475 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
7476 p_proc_name => l_proc_name,
7477 p_add_to_msg_list => FALSE );
7478 RAISE FND_API.g_exc_unexpected_error;
7479 WHEN OTHERS THEN
7480 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
7481 p_proc_name => l_proc_name );
7482 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7483 END create_split_shipments;
7484
7485 -------------------------------------------------------------------------------
7486 --Start of Comments
7487 --Name: create_split_distributions
7488 --Function:
7489 -- Creates split distributions.
7490 --Pre-reqs:
7491 -- None.
7492 --Modifies:
7493 -- Inserts the split distributions into PO_DISTRIBUTIONS_ALL.
7494 -- Updates p_chg with the new PO_DISTRIBUTION_ID for each split distribution.
7495 --Locks:
7496 -- None.
7497 --End of Comments
7498 -------------------------------------------------------------------------------
7499 PROCEDURE create_split_distributions (
7500 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE
7501 ) IS
7502 l_proc_name CONSTANT VARCHAR2(30) := 'CREATE_SPLIT_DISTRIBUTIONS';
7503 l_module CONSTANT VARCHAR2(80) := g_module_prefix || l_proc_name;
7504 l_progress VARCHAR2(3) := '000';
7505 l_po_distribution_id PO_DISTRIBUTIONS.po_distribution_id%TYPE;
7506 l_line_location_id PO_DISTRIBUTIONS.line_location_id%TYPE;
7507 l_ship_chg_i NUMBER;
7508 l_dist_chg_i NUMBER;
7509 -- <GRANTS FPJ START>
7510 l_return_status VARCHAR2(1);
7511 l_gms_i NUMBER;
7512 l_gms_po_obj GMS_PO_INTERFACE_TYPE;
7513 l_msg_count NUMBER;
7514 l_msg_data VARCHAR2(2000);
7515 -- <GRANTS FPJ END>
7516 BEGIN
7517 IF (g_fnd_debug = 'Y') THEN
7518 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
7519 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
7520 module => l_module,
7521 message => 'Entering ' || l_proc_name );
7522 END IF;
7523 END IF;
7524
7525 -- For each split distribution, assign a new PO_DISTRIBUTION_ID.
7526 FOR l_split_dist_tbl_i IN 1..g_split_dist_changes_tbl.COUNT LOOP
7527 l_dist_chg_i := g_split_dist_changes_tbl(l_split_dist_tbl_i);
7528
7529 -- Generate a new PO_DISTRIBUTION_ID from the sequence.
7530 SELECT PO_DISTRIBUTIONS_S.nextval
7531 INTO l_po_distribution_id
7532 FROM dual;
7533
7534 -- Update the split distribution change with the new PO_DISTRIBUTION_ID.
7535 p_chg.distribution_changes.po_distribution_id(l_dist_chg_i)
7536 := l_po_distribution_id;
7537
7538 -- Retrieve the new PO_LINE_LOCATION_ID from the split shipment.
7539 l_ship_chg_i := get_split_ship_change ( p_chg,
7540 p_chg.distribution_changes.c_po_line_id(l_dist_chg_i),
7541 p_chg.distribution_changes.c_parent_line_location_id(l_dist_chg_i),
7542 p_chg.distribution_changes.split_shipment_num(l_dist_chg_i) );
7543 l_line_location_id :=
7544 p_chg.shipment_changes.po_line_location_id(l_ship_chg_i);
7545
7546 -- Update the split distribution change with the new PO_LINE_LOCATION_ID.
7547 p_chg.distribution_changes.c_line_location_id(l_dist_chg_i)
7548 := l_line_location_id;
7549
7550 IF (l_line_location_id IS NULL) THEN
7551 -- PO_LINE_LOCATION_ID should have been assigned to the split shipment
7552 -- in create_split_shipments. If not, throw an unexpected error.
7553 FND_MESSAGE.set_name('PO', 'PO_GENERIC_ERROR');
7554 FND_MESSAGE.set_token('ERROR_TEXT',
7555 'Could not find the new shipment for this split distribution.');
7556 FND_MSG_PUB.add;
7557 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7558 END IF;
7559
7560
7561 END LOOP; -- split distribution changes
7562
7563 -- Bulk insert all the split distributions into PO_DISTRIBUTIONS_ALL,
7564 -- by copying most of the field values from the parent distribution.
7565 l_progress := '010';
7566 FORALL i IN 1..p_chg.distribution_changes.po_distribution_id.COUNT
7567 INSERT INTO po_distributions_all (
7568 PO_DISTRIBUTION_ID ,
7569 LAST_UPDATE_DATE ,
7570 LAST_UPDATED_BY ,
7571 PO_HEADER_ID ,
7572 PO_LINE_ID ,
7573 LINE_LOCATION_ID ,
7574 SET_OF_BOOKS_ID ,
7575 CODE_COMBINATION_ID ,
7576 QUANTITY_ORDERED ,
7577 LAST_UPDATE_LOGIN ,
7578 CREATION_DATE ,
7579 CREATED_BY ,
7580 PO_RELEASE_ID ,
7581 QUANTITY_DELIVERED ,
7582 QUANTITY_BILLED ,
7583 QUANTITY_CANCELLED ,
7584 REQ_HEADER_REFERENCE_NUM ,
7585 REQ_LINE_REFERENCE_NUM ,
7586 REQ_DISTRIBUTION_ID ,
7587 DELIVER_TO_LOCATION_ID ,
7588 DELIVER_TO_PERSON_ID ,
7589 RATE_DATE ,
7590 RATE ,
7591 AMOUNT_BILLED ,
7592 ACCRUED_FLAG ,
7593 ENCUMBERED_FLAG ,
7594 ENCUMBERED_AMOUNT ,
7595 UNENCUMBERED_QUANTITY ,
7596 UNENCUMBERED_AMOUNT ,
7597 FAILED_FUNDS_LOOKUP_CODE ,
7598 GL_ENCUMBERED_DATE ,
7599 GL_ENCUMBERED_PERIOD_NAME ,
7600 GL_CANCELLED_DATE ,
7601 DESTINATION_TYPE_CODE ,
7602 DESTINATION_ORGANIZATION_ID ,
7603 DESTINATION_SUBINVENTORY ,
7604 ATTRIBUTE_CATEGORY ,
7605 ATTRIBUTE1 ,
7606 ATTRIBUTE2 ,
7607 ATTRIBUTE3 ,
7608 ATTRIBUTE4 ,
7609 ATTRIBUTE5 ,
7610 ATTRIBUTE6 ,
7611 ATTRIBUTE7 ,
7612 ATTRIBUTE8 ,
7613 ATTRIBUTE9 ,
7614 ATTRIBUTE10 ,
7615 ATTRIBUTE11 ,
7616 ATTRIBUTE12 ,
7617 ATTRIBUTE13 ,
7618 ATTRIBUTE14 ,
7619 ATTRIBUTE15 ,
7620 WIP_ENTITY_ID ,
7621 WIP_OPERATION_SEQ_NUM ,
7622 WIP_RESOURCE_SEQ_NUM ,
7623 WIP_REPETITIVE_SCHEDULE_ID ,
7624 WIP_LINE_ID ,
7625 BOM_RESOURCE_ID ,
7626 BUDGET_ACCOUNT_ID ,
7627 ACCRUAL_ACCOUNT_ID ,
7628 VARIANCE_ACCOUNT_ID ,
7629 PREVENT_ENCUMBRANCE_FLAG ,
7630 GOVERNMENT_CONTEXT ,
7631 DESTINATION_CONTEXT ,
7632 DISTRIBUTION_NUM ,
7633 SOURCE_DISTRIBUTION_ID ,
7634 REQUEST_ID ,
7635 PROGRAM_APPLICATION_ID ,
7636 PROGRAM_ID ,
7637 PROGRAM_UPDATE_DATE ,
7638 PROJECT_ID ,
7639 TASK_ID ,
7640 EXPENDITURE_TYPE ,
7641 PROJECT_ACCOUNTING_CONTEXT ,
7642 EXPENDITURE_ORGANIZATION_ID ,
7643 GL_CLOSED_DATE ,
7644 ACCRUE_ON_RECEIPT_FLAG ,
7645 EXPENDITURE_ITEM_DATE ,
7646 ORG_ID ,
7647 KANBAN_CARD_ID ,
7648 AWARD_ID ,
7649 MRC_RATE_DATE ,
7650 MRC_RATE ,
7651 MRC_ENCUMBERED_AMOUNT ,
7652 MRC_UNENCUMBERED_AMOUNT ,
7653 END_ITEM_UNIT_NUMBER ,
7654 TAX_RECOVERY_OVERRIDE_FLAG ,
7655 RECOVERABLE_TAX ,
7656 NONRECOVERABLE_TAX ,
7657 RECOVERY_RATE ,
7658 OKE_CONTRACT_LINE_ID ,
7659 OKE_CONTRACT_DELIVERABLE_ID ,
7660 AMOUNT_ORDERED ,
7661 AMOUNT_DELIVERED ,
7662 AMOUNT_CANCELLED ,
7663 DISTRIBUTION_TYPE ,
7664 AMOUNT_TO_ENCUMBER ,
7665 INVOICE_ADJUSTMENT_FLAG ,
7666 DEST_CHARGE_ACCOUNT_ID ,
7667 DEST_VARIANCE_ACCOUNT_ID ,
7668 tax_attribute_update_code --<R12 eTax Integration>
7669 )
7670 SELECT
7671 p_chg.distribution_changes.po_distribution_id(i), -- PO_DISTRIBUTION_ID
7672 sysdate , -- LAST_UPDATE_DATE
7673 g_user_id , -- LAST_UPDATED_BY
7674 PO_HEADER_ID ,
7675 PO_LINE_ID ,
7676 p_chg.distribution_changes.c_line_location_id(i), -- LINE_LOCATION_ID
7677 SET_OF_BOOKS_ID ,
7678 CODE_COMBINATION_ID ,
7679 nvl(p_chg.distribution_changes.quantity_ordered(i),
7680 QUANTITY_ORDERED) , -- QUANTITY_ORDERED
7681 LAST_UPDATE_LOGIN ,
7682 sysdate , -- CREATION_DATE
7683 g_user_id , -- CREATED_BY
7684 PO_RELEASE_ID ,
7685 decode(quantity_delivered, null, null, 0) , -- QUANTITY_DELIVERED
7686 decode(quantity_billed, null, null, 0) , -- QUANTITY_BILLED
7687 decode(quantity_cancelled, null, null, 0) , -- QUANTITY_CANCELLED
7688 REQ_HEADER_REFERENCE_NUM ,
7689 REQ_LINE_REFERENCE_NUM ,
7690 -- bug 5750240 : the Req distribution id for the split
7691 -- shipment should not be carried from the parent dist.
7692 NULL,
7693 -- REQ_DISTRIBUTION_ID ,
7694 DELIVER_TO_LOCATION_ID ,
7695 DELIVER_TO_PERSON_ID ,
7696 RATE_DATE ,
7697 RATE ,
7698 decode(amount_billed, null, null, 0) , -- AMOUNT_BILLED
7699 ACCRUED_FLAG ,
7700 'N' , -- ENCUMBERED_FLAG Bug 5558172 changed NULL to 'N' so that the distriution will be visble in enter po form.
7701 NULL , -- ENCUMBERED_AMOUNT
7702 NULL , -- UNENCUMBERED_QUANTITY
7703 NULL , -- UNENCUMBERED_AMOUNT
7704 NULL , -- FAILED_FUNDS_LOOKUP_CODE
7705 GL_ENCUMBERED_DATE ,
7706 GL_ENCUMBERED_PERIOD_NAME ,
7707 NULL , -- GL_CANCELLED_DATE
7708 DESTINATION_TYPE_CODE ,
7709 DESTINATION_ORGANIZATION_ID ,
7710 DESTINATION_SUBINVENTORY ,
7711 ATTRIBUTE_CATEGORY ,
7712 ATTRIBUTE1 ,
7713 ATTRIBUTE2 ,
7714 ATTRIBUTE3 ,
7715 ATTRIBUTE4 ,
7716 ATTRIBUTE5 ,
7717 ATTRIBUTE6 ,
7718 ATTRIBUTE7 ,
7719 ATTRIBUTE8 ,
7720 ATTRIBUTE9 ,
7721 ATTRIBUTE10 ,
7722 ATTRIBUTE11 ,
7723 ATTRIBUTE12 ,
7724 ATTRIBUTE13 ,
7725 ATTRIBUTE14 ,
7726 ATTRIBUTE15 ,
7727 WIP_ENTITY_ID ,
7728 WIP_OPERATION_SEQ_NUM ,
7729 WIP_RESOURCE_SEQ_NUM ,
7730 WIP_REPETITIVE_SCHEDULE_ID ,
7731 WIP_LINE_ID ,
7732 BOM_RESOURCE_ID ,
7733 BUDGET_ACCOUNT_ID ,
7734 ACCRUAL_ACCOUNT_ID ,
7735 VARIANCE_ACCOUNT_ID ,
7736 PREVENT_ENCUMBRANCE_FLAG ,
7737 GOVERNMENT_CONTEXT ,
7738 DESTINATION_CONTEXT ,
7739 DISTRIBUTION_NUM ,
7740 SOURCE_DISTRIBUTION_ID ,
7741 NULL , -- REQUEST_ID
7742 NULL , -- PROGRAM_APPLICATION_ID
7743 NULL , -- PROGRAM_ID
7744 NULL , -- PROGRAM_UPDATE_DATE
7745 PROJECT_ID ,
7746 TASK_ID ,
7747 EXPENDITURE_TYPE ,
7748 PROJECT_ACCOUNTING_CONTEXT ,
7749 EXPENDITURE_ORGANIZATION_ID ,
7750 NULL , -- GL_CLOSED_DATE
7751 ACCRUE_ON_RECEIPT_FLAG ,
7752 EXPENDITURE_ITEM_DATE ,
7753 ORG_ID ,
7754 KANBAN_CARD_ID ,
7755 NULL , -- AWARD_ID
7756 MRC_RATE_DATE ,
7757 MRC_RATE ,
7758 NULL , -- MRC_ENCUMBERED_AMOUNT
7759 NULL , -- MRC_UNENCUMBERED_AMOUNT
7760 END_ITEM_UNIT_NUMBER ,
7761 TAX_RECOVERY_OVERRIDE_FLAG ,
7762 --<R12 eTax Integration Start>
7763 null , -- RECOVERABLE_TAX
7764 null , -- NONRECOVERABLE_TAX
7765 decode(tax_recovery_override_flag,'Y',recovery_rate, null) , -- RECOVERY_RATE
7766 --<R12 eTax Integration End>
7767 OKE_CONTRACT_LINE_ID ,
7768 OKE_CONTRACT_DELIVERABLE_ID ,
7769 nvl(p_chg.distribution_changes.amount_ordered(i),
7770 AMOUNT_ORDERED) , -- AMOUNT_ORDERED
7771 decode(amount_delivered, null, null, 0) , -- AMOUNT_DELIVERED
7772 decode(amount_cancelled, null, null, 0) , -- AMOUNT_CANCELLED
7773 DISTRIBUTION_TYPE ,
7774 AMOUNT_TO_ENCUMBER ,
7775 NULL , -- INVOICE_ADJUSTMENT_FLAG
7776 DEST_CHARGE_ACCOUNT_ID ,
7777 DEST_VARIANCE_ACCOUNT_ID ,
7778 nvl2(g_calculate_tax_flag, 'CREATE', null) --<R12 eTax Integration>
7779 FROM po_distributions
7780 WHERE p_chg.distribution_changes.parent_distribution_id(i) IS NOT NULL
7781 AND po_distribution_id =
7782 p_chg.distribution_changes.parent_distribution_id(i);
7783
7784 -- <GRANTS FPJ START>
7785 l_progress := '020';
7786 -- We need to call the Grants API to generate new award IDs for the
7787 -- split distributions whose parents have award IDs.
7788 l_gms_po_obj := GMS_PO_INTERFACE_TYPE (
7789 distribution_id => GMS_TYPE_NUMBER(),
7790 distribution_num => GMS_TYPE_NUMBER(),
7791 project_id => GMS_TYPE_NUMBER(),
7792 task_id => GMS_TYPE_NUMBER(),
7793 award_set_id_in => GMS_TYPE_NUMBER(),
7794 award_set_id_out => GMS_TYPE_NUMBER() );
7795
7796 FOR l_split_dist_tbl_i IN 1..g_split_dist_changes_tbl.COUNT LOOP
7797 l_dist_chg_i := g_split_dist_changes_tbl(l_split_dist_tbl_i);
7798
7799 IF (p_chg.distribution_changes.c_award_id(l_dist_chg_i) IS NOT NULL) THEN
7800
7801 -- Add the information for this split distribution to l_gms_po_obj.
7802 l_gms_po_obj.distribution_id.extend;
7803 l_gms_i := l_gms_po_obj.distribution_id.count;
7804 l_gms_po_obj.distribution_id(l_gms_i) :=
7805 p_chg.distribution_changes.po_distribution_id(l_dist_chg_i);
7806 l_gms_po_obj.distribution_num.extend;
7807 l_gms_po_obj.distribution_num(l_gms_i) :=
7808 p_chg.distribution_changes.c_distribution_num(l_dist_chg_i);
7809 l_gms_po_obj.project_id.extend;
7810 l_gms_po_obj.project_id(l_gms_i) :=
7811 p_chg.distribution_changes.c_project_id(l_dist_chg_i);
7812 l_gms_po_obj.task_id.extend;
7813 l_gms_po_obj.task_id(l_gms_i) :=
7814 p_chg.distribution_changes.c_task_id(l_dist_chg_i);
7815 l_gms_po_obj.award_set_id_in.extend;
7816 l_gms_po_obj.award_set_id_in(l_gms_i) :=
7817 p_chg.distribution_changes.c_award_id(l_dist_chg_i);
7818 l_gms_po_obj.award_set_id_out.extend;
7819
7820 IF (g_fnd_debug = 'Y') THEN
7821 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_STATEMENT) THEN
7822 FND_LOG.string (
7823 log_level => FND_LOG.LEVEL_STATEMENT,
7824 module => l_module,
7825 message => 'Calling GMS; ' || l_gms_i
7826 ||' distribution_id: '||l_gms_po_obj.distribution_id(l_gms_i)
7827 ||' distribution_num: '||l_gms_po_obj.distribution_num(l_gms_i)
7828 ||' project_id: '||l_gms_po_obj.project_id(l_gms_i)
7829 ||' task_id: '||l_gms_po_obj.task_id(l_gms_i)
7830 ||' award_set_id_in: '||l_gms_po_obj.award_set_id_in(l_gms_i) );
7831 END IF;
7832 END IF;
7833
7834 END IF; -- c_award_id
7835 END LOOP; -- split distribution changes
7836
7837 -- If we found any split distributions that need new award IDs, call the
7838 -- Grants API.
7839 l_progress := '030';
7840 IF (l_gms_po_obj.distribution_id.count > 0) THEN
7841 PO_GMS_INTEGRATION_PVT.maintain_adl (
7842 p_api_version => 1.0,
7843 x_return_status => l_return_status,
7844 x_msg_count => l_msg_count,
7845 x_msg_data => l_msg_data,
7846 p_caller => 'CHANGE_PO',
7847 x_po_gms_interface_obj => l_gms_po_obj
7848 );
7849 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
7850 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7851 END IF;
7852
7853 l_progress := '040';
7854 -- Bulk update the distributions with the new award IDs.
7855 FORALL i IN 1..l_gms_po_obj.award_set_id_out.COUNT
7856 UPDATE po_distributions
7857 SET last_update_date = sysdate,
7858 last_updated_by = g_user_id,
7859 award_id = l_gms_po_obj.award_set_id_out(i)
7860 WHERE po_distributions.po_distribution_id
7861 = l_gms_po_obj.distribution_id(i);
7862
7863 END IF; -- l_gms_po_obj
7864 -- <GRANTS FPJ END>
7865
7866 EXCEPTION
7867 WHEN FND_API.g_exc_unexpected_error THEN
7868 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
7869 p_proc_name => l_proc_name,
7870 p_progress => l_progress,
7871 p_add_to_msg_list => FALSE );
7872 RAISE FND_API.g_exc_unexpected_error;
7873 WHEN OTHERS THEN
7874 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
7875 p_proc_name => l_proc_name,
7876 p_progress => l_progress );
7877 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7878 END create_split_distributions;
7879
7880 -------------------------------------------------------------------------------
7881 --Start of Comments
7882 --Name: delete_records
7883 --Function:
7884 -- Deletes the lines, shipments, and distributions with delete_record set to
7885 -- G_PARAMETER_YES.
7886 --Pre-reqs:
7887 -- None.
7888 --Modifies:
7889 -- PO_LINES, PO_LINE_LOCATIONS, PO_DISTRIBUTIONS
7890 --Locks:
7891 -- None.
7892 --End of Comments
7893 -------------------------------------------------------------------------------
7894 PROCEDURE delete_records (
7895 p_chg IN PO_CHANGES_REC_TYPE
7896 ) IS
7897 l_proc_name CONSTANT VARCHAR2(30) := 'DELETE_RECORDS';
7898 l_module CONSTANT VARCHAR2(80) := g_module_prefix || l_proc_name;
7899 l_progress VARCHAR2(3) := '000';
7900 l_rowid VARCHAR2(2000);
7901 BEGIN
7902 IF (g_fnd_debug = 'Y') THEN
7903 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
7904 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
7905 module => l_module,
7906 message => 'Entering ' || l_proc_name );
7907 END IF;
7908 END IF;
7909
7910 -- Delete the requested distributions.
7911 l_progress := '010';
7912 FOR i IN 1..p_chg.distribution_changes.get_count LOOP
7913 IF (p_chg.distribution_changes.delete_record(i) = G_PARAMETER_YES) THEN
7914 SELECT rowid
7915 INTO l_rowid
7916 FROM po_distributions
7917 WHERE po_distribution_id
7918 = p_chg.distribution_changes.po_distribution_id(i);
7919
7920 PO_DISTRIBUTIONS_PKG2.delete_row ( l_rowid );
7921 END IF;
7922 END LOOP;
7923
7924 -- Delete the requested shipments and their children.
7925 l_progress := '020';
7926 FOR i IN 1..p_chg.shipment_changes.get_count LOOP
7927 IF (p_chg.shipment_changes.delete_record(i) = G_PARAMETER_YES) THEN
7928 SELECT rowid
7929 INTO l_rowid
7930 FROM po_line_locations
7931 WHERE line_location_id = p_chg.shipment_changes.po_line_location_id(i);
7932
7933 PO_SHIPMENTS_SV4.delete_shipment (
7934 x_line_location_id => p_chg.shipment_changes.po_line_location_id(i),
7935 x_row_id => l_rowid,
7936 x_doc_header_id => g_po_header_id,
7937 x_shipment_type => p_chg.shipment_changes.c_shipment_type(i)
7938 );
7939 END IF;
7940 END LOOP;
7941
7942 -- Delete the requested lines and their children.
7943 l_progress := '030';
7944 FOR i IN 1..p_chg.line_changes.get_count LOOP
7945 IF (p_chg.line_changes.delete_record(i) = G_PARAMETER_YES) THEN
7946 SELECT rowid
7947 INTO l_rowid
7948 FROM po_lines
7949 WHERE po_line_id = p_chg.line_changes.po_line_id(i);
7950
7951 PO_LINES_SV.delete_line (
7952 x_type_lookup_code => g_document_subtype,
7953 x_po_line_id => p_chg.line_changes.po_line_id(i),
7954 x_row_id => l_rowid
7955 );
7956 END IF;
7957 END LOOP;
7958
7959 l_progress := '040';
7960
7961 EXCEPTION
7962 WHEN FND_API.g_exc_unexpected_error THEN
7963 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
7964 p_proc_name => l_proc_name,
7965 p_progress => l_progress,
7966 p_add_to_msg_list => FALSE );
7967 RAISE FND_API.g_exc_unexpected_error;
7968 WHEN OTHERS THEN
7969 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
7970 p_proc_name => l_proc_name,
7971 p_progress => l_progress );
7972 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7973 END delete_records;
7974
7975 -------------------------------------------------------------------------------
7976 --Start of Comments
7977 --Name: calculate_taxes
7978 --Function:
7979 -- Calculates the taxes on all of the modified shipments.
7980 --Pre-reqs:
7981 -- None.
7982 --Modifies:
7983 -- Updates the RECOVERABLE_TAX and NONRECOVERABLE_TAX columns in
7984 -- PO_DISTRIBUTIONS_ALL.
7985 --Locks:
7986 -- None.
7987 --End of Comments
7988 -------------------------------------------------------------------------------
7989 PROCEDURE calculate_taxes (
7990 p_chg IN PO_CHANGES_REC_TYPE
7991 ) IS
7992
7993 BEGIN
7994 NULL;
7995 --<R12 eTax Integration>, stubbed out procedure
7996 END calculate_taxes;
7997
7998 -------------------------------------------------------------------------------
7999 --Start of Comments
8000 --Name: launch_po_approval_wf
8001 --Function:
8002 -- Launches the Document Approval workflow for the given document.
8003 --Pre-reqs:
8004 -- The Applications context must be set before calling this API - i.e.:
8005 -- FND_GLOBAL.apps_initialize ( user_id => <user ID>,
8006 -- resp_id => <responsibility ID>,
8007 -- resp_appl_id => 201 );
8008 --Modifies:
8009 -- Modifies the approval status, etc. on the PO/release.
8010 --Locks:
8011 -- None.
8012 --Parameters:
8013 --IN:
8014 --p_document_id
8015 -- This value for this parameter depends on the p_document_type:
8016 -- 'PO' or 'PA': PO_HEADERS_ALL.po_header_id
8017 -- 'RELEASE': PO_RELEASES_ALL.po_release_id
8018 --p_document_type
8019 -- 'PO', 'PA', 'RELEASE'
8020 --p_document_subtype
8021 -- The value for this parameter depends on the p_document_type:
8022 -- 'PO' or 'PA': PO_HEADERS_ALL.type_lookup_code
8023 -- 'RELEASE': PO_RELEASES_ALL.release_type
8024 --p_preparer_id
8025 -- EMPLOYEE_ID of the buyer whose approval authority should be used in the
8026 -- approval workflow; if NULL, use the buyer on the document.
8027 --p_approval_background_flag
8028 -- PO_CORE_S.G_PARAMETER_NO or NULL: Launch the PO Approval Workflow in
8029 -- synchronous mode, where we issue a commit and launch the workflow.
8030 -- Control does not return to the caller until the workflow completes or
8031 -- reaches a wait node (ex. when it sends a notification to the approver).
8032 -- PO_CORE_S.G_PARAMETER_YES: Launch the PO Approval Workflow in background
8033 -- mode, where we start the workflow in the background and return
8034 -- immediately, without issuing any commits.
8035 --p_mass_update_releases
8036 -- <RETROACTIVE FPI> Blankets / GAs only: If 'Y', we will update the price
8037 -- on the releases of the blanket or standard POs of the GA with the
8038 -- retroactive price change on the blanket/GA line.
8039 --p_retroactive_price_change
8040 -- This parameter is used for performance reasons only.
8041 -- <RETROACTIVE FPI> Releases / Standard POs only: If 'Y', indicates that
8042 -- this release/PO has been updated with a retroactive price change.
8043 -- If NULL or 'N', start_wf_process will query the database to figure out
8044 -- if there was a retroactive price change.
8045 --Notes:
8046 -- Bug 3605355 Added more parameters to this procedure, so that we can expose
8047 -- it as a Group API.
8048 --End of Comments
8049 -------------------------------------------------------------------------------
8050 PROCEDURE launch_po_approval_wf (
8051 p_api_version IN NUMBER,
8052 p_init_msg_list IN VARCHAR2,
8053 x_return_status OUT NOCOPY VARCHAR2,
8054 p_document_id IN NUMBER,
8055 p_document_type IN PO_DOCUMENT_TYPES_ALL_B.document_type_code%TYPE,
8056 p_document_subtype IN PO_DOCUMENT_TYPES_ALL_B.document_subtype%TYPE,
8057 p_preparer_id IN NUMBER,
8058 p_approval_background_flag IN VARCHAR2,
8059 p_mass_update_releases IN VARCHAR2,
8060 p_retroactive_price_change IN VARCHAR2
8061 ) IS
8062 l_proc_name CONSTANT VARCHAR2(30) := 'LAUNCH_PO_APPROVAL_WF';
8063 l_api_version CONSTANT NUMBER := 1.0;
8064 l_progress VARCHAR2(3) := '000';
8065
8066 l_preparer_id PO_HEADERS_ALL.agent_id%TYPE;
8067 l_printflag VARCHAR2(1) := 'N';
8068 l_faxflag VARCHAR2(1) := 'N';
8069 l_faxnum VARCHAR2(30); --Bug 5765243
8070 l_emailflag VARCHAR2(1) := 'N';
8071 l_emailaddress PO_VENDOR_SITES.email_address%TYPE;
8072 l_default_method PO_VENDOR_SITES.supplier_notif_method%TYPE;
8073 l_document_num PO_HEADERS.segment1%TYPE;
8074 BEGIN
8075 IF (g_fnd_debug = 'Y') THEN
8076 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= FND_LOG.LEVEL_PROCEDURE) THEN
8077 FND_LOG.string( log_level => FND_LOG.LEVEL_PROCEDURE,
8078 module => g_module_prefix || l_proc_name,
8079 message => 'Entering ' || l_proc_name
8080 || '; document_id: ' || p_document_id
8081 || ' document_type: ' || p_document_type
8082 || ' document_subtype: ' || p_document_subtype
8083 || ' preparer_id: ' || p_preparer_id
8084 || ' approval_background: '||p_approval_background_flag
8085 || ' mass_update_releases: '||p_mass_update_releases
8086 || ' retroactive_price: '||p_retroactive_price_change );
8087 END IF;
8088 END IF;
8089
8090 x_return_status := FND_API.G_RET_STS_SUCCESS;
8091
8092 -- Standard API initialization:
8093 IF NOT FND_API.compatible_api_call (
8094 p_current_version_number => l_api_version,
8095 p_caller_version_number => p_api_version,
8096 p_api_name => l_proc_name,
8097 p_pkg_name => g_pkg_name ) THEN
8098 RAISE FND_API.g_exc_unexpected_error;
8099 END IF;
8100
8101 IF (FND_API.to_boolean(p_init_msg_list)) THEN
8102 FND_MSG_PUB.initialize();
8103 END IF;
8104
8105 IF (p_preparer_id IS NOT NULL) THEN
8106 -- Launch approvals using the approval hierarchy of p_preparer_id.
8107 l_preparer_id := p_preparer_id;
8108 ELSE
8109 -- Launch approvals using the hierarchy of the buyer on the document.
8110 l_preparer_id := NULL;
8111 END IF;
8112
8113 l_progress := '010';
8114
8115 -- Retrieve some settings for launching the PO Approval workflow.
8116 PO_VENDOR_SITES_SV.get_transmission_defaults (
8117 p_document_id => p_document_id,
8118 p_document_type => p_document_type,
8119 p_document_subtype => p_document_subtype,
8120 p_preparer_id => l_preparer_id, -- IN OUT parameter
8121 x_default_method => l_default_method,
8122 x_email_address => l_emailaddress,
8123 x_fax_number => l_faxnum,
8124 x_document_num => l_document_num
8125 );
8126
8127 IF (l_default_method = 'EMAIL') AND (l_emailaddress IS NOT NULL) THEN
8128 l_emailflag := 'Y';
8129 ELSIF (l_default_method = 'FAX') AND (l_faxnum IS NOT NULL) then
8130 l_emailaddress := NULL;
8131 l_faxflag := 'Y';
8132 ELSIF (l_default_method = 'PRINT') then
8133 l_emailaddress := null;
8134 l_faxnum := null;
8135 l_printflag := 'Y';
8136 ELSE
8137 l_emailaddress := null;
8138 l_faxnum := null;
8139 END IF; -- l_default_method
8140
8141 l_progress := '020';
8142
8143 -- Launch the PO Approval workflow.
8144 PO_REQAPPROVAL_INIT1.start_wf_process (
8145 ItemType => NULL, -- defaulted in start_wf_process
8146 ItemKey => NULL, -- defaulted in start_wf_process
8147 WorkflowProcess => NULL, -- defaulted in start_wf_process
8148 ActionOriginatedFrom => NULL,
8149 DocumentID => p_document_id,
8150 DocumentNumber => NULL,
8151 PreparerID => l_preparer_id,
8152 DocumentTypeCode => p_document_type,
8153 DocumentSubtype => p_document_subtype,
8154 SubmitterAction => NULL,
8155 ForwardToID => NULL,
8156 ForwardFromID => NULL,
8157 DefaultApprovalPathID => NULL,
8158 Note => NULL,
8159 PrintFlag => l_printflag,
8160 FaxFlag => l_faxflag,
8161 FaxNumber => l_faxnum,
8162 EmailFlag => l_emailflag,
8163 EmailAddress => l_emailaddress,
8164 MassUpdateReleases => p_mass_update_releases, -- Bug 3373453
8165 RetroactivePriceChange => p_retroactive_price_change,
8166 p_background_flag => NVL(p_approval_background_flag, G_PARAMETER_NO)
8167 );
8168
8169 l_progress := '030';
8170 EXCEPTION
8171 WHEN FND_API.g_exc_unexpected_error THEN
8172 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
8173 p_proc_name => l_proc_name,
8174 p_progress => l_progress,
8175 p_add_to_msg_list => FALSE );
8176 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
8177 WHEN OTHERS THEN
8178 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
8179 p_proc_name => l_proc_name,
8180 p_progress => l_progress );
8181 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
8182 END launch_po_approval_wf;
8183
8184 -------------------------------------------------------------------------------
8185 -- The following procedures manage the change indexes, which allow us
8186 -- to quickly retrieve a line/shipment/distribution change by
8187 -- PO_LINE_ID, LINE_LOCATION_ID, or PO_DISTRIBUTION_ID:
8188
8189 -------------------------------------------------------------------------------
8190 --Start of Comments
8191 --Name: init_change_indexes
8192 --Function:
8193 -- Clears the change indexes, including the line changes index, the
8194 -- shipment changess index, etc.
8195 --Pre-reqs:
8196 -- None.
8197 --Modifies:
8198 -- g_line_changes_index, g_ship_changes_index, g_dist_changes_index,
8199 -- g_split_ship_changes_tbl, g_split_dist_changes_tbl
8200 --Locks:
8201 -- None.
8202 --End of Comments
8203 -------------------------------------------------------------------------------
8204 PROCEDURE init_change_indexes
8205 IS
8206 BEGIN
8207 g_line_changes_index.DELETE;
8208 g_ship_changes_index.DELETE;
8209 g_dist_changes_index.DELETE;
8210 g_split_ship_changes_tbl := PO_TBL_NUMBER();
8211 g_split_dist_changes_tbl := PO_TBL_NUMBER();
8212 END init_change_indexes;
8213
8214 -------------------------------------------------------------------------------
8215 --Start of Comments
8216 --Name: add_line_change_to_index
8217 --Function:
8218 -- Adds the i-th line change in p_chg to the line changes index.
8219 -- Raises an unexpected exception if the index already has a change
8220 -- for the same PO_LINE_ID.
8221 --Pre-reqs:
8222 -- None.
8223 --Modifies:
8224 -- g_line_changes_index
8225 --Locks:
8226 -- None.
8227 --End of Comments
8228 -------------------------------------------------------------------------------
8229 PROCEDURE add_line_change_to_index (
8230 p_chg IN PO_CHANGES_REC_TYPE,
8231 i IN NUMBER
8232 ) IS
8233 l_po_line_id NUMBER;
8234 BEGIN
8235 l_po_line_id := p_chg.line_changes.po_line_id(i);
8236
8237 IF g_line_changes_index.EXISTS(l_po_line_id) THEN
8238 -- Error: This is a duplicate change for the same PO_LINE_ID.
8239 FND_MESSAGE.set_name('PO', 'PO_CHNG_DUP_LINE');
8240 FND_MSG_PUB.add;
8241 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
8242 END IF;
8243
8244 -- Add this change to the index.
8245 g_line_changes_index(l_po_line_id) := i;
8246 END add_line_change_to_index;
8247
8248 -------------------------------------------------------------------------------
8249 --Start of Comments
8250 --Name: add_ship_change_to_index
8251 --Function:
8252 -- Adds the i-th shipment change in p_chg to the shipment changes index.
8253 -- Raises an unexpected exception if the index already has a change
8254 -- for the same PO_LINE_LOCATION_ID.
8255 --Pre-reqs:
8256 -- The c_po_line_id field of this shipment change must contain the po_line_id
8257 -- of the shipment.
8258 --Modifies:
8259 -- g_ship_changes_index
8260 --Locks:
8261 -- None.
8262 --End of Comments
8263 -------------------------------------------------------------------------------
8264 PROCEDURE add_ship_change_to_index (
8265 p_chg IN PO_CHANGES_REC_TYPE,
8266 i IN NUMBER
8267 ) IS
8268 l_line_location_id PO_LINE_LOCATIONS.line_location_id%TYPE;
8269 l_po_line_id PO_LINES.po_line_id%TYPE;
8270 c NUMBER;
8271 BEGIN
8272 l_line_location_id := p_chg.shipment_changes.po_line_location_id(i);
8273
8274 IF (l_line_location_id IS NOT NULL) THEN -- Existing shipment
8275
8276 IF g_ship_changes_index.EXISTS(l_line_location_id) THEN
8277 -- Error: This is a duplicate change for the same LINE_LOCATION_ID.
8278 FND_MESSAGE.set_name('PO', 'PO_CHNG_DUP_SHIPMENT');
8279 FND_MSG_PUB.add;
8280 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
8281 END IF;
8282
8283 -- Add this to the index of shipment changes by LINE_LOCATION_ID.
8284 -- Key: LINE_LOCATION_ID
8285 -- Value: subscript of the shipment change
8286 g_ship_changes_index(l_line_location_id) := i;
8287
8288 ELSE -- Split shipment
8289
8290 -- Add this to the table of split shipment changes.
8291 -- Value: subscript of the split shipment change
8292 g_split_ship_changes_tbl.extend;
8293 c := g_split_ship_changes_tbl.count;
8294 g_split_ship_changes_tbl(c) := i;
8295
8296 END IF; -- l_line_location_id...
8297
8298 END add_ship_change_to_index;
8299
8300 -------------------------------------------------------------------------------
8301 --Start of Comments
8302 --Name: add_dist_change_to_index
8303 --Function:
8304 -- Adds the i-th distribution change in p_chg to the distribution changes
8305 -- index. Raises an unexpected exception if the index already has a
8306 -- change for the same PO_DISTRIBUTION_ID.
8307 --Pre-reqs:
8308 -- None.
8309 --Modifies:
8310 -- g_dist_changes_index
8311 --Locks:
8312 -- None.
8313 --End of Comments
8314 -------------------------------------------------------------------------------
8315 PROCEDURE add_dist_change_to_index (
8316 p_chg IN PO_CHANGES_REC_TYPE,
8317 i IN NUMBER
8318 ) IS
8319 l_po_distribution_id PO_DISTRIBUTIONS.po_distribution_id%TYPE;
8320 l_line_location_id PO_LINE_LOCATIONS.line_location_id%TYPE;
8321 c NUMBER;
8322 BEGIN
8323 l_po_distribution_id := p_chg.distribution_changes.po_distribution_id(i);
8324
8325 IF (l_po_distribution_id IS NOT NULL) THEN -- Existing distribution
8326
8327 IF g_dist_changes_index.EXISTS(l_po_distribution_id) THEN
8328 -- Error: This is a duplicate change for the same PO_DISTRIBUTION_ID.
8329 FND_MESSAGE.set_name('PO', 'PO_CHNG_DUP_DISTRIBUTION');
8330 FND_MSG_PUB.add;
8331 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
8332 END IF;
8333
8334 -- Add this to the index of distribution changes by PO_DISTRIBUTION_ID.
8335 -- Key: PO_DISTRIBUTION_ID
8336 -- Value: subscript of the distribution change
8337 g_dist_changes_index(l_po_distribution_id) := i;
8338
8339 ELSE -- Split distribution
8340
8341 -- Add this to the table of split distribution changes.
8342 -- Value: subscript of the split distribution change
8343 g_split_dist_changes_tbl.extend;
8344 c := g_split_dist_changes_tbl.count;
8345 g_split_dist_changes_tbl(c) := i;
8346
8347 END IF; -- l_po_distribution_id...
8348
8349 END add_dist_change_to_index;
8350
8351 -------------------------------------------------------------------------------
8352 --Start of Comments
8353 --Name: get_line_change
8354 --Function:
8355 -- Returns the index of the line change for p_po_line_id.
8356 -- If none exists, returns NULL.
8357 --Pre-reqs:
8358 -- None.
8359 --Modifies:
8360 -- None.
8361 --Locks:
8362 -- None.
8363 --End of Comments
8364 -------------------------------------------------------------------------------
8365 FUNCTION get_line_change (
8366 p_po_line_id IN PO_LINES.po_line_id%TYPE
8367 ) RETURN NUMBER IS
8368 i NUMBER;
8369 BEGIN
8370 IF g_line_changes_index.EXISTS(p_po_line_id) THEN
8371 RETURN g_line_changes_index(p_po_line_id);
8372 ELSE
8373 RETURN NULL;
8374 END IF;
8375 END get_line_change;
8376
8377 -------------------------------------------------------------------------------
8378 --Start of Comments
8379 --Name: find_line_change
8380 --Function:
8381 -- Returns the index of the line change for p_po_line_id.
8382 -- If none exists, adds a line change for p_po_line_id and returns its index.
8383 --Pre-reqs:
8384 -- None.
8385 --Modifies:
8386 -- Adds a line change for p_po_line_id to p_chg, if needed.
8387 --Locks:
8388 -- None.
8389 --Notes:
8390 -- get_line_change and find_line_change differ in their behavior when the
8391 -- requested change does not exist.
8392 -- get_line_change returns NULL, while find_line_change creates a new change.
8393 --End of Comments
8394 -------------------------------------------------------------------------------
8395 FUNCTION find_line_change (
8396 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
8397 p_po_line_id IN PO_LINES.po_line_id%TYPE
8398 ) RETURN NUMBER IS
8399 i NUMBER;
8400 BEGIN
8401 i := get_line_change(p_po_line_id);
8402 IF (i IS NULL) THEN
8403 -- This line change does not exist yet. Create a new one.
8404 p_chg.line_changes.add_change(p_po_line_id);
8405 i := p_chg.line_changes.get_count;
8406
8407 populate_line_cached_fields(p_chg, i);
8408 add_line_change_to_index(p_chg, i);
8409 END IF; -- i is null
8410
8411 RETURN i;
8412 END find_line_change;
8413
8414 -------------------------------------------------------------------------------
8415 --Start of Comments
8416 --Name: get_ship_change
8417 --Function:
8418 -- Returns the index of the shipment change for p_po_line_id.
8419 -- If none exists, returns NULL.
8420 --Pre-reqs:
8421 -- None.
8422 --Modifies:
8423 -- None.
8424 --Locks:
8425 -- None.
8426 --End of Comments
8427 -------------------------------------------------------------------------------
8428 FUNCTION get_ship_change (
8429 p_line_location_id IN PO_LINE_LOCATIONS.line_location_id%TYPE
8430 ) RETURN NUMBER IS
8431 i NUMBER;
8432 BEGIN
8433 IF g_ship_changes_index.EXISTS(p_line_location_id) THEN
8434 RETURN g_ship_changes_index(p_line_location_id);
8435 ELSE
8436 RETURN NULL;
8437 END IF;
8438 END get_ship_change;
8439
8440 -------------------------------------------------------------------------------
8441 --Start of Comments
8442 --Name: find_ship_change
8443 --Function:
8444 -- Returns the index of the shipment change for p_line_location_id.
8445 -- If none exists, adds a shipment change for p_line_location_id and
8446 -- returns its index.
8447 --Pre-reqs:
8448 -- None.
8449 --Modifies:
8450 -- Adds a shipment change for p_line_location_id to p_chg, if needed.
8451 --Locks:
8452 -- None.
8453 --End of Comments
8454 -------------------------------------------------------------------------------
8455 FUNCTION find_ship_change (
8456 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
8457 p_line_location_id IN PO_LINE_LOCATIONS.line_location_id%TYPE
8458 ) RETURN NUMBER IS
8459 i NUMBER;
8460 BEGIN
8461 i := get_ship_change(p_line_location_id);
8462 IF (i IS NULL) THEN
8463 -- This shipment change does not exist yet. Create a new one.
8464 p_chg.shipment_changes.add_change(p_line_location_id);
8465 i := p_chg.shipment_changes.get_count;
8466
8467 populate_ship_cached_fields(p_chg, i);
8468 add_ship_change_to_index(p_chg, i);
8469 END IF; -- i is null
8470
8471 RETURN i;
8472 END find_ship_change;
8473
8474 -------------------------------------------------------------------------------
8475 --Start of Comments
8476 --Name: get_dist_change
8477 --Function:
8478 -- Returns the index of the distribution change for p_po_distribution_id.
8479 -- If none exists, returns NULL.
8480 --Pre-reqs:
8481 -- None.
8482 --Modifies:
8483 -- None.
8484 --Locks:
8485 -- None.
8486 --End of Comments
8487 -------------------------------------------------------------------------------
8488 FUNCTION get_dist_change (
8489 p_po_distribution_id IN PO_DISTRIBUTIONS.po_distribution_id%TYPE
8490 ) RETURN NUMBER IS
8491 i NUMBER;
8492 BEGIN
8493 IF g_dist_changes_index.EXISTS(p_po_distribution_id) THEN
8494 RETURN g_dist_changes_index(p_po_distribution_id);
8495 ELSE
8496 RETURN NULL;
8497 END IF;
8498 END get_dist_change;
8499
8500 -------------------------------------------------------------------------------
8501 --Start of Comments
8502 --Name: find_dist_change
8503 --Function:
8504 -- Returns the index of the distribution change for p_po_distribution_id.
8505 -- If none exists, adds a distribution change for p_po_distribution_id and
8506 -- returns its index.
8507 --Pre-reqs:
8508 -- None.
8509 --Modifies:
8510 -- Adds a distribution change for p_po_distribution_id to p_chg, if needed.
8511 --Locks:
8512 -- None.
8513 --End of Comments
8514 -------------------------------------------------------------------------------
8515 FUNCTION find_dist_change (
8516 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
8517 p_po_distribution_id IN PO_DISTRIBUTIONS.po_distribution_id%TYPE
8518 ) RETURN NUMBER IS
8519 i NUMBER;
8520 BEGIN
8521 i := get_dist_change(p_po_distribution_id);
8522 IF (i IS NULL) THEN
8523 -- This distribution change does not exist yet. Create a new one.
8524 p_chg.distribution_changes.add_change(p_po_distribution_id);
8525 i := p_chg.distribution_changes.get_count;
8526
8527 populate_dist_cached_fields(p_chg, i);
8528 add_dist_change_to_index(p_chg, i);
8529 END IF; -- i is null
8530
8531 RETURN i;
8532 END find_dist_change;
8533
8534 -------------------------------------------------------------------------------
8535 --Start of Comments
8536 --Name: get_split_ship_change
8537 --Function:
8538 -- Returns the index of the split shipment change for p_parent_line_location_id
8539 -- and p_split_shipment_num. If none exists, returns NULL.
8540 --Pre-reqs:
8541 -- None.
8542 --Modifies:
8543 -- None.
8544 --Locks:
8545 -- None.
8546 --End of Comments
8547 -------------------------------------------------------------------------------
8548 FUNCTION get_split_ship_change (
8549 p_chg IN PO_CHANGES_REC_TYPE,
8550 p_po_line_id IN PO_LINES.po_line_id%TYPE,
8551 p_parent_line_loc_id IN PO_LINE_LOCATIONS.line_location_id%TYPE,
8552 p_split_shipment_num IN PO_LINE_LOCATIONS.shipment_num%TYPE
8553 ) RETURN NUMBER IS
8554 l_ship_chg_i NUMBER;
8555 BEGIN
8556 -- Loop through the split shipment changes.
8557 FOR l_split_ship_tbl_i IN 1..g_split_ship_changes_tbl.COUNT LOOP
8558 l_ship_chg_i := g_split_ship_changes_tbl(l_split_ship_tbl_i);
8559
8560 -- Identify the split shipment using the parent line_location_id and
8561 -- split shipment number.
8562 IF (p_chg.shipment_changes.parent_line_location_id(l_ship_chg_i)
8563 = p_parent_line_loc_id)
8564 AND (p_chg.shipment_changes.split_shipment_num(l_ship_chg_i)
8565 = p_split_shipment_num) THEN
8566 RETURN l_ship_chg_i; -- Found the split shipment.
8567 END IF;
8568
8569 END LOOP; -- split shipment changes
8570
8571 RETURN NULL; -- None of the split shipments matched.
8572 END get_split_ship_change;
8573
8574 -------------------------------------------------------------------------------
8575 --Start of Comments
8576 --Name: get_split_dist_change
8577 --Function:
8578 -- Returns the index of the split distribution change for
8579 -- p_parent_distribution_id and p_split_shipment_num.
8580 -- If none exists, returns NULL.
8581 --Pre-reqs:
8582 -- None.
8583 --Modifies:
8584 -- None.
8585 --Locks:
8586 -- None.
8587 --End of Comments
8588 -------------------------------------------------------------------------------
8589 FUNCTION get_split_dist_change (
8590 p_chg IN PO_CHANGES_REC_TYPE,
8591 p_parent_distribution_id IN PO_DISTRIBUTIONS.po_distribution_id%TYPE,
8592 p_parent_line_loc_id IN PO_LINE_LOCATIONS.line_location_id%TYPE,
8593 p_split_shipment_num IN PO_LINE_LOCATIONS.shipment_num%TYPE
8594 ) RETURN NUMBER IS
8595 l_dist_chg_i NUMBER;
8596 BEGIN
8597 -- Loop through the split distribution changes.
8598 FOR l_split_dist_tbl_i IN 1..g_split_dist_changes_tbl.COUNT LOOP
8599 l_dist_chg_i := g_split_dist_changes_tbl(l_split_dist_tbl_i);
8600
8601 -- Uniquely identify the split distribution using parent distribution id
8602 -- and split shipment number.
8603 IF (p_chg.distribution_changes.parent_distribution_id(l_dist_chg_i)
8604 = p_parent_distribution_id)
8605 AND (p_chg.distribution_changes.split_shipment_num(l_dist_chg_i)
8606 = p_split_shipment_num) THEN
8607 RETURN l_dist_chg_i; -- Found the split distribution.
8608 END IF;
8609
8610 END LOOP; -- split distribution changes
8611
8612 RETURN NULL; -- None of the split distributions matched.
8613 END get_split_dist_change;
8614
8615 -------------------------------------------------------------------------------
8616 --Start of Comments
8617 --Name: find_split_dist_change
8618 --Function:
8619 -- Returns the index of the split distribution change for
8620 -- p_parent_distribution_id and p_split_shipment_num.
8621 -- If none exists, adds a distribution change for this split distribution
8622 -- and returns its index.
8623 --Pre-reqs:
8624 -- None.
8625 --Modifies:
8626 -- Adds a split distribution change to p_chg, if needed.
8627 --Locks:
8628 -- None.
8629 --End of Comments
8630 -------------------------------------------------------------------------------
8631 FUNCTION find_split_dist_change (
8632 p_chg IN OUT NOCOPY PO_CHANGES_REC_TYPE,
8633 p_parent_distribution_id IN PO_DISTRIBUTIONS.po_distribution_id%TYPE,
8634 p_parent_line_loc_id IN PO_LINE_LOCATIONS.line_location_id%TYPE,
8635 p_split_shipment_num IN PO_LINE_LOCATIONS.shipment_num%TYPE
8636 ) RETURN NUMBER IS
8637 i NUMBER;
8638 BEGIN
8639 i := get_split_dist_change(p_chg, p_parent_distribution_id,
8640 p_parent_line_loc_id, p_split_shipment_num);
8641 IF (i IS NULL) THEN
8642 -- This distribution change does not exist yet. Create a new one.
8643 p_chg.distribution_changes.add_change(
8644 p_po_distribution_id => NULL,
8645 p_parent_distribution_id => p_parent_distribution_id,
8646 p_split_shipment_num => p_split_shipment_num
8647 );
8648 i := p_chg.distribution_changes.get_count;
8649
8650 populate_dist_cached_fields(p_chg, i);
8651 add_dist_change_to_index(p_chg, i);
8652 END IF; -- i is null
8653
8654 RETURN i;
8655 END find_split_dist_change;
8656
8657 -------------------------------------------------------------------------------
8658 --Start of Comments
8659 --Name: add_error
8660 --Function:
8661 -- Adds an error message to p_api_errors.
8662 -- If p_message_text is null, retrieves the message text by calling the
8663 -- FND message dictionary with p_message_name and the token/value pairs
8664 -- for token substitution.
8665 --Pre-reqs:
8666 -- p_api_errors should be initialized.
8667 --Modifies:
8668 -- p_api_errors
8669 --Locks:
8670 -- None.
8671 --Parameters:
8672 --OUT:
8673 --x_return_status
8674 -- This procedure always returns FND_API.G_RET_STS_ERROR.
8675 --End of Comments
8676 -------------------------------------------------------------------------------
8677 PROCEDURE add_error
8678 ( p_api_errors IN OUT NOCOPY PO_API_ERRORS_REC_TYPE,
8679 x_return_status OUT NOCOPY VARCHAR2,
8680 p_message_name IN VARCHAR2,
8681 p_message_text IN VARCHAR2,
8682 p_table_name IN VARCHAR2,
8683 p_column_name IN VARCHAR2,
8684 p_entity_type IN VARCHAR2,
8685 p_entity_id IN NUMBER,
8686 p_token_name1 IN VARCHAR2,
8687 p_token_value1 IN VARCHAR2,
8688 p_token_name2 IN VARCHAR2,
8689 p_token_value2 IN VARCHAR2,
8690 p_module IN VARCHAR2,
8691 p_level IN VARCHAR2,
8692 p_message_type IN VARCHAR2
8693 ) IS
8694 l_message_text PO_INTERFACE_ERRORS.error_message%TYPE;
8695 l_progress VARCHAR2(3) := '000';
8696 -- Bug 4618614: Workaround GSCC error for checking logging statement.
8697 l_debug VARCHAR2(400);
8698 BEGIN
8699 -- Bug 4618614: Workaround GSCC error for checking logging statement.
8700 l_debug := NVL(p_level, FND_LOG.LEVEL_ERROR);
8701 IF (p_api_errors IS NULL) THEN
8702 p_api_errors := PO_API_ERRORS_REC_TYPE.create_object();
8703 END IF;
8704
8705 IF (p_message_text IS NULL) THEN
8706 l_progress := '010';
8707 FND_MESSAGE.set_name('PO', p_message_name);
8708
8709 if (p_token_name1 is not null) then
8710 FND_MESSAGE.set_token(p_token_name1, p_token_value1);
8711 end if;
8712
8713 IF (p_token_name2 IS NOT NULL) THEN
8714 FND_MESSAGE.set_token(p_token_name2, p_token_value2);
8715 END IF;
8716
8717 l_message_text := FND_MESSAGE.get;
8718 ELSE
8719 l_message_text := p_message_text;
8720 END IF;
8721
8722 l_progress := '020';
8723 p_api_errors.add_error (
8724 p_message_name => p_message_name,
8725 p_message_text => l_message_text,
8726 p_table_name => p_table_name,
8727 p_column_name => p_column_name,
8728 p_entity_type => p_entity_type,
8729 p_entity_id => p_entity_id,
8730 p_message_type => p_message_type
8731 );
8732
8733 l_progress := '030';
8734 IF (g_fnd_debug = 'Y') THEN
8735 -- Bug 4618614: Workaround GSCC error for checking logging statement.
8736 IF (FND_LOG.G_CURRENT_RUNTIME_LEVEL <= l_debug)
8737 THEN
8738 FND_LOG.string( l_debug,
8739 NVL(p_module, g_module_prefix||'add_error'),
8740 l_message_text );
8741 END IF;
8742 END IF;
8743
8744 x_return_status := FND_API.G_RET_STS_ERROR;
8745 EXCEPTION
8746 WHEN FND_API.g_exc_unexpected_error THEN
8747 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
8748 p_proc_name => 'ADD_ERROR',
8749 p_progress => l_progress,
8750 p_add_to_msg_list => FALSE );
8751 RAISE FND_API.g_exc_unexpected_error;
8752 WHEN OTHERS THEN
8753 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
8754 p_proc_name => 'ADD_ERROR',
8755 p_progress => l_progress );
8756 RAISE FND_API.g_exc_unexpected_error;
8757 END add_error;
8758
8759 -------------------------------------------------------------------------------
8760 --Start of Comments
8761 --Name: add_message_list_errors
8762 --Function:
8763 -- Adds the messages on the standard API message list (starting from
8764 -- p_start_index) to p_api_errors. Deletes the messages from the API message
8765 -- list once they have been transferred.
8766 --Pre-reqs:
8767 -- p_api_errors should be initialized.
8768 --Modifies:
8769 -- p_api_errors, API message list
8770 --Locks:
8771 -- None.
8772 --Parameters:
8773 --IN:
8774 --p_start_index
8775 -- Message list index to start from. If NULL, start from 1 - i.e. add all of
8776 -- the messages on the message list to p_api_errors.
8777 --OUT:
8778 --x_return_status
8779 -- This procedure always returns FND_API.G_RET_STS_ERROR.
8780 --End of Comments
8781 -------------------------------------------------------------------------------
8782 PROCEDURE add_message_list_errors
8783 ( p_api_errors IN OUT NOCOPY PO_API_ERRORS_REC_TYPE,
8784 x_return_status OUT NOCOPY VARCHAR2,
8785 p_start_index IN NUMBER,
8786 p_entity_type IN VARCHAR2,
8787 p_entity_id IN NUMBER
8788 ) IS
8789 BEGIN
8790 -- Add the messages to the API errors object.
8791 FOR i IN NVL(p_start_index,1)..FND_MSG_PUB.count_msg LOOP
8792 add_error (
8793 p_api_errors => p_api_errors,
8794 x_return_status => x_return_status,
8795 p_message_name => NULL,
8796 p_message_text =>
8797 FND_MSG_PUB.get ( p_msg_index => i, p_encoded => FND_API.G_FALSE ),
8798 p_entity_type => p_entity_type,
8799 p_entity_id => p_entity_id
8800 );
8801 END LOOP;
8802
8803 -- Delete the messages from the message list.
8804 FOR i IN REVERSE NVL(p_start_index,1)..FND_MSG_PUB.count_msg LOOP
8805 FND_MSG_PUB.delete_msg ( p_msg_index => i );
8806 END LOOP;
8807
8808 x_return_status := FND_API.G_RET_STS_ERROR;
8809 EXCEPTION
8810 WHEN FND_API.g_exc_unexpected_error THEN
8811 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
8812 p_proc_name => 'ADD_MESSAGE_LIST_ERRORS',
8813 p_add_to_msg_list => FALSE );
8814 RAISE FND_API.g_exc_unexpected_error;
8815 WHEN OTHERS THEN
8816 PO_DEBUG.handle_unexp_error ( p_pkg_name => g_pkg_name,
8817 p_proc_name => 'ADD_MESSAGE_LIST_ERRORS' );
8818 RAISE FND_API.g_exc_unexpected_error;
8819 END add_message_list_errors;
8820
8821 -----------------------------------------------------------------------------
8822 --Start of Comments
8823 --Name: validate_delete_action
8824 --Pre-reqs:
8825 -- None
8826 --Modifies:
8827 -- None
8828 --Locks:
8829 -- None
8830 --Function:
8831 -- Checks whether a given po entity LINE/SHIPMENT/DISTRIBUTION
8832 -- can be deleted.
8833 --Parameters:
8834 --IN:
8835 --p_entity
8836 -- the entity which is being deleted [HEADER/LINE/SHIPMENT/DISTRIBUTION]
8837 --p_doc_header_id
8838 -- Header ID of the PO to which the entity being deleted belongs
8839 --p_po_line_id
8840 -- Line ID for the Po line to which the entity being deleted belongs
8841 --p_po_line_loc_id
8842 -- Line Location ID for the Po Shipment to which the entity being deleted belongs
8843 --p_po_distribution_id
8844 -- Distribution ID for the Po Distribution which the entity being deleted belongs
8845 --p_doc_type
8846 -- Document type of the PO [PO/PA]
8847 --OUT:
8848 --x_error_message
8849 -- Translated error message encountered
8850 --Notes:
8851 --It house the logic for validation of delete action of a document or its
8852 --Line/Shipment/Distribution. This API shoule be called
8853 --before initiating a delete action on any level
8854 --End of Comments
8855 -----------------------------------------------------------------------------
8856 PROCEDURE validate_delete_action( p_entity IN VARCHAR2
8857 ,p_doc_type IN VARCHAR2
8858 ,p_doc_header_id IN NUMBER
8859 ,p_po_line_id IN NUMBER
8860 ,p_line_loc_id IN NUMBER
8861 ,p_distribution_id IN NUMBER
8862 ,x_error_message OUT NOCOPY VARCHAR2)
8863 IS
8864 l_modify_action_allowed BOOLEAN := FALSE;
8865 l_style_disp_name PO_DOC_STYLE_LINES_TL.display_name%TYPE;
8866 l_doc_subtype PO_HEADERS_ALL.TYPE_LOOKUP_CODE%TYPE;
8867 l_closed_code PO_HEADERS_ALL.closed_code%TYPE;
8868 l_doc_approved_date PO_HEADERS_ALL.approved_date%TYPE;
8869 l_doc_approved_flag PO_HEADERS_ALL.approved_flag%TYPE;
8870 l_auth_status PO_HEADERS_ALL.authorization_status%TYPE;
8871 l_frozen_flag PO_HEADERS_ALL.frozen_flag%TYPE;
8872 l_conterms_exist_flag PO_HEADERS_ALL.conterms_exist_flag%type;
8873 l_consigned_consumption_flag PO_HEADERS_ALL.consigned_consumption_flag%type;
8874 l_cancel_flag PO_HEADERS_ALL.cancel_flag%type;
8875 l_ga_flag PO_HEADERS_ALL.global_agreement_flag%type;
8876 l_shipment_type PO_LINE_LOCATIONS_ALL.shipment_type%TYPE;
8877 l_allow_delete VARCHAR2(1);
8878 d_pos NUMBER := 0;
8879 l_api_name CONSTANT VARCHAR2(30) := 'validate_delete_action';
8880 d_module CONSTANT VARCHAR2(70) := 'po.plsql.PO_DOCUMENT_UPDATE_PVT.validate_delete_action';
8881
8882 BEGIN
8883 IF (PO_LOG.d_proc) THEN
8884 PO_LOG.proc_begin(d_module); PO_LOG.proc_begin(d_module,'p_entity', p_entity); PO_LOG.proc_begin(d_module,'p_doc_type', p_doc_type); PO_LOG.proc_begin(d_module,'p_doc_header_id', p_doc_header_id);
8885 PO_LOG.proc_begin(d_module,'p_po_line_id', p_po_line_id);PO_LOG.proc_begin(d_module,'p_line_loc_id', p_line_loc_id); PO_LOG.proc_begin(d_module,'p_distribution_id', p_distribution_id);
8886 END IF;
8887
8888 x_error_message := NULL;
8889 d_pos :=10;
8890 SELECT type_lookup_code
8891 ,nvl(closed_code,'OPEN')
8892 ,approved_date
8893 ,approved_flag
8894 ,nvl(frozen_flag,'N')
8895 ,nvl(cancel_flag,'N')
8896 ,nvl(authorization_status,'INCOMPLETE')
8897 ,nvl(global_agreement_flag, 'N')
8898 ,nvl(conterms_exist_flag, 'N')
8899 ,nvl(consigned_consumption_flag, 'N')
8900 INTO l_doc_subtype
8901 ,l_closed_code
8902 ,l_doc_approved_date
8903 ,l_doc_approved_flag
8904 ,l_frozen_flag
8905 ,l_cancel_flag
8906 ,l_auth_status
8907 ,l_ga_flag
8908 ,l_conterms_exist_flag
8909 ,l_consigned_consumption_flag
8910 FROM po_headers_all
8911 WHERE po_header_id = p_doc_header_id;
8912
8913 IF (PO_LOG.d_stmt) THEN
8914 PO_LOG.stmt(d_module,d_pos,'l_doc_subtype', l_doc_subtype); PO_LOG.stmt(d_module,d_pos,'l_closed_code', l_closed_code); PO_LOG.stmt(d_module,d_pos,'l_doc_approved_date', l_doc_approved_date);
8915 PO_LOG.stmt(d_module,d_pos,'l_doc_approved_flag', l_doc_approved_flag); PO_LOG.stmt(d_module,d_pos,'l_auth_status', l_auth_status); PO_LOG.stmt(d_module,d_pos,'l_frozen_flag', l_frozen_flag);
8916 PO_LOG.stmt(d_module,d_pos,'l_conterms_exist_flag', l_conterms_exist_flag); PO_LOG.stmt(d_module,d_pos,'l_consigned_consumption_flag',l_consigned_consumption_flag); PO_LOG.stmt(d_module,d_pos,'l_ga_flag', l_ga_flag);
8917 END IF;
8918
8919 -- checks for update privileges based on the status
8920 -- FROZEN, CANCELLED, FINALLY CLOSED
8921 -- Or it is in In Process or Pre Approved State
8922 d_pos := 20;
8923 IF ( (l_closed_code = PO_CORE_S.g_clsd_FINALLY_CLOSED)
8924 OR (l_frozen_flag = 'Y')
8925 OR (l_cancel_flag = 'Y')
8926 OR (l_auth_status IN ('IN PROCESS', 'PRE-APPROVED')))
8927 THEN
8928 x_error_message := PO_CORE_S.get_translated_text('PO_RQ_DOC_UPDATE_NA');
8929 RAISE PO_CORE_S.G_EARLY_RETURN_EXC;
8930 END IF;
8931
8932 d_pos := 30;
8933 --We should not allow deletion of Consumption Advice POs
8934 If l_consigned_consumption_flag = 'Y'
8935 THEN
8936 x_error_message := PO_CORE_S.get_translated_text('PO_CONSIGNED_UPDATE_ERROR');
8937 RAISE PO_CORE_S.G_EARLY_RETURN_EXC;
8938 END IF;
8939
8940 d_pos := 40;
8941 -- Checks for update privileges based on approver can modify option
8942 -- and the current owner of the document.
8943 PO_SECURITY_CHECK_SV.check_before_lock(l_doc_subtype,
8944 p_doc_header_id,
8945 fnd_global.employee_id,
8946 l_modify_action_allowed);
8947 IF (PO_LOG.d_stmt) THEN
8948 PO_LOG.stmt(d_module,d_pos,'l_modify_action_allowed', l_modify_action_allowed);
8949 END IF;
8950
8951 IF NOT l_modify_action_allowed
8952 THEN
8953 x_error_message := PO_CORE_S.get_translated_text('PO_RQ_DOC_UPDATE_NA');
8954 RAISE PO_CORE_S.G_EARLY_RETURN_EXC;
8955 END IF;
8956
8957 d_pos := 50;
8958 l_style_disp_name := PO_DOC_STYLE_PVT.get_style_display_name(
8959 p_doc_id => p_doc_header_id,
8960 p_language => NULL);
8961
8962 IF (PO_LOG.d_stmt) THEN
8963 PO_LOG.stmt(d_module,d_pos,'l_style_disp_name', l_style_disp_name);
8964 END IF;
8965
8966 d_pos := 60;
8967 IF p_entity = PO_CORE_S.g_doc_level_HEADER
8968 THEN
8969 d_pos := 70;
8970 -- Validates the delete action on the header
8971 PO_HEADERS_SV1.validate_delete_document(
8972 p_doc_type => p_doc_type
8973 ,p_doc_header_id => p_doc_header_id
8974 ,p_doc_approved_date => l_doc_approved_date
8975 ,p_auth_status => l_auth_status
8976 ,p_style_disp_name => l_style_disp_name
8977 ,x_message_text => x_error_message);
8978
8979 ELSIF p_entity = PO_CORE_S.g_doc_level_LINE
8980 THEN
8981 d_pos := 80;
8982 -- Validates the delete action on the line
8983 PO_LINES_SV.check_line_deletion_allowed(
8984 x_po_line_id => p_po_line_id
8985 ,x_allow_delete => l_allow_delete
8986 ,p_token => 'DOCUMENT_TYPE'
8987 ,p_token_value => l_style_disp_name
8988 ,x_message_text => x_error_message);
8989
8990 ELSIF p_entity = PO_CORE_S.g_doc_level_SHIPMENT
8991 THEN
8992 d_pos := 90;
8993 -- Validates the delete action on the shipment
8994 PO_SHIPMENTS_SV4.validate_delete_line_loc(
8995 p_line_loc_id => p_line_loc_id
8996 ,p_po_line_id => p_po_line_id
8997 ,p_doc_type => p_doc_type
8998 ,p_style_disp_name => l_style_disp_name
8999 ,x_message_text => x_error_message);
9000
9001 ELSIF p_entity = PO_CORE_S.g_doc_level_DISTRIBUTION
9002 THEN
9003 d_pos := 100;
9004 -- Validates the delete action on the distribution
9005 PO_DISTRIBUTIONS_SV.validate_delete_distribution(
9006 p_po_distribution_id => p_distribution_id
9007 ,p_line_loc_id => p_line_loc_id
9008 ,p_approved_date => l_doc_approved_date
9009 ,p_style_disp_name => l_style_disp_name
9010 ,x_message_text => x_error_message);
9011
9012 END IF;
9013 d_pos := 110;
9014 IF x_error_message is NOT NULL THEN
9015 RAISE PO_CORE_S.G_EARLY_RETURN_EXC;
9016 END IF;
9017
9018 IF (PO_LOG.d_proc) THEN
9019 PO_LOG.proc_end(d_module);
9020 END IF;
9021
9022 EXCEPTION
9023 WHEN PO_CORE_S.G_EARLY_RETURN_EXC THEN
9024 IF (PO_LOG.d_stmt) THEN
9025 PO_LOG.stmt(d_module,d_pos,'x_error_message', x_error_message);
9026 END IF;
9027 WHEN OTHERS THEN
9028 FND_MSG_PUB.add_exc_msg(g_pkg_name, l_api_name||':'||d_pos);
9029 IF PO_LOG.d_exc THEN
9030 PO_LOG.exc(d_module,d_pos,'Unhandled Exception in ' || SQLCODE||':'||SQLERRM);
9031 END IF;
9032 RAISE;
9033 END validate_delete_action;
9034 -----------------------------------------------------------------------------
9035 --Start of Comments
9036 --Name: process_delete_action
9037 --Pre-reqs:
9038 -- None
9039 --Modifies:
9040 -- None
9041 --Locks:
9042 -- None
9043 --Function:
9044 -- Invokes the corresponding validation and deletion logic when a particular
9045 -- po entity LINE/SHIPMENT/DISTRIBUTION is to be deleted
9046 --Parameters:
9047 --IN:
9048 --p_init_msg_list
9049 -- Standard API specification parameter
9050 -- Pass FND_API.G_FALSE if message list has already been initialized for
9051 -- transaction else pass FND_API.G_TRUE
9052 --p_calling_program
9053 -- Calling module.
9054 --p_entity
9055 -- the entity which is being deleted [HEADER/LINE/SHIPMENT/DISTRIBUTION]
9056 --p_entity_row_id
9057 -- Row ID for the entity record which is being deleted
9058 --p_doc_header_id
9059 -- Header ID of the PO to which the entity being deleted belongs
9060 --p_ga_flag
9061 -- Global Agreement Flag for the document
9062 --p_conterms_exist_flag
9063 -- Contract Terms Flag for the document
9064 --p_po_line_id
9065 -- Line ID for the Po line to which the entity being deleted belongs
9066 --p_po_line_loc_id
9067 -- Line Location ID for the Po Shipment to which the entity being deleted belongs
9068 --p_po_distribution_id
9069 -- Distribution ID for the Po Distribution which the entity being deleted belongs
9070 --p_doc_type
9071 -- Document type of the PO [PO/PA]
9072 --OUT:
9073 --x_return_status
9074 -- Standard API specification parameter
9075 -- Can hold one of the following values:
9076 -- FND_API.G_RET_STS_SUCCESS (='S')
9077 -- FND_API.G_RET_STS_ERROR (='E')
9078 -- FND_API.G_RET_STS_UNEXP_ERROR (='U')
9079 --x_error_msg_tbl
9080 -- table of rrror messages if any.
9081 --Notes:
9082 -- ONLY SUPORTS DELETION for PO/PA document types
9083 --It house the logic for validation of delete action and deletion of a Document
9084 --or its Line/Shipment/Distribution.
9085 --End of Comments
9086 -----------------------------------------------------------------------------
9087 PROCEDURE process_delete_action( p_init_msg_list IN VARCHAR2
9088 ,x_return_status OUT NOCOPY VARCHAR2
9089 ,p_calling_program IN VARCHAR2
9090 ,p_entity IN VARCHAR2
9091 ,p_entity_row_id IN ROWID
9092 ,p_doc_type IN VARCHAR2
9093 ,p_doc_subtype IN VARCHAR2
9094 ,p_doc_header_id IN NUMBER
9095 ,p_ga_flag IN VARCHAR2
9096 ,p_conterms_exist_flag IN VARCHAR2
9097 ,p_po_line_id IN NUMBER
9098 ,p_line_loc_id IN NUMBER
9099 ,p_distribution_id IN NUMBER
9100 ,x_error_msg_tbl OUT NOCOPY PO_TBL_VARCHAR2000)
9101 IS
9102 l_error_message VARCHAR2(2000);
9103 l_entity_row_id ROWID := NULL;
9104 d_pos NUMBER := 0;
9105 l_api_name CONSTANT VARCHAR2(30) := 'process_delete_action';
9106 d_module CONSTANT VARCHAR2(70) := 'po.plsql.PO_DOCUMENT_UPDATE_PVT.process_delete_action';
9107
9108 BEGIN
9109 IF (PO_LOG.d_proc) THEN
9110 PO_LOG.proc_begin(d_module, 'p_init_msg_list', p_init_msg_list); PO_LOG.proc_begin(d_module, 'p_entity', p_entity); PO_LOG.proc_begin(d_module, 'p_entity_row_id', p_entity_row_id);
9111 PO_LOG.proc_begin(d_module, 'p_doc_type', p_doc_type); PO_LOG.proc_begin(d_module, 'p_doc_subtype', p_doc_subtype); PO_LOG.proc_begin(d_module, 'p_doc_header_id', p_doc_header_id);
9112 PO_LOG.proc_begin(d_module, 'p_ga_flag', p_ga_flag); PO_LOG.proc_begin(d_module, 'p_conterms_exist_flag', p_conterms_exist_flag); PO_LOG.proc_begin(d_module, 'p_po_line_id', p_po_line_id);
9113 PO_LOG.proc_begin(d_module, 'p_line_loc_id', p_line_loc_id); PO_LOG.proc_begin(d_module, 'p_distribution_id', p_distribution_id);
9114 END IF;
9115 -- Standard start of API savepoint
9116 SAVEPOINT PO_PROCESS_DELETE_ACTION;
9117
9118 --Initialize message list if necessary (p_init_msg_list is set to TRUE)
9119 IF FND_API.to_Boolean(p_init_msg_list)
9120 THEN
9121 FND_MSG_PUB.initialize;
9122 END IF;
9123
9124 -- By default return status is SUCCESS if no exception occurs
9125 x_return_status := FND_API.G_RET_STS_SUCCESS;
9126
9127 d_pos := 5;
9128 --Lock the document so that while we do validation no body else changes the
9129 --record
9130 PO_DOCUMENT_LOCK_GRP.lock_document( p_api_version => 1.0
9131 ,p_init_msg_list => FND_API.G_FALSE
9132 ,x_return_status => x_return_status
9133 ,p_document_type => p_doc_type
9134 ,p_document_id => p_doc_header_id);
9135
9136 d_pos := 8;
9137 IF x_return_status = FND_API.G_RET_STS_ERROR THEN
9138 RAISE FND_API.g_exc_error;
9139 ELSIF x_return_status = FND_API.G_RET_STS_UNEXP_ERROR THEN
9140 RAISE FND_API.g_exc_unexpected_error;
9141 END IF;
9142
9143 d_pos := 10;
9144 --We only validate in case the call is not made form HTML
9145 IF NVL(p_calling_program,'NULL') <> G_CALL_MOD_HTML_CONTROL_ACTION THEN
9146 validate_delete_action( p_entity => p_entity
9147 ,p_doc_type => p_doc_type
9148 ,p_doc_header_id => p_doc_header_id
9149 ,p_po_line_id => p_po_line_id
9150 ,p_line_loc_id => p_line_loc_id
9151 ,p_distribution_id => p_distribution_id
9152 ,x_error_message => l_error_message);
9153
9154 d_pos := 20;
9155 IF (PO_LOG.d_stmt) THEN
9156 PO_LOG.stmt(d_module,d_pos,'l_error_message',l_error_message);
9157 END IF;
9158
9159 IF l_error_message is NOT NULL
9160 THEN
9161 FND_MESSAGE.set_name('PO','PO_CUSTOM_MSG');
9162 FND_MESSAGE.set_token('TRANSLATED_TOKEN', l_error_message);
9163 FND_MSG_PUB.add;
9164 RAISE FND_API.g_exc_error;
9165 END IF; --x_error_message is NULL
9166 END IF;
9167
9168 IF p_entity = PO_CORE_S.g_doc_level_HEADER
9169 THEN
9170 d_pos := 30;
9171 PO_HEADERS_SV1.delete_document( p_doc_type => p_doc_type
9172 ,p_doc_subtype => p_doc_subtype
9173 ,p_doc_header_id => p_doc_header_id
9174 ,p_ga_flag => p_ga_flag
9175 ,p_conterms_exist_flag => p_conterms_exist_flag
9176 ,x_return_status => x_return_status);
9177 IF (PO_LOG.d_stmt) THEN
9178 PO_LOG.stmt(d_module,d_pos,'x_return_status',x_return_status);
9179 END IF;
9180 ELSIF p_entity = PO_CORE_S.g_doc_level_LINE
9181 THEN
9182
9183 d_pos := 40;
9184 SELECT ROWID
9185 INTO l_entity_row_id
9186 FROM PO_LINES_ALL
9187 WHERE PO_LINE_ID = p_po_line_id;
9188
9189 d_pos := 45;
9190 PO_LINES_SV.delete_line( X_type_lookup_code => p_doc_subtype
9191 ,X_po_line_id => p_po_line_id
9192 ,X_row_id => l_entity_row_id
9193 ,p_skip_validation => 'Y'); --skip validations as we already have called validate_delete_action
9194 ELSIF p_entity = PO_CORE_S.g_doc_level_SHIPMENT
9195 THEN
9196 d_pos := 50;
9197 PO_SHIPMENTS_SV4.process_delete_line_loc(
9198 p_line_loc_id => p_line_loc_id
9199 ,p_line_loc_row_id => p_entity_row_id
9200 ,p_po_header_id => p_doc_header_id
9201 ,p_po_line_id => p_po_line_id
9202 ,p_doc_subtype => p_doc_subtype);
9203
9204 ELSIF p_entity = PO_CORE_S.g_doc_level_DISTRIBUTION
9205 THEN
9206 d_pos := 60;
9207 -- If all validations go thru fine we go ahead and delete the distribution
9208 PO_DISTRIBUTIONS_PKG2.delete_row(x_rowid => p_entity_row_id);
9209 END IF; -- p_entity = PO_CORE_S.g_doc_level_HEADER
9210
9211 --<Bug#4514269 Start>
9212 d_pos := 70;
9213 --Call etax api to calculate tax.
9214 PO_TAX_INTERFACE_PVT.calculate_tax( p_po_header_id => p_doc_header_id
9215 ,p_po_release_id => NULL
9216 ,p_calling_program => p_calling_program
9217 ,x_return_status => x_return_status);
9218
9219 d_pos := 80;
9220 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
9221 RAISE FND_API.g_exc_unexpected_error;
9222 END IF;
9223 --<Bug#4514269 End>
9224
9225 IF (PO_LOG.d_proc) THEN
9226 PO_LOG.proc_end(d_module);
9227 END IF;
9228 EXCEPTION
9229 WHEN FND_API.g_exc_error THEN
9230 ROLLBACK TO PO_PROCESS_DELETE_ACTION;
9231 x_return_status := FND_API.g_ret_sts_error;
9232 x_error_msg_tbl := PO_TBL_VARCHAR2000();
9233 --Copy the messages on the list to the out parameter
9234 FOR I IN 1..FND_MSG_PUB.count_msg loop
9235 x_error_msg_tbl.extend;
9236 x_error_msg_tbl(I) := FND_MSG_PUB.get(I, 'F');
9237 IF (PO_LOG.d_stmt) THEN
9238 PO_LOG.stmt(d_module,d_pos,'x_error_msg_tbl(' || I || ')', x_error_msg_tbl(I));
9239 END IF;
9240 END LOOP;
9241 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
9242 ROLLBACK TO PO_PROCESS_DELETE_ACTION;
9243 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
9244 IF PO_LOG.d_exc THEN
9245 PO_LOG.exc(d_module,d_pos,'Unexpected Error in' || d_module);
9246 END IF;
9247 WHEN OTHERS THEN
9248 ROLLBACK TO PO_PROCESS_DELETE_ACTION;
9249 x_return_status := FND_API.g_ret_sts_unexp_error;
9250 FND_MSG_PUB.add_exc_msg(g_pkg_name, l_api_name||':'||d_pos);
9251 IF PO_LOG.d_exc THEN
9252 PO_LOG.exc(d_module,d_pos,'Unhandled Exception in ' || SQLCODE||':'||SQLERRM);
9253 END IF;
9254 END process_delete_action;
9255
9256 END PO_DOCUMENT_UPDATE_PVT;