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