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