DBA Data[Home] [Help]

PACKAGE BODY: APPS.PO_DOCUMENT_UPDATE_PVT

Source


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