DBA Data[Home] [Help]

PACKAGE BODY: APPS.AHL_UMP_PROCESSUNIT_PVT

Source


1 PACKAGE BODY AHL_UMP_PROCESSUNIT_PVT AS
2 /* $Header: AHLVUMUB.pls 120.35.12020000.3 2013/04/01 02:58:59 sracha ship $ */
3 
4 G_PKG_NAME          CONSTANT VARCHAR2(30) := 'AHL_UMP_ProcessUnit_PVT';
5 G_DEBUG             VARCHAR2(1) := AHL_DEBUG_PUB.is_log_enabled;
6 G_IS_PM_INSTALLED   CONSTANT VARCHAR2(1) := AHL_UTIL_PKG.IS_PM_INSTALLED;
7 
8 G_CONCURRENT_FLAG   VARCHAR2(1);
9 
10 -- added to debug concurrent worker pgms failure.
11 G_DEBUG_LINE_NUM    NUMBER;
12 
13 -- This variable is populated based on the AHL_APPLN_USAGE profile value.
14 -- 11.5.10 enhancement.
15 G_application_usg_code VARCHAR2(30) := fnd_profile.value('AHL_APPLN_USAGE');
16 
17 ----------------------------------------------------------------
18 -- Define local record structures used by Process Unit Procedure.
19 ----------------------------------------------------------------
20 -- To hold the counter rules.
21 TYPE counter_rules_rec_type IS RECORD(
22    UOM_CODE  VARCHAR2(3),
23    RATIO     NUMBER);
24 
25 -- To hold the applicable MRs table record.
26 TYPE applicable_mrs_rec_type IS RECORD(
27    CSI_ITEM_INSTANCE_ID      NUMBER,
28    MR_HEADER_ID              NUMBER,
29    TITLE                     AHL_MR_HEADERS_VL.TITLE%TYPE,
30    VERSION_NUMBER            NUMBER,
31    REPETITIVE_FLAG           VARCHAR2(1),
32    SHOW_REPETITIVE_CODE      VARCHAR2(30),
33    IMPLEMENT_STATUS_CODE     VARCHAR2(30),
34    COPY_ACCOMPLISHMENT_CODE  VARCHAR2(30),
35    PRECEDING_MR_HEADER_ID    NUMBER,
36    DESCENDENT_COUNT          NUMBER,
37    WHICHEVER_FIRST_CODE      VARCHAR2(30),
38    PROGRAM_MR_HEADER_ID      NUMBER,
39    SERVICE_LINE_ID           NUMBER,      -- from service contracts for PM installation.
40    PM_SCHEDULE_EXISTS        VARCHAR2(1), -- used only for PM installation.
41    CONTRACT_START_DATE       DATE,        -- used only for PM installation.
42    CONTRACT_END_DATE         DATE,        -- used only for PM installation.
43    PROGRAM_END_DATE          DATE,        -- used only for PM installation.
44    COVERAGE_IMP_LEVEL        NUMBER,      -- used only for PM installation.
45    EFFECTIVE_TO              DATE,
46    EFFECTIVE_FROM            DATE,
47    -- added for 9263774
48    EXPIRED_MR_FLAG           VARCHAR2(1),
49    -- added for SB Enh
50    TERMINATE_TRIGGER_CHECK   VARCHAR2(1),
51    ACCOMPLISH_TRIGGER_TYPE   VARCHAR2(30),
52    LOOP_CHAIN_SEQ_NUM        NUMBER);
53 
54 -- To hold the forecast details.
55 TYPE forecast_details_rec_type IS RECORD(
56    START_DATE     DATE,
57    END_DATE       DATE,
58    UOM_CODE       VARCHAR2(3),
59    USAGE_PER_DAY  NUMBER,
60    -- JKJain, NR Analysis and Forecasting
61    UTILIZATION_TYPE VARCHAR2(10));
62 
63 -- To hold the ahl unit effectivity record details.
64 TYPE unit_effectivity_rec_type IS RECORD(
65    UNIT_EFFECTIVITY_ID  NUMBER,
66    STATUS_CODE          VARCHAR2(30),
67    DUE_DATE             DATE,
68    FORECAST_SEQUENCE    NUMBER,
69    RELATED_UE_ID        NUMBER,
70    ORIGINATOR_UE_ID     NUMBER,
71    VISIT_ASSIGN_FLAG    VARCHAR2(1),
72    VISIT_END_DATE       DATE,
73    -- added for 9263774
74    PRIOR_MR_HEADER_ID   NUMBER);
75 
76 -- To hold the calculated next due details.
77 TYPE next_due_date_rec_type IS RECORD(
78    MR_EFFECTIVITY_ID     NUMBER,
79    MR_INTERVAL_ID        NUMBER,
80    DUE_DATE              DATE,
81    DUE_AT_COUNTER_VALUE  NUMBER,
82    CURRENT_CTR_VALUE     NUMBER,
83    LAST_CTR_VALUE        NUMBER,
84    MESSAGE_CODE          VARCHAR2(30),
85    TOLERANCE_AFTER       NUMBER,
86    TOLERANCE_BEFORE      NUMBER,
87    TOLERANCE_FLAG        VARCHAR2(1),
88    CTR_UOM_CODE          VARCHAR2(3),
89    EARLIEST_DUE_DATE     DATE,
90    LATEST_DUE_DATE       DATE,
91    COUNTER_ID            NUMBER,
92    -- Added to fix bug# 4224867.
93    COUNTER_REMAIN        NUMBER,
94    -- JKJain, NR Analysis and Forecasting
95    FLEET_HEADER_ID       NUMBER,
96    FLEET_ASSO_REJECTED   VARCHAR2(1));
97 
98 /*TYPE MR_RELATIONSHIP_REC IS RECORD (
99    MR_HEADER_ID          NUMBER,
100    RELATED_MR_HEADER_ID  NUMBER,
101    RELATIONSHIP_CODE     VARCHAR2(30)); */
102 
103 -- To hold the PM program details.
104 TYPE PMprogram_rec_type IS RECORD(
105    PROGRAM_MR_HEADER_ID   NUMBER,
106    MR_EFFECTIVITY_ID      NUMBER);
107 
108 -- Added for Service Bulletin Enhancement
109 TYPE loop_chain_rec_type IS RECORD(
110    MR_HEADER_ID             NUMBER,
111    LOOP_CHAIN_SEQ_NUM       NUMBER,
112    ACCOMPLISHED_UE_ID       NUMBER,
113    ACCOMPLISHMENT_EXISTS    VARCHAR2(1),
114    MR_TITLE                 ahl_mr_headers_b.title%TYPE
115 );
116 
117 -- Begin -- Added for performance fix bug# 6893404.
118 -- number table.
119 TYPE nbr_tbl_type IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
120 
121 -- varchar2 table.
122 TYPE vchar_tbl_type IS TABLE OF VARCHAR2(400) INDEX BY BINARY_INTEGER;
123 
124 -- date table.
125 TYPE date_tbl_type IS TABLE OF DATE INDEX BY BINARY_INTEGER;
126 -- End -- Added for performance fix bug# 6893404.
127 
128 ----------------------------------------------
129 -- Define Table Types for record structures --
130 ----------------------------------------------
131 TYPE unit_effectivity_tbl_type IS TABLE OF unit_effectivity_rec_type INDEX BY BINARY_INTEGER;
132 TYPE counter_rules_tbl_type IS TABLE OF counter_rules_rec_type INDEX BY BINARY_INTEGER;
133 TYPE forecast_details_tbl_type IS TABLE OF forecast_details_rec_type INDEX BY BINARY_INTEGER;
134 
135 --TYPE MR_RELATIONSHIP_TBL IS TABLE OF MR_RELATIONSHIP_REC INDEX BY BINARY_INTEGER;
136 
137 TYPE PMprogram_tbl_type IS TABLE OF PMprogram_rec_type INDEX BY BINARY_INTEGER;
138 
139 TYPE loop_chain_MR_tbl_type IS TABLE OF loop_chain_rec_type INDEX BY BINARY_INTEGER;
140 ------------------------------
141 -- Declare Local Procedures --
142 ------------------------------
143 -- To get the unit and master configurations IDs for the input item instance.
144 PROCEDURE Get_Unit_Master_ConfigIDs (p_csi_item_instance_id IN NUMBER,
145                                      x_uc_header_id OUT NOCOPY NUMBER,
146                                      x_master_config_id OUT NOCOPY NUMBER);
147 
148 -- To get the root item instance for the input item instance if exists.
149 FUNCTION Get_RootInstanceID(p_csi_item_instance_id IN NUMBER)
150 RETURN NUMBER;
151 
152 -- Validate the input item instance.
153 PROCEDURE Validate_Item_Instance (p_csi_item_instance_id       IN NUMBER,
154                                   x_inventory_item_id          OUT NOCOPY NUMBER,
155                                   x_inv_master_organization_id OUT NOCOPY NUMBER,
156                                   x_expired_flag               OUT NOCOPY VARCHAR2);
157 
158 -- Build the item instance tree containing root nodes and its components.
159 PROCEDURE Build_Config_Tree(p_csi_root_instance_id  IN         NUMBER,
160                             p_master_config_id      IN         NUMBER,
161                             x_config_node_tbl       OUT NOCOPY AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type);
162 
163 
164 -- To get the last day of the rolling window from profile values.
165 FUNCTION Get_Rolling_Window_Date RETURN DATE;
166 
167 -- Procedure to build unit effectivity for ASO Installation.
168 -- Called from Process_Unit API. This procedure uses the global variables
169 -- set in 'Process Unit' API for processing.
170 PROCEDURE Process_ASO_Unit;
171 
172 -- Get the utilization forecast applicable to the input item instance/unit.
173 PROCEDURE Get_Utilization_Forecast (p_csi_item_instance_id IN         NUMBER,
174                                     p_uc_header_id         IN         NUMBER,
175                                     p_inventory_item_id    IN         NUMBER,
176                                     p_inventory_org_id     IN         NUMBER,
177                                     x_forecast_details_tbl OUT NOCOPY forecast_details_tbl_type);
178 
179 -- Lock all existing unit effectivity records.
180 PROCEDURE Lock_UnitEffectivity_Records(x_ret_code  OUT NOCOPY VARCHAR2);
181 
182 -- Build the counter ratio that needs to be applied to the item instance based
183 -- on its master configuration position. Input is the item instance.
184 PROCEDURE build_Counter_Ratio(p_position_reference   IN         VARCHAR2,
185                               p_csi_item_instance_id IN         NUMBER,
186                               p_master_config_id     IN         NUMBER,
187                               x_counter_rules_tbl    OUT NOCOPY counter_rules_tbl_type);
188 
189 -- Build the current usage on the item instance's counters based on counters attached
190 -- to the item instance.
191 PROCEDURE get_Current_Usage ( p_csi_item_instance_id IN         NUMBER,
192                               x_current_usage_tbl    OUT NOCOPY counter_values_tbl_type );
193 
194 -- Get accomplishment details for an MR.
195 -- Added parameter x_no_forecast to fix bug# 6711228
196 -- Added parameter x_accomplished_ue_id to fix bug# 8994566
197 PROCEDURE get_accomplishment_details (p_applicable_mrs_rec       IN         applicable_mrs_rec_type,
198                                       p_current_usage_tbl        IN         counter_values_tbl_type,
199                                       p_counter_rules_tbl        IN         counter_rules_tbl_type,
200                                       x_accomplishment_date      OUT NOCOPY DATE,
201                                       x_last_acc_counter_val_tbl OUT NOCOPY counter_values_tbl_type,
202                                       x_one_time_mr_flag         OUT NOCOPY BOOLEAN,
203                                       x_dependent_mr_flag        OUT NOCOPY BOOLEAN,
204                                       x_get_preceding_next_due   OUT NOCOPY BOOLEAN,
205                                       x_mr_accomplish_exists     OUT NOCOPY BOOLEAN,
206                                       x_no_forecast_flag         OUT NOCOPY BOOLEAN,
207                                       x_accomplished_ue_id       OUT NOCOPY NUMBER);
208 
209 
210 -- Build unit effectivity for a given item instance and a maintenance requirement.
211 -- The unit effectivities created here will be written into a temporary table.
212 PROCEDURE Build_Effectivity ( p_applicable_mrs_rec      IN         applicable_mrs_rec_type,
213                               p_current_usage_tbl       IN         counter_values_tbl_type,
214                               p_counter_rules_tbl       IN         counter_rules_tbl_type);
215 
216 -- Calculate due date for the item instance and mr using current usage, counter rules,
217 -- last accomplishment counters and forecast (defined in global variable).
218 -- Added parameter p_dependent_mr_flag to fix bug# 6711228.
219 -- Added parameters p_mr_accomplish_exists and p_last_due_mr_interval_id to fix bug# 6858788.
220 PROCEDURE Calculate_Due_Date ( p_repetivity_flag    IN VARCHAR2 := 'Y',
221                                p_applicable_mrs_rec IN applicable_mrs_rec_type,
222                                p_current_usage_tbl  IN counter_values_tbl_type,
223                                p_counter_rules_tbl  IN counter_rules_tbl_type,
224                                p_last_due_date      IN DATE,
225                                p_last_due_counter_val_tbl IN counter_values_tbl_type,
226                                p_dependent_mr_flag  IN BOOLEAN := FALSE,
227                                p_mr_accomplish_exists IN BOOLEAN,
228                                p_last_due_mr_interval_id IN NUMBER := NULL,
229                                x_next_due_date_rec  OUT NOCOPY next_due_date_rec_type);
230 
231 
232 -- Calculate due at counter values for a given due due from last due date and last due counters using
233 -- counter rules and forecast (defined in global variable).
234 PROCEDURE Get_Due_At_Counter_Values ( p_last_due_date IN DATE,
235                                       p_last_due_counter_val_tbl IN counter_values_tbl_type,
236                                       p_due_date IN DATE,
237                                       p_counter_rules_tbl IN counter_rules_tbl_type,
238                                       x_due_at_counter_val_tbl OUT NOCOPY counter_values_tbl_type,
239                                       x_return_value      OUT NOCOPY BOOLEAN);
240 
241 -- Calculates the due date for the counter_remain from a given start date using forecast, counter rules
242 -- and counter uom.
243 PROCEDURE Get_Date_from_UF ( p_counter_remain IN NUMBER,
244                              p_counter_uom_code IN VARCHAR2,
245                              p_counter_rules_tbl IN counter_rules_tbl_type,
246                              p_start_date IN DATE := NULL,
247                              x_due_date         OUT NOCOPY DATE);
248 
249 -- Apply the counter ratio factor to convert a given counter value at a component level to the
250 -- root instance. This is needed as forecast is only defined at root instance.
251 FUNCTION Apply_Counter_Ratio ( p_counter_remain IN NUMBER,
252                                p_counter_uom_code IN VARCHAR2,
253                                p_counter_rules_tbl IN counter_rules_tbl_type)
254 RETURN NUMBER;
255 
256 -- Apply the counter ratio factor to convert a given counter value at a root instance level to the
257 -- component. This is needed as forecast is only defined at root instance.
258 FUNCTION Apply_ReverseCounter_Ratio ( p_counter_remain IN NUMBER,
259                                       p_counter_uom_code IN VARCHAR2,
260                                       p_counter_rules_tbl IN counter_rules_tbl_type)
261 RETURN NUMBER;
262 
263 -- This will return the adjusted interval value if the next due counter value overlaps two intervals.
264 -- It will be used where the overflow condition occurs based on the interval's start value and stop value.
265 PROCEDURE Adjust_Interval_Value ( p_mr_effectivity_id IN NUMBER,
266                                   p_counter_id IN NUMBER,
267                                   p_counter_value IN NUMBER,
268                                   p_interval_value IN NUMBER,
269                                   p_stop_value IN NUMBER,
270                                   x_adjusted_int_value OUT NOCOPY NUMBER,
271                                   x_nxt_interval_found OUT NOCOPY BOOLEAN);
272 
273 -- This will return the adjusted due date if the next due date overlaps two intervals.
274 -- It will be used where the overflow condition occurs based on the interval's start date and stop date.
275 PROCEDURE Adjust_Due_Date ( p_mr_effectivity_id IN NUMBER,
276                             p_start_counter_rec IN counter_values_rec_type,
277                             p_start_due_date    IN DATE,
278                             p_counter_rules_tbl IN counter_rules_tbl_type,
279                             p_interval_value IN NUMBER,
280                             p_stop_date IN DATE,
281                             p_due_date IN DATE,
282                             x_adjusted_due_date OUT NOCOPY DATE,
283                             x_adjusted_due_ctr  OUT NOCOPY NUMBER,
284                             x_nxt_interval_found OUT NOCOPY BOOLEAN);
285 
286 -- This procedure will return due date based on the next interval(if exists), whenever an interval
287 -- is not found for the current start/stop values or dates.
288 -- Added parameter p_dependent_mr_flag to fix bug# 6711228.
289 -- Added parameter p_mr_accomplish_exists and p_last_due_mr_interval_id to fix bug# 6858788. Commented
290 -- p_last_accomplishment_date and will instead use p_mr_accomplish_exists.
291 PROCEDURE Get_DueDate_from_NxtInterval(p_applicable_mrs_rec      IN  applicable_mrs_rec_type,
292                                        p_repetivity_flag         IN  VARCHAR2,
293                                        p_mr_effectivity_id       IN  NUMBER,
294                                        p_current_ctr_rec         IN  Counter_values_rec_type,
295                                        p_current_ctr_at_date     IN  DATE,
296                                        p_counter_rules_tbl       IN  Counter_rules_tbl_type,
297                                        p_start_int_match_at_ctr  IN  NUMBER,
298                                        p_last_accomplish_ctr_val IN  NUMBER,
299                                        --p_last_accomplishment_date IN DATE,
300                                        p_dependent_mr_flag       IN  BOOLEAN,
301                                        p_mr_accomplish_exists    IN  BOOLEAN,
302                                        p_last_due_mr_interval_id IN  NUMBER,
303                                        x_next_due_date_rec       OUT NOCOPY next_due_date_rec_type,
304                                        x_mr_interval_found       OUT NOCOPY BOOLEAN,
305                                        x_return_val              OUT NOCOPY BOOLEAN);
306 
307 -- To write a record into ahl_temp_unit_effectivities.
308 PROCEDURE Create_temp_unit_effectivity (X_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE);
309 
310 -- To process the decendents in case the mr is a group MR.
311 PROCEDURE Process_GroupMR (p_applicable_mrs_rec  IN applicable_mrs_rec_type,
312                            p_new_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE,
313                            p_unit_effectivity_tbl IN unit_effectivity_tbl_type,
314                            p_old_UE_forecast_sequence IN NUMBER := -1);
315 
316 -- To process the dependent MRs based on the value of preceding MR.
317 PROCEDURE Process_PrecedingMR (p_applicable_mrs_rec IN applicable_mrs_rec_type,
318                                p_counter_rules_tbl  IN counter_rules_tbl_type,
319                                p_current_usage_tbl  IN counter_values_tbl_type);
320 
321 
322 -- To update the preceding_check_flag in the temporary unit effectivities table.
323 PROCEDURE Update_check_flag (p_applicable_mrs_rec IN applicable_mrs_rec_type,
324                              p_dependent_mr_flag IN BOOLEAN,
325                              p_next_due_date_rec IN next_due_date_rec_type);
326 
327 -- To log error messages into a log file if called from concurrent process.
328 PROCEDURE log_error_messages;
329 
330 
331 -------------------------------------------------
332 -- Procedures for Preventive Maintenance Logic --
333 -------------------------------------------------
334 -- Populate applicable MRs temporary table from the output of FMP API.
335 PROCEDURE PopulatePM_Appl_MRs (p_csi_ii_id      IN  NUMBER,
336                                x_return_status  OUT NOCOPY VARCHAR2,
337                                x_msg_count      OUT NOCOPY NUMBER,
338                                x_msg_data       OUT NOCOPY VARCHAR2,
339                                x_UnSch_programs_tbl OUT NOCOPY PMprogram_tbl_type);
340 
341 -- Procedure to build instance level effectivity for PM installation
342 -- using service contracts.
343 -- Called from Process_Unit API.
344 PROCEDURE Process_PM_Unit(p_csi_item_instance_id IN    NUMBER,
345                           p_UnSch_programs_tbl   IN    PMprogram_tbl_type);
346 
347 
348 -- Calculate program end date for all MR's where contract is not scheduled.
349 PROCEDURE Calc_program_end_dates (p_UnSch_programs_tbl IN PMprogram_tbl_type,
350                                   p_current_usage_tbl  IN counter_values_tbl_type);
351 
352 -- Process records with contract dates scheduled.
353 PROCEDURE Process_PMSch_Activities;
354 
355 -- Process records with no contract dates.
356 PROCEDURE Process_PMUnSch_Activities(p_current_usage_tbl IN counter_values_tbl_type);
357 
358 -- Procedure to find the service_line_id and program for a calculated due_date.
359 -- The calculated due_date may be overridden by the contract/program dates.
360 -- Also the earliest due and latest due date will get adjusted if they are not
361 -- within the contract and program start/end dates.
362 PROCEDURE Get_PMprogram(p_csi_item_instance_id       IN  NUMBER,
363                         p_mr_header_id               IN  NUMBER,
364                         p_last_due_date              IN  DATE,
365                         p_due_date                   IN  DATE,
366                         p_earliest_due               IN  DATE,
367                         p_latest_due                 IN  DATE,
368                         x_program_mr_header_id       OUT NOCOPY NUMBER,
369                         x_service_line_id            OUT NOCOPY NUMBER,
370                         x_contract_override_due_date OUT NOCOPY DATE,
371                         x_cont_override_earliest_due OUT NOCOPY DATE,
372                         x_cont_override_latest_due   OUT NOCOPY DATE,
373                         x_contract_found_flag        OUT NOCOPY BOOLEAN);
374 
375 -- After creation of all maintenance requirements for the instance in the temporary table,
376 -- assign unit effectivity IDs from existing un-accomplished maintenance requirements
377 -- from ahl_unit_effectivities_b.
378 PROCEDURE Assign_Unit_effectivity_IDs;
379 
380 -- Fix for Prev. Maint. performance bug# 5093064.
381 -- instead of calling procedure AHL_FMP_PVT.GET_MR_AFFECTED_ITEMS,
382 -- write PM effectivity logic in this procedure.
383 PROCEDURE Process_PM_MR_Affected_Items(p_commit           IN            VARCHAR2 := FND_API.G_FALSE,
384                                        x_msg_count           OUT NOCOPY NUMBER,
385                                        x_msg_data            OUT NOCOPY VARCHAR2,
386                                        x_return_status       OUT NOCOPY VARCHAR2,
387                                        p_mr_header_id     IN            NUMBER,
388                                        p_old_mr_header_id IN            NUMBER := NULL,
389                                        p_concurrent_flag  IN            VARCHAR2 := 'N',
390                                        p_num_of_workers   IN            NUMBER := 10);
391 
392 --------------------------------------------------------------------
393 -- Following procedures have been added for 11.5.10 Enhancements. --
394 --------------------------------------------------------------------
395 -- Get the latest recorded counter reading for a given date.
396 PROCEDURE get_ctr_reading_for_date (p_csi_item_instance_id IN NUMBER,
397                                     p_counter_id           IN NUMBER,
398                                     p_reading_date         IN DATE,
399                                     x_net_reading        OUT NOCOPY NUMBER);
400 
401 -- Get the earliest date on which a given reading was recorded.
402 PROCEDURE get_ctr_date_for_reading (p_csi_item_instance_id IN NUMBER,
403                                     p_counter_id           IN NUMBER,
404                                     p_counter_value        IN NUMBER,
405                                     x_ctr_record_date    OUT NOCOPY DATE,
406                                     x_return_val         OUT NOCOPY BOOLEAN);
407 
408 -- Calculate due date all deferred unit effectivities.
409 PROCEDURE Process_Deferred_UE (p_csi_item_instance_id IN NUMBER,
410                                p_current_usage_tbl  IN counter_values_tbl_type,
411                                p_counter_rules_tbl  IN counter_rules_tbl_type);
412 
413 -- Explode SR's having MRs for calculating MR due dates.
414 PROCEDURE Process_SR_UE (p_csi_item_instance_id IN NUMBER);
415 
416 -- Match if current UE group MR matches the applicable group MR.
417 PROCEDURE Match_Group_MR (p_orig_csi_item_instance_id  IN  NUMBER,
418                           p_orig_mr_header_id          IN  NUMBER,
419                           p_unit_effectivity_id        IN  NUMBER,
420                           x_group_match_flag           OUT NOCOPY VARCHAR2);
421 
422 -----------------------------------------------------------------------------------
423 -- Following procedures have been added for 11.5.10+ Transit Check Enhancements. --
424 -----------------------------------------------------------------------------------
425 
426 -- Validate applicability for Unplanned MRs (MRs directly planned into a Visit from FMP).
427 PROCEDURE Process_Unplanned_UE(p_csi_item_instance_id IN NUMBER,
428                                p_current_usage_tbl    IN counter_values_tbl_type,
429                                p_counter_rules_tbl    IN counter_rules_tbl_type);
430 
431 ---------------------------------------
432 -- added to fix performance bug 5093064.
433 ---------------------------------------
434 -- Split instances based on instance count.
435 PROCEDURE Instance_Split_BTree(p_csi_max_id  in NUMBER,
436                                p_csi_min_id  IN NUMBER,
437                                p_num_workers IN NUMBER,
438                                p_mr_header_id IN NUMBER,
439                                p_total_inst_count  IN NUMBER);
440 
441 
442 -- Split instance range into blocks based on instance IDs.
443 PROCEDURE Instance_Split_Sequential(p_csi_max_id  in NUMBER,
444                                     p_csi_min_id  IN NUMBER,
445                                     p_num_workers IN NUMBER,
446                                     p_mr_header_id IN NUMBER);
447 
448 ----------------------------------------------
449 -- Following procedures have been added R12 --
450 ----------------------------------------------
451 -- Added to fix bug# 4224867.
452 -- find usage forecast for a given date.
453 PROCEDURE get_usage_for_date(p_due_date          IN DATE,
454                              p_counter_uom_code  IN VARCHAR2,
455                              p_counter_rules_tbl IN Counter_rules_tbl_type,
456                              x_usage_per_day     OUT NOCOPY NUMBER);
457 
458 -- Added to fix bug# 6875650.
459 -- Get the latest recorded counter reading for a given date-time.
460 PROCEDURE get_ctr_reading_for_datetime (p_csi_item_instance_id IN NUMBER,
461                                         p_counter_id           IN NUMBER,
462                                         p_reading_date         IN DATE,
463                                         x_net_reading          OUT NOCOPY NUMBER);
464 
465 
466 ----------------------------------------------------------------
467 -- Following procedures were added for performance bug# 6893404.
468 ----------------------------------------------------------------
469 -- Identify affected units and process or launch concurrent workers for AHL processing.
470 PROCEDURE Split_Process_All_Instances(p_concurrent_flag  IN  VARCHAR2,
471                                       p_commit_flag      IN  VARCHAR2,
472                                       p_num_of_workers   IN  NUMBER,
473                                       p_mr_header_id     IN  NUMBER,
474                                       p_mtl_category_id  IN  NUMBER,
475                                       p_process_option   IN  VARCHAR2,
476                                       x_msg_count        OUT NOCOPY  NUMBER,
477                                       x_msg_data         OUT NOCOPY  NUMBER,
478                                       x_return_status    OUT NOCOPY  VARCHAR2);
479 
480 -- Write into BUE worker table when processing all units.
481 PROCEDURE Populate_BUE_Worker(p_conc_request_id IN  NUMBER,
482                               p_concurrent_flag IN  VARCHAR2,
483                               p_mtl_category_id IN  NUMBER,
484                               p_process_option  IN  VARCHAR2,
485                               errbuf            OUT NOCOPY VARCHAR2,
486                               x_return_status   OUT NOCOPY VARCHAR2);
487 
488 
489 -- Write into BUE worker table when processing for a MR.
490 PROCEDURE Populate_BUE_Worker_for_MR(p_conc_request_id IN  NUMBER,
491                                      p_mr_header_id    IN  NUMBER,
492                                      p_concurrent_flag IN  VARCHAR2,
493                                      p_mtl_category_id IN  NUMBER,
494                                      p_process_option  IN  VARCHAR2,
495                                      x_return_status   OUT NOCOPY VARCHAR2);
496 
497 -- get next instance from BUE worker table to process.
498 PROCEDURE Get_Next_BUE_Row(p_parent_conc_pgm_id    IN  NUMBER,
499                            p_conc_child_req_id     IN  NUMBER,
500                            x_return_status         OUT NOCOPY VARCHAR2,
501                            errbuf                  OUT NOCOPY VARCHAR2,
502                            x_item_instance_id      OUT NOCOPY NUMBER);
503 
504 
505 -- cleanup worker table
506 -- added x_return_status and x_errbuf to fix bug# 10185468
507 PROCEDURE Cleanup_BUE_Worker(p_parent_conc_request_id IN  NUMBER,
508                              p_child_conc_request_id  IN  NUMBER,
509                              x_return_status          OUT NOCOPY VARCHAR2,
510                              x_errbuf                 OUT NOCOPY VARCHAR2);
511 
512 
513 -------------------------------------------------------
514 -- Following procedures were added to fix bug# 6907562.
515 -------------------------------------------------------
516 -- function that compares previous due date and uom remain with current values
517 -- and return Y is the current due date replaces the prev one.
518 FUNCTION validate_for_duedate_reset(p_due_date        IN DATE,
519                                     p_uom_remain      IN NUMBER,
520                                     p_prev_due_date   IN DATE,
521                                     p_prev_counter_id IN NUMBER,
522                                     p_prev_uom_remain IN NUMBER) RETURN VARCHAR2;
523 
524 -- procedure checks forecast and adds zero forecast row if missing forecast.
525 PROCEDURE validate_uf_for_ctr(p_current_usage_tbl       IN counter_values_tbl_type,
526                               p_x_forecast_details_tbl IN OUT NOCOPY forecast_details_tbl_type);
527 
528 -------------------------------------------------------
529 -- Following procedures were added to fix bug# 9263774.
530 -------------------------------------------------------
531 -- To process prior revision of a MR.
532 PROCEDURE Process_Prior_MR_Version (p_applicable_mrs_rec  IN applicable_mrs_rec_type,
533                                     p_new_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE,
534                                     p_unit_effectivity_tbl IN unit_effectivity_tbl_type,
535                                     p_old_UE_forecast_sequence IN NUMBER);
536 
537 -- Get applicability for expired MRs.
538 PROCEDURE Process_Appl_Expired_MRs;
539 
540 ----------------------------------------------------------
541 -- Following procedures were added for Service Bulletin ER
542 ----------------------------------------------------------
543 -- If MR has a accomplishment trigger of 'terminated_by' then check if parent MRs are processed
544 -- and if not, process them.
545 PROCEDURE Process_Terminating_Parent_MRs(p_applicable_mrs_rec IN applicable_mrs_rec_type,
546                                          p_current_usage_tbl  IN counter_values_tbl_type,
547                                          p_counter_rules_tbl  IN counter_rules_tbl_type,
548                                          x_mr_termination_date OUT NOCOPY DATE);
549 
550 -- initialization procedure for loops
551 PROCEDURE Process_Loop_Init(p_applicable_mrs_rec IN applicable_mrs_rec_type,
552                             p_current_usage_tbl  IN counter_values_tbl_type,
553                             p_counter_rules_tbl  IN counter_rules_tbl_type,
554                             x_loop_chain_MR_tbl         OUT NOCOPY loop_chain_MR_tbl_type,
555                             x_next_due_skip_flag        OUT NOCOPY VARCHAR2,
556                             x_loop_last_due_date        OUT NOCOPY DATE,
557                             x_loop_last_counter_val_tbl OUT NOCOPY counter_values_tbl_type);
558 
559 
560 -- initialization procedure for chains
561 PROCEDURE Process_Chain_Init(p_applicable_mrs_rec IN applicable_mrs_rec_type,
562                              p_current_usage_tbl  IN  counter_values_tbl_type,
563                              p_counter_rules_tbl  IN  counter_rules_tbl_type,
564                              x_loop_chain_MR_tbl       OUT NOCOPY loop_chain_MR_tbl_type);
565 
566 
567 -- process child MRs in a loop or chain
568 PROCEDURE Process_Loop_Chain_MRs (p_item_instance_id         IN NUMBER,
569                                   p_new_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE,
570                                   p_repetivity_flag          IN VARCHAR2 := 'Y',
571                                   p_current_usage_tbl        IN counter_values_tbl_type,
572                                   p_counter_rules_tbl        IN counter_rules_tbl_type,
573                                   p_last_due_date            IN DATE,
574                                   p_last_due_counter_val_tbl IN counter_values_tbl_type,
575                                   p_loop_chain_MR_tbl        IN loop_chain_MR_tbl_type,
576                                   x_loop_due_date              OUT NOCOPY DATE,
577                                   x_loop_last_due_date         OUT NOCOPY DATE,
578                                   x_loop_last_counter_val_tbl  OUT NOCOPY counter_values_tbl_type);
579 
580 -- get instance counter values for instance, accomplishment date or unit effectivity
581 PROCEDURE get_instance_ctr_for_date (p_item_instance_id         IN NUMBER,
582                                      p_last_accomplishment_date IN DATE,
583                                      p_deferral_flag            IN VARCHAR2,
584                                      p_unit_effectivity_id      IN NUMBER,
585                                      p_current_usage_tbl        IN counter_values_tbl_type,
586                                      p_counter_rules_tbl        IN counter_rules_tbl_type,
587                                      x_no_forecast_flag         OUT NOCOPY BOOLEAN,
588                                      x_last_acc_counter_val_tbl OUT NOCOPY counter_values_tbl_type);
589 
590 -- added for Complex Assembly Enh: To calculate due date for nonroutine when UE status is init-due.
591 PROCEDURE Calculate_NR_due_date(p_unit_effectivity_id  IN NUMBER,
592                                 x_due_date             OUT NOCOPY  DATE,
593                                 x_due_counter_value    OUT NOCOPY  NUMBER,
594                                 x_counter_id           OUT NOCOPY  NUMBER);
595 
596 ------------------------------
597 -- Declare global variables --
598 ------------------------------
599 G_config_node_tbl      AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type;
600 -- This variable holds all the item instances that are contained in a configuration.
601 -- For AHL installation, this will hold the top node and all of its components.
602 -- For PM installation, this will contain only one item instance, because each
603 -- component of a configuration is processed as a unit for this case.
604 
605 G_forecast_details_tbl forecast_details_tbl_type;
606 -- This variable holds the forecast information for the unit that is being
607 -- processed. This variable is set in procedure Process_Unit.
608 
609 G_last_day_of_window   DATE;
610 -- This variable holds the last day of the rolling window, calculated based on
611 -- the profile values set. This is set in procedure Process_Unit.
612 
613 G_master_config_id  NUMBER;
614 -- This variable holds the Master config ID if configuration has a master Configuration.
615 -- Not Applicable for PM installation.
616 
617 -- JKJain, NR Analysis and Forecasting
618 G_SIMULATION_PLAN_ID NUMBER := NULL;
619 -- This variable holds the SIMULATION_PLAN_ID if SIMULATION_PLAN_ID is passed to Process (ALL) Unit API.
620 
621 G_PRIMARY_PLAN VARCHAR2(1) := 'Y';
622 -- This variable will be Y if SIMULATION_PLAN_ID passed to Process (ALL) Unit API is NULL. Else it will be N.
623 
624 G_UC_HEADER_ID NUMBER ;
625 -- This variable holds the Unit config header ID if configuration has a unit Configuration.
626 
627 -----------------------
628 -- Define Procedures --
629 -----------------------
630 
631 -- Start of Comments --
632 --  Procedure name    : Process_Unit
633 --  Type        : Private
634 --  Function    : Manages Create/Modify/Delete operations of applicable maintenance
635 --                requirements on a unit.
636 --  Pre-reqs    :
637 --  Parameters  :
638 --
639 --  Standard OUT Parameters :
640 --      x_return_status                 OUT     VARCHAR2               Required
641 --      x_msg_count                     OUT     NUMBER                 Required
642 --      x_msg_data                      OUT     VARCHAR2               Required
643 --
644 --  Process_Unit Parameters :
645 --      Unit's Effectivity will be built for the input item instance.
646 --
647 
648 PROCEDURE Process_Unit (
649     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
650     p_init_msg_list          IN            VARCHAR2  := FND_API.G_FALSE,
651     x_msg_count              OUT  NOCOPY   NUMBER,
652     x_msg_data               OUT  NOCOPY   VARCHAR2,
653     x_return_status          OUT  NOCOPY   VARCHAR2,
654     p_csi_item_instance_id   IN            NUMBER,
655     p_concurrent_flag        IN            VARCHAR2 := 'N',
656     -- JKJain, NR Analysis and Forecasting
657     p_simulation_plan_id     IN            NUMBER    := NULL)
658 
659 IS
660 
661   l_inventory_item_id  NUMBER;
662   l_inv_master_organization_id NUMBER;
663 
664   l_uc_header_id    NUMBER;
665   -- This variable holds the Unit config ID if configuration is a Unit Configuration.
666   -- Not Applicable for PM installation.
667 
668   l_csi_item_instance_id  NUMBER;
669   -- This variable holds the Root item instance id.
670   -- For AHL installation, this is the root item instance of the input parameter p_csi_item_instance_id
671   -- For PM installation, this is the item instance input to this procedure(i.e p_csi_item_instance_id).
672 
673   l_config_node_tbl      AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type;
674   l_forecast_details_tbl forecast_details_tbl_type;
675 
676   l_UnSch_programs_tbl   PMprogram_tbl_type;
677   -- contains programs and their effectivities.
678 
679   l_ret_code             VARCHAR2(30);
680   l_expired_flag         VARCHAR2(1);
681 
682 BEGIN
683 
684   -- Standard start of API savepoint
685   SAVEPOINT Process_Unit_PVT;
686 
687  -- Initialize message list if p_init_msg_list is set to TRUE
688   IF FND_API.To_Boolean(p_init_msg_list) THEN
689     FND_MSG_PUB.Initialize;
690   END IF;
691 
692   -- Initialize Procedure return status to success
693   x_return_status := FND_API.G_RET_STS_SUCCESS;
694 
695   -- Enable Debug.
696   IF G_DEBUG = 'Y' THEN
697     AHL_DEBUG_PUB.enable_debug;
698   END IF;
699 
700   -- Add debug mesg.
701   IF G_DEBUG = 'Y' THEN
702     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'ProcessUnit');
703 
704     -- Dump input parameters.
705     AHL_DEBUG_PUB.debug(' Csi Item instance ID:' || p_csi_item_instance_id);
706     AHL_DEBUG_PUB.debug(' p_concurrent_flag:' || p_concurrent_flag );
707     AHL_DEBUG_PUB.debug(' p_commit:' || p_commit);
708     AHL_DEBUG_PUB.debug(' p_simulation_plan_id :' ||  p_simulation_plan_id);
709   END IF;
710 
711   G_concurrent_flag := p_concurrent_flag;
712 
713   -- JKJain, NR Analysis and Forecasting
714   IF(p_simulation_plan_id IS NULL) THEN
715       G_PRIMARY_PLAN := 'Y';
716       G_SIMULATION_PLAN_ID := NULL;
717   ELSE
718       G_PRIMARY_PLAN := 'N';
719       G_SIMULATION_PLAN_ID := p_simulation_plan_id;
720   END IF;
721 
722   IF (p_concurrent_flag = 'Y') THEN
723      fnd_file.put_line(fnd_file.log, 'Starting Process Unit for item instance: '|| p_csi_item_instance_id);
724      --fnd_file.put_line(fnd_file.log, 'G_IS_PM_INSTALLED: '|| G_IS_PM_INSTALLED);
725   END IF;
726 
727   -- Initialize temporary tables.
728 
729   DELETE FROM AHL_TEMP_UNIT_EFFECTIVITIES;
730   DELETE FROM AHL_TEMP_UNIT_SR_DEFERRALS;
731 
732   /* this validation will be done after getting root instance.
733   -- validate item instance.
734   Validate_item_instance(p_csi_item_instance_id, l_inventory_item_id,
735                          l_inv_master_organization_id);
736 
737   IF FND_MSG_PUB.Count_msg > 0 THEN
738      RAISE FND_API.G_EXC_ERROR;
739   END IF;
740 
741   -- Log success message if called by concurrent program.
742   IF (p_concurrent_flag = 'Y') THEN
743     fnd_file.put_line (FND_FILE.LOG, 'Validated Instance:'||p_csi_item_instance_id);
744   END IF;
745   */
746 
747   -- set instance variable.
748   l_csi_item_instance_id := p_csi_item_instance_id;
749 
750 
751   -- Set configuration variables based on installation type.
752   IF (G_IS_PM_INSTALLED = 'N') THEN
753   -- Only for AHL installation.
754 
755       -- If item instance is not top node, find the root item instance.
756       l_csi_item_instance_id := Get_RootInstanceID(l_csi_item_instance_id);
757 
758       -- validate item instance.
759       Validate_item_instance(l_csi_item_instance_id, l_inventory_item_id,
760                              l_inv_master_organization_id, l_expired_flag);
761 
762       IF FND_MSG_PUB.Count_msg > 0 THEN
763          RAISE FND_API.G_EXC_ERROR;
764       END IF;
765 
766       -- Log success message if called by concurrent program.
767       IF (p_concurrent_flag = 'Y') THEN
768         fnd_file.put_line (FND_FILE.LOG, 'Validated Instance:'||l_csi_item_instance_id);
769       END IF;
770 
771       -- Get master and unit configuration IDs if they exist for this item instance.
772       Get_Unit_Master_ConfigIDs (l_csi_item_instance_id,
773                                  l_uc_header_id, G_master_config_id);
774 
775       -- JKJain, NR Analysis and Forecasting
776       G_UC_HEADER_ID := l_uc_header_id;
777 
778       -- Check for errors.
779       IF FND_MSG_PUB.Count_msg > 0 THEN
780          RAISE FND_API.G_EXC_ERROR;
781       END IF;
782 
783       -- Build the Configuration tree structure.(G_config_node_tbl).
784       Build_Config_Tree(l_csi_item_instance_id, G_master_config_id, G_CONFIG_NODE_TBL);
785 
786   ELSE
787   -- For PM installation.
788 
789       -- validate item instance.
790       Validate_item_instance(p_csi_item_instance_id, l_inventory_item_id,
791                              l_inv_master_organization_id, l_expired_flag);
792 
793       IF FND_MSG_PUB.Count_msg > 0 THEN
794          RAISE FND_API.G_EXC_ERROR;
795       END IF;
796 
797       -- Log success message if called by concurrent program.
798       IF (p_concurrent_flag = 'Y') THEN
799         fnd_file.put_line (FND_FILE.LOG, 'Validated Instance:'||p_csi_item_instance_id);
800       END IF;
801 
802       -- Intialize config node table consisting of the input item instance.
803       G_config_node_tbl(1).csi_item_instance_id := p_csi_item_instance_id;
804 
805   END IF;  -- pm_install check
806 
807   -- Add debug mesg.
808   IF G_DEBUG = 'Y' THEN
809     AHL_DEBUG_PUB.debug(' Count on Config Node Tbl:' || G_config_node_tbl.COUNT);
810     AHL_DEBUG_PUB.debug(' Root Node:' || l_csi_item_instance_id );
811     AHL_DEBUG_PUB.debug(' Unit Config ID:' || l_uc_header_id);
812     AHL_DEBUG_PUB.debug(' Master Config ID:' || G_master_config_id);
813     AHL_DEBUG_PUB.debug(' l_expired_flag:' || l_expired_flag);
814   END IF;
815 
816   -- Get rolling window end date.
817   G_last_day_of_window := Get_Rolling_Window_Date;
818 
819   IF (l_expired_flag = 'Y') THEN
820     GOTO process_cleanup;
821   END IF;
822 
823   -- Call FMP to get applicable MRs.
824   IF (G_IS_PM_INSTALLED = 'N') THEN
825    -- Only for AHL installation.
826 
827       IF G_DEBUG = 'Y' THEN
828         AHL_DEBUG_PUB.debug('AHL Installation processing');
829       END IF;
830 
831        -- Call FMP api to build applicable MRs for the unit.
832        AHL_UMP_UTIL_PKG.Populate_Appl_MRs ( p_csi_ii_id => l_csi_item_instance_id,
833                                             --p_include_doNotImplmt => 'N',
834                                             p_include_doNotImplmt => 'Y',
835                                             x_return_status => x_return_status,
836                                             x_msg_count => x_msg_count,
837                                             x_msg_data => x_msg_data );
838 
839        IF (x_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
840           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
841        ELSIF (x_return_status = FND_API.G_RET_STS_ERROR) THEN
842           RAISE FND_API.G_EXC_ERROR;
843        END IF;
844 
845        -- Build applicability for group MRs.
846        AHL_UMP_UTIL_PKG.Process_Group_MRs;
847 
848   ELSE  -- for PM installation.
849        IF G_DEBUG = 'Y' THEN
850          AHL_DEBUG_PUB.debug('PM Installation processing');
851        END IF;
852 
853        -- Call FMP-PM api to build applicable MRs for an instance.
854        PopulatePM_Appl_MRs (p_csi_ii_id => l_csi_item_instance_id,
855                             x_return_status => x_return_status,
856                             x_msg_count => x_msg_count,
857                             x_msg_data => x_msg_data,
858                             x_UnSch_programs_tbl => l_UnSch_programs_tbl);
859 
860        IF (x_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
861          RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
862        ELSIF (x_return_status = FND_API.G_RET_STS_ERROR) THEN
863          RAISE FND_API.G_EXC_ERROR;
864        END IF;
865 
866   END IF; -- pm_install check.
867 
868   IF G_DEBUG = 'Y' THEN
869     AHL_DEBUG_PUB.debug('After calling FMP API and process group MRs');
870   END IF;
871 
872   -- Read applicable utilization forecast for the configuration.
873   Get_Utilization_Forecast (l_csi_item_instance_id,
874                             l_uc_header_id,
875                             l_inventory_item_id,
876                             l_inv_master_organization_id,
877                             G_forecast_details_tbl);
878 
879 
880   -- Lock records.
881   FOR i IN 1..4 LOOP
882     Lock_UnitEffectivity_Records(x_ret_code => l_ret_code);
883     EXIT WHEN (l_ret_code <> '-54');
884     DBMS_LOCK.SLEEP(30);
885   END LOOP;
886 
887   IF (l_ret_code = -54) THEN
888     FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_ALREADY_RUNNING');
889     FND_MSG_PUB.ADD;
890     RAISE  FND_API.G_EXC_ERROR;
891   END IF;
892 
893   /*
894   -- Log success message if called by concurrent program.
895   IF (p_concurrent_flag = 'Y') THEN
896     fnd_file.put_line (FND_FILE.LOG, 'G Config Tbl:' || G_config_node_tbl.COUNT);
897     fnd_file.put_line (FND_FILE.LOG, 'G_forecast_details_tbl:' || G_forecast_details_tbl.count);
898     fnd_file.put_line (FND_FILE.LOG, 'Last Day window:' || G_last_day_of_window);
899     fnd_file.put_line (FND_FILE.LOG, 'UC Header ID:' || l_uc_header_id);
900   END IF;
901   */
902 
903   -- Note: Both of the procedures Process_ASO_Unit and Process_PM_Unit use global variables
904   -- set by this procedure in addition to any input parameters.
905   IF (G_IS_PM_INSTALLED = 'N') THEN
906      Process_ASO_Unit;
907   ELSE
908      Process_PM_Unit(p_csi_item_instance_id  => l_csi_item_instance_id,
909                      p_UnSch_programs_tbl    => l_UnSch_programs_tbl);
910   END IF;
911 
912   <<process_cleanup>>
913   -- JKJain, NR Analysis and Forecasting
914   --IF p_simulation_plan_id is null, then flush to UE table else, flush to simulated UE table
915   IF (G_PRIMARY_PLAN = 'Y') THEN
916       -- Flush from temporary table to ahl_unit_effectivities.
917       AHL_UMP_PROCESSUNIT_EXTN_PVT.Flush_From_Temp_Table(G_config_node_tbl,G_UC_HEADER_ID);
918   ELSE
919       AHL_UMP_PROCESSUNIT_EXTN_PVT.Flush_To_Sim_Ue_Table(G_config_node_tbl,p_simulation_plan_id,G_UC_HEADER_ID);
920   END IF;
921 
922   -- Check for errors.
923   IF FND_MSG_PUB.Count_msg > 0 THEN
924      RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
925   END IF;
926 
927   /* -- commented for performance fix - bug# 6893404
928   IF (G_IS_PM_INSTALLED = 'N') THEN
929    -- Only for AHL installation.
930 
931     --call for material requirement forecst
932     AHL_UMP_FORECAST_REQ_PVT.process_mrl_req_forecast
933     (
934      p_api_version                => 1.0,
935      p_init_msg_list              => FND_API.G_TRUE,
936      p_commit                     => FND_API.G_FALSE,
937      p_validation_level           => FND_API.G_VALID_LEVEL_FULL,
938      x_return_status              => x_return_status,
939      x_msg_count                  => x_msg_count,
940      x_msg_data                   => x_msg_data,
941      p_applicable_instances_tbl   => G_config_node_tbl
942     );
943 
944     -- Check for errors.
945     IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
946        RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
947     END IF;
948 
949   END IF;
950   */
951 
952   -- Standard check of p_commit
953   IF FND_API.TO_BOOLEAN(p_commit) THEN
954       COMMIT WORK;
955   END IF;
956 
957   -- Log success message if called by concurrent program.
958   IF (p_concurrent_flag = 'Y') THEN
959     fnd_file.put_line (FND_FILE.LOG, 'Message-Successfully processed:'||p_csi_item_instance_id);
960   END IF;
961 
962   -- Standard call to get message count and if count is 1, get message info
963   FND_MSG_PUB.Count_And_Get
964     ( p_count => x_msg_count,
965       p_data  => x_msg_data,
966       p_encoded => fnd_api.g_false
967     );
968 
969 --
970 EXCEPTION
971  WHEN FND_API.G_EXC_ERROR THEN
972    x_return_status := FND_API.G_RET_STS_ERROR;
973    Rollback to Process_Unit_PVT;
974    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
975                               p_data  => x_msg_data,
976                               p_encoded => fnd_api.g_false);
977 
978    IF (p_concurrent_flag = 'Y') THEN
979 
980      fnd_file.put_line(fnd_file.log, 'Process Unit failed for item instance: '|| p_csi_item_instance_id);
981      log_error_messages;
982    END IF;
983 
984    -- Disable debug
985    AHL_DEBUG_PUB.disable_debug;
986 
987  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
988    x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
989    Rollback to Process_Unit_PVT;
990    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
991                               p_data  => x_msg_data,
992                               p_encoded => fnd_api.g_false);
993 
994    IF (p_concurrent_flag = 'Y') THEN
995      fnd_file.put_line(fnd_file.log, 'Process Unit failed for item instance: '|| p_csi_item_instance_id);
996      log_error_messages;
997    END IF;
998 
999    -- Disable debug
1000    AHL_DEBUG_PUB.disable_debug;
1001 
1002  WHEN OTHERS THEN
1003 
1004     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1005     Rollback to Process_Unit_PVT;
1006     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1007        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
1008                                p_procedure_name => 'Process_Unit_PVT',
1009                                p_error_text     => SUBSTR(SQLERRM,1,240));
1010     END IF;
1011     FND_MSG_PUB.count_and_get( p_count => x_msg_count,
1012                                p_data  => x_msg_data,
1013                                p_encoded => fnd_api.g_false);
1014 
1015 
1016     IF (p_concurrent_flag = 'Y') THEN
1017      fnd_file.put_line(fnd_file.log, 'Process Unit failed for item instance: '|| p_csi_item_instance_id);
1018      log_error_messages;
1019     END IF;
1020 
1021     -- Disable debug
1022     AHL_DEBUG_PUB.disable_debug;
1023 
1024 END Process_Unit;
1025 
1026 -------------------------------------------------------------------------------
1027 -- Start of Comments --
1028 --  Procedure name    : Process_MRAffected_Units
1029 --  Type        : Private
1030 --  Function    : Processes all units that are affected for a Maintenance requirement.
1031 --  Pre-reqs    :
1032 --  Parameters  :
1033 --
1034 --  Process_MR_Affected_Units Parameters :
1035 --  Effectivity will be built for all units having p_mr_id as a maintenance requirement.
1036 --  This procedure will also be called from terminate_MRs; in which case p_old_mr_header_id
1037 --  will also be passed.p_old_mr_header_id is the MR that was terminated. Effectivity will
1038 --  be re-build for all units that had p_old_mr_header_id as applicability.
1039 --
1040 --  p_concurrent_flag                   IN      VARCHAR2
1041 --  This flag will be 'Y' if called from a concurrent program. Based on this flag, the error
1042 --  and informational messages will be logged into the log file.
1043 --
1044 
1045 PROCEDURE Process_MRAffected_Units (
1046     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
1047     x_msg_count              OUT NOCOPY    NUMBER,
1048     x_msg_data               OUT NOCOPY    VARCHAR2,
1049     x_return_status          OUT NOCOPY    VARCHAR2,
1050     p_mr_header_id           IN            NUMBER,
1051     p_old_mr_header_id       IN            NUMBER    := NULL,
1052     p_concurrent_flag        IN            VARCHAR2  := 'N',
1053     p_num_of_workers         IN            NUMBER    := 1,
1054     p_mtl_category_id        IN            NUMBER    := NULL,
1055     p_process_option         IN            VARCHAR2  := NULL)
1056 
1057 
1058 IS
1059 
1060   l_commit VARCHAR2(1) := p_commit;
1061 
1062   l_conc_request_id        NUMBER;
1063   l_req_id                 NUMBER;
1064   l_instance_id            NUMBER;
1065   l_num_of_workers         NUMBER;
1066 
1067   -- added for bug# 10185468
1068   l_err_mesg               VARCHAR2(4000);
1069   l_return_status          VARCHAR2(1);
1070 
1071 BEGIN
1072 
1073   -- Initialize Procedure return status to success
1074   x_return_status := FND_API.G_RET_STS_SUCCESS;
1075 
1076   -- Enable Debug.
1077   IF G_DEBUG = 'Y' THEN
1078     AHL_DEBUG_PUB.enable_debug;
1079   END IF;
1080 
1081   -- Add debug mesg.
1082   IF G_DEBUG = 'Y' THEN
1083     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Process_MRAffected_Units');
1084     AHL_DEBUG_PUB.debug('Application Usage Profile:' || fnd_profile.value('AHL_APPLN_USAGE'));
1085   END IF;
1086 
1087   IF (p_concurrent_flag = 'Y') THEN
1088      l_commit := FND_API.G_TRUE;
1089      l_conc_request_id := fnd_global.conc_request_id;
1090      IF (l_conc_request_id = -1) OR (l_conc_request_id IS NULL) OR (l_conc_request_id <= 0) THEN
1091         -- this will happen only when called from UMP Terminate_MR_Instances api.
1092         l_conc_request_id := fnd_global.login_id;
1093      END IF;
1094   ELSE
1095      l_conc_request_id := fnd_global.session_id;
1096   END IF;
1097 
1098   -- validate p_num_of_workers.
1099   l_num_of_workers := trunc(p_num_of_workers);
1100 
1101   IF (l_num_of_workers IS NULL OR l_num_of_workers <= 0) THEN
1102     l_num_of_workers := 1;
1103   ELSIF l_num_of_workers > 30 THEN
1104     l_num_of_workers := 30;
1105   END IF;
1106 
1107   -- Set FMP parameter based on PM installation.
1108   IF (G_IS_PM_INSTALLED = 'Y') THEN
1109      -- PM processing(fix for performance bug# 5093064).
1110      Process_PM_MR_Affected_Items(
1111                    p_commit       => l_commit,
1112  	           x_msg_count    => x_msg_count,
1113  	           x_msg_data       => x_msg_data,
1114  	           x_return_status  => x_return_status,
1115  	           p_mr_header_id    => p_mr_header_id,
1116  	           p_old_mr_header_id  => p_old_mr_header_id,
1117                    p_concurrent_flag   => p_concurrent_flag,
1118                    p_num_of_workers   => l_num_of_workers);
1119   ELSE
1120 
1121      Populate_BUE_Worker_for_MR(p_conc_request_id => l_conc_request_id,
1122                                 p_mr_header_id    => p_mr_header_id,
1123                                 p_concurrent_flag => p_concurrent_flag,
1124                                 p_mtl_category_id => p_mtl_category_id,
1125                                 p_process_option  => p_process_option,
1126                                 x_return_status   => x_return_status);
1127 
1128      IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1129        RETURN;
1130      END IF;
1131 
1132      IF (p_old_mr_header_id IS NOT NULL AND p_old_mr_header_id <> FND_API.G_MISS_NUM) THEN
1133          -- Call FMP API to get all items instances which have old mr_id in its applicability.
1134          Populate_BUE_Worker_for_MR(p_conc_request_id => l_conc_request_id,
1135                                     p_mr_header_id    => p_old_mr_header_id,
1136                                     p_concurrent_flag => p_concurrent_flag,
1137                                     p_mtl_category_id => p_mtl_category_id,
1138                                     p_process_option  => p_process_option,
1139                                     x_return_status   => x_return_status);
1140          IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1141            RETURN;
1142          END IF;
1143      END IF; -- p_old_mr_header_id I
1144 
1145      IF (p_concurrent_flag = 'Y') THEN
1146        -- submit worker programs to process units.
1147        FOR i IN 1..l_num_of_workers LOOP
1148          l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, l_conc_request_id);
1149          IF (l_req_id = 0 OR l_req_id IS NULL) THEN
1150             IF G_debug = 'Y' THEN
1151                AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
1152             END IF;
1153             fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
1154             fnd_file.new_line(FND_FILE.LOG,1);
1155             x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1156             EXIT; -- abort and return to calling pgm.
1157 
1158          ELSE
1159             fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id);
1160             IF G_debug = 'Y' THEN
1161                AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id );
1162             END IF;
1163          END IF; -- l_req_id = 0 OR ..
1164 
1165        END LOOP;
1166 
1167        -- call cleanup BUE for previously failed deletes.
1168        Cleanup_BUE_Worker(p_parent_conc_request_id => l_conc_request_id,
1169                           p_child_conc_request_id  => NULL,
1170                           x_return_status          => l_return_status,
1171                           x_errbuf                 => l_err_mesg);
1172        IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1173          -- ignore error returned from this procedure
1174          -- log message in concurrent request log.
1175          fnd_file.put_line(FND_FILE.LOG, 'Warning: Error from Cleanup_BUE_Worker:' || l_err_mesg);
1176        END IF;
1177 
1178      ELSE
1179          LOOP
1180             -- initialize return status.
1181             x_return_status := FND_API.G_RET_STS_SUCCESS;
1182 
1183             -- process each unit from worker table.
1184             Get_Next_BUE_Row(p_parent_conc_pgm_id  => l_conc_request_id,
1185                              p_conc_child_req_id   => l_conc_request_id,
1186                              errbuf                => x_msg_data,
1187                              x_return_status       => x_return_status,
1188                              x_item_instance_id    => l_instance_id);
1189 
1190             IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1191               EXIT; -- abort and return to calling pgm.
1192             END IF;
1193 
1194             EXIT WHEN (l_instance_id IS NULL);
1195 
1196             IF G_DEBUG = 'Y' THEN
1197                AHL_DEBUG_PUB.debug('Now processing..:' || l_instance_id);
1198             END IF;
1199 
1200             -- Call Process Unit for the item instance.
1201             Process_Unit (
1202                   p_commit               => l_commit,
1203                   p_init_msg_list        => FND_API.G_TRUE,
1204                   x_msg_count            => x_msg_count,
1205                   x_msg_data             => x_msg_data,
1206                   x_return_status        => x_return_status,
1207                   p_csi_item_instance_id => l_instance_id,
1208                   p_concurrent_flag      => p_concurrent_flag);
1209 
1210             IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1211               EXIT; -- abort and return to calling pgm.
1212             END IF;
1213 
1214          END LOOP;
1215 
1216          -- cleanup worker table after processing.
1217          Cleanup_BUE_Worker(p_parent_conc_request_id => l_conc_request_id,
1218                             p_child_conc_request_id  => l_conc_request_id,
1219                             x_return_status          => l_return_status,
1220                             x_errbuf                 => l_err_mesg);
1221          IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1222             -- ignore error returned from this procedure
1223             IF G_DEBUG = 'Y' THEN
1224                AHL_DEBUG_PUB.debug('Warning: Error from Cleanup_BUE_Worker:' || l_err_mesg);
1225             END IF;
1226          END IF;
1227 
1228      END IF; -- p_concurrent_flag
1229 
1230   END IF; -- G_IS_PM_INSTALLED.
1231 
1232 END Process_MRAffected_Units;
1233 
1234 -- Tamal: Bug #4207212, #4114368: Begin
1235 ------------------------------------------------------------------------------
1236 -- Start of Comments --
1237 --  Procedure name    : Process_PM_Contracts
1238 --  Type        : Private
1239 --  Function    : Retrieves all instances for a contract and calls Process_Unit for each unit.
1240 --  Pre-reqs    :
1241 --  Parameters  :
1242 --
1243 --  p_concurrent_flag                   IN      VARCHAR2
1244 --  This flag will be 'Y' if called from a concurrent program. Based on this flag, the error
1245 --  and informational messages will be logged into the log file.
1246 --  p_contract_number			IN	VARCHAR2
1247 --  The contract number for which want to process csi_item_instances entitlement
1248 --  p_contract_number			IN	VARCHAR2
1249 --  The contract number modifier for above contract number
1250 
1251 PROCEDURE Process_PM_Contracts
1252 (
1253     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
1254     p_init_msg_list          IN            VARCHAR2  := FND_API.G_FALSE,
1255     x_msg_count              OUT  NOCOPY   NUMBER,
1256     x_msg_data               OUT  NOCOPY   VARCHAR2,
1257     x_return_status          OUT  NOCOPY   VARCHAR2,
1258     p_contract_number        IN            VARCHAR2  := NULL,
1259     p_contract_modifier      IN            VARCHAR2  := NULL,
1260     p_concurrent_flag        IN            VARCHAR2  := 'N'
1261 )
1262 IS
1263     l_msg_count		number;
1264     l_commit		varchar2(1) := p_commit;
1265 
1266     l_inp_cont_rec           OKS_ENTITLEMENTS_PUB.inp_cont_rec;
1267     l_ent_cont_tbl           OKS_ENTITLEMENTS_PUB.ent_cont_tbl;
1268 
1269     -- Fix for bug# 5639852.
1270     CURSOR get_oks_line_end_dt1(p_contract_number IN VARCHAR2,
1271                                 p_contract_modifier IN VARCHAR2)
1272     IS
1273       SELECT trunc(min(okl.end_date)), trunc(okh.start_date)
1274       FROM okc_k_headers_b okh, okc_k_lines_b okl
1275       WHERE OKL.DNZ_CHR_ID = OKH.ID
1276         AND OKH.CONTRACT_NUMBER = p_contract_number
1277         AND OKH.CONTRACT_NUMBER_MODIFIER = p_contract_modifier
1278         GROUP BY OKH.ID, OKH.start_date;
1279 
1280     CURSOR get_oks_line_end_dt2(p_contract_number IN VARCHAR2)
1281     IS
1282       SELECT trunc(min(okl.end_date)), trunc(okh.start_date)
1283       FROM okc_k_headers_b okh, okc_k_lines_b okl
1284       WHERE OKL.DNZ_CHR_ID = OKH.ID
1285         AND OKH.CONTRACT_NUMBER = p_contract_number
1286         GROUP BY OKH.ID, OKH.start_date;
1287 
1288     l_end_date  DATE;
1289     l_start_date  DATE;
1290 
1291 BEGIN
1292     -- Standard start of API savepoint
1293     SAVEPOINT Process_PM_Contracts_PVT;
1294 
1295     -- Initialize message list if p_init_msg_list is set to TRUE
1296     IF FND_API.To_Boolean(p_init_msg_list) THEN
1297         FND_MSG_PUB.Initialize;
1298     END IF;
1299 
1300     -- Initialize Procedure return status to success
1301     x_return_status := FND_API.G_RET_STS_SUCCESS;
1302 
1303     -- Enable Debug.
1304     IF G_DEBUG = 'Y' THEN
1305         AHL_DEBUG_PUB.enable_debug;
1306     END IF;
1307 
1308     -- Add debug mesg.
1309     IF G_DEBUG = 'Y' THEN
1310         AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Process_PM_Contracts');
1311         -- Dump input parameters.
1312         AHL_DEBUG_PUB.debug('Contract Number:' || p_contract_number );
1313         AHL_DEBUG_PUB.debug('Contract Modifier:' || p_contract_modifier );
1314         AHL_DEBUG_PUB.debug('p_concurrent_flag:' || p_concurrent_flag );
1315         AHL_DEBUG_PUB.debug('p_commit:' || p_commit );
1316     END IF;
1317 
1318     IF (p_concurrent_flag = 'Y') THEN
1319         fnd_file.put_line(fnd_file.log, 'Starting processing for contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1320     	-- If the call is from concurrent program, then commit should default to TRUE
1321     	l_commit := FND_API.G_TRUE;
1322     END IF;
1323 
1324     l_inp_cont_rec.contract_number := p_contract_number;
1325     l_inp_cont_rec.contract_number_modifier := p_contract_modifier;
1326     l_inp_cont_rec.validate_flag := 'Y';
1327 
1328     -- Fix for bug# 5639852 -- Begin.
1329     l_inp_cont_rec.request_date := NULL;  -- defaults to sysdate.
1330 
1331     -- For signed contracts we need to send a future date.
1332     -- find out the minimum end date for the contract lines to ensure date
1333     -- coverage for all service lines.
1334     IF (p_contract_modifier IS NULL) THEN
1335        OPEN get_oks_line_end_dt2(p_contract_number);
1336        FETCH get_oks_line_end_dt2 INTO l_end_date, l_start_date;
1337        CLOSE get_oks_line_end_dt2;
1338     ELSE
1339        OPEN get_oks_line_end_dt1(p_contract_number, p_contract_modifier);
1340        FETCH get_oks_line_end_dt1 INTO l_end_date, l_start_date;
1341        CLOSE get_oks_line_end_dt1;
1342     END IF;
1343 
1344     IF (l_start_date > trunc(sysdate)) THEN
1345       IF (l_end_date IS NOT NULL) THEN
1346          l_inp_cont_rec.request_date := l_end_date;
1347       END IF;
1348     END IF;
1349     -- Fix for bug# 5639852 -- End.
1350 
1351     OKS_ENTITLEMENTS_PUB.get_contracts
1352     (
1353         p_api_version   => 1.0,
1354         p_init_msg_list => FND_API.G_FALSE,
1355         p_inp_rec       => l_inp_cont_rec,
1356         x_return_status => x_return_status,
1357         x_msg_count     => x_msg_count,
1358         x_msg_data      => x_msg_data,
1359         x_ent_contracts => l_ent_cont_tbl
1360     );
1361 
1362     -- Check Error Message stack.
1363     l_msg_count := FND_MSG_PUB.count_msg;
1364     IF (l_msg_count > 0 or x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1365         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1366     END IF;
1367 
1368     IF (l_ent_cont_tbl.count > 0)
1369     THEN
1370         FOR i IN l_ent_cont_tbl.FIRST..l_ent_cont_tbl.LAST
1371         LOOP
1372             IF (l_ent_cont_tbl(i).coverage_level_code = 'COVER_PROD')
1373             THEN
1374                 IF (p_concurrent_flag = 'Y') THEN
1375                     fnd_file.put_line(fnd_file.log, 'Calling Process_Unit for instance: ' || l_ent_cont_tbl(i).coverage_level_id);
1376                 END IF;
1377                 AHL_UMP_ProcessUnit_PVT.Process_Unit
1378                 (
1379                     p_commit               => l_commit,
1380                     x_msg_count            => x_msg_count,
1381                     x_msg_data             => x_msg_data,
1382                     x_return_status        => x_return_status,
1383                     p_csi_item_instance_id => l_ent_cont_tbl(i).coverage_level_id,
1384                     p_concurrent_flag      => p_concurrent_flag
1385                 );
1386                 IF (p_concurrent_flag = 'Y' and (FND_MSG_PUB.count_msg > 0 or x_return_status <> FND_API.G_RET_STS_SUCCESS)) THEN
1387                     fnd_file.put_line(fnd_file.log, 'Process_Unit failed for instance: ' || l_ent_cont_tbl(i).coverage_level_id);
1388                 END IF;
1389             END IF;
1390         END LOOP;
1391     END IF;
1392 
1393     -- Check Error Message stack.
1394     l_msg_count := FND_MSG_PUB.count_msg;
1395     IF (l_msg_count > 0 or x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1396         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1397     END IF;
1398 
1399     -- Standard check of p_commit
1400     IF FND_API.TO_BOOLEAN(p_commit) THEN
1401         COMMIT WORK;
1402     END IF;
1403 
1404     -- Log success message if called by concurrent program.
1405     IF (p_concurrent_flag = 'Y') THEN
1406         fnd_file.put_line(fnd_file.log, 'Message-Successfully processed: contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1407     END IF;
1408 
1409     -- Standard call to get message count and if count is 1, get message info
1410     FND_MSG_PUB.Count_And_Get
1411     (
1412         p_count => x_msg_count,
1413         p_data  => x_msg_data,
1414         p_encoded => fnd_api.g_false
1415     );
1416 
1417 EXCEPTION
1418     WHEN FND_API.G_EXC_ERROR THEN
1419         x_return_status := FND_API.G_RET_STS_ERROR;
1420         Rollback to Process_PM_Contracts_PVT;
1421         FND_MSG_PUB.count_and_get
1422         (
1423             p_count => x_msg_count,
1424             p_data  => x_msg_data,
1425             p_encoded => fnd_api.g_false
1426         );
1427         IF (p_concurrent_flag = 'Y') THEN
1428             fnd_file.put_line(fnd_file.log, 'Process_PM_Contracts failed for: contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1429             log_error_messages;
1430         END IF;
1431         AHL_DEBUG_PUB.disable_debug;
1432 
1433     WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
1434         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1435         Rollback to Process_PM_Contracts_PVT;
1436         FND_MSG_PUB.count_and_get
1437         (
1438             p_count => x_msg_count,
1439             p_data  => x_msg_data,
1440             p_encoded => fnd_api.g_false
1441         );
1442         IF (p_concurrent_flag = 'Y') THEN
1443             fnd_file.put_line(fnd_file.log, 'Process_PM_Contracts failed for: contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1444             log_error_messages;
1445         END IF;
1446         AHL_DEBUG_PUB.disable_debug;
1447 
1448     WHEN OTHERS THEN
1449         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1450         Rollback to Process_PM_Contracts_PVT;
1451         IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1452             fnd_msg_pub.add_exc_msg
1453             (
1454                 p_pkg_name       => G_PKG_NAME,
1455                 p_procedure_name => 'Process_PM_Contracts',
1456                 p_error_text     => SUBSTR(SQLERRM,1,240)
1457             );
1458         END IF;
1459         FND_MSG_PUB.count_and_get
1460         (
1461             p_count => x_msg_count,
1462             p_data  => x_msg_data,
1463             p_encoded => fnd_api.g_false
1464         );
1465         IF (p_concurrent_flag = 'Y') THEN
1466             fnd_file.put_line(fnd_file.log, 'Process_PM_Contracts failed for: contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1467             log_error_messages;
1468         END IF;
1469         AHL_DEBUG_PUB.disable_debug;
1470 END Process_PM_Contracts;
1471 -- Tamal: Bug #4207212, #4114368: End
1472 
1473 ------------------------------------------------------------------------------
1474 -- Start of Comments --
1475 --  Procedure name    : Process_All_Units
1476 --  Type        : Private
1477 --  Function    : Loops through all units and calls Process_Unit for each unit.
1478 --  Pre-reqs    :
1479 --  Parameters  :
1480 --
1481 --  p_concurrent_flag                   IN      VARCHAR2
1482 --  This flag will be 'Y' if called from a concurrent program. Based on this flag, the error
1483 --  and informational messages will be logged into the log file by Process_Unit.
1484 
1485 PROCEDURE Process_All_Units (
1486     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
1487     x_msg_count              OUT  NOCOPY   NUMBER,
1488     x_msg_data               OUT  NOCOPY   VARCHAR2,
1489     x_return_status          OUT  NOCOPY   VARCHAR2,
1490     p_concurrent_flag        IN            VARCHAR2  := 'N',
1491     p_num_of_workers         IN            NUMBER    := 1,
1492     p_mtl_category_id        IN            NUMBER    := NULL,
1493     p_process_option         IN            VARCHAR2  := NULL,
1494     -- JKJain, NR Analysis and Forecasting
1495     p_simulation_plan_id     IN            NUMBER    := NULL)
1496 
1497 IS
1498 
1499   -- uncommented query to fix performance issue 6893404
1500   -- declare cursor to retrieve min/max instances from Installed Base for PM installation.
1501   CURSOR csi_pm_instance_csr IS
1502      SELECT min(instance_id), max(instance_id)
1503      FROM csi_item_instances csi,
1504      (select me.inventory_item_id
1505       from ahl_mr_effectivities me, ahl_mr_headers_app_v mr
1506       where mr.mr_header_id = me.mr_header_id
1507         and mr.type_code = 'PROGRAM') mre
1508      WHERE trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) AND
1509            trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
1510      AND mre.inventory_item_id = csi.inventory_item_id;
1511 
1512 
1513   l_commit VARCHAR2(1) := p_commit;
1514 
1515   l_min_csi_id             NUMBER;
1516   l_max_csi_id             NUMBER;
1517 
1518 BEGIN
1519 
1520   -- Initialize Procedure return status to success
1521   x_return_status := FND_API.G_RET_STS_SUCCESS;
1522 
1523   -- Enable Debug.
1524   -- Add api start debug mesg.
1525   IF G_DEBUG = 'Y' THEN
1526     AHL_DEBUG_PUB.enable_debug;
1527     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Process_All_Units');
1528   END IF;
1529 
1530   -- For concurrent program.
1531   IF (p_concurrent_flag = 'Y') THEN
1532      l_commit := FND_API.G_TRUE;
1533   END IF;
1534 
1535   -- JKJain, NR Analysis and Forecasting
1536   IF(p_simulation_plan_id IS NULL) THEN
1537     G_PRIMARY_PLAN := 'Y';
1538     G_SIMULATION_PLAN_ID := NULL;
1539   ELSE
1540     G_PRIMARY_PLAN := 'N';
1541     G_SIMULATION_PLAN_ID := p_simulation_plan_id;
1542 
1543     --Delete sim UEs belonging to unit which are not not present in the sim plan now or are expired
1544     DELETE FROM AHL_UE_SIMULATIONS
1545      WHERE SIMULATION_PLAN_ID  = p_simulation_plan_id
1546        AND UNIT_CONFIG_HEADER_ID NOT IN
1547           (SELECT DISTINCT FU.UNIT_CONFIG_HEADER_ID
1548              FROM AHL_FLEET_UNIT_ASSOCS FU,
1549                   AHL_UNIT_CONFIG_HEADERS UC
1550             WHERE SIMULATION_PLAN_ID  =  p_simulation_plan_id
1551               AND UC.UNIT_CONFIG_HEADER_ID  = FU.UNIT_CONFIG_HEADER_ID
1552               AND ahl_util_uc_pkg.get_uc_status_code(UC.UNIT_CONFIG_HEADER_ID) NOT IN ('DRAFT', 'EXPIRED')
1553           );
1554   END IF;
1555 
1556   IF (G_IS_PM_INSTALLED = 'N') THEN
1557      -- AHL processing.
1558      Split_Process_All_Instances(p_concurrent_flag => p_concurrent_flag,
1559                                  p_commit_flag     => l_commit,
1560                                  p_num_of_workers  => p_num_of_workers,
1561                                  p_mr_header_id    => null,
1562                                  p_mtl_category_id => p_mtl_category_id,
1563                                  p_process_option  => p_process_option,
1564                                  x_msg_count       => x_msg_count,
1565                                  x_msg_data        => x_msg_data,
1566                                  x_return_status   => x_return_status);
1567 
1568      IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1569        RETURN;
1570      END IF;
1571 
1572   ELSE
1573      -- PM processing.
1574      OPEN csi_pm_instance_csr;
1575      FETCH csi_pm_instance_csr INTO l_min_csi_id, l_max_csi_id;
1576      CLOSE csi_pm_instance_csr;
1577 
1578      Instance_Split_Sequential(p_csi_max_id  => l_max_csi_id,
1579                                p_csi_min_id  => l_min_csi_id,
1580                                p_num_workers => p_num_of_workers,
1581                                p_mr_header_id => null);
1582   END IF; -- pm installation check.
1583 
1584 END Process_All_Units;
1585 
1586 --------------------------------------------------------------------------
1587 PROCEDURE Validate_Item_Instance (p_csi_item_instance_id IN NUMBER,
1588                                   x_inventory_item_id    OUT NOCOPY NUMBER,
1589                                   x_inv_master_organization_id OUT NOCOPY NUMBER,
1590                                   x_expired_flag               OUT NOCOPY VARCHAR2)
1591 IS
1592 
1593 -- To validate instance.
1594   CURSOR csi_item_instances_csr(p_csi_item_instance_id IN  NUMBER) IS
1595     SELECT instance_number, active_end_date,
1596            inventory_item_id,
1597            inv_master_organization_id
1598     FROM csi_item_instances
1599     WHERE instance_id = p_csi_item_instance_id;
1600 
1601 l_inventory_item_id           NUMBER;
1602 l_inv_master_organization_id  NUMBER;
1603 l_instance_number             csi_item_instances.instance_number%TYPE;
1604 l_active_end_date             DATE;
1605 l_expired_flag                VARCHAR2(1);
1606 
1607 BEGIN
1608 
1609   IF G_DEBUG = 'Y' THEN
1610      AHL_DEBUG_PUB.debug('Start Validate Item Instance');
1611   END IF;
1612 
1613   -- added to fix bug# 8567880.
1614   l_expired_flag := 'N';
1615 
1616   -- Validate csi_item_instance_id.
1617   IF (p_csi_item_instance_id IS NOT NULL) THEN
1618     OPEN csi_item_instances_csr (p_csi_item_instance_id);
1619     FETCH csi_item_instances_csr INTO l_instance_number, l_active_end_date,
1620                                      l_inventory_item_id, l_inv_master_organization_id;
1621     IF (csi_item_instances_csr%NOTFOUND) THEN
1622       FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_INSTID_NOTFOUND');
1623       FND_MESSAGE.Set_Token('INST_ID', p_csi_item_instance_id);
1624       FND_MSG_PUB.ADD;
1625       CLOSE csi_item_instances_csr;
1626       --dbms_output.put_line('Instance not found');
1627       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1628     ELSIF l_active_end_date <= sysdate THEN
1629     /* Bypass error to fix bug# 8567880. For expired
1630        instances we will delete open UMPs.
1631       FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_INST_EXPIRED');
1632       FND_MESSAGE.Set_Token('NUMBER', l_instance_number);
1633       FND_MSG_PUB.ADD;
1634       --dbms_output.put_line('Instance has expired');
1635     */
1636       l_expired_flag := 'Y';
1637     END IF;
1638 
1639     CLOSE csi_item_instances_csr;
1640   END IF;
1641 
1642   x_inventory_item_id := l_inventory_item_id;
1643   x_inv_master_organization_id := l_inv_master_organization_id;
1644   x_expired_flag := l_expired_flag;
1645 
1646   IF G_DEBUG = 'Y' THEN
1647         AHL_DEBUG_PUB.debug('End Validate Item Instance');
1648   END IF;
1649 
1650 END Validate_Item_Instance;
1651 
1652 -----------------------------------------------------------------------------
1653 -- To get the unit and master configurations IDs for the input item instance.
1654 
1655 PROCEDURE Get_Unit_Master_ConfigIDs (p_csi_item_instance_id IN NUMBER,
1656                                      x_uc_header_id OUT NOCOPY NUMBER,
1657                                      x_master_config_id OUT NOCOPY NUMBER)
1658 IS
1659 
1660   -- To get unit config id.
1661   CURSOR ahl_unit_config_header_csr (p_item_instance_id IN NUMBER) IS
1662     SELECT name, active_start_date, active_end_date, master_config_id, unit_config_header_id,
1663            unit_config_status_code
1664     FROM  ahl_unit_config_headers
1665     WHERE csi_item_instance_id = p_item_instance_id
1666       --AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate) AND
1667       --    trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
1668       AND parent_uc_header_id IS NULL;
1669 
1670   l_name              ahl_unit_config_headers.name%TYPE;
1671   l_active_start_date DATE;
1672   l_active_end_date   DATE;
1673   l_master_config_id  NUMBER;
1674   l_unit_config_header_id NUMBER;
1675   l_config_status_code    fnd_lookup_values_vl.lookup_code%TYPE;
1676 
1677 BEGIN
1678 
1679     IF G_DEBUG = 'Y' THEN
1680         AHL_DEBUG_PUB.debug('Start Get_Unit_Master_ConfigIDs');
1681     END IF;
1682 
1683      x_uc_header_id := null;
1684      x_master_config_id := null;
1685 
1686     IF (p_csi_item_instance_id IS NOT NULL) THEN
1687       OPEN ahl_unit_config_header_csr (p_csi_item_instance_id);
1688       FETCH ahl_unit_config_header_csr INTO l_name, l_active_start_date,
1689                                             l_active_end_date, l_master_config_id,
1690                                             l_unit_config_header_id,
1691                                             l_config_status_code;
1692       IF (ahl_unit_config_header_csr%FOUND) THEN
1693         --IF (l_config_status_code <> 'COMPLETE' AND l_config_status_code <> 'INCOMPLETE') THEN
1694         --modified for quaratine statuses.
1695         IF (l_config_status_code = 'DRAFT') THEN
1696            FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_STATUS_INVALID');
1697            FND_MESSAGE.Set_Token('NAME',l_name);
1698            FND_MSG_PUB.ADD;
1699            --dbms_output.put_line('UC is in draft status');
1700         ELSE
1701            x_uc_header_id := l_unit_config_header_id;
1702            x_master_config_id := l_master_config_id;
1703         END IF;
1704       END IF;
1705       CLOSE ahl_unit_config_header_csr;
1706     END IF;
1707 
1708     IF (G_concurrent_flag = 'Y') THEN
1709       fnd_file.put_line (FND_FILE.LOG, 'Unit Config Name:' || l_name);
1710     END IF;
1711 
1712     IF G_DEBUG = 'Y' THEN
1713         AHL_DEBUG_PUB.debug('Unit Config ID:' || x_uc_header_id);
1714         AHL_DEBUG_PUB.debug('Master Config ID:' || x_master_config_id);
1715         AHL_DEBUG_PUB.debug('End Get_Unit_Master_ConfigIDs');
1716     END IF;
1717 
1718 END Get_Unit_Master_ConfigIDs;
1719 
1720 -----------------------------------------------------------------------
1721 -- To get the root item instance for the input item instance if exists.
1722 
1723 FUNCTION Get_RootInstanceID(p_csi_item_instance_id IN NUMBER)
1724 RETURN NUMBER
1725 IS
1726 
1727   CURSOR csi_root_instance_csr (p_instance_id IN NUMBER) IS
1728     SELECT root.object_id
1729     FROM csi_ii_relationships root
1730     WHERE NOT EXISTS (SELECT 'x'
1731                       FROM csi_ii_relationships
1732                       WHERE subject_id = root.object_id
1733                         AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
1734                       )
1735     START WITH root.subject_id = p_instance_id
1736                AND root.relationship_type_code = 'COMPONENT-OF'
1737                AND trunc(nvl(root.active_start_date,sysdate)) <= trunc(sysdate)
1738                AND trunc(sysdate) < trunc(nvl(root.active_end_date, sysdate+1))
1739     CONNECT BY PRIOR root.object_id = root.subject_id
1740                      AND root.relationship_type_code = 'COMPONENT-OF'
1741                      AND trunc(nvl(root.active_start_date,sysdate)) <= trunc(sysdate)
1742                      AND trunc(sysdate) < trunc(nvl(root.active_end_date, sysdate+1));
1743 
1744   l_csi_instance_id  NUMBER;
1745 
1746 BEGIN
1747 
1748   -- get root instance given an item instance_id.
1749   OPEN csi_root_instance_csr (p_csi_item_instance_id);
1750   FETCH csi_root_instance_csr INTO l_csi_instance_id;
1751   IF (csi_root_instance_csr%NOTFOUND) THEN
1752      -- input id is root instance.
1753      l_csi_instance_id := p_csi_item_instance_id;
1754   END IF;
1755   CLOSE csi_root_instance_csr;
1756   --dbms_output.put_line ('root instance' || l_csi_instance_id);
1757 
1758   RETURN  l_csi_instance_id;
1759 
1760 END Get_RootInstanceID;
1761 
1762 -------------------------------------------------------------
1763 -- Validate the input item instance.
1764 
1765 PROCEDURE Build_Config_Tree(p_csi_root_instance_id IN         NUMBER,
1766                             p_master_config_id     IN         NUMBER,
1767                             x_config_node_tbl      OUT NOCOPY AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type)
1768 
1769 IS
1770 
1771   CURSOR csi_config_tree_csr ( p_csi_root_instance_id IN NUMBER) IS
1772     SELECT subject_id , object_id, position_reference
1773     FROM csi_ii_relationships
1774     START WITH object_id = p_csi_root_instance_id
1775                AND relationship_type_code = 'COMPONENT-OF'
1776                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
1777                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
1778     CONNECT BY PRIOR subject_id = object_id
1779                      AND relationship_type_code = 'COMPONENT-OF'
1780                      AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
1781                      AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
1782     ORDER BY level;
1783 
1784   i  NUMBER;
1785   l_config_node_tbl   AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type := x_config_node_tbl;
1786 
1787   -- added for perf fix for bug# 6893404.
1788   l_buffer_limit      number := 1000;
1789 
1790   l_subj_id_tbl       nbr_tbl_type;
1791   l_obj_id_tbl        nbr_tbl_type;
1792   l_posn_ref_tbl      vchar_tbl_type;
1793 
1794 BEGIN
1795 
1796   IF G_DEBUG = 'Y' THEN
1797         AHL_DEBUG_PUB.debug('Start Build_Config_Tree');
1798   END IF;
1799 
1800    -- For top node.
1801   l_config_node_tbl(1).csi_item_instance_id := p_csi_root_instance_id;
1802 
1803   -- For position reference.
1804   IF (p_master_config_id IS NOT NULL) THEN
1805     l_config_node_tbl(1).position_reference := to_char(p_master_config_id);
1806   END IF;
1807 
1808   i := 1;
1809 
1810   -- add child nodes.
1811   -- added for perf fix for bug# 6893404.
1812   OPEN csi_config_tree_csr(p_csi_root_instance_id);
1813   LOOP
1814     FETCH csi_config_tree_csr BULK COLLECT INTO l_subj_id_tbl, l_obj_id_tbl, l_posn_ref_tbl
1815                               LIMIT l_buffer_limit;
1816 
1817     EXIT WHEN (l_subj_id_tbl.count = 0);
1818 
1819     FOR j IN l_subj_id_tbl.FIRST..l_subj_id_tbl.LAST LOOP
1820 
1821       -- Loop through to get all components of the configuration.
1822       -- FOR node_rec IN csi_config_tree_csr(p_csi_root_instance_id) LOOP
1823       i := i + 1;
1824 
1825       --l_config_node_tbl(i).csi_item_instance_id := node_rec.subject_id;
1826       --l_config_node_tbl(i).object_id := node_rec.object_id;
1827       --l_config_node_tbl(i).position_reference := node_rec.position_reference;
1828 
1829       l_config_node_tbl(i).csi_item_instance_id := l_subj_id_tbl(j);
1830       l_config_node_tbl(i).object_id            := l_obj_id_tbl(j);
1831       l_config_node_tbl(i).position_reference   := l_posn_ref_tbl(j);
1832 
1833     END LOOP; -- l_subj_id_tbl.FIRST
1834 
1835     -- reset tables and get the next batch of nodes.
1836     l_subj_id_tbl.DELETE;
1837     l_obj_id_tbl.DELETE;
1838     l_posn_ref_tbl.DELETE;
1839 
1840   END LOOP; -- FETCH csi_config_tree_csr
1841   CLOSE csi_config_tree_csr;
1842 
1843   X_CONFIG_NODE_TBL := l_config_node_tbl;
1844 
1845   IF G_DEBUG = 'Y' THEN
1846      AHL_DEBUG_PUB.debug('End Build_Config_Tree');
1847      AHL_DEBUG_PUB.debug('Count on config' || x_config_node_tbl.COUNT);
1848   END IF;
1849 
1850 END Build_Config_Tree;
1851 
1852 -----------------------------------------------------------------------
1853 -- This function calculates the last day of the rolling window based on
1854 -- profile values.
1855 
1856 FUNCTION Get_Rolling_Window_Date RETURN DATE  IS
1857 
1858   l_date_uom            VARCHAR2(30);
1859   l_value               NUMBER;
1860   l_last_day_of_window  DATE;
1861 
1862 BEGIN
1863 
1864    BEGIN
1865      l_date_uom := FND_PROFILE.VALUE('AHL_UMP_MAX_PLANNING_UOM');
1866      l_value    := to_number(FND_PROFILE.VALUE('AHL_UMP_MAX_PLANNING_VALUE'));
1867 
1868      IF (l_date_uom IS NULL) THEN
1869         l_last_day_of_window := SYSDATE;
1870      ELSIF (l_value <= 0 OR l_value IS NULL) THEN
1871         l_last_day_of_window := SYSDATE;
1872      ELSIF (l_date_uom = 'YR') THEN
1873         l_last_day_of_window := ADD_MONTHS(SYSDATE, 12 * l_value);
1874      ELSIF (l_date_uom = 'MTH') THEN
1875         l_last_day_of_window := ADD_MONTHS(SYSDATE, l_value);
1876      ELSIF (l_date_uom = 'WK') THEN
1877         l_last_day_of_window := SYSDATE + (7 * l_value);
1878      ELSIF (l_date_uom = 'DAY') THEN
1879         l_last_day_of_window := SYSDATE + l_value;
1880      END IF;
1881 
1882      -- Add debug mesg.
1883      IF G_DEBUG = 'Y' THEN
1884        AHL_DEBUG_PUB.debug('last day of window' || l_last_day_of_window);
1885        AHL_DEBUG_PUB.debug('profile uom:' || l_date_uom);
1886        AHL_DEBUG_PUB.debug('profile value:' || l_value);
1887      END IF;
1888 
1889    EXCEPTION
1890      WHEN VALUE_ERROR THEN
1891         l_last_day_of_window := SYSDATE;
1892 
1893      WHEN INVALID_NUMBER THEN
1894         l_last_day_of_window := SYSDATE;
1895 
1896    END;
1897 
1898    -- return date.
1899    RETURN l_last_day_of_window;
1900 
1901 END Get_Rolling_Window_Date;
1902 
1903 --------------------------------------------------------------------
1904 -- Get the utilization forecast applicable to the input item instance/unit.
1905 -- For preventive maintenance, forecast definition is at either instance level
1906 -- or item level.
1907 PROCEDURE Get_Utilization_Forecast (p_csi_item_instance_id IN NUMBER,
1908                                     p_uc_header_id         IN NUMBER,
1909                                     p_inventory_item_id    IN NUMBER,
1910                                     p_inventory_org_id     IN NUMBER,
1911                                     x_forecast_details_tbl OUT NOCOPY forecast_details_tbl_type)
1912 IS
1913 
1914   CURSOR ahl_uf_headers_csr(p_uc_header_id IN NUMBER) IS
1915     SELECT uf_header_id, use_unit_flag
1916     FROM ahl_uf_headers
1917     WHERE unit_config_header_id = p_uc_header_id;
1918 
1919   CURSOR ahl_uf_details_csr(p_uf_header_id IN NUMBER) IS
1920     SELECT uom_code, start_date, end_date, usage_per_day
1921     FROM   ahl_uf_details
1922     WHERE uf_header_id = p_uf_header_id
1923     AND trunc(nvl(end_date, sysdate)) >= trunc(sysdate)
1924     order by uom_code, start_date;
1925 
1926   CURSOR ahl_pm_uf_headers_csr(p_csi_item_instance_id IN NUMBER) IS
1927     SELECT uf_header_id, use_unit_flag
1928     FROM ahl_uf_headers
1929     WHERE csi_item_instance_id = p_csi_item_instance_id;
1930 
1931   CURSOR ahl_pm_item_uf_csr (p_csi_item_instance_id  IN  NUMBER) IS
1932     SELECT uom_code, start_date, end_date, usage_per_day
1933     FROM ahl_uf_headers uh, ahl_uf_details ud, csi_item_instances csi
1934     WHERE uh.uf_header_id = ud.uf_header_id
1935     AND csi.instance_id = p_csi_item_instance_id
1936     AND csi.inventory_item_id = uh.inventory_item_id
1937     AND trunc(nvl(end_date, sysdate)) >= trunc(sysdate)
1938     order by uom_code, start_date;
1939 
1940 -- JKJain, NR Analysis and Forecasting
1941 
1942   CURSOR ahl_fleet_uf_header_csr(c_uc_header_id IN NUMBER) IS
1943     SELECT simulation_plan_id
1944     FROM   ahl_fleet_unit_assocs
1945     WHERE unit_config_header_id = c_uc_header_id
1946     AND simulation_plan_id = nvl(G_SIMULATION_PLAN_ID, get_primary_plan_id)
1947     AND trunc(nvl(association_end, sysdate)) >= trunc(sysdate);
1948 
1949   CURSOR ahl_fleet_uf_details_csr(c_uc_header_id IN NUMBER, c_simulation_plan_id In NUMBER) IS
1950     SELECT FUF.uom_code, FUF.period_start_date, FUF.period_end_date,FUA.association_start ,FUA.association_end, FUF.forecasted_daily_usage usage_per_day
1951     FROM  ahl_fleet_utlzn_forecast FUF ,ahl_fleet_unit_assocs FUA, ahl_fleet_headers_b FLT
1952     WHERE FUF.fleet_header_id = FUA.fleet_header_id
1953     AND trunc(nvl(period_end_date, sysdate)) >= trunc(sysdate)
1954     AND trunc(nvl(association_end, sysdate)) >= trunc(sysdate)
1955     AND trunc(nvl(period_end_date, association_start))  >= trunc(association_start)
1956     AND trunc(period_start_date)  <=  trunc(nvl(association_end,period_start_date)) -- Bug 13012968
1957     AND FUA.unit_config_header_id = c_uc_header_id
1958     AND FUA.simulation_plan_id = c_simulation_plan_id
1959     AND FLT.fleet_header_id = FUA.fleet_header_id
1960     AND FLT.status_code = 'COMPLETE'
1961     order by uom_code, association_start, period_start_date;
1962 
1963   -- JKJain, NR Analysis and Forecasting
1964   l_forecast_details_flt_tbl  forecast_details_tbl_type;
1965   l_forecast_details_pc_tbl   forecast_details_tbl_type;
1966   l_simulation_plan_id NUMBER;
1967   l_flt_start_date DATE;
1968   l_flt_end_date DATE;
1969   l_pc_start_date DATE;
1970   l_pc_end_date DATE;
1971   l_previous_end_date DATE := sysdate;
1972   l_pc_index NUMBER;
1973   l_flt_index NUMBER;
1974   l_flt_uom_code VARCHAR2(3);
1975   l_pc_uom_code  VARCHAR2(3);
1976 
1977   l_uf_header_id  NUMBER;
1978   l_use_unit_flag   AHL_UF_HEADERS.USE_UNIT_FLAG%TYPE;
1979   l_uf_details_tbl  AHL_UMP_UF_PVT.uf_details_tbl_type;
1980 
1981   l_index  NUMBER := 1;
1982   l_forecast_details_tbl  forecast_details_tbl_type;
1983   l_return_status   VARCHAR2(1);
1984 
1985   -- Added to fix bug# 6326056.
1986   l_duplicate_flag  VARCHAR2(1);
1987 
1988   -- Added to fix bug# 13025105
1989   l_uom_code  VARCHAR2(3);
1990 
1991 BEGIN
1992 
1993   IF G_DEBUG = 'Y' THEN
1994      AHL_DEBUG_PUB.debug('Start Get_Utilization_Forecast');
1995      AHL_DEBUG_PUB.debug ('Input csi'|| p_csi_item_instance_id);
1996      AHL_DEBUG_PUB.debug ('Input uc'|| p_uc_header_id);
1997      AHL_DEBUG_PUB.debug ('Input invID' || p_inventory_item_id);
1998      AHL_DEBUG_PUB.debug ('Input invORGID' || p_inventory_org_id);
1999   END IF;
2000 
2001   -- Check installation to get appropriate forecast.
2002   IF (G_IS_PM_INSTALLED = 'Y') THEN
2003     -- pm is installed.
2004 
2005     IF G_DEBUG = 'Y' THEN
2006        AHL_DEBUG_PUB.debug('PM forecast');
2007     END IF;
2008 
2009     -- Check if forecast available at instance level.
2010     OPEN ahl_pm_uf_headers_csr(p_csi_item_instance_id);
2011     FETCH ahl_pm_uf_headers_csr INTO l_uf_header_id, l_use_unit_flag;
2012     IF (ahl_pm_uf_headers_csr%FOUND) AND (l_use_unit_flag = 'Y') THEN
2013        --dbms_output.put_line('Found uf header and use_unit_flag' || l_uf_header_id);
2014 
2015        -- initialize.
2016        l_index := 1;
2017        FOR l_forecast_detail_rec IN ahl_uf_details_csr(l_uf_header_id) LOOP
2018            l_forecast_details_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
2019            l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_detail_rec.start_date);
2020            l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_detail_rec.end_date);
2021            l_forecast_details_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
2022             -- JKJain, NR Analysis and Forecasting
2023            l_forecast_details_tbl(l_index).utilization_type := 'PM-UNIT';
2024            l_index := l_index + 1;
2025 
2026        END LOOP;
2027     ELSE  -- use item forecast.
2028        --dbms_output.put_line ('item forecast');
2029 
2030        -- initialize.
2031        l_index := 1;
2032        FOR l_forecast_detail_rec IN ahl_pm_item_uf_csr(p_csi_item_instance_id) LOOP
2033            l_forecast_details_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
2034            l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_detail_rec.start_date);
2035            l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_detail_rec.end_date);
2036            l_forecast_details_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
2037            -- JKJain, NR Analysis and Forecasting
2038            l_forecast_details_tbl(l_index).utilization_type := 'PM-ITEM';
2039            l_index := l_index + 1;
2040 
2041        END LOOP;
2042     END IF;
2043     CLOSE ahl_pm_uf_headers_csr;
2044   ELSE -- is_pm_installed.
2045   -- forecast for AHL installation.
2046     IF G_DEBUG = 'Y' THEN
2047        AHL_DEBUG_PUB.debug('AHL Installation forecast');
2048     END IF;
2049 
2050     -- If Utlization forecast defined at unit level
2051     IF (p_uc_header_id IS NOT NULL) THEN
2052        --dbms_output.put_line ('uc header not null');
2053        -- check if forecast defined.
2054 
2055        -- JKJain, NR Analysis and Forecasting
2056        --If utilization defined at Fleet Level
2057         OPEN ahl_fleet_uf_header_csr(p_uc_header_id);
2058         FETCH ahl_fleet_uf_header_csr INTO l_simulation_plan_id;
2059             IF (ahl_fleet_uf_header_csr%FOUND) THEN --Fleet
2060             l_index := 1;
2061             FOR l_forecast_detail_rec IN ahl_fleet_uf_details_csr(p_uc_header_id,l_simulation_plan_id) LOOP
2062 
2063             IF(l_forecast_detail_rec.association_start > l_forecast_detail_rec.period_start_date) THEN
2064              l_flt_start_date := trunc(l_forecast_detail_rec.association_start);
2065             ELSE
2066               l_flt_start_date := trunc(l_forecast_detail_rec.period_start_date);
2067             END IF;
2068 
2069 
2070             IF(l_forecast_detail_rec.association_end IS NOT NULL) THEN
2071               IF(l_forecast_detail_rec.period_end_date IS NULL OR l_forecast_detail_rec.period_end_date > l_forecast_detail_rec.association_end) THEN
2072                 l_flt_end_date := trunc(l_forecast_detail_rec.association_end);
2073               ELSE
2074                 l_flt_end_date := trunc(l_forecast_detail_rec.period_end_date);
2075               END IF;
2076             ELSE
2077               l_flt_end_date := trunc(l_forecast_detail_rec.period_end_date);
2078             END IF;
2079 
2080                 l_forecast_details_flt_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
2081                 l_forecast_details_flt_tbl(l_index).start_date := l_flt_start_date;
2082                 l_forecast_details_flt_tbl(l_index).end_date   := l_flt_end_date;
2083                 l_forecast_details_flt_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
2084                 l_forecast_details_flt_tbl(l_index).utilization_type := 'FLEET';
2085                 l_index := l_index + 1;
2086 
2087 
2088             END LOOP;
2089 
2090            END IF; -- Fleet
2091         CLOSE ahl_fleet_uf_header_csr;
2092 
2093        -- JKJain, NR Analysis and Forecasting
2094 	    l_index :=1;
2095        OPEN ahl_uf_headers_csr (p_uc_header_id);
2096        FETCH ahl_uf_headers_csr INTO l_uf_header_id, l_use_unit_flag;
2097        IF (ahl_uf_headers_csr%FOUND) AND (l_use_unit_flag = 'Y') THEN
2098           FOR l_forecast_detail_rec IN ahl_uf_details_csr(l_uf_header_id) LOOP
2099             l_forecast_details_pc_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
2100             l_forecast_details_pc_tbl(l_index).start_date := trunc(l_forecast_detail_rec.start_date);
2101             l_forecast_details_pc_tbl(l_index).end_date   := trunc(l_forecast_detail_rec.end_date);
2102             l_forecast_details_pc_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
2103             -- JKJain, NR Analysis and Forecasting
2104             l_forecast_details_pc_tbl(l_index).utilization_type := 'UNIT';
2105             l_index := l_index + 1;
2106 
2107           END LOOP;
2108        ELSE /* forecast not defined at UC */
2109           --dbms_output.put_line ('use_unit_flag not Y');
2110           IF G_DEBUG = 'Y' THEN
2111              AHL_DEBUG_PUB.debug('AHL PC forecast for UNIT');
2112           END IF;
2113 
2114           -- added parameter p_add_unit_item_forecast to fix bug# 6749351.
2115           AHL_UMP_UF_PVT.Get_UF_FROM_PC (p_unit_config_header_id => p_uc_header_id,
2116                                          p_add_unit_item_forecast => 'Y',
2117                                          p_onward_end_date => trunc(sysdate),
2118                                          x_uf_details_tbl => l_uf_details_tbl,
2119                                          x_return_status => l_return_status);
2120           /* This will give forecast defined item/pc_node level. */
2121 
2122           IF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
2123             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2124           ELSIF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
2125             RAISE FND_API.G_EXC_ERROR;
2126           END IF;
2127 
2128           -- populate l_forecast_details_tbl based on l_uf_details_tbl.
2129           IF (l_uf_details_tbl.COUNT) > 0 THEN
2130             l_index := 1;
2131 
2132             FOR i IN l_uf_details_tbl.FIRST..l_uf_details_tbl.LAST LOOP
2133               l_forecast_details_pc_tbl(l_index).uom_code := l_uf_details_tbl(i).uom_code;
2134               l_forecast_details_pc_tbl(l_index).start_date := trunc(l_uf_details_tbl(i).start_date);
2135               l_forecast_details_pc_tbl(l_index).end_date   := trunc(l_uf_details_tbl(i).end_date);
2136               l_forecast_details_pc_tbl(l_index).usage_per_day := l_uf_details_tbl(i).usage_per_day;
2137 			   -- JKJain, NR Analysis and Forecasting
2138               l_forecast_details_pc_tbl(l_index).utilization_type := 'PC';
2139               l_index := l_index + 1;
2140 
2141             END LOOP;
2142 
2143           END IF; /* count > 0 */
2144 
2145        END IF; -- %found.
2146        CLOSE ahl_uf_headers_csr;
2147     ELSE
2148        IF G_DEBUG = 'Y' THEN
2149           AHL_DEBUG_PUB.debug('AHL PC forecast for ITEM');
2150        END IF;
2151        --dbms_output.put_line ('inv case');
2152 
2153        /* following taken care by get_uf_from_pc as part fix for bug# 6749351.
2154        -- first get forecast at item level (fix for bug# 6002569).
2155        -- initialize.
2156        l_index := 1;
2157        FOR l_forecast_detail_rec IN ahl_pm_item_uf_csr(p_csi_item_instance_id)
2158        LOOP
2159            l_forecast_details_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
2160            l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_detail_rec.start_date);
2161            l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_detail_rec.end_date);
2162            l_forecast_details_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
2163 
2164            l_index := l_index + 1;
2165 
2166        END LOOP;
2167        */
2168        /* Next, get forecast defined at instance's item/pc node level. */
2169        -- set parameter to get forecast at item level as well.
2170        AHL_UMP_UF_PVT.Get_UF_FROM_PC (p_inventory_item_id => p_inventory_item_id,
2171                                       p_inventory_org_id => p_inventory_org_id,
2172                                       p_add_unit_item_forecast => 'Y',
2173                                       p_onward_end_date => trunc(sysdate),
2174                                       x_uf_details_tbl => l_uf_details_tbl,
2175                                       x_return_status => l_return_status);
2176 
2177        IF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
2178           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2179        ELSIF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
2180           RAISE FND_API.G_EXC_ERROR;
2181        END IF;
2182 
2183        -- Bug# 6749351:Removed duplicate check which is now taken care by get_uf_from_pc.
2184        IF (l_uf_details_tbl.count > 0) THEN
2185            l_index := 1;
2186 
2187            FOR i IN l_uf_details_tbl.FIRST..l_uf_details_tbl.LAST LOOP
2188 
2189               l_forecast_details_pc_tbl(l_index).uom_code := l_uf_details_tbl(i).uom_code;
2190               l_forecast_details_pc_tbl(l_index).start_date := trunc(l_uf_details_tbl(i).start_date);
2191               l_forecast_details_pc_tbl(l_index).end_date   := trunc(l_uf_details_tbl(i).end_date);
2192               l_forecast_details_pc_tbl(l_index).usage_per_day := l_uf_details_tbl(i).usage_per_day;
2193 			   -- JKJain, NR Analysis and Forecasting
2194               l_forecast_details_pc_tbl(l_index).utilization_type := 'ITEM';
2195               l_index := l_index + 1;
2196 
2197            END LOOP; -- l_uf_details_tbl
2198        END IF; -- l_uf_details_tbl.count
2199 
2200     END IF; -- p_uc_header_id is not null.
2201 
2202 -- JKJain, NR Analysis and Forecasting : Merging Fllet and PC forecasts.
2203     IF (G_DEBUG = 'Y') THEN
2204              AHL_DEBUG_PUB.debug('l_forecast_details_flt_tbl.COUNT '|| l_forecast_details_flt_tbl.COUNT);
2205 			 AHL_DEBUG_PUB.debug('l_forecast_details_pc_tbl.COUNT ' || l_forecast_details_pc_tbl.COUNT);
2206     END IF;
2207 
2208     IF (l_forecast_details_flt_tbl.COUNT > 0) THEN
2209       l_index := 1;
2210       l_pc_index :=1;
2211       l_flt_index :=1;
2212 
2213       LOOP
2214 
2215             IF ( l_forecast_details_flt_tbl.EXISTS(l_flt_index)) THEN
2216              l_flt_uom_code := l_forecast_details_flt_tbl(l_flt_index).uom_code ;
2217             ELSE
2218              l_flt_uom_code := 'zzz';
2219             END IF;
2220 
2221 
2222             IF (l_forecast_details_pc_tbl.EXISTS(l_pc_index) ) THEN
2223              l_pc_uom_code := l_forecast_details_pc_tbl(l_pc_index).uom_code ;
2224             ELSE
2225              l_pc_uom_code := 'zzz';
2226             END IF;
2227 
2228             IF (G_DEBUG = 'Y') THEN
2229              AHL_DEBUG_PUB.debug('l_flt_uom_code =  '|| l_flt_uom_code || ' and l_pc_uom_code = ' || l_pc_uom_code);
2230             END IF;
2231 
2232             EXIT WHEN (l_pc_uom_code = 'zzz' AND l_flt_uom_code = 'zzz');
2233                 -- Add pc_uom if it is less than flt_uom
2234                 IF(l_flt_uom_code > l_pc_uom_code)THEN
2235                     LOOP -- If same UOM has multiple records with different usage
2236 
2237                      l_forecast_details_tbl(l_index).uom_code := l_pc_uom_code;
2238                      l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_details_pc_tbl(l_pc_index).start_date);
2239                      l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_details_pc_tbl(l_pc_index).end_date);
2240                      l_forecast_details_tbl(l_index).usage_per_day := l_forecast_details_pc_tbl(l_pc_index).usage_per_day;
2241                      l_forecast_details_tbl(l_index).utilization_type := l_forecast_details_pc_tbl(l_pc_index).utilization_type;
2242                      l_index := l_index + 1;
2243                      l_pc_index := l_pc_index + 1;
2244 
2245                      IF ( l_forecast_details_pc_tbl.EXISTS(l_pc_index)) THEN
2246                        EXIT WHEN (l_pc_uom_code <> l_forecast_details_pc_tbl(l_pc_index).uom_code );
2247                      ELSE
2248                        EXIT;
2249                      END IF;
2250                     END LOOP;
2251                 -- Add flt_uom if it is less than pc_uom
2252                 ELSIF (l_flt_uom_code < l_pc_uom_code) THEN
2253                     LOOP -- If same UOM has multiple records with different usage
2254 
2255                      l_forecast_details_tbl(l_index).uom_code := l_flt_uom_code ;
2256                      l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_details_flt_tbl(l_flt_index).start_date);
2257                      l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_details_flt_tbl(l_flt_index).end_date);
2258                      l_forecast_details_tbl(l_index).usage_per_day := l_forecast_details_flt_tbl(l_flt_index).usage_per_day;
2259                      l_forecast_details_tbl(l_index).utilization_type := l_forecast_details_flt_tbl(l_flt_index).utilization_type;
2260                      l_index := l_index + 1;
2261                      l_flt_index := l_flt_index+1;
2262 
2263                      IF ( l_forecast_details_flt_tbl.EXISTS(l_flt_index)) THEN
2264                        EXIT WHEN (l_flt_uom_code <> l_forecast_details_flt_tbl(l_flt_index).uom_code );
2265                      ELSE
2266                        EXIT;
2267                      END IF;
2268                     END LOOP;
2269 
2270                 ELSE -- l_flt_uom_code = l_pc_uom_code
2271 
2272                     --Initialize previous end date as a day before today for start of a UOM.
2273                     l_previous_end_date := trunc(sysdate-1);
2274 
2275                     LOOP -- If same UOM has multiple records with different usage
2276                         l_flt_start_date := trunc(l_forecast_details_flt_tbl(l_flt_index).start_date);
2277                         l_flt_end_date   := trunc(l_forecast_details_flt_tbl(l_flt_index).end_date);
2278                         l_pc_start_date  := trunc(l_forecast_details_pc_tbl(l_pc_index).start_date);
2279                         l_pc_end_date    := trunc(l_forecast_details_pc_tbl(l_pc_index).end_date);
2280                         --Find GAP. New start date should be old_end_date+1
2281                         IF(l_flt_start_date > l_previous_end_date+1 AND l_flt_start_date > l_pc_start_date)THEN
2282                             --In case of GAP, consider pc utilization
2283                             -- IF pc_uom end date is null or more than l_previous_end_date
2284                             IF (nvl(l_pc_end_date,l_previous_end_date+1) > l_previous_end_date ) THEN
2285                                 l_forecast_details_tbl(l_index).uom_code := l_pc_uom_code;
2286                                 l_forecast_details_tbl(l_index).start_date := GREATEST(l_previous_end_date+1,l_pc_start_date);
2287                                 l_forecast_details_tbl(l_index).end_date   := LEAST(l_flt_start_date-1,nvl(l_pc_end_date,l_flt_start_date-1));
2288                                 l_forecast_details_tbl(l_index).usage_per_day := l_forecast_details_pc_tbl(l_pc_index).usage_per_day;
2289                                 l_forecast_details_tbl(l_index).utilization_type := l_forecast_details_pc_tbl(l_pc_index).utilization_type;
2290 
2291                                 l_previous_end_date := l_forecast_details_tbl(l_index).end_date;
2292                                 l_index := l_index + 1;
2293 
2294                             ELSE -- IF pc_uom end date is not null and less than l_previous_end_date
2295                                 IF(l_forecast_details_pc_tbl.EXISTS(l_pc_index+1)) THEN
2296                                     IF(l_pc_uom_code = l_forecast_details_pc_tbl(l_pc_index+1).uom_code )THEN -- same UOM
2297                                     l_pc_index := l_pc_index+1;
2298                                     ELSE
2299                                         l_forecast_details_tbl(l_index).uom_code := l_flt_uom_code;
2300                                         l_forecast_details_tbl(l_index).start_date := l_flt_start_date;
2301                                         l_forecast_details_tbl(l_index).end_date   := l_flt_end_date;
2302                                         l_forecast_details_tbl(l_index).usage_per_day := l_forecast_details_flt_tbl(l_flt_index).usage_per_day;
2303                                         l_forecast_details_tbl(l_index).utilization_type := l_forecast_details_flt_tbl(l_flt_index).utilization_type;
2304 
2305                                         l_previous_end_date := l_flt_end_date;
2306                                         l_index := l_index + 1;
2307                                         l_flt_index := l_flt_index+1;
2308                                     END IF;
2309                                 ELSE --pc table last record reached
2310                                     l_forecast_details_tbl(l_index).uom_code := l_flt_uom_code;
2311                                     l_forecast_details_tbl(l_index).start_date := l_flt_start_date;
2312                                     l_forecast_details_tbl(l_index).end_date   := l_flt_end_date;
2313                                     l_forecast_details_tbl(l_index).usage_per_day := l_forecast_details_flt_tbl(l_flt_index).usage_per_day;
2314                                     l_forecast_details_tbl(l_index).utilization_type := l_forecast_details_flt_tbl(l_flt_index).utilization_type;
2315 
2316                                     l_previous_end_date := l_flt_end_date;
2317                                     l_index := l_index + 1;
2318                                     l_flt_index := l_flt_index+1;
2319                                 END IF;
2320 
2321                             END IF;
2322 
2323                         ELSE --l_flt_start_date <= l_previous_end_date+1
2324 
2325                             l_forecast_details_tbl(l_index).uom_code := l_flt_uom_code;
2326                             l_forecast_details_tbl(l_index).start_date := l_flt_start_date;
2327                             l_forecast_details_tbl(l_index).end_date   := l_flt_end_date;
2328                             l_forecast_details_tbl(l_index).usage_per_day := l_forecast_details_flt_tbl(l_flt_index).usage_per_day;
2329                             l_forecast_details_tbl(l_index).utilization_type := l_forecast_details_flt_tbl(l_flt_index).utilization_type;
2330 
2331                             l_previous_end_date := l_flt_end_date;
2332                             l_index := l_index + 1;
2333                             l_flt_index := l_flt_index+1;
2334 
2335                         END IF; --l_flt_start_date > l_previous_end_date+1
2336 
2337                         IF ( l_forecast_details_flt_tbl.EXISTS(l_flt_index)) THEN
2338                             EXIT WHEN (l_flt_uom_code <> l_forecast_details_flt_tbl(l_flt_index).uom_code );
2339                         ELSE
2340                             EXIT;
2341                          END IF;
2342                     END LOOP;
2343 
2344                     --IF pc forecast exists after fleet forecast for the same UOM
2345                     IF(l_previous_end_date IS NOT NULL) THEN
2346                         LOOP
2347                             IF (x_forecast_details_tbl.COUNT > 0) THEN
2348                                  AHL_DEBUG_PUB.debug('l_previous_end_date =  '|| l_previous_end_date|| ' and l_pc_uom_code = '||l_pc_uom_code);
2349                             END IF;
2350                             IF ( l_forecast_details_pc_tbl.EXISTS(l_pc_index)) THEN
2351                                 EXIT WHEN (l_pc_uom_code <> l_forecast_details_pc_tbl(l_pc_index).uom_code );
2352                             ELSE
2353                                 EXIT;
2354                             END IF;
2355 
2356                             l_pc_start_date  := trunc(l_forecast_details_pc_tbl(l_pc_index).start_date);
2357                             l_pc_end_date    := trunc(l_forecast_details_pc_tbl(l_pc_index).end_date);
2358                             IF(trunc(nvl(l_pc_end_date,l_previous_end_date)) >= l_previous_end_date) THEN
2359                                 l_forecast_details_tbl(l_index).uom_code := l_pc_uom_code;
2360                                 l_forecast_details_tbl(l_index).start_date := GREATEST(l_previous_end_date+1,l_pc_start_date);
2361                                 l_forecast_details_tbl(l_index).end_date   := l_pc_end_date;
2362                                 l_forecast_details_tbl(l_index).usage_per_day := l_forecast_details_pc_tbl(l_pc_index).usage_per_day;
2363                                 l_forecast_details_tbl(l_index).utilization_type := l_forecast_details_pc_tbl(l_pc_index).utilization_type;
2364 
2365                                 l_previous_end_date := l_forecast_details_tbl(l_index).end_date;
2366                                 l_index := l_index + 1;
2367                             END IF;
2368                             l_pc_index := l_pc_index + 1;
2369 
2370                          END LOOP;
2371                     ELSE -- Iterate through pc forecast table till next UOM.
2372                         LOOP
2373                             IF ( l_forecast_details_pc_tbl.EXISTS(l_pc_index)) THEN
2374                                 EXIT WHEN (l_pc_uom_code <> l_forecast_details_pc_tbl(l_pc_index).uom_code );
2375                             ELSE
2376                                 EXIT;
2377                             END IF;
2378                             l_pc_index := l_pc_index + 1;
2379                         END LOOP;
2380                     END IF;
2381 
2382 
2383                 END IF; --l_flt_uom_code > l_pc_uom_code
2384 
2385         END LOOP; -- Loop
2386 
2387     ELSE
2388         l_forecast_details_tbl := l_forecast_details_pc_tbl;
2389     END IF;    --l_forecast_details_flt_tbl.COUNT >0
2390 
2391 
2392 
2393   END IF; -- end pm installed check.
2394 
2395   -- fix for bug# 13025105: Insert 0 usage row from sysdate to start_date - 1 if forecast is missing for sysdate.
2396   l_uom_code := null;
2397   l_index := 1;
2398   -- iterate through the forecast table and insert rows with 0 usage
2399   IF (l_forecast_details_tbl.count > 0) THEN
2400     FOR i IN l_forecast_details_tbl.FIRST..l_forecast_details_tbl.LAST LOOP
2401       -- when UOM changes, check if start date > sysdate
2402       IF (l_uom_code IS NULL) OR (l_uom_code <> l_forecast_details_tbl(i).uom_code) THEN
2403         IF (l_forecast_details_tbl(i).start_date > trunc(sysdate)) THEN
2404             x_forecast_details_tbl(l_index).uom_code := l_forecast_details_tbl(i).uom_code;
2405             x_forecast_details_tbl(l_index).start_date := trunc(sysdate - 1);
2406             x_forecast_details_tbl(l_index).end_date := trunc(l_forecast_details_tbl(i).start_date - 1);
2407             x_forecast_details_tbl(l_index).usage_per_day  := 0;
2408             x_forecast_details_tbl(l_index).utilization_type := 'ZR-USAGE';
2409             l_index := l_index + 1;
2410             l_uom_code := l_forecast_details_tbl(i).uom_code;
2411         END IF;
2412       ELSE -- uom has not changed
2413         -- if there is a gap in the forecast, insert rows for 0 usage for this period.
2414         IF (l_index > 1) AND (x_forecast_details_tbl(l_index-1).end_date + 1 <> l_forecast_details_tbl(i).start_date) THEN
2415            -- insert 0 usage row
2416            x_forecast_details_tbl(l_index).uom_code := l_forecast_details_tbl(i).uom_code;
2417            x_forecast_details_tbl(l_index).start_date := trunc(x_forecast_details_tbl(l_index-1).end_date + 1);
2418            x_forecast_details_tbl(l_index).end_date := trunc(l_forecast_details_tbl(i).start_date - 1);
2419            x_forecast_details_tbl(l_index).usage_per_day  := 0;
2420            x_forecast_details_tbl(l_index).utilization_type := 'ZR-USAGE';
2421            l_index := l_index + 1;
2422         END IF;
2423       END IF;
2424       x_forecast_details_tbl(l_index).uom_code := l_forecast_details_tbl(i).uom_code;
2425       x_forecast_details_tbl(l_index).start_date := l_forecast_details_tbl(i).start_date;
2426       x_forecast_details_tbl(l_index).end_date := l_forecast_details_tbl(i).end_date;
2427       x_forecast_details_tbl(l_index).usage_per_day  := l_forecast_details_tbl(i).usage_per_day;
2428       x_forecast_details_tbl(l_index).utilization_type := l_forecast_details_tbl(i).utilization_type;
2429       l_index := l_index + 1;
2430     END LOOP;
2431   END IF;
2432 
2433   -- Set output variable for forecast.
2434   -- x_forecast_details_tbl := l_forecast_details_tbl;
2435 
2436   IF G_DEBUG = 'Y' THEN
2437      AHL_DEBUG_PUB.debug ('Count on forecast_details' || x_forecast_details_tbl.COUNT);
2438      AHL_DEBUG_PUB.debug ('Count on l_forecast_details' || l_forecast_details_tbl.COUNT);
2439 
2440      IF (x_forecast_details_tbl.COUNT > 0) THEN
2441        FOR i IN x_forecast_details_tbl.FIRST..x_forecast_details_tbl.LAST LOOP
2442              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Uom_Code' || x_forecast_details_tbl(i).uom_code);
2443              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Start Date' || x_forecast_details_tbl(i).start_date);
2444              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') End Date' || x_forecast_details_tbl(i).end_date);
2445              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Usage' || x_forecast_details_tbl(i).usage_per_day);
2446              -- JKJain, NR Analysis and Forecasting
2447              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') utilization_type ' || x_forecast_details_tbl(i).utilization_type);
2448        END LOOP;
2449      END IF;
2450 
2451      AHL_DEBUG_PUB.debug ('End Get_Utilization_Forecast');
2452 
2453   END IF;
2454 
2455 END Get_Utilization_Forecast;
2456 
2457 -----------------------------------------
2458 -- Lock all existing unit effectivity records.
2459 -- Modified for perf. bug# 6893404.
2460 PROCEDURE Lock_UnitEffectivity_Records(x_ret_code  OUT NOCOPY VARCHAR2) IS
2461 
2462   /*
2463   CURSOR ahl_unit_effectivities_csr (p_csi_item_instance_id IN NUMBER) IS
2464     SELECT UNIT_EFFECTIVITY_ID
2465     FROM AHL_UNIT_EFFECTIVITIES_APP_V
2466     WHERE csi_item_instance_id = p_csi_item_instance_id
2467     AND (status_code IS NULL OR status_code = 'INIT-DUE')
2468     FOR UPDATE OF object_version_number NOWAIT;
2469   */
2470 
2471   /* 13 Jul 08: Modified query for performance. Instead of looping for every
2472    * instance, we loop for the configuration.
2473   -- 13 Jul 08: Modified query to use status_code instead of object_version_number
2474   CURSOR ahl_unit_effectivities_csr (p_csi_item_instance_id IN NUMBER) IS
2475     --SELECT UNIT_EFFECTIVITY_ID
2476     SELECT 1
2477     FROM AHL_UNIT_EFFECTIVITIES_APP_V
2478     WHERE csi_item_instance_id = p_csi_item_instance_id
2479     AND (status_code IS NULL OR status_code IN ('INIT-DUE','EXCEPTION'))
2480     FOR UPDATE OF status_code NOWAIT;
2481   */
2482 
2483   CURSOR ahl_unit_effectivities_csr (p_csi_item_instance_id IN NUMBER, p_appln_usg_code IN VARCHAR2) IS
2484     WITH II AS (SELECT p_csi_item_instance_id instance_id
2485                 FROM DUAL
2486                 UNION ALL
2487                 SELECT A.SUBJECT_ID INSTANCE_ID
2488                 FROM CSI_II_RELATIONSHIPS A
2489                 START WITH OBJECT_ID = p_csi_item_instance_id
2490                   AND RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF'
2491                   AND SYSDATE BETWEEN TRUNC(NVL(ACTIVE_START_DATE,SYSDATE))
2492                   AND TRUNC(NVL(ACTIVE_END_DATE, SYSDATE+1))
2493                 CONNECT BY OBJECT_ID = PRIOR SUBJECT_ID
2494                   AND RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF'
2495                   AND SYSDATE BETWEEN TRUNC(NVL(ACTIVE_START_DATE,SYSDATE))
2496                   AND TRUNC(NVL(ACTIVE_END_DATE, SYSDATE+1))
2497                )
2498     SELECT 1
2499     --FROM AHL_UNIT_EFFECTIVITIES_APP_V UE, II
2500     FROM AHL_UNIT_EFFECTIVITIES_B UE, II
2501     WHERE UE.csi_item_instance_id = II.INSTANCE_ID
2502     AND UE.application_usg_code = p_appln_usg_code
2503     AND (status_code IS NULL OR status_code IN ('INIT-DUE','EXCEPTION'))
2504     FOR UPDATE OF status_code NOWAIT;
2505 
2506     -- JKJain, NR Analysis and Forecasting
2507     CURSOR ahl_sim_ues_csr (p_csi_item_instance_id IN NUMBER) IS
2508     WITH II AS (SELECT p_csi_item_instance_id instance_id
2509                 FROM DUAL
2510                 UNION ALL
2511                 SELECT A.SUBJECT_ID INSTANCE_ID
2512                 FROM CSI_II_RELATIONSHIPS A
2513                 START WITH OBJECT_ID = p_csi_item_instance_id
2514                   AND RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF'
2515                   AND SYSDATE BETWEEN TRUNC(NVL(ACTIVE_START_DATE,SYSDATE))
2516                   AND TRUNC(NVL(ACTIVE_END_DATE, SYSDATE+1))
2517                 CONNECT BY OBJECT_ID = PRIOR SUBJECT_ID
2518                   AND RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF'
2519                   AND SYSDATE BETWEEN TRUNC(NVL(ACTIVE_START_DATE,SYSDATE))
2520                   AND TRUNC(NVL(ACTIVE_END_DATE, SYSDATE+1))
2521                )
2522     SELECT 1
2523     FROM AHL_UE_SIMULATIONS UE, II
2524     WHERE UE.csi_item_instance_id = II.INSTANCE_ID
2525     AND (status_code IS NULL OR status_code IN ('INIT-DUE','EXCEPTION'))
2526     AND UE.SIMULATION_PLAN_ID = G_SIMULATION_PLAN_ID
2527     FOR UPDATE OF status_code NOWAIT;
2528 
2529   --l_next_rec_flag  BOOLEAN;
2530   --l_unit_effectivity_id NUMBER;
2531 
2532   l_ue_id_tbl      nbr_tbl_type;
2533 
2534 BEGIN
2535 
2536   IF G_DEBUG = 'Y' THEN
2537      AHL_DEBUG_PUB.debug ('Start Lock Effectivity records');
2538   END IF;
2539 
2540   x_ret_code := '0';
2541 
2542   /*
2543   -- Lock all records for all item instances in G_config_node_tbl.
2544   IF G_config_node_tbl.COUNT > 0 THEN
2545      FOR i IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
2546         OPEN ahl_unit_effectivities_csr(G_config_node_tbl(i).csi_item_instance_id);
2547         IF ahl_unit_effectivities_csr%NOTFOUND THEN
2548           --dbms_output.put_line (' in lock effecti - no record found');
2549           CLOSE ahl_unit_effectivities_csr;
2550           EXIT;
2551         END IF;
2552         l_next_rec_flag := TRUE;  -- there is at least one record
2553         WHILE (l_next_rec_flag) LOOP
2554            FETCH ahl_unit_effectivities_csr INTO l_unit_effectivity_id;
2555            IF ahl_unit_effectivities_csr%NOTFOUND THEN
2556               l_next_rec_flag := FALSE;
2557            END IF;
2558         END LOOP;
2559         CLOSE ahl_unit_effectivities_csr;
2560      END LOOP;
2561   END IF;
2562   */
2563 
2564   /* 13 Jul 08: Modified query for performance. Instead of looping for every
2565    * instance, we loop for the configuration.
2566   -- Lock all records for all item instances in G_config_node_tbl.
2567   IF G_config_node_tbl.COUNT > 0 THEN
2568     FOR i IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
2569        OPEN ahl_unit_effectivities_csr(G_config_node_tbl(i).csi_item_instance_id);
2570        LOOP
2571          FETCH ahl_unit_effectivities_csr BULK COLLECT INTO l_ue_id_tbl LIMIT 5000;
2572          IF G_DEBUG = 'Y' THEN
2573            AHL_DEBUG_PUB.debug ('Rows processed for instance: ' || G_config_node_tbl(i).csi_item_instance_id
2574                                   || 'is: ' || ahl_unit_effectivities_csr%ROWCOUNT);
2575          END IF;
2576          --EXIT WHEN ahl_unit_effectivities_csr%NOTFOUND;
2577          EXIT WHEN (l_ue_id_tbl.count = 0);
2578 
2579          -- delete tbl
2580          l_ue_id_tbl.delete;
2581 
2582        END LOOP;
2583        CLOSE ahl_unit_effectivities_csr;
2584     END LOOP;
2585   END IF;
2586   */
2587 
2588   IF (G_config_node_tbl.COUNT <= 0) THEN
2589     -- this should never happen.
2590     RETURN;
2591   END IF;
2592 
2593   -- JKJain, NR Analysis and Forecasting
2594   IF (G_PRIMARY_PLAN = 'Y') THEN
2595     -- G_config_node_tbl(1).csi_item_instance_id contains root node.
2596     -- Lock all records for all item instances in G_config_node_tbl.
2597     OPEN ahl_unit_effectivities_csr(G_config_node_tbl(1).csi_item_instance_id, G_application_usg_code);
2598     LOOP
2599        FETCH ahl_unit_effectivities_csr BULK COLLECT INTO l_ue_id_tbl LIMIT 5000;
2600        IF G_DEBUG = 'Y' THEN
2601          AHL_DEBUG_PUB.debug ('Rows processed are: ' || ahl_unit_effectivities_csr%ROWCOUNT);
2602        END IF;
2603        --EXIT WHEN ahl_unit_effectivities_csr%NOTFOUND;
2604        EXIT WHEN (l_ue_id_tbl.count = 0);
2605 
2606        -- delete tbl
2607        l_ue_id_tbl.delete;
2608     END LOOP;
2609 
2610     CLOSE ahl_unit_effectivities_csr;
2611   ELSE
2612     OPEN ahl_sim_ues_csr(G_config_node_tbl(1).csi_item_instance_id);
2613         LOOP
2614             FETCH ahl_sim_ues_csr BULK COLLECT INTO l_ue_id_tbl LIMIT 5000;
2615             IF G_DEBUG = 'Y' THEN
2616               AHL_DEBUG_PUB.debug ('Rows processed are: ' || ahl_sim_ues_csr%ROWCOUNT);
2617             END IF;
2618             EXIT WHEN (l_ue_id_tbl.count = 0);
2619 
2620             -- delete tbl
2621             l_ue_id_tbl.delete;
2622         END LOOP;
2623     CLOSE ahl_sim_ues_csr;
2624   END IF;
2625 
2626 
2627 
2628   IF G_DEBUG = 'Y' THEN
2629      AHL_DEBUG_PUB.debug ('End Lock Effectivity records');
2630   END IF;
2631 
2632 EXCEPTION
2633 
2634 WHEN OTHERS THEN
2635   IF (SQLCODE = -54) THEN
2636      --FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_ALREADY_RUNNING');
2637      --FND_MSG_PUB.ADD;
2638      --RAISE  FND_API.G_EXC_ERROR;
2639      x_ret_code := '-54';
2640   ELSE
2641     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
2642        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
2643                                p_procedure_name => 'Lock_UnitEffectivity_Records',
2644                                p_error_text     => SUBSTR(SQLERRM,1,240));
2645     END IF;
2646     RAISE  FND_API.G_EXC_UNEXPECTED_ERROR;
2647   END IF;
2648 
2649 END Lock_UnitEffectivity_Records;
2650 
2651 --------------------------------------------------------------------------------
2652 -- Process Unit for ASO installation.
2653 PROCEDURE Process_ASO_Unit IS
2654 
2655   CURSOR ahl_applicable_MRs (p_csi_item_instance_id IN NUMBER) IS
2656     SELECT DISTINCT appl.csi_item_instance_id,
2657                     appl.MR_header_id,
2658                     mr.Title,
2659                     mr.version_number,
2660                     appl.Implement_status_code,
2661                     appl.copy_accomplishment_code,
2662                     appl.repetitive_flag,
2663                     appl.show_repetitive_code,
2664                     appl.preceding_mr_header_id,
2665                     appl.descendent_count,
2666                     mr.whichever_first_code,
2667                     mr.effective_to,
2668                     mr.effective_from,
2669                     appl.processing_order, -- needed for 'order by' to work. This will be the same for all Eff.
2670                     appl.terminate_trigger_check,
2671                     appl.accomplish_trigger_type,
2672                     appl.loop_chain_seq_num
2673     FROM ahl_applicable_MRs appl, ahl_mr_headers_b mr
2674     WHERE appl.csi_item_instance_id = p_csi_item_instance_id
2675        AND (appl.implement_status_code <> 'OPTIONAL_DO_NOT_IMPLEMENT')
2676        -- check on preceding_mr_header_id is commented out as part of SB Enh
2677        --AND appl.preceding_mr_header_id IS NULL
2678        AND appl.mr_header_id = mr.mr_header_id
2679        AND trunc(nvl(mr.effective_from,sysdate)) <= trunc(sysdate)
2680        -- commented to support expired MRs for bug# 9263774
2681        --AND trunc(sysdate) <= trunc(nvl(mr.effective_to,sysdate+1))
2682        -- added check for accomplish_trigger_type and start_mr_header_id for SB Enh
2683        AND nvl(appl.accomplish_trigger_type,'X') <> 'INITIATED_BY'
2684        -- SB ENh: only process start MR for loops and chains
2685        AND nvl(appl.start_mr_header_id,appl.MR_header_id) = appl.MR_header_id
2686     ORDER BY processing_order ASC, descendent_count DESC;
2687 
2688   l_applicable_mr_rec applicable_mrs_rec_type;
2689 
2690   l_current_usage_tbl    counter_values_tbl_type;
2691   /* contains current counter usage */
2692 
2693   l_counter_rules_tbl    counter_rules_tbl_type;
2694   /* contains current counter rules for the position */
2695 
2696 BEGIN
2697 
2698   -- added to fix bug# 9266774
2699   -- Build MR applicability for expired MRs.
2700   Process_Appl_Expired_MRs;
2701 
2702   -- Added for SB Enh: Set applicable MRs order to process terminating MRs.
2703   -- default value of processing_order = 1
2704   -- select MRs that are terminating other MRs but themselves are not 'initiated_by' MRs.
2705   -- group MRs cannot be in a 'TERMINATES' relationship.
2706   UPDATE AHL_APPLICABLE_MRS appl
2707   SET processing_order = 2,
2708       terminate_trigger_check = 'Y'
2709   WHERE EXISTS (SELECT 'x'
2710                 FROM AHL_MR_RELATIONSHIPS mrr, ahl_applicable_mrs parent_appl
2711                 WHERE mrr.related_mr_header_id = appl.mr_header_id
2712                   AND mrr.mr_header_id = parent_appl.mr_header_id -- parent row exists
2713                   AND parent_appl.csi_item_instance_id = appl.csi_item_instance_id
2714                   AND mrr.relationship_code = 'TERMINATES');
2715 
2716   -- Process Unit beginning with top node.
2717   IF G_config_node_tbl.COUNT > 0 THEN
2718     FOR i IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
2719        IF G_DEBUG = 'Y' THEN
2720           AHL_DEBUG_PUB.debug('Processing for..:' || G_config_node_tbl(i).csi_item_instance_id );
2721        END IF;
2722 
2723        -- Build counter rules ratio if node is not root node.
2724        IF (G_master_config_id IS NOT NULL AND G_config_node_tbl(i).object_id IS NOT NULL) THEN
2725            build_Counter_Ratio(G_config_node_tbl(i).position_reference,
2726                                G_config_node_tbl(i).csi_item_instance_id,
2727                                G_master_config_id,
2728                                l_counter_rules_tbl);
2729        END IF;
2730 
2731        -- Get current usage for all the counters defined for the item instance.
2732        get_Current_Usage (G_config_node_tbl(i).csi_item_instance_id,
2733                           l_current_usage_tbl);
2734 
2735        -- Add zero forecast row to G_forecast_details_tbl if forecast missing for a UOM.
2736        validate_uf_for_ctr(p_current_usage_tbl => l_current_usage_tbl,
2737                            p_x_forecast_details_tbl => G_forecast_details_tbl);
2738 
2739        -- Calculate due dates for all deferred MRs.
2740        Process_Deferred_UE (p_csi_item_instance_id => G_config_node_tbl(i).csi_item_instance_id,
2741                             p_current_usage_tbl    => l_current_usage_tbl,
2742                             p_counter_rules_tbl    => l_counter_rules_tbl);
2743 
2744        -- For UE's of type SR, re-validate MR applicability and explode group MR for next due
2745        -- date calculation.
2746        Process_SR_UE (p_csi_item_instance_id => G_config_node_tbl(i).csi_item_instance_id);
2747 
2748        -- JKJain, Bypass Process_Unplanned_UE for simulation plan
2749        IF (G_PRIMARY_PLAN = 'Y') THEN
2750          -- For Unplanned MRs (MRs directly planned into a Visit from FMP), validate applicability.
2751          Process_Unplanned_UE(p_csi_item_instance_id => G_config_node_tbl(i).csi_item_instance_id,
2752                               p_current_usage_tbl    => l_current_usage_tbl,
2753                               p_counter_rules_tbl    => l_counter_rules_tbl);
2754        END IF;
2755 
2756        -- Read ahl_applicable_mrs for all MRs applicable to the item instance.
2757        FOR l_appl_rec IN ahl_applicable_MRs(G_config_node_tbl(i).csi_item_instance_id) LOOP
2758 
2759          IF G_DEBUG = 'Y' THEN
2760             AHL_DEBUG_PUB.debug('Found applicable MR-ID[Title]:' || l_appl_rec.mr_header_id || '[' || l_appl_rec.title || ']');
2761          END IF;
2762 
2763          /*
2764          IF (G_concurrent_flag = 'Y') THEN
2765            fnd_file.put_line (FND_FILE.LOG, 'Found applicable MR-ID:title:' || l_appl_rec.mr_header_id || ':'
2766                               || l_appl_rec.title);
2767          END IF;
2768          */
2769 
2770 
2771          l_applicable_mr_rec.csi_item_instance_id := l_appl_rec.csi_item_instance_id;
2772          l_applicable_mr_rec.MR_header_id := l_appl_rec.MR_header_id;
2773          l_applicable_mr_rec.title := l_appl_rec.title;
2774          l_applicable_mr_rec.version_number := l_appl_rec.version_number;
2775          l_applicable_mr_rec.Implement_status_code := l_appl_rec.Implement_status_code;
2776          l_applicable_mr_rec.copy_accomplishment_code := l_appl_rec.copy_accomplishment_code;
2777          l_applicable_mr_rec.repetitive_flag := l_appl_rec.repetitive_flag;
2778          l_applicable_mr_rec.show_repetitive_code := l_appl_rec.show_repetitive_code;
2779          l_applicable_mr_rec.preceding_mr_header_id := l_appl_rec.preceding_mr_header_id;
2780          l_applicable_mr_rec.descendent_count := l_appl_rec.descendent_count;
2781          l_applicable_mr_rec.whichever_first_code := l_appl_rec.whichever_first_code;
2782          l_applicable_mr_rec.effective_to := l_appl_rec.effective_to;
2783          l_applicable_mr_rec.effective_from := l_appl_rec.effective_from;
2784 
2785          -- added for bug# 9263774
2786          IF (l_applicable_mr_rec.effective_to < sysdate) THEN
2787             l_applicable_mr_rec.expired_mr_flag := 'Y';
2788          ELSE
2789             l_applicable_mr_rec.expired_mr_flag := 'N';
2790          END IF;
2791 
2792          -- Added for SB Effectivity Enh
2793          l_applicable_mr_rec.terminate_trigger_check := l_appl_rec.terminate_trigger_check;
2794          l_applicable_mr_rec.accomplish_trigger_type := l_appl_rec.accomplish_trigger_type;
2795          l_applicable_mr_rec.loop_chain_seq_num      := l_appl_rec.loop_chain_seq_num;
2796 
2797          -- call procedure to build effectivity.
2798          Build_Effectivity ( p_applicable_mrs_rec => l_applicable_mr_rec,
2799                              p_current_usage_tbl  => l_current_usage_tbl,
2800                              p_counter_rules_tbl  => l_counter_rules_tbl );
2801 
2802          IF G_DEBUG = 'Y' THEN
2803             AHL_DEBUG_PUB.debug('Process Unit:LOOP to next MR-ID');
2804          END IF;
2805 
2806        END LOOP; /* loop through next mr */
2807 
2808        IF G_DEBUG = 'Y' THEN
2809           AHL_DEBUG_PUB.debug('Process Unit:LOOP to next NODE');
2810        END IF;
2811 
2812     END LOOP; /* loop to process next node. */
2813   END IF; /* for count > 0 */
2814 
2815 END Process_ASO_Unit;
2816 
2817 --------------------------------------------------------------------------------
2818 -- Build the counter ratio that needs to be applied to the item instance based
2819 -- on its master configuration position. Input is the item instance.
2820 -- Modified per 11.5.10 UC enhancements.
2821 
2822 PROCEDURE build_Counter_Ratio(p_position_reference   IN VARCHAR2,
2823                               p_csi_item_instance_id IN NUMBER,
2824                               p_master_config_id     IN NUMBER,
2825                               x_counter_rules_tbl    OUT NOCOPY counter_rules_tbl_type)
2826 IS
2827 
2828   -- for counter rules given a relationship_id.
2829   CURSOR ahl_ctr_rule_csr ( p_relationship_id IN NUMBER) IS
2830     SELECT uom_code, ratio
2831     FROM ahl_ctr_update_rules
2832     WHERE relationship_id = p_relationship_id
2833         AND rule_code = 'STANDARD';
2834 
2835   -- traverse up the master configuration to top node.
2836 /*  CURSOR ahl_master_config_csr (p_start_node_id IN NUMBER) IS
2837     SELECT relationship_id
2838     FROM   ahl_relationships_b
2839     START WITH relationship_id = p_start_node_id
2840     CONNECT BY PRIOR parent_relationship_id = relationship_id
2841        AND trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate)
2842        AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate + 1));
2843 */
2844 
2845   -- Per UC 11.5.10 enhancements, instead of traversing MC; we traverse UC and get the position
2846   -- reference.
2847   CURSOR ahl_unit_config_csr (p_csi_item_instance_id IN NUMBER) IS
2848     SELECT to_number(position_reference) position_reference
2849     FROM csi_ii_relationships
2850     START WITH subject_id = p_csi_item_instance_id
2851                AND relationship_type_code = 'COMPONENT-OF'
2852                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
2853                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
2854     CONNECT BY PRIOR subject_id = object_id
2855                AND relationship_type_code = 'COMPONENT-OF'
2856                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
2857                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1));
2858 
2859   -- get root master configuration for the item's position reference.
2860   CURSOR ahl_posn_master_config_csr (p_start_node_id IN NUMBER) IS
2861     SELECT relationship_id
2862     FROM   ahl_mc_relationships
2863     WHERE parent_relationship_id IS NULL
2864     START WITH relationship_id = p_start_node_id
2865     CONNECT BY PRIOR parent_relationship_id = relationship_id
2866        AND trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate)
2867        AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate + 1));
2868 
2869 
2870   l_position_ref           NUMBER;
2871   l_uom_code               ahl_ctr_update_rules.uom_code%TYPE;
2872   l_ratio                  NUMBER;
2873   l_match_found_flag       BOOLEAN;
2874   l_table_count            NUMBER;
2875   l_posn_master_config_id  NUMBER;
2876 
2877   l_counter_rules_tbl  counter_rules_tbl_type;
2878 
2879 
2880 BEGIN
2881 
2882   IF G_DEBUG = 'Y' THEN
2883      AHL_DEBUG_PUB.debug ('Start Build Counter Ratio');
2884   END IF;
2885 
2886   -- If there is no master configuration
2887   IF (p_master_config_id IS NOT NULL) THEN
2888 
2889       l_position_ref := to_number(p_position_reference);
2890       x_counter_rules_tbl := l_counter_rules_tbl;
2891 
2892       -- Check if position reference belongs to master configuration.
2893       OPEN ahl_posn_master_config_csr(l_position_ref);
2894       FETCH ahl_posn_master_config_csr INTO l_posn_master_config_id;
2895       IF (ahl_posn_master_config_csr%FOUND) THEN
2896         IF (l_posn_master_config_id = p_master_config_id) THEN
2897 
2898            l_table_count := 0;
2899            -- Build counter rules table.
2900            FOR l_relationship_id IN ahl_unit_config_csr(p_csi_item_instance_id) LOOP
2901              FOR l_ratio_rec IN ahl_ctr_rule_csr (l_relationship_id.position_reference) LOOP
2902                l_uom_code := l_ratio_rec.uom_code;
2903                l_ratio    := l_ratio_rec.ratio;
2904 
2905                -- Check if uom_code already exists in x_counter_rules_tbl.
2906                l_match_found_flag := FALSE;
2907 
2908                IF (l_table_count > 0) THEN
2909                  FOR i IN x_counter_rules_tbl.FIRST..x_counter_rules_tbl.LAST LOOP
2910                    IF (x_counter_rules_tbl(i).uom_code = l_uom_code) THEN
2911                       x_counter_rules_tbl(i).ratio := x_counter_rules_tbl(i).ratio * l_ratio;
2912                       l_match_found_flag := TRUE;
2913                    END IF;
2914                  END LOOP; /* counter_rules_tbl */
2915                END IF; /* count > 0 */
2916 
2917                -- Add new row if match not found.
2918                IF NOT (l_match_found_flag) THEN
2919                  l_table_count := l_table_count + 1;
2920                  x_counter_rules_tbl(l_table_count).uom_code := l_uom_code;
2921                  x_counter_rules_tbl(l_table_count).ratio    := l_ratio;
2922                END IF;
2923              END LOOP; /* for ahl_ctr_rule_csr */
2924 
2925            END LOOP; /* for ahl_master-config_csr */
2926         END IF; /* master config id matches */
2927       END IF; /* found */
2928       CLOSE ahl_posn_master_config_csr;
2929   END IF; /* master config not null */
2930 
2931   IF G_DEBUG = 'Y' THEN
2932      AHL_DEBUG_PUB.debug ('End Build Counter Ratio');
2933      AHL_DEBUG_PUB.debug ('Counter Rules tbl count' || x_counter_rules_tbl.COUNT);
2934   END IF;
2935 
2936 EXCEPTION
2937 
2938   WHEN INVALID_NUMBER THEN
2939     x_counter_rules_tbl := l_counter_rules_tbl;
2940 
2941 END build_Counter_Ratio;
2942 
2943 ----------------------------------------------------------------------------------
2944 -- Build the current usage on the item instance's counters based on counters attached
2945 -- to the item instance.
2946 
2947 PROCEDURE get_Current_Usage ( p_csi_item_instance_id IN NUMBER,
2948                               x_current_usage_tbl    OUT NOCOPY counter_values_tbl_type )
2949 IS
2950 
2951   CURSOR csi_cp_counters_csr (p_csi_instance_id IN NUMBER) IS
2952      /*
2953      SELECT counter_id, uom_code, net_reading, counter_name
2954      FROM   csi_cp_counters_v
2955      WHERE  customer_product_id = p_csi_item_instance_id
2956      ORDER BY uom_code;
2957 
2958      SELECT cc.counter_id, cc.uom_code,
2959             cc.counter_template_name counter_name
2960      from   csi_counter_associations cca, csi_counters_vl cc
2961      where  cca.counter_id = cc.counter_id
2962      AND    source_object_code = 'CP'
2963      AND    source_object_id = p_csi_instance_id;
2964      */
2965 
2966      /* reverted to old code - see bug# 7355947
2967      SELECT cc.counter_id, cc.uom_code,
2968             cc.counter_template_name counter_name,
2969             (select ccr.net_reading
2970             from csi_counter_readings ccr
2971             where ccr.counter_id = cc.counter_id
2972             and value_timestamp = (select max(value_timestamp) from csi_counter_readings rd
2973                                    where counter_id = cc.counter_id
2974                                    and nvl(disabled_flag,'N') = 'N')) net_reading
2975      FROM   csi_counter_associations cca, csi_counters_vl cc
2976      WHERE  cca.counter_id = cc.counter_id
2977      AND    source_object_code = 'CP'
2978      AND    source_object_id = p_csi_item_instance_id;
2979      */
2980 
2981      -- 15 Sept 08: Modified based on IB changes - refer bug# 7374316
2982      SELECT cc.counter_id, cc.uom_code,
2983             cc.counter_template_name counter_name,
2984             (select ccr.net_reading
2985              from csi_counter_readings ccr
2986              where ccr.counter_value_id = cc.CTR_VAL_MAX_SEQ_NO
2987                and nvl(ccr.disabled_flag,'N') = 'N')
2988      FROM   csi_counter_associations cca, csi_counters_vl cc
2989      WHERE  cca.counter_id = cc.counter_id
2990      AND    source_object_code = 'CP'
2991      AND    source_object_id = p_csi_instance_id;
2992 
2993   /*
2994   -- get net reading.
2995   CURSOR csi_cp_counters_val_csr (p_counter_id IN NUMBER) IS
2996      SELECT nvl(cv.net_reading,0) net_reading
2997      FROM csi_counter_values_v cv
2998      WHERE cv.counter_id = p_counter_id
2999        AND rownum < 2;
3000 
3001   -- get net reading.
3002   CURSOR csi_cp_counters_val_csr (p_counter_id IN NUMBER) IS
3003      SELECT * FROM
3004         (SELECT net_reading
3005          FROM csi_counter_readings
3006          WHERE counter_id = p_counter_id
3007            AND nvl(disabled_flag,'N') = 'N'
3008          ORDER BY value_timestamp desc)
3009      WHERE rownum < 2;
3010   */
3011 
3012   i  NUMBER;
3013 
3014   l_current_usage_tbl  counter_values_tbl_type;
3015 
3016   -- added for perf fix.
3017   l_ctr_id_tbl       nbr_tbl_type;
3018   l_ctr_uom_tbl      vchar_tbl_type;
3019   l_ctr_name_tbl     vchar_tbl_type;
3020   l_ctr_net_read_tbl nbr_tbl_type;
3021 
3022 BEGIN
3023 
3024   IF G_DEBUG = 'Y' THEN
3025      AHL_DEBUG_PUB.debug ('Start Get Current Usage');
3026   END IF;
3027 
3028   -- Build current usage counters.
3029   OPEN csi_cp_counters_csr(p_csi_item_instance_id);
3030   FETCH csi_cp_counters_csr BULK COLLECT INTO l_ctr_id_tbl, l_ctr_uom_tbl, l_ctr_name_tbl,
3031                                               l_ctr_net_read_tbl;
3032   CLOSE csi_cp_counters_csr;
3033 
3034   /*
3035   LOOP
3036     FETCH csi_cp_counters_csr INTO l_current_usage_tbl(i).counter_id,
3037                                    l_current_usage_tbl(i).uom_code,
3038                                    l_current_usage_tbl(i).counter_name;
3039     EXIT WHEN csi_cp_counters_csr%NOTFOUND;
3040 
3041     -- get latest net reading.
3042     OPEN csi_cp_counters_val_csr(l_current_usage_tbl(i).counter_id);
3043     FETCH csi_cp_counters_val_csr INTO l_current_usage_tbl(i).counter_value;
3044     CLOSE csi_cp_counters_val_csr;
3045 
3046     IF (l_current_usage_tbl(i).counter_value IS NULL) THEN
3047        l_current_usage_tbl(i).counter_value := 0;
3048     END IF;
3049 
3050     i := i + 1;
3051   END LOOP;
3052   */
3053 
3054   IF (l_ctr_id_tbl.COUNT > 0) THEN
3055 
3056     i := 1;
3057     FOR j IN l_ctr_id_tbl.FIRST..l_ctr_id_tbl.LAST LOOP
3058       l_current_usage_tbl(i).counter_id := l_ctr_id_tbl(j);
3059       l_current_usage_tbl(i).uom_code   := l_ctr_uom_tbl(j);
3060       l_current_usage_tbl(i).counter_name := l_ctr_name_tbl(j);
3061 
3062       /* 15 Sept 08: commented to incorporate IB changes - see bug# 7374316
3063       -- get latest net reading.
3064       OPEN csi_cp_counters_val_csr(l_current_usage_tbl(i).counter_id);
3065       FETCH csi_cp_counters_val_csr INTO l_current_usage_tbl(i).counter_value;
3066       CLOSE csi_cp_counters_val_csr;
3067 
3068       IF (l_current_usage_tbl(i).counter_value IS NULL) THEN
3069         l_current_usage_tbl(i).counter_value := 0;
3070       END IF;
3071       */
3072 
3073       IF (l_ctr_net_read_tbl(j) IS NULL) THEN
3074          l_current_usage_tbl(i).counter_value := 0;
3075       ELSE
3076          l_current_usage_tbl(i).counter_value := l_ctr_net_read_tbl(j);
3077       END IF;
3078 
3079       i := i + 1;
3080     END LOOP;
3081   END IF; -- l_ctr_id_tbl.COUNT
3082 
3083   -- Set return value.
3084   x_current_usage_tbl := l_current_usage_tbl;
3085 
3086   IF G_DEBUG = 'Y' THEN
3087      AHL_DEBUG_PUB.debug ('Counter Usage tbl count' || x_current_usage_tbl.COUNT);
3088      AHL_DEBUG_PUB.debug ('End Get Current Usage');
3089   END IF;
3090 
3091 END get_Current_Usage;
3092 
3093 --------------------------------------------------------------------------------------------
3094 -- Get accomplishment details for an MR.
3095 -- Added parameter x_no_forecast_flag to fix bug# 6711228.
3096 PROCEDURE get_accomplishment_details (p_applicable_mrs_rec IN applicable_mrs_rec_type,
3097                                       p_current_usage_tbl  IN counter_values_tbl_type,
3098                                       p_counter_rules_tbl  IN counter_rules_tbl_type,
3099                                       x_accomplishment_date OUT NOCOPY DATE,
3100                                       x_last_acc_counter_val_tbl OUT NOCOPY counter_values_tbl_type,
3101                                       x_one_time_mr_flag     OUT NOCOPY BOOLEAN,
3102                                       -- x_update_check_flag OUT NOCOPY BOOLEAN,
3103                                       x_dependent_mr_flag  OUT NOCOPY BOOLEAN,
3104                                       x_get_preceding_next_due OUT NOCOPY BOOLEAN,
3105                                       x_mr_accomplish_exists   OUT NOCOPY BOOLEAN,
3106                                       x_no_forecast_flag       OUT NOCOPY BOOLEAN,
3107                                       -- added to fix bug# 8994566
3108                                       x_accomplished_ue_id     OUT NOCOPY NUMBER)
3109 
3110 IS
3111 
3112   -- Get last accomplishment counter values.
3113   CURSOR ahl_unit_accomplish_csr (p_unit_effectivity_id IN NUMBER) IS
3114 
3115   /*
3116   SELECT ua.counter_id, ua.counter_value, cs.uom_code, cs.name counter_name
3117    FROM   ahl_unit_accomplishmnts ua, cs_counters_v cs
3118    WHERE  ua.counter_id = cs.counter_id AND
3119           ua.unit_effectivity_id = p_unit_effectivity_id
3120    ORDER BY cs.uom_code;
3121 */
3122 
3123 	 --Priyan
3124 	 --Query being changed due to performance related fixes
3125 	 --Refer Bug # 4918744
3126 	 --Changed the usage of CS_COUNTERS_V to CSI_COUNTERS_VL
3127 
3128 	SELECT
3129 		UA.COUNTER_ID,
3130 		UA.COUNTER_VALUE,
3131 		CS.UOM_CODE,
3132 		--CS.NAME COUNTER_NAME
3133                 CS.COUNTER_TEMPLATE_NAME COUNTER_NAME
3134 	FROM
3135 		AHL_UNIT_ACCOMPLISHMNTS UA,
3136 		CSI_COUNTERS_VL CS
3137 	WHERE
3138 		UA.COUNTER_ID = CS.COUNTER_ID AND
3139 		UA.UNIT_EFFECTIVITY_ID = P_UNIT_EFFECTIVITY_ID
3140 	ORDER BY
3141 		CS.UOM_CODE ;
3142 
3143   -- Get instance counter details.
3144   CURSOR csi_cp_counters_csr (p_csi_instance_id IN NUMBER) IS
3145      /*
3146      SELECT counter_id, uom_code, counter_name
3147      FROM   csi_cp_counters_v
3148      WHERE  customer_product_id = p_csi_instance_id
3149      ORDER BY uom_code;
3150      */
3151      SELECT cc.counter_id, cc.uom_code,
3152             cc.counter_template_name counter_name
3153      from   csi_counter_associations cca, csi_counters_vl cc
3154      where  cca.counter_id = cc.counter_id
3155      AND    source_object_code = 'CP'
3156      AND    source_object_id = p_csi_instance_id;
3157 
3158   -- Get deferred MRs.
3159   -- consider deferral_effective_on instead of due date, only if l_affect_calc_due_date is 'N'.
3160   -- include prior MR revisions
3161   CURSOR ahl_def_csr (p_csi_instance_id IN NUMBER,
3162                       p_mr_header_id    IN NUMBER) IS
3163     SELECT
3164     -- fix for bug# 6875650. Deferral date includes timestamp.
3165     --decode (affect_due_calc_flag, 'N', trunc(nvl(visit_end_date, deferral_effective_on)), trunc(nvl(visit_end_date, due_date)))
3166 
3167     decode (def.affect_due_calc_flag, 'N', def.deferral_effective_on, nvl(def.visit_end_date, def.due_date))
3168     FROM ahl_temp_unit_SR_deferrals def, ahl_mr_headers_b mr1,
3169          (select title from ahl_mr_headers_b where mr_header_id = p_mr_header_id) mr2
3170     WHERE def.csi_item_instance_id = p_csi_instance_id
3171           AND def.mr_header_id = mr1.mr_header_id
3172           AND mr1.title = mr2.title
3173           --AND mr_header_id = p_mr_header_id
3174           AND def.object_type = 'MR'
3175           AND def.deferral_effective_on IS NOT NULL
3176     ORDER BY def.deferral_effective_on DESC;
3177     -- get the latest deferral.
3178     -- pick only deferrals and not SR related MRs.
3179 
3180   -- check for existence of old MR revision
3181   CURSOR check_old_mr_ver (p_csi_instance_id IN NUMBER,
3182                            p_mr_header_id    IN NUMBER) IS
3183   SELECT 'x'
3184   FROM ahl_unit_effectivities_b ue, ahl_mr_headers_b mr1, ahl_mr_headers_b mr2
3185   WHERE mr2.mr_header_id = p_mr_header_id
3186     and mr1.title = mr2.title
3187     and mr1.version_number <> mr2.version_number
3188     and mr1.mr_header_id = ue.mr_header_id
3189     and ue.csi_item_instance_id = p_csi_instance_id
3190     and (ue.status_code IS NULL or ue.status_code = 'INIT-DUE');
3191 
3192 
3193   l_acc_unit_effectivity_id   NUMBER;
3194   l_acc_status_code           ahl_unit_effectivities_app_v.status_code%TYPE;
3195 
3196   l_last_accomplishment_date  DATE;
3197   l_last_acc_counter_val_tbl  counter_values_tbl_type;
3198   l_due_counter_val_tbl       counter_values_tbl_type;
3199   l_due_date      DATE;
3200 
3201   l_return_val   BOOLEAN;
3202   i NUMBER;
3203   l_acc_deferral_flag  BOOLEAN;
3204 
3205   l_dependent_mr_flag  BOOLEAN;
3206   /* set based on preceding mr and accomplishment */
3207 
3208   --l_update_check_flag  BOOLEAN := FALSE;
3209   l_get_preceding_next_due BOOLEAN := FALSE;
3210 
3211   l_one_time_mr_flag  BOOLEAN := FALSE;
3212   /* set to true if the MR is a one time MR and already has an accomplishment */
3213   /* or there exists a deferral with it's due date = null. */
3214 
3215   l_net_reading  NUMBER;
3216 
3217   l_no_forecast_flag  BOOLEAN := FALSE;
3218   -- set this flag to true if no forecast available when calculating deferral due date.
3219 
3220   l_mr_accomplish_exists BOOLEAN := FALSE;
3221   -- set this flag if a mr accomplishment exists.
3222 
3223   l_junk  VARCHAR2(1);
3224 
3225 BEGIN
3226 
3227   IF G_DEBUG = 'Y' THEN
3228      AHL_DEBUG_PUB.debug ('Start Get Accomplishment Details');
3229   END IF;
3230 
3231   -- Check if any deferrals exist.
3232   OPEN ahl_def_csr (p_applicable_mrs_rec.csi_item_instance_id,
3233                     p_applicable_mrs_rec.mr_header_id);
3234   FETCH ahl_def_csr INTO l_last_accomplishment_date;
3235   IF (ahl_def_csr%FOUND) THEN
3236     l_acc_deferral_flag := TRUE;
3237     l_mr_accomplish_exists := TRUE; -- deferral record.
3238   ELSE
3239     -- Lookup if any accomplishments exist.
3240 
3241     -- Get last accomplishment for the MR..
3242     AHL_UMP_UTIL_PKG.get_last_accomplishment(p_applicable_mrs_rec.csi_item_instance_id,
3243                                              p_applicable_mrs_rec.mr_header_id,
3244                                              l_last_accomplishment_date,
3245                                              l_acc_unit_effectivity_id,
3246                                              l_acc_deferral_flag,
3247                                              l_acc_status_code,
3248                                              l_return_val);
3249     IF (l_acc_unit_effectivity_id IS NOT NULL) THEN
3250       l_mr_accomplish_exists := TRUE;
3251       -- added for bug# 8994566
3252       x_accomplished_ue_id   := l_acc_unit_effectivity_id;
3253     END IF;
3254 
3255   END IF;
3256 
3257   -- Check for one time MR.
3258   IF (l_acc_unit_effectivity_id IS NOT NULL AND p_applicable_mrs_rec.repetitive_flag = 'N') OR
3259      (l_acc_deferral_flag = TRUE AND p_applicable_mrs_rec.repetitive_flag = 'N') THEN
3260      --dbms_output.put_line('one time true');
3261      l_one_time_mr_flag := TRUE;
3262   END IF;
3263 
3264   -- check for old revisions.
3265   IF (p_applicable_mrs_rec.repetitive_flag = 'N' AND NOT(l_one_time_mr_flag)) THEN
3266      OPEN check_old_mr_ver(p_applicable_mrs_rec.csi_item_instance_id,
3267                            p_applicable_mrs_rec.mr_header_id);
3268      FETCH check_old_mr_ver INTO l_junk;
3269      IF (check_old_mr_ver%FOUND) THEN
3270         l_one_time_mr_flag := TRUE;
3271      END IF;
3272      CLOSE check_old_mr_ver;
3273   END IF;
3274 
3275   l_dependent_mr_flag := FALSE;
3276   -- Set this flag only if there are no accomplishments for the MR and this MR has
3277   -- a preceding MR.
3278 
3279   IF (p_applicable_mrs_rec.preceding_mr_header_id IS NOT NULL AND
3280      l_acc_unit_effectivity_id IS NULL)
3281   THEN
3282      l_dependent_mr_flag := TRUE;
3283      --dbms_output.put_line ('dependent flag true');
3284      -- Modified to get first accomplishment to fix bug#6711228
3285      AHL_UMP_UTIL_PKG.get_first_accomplishment(p_applicable_mrs_rec.csi_item_instance_id,
3286                                                p_applicable_mrs_rec.preceding_mr_header_id,
3287                                                l_last_accomplishment_date,
3288                                                l_acc_unit_effectivity_id,
3289                                                l_acc_deferral_flag,
3290                                                l_acc_status_code,
3291                                                l_return_val);
3292   END IF;
3293 
3294   IF (l_acc_deferral_flag) THEN
3295     IF (l_last_accomplishment_date IS NULL) THEN
3296        --l_one_time_mr_flag := TRUE;  -- no forecast and cannot calculate deferral due date.
3297        l_no_forecast_flag := TRUE;  -- no forecast and cannot calculate deferral due date.
3298     -- fix for bug# 6875650.
3299     -- ELSIF (trunc(l_last_accomplishment_date) <= trunc(sysdate)) THEN
3300     ELSIF (l_last_accomplishment_date <= sysdate) THEN
3301       -- get counter values from counter values tables.
3302       i := 1;
3303       FOR instance_counter_rec IN csi_cp_counters_csr(p_applicable_mrs_rec.csi_item_instance_id) LOOP
3304           l_net_reading := 0;
3305           get_ctr_reading_for_datetime (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
3306                                         p_counter_id           => instance_counter_rec.counter_id,
3307                                         p_reading_date         => l_last_accomplishment_date,
3308                                         x_net_reading          => l_net_reading);
3309 
3310           l_last_acc_counter_val_tbl(i).uom_code := instance_counter_rec.uom_code;
3311           l_last_acc_counter_val_tbl(i).counter_id := instance_counter_rec.counter_id;
3312           l_last_acc_counter_val_tbl(i).counter_name := instance_counter_rec.counter_name;
3313           l_last_acc_counter_val_tbl(i).counter_value := l_net_reading;
3314           i := i + 1;
3315 
3316       END LOOP;
3317     ELSE  -- deferral due date is a future date.
3318        -- get all counter values as on l_preceding_next_due_date.
3319        Get_Due_at_Counter_Values (p_last_due_date => sysdate,
3320                                   p_last_due_counter_val_tbl => p_current_usage_tbl,
3321                                   p_due_date => l_last_accomplishment_date,
3322                                   p_counter_rules_tbl => p_counter_rules_tbl,
3323                                   x_due_at_counter_val_tbl => l_last_acc_counter_val_tbl,
3324                                   x_return_value => l_return_val);
3325 
3326        IF G_DEBUG = 'Y' THEN
3327          AHL_DEBUG_PUB.Debug('l_deferral_due_date: ' || l_last_accomplishment_date);
3328          IF (l_last_acc_counter_val_tbl.COUNT) > 0 THEN
3329             for i in l_last_acc_counter_val_tbl.FIRST..l_last_acc_counter_val_tbl.LAST LOOP
3330                AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_last_acc_counter_val_tbl(i).counter_value || 'ID: ' || l_last_acc_counter_val_tbl(i).counter_id);
3331             end loop;
3332          END IF;
3333        END IF;
3334 
3335        -- check return value.
3336        IF NOT(l_return_val) THEN  -- no forecast case.
3337          --l_one_time_mr_flag := TRUE;
3338          l_no_forecast_flag := TRUE;
3339        END IF;
3340 
3341     END IF;  -- Last accomplishment date.
3342   ELSE  -- not based on deferral_effective_date.
3343     IF (l_acc_unit_effectivity_id IS NOT NULL) THEN
3344       i := 1;
3345       -- Build last accomplishment counter values.
3346       FOR l_acc_counter_rec IN ahl_unit_accomplish_csr(l_acc_unit_effectivity_id) LOOP
3347         l_last_acc_counter_val_tbl(i).uom_code := l_acc_counter_rec.uom_code;
3348         l_last_acc_counter_val_tbl(i).counter_id := l_acc_counter_rec.counter_id;
3349         l_last_acc_counter_val_tbl(i).counter_name := l_acc_counter_rec.counter_name;
3350         l_last_acc_counter_val_tbl(i).counter_value := l_acc_counter_rec.counter_value;
3351         i := i + 1;
3352       END LOOP;
3353 
3354     ELSIF (l_dependent_mr_flag) THEN
3355        -- no accomplishment for preceding MR available.
3356        -- get the next due date from temporary table for calculation.
3357        l_get_preceding_next_due := TRUE;
3358     END IF;
3359   END IF; -- l_acc_deferral_flag.
3360 
3361   -- set return parameters.
3362   x_accomplishment_date := l_last_accomplishment_date;
3363   x_last_acc_counter_val_tbl := l_last_acc_counter_val_tbl;
3364   x_one_time_mr_flag := l_one_time_mr_flag;
3365   x_dependent_mr_flag := l_dependent_mr_flag;
3366   x_get_preceding_next_due := l_get_preceding_next_due;
3367   x_no_forecast_flag := l_no_forecast_flag;
3368   x_mr_accomplish_exists := l_mr_accomplish_exists;
3369 
3370   IF G_DEBUG = 'Y' THEN
3371      AHL_DEBUG_PUB.debug ('Last Accomplished Date:' || x_accomplishment_date);
3372      AHL_DEBUG_PUB.debug ('Last Accomplished UE ID:' || x_accomplished_ue_id);
3373      AHL_DEBUG_PUB.debug ('Count of ctr values:' || x_last_acc_counter_val_tbl.COUNT);
3374      AHL_DEBUG_PUB.debug ('End Get Accomplishment Details');
3375   END IF;
3376 
3377 END get_accomplishment_details;
3378 
3379 ------------------------------------------------------------------------------
3380 -- Build unit effectivity for a given item instance and a maintenance requirement.
3381 -- The unit effectivities created here will be written into a temporary table.
3382 
3383 PROCEDURE Build_Effectivity ( p_applicable_mrs_rec IN applicable_mrs_rec_type,
3384                               p_current_usage_tbl  IN counter_values_tbl_type,
3385                               p_counter_rules_tbl  IN counter_rules_tbl_type)
3386 
3387 IS
3388 
3389   /* modified for bug# 9263774 - calc due date for prior revisions.
3390   -- retrieve current unit effectivity records.
3391   CURSOR ahl_unit_effectivity_csr (p_mr_header_id IN NUMBER,
3392                                    p_csi_item_instance_id IN NUMBER) IS
3393   SELECT ue.unit_effectivity_id, ue.status_code, reln.related_ue_id, reln.originator_ue_id
3394   FROM   ahl_unit_effectivities_app_v UE, ahl_UE_relationships reln
3395   WHERE  UE.unit_effectivity_id = RELN.RELATED_UE_ID(+)
3396        AND mr_header_id = p_mr_header_id
3397        AND csi_item_instance_id = p_csi_item_instance_id
3398        AND (UE.Status_code IS NULL OR status_code = 'INIT-DUE')
3399        AND UE.defer_from_ue_id IS NULL  -- do not pick deferred unit effectivities.
3400        AND nvl(UE.manually_planned_flag,'N') = 'N'   -- do not pick manually planned UEs.
3401        -- do not pick up child UEs if parent init-accomplished.
3402        AND NOT EXISTS (SELECT 'x' FROM AHL_UNIT_EFFECTIVITIES_B PARENT_UE
3403                        WHERE PARENT_UE.UNIT_EFFECTIVITY_ID = RELN.ORIGINATOR_UE_ID
3404                          AND PARENT_UE.STATUS_CODE = 'INIT-ACCOMPLISHED')
3405   ORDER BY forecast_sequence ASC;
3406   */
3407 
3408   -- retrieve current unit effectivity records(including prior revisions).
3409   CURSOR ahl_unit_effectivity_csr (p_title IN VARCHAR2,
3410                                    p_csi_item_instance_id IN NUMBER,
3411                                    p_appln_usg_code       IN VARCHAR2) IS
3412   SELECT ue.unit_effectivity_id, ue.status_code, reln.related_ue_id, reln.originator_ue_id, ue.mr_header_id
3413   --FROM   ahl_unit_effectivities_app_v UE, ahl_UE_relationships reln,
3414   FROM   ahl_unit_effectivities_b UE, ahl_UE_relationships reln,
3415          ahl_mr_headers_b mr
3416   WHERE  UE.unit_effectivity_id = RELN.RELATED_UE_ID(+)
3417        AND UE.mr_header_id = mr.mr_header_id
3418        AND mr.mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1 where mr1.title = p_title)
3419        AND UE.csi_item_instance_id = p_csi_item_instance_id
3420        AND UE.application_usg_code = p_appln_usg_code
3421        AND (UE.Status_code IS NULL OR UE.status_code = 'INIT-DUE')
3422        AND UE.defer_from_ue_id IS NULL  -- do not pick deferred unit effectivities.
3423        AND nvl(UE.manually_planned_flag,'N') = 'N'   -- do not pick manually planned UEs.
3424        -- do not pick up child UEs if parent init-accomplished.
3425        AND NOT EXISTS (SELECT 'x' FROM AHL_UNIT_EFFECTIVITIES_B PARENT_UE
3426                        WHERE PARENT_UE.UNIT_EFFECTIVITY_ID = RELN.ORIGINATOR_UE_ID
3427                          AND PARENT_UE.STATUS_CODE = 'INIT-ACCOMPLISHED')
3428   ORDER BY mr.version_number ASC, forecast_sequence ASC ;
3429 
3430   -- Get group MRs if any, from ahl_temp_unit_effectivities for the item instance.
3431   -- select only the first row.
3432   -- modified to support multiple MR revisions for bug# 9263774
3433   CURSOR ahl_temp_ue_csr (p_item_instance_id IN NUMBER,
3434                           --p_mr_header_id     IN NUMBER,
3435                           p_title            IN VARCHAR2,
3436                           p_last_due_date    IN DATE,
3437                           p_due_date         IN DATE ) IS
3438    SELECT *
3439    FROM (
3440         SELECT due_date,
3441                orig_csi_item_instance_id,
3442                orig_mr_header_id,
3443                --orig_forecast_sequence,
3444                visit_end_date
3445         FROM ahl_temp_unit_effectivities
3446         WHERE csi_item_instance_id = p_item_instance_id AND
3447               --mr_header_id = p_mr_header_id AND
3448               mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1 where mr1.title = p_title) AND
3449               orig_csi_item_instance_id IS NOT NULL AND
3450               orig_mr_header_id IS NOT NULL AND
3451               trunc(nvl(visit_end_date, nvl(due_date, p_last_due_date))) > trunc(p_last_due_date) AND
3452               trunc(nvl(visit_end_date, nvl(due_date, p_due_date+1))) <= trunc(p_due_date) AND
3453               preceding_check_flag = 'N'
3454         /* ignore records with null due dates */
3455         /* order selected rows so that the record with max due date is first */
3456         /* consider visit end date instead of due date, if it is available. */
3457 
3458         UNION
3459 
3460         -- Get SR's.
3461         SELECT due_date,
3462                csi_item_instance_id orig_csi_item_instance_id,
3463                mr_header_id orig_mr_header_id,
3464                visit_end_date
3465         FROM ahl_temp_unit_SR_deferrals
3466         WHERE csi_item_instance_id = p_item_instance_id
3467               --AND mr_header_id = p_mr_header_id
3468               AND mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1 where mr1.title = p_title)
3469               AND trunc(nvl(visit_end_date, nvl(due_date, p_last_due_date))) > trunc(p_last_due_date)
3470               AND trunc(nvl(visit_end_date, nvl(due_date, p_due_date+1))) <= trunc(p_due_date)
3471               AND deferral_effective_on IS NULL -- pick only SR related MRs.
3472         -- ignore records with null due dates.
3473         -- ignore deferral records.
3474 
3475         ORDER BY due_date DESC
3476         )
3477    WHERE ROWNUM < 2;
3478 
3479   -- in case of 'next-due', we need to check p_last_due_date equality condition too.
3480   -- Get group MRs if any, from ahl_temp_unit_effectivities for the item instance.
3481   -- select only the first row.
3482   -- modified to support multiple MR revisions for bug# 9263774
3483   CURSOR ahl_temp_ue_csr1 (p_item_instance_id IN NUMBER,
3484                            --p_mr_header_id     IN NUMBER,
3485                            p_title            IN VARCHAR2,
3486                            p_last_due_date    IN DATE,
3487                            p_due_date         IN DATE ) IS
3488    SELECT *
3489    FROM (
3490         SELECT due_date,
3491                orig_csi_item_instance_id,
3492                orig_mr_header_id,
3493                --orig_forecast_sequence,
3494                visit_end_date
3495         FROM ahl_temp_unit_effectivities
3496         WHERE csi_item_instance_id = p_item_instance_id AND
3497               --mr_header_id = p_mr_header_id AND
3498               mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1 where mr1.title = p_title) AND
3499               orig_csi_item_instance_id IS NOT NULL AND
3500               orig_mr_header_id IS NOT NULL AND
3501               trunc(nvl(visit_end_date, nvl(due_date, p_last_due_date))) >= trunc(p_last_due_date) AND
3502               trunc(nvl(visit_end_date, nvl(due_date, p_due_date+1))) <= trunc(p_due_date) AND
3503               preceding_check_flag = 'N'
3504         /* ignore records with null due dates */
3505         /* order selected rows so that the record with max due date is first */
3506         /* consider visit end date instead of due date, if it is available. */
3507 
3508         UNION
3509 
3510         -- Get SR's.
3511         SELECT due_date,
3512                csi_item_instance_id orig_csi_item_instance_id,
3513                mr_header_id orig_mr_header_id,
3514                visit_end_date
3515         FROM ahl_temp_unit_SR_deferrals
3516         WHERE csi_item_instance_id = p_item_instance_id
3517               --AND mr_header_id = p_mr_header_id
3518               AND mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1 where mr1.title = p_title)
3519               AND trunc(nvl(visit_end_date, nvl(due_date, p_last_due_date))) >= trunc(p_last_due_date)
3520               AND trunc(nvl(visit_end_date, nvl(due_date, p_due_date+1))) <= trunc(p_due_date)
3521               AND deferral_effective_on IS NULL -- pick only SR related MRs.
3522         -- ignore records with null due dates.
3523         -- ignore deferral records.
3524         ORDER BY due_date DESC
3525         )
3526    WHERE ROWNUM < 2;
3527 
3528   -- Check if MR is a group MR.
3529   CURSOR group_check_csr (p_item_instance_id IN NUMBER,
3530                           p_mr_header_id IN NUMBER) IS
3531    SELECT 'x'
3532    FROM ahl_applicable_mr_relns
3533    WHERE orig_csi_item_instance_id = p_item_instance_id AND
3534          orig_mr_header_id = p_mr_header_id;
3535 
3536   -- Get next due date of preceding MR from temporary table.
3537   -- modified to support multiple MR revisions for bug# 9263774
3538   -- fix for bug# 9673770. next due from deferral temp table.
3539   CURSOR preceding_due_date_csr (p_preceding_instance_id IN NUMBER,
3540                                  p_preceding_mr_header_id IN NUMBER) IS
3541    SELECT * FROM (
3542      SELECT due_date
3543      FROM ahl_temp_unit_effectivities
3544      WHERE csi_item_instance_id = p_preceding_instance_id AND
3545            --mr_header_id = p_preceding_mr_header_id AND
3546            mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1
3547                             where mr1.title = (select mr2.title from ahl_mr_headers_b mr2 where mr2.mr_header_id = p_preceding_mr_header_id)
3548                            ) AND
3549            preceding_check_flag = 'N'
3550 
3551      UNION
3552      SELECT due_date
3553      FROM ahl_temp_unit_SR_deferrals
3554      WHERE csi_item_instance_id = p_preceding_instance_id AND
3555            mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1
3556                             where mr1.title = (select mr2.title from ahl_mr_headers_b mr2 where mr2.mr_header_id = p_preceding_mr_header_id)
3557                            )
3558      ORDER by due_date
3559    )
3560    WHERE ROWNUM < 2;
3561 
3562   -- Added for 11.5.10+ enhancements for Unplanned MRs.
3563   -- Read open Unplanned MRs.
3564   -- modified to consider prior MR revsions to fix bug#	9263774.
3565   CURSOR ahl_unplanned_MRs_csr(p_item_instance_id IN NUMBER,
3566                                p_title            IN VARCHAR2,
3567                                p_appln_usg_code   IN VARCHAR2) IS
3568     SELECT ue.unit_effectivity_id
3569     --FROM ahl_unit_effectivities_app_v ue
3570     FROM ahl_unit_effectivities_b ue
3571     WHERE ue.csi_item_instance_id = p_item_instance_id
3572        AND ue.application_usg_code = p_appln_usg_code
3573        AND ue.mr_header_id IN (select amh.mr_header_id from ahl_mr_headers_b amh where amh.title = p_title)
3574        AND ue.status_code IS NULL
3575        AND ue.manually_planned_flag = 'Y'
3576        AND NOT EXISTS (SELECT 'x'
3577                        FROM ahl_ue_relationships uer, ahl_unit_effectivities_b ue1
3578                        WHERE uer.related_ue_id = ue.unit_effectivity_id
3579                          AND uer.originator_ue_id = ue1.unit_effectivity_id
3580                          AND ue1.object_type = 'SR');
3581     -- Do not pick MRs associated to a SR.
3582   --
3583   l_unit_effectivity_tbl  unit_effectivity_tbl_type;
3584   /* this table will contain the current unit effectivity definitions for the mr and item instance */
3585 
3586   i    NUMBER := 0;
3587   /* running index for unit effectivity tbl */
3588 
3589   l_visit_start_date   DATE;
3590   l_visit_end_date     DATE;
3591   l_visit_assign_code  VARCHAR2(30);
3592 
3593   l_forecast_sequence  NUMBER;
3594   l_old_UE_forecast_sequence  NUMBER;
3595   l_next_due_date_rec         next_due_date_rec_type;
3596 
3597   l_new_unit_effectivity_rec      ahl_temp_unit_effectivities%ROWTYPE;
3598   l_new_unit_effectivity_initrec  ahl_temp_unit_effectivities%ROWTYPE;
3599 
3600   l_temp_grp_mr_rec   ahl_temp_ue_csr%ROWTYPE;
3601 
3602   l_last_accomplishment_date  DATE;
3603   l_last_acc_counter_val_tbl  counter_values_tbl_type;
3604   l_dependent_mr_flag BOOLEAN;
3605   l_get_preceding_next_due BOOLEAN; -- to indicate that the dependent MR calculation is based on preceding MR's next due.
3606   l_preceding_next_due_date DATE;
3607 
3608   l_one_time_mr_flag  BOOLEAN;
3609 
3610   l_calc_due_date_flag   BOOLEAN := TRUE;
3611   -- set to true if preceding MR due date is null. So the dependent's due date
3612   -- will also be null. Calc due date must not be done.
3613 
3614   --l_bef_tolr_due_date  DATE;
3615   --l_aft_tolr_due_date  DATE;
3616 
3617   l_last_due_date  DATE;
3618   l_last_due_counter_val_tbl  counter_values_tbl_type;
3619   l_due_at_counter_val_tbl    counter_values_tbl_type;
3620   l_due_date       DATE;
3621 
3622   l_next_due_flag  BOOLEAN;
3623   l_grp_duedate_found  BOOLEAN;
3624   l_old_UE_forecast_found BOOLEAN := TRUE;
3625 
3626   l_return_value BOOLEAN;
3627   l_junk    VARCHAR2(1);
3628   group_check_flag  BOOLEAN := FALSE;  -- flag to check if it is a group MR.
3629 
3630   -- Added for 11.5.10+ enhancements for Unplanned MRs.
3631   -- Define rec and table type to hold Unplanned MRs.
3632   TYPE Unplanned_UE_rec_type IS RECORD(
3633      UNIT_EFFECTIVITY_ID  NUMBER,
3634      VISIT_END_DATE       DATE);
3635 
3636   TYPE Unplanned_UE_Tbl_type IS TABLE OF Unplanned_UE_rec_type INDEX BY BINARY_INTEGER;
3637 
3638   l_unplanned_MRs_tbl     Unplanned_UE_Tbl_type;
3639   l_min_visit_date        DATE;
3640 
3641   -- R12 to fix bug# 4224867.
3642   l_duplicate_MRs         NUMBER;
3643   l_usage_per_day         NUMBER;
3644 
3645   -- Added to fix bug# 6711228.
3646   l_no_forecast_flag      BOOLEAN;
3647   l_mr_accomplish_exists  BOOLEAN;
3648 
3649   -- Added to fix bug# 6858788
3650   l_last_due_mr_interval_id NUMBER;
3651 
3652   -- Added for performance.
3653   l_ue_id_tbl              nbr_tbl_type;
3654   l_ue_status_tbl          vchar_tbl_type;
3655   l_related_ue_tbl         nbr_tbl_type;
3656   l_orig_ue_tbl            nbr_tbl_type;
3657   l_prior_mr_header_tbl    nbr_tbl_type;
3658 
3659   l_buffer_limit           NUMBER := 1000;
3660 
3661   -- Added to fix bug# 8994566
3662   l_accomplished_ue_id     NUMBER;
3663 
3664   -- Added for SB Enhancements
3665   l_mr_termination_date    DATE;
3666   l_lc_mr_tbl              loop_chain_MR_tbl_type;
3667 
3668   l_loop_due_date              DATE;
3669   l_loop_last_due_date         DATE;
3670   l_loop_last_counter_val_tbl  counter_values_tbl_type;
3671   l_skip_next_due_flag         VARCHAR2(1);
3672   l_single_mr_seq              NUMBER;
3673 
3674   l_visit_status               VARCHAR2(30);
3675   l_process_status_flag          VARCHAR2(1);
3676 
3677   -- JKJain, NR Analysis and Forecasting
3678   l_next_fleet_asso_date DATE;
3679   l_fleet_asso_rej_date  DATE;
3680 
3681 
3682   CURSOR get_next_fleet_asso_date(l_date DATE)
3683   IS
3684   SELECT * FROM(
3685               SELECT FUA.association_start
3686               FROM ahl_fleet_unit_assocs FUA, ahl_fleet_headers_b FLT
3687               WHERE FUA.unit_config_header_id = G_UC_HEADER_ID
3688                 AND FUA.simulation_plan_id = nvl(G_SIMULATION_PLAN_ID, get_primary_plan_id)
3689                 AND FLT.fleet_header_id = FUA.fleet_header_id
3690                 AND FLT.status_code = 'COMPLETE'
3691                 AND trunc(FUA.association_start) >= trunc(l_date)
3692               ORDER BY FUA.association_start ASC)
3693   WHERE rownum < 2;
3694 
3695 BEGIN
3696 
3697 
3698   IF G_DEBUG = 'Y' THEN
3699      AHL_DEBUG_PUB.debug ('Start Build Effectivity for mr:csi' || p_applicable_mrs_rec.mr_header_id || ':' || p_applicable_mrs_rec.csi_item_instance_id );
3700   END IF;
3701 
3702   -- verify processing flag as it may have been updated during processing.
3703   BEGIN
3704     SELECT process_status_flag
3705       INTO l_process_status_flag
3706     FROM ahl_applicable_MRs
3707     WHERE mr_header_id = p_applicable_mrs_rec.mr_header_id
3708       AND csi_item_instance_id = p_applicable_mrs_rec.csi_item_instance_id
3709       AND rownum < 2;
3710 
3711     IF l_process_status_flag = 'Y' THEN
3712        IF G_DEBUG = 'Y' THEN
3713          AHL_DEBUG_PUB.debug ('Already Processed ...Skipping Build Effectivity for mr:csi' || p_applicable_mrs_rec.mr_header_id || ':' || p_applicable_mrs_rec.csi_item_instance_id );
3714        END IF;
3715        RETURN;
3716     END IF;
3717 
3718   EXCEPTION
3719     WHEN OTHERS THEN
3720       NULL;
3721   END;
3722 
3723   -- If MR has a accomplishment trigger of 'terminated_by' then check if parent MRs are processed and if not, process them.
3724   -- added for SB Enh.
3725   IF (p_applicable_mrs_rec.terminate_trigger_check = 'Y') THEN
3726     Process_terminating_parent_MRs(p_applicable_mrs_rec => p_applicable_mrs_rec,
3727                                    p_current_usage_tbl  => p_current_usage_tbl,
3728                                    p_counter_rules_tbl  => p_counter_rules_tbl,
3729                                    x_mr_termination_date => l_mr_termination_date);
3730 
3731     -- delete any processed deferrals from temp table.
3732     -- *******handle group MRs?
3733     IF (l_mr_termination_date IS NOT NULL) THEN
3734       BEGIN
3735         --dbms_output.put_line ('Start Build Effectivity for mr:csi' || p_applicable_mrs_rec.mr_header_id || ':' || p_applicable_mrs_rec.csi_item_instance_id );
3736         --dbms_output.put_line ('l_mr_termination_date:' || l_mr_termination_date || ':' || p_applicable_mrs_rec.title);
3737         DELETE FROM ahl_temp_unit_SR_deferrals tdef
3738         WHERE tdef.CSI_ITEM_INSTANCE_ID = p_applicable_mrs_rec.csi_item_instance_id
3739           AND tdef.MR_HEADER_ID IN (select MR_HEADER_ID from ahl_mr_headers_b where title = p_applicable_mrs_rec.title)
3740           AND trunc(tdef.DUE_DATE) >= trunc(l_mr_termination_date)
3741           AND NOT EXISTS (select 'x' from ahl_temp_unit_SR_deferrals where orig_unit_effectivity_id = tdef.unit_effectivity_id);
3742       EXCEPTION
3743         WHEN OTHERS THEN
3744           null;
3745       END;
3746     END IF;
3747   END IF;
3748 
3749 
3750 
3751   -- Added for SB Enhancements
3752   -- If p_applicable_mrs_rec.mr_header_id is a starting mr for a loop or chain
3753   -- then initialize
3754   IF (p_applicable_mrs_rec.accomplish_trigger_type = 'CHAIN') THEN
3755 
3756      Process_Chain_Init(p_applicable_mrs_rec => p_applicable_mrs_rec,
3757                         p_current_usage_tbl  => p_current_usage_tbl,
3758                         p_counter_rules_tbl  => p_counter_rules_tbl,
3759                         x_loop_chain_MR_tbl  => l_lc_mr_tbl);
3760 
3761      l_skip_next_due_flag := 'N';
3762      IF G_DEBUG = 'Y' THEN
3763        AHL_DEBUG_PUB.debug ('count x_loop_chain_MR_tbl:next_due_flag:' || l_lc_mr_tbl.count || ':' || l_skip_next_due_flag);
3764      END IF;
3765   END IF;
3766 
3767 
3768   IF (p_applicable_mrs_rec.accomplish_trigger_type = 'LOOP') THEN
3769      Process_Loop_Init(p_applicable_mrs_rec => p_applicable_mrs_rec,
3770                        p_current_usage_tbl  => p_current_usage_tbl,
3771                        p_counter_rules_tbl  => p_counter_rules_tbl,
3772                        x_loop_chain_MR_tbl  => l_lc_mr_tbl,
3773                        x_loop_last_due_date  =>  l_loop_last_due_date,
3774                        x_loop_last_counter_val_tbl => l_loop_last_counter_val_tbl,
3775                        x_next_due_skip_flag => l_skip_next_due_flag);
3776 
3777      IF G_DEBUG = 'Y' THEN
3778        AHL_DEBUG_PUB.debug ('count x_loop_chain_MR_tbl:next_due_flag:' || l_lc_mr_tbl.count || ':' || l_skip_next_due_flag);
3779      END IF;
3780 
3781      -- for loop case, l_skip_next_due_flag returned from Process_Loop_Init indicates if
3782      -- next due calculation needs to be skipped, in which case, we start calculating based on repetivity flag = Y
3783      -- as there is at least one child MR in the loop that is not accomplished yet.
3784      IF (l_skip_next_due_flag IS NULL) THEN
3785         l_skip_next_due_flag := 'N';
3786      ELSIF (l_skip_next_due_flag = 'Y') THEN
3787 
3788         -- initialize calculation variables.
3789         l_next_due_flag := FALSE;
3790         l_forecast_sequence := 1; -- start from 1 instead of 0
3791 
3792         -- start calculation from last loop num ctr values.
3793         l_last_due_date := l_loop_last_due_date;
3794         l_last_due_counter_val_tbl := l_loop_last_counter_val_tbl;
3795 
3796         GOTO process_next_mr_and_repetivity;
3797 
3798      END IF;
3799 
3800   END IF;
3801   -- End SB Enh loop/chain init ---
3802 
3803   -- Set last accomplishment details.
3804   Get_accomplishment_details(p_applicable_mrs_rec => p_applicable_mrs_rec,
3805                              p_current_usage_tbl  => p_current_usage_tbl,
3806                              p_counter_rules_tbl  => p_counter_rules_tbl,
3807                              x_accomplishment_date => l_last_accomplishment_date,
3808                              x_last_acc_counter_val_tbl => l_last_acc_counter_val_tbl,
3809                              x_one_time_mr_flag         => l_one_time_mr_flag,
3810                              x_dependent_mr_flag => l_dependent_mr_flag,
3811                              x_get_preceding_next_due => l_get_preceding_next_due,
3812                              x_mr_accomplish_exists  => l_mr_accomplish_exists,
3813                              x_no_forecast_flag => l_no_forecast_flag,
3814                              x_accomplished_ue_id => l_accomplished_ue_id);
3815 
3816   -- Check for one time MR case.
3817   IF (l_one_time_mr_flag) THEN
3818      --dbms_output.put_line('one time true in build');
3819      GOTO process_preceding_mr;
3820   ELSIF (l_no_forecast_flag) THEN
3821      RETURN;  -- no more MRs needed.
3822   END IF;
3823 
3824   -- get next accomplishment details for the preceding MR if needed.
3825   IF (l_get_preceding_next_due) THEN
3826     OPEN preceding_due_date_csr (p_applicable_mrs_rec.csi_item_instance_id,
3827                                  p_applicable_mrs_rec.preceding_mr_header_id);
3828 
3829     FETCH preceding_due_date_csr INTO l_preceding_next_due_date;
3830     IF (preceding_due_date_csr%NOTFOUND) OR (l_preceding_next_due_date IS NULL) THEN
3831         --dbms_output.put_line ('not found preceding');
3832         l_calc_due_date_flag := FALSE;
3833     ELSE
3834         IF G_DEBUG = 'Y' THEN
3835           AHL_DEBUG_PUB.Debug('Found due_date for preceding MR: '|| l_preceding_next_due_date);
3836         END IF;
3837         l_last_accomplishment_date := l_preceding_next_due_date;
3838         --dbms_output.put_line ('found preceding due_date' ||l_preceding_next_due_date );
3839         -- get all counter values as on l_preceding_next_due_date.
3840         Get_Due_at_Counter_Values (p_last_due_date => sysdate,
3841                                    p_last_due_counter_val_tbl => p_current_usage_tbl,
3842                                    p_due_date => l_preceding_next_due_date,
3843                                    p_counter_rules_tbl => p_counter_rules_tbl,
3844                                    x_due_at_counter_val_tbl => l_last_acc_counter_val_tbl,
3845                                    x_return_value => l_return_value);
3846 
3847         IF G_DEBUG = 'Y' THEN
3848            AHL_DEBUG_PUB.Debug('l_preceding_due_date: '|| l_preceding_next_due_date);
3849            IF (l_last_acc_counter_val_tbl.COUNT) > 0 THEN
3850               for i in l_last_acc_counter_val_tbl.FIRST..l_last_acc_counter_val_tbl.LAST LOOP
3851                 AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_last_acc_counter_val_tbl(i).counter_value || 'ID: ' || l_last_acc_counter_val_tbl(i).counter_id);
3852                 --dbms_output.put_line('i:'|| i|| ' value:' || l_last_acc_counter_val_tbl(i).counter_value || 'ID: ' || l_last_acc_counter_val_tbl(i).counter_id);
3853               end loop;
3854            END IF;
3855         END IF;
3856 
3857         -- check return value.
3858         IF NOT(l_return_value) THEN  -- no forecast case.
3859           --l_preceding_next_due_date := NULL;
3860           l_calc_due_date_flag := FALSE;
3861         END IF;
3862     END IF;
3863     CLOSE preceding_due_date_csr;
3864   END IF;
3865 
3866 
3867   -- Calculate Due date.
3868   IF (l_calc_due_date_flag) THEN -- no calculation needed if preceding mr's next due has no due date.
3869 
3870     --dbms_output.put_line ('bef calculate_due_date');
3871     --dbms_output.put_line ('accomplish:date:' || l_last_accomplishment_date);
3872 
3873     -- Calculate next due date.
3874     -- Added parameter p_dependent_mr_flag to fix bug# 6711228.
3875     Calculate_Due_Date (p_repetivity_flag => 'N',
3876                         p_applicable_mrs_rec => p_applicable_mrs_rec,
3877                         p_current_usage_tbl => p_current_usage_tbl,
3878                         p_counter_rules_tbl => p_counter_rules_tbl,
3879                         p_last_due_date => l_last_accomplishment_date,
3880                         p_last_due_counter_val_tbl => l_last_acc_counter_val_tbl,
3881                         p_dependent_mr_flag => l_dependent_mr_flag,
3882                         p_mr_accomplish_exists  => l_mr_accomplish_exists,
3883                         x_next_due_date_rec => l_next_due_date_rec);
3884   END IF;
3885 
3886   IF G_DEBUG = 'Y' THEN
3887     AHL_DEBUG_PUB.Debug('Aft calculate_due_date nextdue');
3888     AHL_DEBUG_PUB.Debug('due date is ' || l_next_due_date_rec.DUE_DATE);
3889     AHL_DEBUG_PUB.Debug('earliest due date is ' || l_next_due_date_rec.EARLIEST_DUE_DATE);
3890     AHL_DEBUG_PUB.Debug('latest due date is ' || l_next_due_date_rec.latest_due_date);
3891     AHL_DEBUG_PUB.Debug('p_repetivity_flag => N,  FLEET_ASSO_REJECTED ' || l_next_due_date_rec.FLEET_ASSO_REJECTED);
3892   END IF;
3893 
3894   -- JKJain, NR Analysis and Forecasting
3895   IF(l_next_due_date_rec.FLEET_ASSO_REJECTED = 'Y' AND l_next_due_date_rec.DUE_DATE IS NOT NULL) THEN
3896         l_fleet_asso_rej_date := l_next_due_date_rec.DUE_DATE;
3897         l_next_due_date_rec.DUE_DATE := null;
3898   END IF;
3899 
3900   -- added for SB Enhancements - termination trigger.
3901   -- if due date > l_mr_termination_date then MR is terminated and no calc is required.
3902   IF (l_mr_termination_date IS NOT NULL) THEN
3903     IF (l_next_due_date_rec.due_date is NOT NULL AND l_next_due_date_rec.due_date >= l_mr_termination_date) THEN
3904       IF G_DEBUG = 'Y' THEN
3905         AHL_DEBUG_PUB.Debug(p_applicable_mrs_rec.title || 'is terminated');
3906       END IF;
3907       RETURN;
3908     ELSIF l_mr_termination_date <= trunc(sysdate) THEN
3909       IF G_DEBUG = 'Y' THEN
3910         AHL_DEBUG_PUB.Debug(p_applicable_mrs_rec.title || 'is terminated');
3911       END IF;
3912       RETURN;
3913     END IF;
3914   END IF;
3915 
3916   -- If the MR is a dependent MR: (1) If calculated due date is earlier than preceding MR due date,
3917   --                                  then change due date to be equal to preceding MR due date.
3918   --                              (2) Update the preceding_check_flag, based on due date.
3919   IF (p_applicable_mrs_rec.preceding_mr_header_id IS NOT NULL) THEN
3920     IF (trunc(l_next_due_date_rec.DUE_DATE) < trunc(l_last_accomplishment_date)) THEN
3921        l_next_due_date_rec.DUE_DATE := l_last_accomplishment_date;
3922     END IF;
3923 
3924     Update_check_flag (p_applicable_mrs_rec => p_applicable_mrs_rec,
3925                        p_dependent_mr_flag => l_dependent_mr_flag,
3926                        p_next_due_date_rec => l_next_due_date_rec);
3927   END IF;
3928 
3929   --- Initialize before processing starts.
3930   l_next_due_flag := TRUE;
3931   /* next due mr calculation. */
3932   l_forecast_sequence := 0;
3933 
3934   -- set last_due values to current values.
3935   l_last_due_date := sysdate;
3936   l_last_due_counter_val_tbl := p_current_usage_tbl;
3937   -----
3938 
3939   <<process_next_mr_and_repetivity>>
3940 
3941   -- Initialize forecast sequence numbers.
3942   l_old_UE_forecast_sequence := 0;
3943   l_old_UE_forecast_found := TRUE;
3944 
3945   -- Read existing unit effectivity records for the mr and item instance.
3946   OPEN ahl_unit_effectivity_csr(p_applicable_mrs_rec.title,
3947                                 p_applicable_mrs_rec.csi_item_instance_id,
3948                                 G_application_usg_code);
3949   i := 0;
3950   l_single_mr_seq := 0;
3951   LOOP
3952     FETCH ahl_unit_effectivity_csr BULK COLLECT INTO l_ue_id_tbl, l_ue_status_tbl, l_related_ue_tbl,
3953                                                      l_orig_ue_tbl, l_prior_mr_header_tbl LIMIT l_buffer_limit;
3954     EXIT WHEN (l_ue_id_tbl.count = 0);
3955 
3956     IF G_DEBUG = 'Y' THEN
3957        AHL_DEBUG_PUB.debug ('Rows fetched for instance-mr is: ' || ahl_unit_effectivity_csr%ROWCOUNT);
3958     END IF;
3959 
3960     --dbms_output.put_line ('unit eff load i:' || l_unit_effectivity_tbl(i).unit_effectivity_id);
3961 
3962     FOR j IN l_ue_id_tbl.FIRST..l_ue_id_tbl.LAST LOOP
3963 
3964        l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status(l_ue_id_tbl(j));
3965 
3966        -- modified for bug# 9263774: calc due date for prior MR versions.
3967        -- for expired MRs, we need to select only those UEs that have WOs associated.
3968        IF (p_applicable_mrs_rec.expired_mr_flag = 'N' AND l_prior_mr_header_tbl(j) = p_applicable_mrs_rec.mr_header_id ) OR
3969           (p_applicable_mrs_rec.expired_mr_flag = 'N' AND l_visit_status IN ('RELEASED','CLOSED')) OR
3970           -- assigned to a visit
3971           (p_applicable_mrs_rec.expired_mr_flag = 'Y' AND l_visit_status IN ('RELEASED','CLOSED'))
3972        THEN
3973           i := i + 1;
3974           -- initialize
3975           l_unit_effectivity_tbl(i).unit_effectivity_id := l_ue_id_tbl(j);
3976           l_unit_effectivity_tbl(i).status_code := l_ue_status_tbl(j);
3977           l_unit_effectivity_tbl(i).related_ue_id := l_related_ue_tbl(j);
3978           l_unit_effectivity_tbl(i).originator_ue_id := l_orig_ue_tbl(j);
3979 
3980           -- added for bug# 9263774
3981           IF (l_prior_mr_header_tbl(j) <> p_applicable_mrs_rec.mr_header_id) THEN
3982              l_unit_effectivity_tbl(i).prior_mr_header_id := l_prior_mr_header_tbl(j);
3983           END IF;
3984 
3985           -- Call visit work package to get visit end date if unit effectivity has been assigned to a visit.
3986           AHL_UMP_UTIL_PKG.get_visit_details (l_unit_effectivity_tbl(i).unit_effectivity_id,
3987                                               l_visit_start_date,
3988                                               l_visit_end_date,
3989                                               l_visit_assign_code);
3990 
3991           IF (l_visit_end_date IS NOT NULL AND trunc(l_visit_end_date) >= trunc(sysdate)) THEN
3992               IF G_DEBUG = 'Y' THEN
3993                  AHL_DEBUG_PUB.Debug('Visit assigned:End Date:' || l_visit_end_date);
3994               END IF;
3995 
3996               l_unit_effectivity_tbl(i).visit_assign_flag := 'Y';
3997               l_unit_effectivity_tbl(i).visit_end_date := l_visit_end_date;
3998           ELSE
3999               l_unit_effectivity_tbl(i).visit_assign_flag := 'N';
4000               l_unit_effectivity_tbl(i).visit_end_date := null;
4001           END IF;
4002 
4003           -- Assign forecast sequence for single (non-group) MRs.
4004           IF (l_unit_effectivity_tbl(i).originator_ue_id IS NULL) THEN
4005               l_single_mr_seq := l_single_mr_seq + 1;
4006               l_unit_effectivity_tbl(i).forecast_sequence := l_single_mr_seq;
4007           END IF;
4008        END IF; -- expired flag
4009     END LOOP; -- l_ue_id_tbl
4010 
4011     -- clean up.
4012     l_ue_id_tbl.DELETE;
4013     l_ue_status_tbl.DELETE;
4014     l_related_ue_tbl.DELETE;
4015     l_orig_ue_tbl.DELETE;
4016 
4017   END LOOP;
4018   CLOSE ahl_unit_effectivity_csr;
4019 
4020   -- Added for 11.5.10+ enhancements for Unplanned MRs.
4021   -- Build table of visit end dates for Unplanned MRs.
4022   i := 0;
4023   FOR ahl_unplanned_MRs_rec IN ahl_unplanned_MRs_csr(p_applicable_mrs_rec.csi_item_instance_id,
4024                                                      p_applicable_mrs_rec.title,
4025                                                      G_application_usg_code)
4026   LOOP
4027     -- Get visit end date; unplanned MRs is always assigned to a visit.
4028     AHL_UMP_UTIL_PKG.get_visit_details (ahl_unplanned_MRs_rec.unit_effectivity_id,
4029                                         l_visit_start_date,
4030                                         l_visit_end_date,
4031                                         l_visit_assign_code);
4032     IF (l_visit_end_date IS NOT NULL) THEN
4033       i := i + 1;
4034       l_unplanned_MRs_tbl(i).unit_effectivity_id := ahl_unplanned_MRs_rec.unit_effectivity_id;
4035       l_unplanned_MRs_tbl(i).visit_end_date := trunc(l_visit_end_date);
4036     END IF;
4037 
4038   END LOOP; -- unplanned MRs.
4039 
4040   -- Check for group MR.
4041   OPEN group_check_csr(p_applicable_mrs_rec.csi_item_instance_id,
4042                        p_applicable_mrs_rec.mr_header_id);
4043   FETCH group_check_csr INTO l_junk;
4044   IF (group_check_csr%NOTFOUND) THEN
4045       --dbms_output.put_line ('group check false');
4046       group_check_flag := FALSE;
4047   ELSE
4048       group_check_flag := TRUE;
4049   END IF;
4050   CLOSE group_check_csr;
4051 
4052   -- process next due and repetivity.
4053   LOOP
4054 
4055      -- Added for SB Enh: If skip next due flag is set, then
4056      -- jump to repetivity calculation.
4057      IF (l_skip_next_due_flag = 'Y') THEN
4058         l_skip_next_due_flag := 'N';
4059         GOTO Calculate_Repetivity_DueDate;
4060      END IF;
4061 
4062      -- At this time assume, that there are no MRs with due dates less than the calc due date.
4063      l_grp_duedate_found := FALSE;
4064 
4065      -- Check output from calculate_due_date.
4066      IF (l_next_due_date_rec.due_date IS NOT NULL AND l_next_due_date_rec.FLEET_ASSO_REJECTED = 'N') THEN
4067 
4068         IF (l_next_due_flag) THEN
4069           -- read ahl_temp_unit_effectivity
4070           IF (l_last_due_date < l_next_due_date_rec.due_date) THEN
4071             OPEN ahl_temp_ue_csr1(p_applicable_mrs_rec.csi_item_instance_id,
4072                                   --p_applicable_mrs_rec.mr_header_id,
4073                                   p_applicable_mrs_rec.title,
4074                                   l_last_due_date,
4075                                   l_next_due_date_rec.due_date);
4076           ELSE
4077             OPEN ahl_temp_ue_csr1(p_applicable_mrs_rec.csi_item_instance_id,
4078                                   --p_applicable_mrs_rec.mr_header_id,
4079                                   p_applicable_mrs_rec.title,
4080                                   l_next_due_date_rec.due_date,
4081                                   l_last_due_date);
4082           END IF;
4083 
4084           FETCH ahl_temp_ue_csr1 INTO l_temp_grp_mr_rec;
4085           IF (ahl_temp_ue_csr1%FOUND) THEN
4086             --dbms_output.put_line ('exists grp rec' || l_temp_grp_mr_rec.due_date);
4087             /* there exists a group record with due date less than the calculated * one */
4088             l_grp_duedate_found := TRUE;
4089 
4090             -- added to fix bug# 6530920.
4091             -- this is to avoid creation of one child UMP row at the end of the
4092             -- planning window when the child MR and parent MR have the same interval
4093             -- threshold. Next due MR can be individual MR or part of a group MR.
4094             l_next_due_flag := FALSE;
4095 
4096           END IF;
4097           CLOSE ahl_temp_ue_csr1;
4098         ELSE
4099           -- read ahl_temp_unit_effectivity
4100           OPEN ahl_temp_ue_csr(p_applicable_mrs_rec.csi_item_instance_id,
4101                                --p_applicable_mrs_rec.mr_header_id,
4102                                p_applicable_mrs_rec.title,
4103                                l_last_due_date,
4104                                l_next_due_date_rec.due_date);
4105           FETCH ahl_temp_ue_csr INTO l_temp_grp_mr_rec;
4106           IF (ahl_temp_ue_csr%FOUND) THEN
4107                 --dbms_output.put_line ('exists grp rec' || l_temp_grp_mr_rec.due_date);
4108            /* there exists a group record with due date less than the calculated one */
4109             l_grp_duedate_found := TRUE;
4110           END IF;
4111           CLOSE ahl_temp_ue_csr;
4112         END IF;
4113         -- Added for 11.5.10+ Unplanned MRs enhancement.
4114         l_min_visit_date := NULL;
4115         IF (l_unplanned_MRs_tbl.COUNT > 0) THEN
4116           FOR i IN l_unplanned_MRs_tbl.FIRST..l_unplanned_MRs_tbl.LAST LOOP
4117             IF (l_unplanned_MRs_tbl(i).visit_end_date > l_last_due_date AND
4118                 l_unplanned_MRs_tbl(i).visit_end_date <= l_next_due_date_rec.due_date) THEN
4119                 IF (l_min_visit_date IS NULL) THEN
4120                    l_min_visit_date := l_unplanned_MRs_tbl(i).visit_end_date;
4121                 ELSIF (l_min_visit_date > l_unplanned_MRs_tbl(i).visit_end_date) THEN
4122                    l_min_visit_date := l_unplanned_MRs_tbl(i).visit_end_date;
4123                 END IF;
4124             END IF;
4125           END LOOP; -- l_unplanned_MRs_tbl.
4126         END IF; -- Count.
4127 
4128         -- Compare dates from ahl_temp_ue_csr and l_min_visit_date.
4129         IF (l_grp_duedate_found) THEN
4130            IF (l_min_visit_date IS NOT NULL) THEN
4131               IF (l_temp_grp_mr_rec.visit_end_date IS NOT NULL) THEN
4132                  IF (l_min_visit_date < l_temp_grp_mr_rec.visit_end_date) THEN
4133                     l_temp_grp_mr_rec.visit_end_date := l_min_visit_date;
4134                     l_temp_grp_mr_rec.due_date := NULL;
4135                  END IF;
4136               ELSIF (l_temp_grp_mr_rec.due_date IS NOT NULL) THEN
4137                  IF (l_min_visit_date < l_temp_grp_mr_rec.due_date) THEN
4138                     l_temp_grp_mr_rec.visit_end_date := l_min_visit_date;
4139                     l_temp_grp_mr_rec.due_date := NULL;
4140                  END IF;
4141               ELSE -- both due date and visit end dates are null.
4142                  l_temp_grp_mr_rec.visit_end_date := l_min_visit_date;
4143                  l_temp_grp_mr_rec.due_date := NULL;
4144               END IF;
4145            END IF; -- l_min_visit_date chk.
4146         ELSE
4147           IF (l_min_visit_date IS NOT NULL) THEN
4148             l_temp_grp_mr_rec.visit_end_date := l_min_visit_date;
4149             l_temp_grp_mr_rec.due_date := NULL;
4150             l_grp_duedate_found := TRUE;
4151             /*
4152             -- added to fix bug# 6530920.
4153             -- this is to avoid creation of one child UMP row at the end of the
4154             -- planning window when the child MR and parent MR have the same interval
4155             -- threshold. Next due MR can be individual MR or part of a group MR.
4156             l_next_due_flag := FALSE;
4157             */
4158           END IF;
4159         END IF; -- l_grp_duedate_found.
4160 
4161      END IF; -- l_next_due_date_rec.due_date chk.
4162 
4163      IF (l_next_due_date_rec.due_date IS NULL AND l_next_due_flag = TRUE and l_next_due_date_rec.FLEET_ASSO_REJECTED = 'N') OR  /* no repetivity as due_date is null */
4164         (NOT(l_grp_duedate_found) AND l_next_due_flag = TRUE and l_next_due_date_rec.FLEET_ASSO_REJECTED = 'N') OR
4165         (NOT(l_grp_duedate_found) AND l_next_due_date_rec.due_date IS NOT NULL AND l_next_due_flag = FALSE
4166           AND trunc(l_next_due_date_rec.due_date) <= trunc(nvl(l_mr_termination_date-1,G_last_day_of_window)))
4167      THEN
4168 
4169         -- R12:Added following logic to fix bug# 4224867.
4170         l_duplicate_MRs := 1; -- default to create only one occurrence of UMP for a day.
4171 
4172         -- find out if multiple UMPs need to be created for a given day.
4173         IF (l_next_due_date_rec.due_date IS NOT NULL AND l_last_due_date = l_next_due_date_rec.due_date
4174             AND l_next_due_date_rec.counter_remain IS NOT NULL AND l_next_due_date_rec.counter_remain > 0)
4175         THEN
4176            IF G_DEBUG = 'Y' THEN
4177               AHL_DEBUG_PUB.Debug('Check Multiple UMPs for due date:' || l_next_due_date_rec.due_date);
4178               AHL_DEBUG_PUB.Debug('Counter Remain:' || l_next_due_date_rec.counter_remain );
4179            END IF;
4180 
4181            -- get usage for due date.
4182            get_usage_for_date(l_next_due_date_rec.due_date,
4183                               l_next_due_date_rec.ctr_uom_code,
4184                               p_counter_rules_tbl,
4185                               l_usage_per_day);
4186 
4187            l_duplicate_MRs := trunc(l_usage_per_day/l_next_due_date_rec.counter_remain);
4188            IF (l_duplicate_MRs = 0) THEN
4189               l_duplicate_MRs := 1;
4190            END IF;
4191 
4192            IF G_DEBUG = 'Y' THEN
4193               AHL_DEBUG_PUB.Debug('get_usage_for_date:' || l_usage_per_day);
4194               AHL_DEBUG_PUB.Debug('l_duplicate_MRs:' || l_duplicate_MRs);
4195            END IF;
4196 
4197         END IF; -- l_next_due_date_rec.due_date IS NOT NULL
4198 
4199         -- Now loop to create temp unit effectivities l_duplicate_MRs times.
4200         FOR m IN 1..l_duplicate_MRs LOOP
4201         -- R12:End code added to fix bug# 4224867.
4202 
4203            -- construct ahl_unit_effectivity record and write into temporary table.
4204            l_new_unit_effectivity_rec := l_new_unit_effectivity_initrec; -- initialise.
4205 
4206            -- find the corressponding match in l_unit_effectivity_tbl if exists.
4207            IF (l_old_UE_forecast_found = TRUE) AND (l_unit_effectivity_tbl.EXISTS(l_old_UE_forecast_sequence+1))
4208            THEN
4209 
4210              -- loop to find the next individual MR.
4211              LOOP
4212                 l_old_UE_forecast_sequence := l_old_UE_forecast_sequence + 1;
4213                 IF (l_unit_effectivity_tbl(l_old_UE_forecast_sequence).forecast_sequence is not null) THEN
4214                     l_new_unit_effectivity_rec.unit_effectivity_id :=
4215                         l_unit_effectivity_tbl(l_old_UE_forecast_sequence).unit_effectivity_id;
4216                         -- added for SB Enh. We need to store visit end date for calculating 'terminated_by' and 'initiated_by' dates.
4217                         -- we only do for non-group UEs. Group case is handled in process_groupMR procedure
4218                         IF NOT(group_check_flag) THEN
4219                           l_new_unit_effectivity_rec.visit_end_date := trunc(l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_end_date);
4220                         END IF;
4221                         EXIT; -- matched record found.
4222                 ELSIF NOT(l_unit_effectivity_tbl.EXISTS(l_old_UE_forecast_sequence+1)) THEN
4223                         l_new_unit_effectivity_rec.unit_effectivity_id := null;
4224                         l_old_UE_forecast_sequence := -1;
4225                         l_old_UE_forecast_found := FALSE;
4226                         EXIT;
4227                 END IF;
4228              END LOOP;
4229 
4230            ELSE
4231              l_new_unit_effectivity_rec.unit_effectivity_id := null;
4232              l_old_UE_forecast_sequence := -1;
4233              l_old_UE_forecast_found := FALSE;
4234            END IF;
4235 
4236 
4237            -- Check for tolerance if visit has been assigned.
4238            IF (l_old_UE_forecast_found = TRUE) AND (l_next_due_date_rec.due_date IS NOT NULL) THEN
4239               IF (l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_assign_flag = 'Y') THEN
4240                  IF l_next_due_date_rec.tolerance_before IS NOT NULL THEN
4241                        IF ((trunc(l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_end_date))
4242                             < trunc(l_next_due_date_rec.earliest_due_date)) THEN
4243                             -- tolerance before.
4244                             l_next_due_date_rec.tolerance_flag := 'Y';
4245                             l_next_due_date_rec.message_code := 'TOLERANCE-BEFORE';
4246 
4247                        END IF;
4248                  END IF;
4249 
4250                  IF l_next_due_date_rec.tolerance_after IS NOT NULL THEN
4251                        IF ((trunc(l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_end_date))
4252                                > trunc(l_next_due_date_rec.latest_due_date)) THEN
4253                             -- tolerance after.
4254                             l_next_due_date_rec.tolerance_flag := 'Y';
4255                             l_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
4256 
4257                        END IF;
4258                  END IF;
4259               END IF;
4260            END IF;
4261 
4262 
4263            l_new_unit_effectivity_rec.due_date := l_next_due_date_rec.due_date;
4264            l_new_unit_effectivity_rec.mr_interval_id := l_next_due_date_rec.mr_interval_id;
4265            l_new_unit_effectivity_rec.mr_effectivity_id := l_next_due_date_rec.mr_effectivity_id;
4266            l_new_unit_effectivity_rec.due_counter_value := l_next_due_date_rec.due_at_counter_value;
4267            l_new_unit_effectivity_rec.tolerance_flag := l_next_due_date_rec.tolerance_flag;
4268            l_new_unit_effectivity_rec.tolerance_before := l_next_due_date_rec.tolerance_before;
4269            l_new_unit_effectivity_rec.tolerance_after := l_next_due_date_rec.tolerance_after;
4270            l_new_unit_effectivity_rec.message_code := l_next_due_date_rec.message_code;
4271            l_new_unit_effectivity_rec.csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
4272            l_new_unit_effectivity_rec.mr_header_id := p_applicable_mrs_rec.mr_header_id;
4273            l_new_unit_effectivity_rec.preceding_check_flag:= 'N';
4274            -- Added for ER# 2636001.
4275            l_new_unit_effectivity_rec.earliest_due_date := l_next_due_date_rec.earliest_due_date;
4276            l_new_unit_effectivity_rec.latest_due_date := l_next_due_date_rec.latest_due_date;
4277            -- Added to fix bug#2780716.
4278            l_new_unit_effectivity_rec.counter_id := l_next_due_date_rec.counter_id;
4279            -- JKJain, NR Analysis and Forecasting --Add fleet_id
4280            l_new_unit_effectivity_rec.fleet_header_id := l_next_due_date_rec.fleet_header_id ;
4281 
4282 
4283            -- increment forecast sequence.
4284            l_forecast_sequence := l_forecast_sequence + 1;
4285            l_new_unit_effectivity_rec.forecast_sequence := l_forecast_sequence;
4286 
4287            IF G_DEBUG = 'Y' THEN
4288               AHL_DEBUG_PUB.Debug('New Unit eff:' || l_new_unit_effectivity_rec.unit_effectivity_id);
4289               AHL_DEBUG_PUB.Debug('Old forecast seq:'|| l_old_UE_forecast_sequence);
4290            END IF;
4291 
4292            -- set repetivity based on next_due_flag.
4293            IF (l_next_due_flag) THEN
4294               l_new_unit_effectivity_rec.repetitive_mr_flag := 'N';
4295            ELSE
4296               l_new_unit_effectivity_rec.repetitive_mr_flag := 'Y';
4297            END IF;
4298 
4299            -- Update preceding MR details.
4300            IF (l_dependent_mr_flag AND l_forecast_sequence = 1) THEN
4301               l_new_unit_effectivity_rec.preceding_mr_header_id := p_applicable_mrs_rec.preceding_mr_header_id;
4302               l_new_unit_effectivity_rec.preceding_csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
4303               l_new_unit_effectivity_rec.preceding_forecast_seq := l_forecast_sequence;
4304               l_dependent_mr_flag := FALSE; -- this is required only for next due.
4305            END IF;
4306 
4307            -- added for SB Enh
4308            IF (p_applicable_mrs_rec.accomplish_trigger_type IN ('LOOP','CHAIN')) THEN
4309               l_new_unit_effectivity_rec.loop_chain_seq_num := p_applicable_mrs_rec.loop_chain_seq_num;
4310               l_new_unit_effectivity_rec.accomplish_trigger_type := p_applicable_mrs_rec.accomplish_trigger_type;
4311               l_new_unit_effectivity_rec.start_mr_header_id := p_applicable_mrs_rec.mr_header_id;
4312               l_new_unit_effectivity_rec.start_lc_ue_id := l_new_unit_effectivity_rec.unit_effectivity_id;
4313               IF G_DEBUG = 'Y' THEN
4314                 AHL_DEBUG_PUB.Debug('SB Changes:Forecast Seq:Seq Num:Trigger:startMR:' || l_forecast_sequence || ':' || l_new_unit_effectivity_rec.loop_chain_seq_num ||
4315                                     ':' || l_new_unit_effectivity_rec.accomplish_trigger_type || ':' || l_new_unit_effectivity_rec.start_mr_header_id);
4316               END IF;
4317            END IF;
4318 
4319            -- if UE ID belongs to prior mr version, call process_prior_mr
4320            IF (l_old_UE_forecast_found = TRUE AND l_unit_effectivity_tbl(l_old_UE_forecast_sequence).prior_mr_header_id IS NOT NULL) OR
4321               (l_old_UE_forecast_found = TRUE AND p_applicable_mrs_rec.expired_mr_flag = 'Y')
4322            THEN
4323 
4324               IF G_DEBUG = 'Y' THEN
4325                 AHL_DEBUG_PUB.Debug('Prior MR Header_id:' || l_unit_effectivity_tbl(l_old_UE_forecast_sequence).prior_mr_header_id);
4326               END IF;
4327 
4328               -- Process prior grpup MR or independent.
4329               Process_Prior_MR_Version (p_applicable_mrs_rec,
4330                                         l_new_unit_effectivity_rec,
4331                                         l_unit_effectivity_tbl,
4332                                         l_old_UE_forecast_sequence);
4333 
4334            -- write into temporary table.
4335            ELSIF NOT(group_check_flag) THEN
4336               -- create record in temporary table.
4337               Create_Temp_Unit_Effectivity (l_new_unit_effectivity_rec);
4338 
4339               IF G_DEBUG = 'Y' THEN
4340                  AHL_DEBUG_PUB.Debug('After create_temp_unit_effectivity');
4341               END IF;
4342 
4343            ELSE
4344               -- Process group MR.
4345               Process_groupMR (p_applicable_mrs_rec,
4346                                l_new_unit_effectivity_rec,
4347                                l_unit_effectivity_tbl,
4348                                l_old_UE_forecast_sequence);
4349            END IF;
4350 
4351            -- Added for SB Effectivity Enhancements
4352            -- Process loop or chain child MRs for the start MR's due date.
4353            IF (NOT(group_check_flag) AND (p_applicable_mrs_rec.accomplish_trigger_type IN ('LOOP','CHAIN'))) THEN
4354 
4355               IF G_DEBUG = 'Y' THEN
4356                  AHL_DEBUG_PUB.Debug('Before call to Process_Loop_Chain_MRs for last due date:' || l_last_due_date);
4357               END IF;
4358               Process_Loop_Chain_MRs (p_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
4359                                       p_repetivity_flag => 'Y',
4360                                       p_new_unit_effectivity_rec => l_new_unit_effectivity_rec,
4361                                       p_current_usage_tbl => p_current_usage_tbl,
4362                                       p_counter_rules_tbl => p_counter_rules_tbl,
4363                                       p_last_due_date => l_last_due_date,
4364                                       p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
4365                                       p_loop_chain_MR_tbl  => l_lc_mr_tbl,
4366                                       x_loop_due_date => l_loop_due_date,
4367                                       x_loop_last_due_date => l_loop_last_due_date,
4368                                       x_loop_last_counter_val_tbl => l_loop_last_counter_val_tbl
4369                                       --x_return_status => l_return_status
4370                                       );
4371 
4372               IF G_DEBUG = 'Y' THEN
4373                  AHL_DEBUG_PUB.Debug('After call to Process_Loop_Chain_MRs:loop_due_date:' || l_loop_due_date); -- || l_return_status);
4374               END IF;
4375            END IF;
4376 
4377            -- Set next due flag to FALSE after writing record into temporary unit_effectivity.
4378            IF (l_next_due_flag) THEN
4379                 l_next_due_flag := FALSE;
4380            END IF;
4381 
4382            -- Fix for bug# 6858788
4383            l_last_due_mr_interval_id := l_next_due_date_rec.mr_interval_id;
4384 
4385        END LOOP; -- m (Duplicate_MRs)
4386      END IF; -- l_next_due_date_rec.due_date IS NULL
4387 
4388      /* exit if one next due mr has been calculated and its due date is null
4389         or if next due date is beyond the rolling window date */
4390      -- JKJain, NR Analysis and Forecasting
4391      EXIT WHEN ((l_next_due_flag = FALSE AND l_next_due_date_rec.due_date IS NULL AND l_next_due_date_rec.FLEET_ASSO_REJECTED = 'N') OR
4392                 (l_next_due_flag = FALSE AND p_applicable_mrs_rec.show_repetitive_code = 'NEXT') OR
4393                 (l_next_due_date_rec.due_date IS NOT NULL AND p_applicable_mrs_rec.expired_mr_flag = 'N'
4394                  AND p_applicable_mrs_rec.effective_to IS NOT NULL AND trunc(l_next_due_date_rec.due_date) > trunc(p_applicable_mrs_rec.effective_to)) OR
4395                  -- added for bug# 9263774
4396                 (l_next_due_date_rec.due_date IS NOT NULL AND p_applicable_mrs_rec.expired_mr_flag = 'Y'
4397                  AND NOT(l_unit_effectivity_tbl.EXISTS(l_old_UE_forecast_sequence+1))) OR
4398                 (l_next_due_flag = FALSE AND trunc(l_next_due_date_rec.due_date) > trunc(G_last_day_of_window) AND p_applicable_mrs_rec.expired_mr_flag = 'N') OR
4399                 (l_mr_termination_date IS NOT NULL AND l_next_due_date_rec.due_date IS NOT NULL
4400                  AND trunc(l_next_due_date_rec.due_date) >= trunc(l_mr_termination_date))
4401                 -- added for SB Effectivity
4402                 OR (p_applicable_mrs_rec.accomplish_trigger_type = 'LOOP' AND l_loop_due_date IS NULL)
4403                );
4404 
4405      -- added for accomplish trigger type LOOP for SB rules
4406      IF (p_applicable_mrs_rec.accomplish_trigger_type = 'LOOP') THEN
4407         -- Reset l_last_due_mr_interval_id if duedate based on loop
4408         l_last_due_mr_interval_id := NULL;
4409 
4410         l_due_date := l_loop_due_date;
4411         l_last_due_date := l_loop_last_due_date;
4412         l_last_due_counter_val_tbl := l_loop_last_counter_val_tbl;
4413 
4414         IF G_DEBUG = 'Y' THEN
4415             AHL_DEBUG_PUB.Debug('Calc Loop dates:l_due_date:l_last_due_date:' || l_due_date || ':' || l_last_due_date);
4416         END IF;
4417 
4418      -- JKJain, NR Analysis and Forecasting
4419      ELSIF(l_next_due_date_rec.FLEET_ASSO_REJECTED = 'Y') THEN
4420         l_next_fleet_asso_date := null;
4421         OPEN get_next_fleet_asso_date(l_fleet_asso_rej_date);
4422         FETCH get_next_fleet_asso_date into l_next_fleet_asso_date;
4423         CLOSE get_next_fleet_asso_date;
4424 
4425         IF G_DEBUG = 'Y' THEN
4426           AHL_DEBUG_PUB.Debug('l_fleet_asso_rej_date =  ' || l_fleet_asso_rej_date);
4427           AHL_DEBUG_PUB.Debug('l_next_fleet_asso_date =  ' || l_next_fleet_asso_date);
4428         END IF;
4429 
4430         IF(l_next_fleet_asso_date IS NULL) THEN
4431           l_next_due_date_rec.FLEET_ASSO_REJECTED := 'N';
4432           EXIT;
4433         END IF;
4434         -- if on date :l_next_fleet_asso_date, no utilization exists, existing logic may not calculate further UEs.
4435          l_due_date := l_next_fleet_asso_date; -- removed -1, as it was resulting in infinite loop if usage > interval
4436      ELSE
4437        -- Set from l_next_due_date_rec.
4438        l_due_date := l_next_due_date_rec.due_date;
4439 
4440        -- If grp MR exists with due date less than calculated date, then re-calculate due date.
4441        IF (l_grp_duedate_found) THEN
4442 
4443          -- Set due date to be either visit_end_date or due_date.
4444          IF (l_temp_grp_mr_rec.visit_end_date IS NOT NULL) THEN
4445             l_due_date := l_temp_grp_mr_rec.visit_end_date;
4446          ELSE
4447             l_due_date := l_temp_grp_mr_rec.due_date;
4448          END IF;
4449 
4450          -- Fix for bug# 6858788. Reset l_last_due_mr_interval_id if duedate based on group MR.
4451          l_last_due_mr_interval_id := NULL;
4452 
4453          IF (G_DEBUG = 'Y') THEN
4454            AHL_DEBUG_PUB.Debug('group due date found');
4455            AHL_DEBUG_PUB.Debug('due date is ' || l_DUE_DATE);
4456          END IF;
4457        ELSE
4458 
4459          -- Set values for next repetivity calculation.
4460          IF (l_unit_effectivity_tbl.EXISTS(l_old_UE_forecast_sequence)) THEN
4461            IF (l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_assign_flag = 'Y') THEN
4462                 l_due_date := l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_end_date;
4463            END IF;
4464          END IF; -- l_unit_effectivity_tbl.EXISTS
4465        END IF; -- l_grp_duedate_found
4466      END IF; -- accomplish trigger type
4467 
4468      -- If due date is a past date, then set it to sysdate.
4469      -- This will happen only when calculating next-due date.
4470      IF (trunc(l_due_date) < trunc(sysdate)) THEN
4471        l_due_date := sysdate;
4472      END IF;
4473 
4474      IF G_DEBUG = 'Y' THEN
4475         AHL_DEBUG_PUB.Debug('Processing for repetivity');
4476         AHL_DEBUG_PUB.Debug('Before get_due_at_counter_values');
4477         AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
4478         AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
4479         IF (l_last_due_counter_val_tbl.COUNT > 0) THEN
4480           FOR i in l_last_due_counter_val_tbl.FIRST..l_last_due_counter_val_tbl.LAST LOOP
4481             AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_last_due_counter_val_tbl(i).counter_value || 'ID: ' || l_last_due_counter_val_tbl(i).counter_id);
4482           END LOOP;
4483         END IF;
4484      END IF;
4485 
4486      -- get all counter values as on l_due_date.
4487      Get_Due_at_Counter_Values (p_last_due_date => l_last_due_date,
4488                                 p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
4489                                 p_due_date => l_due_date,
4490                                 p_counter_rules_tbl => p_counter_rules_tbl,
4491                                 x_due_at_counter_val_tbl => l_due_at_counter_val_tbl,
4492                                 x_return_value => l_return_value);
4493      l_last_due_date := l_due_date;
4494      l_last_due_counter_val_tbl := l_due_at_counter_val_tbl;
4495 
4496      IF G_DEBUG = 'Y' THEN
4497         AHL_DEBUG_PUB.Debug('AFter get_due_at_counter_values');
4498         AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
4499         AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
4500         IF (l_due_at_counter_val_tbl.COUNT) > 0 THEN
4501            for i in l_due_at_counter_val_tbl.FIRST..l_due_at_counter_val_tbl.LAST LOOP
4502              AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_due_at_counter_val_tbl(i).counter_value || 'ID: ' || l_due_at_counter_val_tbl(i).counter_id);
4503            end loop;
4504         END IF;
4505      END IF;
4506 
4507      IF NOT(l_return_value) THEN
4508         EXIT; /* no forecast available so exit */
4509      END IF;
4510 
4511     -- goto used by loop and chain processing.
4512     <<Calculate_Repetivity_DueDate>>
4513 
4514      -- Calculate next due date.
4515      Calculate_Due_Date (p_repetivity_flag => 'Y',
4516                          p_applicable_mrs_rec => p_applicable_mrs_rec,
4517                          p_current_usage_tbl => p_current_usage_tbl,
4518                          p_counter_rules_tbl => p_counter_rules_tbl,
4519                          p_last_due_date => l_last_due_date,
4520                          p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
4521                          p_mr_accomplish_exists  => l_mr_accomplish_exists,
4522                          p_last_due_mr_interval_id => l_last_due_mr_interval_id,
4523                          x_next_due_date_rec => l_next_due_date_rec);
4524 
4525      IF G_DEBUG = 'Y' THEN
4526         AHL_DEBUG_PUB.Debug('aft calculate_due_date - repetivity');
4527         AHL_DEBUG_PUB.Debug('due date is ' || l_next_due_date_rec.DUE_DATE);
4528         AHL_DEBUG_PUB.Debug('earliest due date is ' || l_next_due_date_rec.EARLIEST_DUE_DATE);
4529         AHL_DEBUG_PUB.Debug('latest due date is ' || l_next_due_date_rec.latest_due_date);
4530         AHL_DEBUG_PUB.Debug('FLEET_ASSO_REJECTED = ' || l_next_due_date_rec.FLEET_ASSO_REJECTED);
4531      END IF;
4532 
4533      -- JKJain, NR Analysis and Forecasting
4534      IF(l_next_due_date_rec.FLEET_ASSO_REJECTED = 'Y' AND l_next_due_date_rec.DUE_DATE IS NOT NULL) THEN
4535         l_fleet_asso_rej_date := l_next_due_date_rec.DUE_DATE;
4536         l_next_due_date_rec.DUE_DATE := null;
4537      END IF;
4538 
4539      -- Check if calculated date is same as last due date. If they are the same then, add one day.
4540      IF (l_next_due_date_rec.due_date IS NOT NULL) THEN
4541         IF (trunc(l_last_due_date) = trunc(l_next_due_date_rec.due_date)) THEN
4542                l_next_due_date_rec.due_date := l_next_due_date_rec.due_date + 1;
4543                l_next_due_date_rec.EARLIEST_DUE_DATE := NULL;
4544                l_next_due_date_rec.latest_due_date := NULL;
4545 
4546                IF G_DEBUG = 'Y' THEN
4547                  AHL_DEBUG_PUB.Debug('Adding one day to l_next_due_date_rec.due_date:' || l_next_due_date_rec.due_date);
4548                END IF;
4549 
4550             --IF G_DEBUG = 'Y' THEN
4551             --   AHL_DEBUG_PUB.Debug('Exiting build effectivity as last due = due date');
4552             --END IF;
4553             --EXIT;
4554         END IF;
4555      END IF;
4556 
4557   END LOOP;
4558 
4559   -- update ahl_applicable MRs table after processing complete.
4560   UPDATE AHL_APPLICABLE_MRS
4561      SET process_status_flag = 'Y',
4562          accomplished_ue_id = l_accomplished_ue_id
4563   WHERE mr_header_id = p_applicable_mrs_rec.mr_header_id
4564     AND csi_item_instance_id = p_applicable_mrs_rec.csi_item_instance_id;
4565 
4566 
4567   -- Fix for bug# 6711228.
4568   <<process_preceding_mr>>
4569   -- Process preceding MRs.
4570   IF ((p_applicable_mrs_rec.implement_status_code = 'MANDATORY') OR
4571       --(l_mr_accomplish_exists)) THEN
4572       -- changing check from l_mr_accomplish_exists to l_accomplished_ue_id as l_mr_accomplish_exists is true when open deferral exists.
4573       (l_accomplished_ue_id IS NOT NULL)) THEN
4574       Process_PrecedingMR (p_applicable_mrs_rec => p_applicable_mrs_rec,
4575                            p_counter_rules_tbl  => p_counter_rules_tbl,
4576                            p_current_usage_tbl  => p_current_usage_tbl);
4577 
4578   END IF;
4579 
4580 END Build_Effectivity;
4581 
4582 --------------------------------------------------------------------------------------
4583 -- Calculate due date for the item instance and mr using current usage, counter rules,
4584 -- last accomplishment counters and forecast (defined in global variable).
4585 -- Added parameter p_dependent_mr_flag to fix bug# 6711228 used when
4586 -- calculating nextdue date.
4587 -- Added parameters p_mr_accomplish_exists and p_last_due_mr_interval_id to fix bug# 6858788.
4588 PROCEDURE Calculate_Due_Date ( p_repetivity_flag    IN VARCHAR2 := 'Y',
4589                                p_applicable_mrs_rec IN applicable_mrs_rec_type,
4590                                p_current_usage_tbl  IN counter_values_tbl_type,
4591                                p_counter_rules_tbl  IN counter_rules_tbl_type,
4592                                p_last_due_date      IN DATE,
4593                                p_last_due_counter_val_tbl IN counter_values_tbl_type,
4594                                p_dependent_mr_flag  IN BOOLEAN := FALSE,
4595                                p_mr_accomplish_exists IN BOOLEAN,
4596                                p_last_due_mr_interval_id IN NUMBER := NULL,
4597                                x_next_due_date_rec  OUT NOCOPY next_due_date_rec_type)
4598 
4599 IS
4600 
4601   -- Read all effectivities for the mr and item instance.
4602   -- JKJain, NR Analysis and Forecasting
4603   CURSOR ahl_applicable_csr (p_instance_id IN NUMBER,
4604                              p_mr_header_id IN NUMBER) IS
4605      SELECT DISTINCT mr.mr_effectivity_id, threshold_date,eff.fleet_header_id
4606      FROM ahl_applicable_mrs mr, ahl_mr_effectivities eff
4607      WHERE mr.mr_effectivity_id = eff.mr_effectivity_id AND
4608            csi_item_instance_id = p_instance_id AND
4609            mr.mr_header_id = p_mr_header_id;
4610 
4611   -- read all intervals for the effectivity id.
4612   CURSOR ahl_mr_interval_csr (p_mr_effectivity_id IN NUMBER,
4613                               --p_counter_id  IN NUMBER,
4614                               p_counter_name  IN VARCHAR2,
4615                               p_counter_value IN NUMBER,
4616                               p_start_date IN DATE) IS
4617      SELECT INT.mr_interval_id, INT.start_date, INT.stop_date,
4618             INT.start_value, INT.stop_value, INT.counter_id,
4619             INT.interval_value, INT.tolerance_after, INT.tolerance_before,
4620             INT.earliest_due_value, -- added for bug# 6358940.
4621             INT.calc_duedate_rule_code  -- added for ER 7415856
4622      --Replaced cs_counters_v with cs_counters to fix perf bug# 3786647.
4623      --FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
4624      --replaced cs_counters CTR with csi_counter_template_vl
4625      --and cs_counters CN with csi_counters_vl CN to fix bug# 5918525.
4626      FROM   ahl_mr_intervals INT, csi_counter_template_vl CTR --, csi_counters_vl CN
4627      WHERE  INT.counter_id = CTR.counter_id AND
4628             --CTR.name = CN.name AND -- bug# 5918525.
4629             --CTR.name = CN.counter_template_name AND -- removed for perf fix.
4630             CTR.name = p_counter_name AND
4631             INT.mr_effectivity_id = p_mr_effectivity_id AND
4632             --CN.counter_id = p_counter_id AND -- removed for perf fix.
4633             (
4634               ( (nvl(start_value, p_counter_value+1) <= p_counter_value AND
4635                  --p_counter_value < nvl(stop_value, p_counter_value+1)) OR
4636                  -- Fix for bug# 3482307.
4637                  p_counter_value <= nvl(stop_value, p_counter_value+1)) OR
4638                 (trunc(nvl(start_date, p_start_date+1)) <= trunc(p_start_date) AND
4639                  --trunc(p_start_date) < trunc(nvl(stop_date, p_start_date+1)) )
4640                  -- Fix for bug# 3482307.
4641                  trunc(p_start_date) <= trunc(nvl(stop_date, p_start_date+1)) )
4642               )
4643              OR
4644                /* pick records with no start/stop values/dates. */
4645               (start_value IS NULL AND stop_value IS NULL AND start_date IS NULL AND stop_date IS NULL
4646                AND interval_value IS NOT NULL)
4647             );
4648 
4649   -- get the unit effectivity record for init-due for this mr and item.
4650   -- modified query to fix bug# 9264774. Replaced input p_mr_header_id with p_title.
4651   CURSOR ahl_init_due_csr (p_csi_item_instance_id IN NUMBER,
4652                            p_title                IN VARCHAR2)  IS
4653     SELECT ud.set_due_date, ue.unit_effectivity_id, ud.unit_deferral_id
4654     --FROM ahl_unit_effectivities_app_v ue, ahl_unit_deferrals_vl ud
4655     FROM ahl_unit_effectivities_b ue, ahl_unit_deferrals_b ud
4656     WHERE ue.unit_effectivity_id = ud.unit_effectivity_id AND
4657           ud.unit_deferral_type = 'INIT-DUE' AND
4658           ue.csi_item_instance_id = p_csi_item_instance_id AND
4659           ue.mr_header_id IN (select mr_header_id from ahl_mr_headers_b mr where mr.title = p_title) AND
4660           ue.status_code = 'INIT-DUE';
4661 
4662   -- get all init-due counter records setup for this unit effectivity.
4663   CURSOR ahl_unit_thresholds_csr (p_unit_deferral_id IN NUMBER) IS
4664     SELECT counter_id, counter_value
4665     FROM ahl_unit_thresholds
4666     WHERE unit_deferral_id = p_unit_deferral_id;
4667 
4668   -- added for performance fix bug# 6893404.
4669   CURSOR get_interval_ctr_name(p_mr_effectivity_id IN NUMBER) IS
4670     SELECT DISTINCT name counter_name
4671     FROM ahl_mr_intervals int, csi_counter_template_vl ctr
4672     WHERE int.mr_effectivity_id = p_mr_effectivity_id
4673       AND int.counter_id = ctr.counter_id;
4674 
4675   --
4676   DUE_DATE_NULL EXCEPTION ;
4677   NO_VALID_INTERVAL EXCEPTION;
4678 
4679   l_next_due_date_rec  Next_Due_Date_Rec_Type;
4680 
4681   l_due_date DATE; /* due date returned back after forecast calculation */
4682   l_calc_due_date  DATE; /* next due date that will be returned by this procedure */
4683   l_adjusted_due_date DATE; /* adjusted due date returned in case of overflow into next interval */
4684   l_adjusted_int_value NUMBER; /* adjusted interval value returned in case of overflow into next interval */
4685   l_nxt_interval_found BOOLEAN;
4686 
4687   l_mr_interval_id  NUMBER; /* the interval id that triggered this mr due date */
4688   l_due_at_counter_value NUMBER; /* next due counter value */
4689   l_counter_remain NUMBER;
4690   l_mr_interval_found BOOLEAN; /*indicates if at one mr_interval exists for the effectivity */
4691 
4692   -- modified to fix bug# 6725769.
4693   --l_old_mr_interval_found  BOOLEAN;
4694   l_old_ctr_interval_found  BOOLEAN;
4695   -- added to fix bug# 6725769.
4696   l_ctr_interval_found      BOOLEAN; -- indicates if a mr interval was found for a counter.
4697 
4698   l_temp_counter_tbl  counter_values_tbl_type;
4699   l_counter_value  NUMBER;
4700   l_current_ctr_value NUMBER;
4701   l_set_due_date  DATE;
4702   l_threshold_date  DATE;
4703   l_start_date DATE;
4704   l_start_int_match_at_ctr  NUMBER; /* interval match start counter value. */
4705 
4706   l_mr_interval_rec ahl_mr_interval_csr%ROWTYPE;
4707 
4708   l_unit_effectivity_id NUMBER;
4709   k   NUMBER; /* for l_temp_counter_tbl */
4710 
4711   l_return_val   BOOLEAN; -- return status indicator.
4712   l_counter_read_date   DATE;
4713   l_unit_deferral_id    NUMBER;
4714 
4715   l_reset_start_value_flag  BOOLEAN;
4716   l_due_counter_tbl         counter_values_tbl_type;
4717   l_last_due_counter_tbl    counter_values_tbl_type;
4718 
4719   l_adjusted_due_ctr        NUMBER;
4720 
4721   -- added to fix calculation of before and after tolerance dates when
4722   -- uom_remain < 0.
4723   l_calc_due_date_ctr_id    NUMBER;
4724 
4725   -- added to fix bug# 6358940.
4726   l_reset_start_date_flag   BOOLEAN;
4727 
4728   -- added to fix perf bug# 6893404.
4729   i  NUMBER; -- setting l_temp_counter_tbl index.
4730 
4731   -- JKJain, NR Analysis and Forecasting
4732   l_fleet_header_id NUMBER ;
4733   l_earliest_due_date DATE;
4734   l_fleet_reject_due_date DATE;
4735 
4736 BEGIN
4737 
4738   IF G_DEBUG = 'Y' THEN
4739         AHL_DEBUG_PUB.Debug('In calculate due date');
4740   END IF;
4741 
4742   -- Initialize due date.
4743   l_calc_due_date := null;
4744   l_calc_due_date_ctr_id := null;
4745 
4746   -- Initialize OUT record.
4747   x_next_due_date_rec := l_next_due_date_rec;
4748   -- JKJain, NR Analysis and Forecasting
4749   x_next_due_date_rec.FLEET_ASSO_REJECTED := 'N';
4750 
4751   IF (p_repetivity_flag = 'N') THEN
4752     l_temp_counter_tbl := p_current_usage_tbl;
4753   ELSE
4754     l_temp_counter_tbl := p_last_due_counter_val_tbl;
4755   END IF;
4756 
4757   -- Fix for bug# 6358940. Due Date should be based only on init-due if it
4758   -- exists. MR thresholds should not be used.
4759   -- Calculate due date based on init-due defination; if exists.
4760   -- skip init-due check for child loop or chain MRs
4761   IF (p_repetivity_flag = 'N') THEN
4762      --dbms_output.put_line ('in INIT-due part');
4763 
4764      -- Check if there is any init-due record for this item instance and mr exists.
4765      OPEN ahl_init_due_csr(p_applicable_mrs_rec.csi_item_instance_id,
4766                            --p_applicable_mrs_rec.mr_header_id);
4767                            p_applicable_mrs_rec.title);
4768      FETCH ahl_init_due_csr INTO l_set_due_date, l_unit_effectivity_id, l_unit_deferral_id;
4769      IF (ahl_init_due_csr%FOUND) THEN
4770 
4771         IF G_DEBUG = 'Y' THEN
4772           AHL_DEBUG_PUB.Debug('INIT-Due processing: Set due_date:UE_ID:' || l_set_due_date || ':' || l_unit_effectivity_id);
4773         END IF;
4774         --dbms_output.put_line ('in INIT-due part: due_date' || l_set_due_date);
4775 
4776         FOR threshold_rec IN ahl_unit_thresholds_csr (l_unit_deferral_id)
4777         LOOP
4778           -- for init due, ctr_value_type_code is always 'defer_to'.
4779           l_due_at_counter_value := threshold_rec.counter_value;
4780           l_counter_remain := 0;
4781           l_current_ctr_value := 0;
4782           k := 0;
4783           -- search for the current counter value in l_current_usage_tbl.
4784           IF (l_temp_counter_tbl.COUNT > 0) THEN
4785             FOR i IN l_temp_counter_tbl.FIRST..l_temp_counter_tbl.LAST LOOP
4786                IF (l_temp_counter_tbl(i).counter_id = threshold_rec.counter_id) THEN
4787                   l_current_ctr_value := l_temp_counter_tbl(i).counter_value;
4788                   k := i;
4789                   EXIT;
4790                END IF;
4791             END LOOP;
4792             l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
4793           END IF;
4794 
4795           -- calculate due date from forecast.
4796           IF (l_counter_remain > 0) THEN
4797             -- get date from forecast.
4798             get_date_from_uf(l_counter_remain,
4799                              l_temp_counter_tbl(k).uom_code,
4800                              p_counter_rules_tbl,
4801                              null, -- start date = sysdate
4802                              l_due_date);
4803           ELSIF (l_counter_remain < 0) THEN
4804             -- Due date = counter reading date.
4805              get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
4806                                        p_counter_id           => l_temp_counter_tbl(k).counter_id,
4807                                        p_counter_value        => l_due_at_counter_value,
4808                                        x_ctr_record_date      => l_counter_read_date,
4809                                        x_return_val           => l_return_val);
4810 
4811              IF NOT(l_return_val) THEN
4812                 l_due_date := sysdate;
4813              ELSE
4814                 l_due_date := l_counter_read_date;
4815              END IF;
4816 
4817           ELSIF (l_counter_remain = 0) THEN  -- due_date = sysdate
4818             --dbms_output.put_line ('counter remain less than zero');
4819             l_due_date := sysdate;
4820           END IF;
4821 
4822           -- Compare with whichever first code and set l_calc_due_date.
4823           IF (l_due_date IS NULL) THEN
4824              -- Added to fix bug# 6907562.
4825              IF (validate_for_duedate_reset(l_due_date,
4826                                             l_counter_remain,
4827                                             l_calc_due_date,
4828                                             l_calc_due_date_ctr_id,
4829                                             x_next_due_date_rec.counter_remain)) = 'Y' THEN
4830 
4831                --dbms_output.put_line ('due date null');
4832                l_calc_due_date := l_due_date;
4833                x_next_due_date_rec.due_date := null;
4834                x_next_due_date_rec.tolerance_after := null;
4835                x_next_due_date_rec.tolerance_before := null;
4836                x_next_due_date_rec.mr_interval_id := null;
4837                x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4838                x_next_due_date_rec.mr_effectivity_id := null;
4839                x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4840                x_next_due_date_rec.last_ctr_value := null;
4841                x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
4842                x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
4843                x_next_due_date_rec.counter_remain := l_counter_remain;
4844                l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
4845                -- fix for bug# 6907562. Loop to next threshold when due date is null.
4846                --EXIT;
4847              END IF;
4848           ELSE
4849             IF (l_calc_due_date IS NULL) THEN
4850                -- Added to fix bug# 6907562.
4851                IF (validate_for_duedate_reset(l_due_date,
4852                                               l_counter_remain,
4853                                               l_calc_due_date,
4854                                               l_calc_due_date_ctr_id,
4855                                               x_next_due_date_rec.counter_remain)) = 'Y' THEN
4856                  --dbms_output.put_line ('calc due date null');
4857                  l_calc_due_date := l_due_date;
4858                  x_next_due_date_rec.due_date := l_due_date;
4859                  x_next_due_date_rec.tolerance_after := null;
4860                  x_next_due_date_rec.tolerance_before := null;
4861                  x_next_due_date_rec.mr_interval_id := null;
4862                  x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4863                  x_next_due_date_rec.mr_effectivity_id := null;
4864                  x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4865                  x_next_due_date_rec.last_ctr_value := null;
4866                  x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
4867                  x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
4868                  x_next_due_date_rec.counter_remain := l_counter_remain;
4869                  l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
4870                END IF;
4871             ELSE
4872                IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
4873                  -- Check due date based on whichever_first_code.
4874                  -- if dates are equal, switch based on lower uom remain value. (bug# 6907562).
4875                  IF (l_calc_due_date > l_due_date) OR
4876                     (trunc(l_calc_due_date) = trunc(l_due_date) AND l_counter_remain IS NOT NULL
4877                         AND x_next_due_date_rec.counter_remain IS NOT NULL
4878                         AND l_counter_remain < x_next_due_date_rec.counter_remain) THEN
4879                       l_calc_due_date := l_due_date;
4880                       x_next_due_date_rec.due_date := l_due_date;
4881                       x_next_due_date_rec.tolerance_after := null;
4882                       x_next_due_date_rec.tolerance_before := null;
4883                       x_next_due_date_rec.mr_interval_id := null;
4884                       x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4885                       x_next_due_date_rec.mr_effectivity_id := null;
4886                       x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4887                       x_next_due_date_rec.last_ctr_value := null;
4888                       x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
4889                       x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
4890                       x_next_due_date_rec.counter_remain := l_counter_remain;
4891                       l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
4892 
4893                     END IF;
4894                  ELSE  -- whichever_first_code = 'LAST'
4895                     -- if dates are equal, switch based on higher uom remain value. (bug# 6907562).
4896                     IF (l_calc_due_date < l_due_date) OR
4897                        (trunc(l_calc_due_date) = trunc(l_due_date) AND l_counter_remain IS NOT NULL
4898                         AND x_next_due_date_rec.counter_remain IS NOT NULL
4899                         AND l_counter_remain > x_next_due_date_rec.counter_remain) THEN
4900                         --dbms_output.put_line ('set due date');
4901                         l_calc_due_date := l_due_date;
4902                         x_next_due_date_rec.due_date := l_due_date;
4903                         x_next_due_date_rec.tolerance_after := null;
4904                         x_next_due_date_rec.tolerance_before := null;
4905                         x_next_due_date_rec.mr_interval_id := null;
4906                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4907                         x_next_due_date_rec.mr_effectivity_id := null;
4908                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4909                         x_next_due_date_rec.last_ctr_value := null;
4910                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
4911                         x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
4912                         x_next_due_date_rec.counter_remain := l_counter_remain;
4913                         l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
4914 
4915                     END IF;
4916                  END IF; -- applicable_mrs_rec
4917             END IF; -- calc_due_date null
4918           END IF; -- l_due_date IS NULL
4919         END LOOP; -- set_threshold_rec
4920 
4921         -- Check for set due date.
4922         IF (l_set_due_date IS NOT NULL) THEN
4923               IF (l_calc_due_date IS NULL) THEN
4924                  -- added to fix bug# 6907562.
4925                  -- reset only when l_calc_due_date_ctr_id is also null.
4926                  IF (l_calc_due_date_ctr_id IS NULL) THEN
4927                    l_calc_due_date := l_set_due_date;
4928                    x_next_due_date_rec.due_date := l_set_due_date;
4929                    x_next_due_date_rec.tolerance_after := null;
4930                    x_next_due_date_rec.tolerance_before := null;
4931                    x_next_due_date_rec.mr_effectivity_id := null;
4932                    x_next_due_date_rec.due_at_counter_value := null;
4933                    x_next_due_date_rec.current_ctr_value := null;
4934                    x_next_due_date_rec.last_ctr_value := null;
4935                    x_next_due_date_rec.mr_interval_id := null;
4936                    x_next_due_date_rec.ctr_uom_code := null;
4937                    x_next_due_date_rec.counter_id := null;
4938                    x_next_due_date_rec.counter_remain := null;
4939                    l_calc_due_date_ctr_id := null;
4940                  END IF;
4941               ELSE
4942                  IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
4943                      IF (l_calc_due_date > l_set_due_date) THEN
4944                        --dbms_output.put_line ('set due da te');
4945                        l_calc_due_date := l_set_due_date;
4946                        x_next_due_date_rec.due_date := l_set_due_date;
4947                        x_next_due_date_rec.tolerance_after := null;
4948                        x_next_due_date_rec.tolerance_before := null;
4949                        x_next_due_date_rec.mr_interval_id := null;
4950                        x_next_due_date_rec.due_at_counter_value := null;
4951                        x_next_due_date_rec.mr_effectivity_id := null;
4952                        x_next_due_date_rec.current_ctr_value := null;
4953                        x_next_due_date_rec.last_ctr_value := null;
4954                        x_next_due_date_rec.ctr_uom_code := null;
4955                        x_next_due_date_rec.counter_id := null;
4956                        x_next_due_date_rec.counter_remain := null;
4957                        l_calc_due_date_ctr_id := null;
4958 
4959                      END IF;
4960                  ELSE
4961                     -- Check for set due date.
4962                     IF (l_calc_due_date < l_set_due_date) THEN
4963                         l_calc_due_date := l_set_due_date;
4964                         x_next_due_date_rec.due_date := l_set_due_date;
4965                         x_next_due_date_rec.tolerance_after := null;
4966                         x_next_due_date_rec.tolerance_before := null;
4967                         x_next_due_date_rec.mr_interval_id := null;
4968                         x_next_due_date_rec.due_at_counter_value := null;
4969                         x_next_due_date_rec.mr_effectivity_id := null;
4970                         x_next_due_date_rec.current_ctr_value := null;
4971                         x_next_due_date_rec.last_ctr_value := null;
4972                         x_next_due_date_rec.ctr_uom_code := null;
4973                         x_next_due_date_rec.counter_id := null;
4974                         x_next_due_date_rec.counter_remain := null;
4975                         l_calc_due_date_ctr_id := null;
4976 
4977                     END IF;
4978                  END IF; -- applicable
4979                END IF;
4980          END IF;  -- set due date
4981         -- If due date is less than sysdate, then flag tolerance.
4982         IF (x_next_due_date_rec.due_date IS NOT NULL) AND
4983            (trunc(x_next_due_date_rec.due_date) < trunc(sysdate)) THEN
4984             x_next_due_date_rec.tolerance_flag := 'Y';
4985             x_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
4986         END IF;
4987         CLOSE ahl_init_due_csr;
4988         RETURN; -- exit calculation.
4989      END IF; -- init_due_csr
4990      CLOSE ahl_init_due_csr;
4991   END IF; -- repetitive_flag
4992 
4993   -- Loop through each effectivity record.
4994   <<mr_effectivity_loop>>
4995   FOR effectivity_rec IN ahl_applicable_csr(p_applicable_mrs_rec.csi_item_instance_id,
4996                                             p_applicable_mrs_rec.mr_header_id)
4997   LOOP
4998 
4999      IF G_DEBUG = 'Y' THEN
5000         AHL_DEBUG_PUB.Debug('eff ID' || effectivity_rec.mr_effectivity_id );
5001      END IF;
5002 
5003      l_threshold_date := effectivity_rec.threshold_date;
5004      l_mr_interval_found := FALSE;
5005      -- JKJain, NR Analysis and Forecasting
5006      l_fleet_header_id := effectivity_rec.fleet_header_id;
5007 
5008      --l_old_mr_interval_found := FALSE;
5009 
5010      -- Loop through all counters in l_temp_counter_tbl.
5011      IF (l_temp_counter_tbl.COUNT > 0) THEN
5012 
5013        -- instead of looping through all counters, loop through interval counters
5014        -- and match counter name in l_temp_counter_tbl and set index i.
5015        --FOR i IN l_temp_counter_tbl.FIRST..l_temp_counter_tbl.LAST LOOP
5016 
5017        FOR ctr_name_rec IN get_interval_ctr_name(effectivity_rec.mr_effectivity_id)  LOOP
5018          -- set l_temp_counter_tbl row for matching counter.
5019          i := -1;
5020 
5021          FOR k IN l_temp_counter_tbl.FIRST..l_temp_counter_tbl.LAST LOOP
5022            IF (l_temp_counter_tbl(k).counter_name = ctr_name_rec.counter_name) THEN
5023                i := k;
5024                EXIT;
5025            END IF;
5026          END LOOP;
5027 
5028          -- if no match for interval counter then
5029          -- proceed to next counter.
5030          IF (i = -1) THEN
5031            GOTO next_counter_loop;
5032          END IF;
5033 
5034          -- Added for fix 6725769.
5035          l_ctr_interval_found := FALSE;
5036          l_old_ctr_interval_found := FALSE;
5037 
5038          -- find the counter value from p_last_due_counter_val_tbl
5039          -- for this counter id.
5040          IF (p_repetivity_flag = 'N') THEN
5041             -- set current ctr value from l_current_usage_tbl.
5042             l_start_date := sysdate; /* interval start/stop dates validation on sysdate */
5043             l_current_ctr_value := l_temp_counter_tbl(i).counter_value;
5044             l_counter_value := 0; /* initialize last due counter value */
5045 
5046             IF (p_last_due_counter_val_tbl.COUNT > 0) THEN
5047                 --dbms_output.put_line ('in last due counter loop-count'||p_last_due_counter_val_tbl.COUNT );
5048               FOR j IN p_last_due_counter_val_tbl.FIRST..p_last_due_counter_val_tbl.LAST
5049               LOOP
5050                 --dbms_output.put_line ('in last due counter loop');
5051                 IF (p_last_due_counter_val_tbl(j).counter_id = l_temp_counter_tbl(i).counter_id) THEN
5052                     -- counter value will be just from last due.
5053                     l_counter_value := p_last_due_counter_val_tbl(j).counter_value;
5054 
5055                     -- start interval matching at last accomplishment data as it is available.
5056                     l_start_int_match_at_ctr := l_counter_value;
5057                 END IF;
5058               END LOOP;
5059             ELSE
5060               -- start interval matching at current counter value as last accomplishment data
5061               -- is not available.
5062               l_start_int_match_at_ctr := l_current_ctr_value;
5063             END IF; /* count > 0 */
5064             --dbms_output.put_line ('SKR_counter_value' || l_counter_value);
5065          ELSE
5066            -- For repetity, set current_ctr_value to zero.
5067            -- Set l_counter_value from l_temp_counter_tbl.
5068            l_counter_value := l_temp_counter_tbl(i).counter_value;
5069            l_current_ctr_value := 0; /* initialize current usage on counter */
5070            l_start_date := p_last_due_date; /* interval start/stop dates validation on last due date */
5071 
5072            -- For repetity, l_start_int_match_at_ctr is last counter value.
5073            l_start_int_match_at_ctr := l_counter_value;
5074 
5075          END IF; /* repetivity */
5076 
5077          --dbms_output.put_line ('CounterID' || l_temp_counter_tbl(i).counter_id);
5078          --dbms_output.put_line ('counter_value' || l_counter_value);
5079 
5080          -- For each effectivity, loop through mr intervals.
5081          FOR mr_interval_rec IN ahl_mr_interval_csr(effectivity_rec.mr_effectivity_id,
5082                                                       --l_temp_counter_tbl(i).counter_id,
5083                                                       l_temp_counter_tbl(i).counter_name,
5084                                                       l_start_int_match_at_ctr,
5085                                                       l_start_date)
5086          LOOP
5087 
5088            -- reset loop variables.
5089            l_old_ctr_interval_found := l_ctr_interval_found;
5090            l_reset_start_value_flag := FALSE;
5091            l_reset_start_date_flag  := FALSE;
5092 
5093            -- added to fix bug#	6725769
5094            IF NOT(l_ctr_interval_found) THEN
5095              l_ctr_interval_found := TRUE; /* found a interval. */
5096            END IF;
5097 
5098            --l_mr_interval_found := TRUE; /* found a interval. */
5099            l_mr_interval_rec := mr_interval_rec;
5100 
5101            IF G_DEBUG = 'Y' THEN
5102              AHL_DEBUG_PUB.Debug('In interval table loop');
5103              AHL_DEBUG_PUB.Debug('mr interval:' || l_mr_interval_rec.mr_interval_id );
5104              AHL_DEBUG_PUB.Debug('start value:' ||l_mr_interval_rec.start_value);
5105              AHL_DEBUG_PUB.Debug('stop value:' ||l_mr_interval_rec.stop_value);
5106              AHL_DEBUG_PUB.Debug('start date:' ||l_mr_interval_rec.start_date);
5107              AHL_DEBUG_PUB.Debug('stop date:' ||l_mr_interval_rec.stop_date);
5108              AHL_DEBUG_PUB.Debug('Interval Value:' ||l_mr_interval_rec.interval_value);
5109              AHL_DEBUG_PUB.Debug('tolerance bef:' ||l_mr_interval_rec.tolerance_before);
5110              AHL_DEBUG_PUB.Debug('tolerance aft:' ||l_mr_interval_rec.tolerance_after);
5111              AHL_DEBUG_PUB.Debug('earliest_due_value:' ||l_mr_interval_rec.earliest_due_value);
5112              AHL_DEBUG_PUB.Debug('CounterID:' || l_temp_counter_tbl(i).counter_id);
5113              AHL_DEBUG_PUB.Debug('CounterName:' || l_temp_counter_tbl(i).counter_name);
5114              AHL_DEBUG_PUB.Debug('counter_value:' || l_counter_value);
5115              AHL_DEBUG_PUB.Debug('current ctr:' ||l_current_ctr_value);
5116            END IF;
5117 
5118            l_counter_remain := 0; /* initialize */
5119 
5120            l_due_at_counter_value := l_mr_interval_rec.interval_value + l_counter_value;
5121 
5122 --           dbms_output.put_line ('SKR_due_at_counter_value' || l_due_at_counter_value);
5123            -- Added for bug# 6358940(start_value).
5124            -- if at least one MR is accomplished and earliest_due_value is defined.
5125            -- (SB Enh) IF (p_last_due_date IS NOT NULL AND p_repetivity_flag = 'N' AND
5126            IF (p_mr_accomplish_exists AND p_repetivity_flag = 'N' AND
5127                mr_interval_rec.start_value IS NOT NULL AND
5128                p_dependent_mr_flag = FALSE) THEN
5129              IF (l_mr_interval_rec.earliest_due_value IS NOT NULL) THEN
5130                 IF (l_counter_value < l_mr_interval_rec.earliest_due_value) THEN
5131                   l_due_at_counter_value := l_mr_interval_rec.start_value;
5132                   l_reset_start_value_flag := TRUE;
5133                 END IF;
5134              END IF;
5135            -- fix for bug#6711228(issue described in problem#2).
5136            -- l_counter_value for this case contains the counter value as of
5137            -- preceding MR's due date so we need to handle this seperately.
5138            ELSIF (p_repetivity_flag = 'N' AND p_dependent_mr_flag = TRUE AND
5139                   mr_interval_rec.start_value IS NOT NULL) THEN
5140                   -- Added for ER 7415856
5141                   -- if rule code is set as INTERVAL
5142                   IF (l_mr_interval_rec.calc_duedate_rule_code = 'INTERVAL') THEN
5143                       l_due_at_counter_value := l_mr_interval_rec.start_value + l_mr_interval_rec.interval_value;
5144                       l_reset_start_value_flag := TRUE;
5145                   ELSE
5146                       l_due_at_counter_value := l_mr_interval_rec.start_value;
5147                       l_reset_start_value_flag := TRUE;
5148                   END IF;
5149            ELSE
5150              -- Check if due counter less than start value or start date. If yes, set it
5151              -- to start value.
5152              IF (l_mr_interval_rec.start_value IS NOT NULL) THEN
5153                IF (l_counter_value < l_mr_interval_rec.start_value) THEN
5154                  -- Added for ER 7415856
5155                  -- if rule code is set as INTERVAL then add interval to due counter value.
5156                  IF (l_mr_interval_rec.calc_duedate_rule_code = 'INTERVAL') THEN
5157                      l_due_at_counter_value := l_mr_interval_rec.start_value + l_mr_interval_rec.interval_value;
5158                      l_reset_start_value_flag := TRUE;
5159                  ELSE
5160                    l_due_at_counter_value := l_mr_interval_rec.start_value;
5161                    l_reset_start_value_flag := TRUE;
5162                  END IF;
5163                END IF;
5164              END IF;
5165            END IF;
5166 
5167 --           dbms_output.put_line ('SKR1_due_at_counter_value' || l_due_at_counter_value);
5168            -- Added for bug# 6358940(start_date).
5169            IF (p_repetivity_flag = 'N') AND (mr_interval_rec.start_date IS NOT NULL) THEN
5170              -- (SB Enh) IF (p_last_due_date IS NOT NULL AND p_dependent_mr_flag = FALSE) THEN
5171              IF (p_mr_accomplish_exists AND p_dependent_mr_flag = FALSE) THEN
5172                 -- MR accomplished
5173                 IF (mr_interval_rec.earliest_due_value IS NOT NULL) THEN
5174                   IF (l_counter_value < mr_interval_rec.earliest_due_value) THEN
5175                     l_due_date := mr_interval_rec.start_date;
5176                     l_reset_start_date_flag := TRUE;
5177                   END IF;
5178                 END IF;
5179              ELSE  -- no accomplishment. first time MR must be done on start date.
5180                 l_due_date := mr_interval_rec.start_date;
5181                 l_reset_start_date_flag := TRUE;
5182              END IF;
5183 
5184 --           dbms_output.put_line ('SKR2_due_at_counter_value' || l_due_at_counter_value);
5185              -- calculate due counter value.
5186              IF (l_reset_start_date_flag) THEN
5187                IF (l_due_date < trunc(sysdate)) THEN
5188                  get_ctr_reading_for_date (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
5189                                            p_counter_id           => l_temp_counter_tbl(i).counter_id,
5190                                            p_reading_date         => l_due_date,
5191                                            x_net_reading          => l_due_at_counter_value);
5192 
5193                ELSIF (l_due_date = trunc(sysdate)) THEN
5194                   -- current counter value.
5195                   l_due_at_counter_value := l_temp_counter_tbl(i).counter_value;
5196                ELSE
5197                   -- calculate due counter value.
5198                   l_last_due_counter_tbl(1) := l_temp_counter_tbl(i); -- current ctr
5199 
5200                   -- before the due counter value.
5201                   Get_Due_At_Counter_Values (p_last_due_date => p_last_due_date,
5202                                              p_last_due_counter_val_tbl => l_last_due_counter_tbl,
5203                                              p_due_date => l_due_date,
5204                                              p_counter_rules_tbl => p_counter_rules_tbl,
5205                                              x_due_at_counter_val_tbl => l_due_counter_tbl,
5206                                              x_return_value  => l_return_val);
5207 
5208                   -- if forecast not setup, cannot calculate due counter value for
5209                   -- start date.
5210                   IF NOT(l_return_val) THEN
5211                     l_due_date := NULL;
5212                     RAISE DUE_DATE_NULL;
5213                   ELSE
5214                     l_due_at_counter_value := l_due_counter_tbl(1).counter_value;
5215                   END IF;
5216 
5217                END IF; -- l_due_date < trunc(sysdate)
5218 
5219 --           dbms_output.put_line ('SKR3_due_at_counter_value' || l_due_at_counter_value);
5220                -- Added for ER 7415856
5221                IF (l_mr_interval_rec.calc_duedate_rule_code = 'INTERVAL') THEN
5222                      l_due_at_counter_value := l_due_at_counter_value + l_mr_interval_rec.interval_value;
5223                      l_reset_start_date_flag := FALSE; -- need to calculate new due date.
5224                END IF;
5225              END IF; -- (l_reset_start_date_flag)
5226 
5227            END IF; -- p_repetivity_flag = 'N') AND ..
5228 
5229            --dbms_output.put_line ('due at counter' || l_due_at_counter_value );
5230 
5231            -- Check for interval value overflow.
5232            IF (mr_interval_rec.stop_value IS NOT NULL) THEN
5233              --IF (l_due_at_counter_value  >= mr_interval_rec.stop_value) THEN
5234              -- Fix for bug# 3482307.
5235              IF (l_due_at_counter_value  > mr_interval_rec.stop_value) THEN
5236 
5237                 Adjust_Interval_Value (p_mr_effectivity_id => effectivity_rec.mr_effectivity_id,
5238                                        p_counter_id        => l_temp_counter_tbl(i).counter_id,
5239                                        p_counter_value     => l_counter_value,
5240                                        p_interval_value    => mr_interval_rec.interval_value,
5241                                        p_stop_value        => mr_interval_rec.stop_value,
5242                                        x_adjusted_int_value => l_adjusted_int_value,
5243                                        x_nxt_interval_found => l_nxt_interval_found);
5244                 -- Fix for bug# 3461118.
5245                 IF NOT(l_nxt_interval_found) THEN
5246                   IF (l_ctr_interval_found = TRUE AND l_old_ctr_interval_found = FALSE) THEN
5247                     l_ctr_interval_found := FALSE;
5248                   END IF;
5249                   GOTO next_mr_interval_loop;
5250                 ELSE
5251                   l_due_at_counter_value := l_adjusted_int_value + l_counter_value;
5252                 END IF;
5253              END IF;
5254            END IF;
5255 
5256 
5257            IF (p_repetivity_flag = 'N') THEN
5258              l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
5259            ELSE
5260              l_counter_remain := l_due_at_counter_value - l_counter_value;
5261            END IF;
5262 
5263            --dbms_output.put_line ('counter remain' || l_counter_remain );
5264 
5265            IF G_DEBUG = 'Y' THEN
5266              AHL_DEBUG_PUB.Debug('due at counter_value:' || l_due_at_counter_value);
5267              AHL_DEBUG_PUB.Debug('counter remain:' || l_counter_remain);
5268            END IF;
5269 
5270            -- if due date already set based on start date then skip date calculation.
5271            IF NOT(l_reset_start_date_flag) THEN
5272              -- calculate due date based on forecast.
5273              IF (l_counter_remain > 0) THEN
5274                 -- get date from forecast.
5275                 get_date_from_uf(l_counter_remain,
5276                                  l_temp_counter_tbl(i).uom_code,
5277                                  p_counter_rules_tbl,
5278                                  l_start_date,
5279                                  --null, /* start date = sysdate */
5280                                  l_due_date);
5281 
5282                 --dbms_output.put_line ('due date by forecast' || l_due_date );
5283 
5284              ELSIF (l_counter_remain < 0) THEN
5285                -- Due date = counter reading date.
5286                get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
5287                                          p_counter_id           => l_temp_counter_tbl(i).counter_id,
5288                                          p_counter_value        => l_due_at_counter_value,
5289                                          x_ctr_record_date      => l_counter_read_date,
5290                                          x_return_val           => l_return_val);
5291 
5292                IF NOT(l_return_val) THEN
5293                   l_due_date := sysdate;
5294                ELSE
5295                   l_due_date := l_counter_read_date;
5296                END IF;
5297 
5298              ELSIF (l_counter_remain = 0) THEN  /* due_date = sysdate */
5299                --dbms_output.put_line ('counter remain less than zero');
5300                l_due_date := sysdate;
5301              END IF;
5302            END IF; -- l_reset_start_date_flag
5303 
5304            /* commented out to fix bug# 6907562
5305            -- Check the due date value.
5306            IF (l_due_date IS NULL) THEN
5307               RAISE DUE_DATE_NULL;
5308            END IF;
5309            */
5310 
5311            -- Check Due date overflow to next interval.
5312            IF (mr_interval_rec.stop_date IS NOT NULL) THEN
5313               IF (l_due_date > mr_interval_rec.stop_date) THEN
5314 
5315                  -- Call procedure to adjust due date.
5316                  Adjust_Due_Date ( p_mr_effectivity_id => effectivity_rec.mr_effectivity_id,
5317                                    p_start_counter_rec => l_temp_counter_tbl(i),
5318                                    p_start_due_date    => p_last_due_date,
5319                                    p_counter_rules_tbl => p_counter_rules_tbl,
5320                                    p_interval_value    => mr_interval_rec.interval_value,
5321                                    p_stop_date         => mr_interval_rec.stop_date,
5322                                    p_due_date          => l_due_date,
5323                                    x_adjusted_due_date => l_adjusted_due_date,
5324                                    x_adjusted_due_ctr  => l_adjusted_due_ctr,
5325                                    x_nxt_interval_found => l_nxt_interval_found);
5326 
5327                  -- Fix for bug# 3461118.
5328                  IF NOT(l_nxt_interval_found) THEN
5329                    IF (l_ctr_interval_found = TRUE AND l_old_ctr_interval_found = FALSE) THEN
5330                      l_ctr_interval_found := FALSE;
5331                    END IF;
5332                    GOTO next_mr_interval_loop;
5333                  ELSE
5334                    IF (l_due_date <> l_adjusted_due_date) THEN
5335                      l_due_at_counter_value := l_adjusted_due_ctr + l_counter_value;
5336                    END IF;
5337                    l_due_date := l_adjusted_due_date;
5338                  END IF;
5339                  --dbms_output.put_line ('adjusted_due_date' || l_due_date );
5340 
5341               END IF;
5342            END IF;
5343 
5344          -- JKJain, NR Analysis and Forecasting
5345            IF G_DEBUG = 'Y' THEN
5346              AHL_DEBUG_PUB.Debug('JKJ- G_UC_HEADER_ID :' || G_UC_HEADER_ID || ' and l_due_date = '|| l_due_date);
5347              AHL_DEBUG_PUB.Debug('JKJ- effectivity_rec.fleet_header_id = ' || l_fleet_header_id);
5348            END IF;
5349 
5350            --Verify if due date  is in fleet-unit asscociation
5351            IF(l_fleet_header_id is NOT NULL) THEN
5352                 IF (G_UC_HEADER_ID is NOT NULL AND l_due_date IS NOT NULL) THEN
5353                     IF (l_fleet_header_id <> nvl(get_fleet_from_unit_asso(G_UC_HEADER_ID,l_due_date,G_SIMULATION_PLAN_ID),-1)) THEN
5354 
5355                         IF(l_fleet_reject_due_date IS NULL) THEN
5356                             l_fleet_reject_due_date := l_due_date;
5357                         ELSIF (l_fleet_reject_due_date > l_due_date) THEN
5358                             l_fleet_reject_due_date := l_due_date;
5359                         END IF;
5360 
5361                         --calculate earliest due date and verify the same.
5362                         IF l_mr_interval_rec.tolerance_before IS NOT NULL THEN
5363                              -- Not required: If due date is today's date then earliest due = due date.
5364                             IF (l_due_date IS NOT NULL) THEN
5365                                  IF (p_repetivity_flag = 'N') THEN
5366                                     l_counter_remain := (l_due_at_counter_value -
5367                                                          l_mr_interval_rec.tolerance_before) -  l_current_ctr_value;
5368                                 ELSE
5369                                     l_counter_remain := (l_due_at_counter_value -
5370                                                          l_mr_interval_rec.tolerance_before) -
5371                                                          l_counter_value;
5372                                 END IF;
5373 
5374                                 IF (l_counter_remain < 0) THEN
5375                                     -- Due date = counter reading date.
5376                                     get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
5377                                                               p_counter_id => l_calc_due_date_ctr_id,
5378                                                               p_counter_value => l_due_at_counter_value -
5379                                                                                  l_mr_interval_rec.tolerance_before,
5380                                                               x_ctr_record_date => l_counter_read_date,
5381                                                               x_return_val => l_return_val);
5382                                     IF NOT(l_return_val) THEN
5383                                         l_earliest_due_date := null;
5384                                     ELSE
5385                                         l_earliest_due_date := l_counter_read_date;
5386                                     END IF;
5387                                     -- if earliest_due_date > due date (when no counters readings exist before counter remain).
5388                                     IF (l_earliest_due_date > l_due_date) THEN
5389                                         l_earliest_due_date := l_due_date;
5390                                     END IF;
5391 
5392                                 ELSE /* counter_remain > 0 */
5393                                     -- get date from forecast.
5394                                     get_date_from_uf(l_counter_remain,
5395                                                             l_temp_counter_tbl(i).uom_code,
5396                                                             p_counter_rules_tbl,
5397                                                             l_start_date,
5398                                                             l_earliest_due_date);
5399                                 END IF; -- counter_remain.
5400 
5401                             END IF; -- due date is not null.
5402                         END IF; -- tolerance before.
5403 
5404 
5405                         IF(l_earliest_due_date IS NOT NULL and l_earliest_due_date < l_due_date) THEN
5406                             IF (l_fleet_header_id <> nvl(get_fleet_from_unit_asso(G_UC_HEADER_ID,l_earliest_due_date,G_SIMULATION_PLAN_ID),-1)) THEN
5407                                 IF (l_ctr_interval_found = TRUE AND l_old_ctr_interval_found = FALSE) THEN
5408                                     l_ctr_interval_found := FALSE;
5409                                     x_next_due_date_rec.FLEET_ASSO_REJECTED := 'Y';
5410                                 END IF;
5411                                 GOTO next_mr_interval_loop;
5412                             END IF;
5413                         ELSE
5414                             x_next_due_date_rec.FLEET_ASSO_REJECTED := 'Y';
5415                             l_ctr_interval_found := l_old_ctr_interval_found;
5416                             GOTO next_mr_interval_loop;
5417                         END IF;
5418                     END IF;
5419                 ELSE
5420                     GOTO next_mr_interval_loop;
5421                 END IF;
5422             END IF; --l_fleet_header_id is NOT NULL
5423 
5424 
5425            /* fix for bug# 6858788: this causes next repetity to be over
5426             * interval value
5427            -- Call Get_Due_At_Counter_Values only if due date is a future date.
5428            IF (l_reset_start_value_flag) AND (trunc(l_due_date) > trunc(sysdate)) THEN
5429               -- Check if the counter value on the due date is less than the due counter value.
5430               -- If less, add a day to the due date. This would ensure that the MR is performed not
5431               -- before due date.
5432               l_last_due_counter_tbl(1) := l_temp_counter_tbl(i);
5433 
5434               -- before the due counter value.
5435               Get_Due_At_Counter_Values (p_last_due_date => p_last_due_date,
5436                                          p_last_due_counter_val_tbl => l_last_due_counter_tbl,
5437                                          p_due_date => l_due_date,
5438                                          p_counter_rules_tbl => p_counter_rules_tbl,
5439                                          x_due_at_counter_val_tbl => l_due_counter_tbl,
5440                                          x_return_value  => l_return_val);
5441 
5442               IF (l_return_val) THEN
5443                 IF (l_due_counter_tbl(1).counter_value < l_due_at_counter_value) THEN
5444                    l_due_date := l_due_date + 1;
5445                 END IF;
5446               END IF;
5447 
5448            END IF;
5449            */
5450            -- Compare with whichever first code and set l_calc_due_date.
5451            -- logic modified to fix bug# 6907562. Here l_due_date can be null.
5452            IF (l_due_date IS NULL) THEN
5453                -- Added to fix bug# 6907562.
5454                IF (validate_for_duedate_reset(l_due_date,
5455                                               l_counter_remain,
5456                                               l_calc_due_date,
5457                                               l_calc_due_date_ctr_id,
5458                                               x_next_due_date_rec.counter_remain)) = 'Y' THEN
5459                    --dbms_output.put_line ('due date is null');
5460                    l_calc_due_date := l_due_date;
5461                    x_next_due_date_rec.due_date := l_due_date;
5462                    x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
5463                    x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
5464                    x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
5465                    x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
5466                    x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5467                    x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5468                    x_next_due_date_rec.last_ctr_value := l_counter_value;
5469                    x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
5470                    x_next_due_date_rec.counter_id := null;
5471                    x_next_due_date_rec.counter_remain := l_counter_remain;
5472                    l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
5473                END IF;
5474            ELSE  -- due date is not null
5475                IF (l_calc_due_date IS NULL) THEN
5476                    -- Added to fix bug# 6907562.
5477                    IF (validate_for_duedate_reset(l_due_date,
5478                                                   l_counter_remain,
5479                                                   l_calc_due_date,
5480                                                   l_calc_due_date_ctr_id,
5481                                                   x_next_due_date_rec.counter_remain)) = 'Y' THEN
5482 
5483                      --dbms_output.put_line ('calc due date is null');
5484                      l_calc_due_date := l_due_date;
5485                      x_next_due_date_rec.due_date := l_due_date;
5486                      x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
5487                      x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
5488                      x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
5489                      x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
5490                      x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5491                      x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5492                      x_next_due_date_rec.last_ctr_value := l_counter_value;
5493                      x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
5494                      x_next_due_date_rec.counter_id := null;
5495                      x_next_due_date_rec.counter_remain := l_counter_remain;
5496                      l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
5497                    END IF;
5498                ELSE
5499                    IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
5500                      -- dbms_output.put_line ('applicable mr which code = first');
5501                      -- Check due date based on whichever_first_code.
5502                      -- if dates are equal, switch based on lower uom remain value. (bug# 6907562).
5503                      IF (l_calc_due_date > l_due_date) OR
5504                        (trunc(l_calc_due_date) = trunc(l_due_date) AND l_counter_remain IS NOT NULL
5505                         AND x_next_due_date_rec.counter_remain IS NOT NULL
5506                         AND l_counter_remain < x_next_due_date_rec.counter_remain) THEN
5507 
5508                         --dbms_output.put_line ('calc_due_date > l_due date');
5509                         l_calc_due_date := l_due_date;
5510                         x_next_due_date_rec.due_date := l_due_date;
5511                         x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
5512                         x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
5513                         x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
5514                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
5515                         x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5516                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5517                         x_next_due_date_rec.last_ctr_value := l_counter_value;
5518                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
5519                         x_next_due_date_rec.counter_id := null;
5520                         x_next_due_date_rec.counter_remain := l_counter_remain;
5521                         l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
5522                      END IF;
5523                    ELSE  /* whichever_first_code = 'LAST' */
5524                      --dbms_output.put_line ('applicable mr which code = last');
5525                      -- if dates are equal, switch based on higher uom remain value. (bug# 6907562).
5526                      IF (l_calc_due_date < l_due_date) OR
5527                         (trunc(l_calc_due_date) = trunc(l_due_date) AND l_counter_remain IS NOT NULL
5528                         AND x_next_due_date_rec.counter_remain IS NOT NULL
5529                         AND l_counter_remain > x_next_due_date_rec.counter_remain) THEN
5530 
5531                         --dbms_output.put_line ('calc_due_date < l_due date');
5532                         l_calc_due_date := l_due_date;
5533                         x_next_due_date_rec.due_date := l_due_date;
5534                         x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
5535                         x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
5536                         x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
5537                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
5538                         x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5539                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5540                         x_next_due_date_rec.last_ctr_value := l_counter_value;
5541                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
5542                         x_next_due_date_rec.counter_id := null;
5543                         x_next_due_date_rec.counter_remain := l_counter_remain;
5544                         l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
5545                      END IF;
5546                    END IF;
5547                END IF; /* calc_due_date null */
5548                --dbms_output.put_line ('Next mr interval');
5549            END IF; -- due date is null.
5550 
5551            IF G_DEBUG = 'Y' THEN
5552              AHL_DEBUG_PUB.Debug('Before Next interval table loop');
5553              AHL_DEBUG_PUB.Debug('l_due_date:' || l_due_date );
5554              AHL_DEBUG_PUB.Debug('l_calc_due_date:' || l_calc_due_date);
5555              AHL_DEBUG_PUB.Debug('l_calc_due_date_ctr_id:' || l_calc_due_date_ctr_id);
5556            END IF;
5557 
5558            -- Fix for bug# 3461118.
5559            <<next_mr_interval_loop>>
5560            NULL;
5561          END LOOP; /* mr_interval_rec */
5562 
5563          -- If no interval found, then check if future intervals exist
5564          -- and calculate date based on that interval.
5565          -- Added p_mr_accomplish_exists and p_last_due_mr_interval_id to fix bug# 6858788.
5566          -- Commented p_last_accomplishment_date and will instead use p_mr_accomplish_exists.
5567          IF NOT(l_ctr_interval_found) THEN
5568            Get_DueDate_from_NxtInterval (p_applicable_mrs_rec => p_applicable_mrs_rec,
5569                                          p_repetivity_flag    => p_repetivity_flag,
5570                                          p_mr_effectivity_id => effectivity_rec.mr_effectivity_id,
5571                                          p_current_ctr_rec   => l_temp_counter_tbl(i),
5572                                          p_counter_rules_tbl => p_counter_rules_tbl,
5573                                          p_current_ctr_at_date => l_start_date,
5574                                          p_start_int_match_at_ctr => l_start_int_match_at_ctr,
5575                                          p_last_accomplish_ctr_val => l_counter_value,
5576                                          --p_last_accomplishment_date => p_last_due_date,
5577                                          p_dependent_mr_flag => p_dependent_mr_flag,
5578                                          p_mr_accomplish_exists => p_mr_accomplish_exists,
5579                                          p_last_due_mr_interval_id => p_last_due_mr_interval_id,
5580                                          x_next_due_date_rec => l_next_due_date_rec,
5581                                                                 --x_next_due_date_rec,
5582                                          x_mr_interval_found => l_ctr_interval_found,
5583                                          x_return_val        => l_return_val);
5584            IF (l_ctr_interval_found) THEN
5585              IF NOT(l_return_val) THEN
5586                RAISE DUE_DATE_NULL; -- forecast not available hence uom remain is not known.
5587              END IF;
5588 
5589              -- JKJain, NR Analysis and Forecasting
5590              --Verify if due date  is in fleet-unit asscociation
5591              IF (l_fleet_header_id is NOT NULL) THEN
5592                IF (G_UC_HEADER_ID is NOT NULL AND l_next_due_date_rec.due_date IS NOT NULL) THEN
5593                     IF (l_fleet_header_id <> nvl(get_fleet_from_unit_asso(G_UC_HEADER_ID,l_next_due_date_rec.due_date,G_SIMULATION_PLAN_ID),-1)) THEN
5594 
5595                         IF(l_fleet_reject_due_date IS NULL) THEN
5596                           l_fleet_reject_due_date := l_next_due_date_rec.due_date;
5597                         ELSIF (l_fleet_reject_due_date > l_next_due_date_rec.due_date) THEN
5598                           l_fleet_reject_due_date := l_next_due_date_rec.due_date;
5599                         END IF;
5600 
5601                         --calculate earliest due date and verify the same.
5602                         IF l_next_due_date_rec.tolerance_before IS NOT NULL THEN
5603                              -- Not required: If due date is today's date then earliest due = due date.
5604                             IF (l_next_due_date_rec.due_date IS NOT NULL) THEN
5605                                  IF (p_repetivity_flag = 'N') THEN
5606                                     l_counter_remain := (l_due_at_counter_value -
5607                                                          l_next_due_date_rec.tolerance_before) -
5608                                                          l_current_ctr_value;
5609                                 ELSE
5610                                     l_counter_remain := (l_due_at_counter_value -
5611                                                          l_next_due_date_rec.tolerance_before) -
5612                                                          l_counter_value;
5613                                 END IF;
5614 
5615                                 IF (l_counter_remain < 0) THEN
5616                                     -- Due date = counter reading date.
5617                                     get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
5618                                                               p_counter_id => l_calc_due_date_ctr_id,
5619                                                               p_counter_value => l_due_at_counter_value -
5620                                                                                  l_next_due_date_rec.tolerance_before,
5621                                                               x_ctr_record_date => l_counter_read_date,
5622                                                               x_return_val => l_return_val);
5623                                     IF NOT(l_return_val) THEN
5624                                         l_earliest_due_date := null;
5625                                     ELSE
5626                                         l_earliest_due_date := l_counter_read_date;
5627                                     END IF;
5628                                     -- if earliest_due_date > due date (when no counters readings exist before counter remain).
5629                                     IF (l_earliest_due_date > l_next_due_date_rec.due_date) THEN
5630                                         l_earliest_due_date := l_next_due_date_rec.due_date;
5631                                     END IF;
5632 
5633                                 ELSE /* counter_remain > 0 */
5634                                     -- get date from forecast.
5635                                     get_date_from_uf(l_counter_remain,
5636                                                             l_temp_counter_tbl(i).uom_code,
5637                                                             p_counter_rules_tbl,
5638                                                             l_start_date,
5639                                                             l_earliest_due_date);
5640                                 END IF; -- counter_remain.
5641 
5642                             END IF; -- due date is not null.
5643                         END IF; -- tolerance before.
5644 
5645 
5646                         IF(l_earliest_due_date IS NOT NULL and l_earliest_due_date < l_next_due_date_rec.due_date) THEN
5647                             IF (l_fleet_header_id <> nvl(get_fleet_from_unit_asso(G_UC_HEADER_ID,l_earliest_due_date,G_SIMULATION_PLAN_ID),-1)) THEN
5648                                 IF (l_ctr_interval_found = TRUE AND l_old_ctr_interval_found = FALSE) THEN
5649                                     l_ctr_interval_found := FALSE;
5650                                     x_next_due_date_rec.FLEET_ASSO_REJECTED := 'Y';
5651                                 END IF;
5652                                 GOTO next_counter_loop;
5653                             END IF;
5654                         ELSE
5655                             l_ctr_interval_found := l_old_ctr_interval_found;
5656                             x_next_due_date_rec.FLEET_ASSO_REJECTED := 'Y';
5657                             GOTO next_counter_loop;
5658                         END IF;
5659                     END IF;
5660                ELSE
5661                  GOTO next_counter_loop;
5662                END IF;
5663              END IF; -- l_fleet_header_id is NOT NULL
5664 
5665              IF (l_next_due_date_rec.due_date IS NOT NULL) THEN
5666                 IF (l_calc_due_date IS NULL) THEN
5667                    -- Added to fix bug# 6907562.
5668                    IF (validate_for_duedate_reset(l_next_due_date_rec.due_date,
5669                                                   l_next_due_date_rec.counter_remain,
5670                                                   l_calc_due_date,
5671                                                   l_calc_due_date_ctr_id,
5672                                                   x_next_due_date_rec.counter_remain)) = 'Y' THEN
5673 
5674                       x_next_due_date_rec := l_next_due_date_rec;
5675                       l_calc_due_date := x_next_due_date_rec.due_date;
5676                       x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5677                       x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5678                       x_next_due_date_rec.last_ctr_value := l_counter_value;
5679                       x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
5680                       x_next_due_date_rec.counter_id := null;
5681                       l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
5682                    END IF; -- validate_for_duedate_reset
5683 
5684                 ELSIF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
5685                   -- if dates are equal, switch based on lower uom remain value. (bug# 6907562).
5686                   IF (l_calc_due_date > l_next_due_date_rec.due_date) OR
5687                      (trunc(l_calc_due_date) = trunc(l_next_due_date_rec.due_date)
5688                      AND l_next_due_date_rec.counter_remain IS NOT NULL
5689                      AND x_next_due_date_rec.counter_remain IS NOT NULL
5690                      AND l_next_due_date_rec.counter_remain < x_next_due_date_rec.counter_remain) THEN
5691 
5692                       x_next_due_date_rec := l_next_due_date_rec;
5693                       l_calc_due_date := x_next_due_date_rec.due_date;
5694                       x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5695                       x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5696                       x_next_due_date_rec.last_ctr_value := l_counter_value;
5697                       x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
5698                       x_next_due_date_rec.counter_id := null;
5699                       l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
5700                   END IF;
5701                 ELSIF (p_applicable_mrs_rec.whichever_first_code = 'LAST') THEN
5702                    -- if dates are equal, switch based on higher uom remain value. (bug# 6907562).
5703                    IF (l_calc_due_date < l_next_due_date_rec.due_date) OR
5704                       (trunc(l_calc_due_date) = trunc(l_next_due_date_rec.due_date)
5705                         AND l_next_due_date_rec.counter_remain IS NOT NULL
5706                         AND x_next_due_date_rec.counter_remain IS NOT NULL
5707                         AND l_next_due_date_rec.counter_remain > x_next_due_date_rec.counter_remain) THEN
5708                        x_next_due_date_rec := l_next_due_date_rec;
5709                        l_calc_due_date := x_next_due_date_rec.due_date;
5710                        x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5711                        x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5712                        x_next_due_date_rec.last_ctr_value := l_counter_value;
5713                        x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
5714                        x_next_due_date_rec.counter_id := null;
5715                        l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
5716                   END IF;
5717                 END IF; -- l_calc_due_date IS NULL
5718              -- else added to fix bug# 6907562.
5719              ELSE -- due date is null.
5720                -- Added to fix bug# 6907562.
5721                IF (validate_for_duedate_reset(l_next_due_date_rec.due_date,
5722                                               l_next_due_date_rec.counter_remain,
5723                                               l_calc_due_date,
5724                                               l_calc_due_date_ctr_id,
5725                                               x_next_due_date_rec.counter_remain)) = 'Y' THEN
5726                     x_next_due_date_rec := l_next_due_date_rec;
5727                     l_calc_due_date := x_next_due_date_rec.due_date;
5728                     x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5729                     x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5730                     x_next_due_date_rec.last_ctr_value := l_counter_value;
5731                     x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
5732                     x_next_due_date_rec.counter_id := null;
5733                     l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
5734 
5735                END IF; -- validate_for_duedate_reset
5736              END IF; -- x_next_due_date_rec.due_date IS NOT NULL
5737            END IF; -- l_ctr_interval_found.
5738          END IF; -- NOT(l_ctr_interval_found)
5739 
5740          -- added to fix bug# 6725769.
5741          IF NOT(l_mr_interval_found) THEN
5742             IF (l_ctr_interval_found) THEN
5743                 l_mr_interval_found := TRUE;
5744                 -- JKJain, NR Analysis and Forecasting
5745                 x_next_due_date_rec.FLEET_ASSO_REJECTED := 'N';
5746             END IF;
5747          END IF;
5748          --dbms_output.put_line ('next counter');
5749 
5750          <<next_counter_loop>>
5751          NULL;
5752        END LOOP; /* temp_counter_tbl */
5753      END IF; /* count > 0 */
5754 
5755      -- Check due date with threshold date.
5756      -- If threshold date exists, then the MR is not repetitive.
5757      -- JKJain, NR Analysis and Forecasting
5758      IF ((effectivity_rec.threshold_date IS NOT NULL) AND (p_repetivity_flag = 'N') AND
5759         ( (l_calc_due_date IS NOT NULL AND l_mr_interval_found = TRUE) OR  /* case of due date is not null for an interval id */
5760           (l_mr_interval_found = FALSE) ) /* case of no intervals defined for an effectivity */
5761            AND (l_fleet_header_id IS NULL OR G_UC_HEADER_ID IS NULL OR
5762                 l_fleet_header_id = get_fleet_from_unit_asso(G_UC_HEADER_ID,effectivity_rec.threshold_date,G_SIMULATION_PLAN_ID)))
5763         THEN
5764          --dbms_output.put_line ('in threshold');
5765          IF (l_calc_due_date IS NULL) THEN
5766              l_calc_due_date := effectivity_rec.threshold_date;
5767              x_next_due_date_rec.due_date := effectivity_rec.threshold_date;
5768              x_next_due_date_rec.tolerance_after := null;
5769              x_next_due_date_rec.tolerance_before := null;
5770              x_next_due_date_rec.mr_interval_id := null;
5771              x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5772              x_next_due_date_rec.due_at_counter_value := null;
5773              x_next_due_date_rec.current_ctr_value := null;
5774              x_next_due_date_rec.last_ctr_value := null;
5775              x_next_due_date_rec.ctr_uom_code := null;
5776              x_next_due_date_rec.counter_id := null;
5777              x_next_due_date_rec.counter_remain := null;
5778              l_calc_due_date_ctr_id := null;
5779          ELSIF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
5780              IF (l_calc_due_date > effectivity_rec.threshold_date) THEN
5781                   l_calc_due_date := effectivity_rec.threshold_date;
5782                   x_next_due_date_rec.due_date := effectivity_rec.threshold_date;
5783                   x_next_due_date_rec.tolerance_after := null;
5784                   x_next_due_date_rec.tolerance_before := null;
5785                   x_next_due_date_rec.mr_interval_id := null;
5786                   x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5787                   x_next_due_date_rec.due_at_counter_value := null;
5788                   x_next_due_date_rec.current_ctr_value := null;
5789                   x_next_due_date_rec.last_ctr_value := null;
5790                   x_next_due_date_rec.ctr_uom_code := null;
5791                   x_next_due_date_rec.counter_id := null;
5792                   x_next_due_date_rec.counter_remain := null;
5793                   l_calc_due_date_ctr_id := null;
5794 
5795               END IF;
5796          ELSIF (p_applicable_mrs_rec.whichever_first_code = 'LAST') THEN
5797            /* whichever_first_code = 'LAST' */
5798             IF (l_calc_due_date < effectivity_rec.threshold_date) THEN
5799                   l_calc_due_date := effectivity_rec.threshold_date;
5800                   x_next_due_date_rec.due_date := effectivity_rec.threshold_date;
5801                   x_next_due_date_rec.tolerance_after := null;
5802                   x_next_due_date_rec.tolerance_before := null;
5803                   x_next_due_date_rec.mr_interval_id := null;
5804                   x_next_due_date_rec.due_at_counter_value := null;
5805                   x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
5806                   x_next_due_date_rec.current_ctr_value := null;
5807                   x_next_due_date_rec.last_ctr_value := null;
5808                   x_next_due_date_rec.ctr_uom_code := null;
5809                   x_next_due_date_rec.counter_id := null;
5810                   x_next_due_date_rec.counter_remain := null;
5811                   l_calc_due_date_ctr_id := null;
5812 
5813             END IF;
5814          END IF; /* whichever_first_code */
5815       END IF; /* threshold_date not null */
5816 
5817       --dbms_output.put_line ('NEXT effectivity');
5818   END LOOP mr_effectivity_loop; /* effectivity_rec */
5819 
5820   -- Fix for bug# 6358940. Due Date should be based only on init-due if it
5821   -- exists. MR thresholds should not be used.
5822   -- Moved below logic to the beginning of the this procedure before processing
5823   -- effectivities.
5824   -- Calculate due date based on init-due defination; if exists.
5825   /*
5826   IF (p_repetivity_flag = 'N') THEN
5827      --dbms_output.put_line ('in INIT-due part');
5828 
5829      -- Check if there is any init-due record for this item instance and mr exists.
5830      OPEN ahl_init_due_csr(p_applicable_mrs_rec.csi_item_instance_id,
5831                            p_applicable_mrs_rec.mr_header_id);
5832      FETCH ahl_init_due_csr INTO l_set_due_date, l_unit_effectivity_id, l_unit_deferral_id;
5833      IF (ahl_init_due_csr%FOUND) THEN
5834 
5835         --dbms_output.put_line ('in INIT-due part: due_date' || l_set_due_date);
5836 
5837         FOR threshold_rec IN ahl_unit_thresholds_csr (l_unit_deferral_id)
5838         LOOP
5839           -- for init due, ctr_value_type_code is always 'defer_to'.
5840           l_due_at_counter_value := threshold_rec.counter_value;
5841           l_counter_remain := 0;
5842           l_current_ctr_value := 0;
5843           k := 0;
5844           -- search for the current counter value in l_current_usage_tbl.
5845           IF (l_temp_counter_tbl.COUNT > 0) THEN
5846             FOR i IN l_temp_counter_tbl.FIRST..l_temp_counter_tbl.LAST LOOP
5847                IF (l_temp_counter_tbl(i).counter_id = threshold_rec.counter_id) THEN
5848                   l_current_ctr_value := l_temp_counter_tbl(i).counter_value;
5849                   k := i;
5850                   EXIT;
5851                END IF;
5852             END LOOP;
5853             l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
5854           END IF;
5855 
5856           -- calculate due date from forecast.
5857           IF (l_counter_remain > 0) THEN
5858             -- get date from forecast.
5859             get_date_from_uf(l_counter_remain,
5860                              l_temp_counter_tbl(k).uom_code,
5861                              p_counter_rules_tbl,
5862                              null, -- start date = sysdate
5863                              l_due_date);
5864           ELSIF (l_counter_remain < 0) THEN
5865             -- Due date = counter reading date.
5866              get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
5867                                        p_counter_id           => l_temp_counter_tbl(k).counter_id,
5868                                        p_counter_value        => l_due_at_counter_value,
5869                                        x_ctr_record_date      => l_counter_read_date,
5870                                        x_return_val           => l_return_val);
5871 
5872              IF NOT(l_return_val) THEN
5873                 l_due_date := sysdate;
5874              ELSE
5875                 l_due_date := l_counter_read_date;
5876              END IF;
5877 
5878           ELSIF (l_counter_remain = 0) THEN  -- due_date = sysdate
5879             --dbms_output.put_line ('counter remain less than zero');
5880             l_due_date := sysdate;
5881           END IF;
5882 
5883           IF (l_calc_due_date IS NOT NULL AND l_mr_interval_found = TRUE) OR  -- case where intervals exist.
5884              (l_mr_interval_found = FALSE)  THEN    -- case where no intervals.
5885             -- Compare with whichever first code and set l_calc_due_date.
5886             IF (l_due_date IS NULL) THEN
5887                --dbms_output.put_line ('due date null');
5888                l_calc_due_date := l_due_date;
5889                x_next_due_date_rec.due_date := null;
5890                x_next_due_date_rec.tolerance_after := null;
5891                x_next_due_date_rec.tolerance_before := null;
5892                x_next_due_date_rec.mr_interval_id := null;
5893                x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
5894                x_next_due_date_rec.mr_effectivity_id := null;
5895                x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5896                x_next_due_date_rec.last_ctr_value := null;
5897                x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
5898                x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
5899                x_next_due_date_rec.counter_remain := l_counter_remain;
5900                l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
5901                EXIT;
5902             ELSE  -- happens when no interval
5903               IF (l_calc_due_date IS NULL) THEN
5904                  --dbms_output.put_line ('calc due date null');
5905                  l_calc_due_date := l_due_date;
5906                  x_next_due_date_rec.due_date := l_due_date;
5907                  x_next_due_date_rec.tolerance_after := null;
5908                  x_next_due_date_rec.tolerance_before := null;
5909                  x_next_due_date_rec.mr_interval_id := null;
5910                  x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
5911                  x_next_due_date_rec.mr_effectivity_id := null;
5912                  x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5913                  x_next_due_date_rec.last_ctr_value := null;
5914                  x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
5915                  x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
5916                  x_next_due_date_rec.counter_remain := l_counter_remain;
5917                  l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
5918 
5919               ELSE
5920                  IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
5921                     -- Check due date based on whichever_first_code.
5922                     IF (l_calc_due_date > l_due_date) THEN
5923                         l_calc_due_date := l_due_date;
5924                         x_next_due_date_rec.due_date := l_due_date;
5925                         x_next_due_date_rec.tolerance_after := null;
5926                         x_next_due_date_rec.tolerance_before := null;
5927                         x_next_due_date_rec.mr_interval_id := null;
5928                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
5929                         x_next_due_date_rec.mr_effectivity_id := null;
5930                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5931                         x_next_due_date_rec.last_ctr_value := null;
5932                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
5933                         x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
5934                         x_next_due_date_rec.counter_remain := l_counter_remain;
5935                         l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
5936 
5937                     END IF;
5938                  ELSE  -- whichever_first_code = 'LAST'
5939                     IF (l_calc_due_date < l_due_date) THEN
5940                         --dbms_output.put_line ('set due date');
5941                         l_calc_due_date := l_due_date;
5942                         x_next_due_date_rec.due_date := l_due_date;
5943                         x_next_due_date_rec.tolerance_after := null;
5944                         x_next_due_date_rec.tolerance_before := null;
5945                         x_next_due_date_rec.mr_interval_id := null;
5946                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
5947                         x_next_due_date_rec.mr_effectivity_id := null;
5948                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
5949                         x_next_due_date_rec.last_ctr_value := null;
5950                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
5951                         x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
5952                         x_next_due_date_rec.counter_remain := l_counter_remain;
5953                         l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
5954 
5955                     END IF;
5956                  END IF; -- applicable_mrs_rec
5957               END IF; -- calc_due_date null
5958             END IF;
5959           END IF; -- calc due date and l_mr_interval_found.
5960         END LOOP; -- set_threshold_rec
5961 
5962         -- Check for set due date.
5963         IF (l_set_due_date IS NOT NULL) THEN
5964            IF (l_calc_due_date IS NOT NULL AND l_mr_interval_found = TRUE) OR  -- case where intervals exist.
5965               (l_mr_interval_found = FALSE)  THEN    -- case where no intervals.
5966 
5967               IF (l_calc_due_date IS NULL) THEN
5968                  l_calc_due_date := l_set_due_date;
5969                  x_next_due_date_rec.due_date := l_set_due_date;
5970                  x_next_due_date_rec.tolerance_after := null;
5971                  x_next_due_date_rec.tolerance_before := null;
5972                  x_next_due_date_rec.mr_effectivity_id := null;
5973                  x_next_due_date_rec.due_at_counter_value := null;
5974                  x_next_due_date_rec.current_ctr_value := null;
5975                  x_next_due_date_rec.last_ctr_value := null;
5976                  x_next_due_date_rec.mr_interval_id := null;
5977                  x_next_due_date_rec.ctr_uom_code := null;
5978                  x_next_due_date_rec.counter_id := null;
5979                  x_next_due_date_rec.counter_remain := null;
5980                  l_calc_due_date_ctr_id := null;
5981 
5982               ELSE
5983                  IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
5984                      IF (l_calc_due_date > l_set_due_date) THEN
5985                        --dbms_output.put_line ('set due da te');
5986                        l_calc_due_date := l_set_due_date;
5987                        x_next_due_date_rec.due_date := l_set_due_date;
5988                        x_next_due_date_rec.tolerance_after := null;
5989                        x_next_due_date_rec.tolerance_before := null;
5990                        x_next_due_date_rec.mr_interval_id := null;
5991                        x_next_due_date_rec.due_at_counter_value := null;
5992                        x_next_due_date_rec.mr_effectivity_id := null;
5993                        x_next_due_date_rec.current_ctr_value := null;
5994                        x_next_due_date_rec.last_ctr_value := null;
5995                        x_next_due_date_rec.ctr_uom_code := null;
5996                        x_next_due_date_rec.counter_id := null;
5997                        x_next_due_date_rec.counter_remain := null;
5998                        l_calc_due_date_ctr_id := null;
5999 
6000                      END IF;
6001                  ELSE
6002                     -- Check for set due date.
6003                     IF (l_calc_due_date < l_set_due_date) THEN
6004                         l_calc_due_date := l_set_due_date;
6005                         x_next_due_date_rec.due_date := l_set_due_date;
6006                         x_next_due_date_rec.tolerance_after := null;
6007                         x_next_due_date_rec.tolerance_before := null;
6008                         x_next_due_date_rec.mr_interval_id := null;
6009                         x_next_due_date_rec.due_at_counter_value := null;
6010                         x_next_due_date_rec.mr_effectivity_id := null;
6011                         x_next_due_date_rec.current_ctr_value := null;
6012                         x_next_due_date_rec.last_ctr_value := null;
6013                         x_next_due_date_rec.ctr_uom_code := null;
6014                         x_next_due_date_rec.counter_id := null;
6015                         x_next_due_date_rec.counter_remain := null;
6016                         l_calc_due_date_ctr_id := null;
6017 
6018                     END IF;
6019                  END IF; -- applicable
6020                END IF;
6021             END IF;
6022          END IF;  -- set due date
6023      END IF; -- init_due_csr
6024      CLOSE ahl_init_due_csr;
6025   END IF; -- repetitive_flag
6026   */
6027   -- After processing all effectivities, check if any interval got triggered.
6028   -- If not, set all values to null and exit procedure.
6029   IF (x_next_due_date_rec.mr_effectivity_id IS NULL) AND
6030      (x_next_due_date_rec.mr_interval_id IS NULL) AND (l_calc_due_date IS NULL) AND
6031      (x_next_due_date_rec.counter_id IS NULL) THEN
6032       RAISE NO_VALID_INTERVAL;
6033   END IF;
6034 
6035   -- Evaluate tolerance condition.
6036   IF (x_next_due_date_rec.mr_interval_id IS NOT NULL) THEN
6037      IF ((x_next_due_date_rec.due_at_counter_value +
6038          x_next_due_date_rec.tolerance_after) < x_next_due_date_rec.current_ctr_value) THEN
6039          x_next_due_date_rec.tolerance_flag := 'Y';
6040          x_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
6041      END IF;
6042 
6043      -- Added for ER#2636001.
6044      -- Calculate earliest due date.
6045      IF x_next_due_date_rec.tolerance_before IS NOT NULL THEN
6046        -- Not required: If due date is today's date then earliest due = due date.
6047        IF (x_next_due_date_rec.due_date IS NOT NULL) THEN
6048           --IF (trunc(x_next_due_date_rec.due_date) = trunc(sysdate)) THEN
6049           --    x_next_due_date_rec.earliest_due_date := x_next_due_date_rec.due_date;
6050           --ELSE
6051             -- find the left over counter value
6052             IF (p_repetivity_flag = 'N') THEN
6053               l_counter_remain := (x_next_due_date_rec.due_at_counter_value -
6054                                    x_next_due_date_rec.tolerance_before) -
6055                                    x_next_due_date_rec.current_ctr_value;
6056             ELSE
6057               l_counter_remain := (x_next_due_date_rec.due_at_counter_value -
6058                                    x_next_due_date_rec.tolerance_before) -
6059                                    x_next_due_date_rec.last_ctr_value;
6060             END IF;
6061 
6062             IF (l_counter_remain < 0) THEN
6063                -- Due date = counter reading date.
6064                get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
6065                                          p_counter_id           => l_calc_due_date_ctr_id,
6066                                          p_counter_value        => x_next_due_date_rec.due_at_counter_value -
6067                                                                    x_next_due_date_rec.tolerance_before,
6068                                          x_ctr_record_date      => l_counter_read_date,
6069                                          x_return_val           => l_return_val);
6070                IF NOT(l_return_val) THEN
6071                   x_next_due_date_rec.earliest_due_date := null;
6072                ELSE
6073                   x_next_due_date_rec.earliest_due_date := l_counter_read_date;
6074                END IF;
6075                -- if earliest_due_date > due date (when no counters readings exist before counter remain).
6076                IF (x_next_due_date_rec.earliest_due_date > x_next_due_date_rec.due_date) THEN
6077                    x_next_due_date_rec.earliest_due_date := x_next_due_date_rec.due_date;
6078                END IF;
6079 
6080             ELSE /* counter_remain > 0 */
6081                -- get date from forecast.
6082                get_date_from_uf(l_counter_remain,
6083                                 x_next_due_date_rec.ctr_uom_code,
6084                                 p_counter_rules_tbl,
6085                                 l_start_date,
6086                                 x_next_due_date_rec.earliest_due_date);
6087                --IF (trunc(x_next_due_date_rec.earliest_due_date) < trunc(sysdate)) THEN
6088                -- x_next_due_date_rec.earliest_due_date := sysdate;
6089                --END IF;
6090             END IF; -- counter_remain.
6091          --END IF; -- due_date = sysdate.
6092        END IF; -- due date is not null.
6093      END IF; -- tolerance before.
6094 
6095      IF (x_next_due_date_rec.tolerance_after) IS NOT NULL THEN
6096        -- Calculate counter remain.
6097        IF (p_repetivity_flag = 'N') THEN
6098          l_counter_remain := (x_next_due_date_rec.due_at_counter_value +
6099                               x_next_due_date_rec.tolerance_after) -
6100                               x_next_due_date_rec.current_ctr_value;
6101        ELSE
6102          l_counter_remain := (x_next_due_date_rec.due_at_counter_value +
6103                               x_next_due_date_rec.tolerance_after) -
6104                               x_next_due_date_rec.last_ctr_value;
6105        END IF;
6106 
6107        IF G_DEBUG = 'Y' THEN
6108          AHL_DEBUG_PUB.Debug('Calculating latest due...uom_remain' || l_counter_remain);
6109        END IF;
6110 
6111        IF (l_counter_remain < 0) THEN
6112           -- Due date = counter reading date.
6113           get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
6114                                     p_counter_id           => l_calc_due_date_ctr_id,
6115                                     p_counter_value        => x_next_due_date_rec.due_at_counter_value +
6116                                                               x_next_due_date_rec.tolerance_after,
6117                                     x_ctr_record_date      => l_counter_read_date,
6118                                     x_return_val           => l_return_val);
6119 
6120           IF NOT(l_return_val) THEN
6121              x_next_due_date_rec.latest_due_date := null;
6122           ELSE
6123              x_next_due_date_rec.latest_due_date := l_counter_read_date;
6124              -- flag tolerance when latest due date < sysdate
6125              x_next_due_date_rec.tolerance_flag := 'Y';
6126              x_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
6127           END IF;
6128 
6129        ELSE   /* counter_remain > 0 */
6130           IF (x_next_due_date_rec.due_date >= sysdate) THEN
6131             -- Calculate latest tolerance.
6132             get_date_from_uf(x_next_due_date_rec.tolerance_after,
6133                              x_next_due_date_rec.ctr_uom_code,
6134                              p_counter_rules_tbl,
6135                              x_next_due_date_rec.due_date,
6136                              x_next_due_date_rec.latest_due_date);
6137           -- added to fix bug# 7646170
6138           ELSE
6139              -- Calculate latest tolerance.
6140              get_date_from_uf(l_counter_remain,
6141                               x_next_due_date_rec.ctr_uom_code,
6142                               p_counter_rules_tbl,
6143                               sysdate,
6144                               x_next_due_date_rec.latest_due_date);
6145 
6146           END IF;
6147        END IF; -- counter_remain.
6148      ELSE
6149         -- If due date is less than sysdate, then flag tolerance.
6150         IF (x_next_due_date_rec.due_date IS NOT NULL) AND
6151            (trunc(x_next_due_date_rec.due_date) < trunc(sysdate)) THEN
6152             x_next_due_date_rec.tolerance_flag := 'Y';
6153             x_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
6154         END IF;
6155 
6156      END IF;
6157      -- End of ER modifications.
6158   END IF;
6159 
6160   -- JKJain, NR Analysis and Forecasting
6161   x_next_due_date_rec.FLEET_ASSO_REJECTED := 'N';
6162 
6163   IF G_DEBUG = 'Y' THEN
6164      AHL_DEBUG_PUB.Debug('End calculate due date : x_next_due_date_rec.due_date = ' || x_next_due_date_rec.due_date);
6165   END IF;
6166 
6167 
6168 EXCEPTION
6169   WHEN DUE_DATE_NULL THEN
6170        x_next_due_date_rec.due_date := null;
6171        x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
6172        x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
6173        x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
6174        x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
6175        x_next_due_date_rec.mr_effectivity_id := null;
6176        x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
6177        x_next_due_date_rec.counter_remain := l_counter_remain;
6178        -- JKJain, NR Analysis and Forecasting
6179        IF (x_next_due_date_rec.due_date IS NULL AND x_next_due_date_rec.FLEET_ASSO_REJECTED = 'Y') THEN
6180             x_next_due_date_rec.due_date := l_fleet_reject_due_date;
6181               IF G_DEBUG = 'Y' THEN
6182               AHL_DEBUG_PUB.Debug('Inside DUE_DATE_NULL l_fleet_reject_due_date = '|| l_fleet_reject_due_date);
6183              END IF;
6184         END IF;
6185 
6186   WHEN NO_VALID_INTERVAL THEN
6187        x_next_due_date_rec.due_date := null;
6188        x_next_due_date_rec.tolerance_after := null;
6189        x_next_due_date_rec.tolerance_before := null;
6190        x_next_due_date_rec.mr_interval_id := null;
6191        x_next_due_date_rec.due_at_counter_value := null;
6192        x_next_due_date_rec.mr_effectivity_id := null;
6193        x_next_due_date_rec.current_ctr_value := null;
6194        x_next_due_date_rec.counter_remain := null;
6195        -- JKJain, NR Analysis and Forecasting
6196        IF (x_next_due_date_rec.due_date IS NULL AND x_next_due_date_rec.FLEET_ASSO_REJECTED = 'Y') THEN
6197            x_next_due_date_rec.due_date := l_fleet_reject_due_date;
6198             IF G_DEBUG = 'Y' THEN
6199               AHL_DEBUG_PUB.Debug('Inside NO_VALID_INTERVAL l_fleet_reject_due_date = '|| l_fleet_reject_due_date);
6200             END IF;
6201        END IF;
6202 
6203 END Calculate_Due_Date;
6204 
6205 -------------------------------------------------------------------------------------------
6206 -- Calculate due at counter values for a given due due from last due date and last due counters using
6207 -- counter rules and forecast (defined in global variable).
6208 
6209 PROCEDURE Get_Due_At_Counter_Values ( p_last_due_date IN DATE,
6210                                       p_last_due_counter_val_tbl IN counter_values_tbl_type,
6211                                       p_due_date IN DATE,
6212                                       p_counter_rules_tbl IN counter_rules_tbl_type,
6213                                       x_due_at_counter_val_tbl OUT NOCOPY counter_values_tbl_type,
6214                                       x_return_value           OUT NOCOPY BOOLEAN)
6215 IS
6216 
6217   l_diff_days  NUMBER := 0;
6218   l_counter_value NUMBER := 0;
6219   l_forecast_days NUMBER := 0;
6220   l_no_forecast BOOLEAN := FALSE;
6221   l_next_index NUMBER;
6222   l_start_date DATE;
6223   l_total_days_in_period NUMBER;
6224 
6225   l_index_found BOOLEAN;
6226 
6227 BEGIN
6228 
6229 
6230   IF G_DEBUG = 'Y' THEN
6231         AHL_DEBUG_PUB.Debug('Start get_due_at_counter_values');
6232   END IF;
6233 
6234   -- Initialize return value.
6235   x_return_value := TRUE;
6236 
6237   -- find the difference between last due and due dates.
6238   l_diff_days := ABS(trunc(p_due_date) - trunc(p_last_due_date));
6239   --dbms_output.put_line ('l_diff_days'|| l_diff_days);
6240 
6241   IF (SIGN(p_due_date - p_last_due_date) = -1) THEN
6242      l_start_date := p_due_date;
6243   ELSE
6244      l_start_date := p_last_due_date;
6245   END IF;
6246 
6247   --dbms_output.put_line ('l_start_date' || l_start_date);
6248   --dbms_output.put_line ('count on last due ctr val' ||   p_last_due_counter_val_tbl.COUNT);
6249 
6250   -- Loop through last due counter tbl.
6251   IF (p_last_due_counter_val_tbl.COUNT > 0) THEN
6252     FOR i IN p_last_due_counter_val_tbl.FIRST..p_last_due_counter_val_tbl.LAST LOOP
6253       l_next_index := G_forecast_details_tbl.FIRST;
6254       -- set the starting index matching the start date and uom in forecast table.
6255       IF (l_next_index IS NULL) THEN
6256            l_no_forecast := TRUE;
6257       ELSE
6258         l_no_forecast := TRUE;
6259         FOR k IN G_forecast_details_tbl.FIRST..G_forecast_details_tbl.LAST LOOP
6260           IF (G_forecast_details_tbl(k).uom_code = p_last_due_counter_val_tbl(i).uom_code)
6261              AND (trunc(G_forecast_details_tbl(k).start_date) <= trunc(l_start_date)
6262              AND trunc(l_start_date) <= trunc(nvl(G_forecast_details_tbl(k).end_date,l_start_date)))
6263           THEN
6264              l_next_index := k;
6265              l_no_forecast := FALSE;
6266              EXIT;
6267           END IF;
6268         END LOOP;
6269       END IF;
6270 
6271       -- Based on counter uom_code, last_due_date, l_diff_days and G_forecast_details_tbl build counter value.
6272       WHILE (l_diff_days <> 0 AND l_no_forecast <> TRUE) LOOP
6273         IF (G_forecast_details_tbl(l_next_index).uom_code = p_last_due_counter_val_tbl(i).uom_code) THEN
6274            IF (trunc(G_forecast_details_tbl(l_next_index).start_date) <= trunc(l_start_date) AND
6275              trunc(nvl(G_forecast_details_tbl(l_next_index).end_date,l_start_date)) >= trunc(l_start_date)) THEN
6276              IF (G_forecast_details_tbl(l_next_index).end_date) IS NOT NULL THEN
6277                l_total_days_in_period := trunc(G_forecast_details_tbl(l_next_index).end_date - l_start_date) + 1;
6278                --dbms_output.put_line ('total days in period' || l_total_days_in_period);
6279                IF (l_total_days_in_period >= l_diff_days) THEN
6280                   l_counter_value := l_counter_value + trunc(l_diff_days * G_forecast_details_tbl(l_next_index).usage_per_day);
6281                   l_diff_days := 0;
6282                   --dbms_output.put_line ('total >= ldiff; ctr val' || l_counter_value );
6283                ELSE
6284                   l_diff_days := l_diff_days - l_total_days_in_period;
6285                   l_counter_value := l_counter_value + trunc(l_total_days_in_period * G_forecast_details_tbl(l_next_index).usage_per_day);
6286                   --dbms_output.put_line ('total < ldiff; ctr val' || l_counter_value );
6287                   -- Get next forecast record.
6288                   l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
6289                   IF (l_next_index IS NULL) THEN
6290                     l_no_forecast := TRUE;
6291                   ELSE
6292                     l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
6293                   END IF;
6294                END IF; /* total days */
6295              ELSE
6296                 l_counter_value := l_counter_value + trunc(l_diff_days * G_forecast_details_tbl(l_next_index).usage_per_day);
6297                 l_diff_days := 0;
6298              END IF; /* end date */
6299            ELSE
6300              -- get next forecast record.
6301              l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
6302              IF (l_next_index IS NULL) THEN
6303                l_no_forecast := TRUE;
6304              ELSE
6305                l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
6306              END IF;
6307            END IF; /* start date */
6308         ELSE
6309           l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
6310           IF (l_next_index IS NULL) THEN
6311             l_no_forecast := TRUE;
6312           ELSE
6313             l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
6314           END IF;
6315         END IF; /* uom_code */
6316       END LOOP; /* while loop */
6317 
6318       IF (l_no_forecast = TRUE AND l_diff_days <> 0 ) THEN
6319         x_return_value := FALSE;
6320         EXIT;
6321       END IF;
6322 
6323       l_counter_value := Apply_ReverseCounter_Ratio ( l_counter_value,
6324                                                       p_last_due_counter_val_tbl(i).uom_code,
6325                                                       p_counter_rules_tbl);
6326 
6327       -- Add new counter values to return parameter.
6328       x_due_at_counter_val_tbl(i).counter_id := p_last_due_counter_val_tbl(i).counter_id;
6329       x_due_at_counter_val_tbl(i).counter_name := p_last_due_counter_val_tbl(i).counter_name;
6330 
6331       IF (SIGN(p_due_date - p_last_due_date) = -1) THEN
6332           l_counter_value := p_last_due_counter_val_tbl(i).counter_value - l_counter_value;
6333       ELSE
6334           l_counter_value := p_last_due_counter_val_tbl(i).counter_value + l_counter_value;
6335       END IF;
6336 
6337       x_due_at_counter_val_tbl(i).counter_value := l_counter_value;
6338       x_due_at_counter_val_tbl(i).uom_code := p_last_due_counter_val_tbl(i).uom_code;
6339 
6340       -- initialize start date.
6341       IF (SIGN(p_due_date - p_last_due_date) = -1) THEN
6342           l_start_date := p_due_date;
6343       ELSE
6344           l_start_date := p_last_due_date;
6345       END IF;
6346       -- Initialize counter value.
6347       l_counter_value := 0;
6348 
6349       l_diff_days := ABS(trunc(p_due_date) - trunc(p_last_due_date));
6350 
6351     END LOOP; /* for loop */
6352   END IF; /* count */
6353 
6354   IF G_DEBUG = 'Y' THEN
6355         AHL_DEBUG_PUB.Debug('End get_due_at_counter_values');
6356   END IF;
6357 
6358 END Get_Due_At_Counter_Values;
6359 
6360 ---------------------------------------------------------------------------
6361 -- Calculates the due date for the counter_remain from a given start date using forecast,
6362 -- counter rules and counter uom.
6363 
6364 PROCEDURE Get_Date_from_UF ( p_counter_remain IN NUMBER,
6365                              p_counter_uom_code IN VARCHAR2,
6366                              p_counter_rules_tbl IN counter_rules_tbl_type,
6367                              p_start_date IN DATE := NULL,
6368                              x_due_date         OUT NOCOPY DATE)
6369 IS
6370 
6371   l_counter_remain NUMBER := p_counter_remain;
6372   l_forecast_days NUMBER := 0;
6373   l_no_forecast BOOLEAN := FALSE;
6374   l_total_days_in_period NUMBER := 0;
6375   l_index_found BOOLEAN;
6376   l_next_index NUMBER := 0;
6377 
6378   l_start_date DATE;
6379 
6380 BEGIN
6381 
6382   IF G_DEBUG = 'Y' THEN
6383      AHL_DEBUG_PUB.Debug('Start get_date from UF');
6384      AHL_DEBUG_PUB.Debug('counter remain input to forecast' || p_counter_remain );
6385      AHL_DEBUG_PUB.Debug('counter uom' || p_counter_uom_code);
6386      AHL_DEBUG_PUB.Debug('Start date' || p_start_date);
6387   END IF;
6388 
6389   l_counter_remain := trunc(apply_counter_ratio (l_counter_remain,
6390                                                  p_counter_uom_code,
6391                                                  p_counter_rules_tbl));
6392   IF G_DEBUG = 'Y' THEN
6393     AHL_DEBUG_PUB.DEBUG('counter remain after ctr_ratio' || l_counter_remain );
6394   END IF;
6395 
6396   -- Start date to begin calculation.
6397   IF (p_start_date IS NULL) THEN
6398     l_start_date := trunc(sysdate);
6399   ELSE
6400     l_start_date:= p_start_date;
6401   END IF;
6402 
6403   -- Read g_forecast_details_tbl to get forecast values.
6404   l_next_index := G_forecast_details_tbl.FIRST;
6405   IF (l_next_index IS NULL) THEN
6406     --dbms_output.put_line ('l_next_index is null');
6407     x_due_date := null;
6408     RETURN;
6409   ELSE
6410     l_no_forecast := TRUE;
6411     FOR i IN G_forecast_details_tbl.FIRST..G_forecast_details_tbl.LAST LOOP
6412       IF (G_forecast_details_tbl(i).uom_code = p_counter_uom_code) AND
6413          (trunc(G_forecast_details_tbl(i).start_date) <= trunc(l_start_date) AND
6414           trunc(l_start_date) <= trunc(nvl(G_forecast_details_tbl(i).end_date,l_start_date)))
6415       THEN
6416          l_next_index := i;
6417          l_no_forecast := FALSE;
6418          EXIT;
6419       END IF;
6420     END LOOP;
6421   END IF;
6422 
6423    --dbms_output.put_line ('counter remain input to forecast' || l_counter_remain );
6424    --dbms_output.put_line ('counter uom' ||p_counter_uom_code);
6425 
6426   -- Calculate due date.
6427   WHILE ((l_counter_remain <> 0) AND (l_no_forecast <> TRUE )) LOOP
6428      IF (G_forecast_details_tbl(l_next_index).uom_code = p_counter_uom_code) THEN
6429         IF (trunc(G_forecast_details_tbl(l_next_index).start_date) <= trunc(l_start_date) AND
6430             trunc(nvl(G_forecast_details_tbl(l_next_index).end_date,sysdate)) >= trunc(sysdate)) THEN
6431 
6432             IF (G_forecast_details_tbl(l_next_index).end_date) IS NOT NULL THEN
6433                l_total_days_in_period := trunc(G_forecast_details_tbl(l_next_index).end_date - l_start_date) + 1;
6434 
6435                IF (G_forecast_details_tbl(l_next_index).usage_per_day <> 0) THEN
6436                  IF (trunc(l_total_days_in_period * G_forecast_details_tbl(l_next_index).usage_per_day) >= l_counter_remain) THEN
6437                     l_forecast_days := l_forecast_days + trunc(l_counter_remain/G_forecast_details_tbl(l_next_index).usage_per_day);
6438                     l_counter_remain := 0;
6439                  ELSE
6440                     l_counter_remain := l_counter_remain - trunc(l_total_days_in_period * G_forecast_details_tbl(l_next_index).usage_per_day);
6441                     l_forecast_days := l_forecast_days + l_total_days_in_period;
6442 
6443                     -- Get next forecast record.
6444                     l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
6445                     IF (l_next_index IS NULL) THEN
6446                       l_no_forecast := TRUE;
6447                     ELSE
6448                       l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
6449                     END IF;
6450 
6451                  END IF; /* total days */
6452                ELSE -- usage_per_day = 0
6453                  -- Get next forecast record.
6454                  l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
6455                  IF (l_next_index IS NULL) THEN
6456                     l_no_forecast := TRUE;
6457                  ELSE
6458                     l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
6459                  END IF;
6460                END IF; -- usage_per_day <> 0
6461             ELSE
6462                IF (G_forecast_details_tbl(l_next_index).usage_per_day <> 0) THEN
6463                  l_forecast_days := l_forecast_days + trunc(l_counter_remain/G_forecast_details_tbl(l_next_index).usage_per_day);
6464                  l_counter_remain := 0;
6465                ELSE -- usage = 0
6466                  -- Get next forecast record.
6467                  l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
6468                  IF (l_next_index IS NULL) THEN
6469                    l_no_forecast := TRUE;
6470                  ELSE
6471                    l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
6472                  END IF;
6473                END IF; -- usage_per_day <> 0
6474             END IF; /* end date */
6475         ELSE
6476           -- fix for bug# 7646170
6477           -- Get next forecast record.
6478           l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
6479           IF (l_next_index IS NULL) THEN
6480               l_no_forecast := TRUE;
6481           ELSE
6482               l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
6483           END IF;
6484 
6485         END IF; /* start date */
6486      ELSE
6487        l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
6488        IF (l_next_index IS NULL) THEN
6489          l_no_forecast := TRUE;
6490        ELSE
6491          l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
6492        END IF;
6493      END IF; /* uom_code */
6494 
6495   END LOOP; /* while */
6496 
6497   IF (l_no_forecast = TRUE AND l_counter_remain <> 0) THEN
6498     x_due_date  := null;
6499   ELSE
6500     IF (p_start_date IS NULL) THEN
6501       -- Added condition to avoid due date > 31-dec-9999 when forecast
6502       -- is very less (like .00001, .000001 etc)
6503       IF (l_forecast_days > (to_date('31/12/9999','DD/MM/YYYY') - trunc(sysdate))) THEN
6504           x_due_date  := null;
6505       ELSE
6506           x_due_date := trunc(sysdate + l_forecast_days);
6507       END IF;
6508     ELSE
6509       -- Added condition to avoid due date > 31-dec-9999 when forecast
6510       -- is very less (like .00001, .000001 etc)
6511       IF (l_forecast_days > (to_date('31/12/9999','DD/MM/YYYY') - trunc(p_start_date))) THEN
6512           x_due_date  := null;
6513       ELSE
6514           x_due_date := trunc(p_start_date + l_forecast_days);
6515       END IF;
6516     END IF;
6517   END IF;
6518 
6519   IF G_DEBUG = 'Y' THEN
6520      AHL_DEBUG_PUB.Debug('Date calculated by forecast:' || x_due_date);
6521      AHL_DEBUG_PUB.Debug('End Get_Date_from_UF');
6522   END IF;
6523 
6524 
6525 END Get_Date_from_UF;
6526 
6527 -------------------------------------------------------------------------------
6528 -- This will return the adjusted interval value if the next due counter value
6529 -- overlaps two intervals. It will be used where the overflow condition occurs
6530 -- based on the interval's start value and stop value.
6531 
6532 PROCEDURE Adjust_Interval_Value ( p_mr_effectivity_id IN NUMBER,
6533                                   p_counter_id IN NUMBER,
6534                                   p_counter_value IN NUMBER,
6535                                   p_interval_value IN NUMBER,
6536                                   p_stop_value IN NUMBER,
6537                                   x_adjusted_int_value OUT NOCOPY NUMBER,
6538                                   x_nxt_interval_found OUT NOCOPY BOOLEAN)
6539 IS
6540   -- read intervals for the effectivity id.
6541   CURSOR ahl_mr_intervalvalue_csr (p_mr_effectivity_id IN NUMBER,
6542                                    p_counter_id  IN NUMBER,
6543                                    p_counter_value IN NUMBER) IS
6544      /*
6545 	 SELECT INT.start_value, INT.stop_value,
6546             INT.interval_value
6547      FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
6548      WHERE  INT.counter_id = CTR.counter_id AND
6549             CTR.name = CN.name AND
6550             INT.mr_effectivity_id = p_mr_effectivity_id AND
6551             CN.counter_id = p_counter_id AND
6552             ( nvl(start_value, p_counter_value+1) <= p_counter_value AND
6553               --p_counter_value < nvl(stop_value, p_counter_value)
6554               p_counter_value < nvl(stop_value, p_counter_value + 1)--fix for bug number 3713078
6555             );
6556 	 */
6557 
6558 	 --Priyan
6559 	 --Query being changed due to performance related fixes
6560 	 --Refer Bug # 4918744
6561 
6562 	SELECT
6563 		INT.START_VALUE,
6564 		INT.STOP_VALUE,
6565 		INT.INTERVAL_VALUE
6566 	FROM
6567 		AHL_MR_INTERVALS INT,
6568 		CSI_COUNTER_TEMPLATE_VL CTR,
6569 		--CSI_COUNTER_TEMPLATE_VL CN --bug# 5918525
6570                 csi_counters_vl CN
6571 	WHERE
6572 		 INT.COUNTER_ID = CTR.COUNTER_ID AND
6573 		 --CTR.NAME = CN.NAME AND -- bug# 5918525
6574                  CTR.NAME = CN.counter_template_name AND
6575 		 INT.MR_EFFECTIVITY_ID = P_MR_EFFECTIVITY_ID AND
6576 		 CN.COUNTER_ID = P_COUNTER_ID AND
6577 		 (
6578 			NVL(START_VALUE, P_COUNTER_VALUE +1) <= P_COUNTER_VALUE AND
6579 			P_COUNTER_VALUE < NVL(STOP_VALUE, P_COUNTER_VALUE + 1)
6580 		 ) ;
6581 
6582   l_remaining_ctr_fraction NUMBER;  /* reminder fraction that needs to be interpolated with
6583                                     the interval value of the next mr interval record */
6584   l_overflow_value  NUMBER; /* the counter value that overflows to the next interval. */
6585   l_next_due_counter_value NUMBER;
6586 
6587   -- variables used in cursor fetch.
6588   l_start_value  NUMBER;
6589   l_stop_value NUMBER;
6590   l_interval_value NUMBER;
6591 
6592 BEGIN
6593 
6594   IF G_DEBUG = 'Y' THEN
6595         AHL_DEBUG_PUB.Debug('Start Adjust Interval Value');
6596   END IF;
6597 
6598   IF (p_stop_value IS NULL) THEN
6599     x_adjusted_int_value := p_interval_value;
6600     x_nxt_interval_found := TRUE;
6601   ELSE
6602     l_next_due_counter_value := p_counter_value + p_interval_value;
6603     l_overflow_value := l_next_due_counter_value - p_stop_value;
6604 
6605     x_adjusted_int_value := p_stop_value - p_counter_value;
6606 
6607     l_remaining_ctr_fraction := (l_overflow_value/p_interval_value);
6608 
6609     -- Get next record to match this interval.
6610     OPEN ahl_mr_intervalvalue_csr (p_mr_effectivity_id,
6611                                    p_counter_id,
6612                                    p_stop_value + 1);
6613     FETCH ahl_mr_intervalvalue_csr INTO l_start_value, l_stop_value, l_interval_value;
6614     IF (ahl_mr_intervalvalue_csr%NOTFOUND) THEN
6615 
6616         -- Fix for bug# 3461118.
6617         x_nxt_interval_found := FALSE;
6618         x_adjusted_int_value := p_interval_value;
6619     ELSE
6620         x_nxt_interval_found := TRUE;
6621         x_adjusted_int_value := x_adjusted_int_value + (l_remaining_ctr_fraction * l_interval_value);
6622     END IF; /* end ahl_mr_intervalvalue_csr if */
6623 
6624     CLOSE ahl_mr_intervalvalue_csr;
6625 
6626   END IF; /* p_stop_value if */
6627 
6628   --x_adjusted_int_value := trunc(x_adjusted_int_value);
6629   x_adjusted_int_value := x_adjusted_int_value;
6630 
6631   IF G_DEBUG = 'Y' THEN
6632         AHL_DEBUG_PUB.Debug('End Adjust Interval Value');
6633   END IF;
6634 
6635 
6636 END Adjust_Interval_Value;
6637 
6638 -----------------------------------------------------------------------------
6639 -- This will return the adjusted due date if the next due date overlaps two intervals.
6640 -- It will be used where the overflow condition occurs based on the interval's start
6641 -- date and stop date.
6642 
6643 PROCEDURE Adjust_Due_Date ( p_mr_effectivity_id IN NUMBER,
6644                             p_start_counter_rec IN counter_values_rec_type,
6645                             p_start_due_date    IN DATE,
6646                             p_counter_rules_tbl IN counter_rules_tbl_type,
6647                             p_interval_value IN NUMBER,
6648                             p_stop_date IN DATE,
6649                             p_due_date IN DATE,
6650                             x_adjusted_due_date OUT NOCOPY DATE,
6651                             x_adjusted_due_ctr  OUT NOCOPY NUMBER,
6652                             x_nxt_interval_found OUT NOCOPY BOOLEAN)
6653 
6654 IS
6655 
6656   l_return_val BOOLEAN;
6657 
6658   l_start_counter_tbl counter_values_tbl_type;
6659   l_stop_counter_tbl  counter_values_tbl_type;
6660 
6661   l_forecast_days NUMBER;
6662   l_temp_due_date DATE;
6663   l_next_due_counter_remain NUMBER;
6664   l_remaining_ctr_fraction NUMBER;
6665 --  l_remaining_ctr_value NUMBER;
6666 
6667   l_start_date DATE;
6668   l_stop_date  DATE;
6669   l_interval_value NUMBER;
6670   l_adjusted_due_ctr NUMBER;
6671 
6672   -- get the next interval record for the provided stop value.
6673   CURSOR ahl_mr_intervaldate_csr (p_mr_effectivity_id IN NUMBER,
6674                                   p_counter_id  IN NUMBER,
6675                                   p_stop_date   IN DATE) IS
6676     /* SELECT INT.start_date, INT.stop_date,
6677             INT.interval_value
6678      FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
6679      WHERE  INT.counter_id = CTR.counter_id AND
6680             CTR.name = CN.name AND
6681             INT.mr_effectivity_id = p_mr_effectivity_id AND
6682             CN.counter_id = p_counter_id AND
6683             trunc(INT.start_date) = trunc(p_stop_date);
6684 	*/
6685 
6686 	 --Priyan
6687 	 --Query being changed due to performance related fixes
6688 	 --Refer Bug # 4918744
6689 	 --Changes the usage of CS_COUNTERS_V to CSI_COUNTER_TEMPLATE_VL
6690 
6691 	SELECT
6692 	   INT.START_DATE,
6693 	   INT.STOP_DATE,
6694 	   INT.INTERVAL_VALUE
6695 	FROM
6696 	   AHL_MR_INTERVALS INT,
6697 	   CSI_COUNTER_TEMPLATE_VL CTR,
6698 	   --CSI_COUNTER_TEMPLATE_VL CN --bug# 5918525
6699            csi_counters_vl CN
6700 	WHERE
6701 	   INT.COUNTER_ID = CTR.COUNTER_ID
6702 	   --AND CTR.NAME = CN.NAME --bug# 5918525
6703            AND CTR.NAME = CN.counter_template_name
6704 	   AND INT.MR_EFFECTIVITY_ID = P_MR_EFFECTIVITY_ID
6705 	   AND CN.COUNTER_ID = P_COUNTER_ID
6706 	   AND TRUNC(INT.START_DATE) = TRUNC(P_STOP_DATE) ;
6707 
6708 BEGIN
6709 
6710   IF G_DEBUG = 'Y' THEN
6711         AHL_DEBUG_PUB.Debug('Start Adjust Due Date');
6712   END IF;
6713 
6714   IF (trunc(p_due_date) <= trunc(p_stop_date)) THEN
6715     x_adjusted_due_date := p_due_date;
6716     x_nxt_interval_found := TRUE;
6717   ELSE
6718     l_start_counter_tbl(1) := p_start_counter_rec;
6719 
6720     -- Get counter values for stop date.
6721     Get_Due_At_Counter_Values (p_last_due_date => p_start_due_date,
6722                                p_last_due_counter_val_tbl => l_start_counter_tbl,
6723                                p_due_date => p_stop_date,
6724                                p_counter_rules_tbl => p_counter_rules_tbl,
6725                                x_due_at_counter_val_tbl => l_stop_counter_tbl,
6726                                x_return_value  => l_return_val);
6727 
6728     IF NOT(l_return_val) THEN
6729       x_adjusted_due_date := p_due_date;
6730       x_nxt_interval_found := FALSE;
6731     ELSE
6732       l_next_due_counter_remain := l_stop_counter_tbl(1).counter_value - p_start_counter_rec.counter_value;
6733       l_adjusted_due_ctr := l_next_due_counter_remain;
6734       l_remaining_ctr_fraction := 1 - (l_next_due_counter_remain/p_interval_value);
6735 
6736       -- Get next record to match this interval.
6737 
6738       OPEN ahl_mr_intervalDate_csr (p_mr_effectivity_id,
6739                                      p_start_counter_rec.counter_id,
6740                                      p_stop_date+1);
6741       FETCH ahl_mr_intervalDate_csr INTO l_start_date, l_stop_date, l_interval_value;
6742       IF (ahl_mr_intervalDate_csr%NOTFOUND) THEN
6743           -- Fix for bug# 3461118.
6744           x_adjusted_due_date := p_due_date;
6745           x_nxt_interval_found := FALSE;
6746       ELSE
6747 
6748           l_next_due_counter_remain := trunc(l_remaining_ctr_fraction * l_interval_value);
6749           x_nxt_interval_found := TRUE;
6750 
6751           -- Based on forecast get the due date.
6752           Get_Date_from_UF ( p_counter_remain => l_next_due_counter_remain,
6753                              p_counter_uom_code => p_start_counter_rec.uom_code,
6754                              p_counter_rules_tbl => p_counter_rules_tbl,
6755                              p_start_date => p_stop_date,
6756                              x_due_date => l_temp_due_date );
6757           -- l_temp_due_date is with respect to sysdate.
6758           IF (l_temp_due_date IS NULL) THEN
6759             x_adjusted_due_date := p_due_date;
6760           ELSE
6761             x_adjusted_due_date := l_temp_due_date;
6762             x_adjusted_due_ctr  := l_adjusted_due_ctr + l_next_due_counter_remain;
6763           END IF;
6764       END IF; /* end ahl_mr_intervalDate_csr if */
6765       CLOSE ahl_mr_intervalDate_csr;
6766     END IF;
6767   END IF;
6768 
6769   IF G_DEBUG = 'Y' THEN
6770         AHL_DEBUG_PUB.Debug('End Adjust Interval Value');
6771   END IF;
6772 
6773 
6774 END Adjust_Due_Date;
6775 
6776 -----------------------------------------------------------------------------
6777 -- This procedure will return due date based on the next interval(if exists),
6778 -- whenever an interval is not found for the current start/stop values or dates.
6779 -- Added parameter p_dependent_mr_flag to fix bug# 6711228.
6780 -- Added parameter p_mr_accomplish_exists and p_last_due_mr_interval_id to fix
6781 -- bug# 6858788. Commented p_last_accomplishment_date and will instead use p_mr_accomplish_exists.
6782 PROCEDURE Get_DueDate_from_NxtInterval(p_applicable_mrs_rec       IN  applicable_mrs_rec_type,
6783                                        p_repetivity_flag          IN  VARCHAR2,
6784                                        p_mr_effectivity_id        IN  NUMBER,
6785                                        p_current_ctr_rec          IN  Counter_values_rec_type,
6786                                        p_current_ctr_at_date      IN  DATE,
6787                                        p_counter_rules_tbl        IN  Counter_rules_tbl_type,
6788                                        p_start_int_match_at_ctr   IN  NUMBER,
6789                                        p_last_accomplish_ctr_val  IN  NUMBER,
6790                                        --p_last_accomplishment_date IN  DATE,
6791                                        p_dependent_mr_flag        IN  BOOLEAN,
6792                                        p_mr_accomplish_exists     IN  BOOLEAN,
6793                                        p_last_due_mr_interval_id  IN  NUMBER,
6794                                        x_next_due_date_rec        OUT NOCOPY next_due_date_rec_type,
6795                                        x_mr_interval_found        OUT NOCOPY BOOLEAN,
6796                                        x_return_val               OUT NOCOPY BOOLEAN)
6797 IS
6798 
6799   CURSOR ahl_next_interval_ctr_csr (p_mr_effectivity_id IN NUMBER,
6800                                     --p_counter_id        IN NUMBER,
6801                                     p_counter_name      IN VARCHAR2,
6802                                     p_counter_value     IN NUMBER) IS
6803     /*
6804 	SELECT  INT.mr_interval_id, INT.start_date, INT.stop_date,
6805             INT.start_value, INT.stop_value, INT.counter_id,
6806             INT.interval_value, INT.tolerance_after, INT.tolerance_before
6807      -- Replaced cs_counters_v with cs_counters to fix perf bug# 3786647.
6808      --FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
6809      FROM   ahl_mr_intervals INT, cs_counters CTR, cs_counters CN
6810      WHERE  INT.counter_id = CTR.counter_id AND
6811             CTR.name = CN.name AND
6812             INT.mr_effectivity_id = p_mr_effectivity_id AND
6813             CN.counter_id = p_counter_id AND
6814             INT.start_value > p_counter_value
6815      ORDER BY INT.start_value;
6816 	*/
6817 
6818 	 --Priyan
6819 	 --Query being changed due to performance related fixes
6820 	 --Refer Bug # 4918744
6821 	 --Changes the usage of CS_COUNTERS_V to CSI_COUNTER_TEMPLATE_VL
6822      -- select first row only.
6823      SELECT *
6824      FROM (
6825 	  SELECT
6826 	   INT.MR_INTERVAL_ID,
6827 	   INT.START_DATE,
6828   	   INT.STOP_DATE,
6829 	   INT.START_VALUE,
6830 	   INT.STOP_VALUE,
6831 	   INT.COUNTER_ID,
6832 	   INT.INTERVAL_VALUE,
6833 	   INT.TOLERANCE_AFTER,
6834 	   INT.TOLERANCE_BEFORE,
6835            INT.EARLIEST_DUE_VALUE,
6836            INT.CALC_DUEDATE_RULE_CODE -- added for ER 7415856
6837 	   FROM
6838 	   AHL_MR_INTERVALS INT,
6839 	   CSI_COUNTER_TEMPLATE_VL CTR --,
6840 	   --CSI_COUNTER_TEMPLATE_VL CN --bug# 5918525
6841            --csi_counters_vl CN
6842 	  WHERE
6843 	   INT.COUNTER_ID = CTR.COUNTER_ID
6844 	   -- AND CTR.NAME = CN.NAME --bug# 5918525
6845            --AND CTR.NAME = CN.counter_template_name
6846            AND CTR.NAME = p_counter_name
6847 	   AND INT.MR_EFFECTIVITY_ID = P_MR_EFFECTIVITY_ID
6848 	   --AND CN.COUNTER_ID = P_COUNTER_ID
6849 	   AND INT.START_VALUE > P_COUNTER_VALUE
6850 	  ORDER BY
6851 	   INT.START_VALUE ASC
6852           )
6853      WHERE ROWNUM < 2;
6854 
6855   CURSOR ahl_next_interval_date_csr (p_mr_effectivity_id IN NUMBER,
6856                                      --p_counter_id        IN NUMBER,
6857                                      p_counter_name      IN VARCHAR2,
6858                                      p_start_date        IN DATE) IS
6859 
6860     /*SELECT  INT.mr_interval_id, INT.start_date, INT.stop_date,
6861             INT.tolerance_after, INT.tolerance_before, INT.interval_value
6862      -- Replaced cs_counters_v with cs_counters to fix perf bug# 3786647.
6863      --FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
6864      FROM   ahl_mr_intervals INT, cs_counters CTR, cs_counters CN
6865      WHERE  INT.counter_id = CTR.counter_id AND
6866             CTR.name = CN.name AND
6867             INT.mr_effectivity_id = p_mr_effectivity_id AND
6868             CN.counter_id = p_counter_id AND
6869             INT.start_date > p_start_date
6870      ORDER BY INT.start_date;
6871 	*/
6872 
6873 	--Priyan
6874 	 --Query being changed due to performance related fixes
6875 	 --Refer Bug # 4918744
6876 	 --Changes the usage of CS_COUNTERS_V to CSI_COUNTER_TEMPLATE_VL
6877      -- select first row only.
6878      SELECT *
6879      FROM (
6880 	  SELECT
6881            INT.MR_INTERVAL_ID,
6882            INT.START_DATE,
6883            INT.STOP_DATE,
6884            INT.TOLERANCE_AFTER,
6885            INT.TOLERANCE_BEFORE,
6886            INT.INTERVAL_VALUE,
6887            INT.EARLIEST_DUE_VALUE,
6888            INT.CALC_DUEDATE_RULE_CODE -- added for ER 7415856
6889          FROM
6890 	   AHL_MR_INTERVALS INT,
6891 	   CSI_COUNTER_TEMPLATE_VL CTR --,
6892 	   --CSI_COUNTER_TEMPLATE_VL CN --bug# 5918525
6893            --csi_counters_vl CN
6894 	  WHERE
6895 	   INT.COUNTER_ID = CTR.COUNTER_ID
6896 	   --AND CTR.NAME = CN.NAME --bug# 5918525
6897            --AND CTR.NAME = CN.counter_template_name
6898            AND CTR.NAME = p_counter_name
6899 	   AND INT.MR_EFFECTIVITY_ID = P_MR_EFFECTIVITY_ID
6900 	   --AND CN.COUNTER_ID = P_COUNTER_ID
6901 	   AND INT.START_DATE > P_START_DATE
6902 	  ORDER BY
6903 	   INT.START_DATE ASC
6904           )
6905      WHERE ROWNUM < 2;
6906 
6907 
6908   l_counter_remain          NUMBER;
6909   l_counter_due_date        DATE; -- due date calculated using start-value of interval.
6910   l_current_ctr_tbl         counter_values_tbl_type;
6911   l_next_interval_ctr_rec   ahl_next_interval_ctr_csr%ROWTYPE;
6912   l_next_interval_date_rec  ahl_next_interval_date_csr%ROWTYPE;
6913   l_return_val              BOOLEAN;
6914   l_due_counter_tbl         counter_values_tbl_type;
6915   l_ctr_based               BOOLEAN; -- indicates if due date is based on start-value of interval.
6916   l_date_based              BOOLEAN; -- indicates if due date is based on start-date of interval.
6917 
6918   l_date_due_date           DATE;
6919   l_due_at_counter          NUMBER;
6920 
6921   l_mr_interval_found       BOOLEAN := FALSE; -- set to true if a future interval is found.
6922 
6923   -- Added to fix bug#4224867.
6924   l_date_based_counter_remain  NUMBER;
6925   l_ctr_based_counter_remain   NUMBER;
6926 
6927   -- Added to fix bug# 6358940.
6928   l_next_due_date_rec          next_due_date_rec_type;
6929   l_ctr_due_at_counter_value   NUMBER;
6930 
6931 BEGIN
6932 
6933    IF G_DEBUG = 'Y' THEN
6934         AHL_DEBUG_PUB.Debug('Start Get_DueDate_from_NxtInterval');
6935         AHL_DEBUG_PUB.Debug('Input Counter ID:' || p_current_ctr_rec.counter_id);
6936         AHL_DEBUG_PUB.Debug('Input Counter Name:' || p_current_ctr_rec.counter_name);
6937         AHL_DEBUG_PUB.Debug('Input Counter start value:' || p_start_int_match_at_ctr);
6938    END IF;
6939 
6940    -- Initialize.
6941    x_return_val := TRUE;
6942    l_ctr_based  := FALSE; -- indicates if due date is based on start-value of interval.
6943    l_date_based := FALSE; -- indicates if due date is based on start-date of interval.
6944 
6945    -- initialize.
6946    x_next_due_date_rec := l_next_due_date_rec;
6947 
6948    -- Find interval greater than the counter value.
6949    OPEN ahl_next_interval_ctr_csr(p_mr_effectivity_id,
6950                                   --p_current_ctr_rec.counter_id,
6951                                   p_current_ctr_rec.counter_name,
6952                                   p_start_int_match_at_ctr);
6953    FETCH ahl_next_interval_ctr_csr INTO l_next_interval_ctr_rec;
6954    IF (ahl_next_interval_ctr_csr%FOUND) THEN
6955      l_mr_interval_found := TRUE;
6956 
6957      l_counter_remain := l_next_interval_ctr_rec.start_value - p_current_ctr_rec.counter_value;
6958      l_ctr_due_at_counter_value := l_next_interval_ctr_rec.start_value;
6959 
6960      -- Added for ER 7415856
6961      -- if rule code is set as INTERVAL then add interval to due counter value.
6962      IF (l_next_interval_ctr_rec.calc_duedate_rule_code = 'INTERVAL') THEN
6963           l_counter_remain := l_next_interval_ctr_rec.start_value + l_next_interval_ctr_rec.interval_value
6964                               - p_current_ctr_rec.counter_value;
6965           l_ctr_due_at_counter_value := l_next_interval_ctr_rec.start_value
6966                                         + l_next_interval_ctr_rec.interval_value;
6967      END IF;
6968 
6969      -- Added to fix bug# 6358940
6970      -- here start value will not be a null value.
6971      IF (l_next_interval_ctr_rec.earliest_due_value IS NOT NULL
6972        AND p_repetivity_flag = 'N') THEN
6973         IF (p_mr_accomplish_exists = TRUE AND p_dependent_mr_flag = FALSE) THEN
6974           -- MR accomplishment exists.
6975           IF (p_last_accomplish_ctr_val >= l_next_interval_ctr_rec.earliest_due_value) THEN
6976              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
6977                                  - p_current_ctr_rec.counter_value;
6978              l_ctr_due_at_counter_value := p_last_accomplish_ctr_val
6979                                            + l_next_interval_ctr_rec.interval_value;
6980 
6981           END IF;
6982         END IF;
6983      ELSIF (l_next_interval_ctr_rec.earliest_due_value IS NULL AND p_repetivity_flag = 'N' AND
6984             p_mr_accomplish_exists = TRUE AND p_dependent_mr_flag = FALSE) THEN
6985              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
6986                                  - p_current_ctr_rec.counter_value;
6987              l_ctr_due_at_counter_value := p_last_accomplish_ctr_val
6988                                            + l_next_interval_ctr_rec.interval_value;
6989 
6990      END IF;
6991 
6992      -- Added to fix bug# 6858788(for repetity).
6993      IF (p_repetivity_flag = 'Y' AND p_last_due_mr_interval_id = l_next_interval_ctr_rec.mr_interval_id) THEN
6994             -- same interval threshold as previous due date calculation. Use
6995             -- interval value rather than start value.
6996              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
6997                                  - p_current_ctr_rec.counter_value;
6998              l_ctr_due_at_counter_value := p_last_accomplish_ctr_val
6999                                            + l_next_interval_ctr_rec.interval_value;
7000      -- case where last and current triggered intervals do not match. Ex: where group MR triggers.
7001      ELSIF (p_repetivity_flag = 'Y' AND l_next_interval_ctr_rec.earliest_due_value IS NOT NULL) THEN
7002          IF (p_last_accomplish_ctr_val >= l_next_interval_ctr_rec.earliest_due_value) THEN
7003             l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
7004                                 - p_current_ctr_rec.counter_value;
7005             l_ctr_due_at_counter_value := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value;
7006          END IF;
7007      ELSIF (p_repetivity_flag = 'Y' AND l_next_interval_ctr_rec.earliest_due_value IS NULL) THEN
7008           l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
7009                               - p_current_ctr_rec.counter_value;
7010           l_ctr_due_at_counter_value := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value;
7011 
7012      END IF;
7013 
7014      IF G_DEBUG = 'Y' THEN
7015        AHL_DEBUG_PUB.Debug('Found future interval with start value:' || l_next_interval_ctr_rec.start_value);
7016        AHL_DEBUG_PUB.Debug('Last due interval ID:' || p_last_due_mr_interval_id);
7017        AHL_DEBUG_PUB.Debug('Current interval ID:' || l_next_interval_ctr_rec.mr_interval_id);
7018        AHL_DEBUG_PUB.Debug('p_last_accomplish_ctr_val:' || p_last_accomplish_ctr_val);
7019        AHL_DEBUG_PUB.Debug('p_current_ctr_rec.counter_value:' || p_current_ctr_rec.counter_value);
7020        AHL_DEBUG_PUB.Debug('l_next_interval_date_rec.interval_value:' || l_next_interval_ctr_rec.interval_value);
7021        AHL_DEBUG_PUB.Debug('counter remain:' || l_counter_remain);
7022      END IF;
7023 
7024      -- l_counter_remain can be negative. Fix bug# 6739599.
7025      IF (l_counter_remain > 0) THEN
7026         -- calculate due date based on forecast.
7027         get_date_from_uf(l_counter_remain,
7028                          p_current_ctr_rec.uom_code,
7029                          p_counter_rules_tbl,
7030                          p_current_ctr_at_date,
7031                          l_counter_due_date);
7032      ELSIF (l_counter_remain = 0) THEN
7033         l_counter_due_date := trunc(sysdate);
7034      ELSIF (l_counter_remain < 0) THEN
7035         -- Due date = counter reading date.
7036         get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
7037                                   p_counter_id           => p_current_ctr_rec.counter_id,
7038                                   p_counter_value        => l_ctr_due_at_counter_value,
7039                                   x_ctr_record_date      => l_counter_due_date,
7040                                   x_return_val           => l_return_val);
7041         IF NOT(l_return_val) THEN
7042           l_counter_due_date := trunc(sysdate);
7043         END IF;
7044 
7045      END IF;
7046 
7047      --dbms_output.put_line ('due date by forecast' || l_due_date );
7048 
7049      /* commented to fix bug# 6907562.
7050      -- Check the due date value.
7051      IF (l_counter_due_date IS NULL) THEN
7052         CLOSE ahl_next_interval_ctr_csr;
7053         x_return_val := FALSE;
7054         RETURN;
7055      END IF;
7056      */
7057 
7058      -- fix bug# 4224867.
7059      l_ctr_based_counter_remain := l_counter_remain;
7060 
7061    END IF; -- ahl_next_ctr_interval_csr found.
7062 
7063    -- Now check for existence of interval, based on date range.
7064    OPEN ahl_next_interval_date_csr(p_mr_effectivity_id,
7065                                    --p_current_ctr_rec.counter_id,
7066                                    p_current_ctr_rec.counter_name,
7067                                    p_current_ctr_at_date);
7068    FETCH ahl_next_interval_date_csr INTO l_next_interval_date_rec;
7069    IF (ahl_next_interval_date_csr%FOUND) THEN
7070      l_mr_interval_found := TRUE;
7071 
7072      -- Added to fix bug# 6358940
7073      -- here start date will not be a null value.
7074      IF (l_next_interval_date_rec.earliest_due_value IS NOT NULL AND p_repetivity_flag = 'N') AND
7075         (p_mr_accomplish_exists = TRUE AND p_dependent_mr_flag = FALSE) AND -- MR accomplishment exists.
7076         (p_last_accomplish_ctr_val >= l_next_interval_date_rec.earliest_due_value) THEN
7077              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
7078                                  - p_current_ctr_rec.counter_value;
7079              l_due_at_counter := p_last_accomplish_ctr_val
7080                                  + l_next_interval_date_rec.interval_value;
7081 
7082      ELSIF (l_next_interval_date_rec.earliest_due_value IS NULL AND p_repetivity_flag = 'N' AND
7083             p_mr_accomplish_exists = TRUE AND p_dependent_mr_flag = FALSE) THEN
7084              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
7085                                  - p_current_ctr_rec.counter_value;
7086              l_due_at_counter := p_last_accomplish_ctr_val
7087                                  + l_next_interval_date_rec.interval_value;
7088 
7089      -- added to fix bug# 6858788(consider repetivity = Y).
7090      ELSIF (p_repetivity_flag = 'Y' AND p_last_due_mr_interval_id = l_next_interval_date_rec.mr_interval_id) THEN
7091             -- same interval threshold as previous due date calculation. Use
7092             -- interval value rather than start value.
7093              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
7094                                  - p_current_ctr_rec.counter_value;
7095              l_due_at_counter := p_last_accomplish_ctr_val
7096                                  + l_next_interval_date_rec.interval_value;
7097      -- added to fix bug# 6858788(consider repetivity = Y) where last and current interval triggered
7098      -- are not the same..
7099      ELSIF (l_next_interval_date_rec.earliest_due_value IS NOT NULL AND p_repetivity_flag = 'Y') AND
7100            (p_last_accomplish_ctr_val >= l_next_interval_date_rec.earliest_due_value) THEN
7101              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
7102                                  - p_current_ctr_rec.counter_value;
7103              l_due_at_counter := p_last_accomplish_ctr_val
7104                                  + l_next_interval_date_rec.interval_value;
7105      ELSIF (l_next_interval_date_rec.earliest_due_value IS NULL AND p_repetivity_flag = 'Y') THEN
7106              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
7107                                  - p_current_ctr_rec.counter_value;
7108              l_due_at_counter := p_last_accomplish_ctr_val
7109                                  + l_next_interval_date_rec.interval_value;
7110 
7111      ELSE
7112         --IF (ahl_next_interval_ctr_csr%FOUND) THEN
7113         -- Find the counter value as of l_next_interval_date_rec.start_date.
7114         l_current_ctr_tbl(1) := p_current_ctr_rec;
7115         Get_Due_At_Counter_Values (p_last_due_date => p_current_ctr_at_date,
7116                                    p_last_due_counter_val_tbl => l_current_ctr_tbl,
7117                                    p_due_date => l_next_interval_date_rec.start_date,
7118                                    p_counter_rules_tbl => p_counter_rules_tbl,
7119                                    x_due_at_counter_val_tbl => l_due_counter_tbl,
7120                                    x_return_value  => l_return_val);
7121         IF NOT(l_return_val) THEN
7122           CLOSE ahl_next_interval_date_csr;
7123           CLOSE ahl_next_interval_ctr_csr;
7124           -- set return values.
7125           x_return_val := FALSE;
7126           x_next_due_date_rec.due_date := l_counter_due_date;
7127           x_next_due_date_rec.tolerance_after := l_next_interval_ctr_rec.tolerance_after;
7128           x_next_due_date_rec.tolerance_before := l_next_interval_ctr_rec.tolerance_before;
7129           x_next_due_date_rec.mr_interval_id := l_next_interval_ctr_rec.mr_interval_id;
7130           x_next_due_date_rec.due_at_counter_value := null;
7131           x_next_due_date_rec.counter_remain := null;
7132 
7133           x_mr_interval_found := l_mr_interval_found;
7134 
7135           RETURN;
7136         END IF;
7137 
7138         -- Add interval to the counter value and get the due date for this.
7139         -- 11/01/07: due date should be l_next_interval_date_rec.start_date.
7140         l_counter_remain := l_due_counter_tbl(1).counter_value
7141                             -- + l_next_interval_date_rec.interval_value
7142                             - p_current_ctr_rec.counter_value;
7143 
7144         l_due_at_counter := l_due_counter_tbl(1).counter_value;
7145                             --+ l_next_interval_date_rec.interval_value;
7146 
7147         -- Added for ER 7415856
7148         -- if  rule code is set as INTERVAL then add interval to due counter value.
7149         IF (l_next_interval_date_rec.calc_duedate_rule_code = 'INTERVAL') THEN
7150              l_counter_remain := l_due_counter_tbl(1).counter_value + l_next_interval_date_rec.interval_value
7151                                  - p_current_ctr_rec.counter_value;
7152              l_due_at_counter := l_due_counter_tbl(1).counter_value
7153                                 + l_next_interval_date_rec.interval_value;
7154         END IF;
7155 
7156      END IF;
7157 
7158      IF G_DEBUG = 'Y' THEN
7159        AHL_DEBUG_PUB.Debug('Found future interval with start date:' || to_char(l_next_interval_date_rec.start_date,'DD-MON-YYYY'));
7160        AHL_DEBUG_PUB.Debug('counter remain:' || l_counter_remain);
7161        AHL_DEBUG_PUB.Debug('l_ctr_due_at_counter_value:' || l_ctr_due_at_counter_value);
7162        AHL_DEBUG_PUB.Debug('p_last_accomplish_ctr_val:' || p_last_accomplish_ctr_val);
7163        AHL_DEBUG_PUB.Debug('earliest_due_value:' || l_next_interval_date_rec.earliest_due_value);
7164      END IF;
7165 
7166      -- calculate due date based on forecast.
7167      get_date_from_uf(l_counter_remain,
7168                       p_current_ctr_rec.uom_code,
7169                       p_counter_rules_tbl,
7170                       p_current_ctr_at_date,
7171                       l_date_due_date);
7172 
7173      --dbms_output.put_line ('due date by forecast' || l_date_due_date );
7174 
7175      /* commented to fix bug# 6907562.
7176      -- Check the due date value.
7177      IF (l_date_due_date IS NULL) THEN
7178         CLOSE ahl_next_interval_ctr_csr;
7179         x_return_val := FALSE;
7180         RETURN;
7181      END IF;
7182      */
7183 
7184      -- fix bug# 4224867.
7185      l_date_based_counter_remain := l_counter_remain;
7186 
7187      IF (ahl_next_interval_ctr_csr%FOUND) THEN
7188        -- Pick one of l_date_due_date OR l_counter_due_date
7189        -- as the due_date based on whichever_first_code.
7190        -- Added null due date checks to fix bug# 6907562.
7191        IF (l_counter_due_date IS NULL OR l_date_due_date IS NULL) THEN
7192           IF (validate_for_duedate_reset(l_date_due_date,
7193                                      l_date_based_counter_remain,
7194                                      l_counter_due_date,
7195                                      p_current_ctr_rec.counter_id,
7196                                      l_ctr_based_counter_remain) = 'Y') THEN
7197              l_date_based := TRUE;
7198           ELSE
7199              l_ctr_based  := TRUE;
7200           END IF;
7201        ELSE
7202 
7203           IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
7204             IF (l_counter_due_date <= l_date_due_date) THEN
7205                l_ctr_based := TRUE;
7206             ELSE
7207                l_date_based := TRUE;
7208             END IF;
7209           ELSE --whichever_first_code = 'LAST'
7210             IF (l_counter_due_date < l_date_due_date) THEN
7211               l_date_based := TRUE;
7212             ELSE
7213               l_ctr_based := TRUE;
7214             END IF;
7215           END IF; -- whichever first code.
7216        END IF; -- l_counter_due_date IS NULL
7217      ELSE
7218        -- Here due_date = start_date counter + interval.
7219        l_date_based := TRUE;
7220      END IF; -- ahl_next_interval_ctr_csr.
7221    ELSIF (ahl_next_interval_ctr_csr%FOUND) THEN
7222      l_ctr_based := TRUE;
7223    END IF; -- ahl_next_interval_date_csr.
7224 
7225    CLOSE ahl_next_interval_ctr_csr;
7226    CLOSE ahl_next_interval_date_csr;
7227 
7228    -- set output parameters.
7229    IF (l_ctr_based) THEN
7230      x_next_due_date_rec.due_date := l_counter_due_date;
7231      x_next_due_date_rec.tolerance_after := l_next_interval_ctr_rec.tolerance_after;
7232      x_next_due_date_rec.tolerance_before := l_next_interval_ctr_rec.tolerance_before;
7233      x_next_due_date_rec.mr_interval_id := l_next_interval_ctr_rec.mr_interval_id;
7234      --x_next_due_date_rec.due_at_counter_value := l_next_interval_ctr_rec.start_value;
7235      x_next_due_date_rec.due_at_counter_value := l_ctr_due_at_counter_value;
7236      x_next_due_date_rec.counter_remain := l_ctr_based_counter_remain;
7237 
7238      /* commenting this out as this causes next repetity to be over interval
7239       * value (fix for bug# 6858788)
7240      -- Fix for bug# 6739599. l_counter_due_date can be a past date.
7241      IF (l_counter_due_date > trunc(sysdate)) THEN
7242        -- Check if the counter value on the due date is less than the due counter value.
7243        -- If less, add a day to the due date. This would ensure that the MR is performed not before
7244        -- the due counter value.
7245        l_current_ctr_tbl(1) := p_current_ctr_rec;
7246        Get_Due_At_Counter_Values (p_last_due_date => p_current_ctr_at_date,
7247                                   p_last_due_counter_val_tbl => l_current_ctr_tbl,
7248                                   p_due_date => l_counter_due_date,
7249                                   p_counter_rules_tbl => p_counter_rules_tbl,
7250                                   x_due_at_counter_val_tbl => l_due_counter_tbl,
7251                                   x_return_value  => l_return_val);
7252 
7253        IF (l_due_counter_tbl(1).counter_value < l_next_interval_ctr_rec.start_value) THEN
7254           l_counter_due_date := l_counter_due_date + 1;
7255           Get_Due_At_Counter_Values (p_last_due_date => p_current_ctr_at_date,
7256                                      p_last_due_counter_val_tbl => l_current_ctr_tbl,
7257                                      p_due_date => l_counter_due_date,
7258                                      p_counter_rules_tbl => p_counter_rules_tbl,
7259                                      x_due_at_counter_val_tbl => l_due_counter_tbl,
7260                                      x_return_value  => l_return_val);
7261           IF NOT(l_return_val) THEN  -- forecast not available.
7262             x_return_val := FALSE;
7263             RETURN;
7264           END IF;
7265 
7266           --x_next_due_date_rec.due_at_counter_value := l_due_counter_tbl(1).counter_value;
7267           x_next_due_date_rec.due_date := l_counter_due_date;
7268        END IF;
7269      END IF; -- l_counter_due_date > trunc(sysdate)
7270      */
7271    ELSIF (l_date_based) THEN
7272 
7273      x_next_due_date_rec.due_date := l_date_due_date;
7274      x_next_due_date_rec.tolerance_after := l_next_interval_date_rec.tolerance_after;
7275      x_next_due_date_rec.tolerance_before := l_next_interval_date_rec.tolerance_before;
7276      x_next_due_date_rec.mr_interval_id := l_next_interval_date_rec.mr_interval_id;
7277      x_next_due_date_rec.due_at_counter_value := l_due_at_counter;
7278      x_next_due_date_rec.counter_remain := l_date_based_counter_remain;
7279    END IF;
7280 
7281    x_mr_interval_found := l_mr_interval_found;
7282 
7283    IF G_DEBUG = 'Y' THEN
7284         AHL_DEBUG_PUB.Debug('End Get_DueDate_from_NxtInterval');
7285    END IF;
7286 
7287 END Get_DueDate_from_NxtInterval;
7288 
7289 -----------------------------------------------------------------------------
7290 -- Apply the counter ratio factor to convert a given counter value at a
7291 -- component level to the root instance. This is needed as forecast is only
7292 -- defined at root instance.
7293 
7294 FUNCTION Apply_Counter_Ratio ( p_counter_remain IN NUMBER,
7295                                p_counter_uom_code IN VARCHAR2,
7296                                p_counter_rules_tbl IN counter_rules_tbl_type)
7297 RETURN NUMBER IS
7298 
7299   l_counter_remain NUMBER := p_counter_remain;
7300 
7301 BEGIN
7302 
7303   IF G_DEBUG = 'Y' THEN
7304      AHL_DEBUG_PUB.Debug('Start Apply Counter Ratio');
7305   END IF;
7306 
7307   -- Loop through p_counter_rules_tbl.
7308   IF (p_counter_rules_tbl.COUNT > 0) THEN
7309     FOR i IN p_counter_rules_tbl.FIRST..p_counter_rules_tbl.LAST LOOP
7310       IF (p_counter_rules_tbl(i).uom_code = p_counter_uom_code) THEN
7311          l_counter_remain := p_counter_remain / p_counter_rules_tbl(i).ratio;
7312       END IF;
7313     END LOOP;
7314   END IF;
7315 
7316   IF G_DEBUG = 'Y' THEN
7317      AHL_DEBUG_PUB.Debug('End Apply Counter Ratio');
7318   END IF;
7319 
7320   RETURN l_counter_remain;
7321 
7322 END Apply_Counter_Ratio;
7323 
7324 -------------------------------------------------------------------------------
7325 -- Apply the counter ratio factor to convert a given counter value at a root
7326 -- instance level to the component. This is needed as forecast is only defined
7327 -- at root instance.
7328 
7329 FUNCTION Apply_ReverseCounter_Ratio ( p_counter_remain IN NUMBER,
7330                                       p_counter_uom_code IN VARCHAR2,
7331                                       p_counter_rules_tbl IN counter_rules_tbl_type)
7332 RETURN NUMBER IS
7333 
7334   l_counter_remain NUMBER := p_counter_remain;
7335 
7336 BEGIN
7337 
7338   IF G_DEBUG = 'Y' THEN
7339      AHL_DEBUG_PUB.Debug('Start Apply Reverse Counter Ratio');
7340   END IF;
7341 
7342 
7343   -- Loop through p_counter_rules_tbl.
7344   IF (p_counter_rules_tbl.COUNT > 0) THEN
7345     FOR i IN p_counter_rules_tbl.FIRST..p_counter_rules_tbl.LAST LOOP
7346       IF (p_counter_rules_tbl(i).uom_code = p_counter_uom_code) THEN
7347          l_counter_remain := p_counter_remain * p_counter_rules_tbl(i).ratio;
7348       END IF;
7349     END LOOP;
7350   END IF;
7351 
7352   IF G_DEBUG = 'Y' THEN
7353      AHL_DEBUG_PUB.Debug('End Apply Reverse Counter Ratio');
7354   END IF;
7355 
7356   RETURN l_counter_remain;
7357 
7358 END Apply_ReverseCounter_Ratio;
7359 
7360 ------------------------------------------------------------------------------
7361 -- To process the decendents in case the mr is a group MR.
7362 
7363 PROCEDURE Process_GroupMR (p_applicable_mrs_rec  IN applicable_mrs_rec_type,
7364                            p_new_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE,
7365                            p_unit_effectivity_tbl IN unit_effectivity_tbl_type,
7366                            p_old_UE_forecast_sequence IN NUMBER := -1)
7367 
7368 IS
7369 
7370   -- Read applicable group table for validation.
7371   -- In this table mr_header_id/csi_item_instance_id are parents
7372   -- and related_mr_header_id/related_csi_item_instance_id are children.
7373   CURSOR ahl_applicable_grp_csr( p_item_instance_id IN NUMBER,
7374                                  p_mr_header_id IN NUMBER,
7375                                  p_level IN NUMBER) IS
7376 
7377     SELECT mr_header_id, csi_item_instance_id,
7378            related_mr_header_id,
7379            related_csi_item_instance_id
7380     FROM ahl_applicable_mr_relns
7381     WHERE level = p_level
7382     START WITH mr_header_id = p_mr_header_id AND
7383                csi_item_instance_id = p_item_instance_id AND
7384                orig_mr_header_id = p_mr_header_id AND
7385                orig_csi_item_instance_id = p_item_instance_id AND
7386                relationship_code = 'PARENT'
7387     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
7388                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
7389                orig_mr_header_id = p_mr_header_id AND
7390                orig_csi_item_instance_id = p_item_instance_id AND
7391                relationship_code = 'PARENT'
7392     ORDER BY   level, mr_header_id, csi_item_instance_id;
7393 
7394   -- Read applicable group table for updates.
7395   CURSOR ahl_applicable1_grp_csr( p_item_instance_id IN NUMBER,
7396                                   p_mr_header_id IN NUMBER) IS
7397 
7398     SELECT mr_header_id, csi_item_instance_id, related_mr_header_id,
7399            related_csi_item_instance_id
7400     FROM ahl_applicable_mr_relns
7401     START WITH mr_header_id = p_mr_header_id AND
7402                csi_item_instance_id = p_item_instance_id AND
7403                orig_mr_header_id = p_mr_header_id AND
7404                orig_csi_item_instance_id = p_item_instance_id AND
7405                relationship_code = 'PARENT'
7406     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
7407                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
7408                orig_mr_header_id = p_mr_header_id AND
7409                orig_csi_item_instance_id = p_item_instance_id AND
7410                relationship_code = 'PARENT'
7411     ORDER BY   level, mr_header_id, csi_item_instance_id;
7412 
7413   -- for reading unit effectivity table.
7414   CURSOR ahl_ue_relns_csr ( p_unit_effectivity_id IN NUMBER, p_level IN NUMBER ) IS
7415     SELECT ue_id, related_ue_id
7416     FROM ahl_ue_relationships relns
7417     WHERE level = p_level
7418     START WITH ue_id = p_unit_effectivity_id AND
7419                relationship_code = 'PARENT'
7420     CONNECT BY PRIOR related_ue_id = ue_id AND
7421                originator_ue_id = p_unit_effectivity_id AND
7422                relationship_code = 'PARENT'
7423     ORDER BY   level;
7424 
7425   -- get related unit effectivities details.
7426   CURSOR ahl_ue_csr ( p_ue_id IN NUMBER,
7427                       p_related_ue_id IN NUMBER ) IS
7428     SELECT ue1.mr_header_id, ue1.csi_item_instance_id,
7429            ue2.mr_header_id related_mr_header_id,
7430            ue2.csi_item_instance_id related_csi_item_instance_id
7431     --FROM ahl_unit_effectivities_app_v ue1, ahl_unit_effectivities_app_v ue2
7432     FROM ahl_unit_effectivities_b ue1, ahl_unit_effectivities_b ue2
7433     WHERE ue1.unit_effectivity_id = p_ue_id AND
7434           ue2.unit_effectivity_id = p_related_ue_id;
7435 
7436   -- To check if mr has a preceding mr.
7437   CURSOR ahl_appl_mr_csr (p_item_instance_id IN NUMBER,
7438                           p_mr_header_id IN NUMBER) IS
7439    SELECT 'x'
7440    FROM ahl_applicable_mrs
7441    WHERE csi_item_instance_id = p_item_instance_id AND
7442          mr_header_id = p_mr_header_id AND
7443          implement_status_code <> 'OPTIONAL_DO_NOT_IMPLEMENT' AND
7444          preceding_mr_header_id IS NOT NULL;
7445 
7446   l_new_unit_effectivity_rec  ahl_temp_unit_effectivities%ROWTYPE;
7447   l_initialize_ue_rec         ahl_temp_unit_effectivities%ROWTYPE;
7448 
7449   l_junk  VARCHAR2(1);
7450   l_visit_end_date DATE;
7451   l_unit_effectivity_id  NUMBER;
7452   l_ue_id                NUMBER;
7453   l_related_ue_id        NUMBER;
7454 
7455   TYPE ue_details_rec_type IS RECORD (
7456      mr_header_id NUMBER,
7457      csi_item_instance_id NUMBER,
7458      related_mr_header_id NUMBER,
7459      related_csi_item_instance_id NUMBER,
7460      match_flag  VARCHAR2(1));
7461 
7462   l_ue_details_rec       ue_details_rec_type;
7463 
7464   TYPE l_ue_details_tbl_type IS TABLE OF ue_details_rec_type INDEX BY BINARY_INTEGER;
7465 
7466   l_ue_details_tbl       l_ue_details_tbl_type;
7467   l_grp_details_tbl      l_ue_details_tbl_type;
7468 
7469   l_grp_match  BOOLEAN;
7470   l_level NUMBER;
7471   l_reln_found BOOLEAN;
7472   l_appl_grp_found BOOLEAN;
7473 
7474   i NUMBER;
7475 
7476   l_visit_status    VARCHAR2(30);
7477 
7478  BEGIN
7479 
7480   IF G_DEBUG = 'Y' THEN
7481      AHL_DEBUG_PUB.Debug('Start Process Group MR');
7482   END IF;
7483 
7484   l_grp_match := FALSE; /* set default to be "no group" available to match against in ahl_unit_effectitivities. */
7485 
7486   IF (p_old_UE_forecast_sequence <> -1) THEN
7487   -- match the group tree under unit_effectivity_id in unit_effectivity_tbl(l_old_UE_forecast_sequence)
7488   -- with the one in ahl_applicable_mr_relns.
7489 
7490     l_level := 0;  /* tree level */
7491     l_unit_effectivity_id := p_unit_effectivity_tbl(p_old_UE_forecast_sequence).unit_effectivity_id;
7492 
7493     l_grp_match := TRUE;
7494     l_reln_found := TRUE; /* ue_relns record found */
7495     l_appl_grp_found := TRUE; /* applicable grp mrs found */
7496 
7497     -- Check if workorder already created.
7498     l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status (l_unit_effectivity_id);
7499 
7500     -- when UE is on shop floor or UE status is INIT-DUE, skip group MR comparison.
7501     -- This will be done later in flush_from_temp_table proc.
7502     IF (p_unit_effectivity_tbl(p_old_UE_forecast_sequence).status_code) = 'INIT-DUE'
7503        OR (nvl(l_visit_status,'x') IN ('RELEASED','CLOSED')) THEN
7504        null; -- for init-due status skip group MR comparison. This will be done later in flush_from_temp_table proc.
7505        -- We need the UE id inserted as the First Due info needs to be copied to new UE
7506     ELSE
7507 
7508       WHILE ( ((l_reln_found) OR (l_appl_grp_found)) AND (l_grp_match = TRUE)) LOOP
7509 
7510          l_level := l_level + 1;
7511          --dbms_output.put_line('level:' || l_level);
7512          i := 1;
7513          FOR l_ue_relns_rec IN ahl_ue_relns_csr(l_unit_effectivity_id, l_level) LOOP
7514              OPEN ahl_ue_csr(l_ue_relns_rec.ue_id, l_ue_relns_rec.related_ue_id);
7515              FETCH ahl_ue_csr INTO l_ue_details_tbl(i).mr_header_id,
7516                                    l_ue_details_tbl(i).csi_item_instance_id,
7517                                    l_ue_details_tbl(i).related_mr_header_id,
7518                                    l_ue_details_tbl(i).related_csi_item_instance_id;
7519              IF (ahl_ue_csr%NOTFOUND) THEN
7520                  FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_RELN_NOTFOUND');
7521                  FND_MESSAGE.Set_Token('UE_ID',l_ue_relns_rec.ue_id);
7522                  FND_MESSAGE.Set_Token('RELATED_UE_ID', l_ue_relns_rec.related_ue_id);
7523                  FND_MSG_PUB.ADD;
7524                  CLOSE ahl_ue_csr;
7525                  RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7526              END IF;
7527              --dbms_output.put_line ('found ue relns');
7528 
7529              l_ue_details_tbl(i).match_flag := 'N';
7530              i := i + 1;
7531              CLOSE ahl_ue_csr;
7532          END LOOP;
7533 
7534          IF (l_ue_details_tbl.COUNT > 0 ) THEN
7535             l_reln_found := TRUE;
7536          ELSE
7537             l_reln_found := FALSE;
7538          END IF;
7539          --dbms_output.put_line('count ue tbl' || l_ue_details_tbl.COUNT);
7540 
7541          -- from applicable_mrs_group.
7542          i := 1;
7543          FOR l_appl_grp_rec IN ahl_applicable_grp_csr(p_applicable_mrs_rec.csi_item_instance_id,
7544                                                       p_applicable_mrs_rec.mr_header_id,
7545                                                       l_level)
7546          LOOP
7547              l_grp_details_tbl(i).mr_header_id := l_appl_grp_rec.mr_header_id;
7548              l_grp_details_tbl(i).csi_item_instance_id := l_appl_grp_rec.csi_item_instance_id;
7549              l_grp_details_tbl(i).related_mr_header_id := l_appl_grp_rec.related_mr_header_id;
7550              l_grp_details_tbl(i).related_csi_item_instance_id := l_appl_grp_rec.related_csi_item_instance_id;
7551              l_grp_details_tbl(i).match_flag := 'N';
7552              i := i + 1;
7553          END LOOP;
7554 
7555          IF (l_grp_details_tbl.COUNT > 0 ) THEN
7556             l_appl_grp_found := TRUE;
7557          ELSE
7558             l_appl_grp_found := FALSE;
7559          END IF;
7560          --dbms_output.put_line('count grp tbl' || l_grp_details_tbl.COUNT);
7561 
7562          -- Now compare l_grp_details_tbl with l_ue_details_tbl.
7563          IF (l_grp_details_tbl.COUNT > 0 ) THEN
7564            FOR i IN l_grp_details_tbl.FIRST..l_grp_details_tbl.LAST LOOP
7565              -- match if entry present in l_ue_details_tbl.
7566 
7567              IF (l_ue_details_tbl.COUNT > 0 ) THEN
7568                FOR j IN l_ue_details_tbl.FIRST..l_ue_details_tbl.LAST LOOP
7569                  IF (l_ue_details_tbl(j).mr_header_id = l_grp_details_tbl(i).mr_header_id AND
7570                     l_ue_details_tbl(j).csi_item_instance_id = l_grp_details_tbl(i).csi_item_instance_id AND
7571                     l_ue_details_tbl(j).related_csi_item_instance_id = l_grp_details_tbl(i).related_csi_item_instance_id AND
7572                     l_ue_details_tbl(j).related_mr_header_id = l_grp_details_tbl(i).related_mr_header_id AND
7573                     l_ue_details_tbl(j).match_flag = 'N' AND
7574                     l_grp_details_tbl(i).match_flag = 'N') THEN
7575                     --l_ue_details_tbl.DELETE(j);
7576                     --l_grp_details_tbl.DELETE(i);
7577                     l_ue_details_tbl(j).match_flag := 'Y';
7578                     l_grp_details_tbl(i).match_flag := 'Y';
7579                      EXIT;
7580                  END IF;
7581                END LOOP; /* ue_details */
7582              END IF; /* count - ue_details */
7583            END LOOP; /* grp_details */
7584          END IF; /* count - grp_details */
7585 
7586          -- delete records from table where match flag is Y.
7587          IF (l_ue_details_tbl.COUNT > 0 ) THEN
7588            FOR j IN l_ue_details_tbl.FIRST..l_ue_details_tbl.LAST LOOP
7589              IF (l_ue_details_tbl(j).match_flag = 'Y') THEN
7590                 l_ue_details_tbl.DELETE(j);
7591              END IF;
7592            END LOOP;
7593          END IF;
7594 
7595          IF (l_grp_details_tbl.COUNT > 0 ) THEN
7596            FOR i IN l_grp_details_tbl.FIRST..l_grp_details_tbl.LAST LOOP
7597              IF (l_grp_details_tbl(i).match_flag = 'Y') THEN
7598                l_grp_details_tbl.DELETE(i);
7599              END IF;
7600            END LOOP;
7601          END IF;
7602 
7603          IF (l_ue_details_tbl.COUNT <= 0) AND (l_grp_details_tbl.COUNT <= 0) THEN
7604              l_grp_match := TRUE;
7605 
7606          ELSE
7607              l_grp_match := FALSE;
7608 
7609          END IF;
7610 
7611       END LOOP; /* while - level */
7612     END IF; -- status_code
7613 
7614   END IF; -- p_old_UE_forecast_sequence
7615 
7616   -- if trees match, then
7617   -- update the temp table record for orig MR with visit_end_date and unit_effectivity ID.
7618   IF (p_old_UE_forecast_sequence IS NOT NULL AND l_grp_match = TRUE) THEN
7619 
7620     -- get visit end date from unit_effectivity_tbl for l_old_UE_Forecast_sequence.
7621     l_visit_end_date := p_unit_effectivity_tbl(p_old_UE_forecast_sequence).visit_end_date;
7622     l_new_unit_effectivity_rec.unit_effectivity_id :=
7623                           p_unit_effectivity_tbl(p_old_UE_forecast_sequence).unit_effectivity_id;
7624 
7625   ELSE
7626     l_visit_end_date := null;
7627   END IF;
7628 
7629   -- construct temporary unit effectivity for group top node.
7630 
7631     l_new_unit_effectivity_rec.due_date := p_new_unit_effectivity_rec.due_date;
7632     l_new_unit_effectivity_rec.mr_interval_id := p_new_unit_effectivity_rec.mr_interval_id;
7633     l_new_unit_effectivity_rec.mr_effectivity_id := p_new_unit_effectivity_rec.mr_effectivity_id;
7634     l_new_unit_effectivity_rec.due_counter_value := p_new_unit_effectivity_rec.due_counter_value;
7635     l_new_unit_effectivity_rec.csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
7636     l_new_unit_effectivity_rec.mr_header_id := p_applicable_mrs_rec.mr_header_id;
7637     l_new_unit_effectivity_rec.repetitive_mr_flag := p_new_unit_effectivity_rec.repetitive_mr_flag;
7638     l_new_unit_effectivity_rec.visit_end_date := l_visit_end_date;
7639     l_new_unit_effectivity_rec.forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
7640     -- to indicate group.
7641     l_new_unit_effectivity_rec.orig_csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
7642     l_new_unit_effectivity_rec.orig_mr_header_id := p_applicable_mrs_rec.mr_header_id;
7643     l_new_unit_effectivity_rec.orig_forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
7644     -- Added for ER# 2636001.
7645     l_new_unit_effectivity_rec.earliest_due_date := p_new_unit_effectivity_rec.earliest_due_date;
7646     l_new_unit_effectivity_rec.latest_due_date := p_new_unit_effectivity_rec.latest_due_date;
7647     l_new_unit_effectivity_rec.counter_id := p_new_unit_effectivity_rec.counter_id;
7648 
7649     l_new_unit_effectivity_rec.tolerance_flag := p_new_unit_effectivity_rec.tolerance_flag;
7650     l_new_unit_effectivity_rec.tolerance_before := p_new_unit_effectivity_rec.tolerance_before;
7651     l_new_unit_effectivity_rec.tolerance_after := p_new_unit_effectivity_rec.tolerance_after;
7652 
7653 
7654   -- write into temp table.
7655     Create_temp_unit_effectivity(l_new_unit_effectivity_rec);
7656 
7657   -- Read group MR tree and apply details from p_next_due_rec_type.
7658   FOR l_mr_grp_rec IN ahl_applicable1_grp_csr(p_applicable_mrs_rec.csi_item_instance_id,
7659                                               p_applicable_mrs_rec.mr_header_id)
7660   LOOP
7661 
7662    l_new_unit_effectivity_rec := l_initialize_ue_rec;
7663 
7664     -- Build temp_unit_effectivity record and write into temporary table.
7665     -- fix bug#6530920: UOM remain issue for child MRs.
7666     l_new_unit_effectivity_rec.due_date := p_new_unit_effectivity_rec.due_date;
7667     l_new_unit_effectivity_rec.mr_interval_id := p_new_unit_effectivity_rec.mr_interval_id;
7668     l_new_unit_effectivity_rec.mr_effectivity_id := p_new_unit_effectivity_rec.mr_effectivity_id;
7669     l_new_unit_effectivity_rec.due_counter_value := p_new_unit_effectivity_rec.due_counter_value;
7670     l_new_unit_effectivity_rec.csi_item_instance_id := l_mr_grp_rec.related_csi_item_instance_id;
7671     l_new_unit_effectivity_rec.parent_csi_item_instance_id := l_mr_grp_rec.csi_item_instance_id;
7672     l_new_unit_effectivity_rec.mr_header_id := l_mr_grp_rec.related_mr_header_id;
7673     l_new_unit_effectivity_rec.parent_mr_header_id := l_mr_grp_rec.mr_header_id;
7674     l_new_unit_effectivity_rec.orig_csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
7675     l_new_unit_effectivity_rec.orig_mr_header_id := p_applicable_mrs_rec.mr_header_id;
7676     l_new_unit_effectivity_rec.orig_forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
7677     l_new_unit_effectivity_rec.repetitive_mr_flag := p_new_unit_effectivity_rec.repetitive_mr_flag;
7678     l_new_unit_effectivity_rec.visit_end_date := l_visit_end_date;
7679     l_new_unit_effectivity_rec.earliest_due_date := p_new_unit_effectivity_rec.earliest_due_date;
7680     l_new_unit_effectivity_rec.latest_due_date := p_new_unit_effectivity_rec.latest_due_date;
7681     l_new_unit_effectivity_rec.counter_id := p_new_unit_effectivity_rec.counter_id;
7682 
7683     l_new_unit_effectivity_rec.tolerance_flag := p_new_unit_effectivity_rec.tolerance_flag;
7684     l_new_unit_effectivity_rec.tolerance_before := p_new_unit_effectivity_rec.tolerance_before;
7685     l_new_unit_effectivity_rec.tolerance_after := p_new_unit_effectivity_rec.tolerance_after;
7686 
7687     l_new_unit_effectivity_rec.unit_effectivity_id := null;
7688 
7689     -- check if this mr has a preceding mr.
7690     OPEN ahl_appl_mr_csr (l_mr_grp_rec.related_csi_item_instance_id,
7691                           l_mr_grp_rec.related_mr_header_id);
7692     FETCH ahl_appl_mr_csr INTO l_junk;
7693     IF (ahl_appl_mr_csr%FOUND) THEN
7694        l_new_unit_effectivity_rec.preceding_check_flag:= 'Y';
7695     ELSE
7696        l_new_unit_effectivity_rec.preceding_check_flag:= 'N';
7697     END IF;
7698     CLOSE ahl_appl_mr_csr;
7699 
7700     -- write into temp table.
7701     Create_temp_unit_effectivity(l_new_unit_effectivity_rec);
7702 
7703   END LOOP;
7704 
7705   IF G_DEBUG = 'Y' THEN
7706      AHL_DEBUG_PUB.Debug('End Process GroupMR');
7707   END IF;
7708 
7709 END Process_GroupMR;
7710 
7711 -------------------------------------------------------------------------------------
7712 -- To process the dependent MRs based on the value of preceding MR.
7713 
7714 PROCEDURE Process_PrecedingMR (p_applicable_mrs_rec IN applicable_mrs_rec_type,
7715                                p_counter_rules_tbl  IN counter_rules_tbl_type,
7716                                p_current_usage_tbl  IN counter_values_tbl_type)
7717 IS
7718 
7719   -- Declare cursor to get all MRs that have preceding MR as that in applicable_mrs_rec.
7720   /* modified for performance
7721   CURSOR ahl_preceding_mr_csr (p_mr_header_id IN NUMBER,
7722                                p_item_instance_id IN NUMBER) IS
7723     SELECT mr.mr_header_id,
7724            apmr.csi_item_instance_id,
7725            apmr.Implement_status_code,
7726            apmr.copy_accomplishment_code,
7727            apmr.show_repetitive_code,
7728            --apmr.preceding_mr_header_id, -- fix for bug# 5922149
7729            curr_mr.mr_header_id preceding_mr_header_id,
7730            apmr.descendent_count,
7731            mr.whichever_first_code,
7732            apmr.repetitive_flag
7733     FROM ahl_mr_headers_app_v mr, ahl_mr_headers_b curr_mr, ahl_applicable_mrs apmr
7734     --fix for bug number 5922149
7735     --WHERE mr.preceding_mr_header_id = curr_mr.mr_header_id AND
7736     WHERE mr.preceding_mr_header_id IN (SELECT t.mr_header_id FROM ahl_mr_headers_b t where t.title = curr_mr.title ) AND
7737           curr_mr.mr_header_id = p_mr_header_id AND
7738           apmr.mr_header_id = mr.mr_header_id AND
7739           -- Fix for bug# 6711228.
7740           -- validation moved to before this procedure call.
7741           -- curr_mr.implement_status_code = 'MANDATORY' AND
7742           trunc(sysdate) >= trunc(nvl(mr.effective_from, sysdate)) AND
7743           trunc(sysdate) <= trunc(nvl(mr.effective_to, sysdate+1)) AND
7744           apmr.csi_item_instance_id = p_item_instance_id;
7745   */
7746 
7747   /* May20th 2011: rewrote query for SB Enhancements
7748   CURSOR ahl_preceding_mr_csr (p_curr_mr_title    IN VARCHAR2,
7749                                p_item_instance_id IN NUMBER) IS
7750     SELECT mr.mr_header_id,
7751            mr.version_number,
7752            apmr.csi_item_instance_id,
7753            apmr.Implement_status_code,
7754            apmr.copy_accomplishment_code,
7755            apmr.show_repetitive_code,
7756            --apmr.preceding_mr_header_id,
7757            apmr.descendent_count,
7758            mr.whichever_first_code,
7759            apmr.repetitive_flag,
7760            mr.title,
7761            mr.effective_from,
7762            mr.effective_to
7763     FROM ahl_mr_headers_app_v mr, ahl_applicable_mrs apmr
7764     WHERE mr.preceding_mr_header_id IN (SELECT t.mr_header_id FROM ahl_mr_headers_app_v t where t.title = p_curr_mr_title ) AND
7765           apmr.mr_header_id = mr.mr_header_id AND
7766           trunc(sysdate) >= trunc(nvl(mr.effective_from, sysdate)) AND
7767           --fix for bug# 9263774. Process prior MR versions.
7768           --trunc(sysdate) <= trunc(nvl(mr.effective_to, sysdate+1)) AND
7769           apmr.csi_item_instance_id = p_item_instance_id;
7770    */
7771 
7772   -- SB Enh: an MR can be initiated by more than one MRs. Due date for the
7773   -- 'initiated By' MR will be later of all of the MR due dates.
7774   CURSOR ahl_dependent_mr_csr (p_curr_mr_header_id IN NUMBER,
7775                                p_item_instance_id IN NUMBER) IS
7776    SELECT amr.related_mr_header_id mr_header_id,
7777            mr.version_number,
7778            apmr.csi_item_instance_id,
7779            apmr.Implement_status_code,
7780            apmr.copy_accomplishment_code,
7781            apmr.show_repetitive_code,
7782            apmr.descendent_count,
7783            mr.whichever_first_code,
7784            apmr.repetitive_flag,
7785            mr.title,
7786            mr.effective_from,
7787            mr.effective_to,
7788            apmr.terminate_trigger_check
7789      FROM ahl_mr_relationships amr, ahl_applicable_mrs apmr, ahl_mr_headers_b mr
7790     WHERE amr.mr_header_id = p_curr_mr_header_id
7791       AND amr.related_mr_header_id = apmr.mr_header_id
7792       AND amr.relationship_code = 'INITIATES'
7793       AND amr.related_mr_header_id = mr.mr_header_id
7794       AND apmr.csi_item_instance_id = p_item_instance_id
7795       -- select only those 'follow after' MRs if all parent MRs are processed.
7796       AND NOT EXISTS (SELECT 'x'
7797                       FROM ahl_mr_relationships amr1, ahl_applicable_mrs apmr1
7798                       WHERE amr1.related_mr_header_id = amr.related_mr_header_id
7799                         AND amr1.mr_header_id = apmr1.mr_header_id
7800                         AND amr1.relationship_code NOT IN ('TERMINATES')
7801                         AND (nvl(apmr1.process_status_flag,'N') = 'N'
7802                         -- initiating MR should either be mandatory OR should be accomplished
7803                         OR (apmr1.accomplished_ue_id IS NULL AND apmr1.implement_status_code <> 'MANDATORY'))
7804                         AND csi_item_instance_id = p_item_instance_id);
7805 
7806    l_dependent_mr_rec applicable_mrs_rec_type;
7807 
7808    k NUMBER := 0;
7809 
7810    -- Added for SB Enh: select initiating MR's earliest due date.
7811    CURSOR get_prec_mr_duedate_csr (p_mr_header_id IN NUMBER,
7812                                    p_item_instance_id IN number) IS
7813      SELECT * FROM (
7814        SELECT due_date, visit_end_date
7815        FROM ahl_temp_unit_effectivities
7816        WHERE csi_item_instance_id = p_item_instance_id AND
7817              mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1
7818                               where mr1.title = (select mr2.title from ahl_mr_headers_b mr2
7819                                                   where mr2.mr_header_id = p_mr_header_id)
7820                              ) AND
7821              preceding_check_flag = 'N'
7822 
7823        UNION
7824        SELECT due_date, visit_end_date
7825        FROM ahl_temp_unit_SR_deferrals
7826        WHERE csi_item_instance_id = p_item_instance_id AND
7827              mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1
7828                               where mr1.title = (select mr2.title from ahl_mr_headers_b mr2
7829                                                   where mr2.mr_header_id = p_mr_header_id )
7830                              )
7831        ORDER by due_date ASC
7832      )
7833      WHERE ROWNUM < 2;
7834 
7835    -- get all preceding MRs.
7836    CURSOR get_preceding_mrs_csr (p_item_instance_id IN number,
7837                                  p_follow_mr_header_id IN number) IS
7838 
7839      select amr.mr_header_id, apmr.accomplished_ue_id, apmr.process_status_flag
7840        from ahl_mr_relationships amr, ahl_applicable_mrs apmr
7841       where amr.mr_header_id = apmr.mr_header_id
7842         and amr.relationship_code = 'INITIATES'
7843         and amr.related_mr_header_id = p_follow_mr_header_id
7844         and apmr.csi_item_instance_id = p_item_instance_id;
7845 
7846    l_due_date            DATE;
7847    l_visit_end_date      DATE;
7848    l_preceding_mr_hdr_id NUMBER;
7849    l_max_due_date        DATE;
7850    l_acc_unit_effectivity_id NUMBER;
7851    l_acc_deferral_flag       BOOLEAN;
7852    l_acc_status_code         VARCHAR2(30);
7853    l_return_val              BOOLEAN;
7854 
7855 BEGIN
7856 
7857   IF G_DEBUG = 'Y' THEN
7858      AHL_DEBUG_PUB.Debug('Start Process PrecedingMR');
7859   END IF;
7860 
7861   -- Process mrs which are dependent on current mr and are applicable to the same item instance.
7862   --FOR l_appl_rec IN ahl_preceding_mr_csr(p_applicable_mrs_rec.mr_header_id,
7863   --                                       p_applicable_mrs_rec.csi_item_instance_id) LOOP
7864   -- Commented for SB Enh. With new model for SB Enh, we can use mr_header_id instead of title
7865   --FOR l_appl_rec IN ahl_preceding_mr_csr(p_applicable_mrs_rec.title,
7866   --                                       p_applicable_mrs_rec.csi_item_instance_id) LOOP
7867 
7868   FOR l_appl_rec IN ahl_dependent_mr_csr(p_applicable_mrs_rec.mr_header_id,
7869                                          p_applicable_mrs_rec.csi_item_instance_id) LOOP
7870 
7871      IF G_DEBUG = 'Y' THEN
7872        AHL_DEBUG_PUB.Debug('Found applicable dependent MR:CSI:' || l_appl_rec.MR_header_id || ':' || l_appl_rec.csi_item_instance_id);
7873        AHL_DEBUG_PUB.Debug('For applicable preceding MR:CSI:' || p_applicable_mrs_rec.MR_header_id || ':' || p_applicable_mrs_rec.csi_item_instance_id);
7874      END IF;
7875 
7876      -- Added for SB Enh.
7877      -- Find the preceding MR Id based on max due/accomplished date across all preceding MRs.
7878      FOR preceding_mr_rec IN get_preceding_mrs_csr(l_appl_rec.csi_item_instance_id,
7879                                                    l_appl_rec.MR_header_id) LOOP
7880         IF (nvl(preceding_mr_rec.process_status_flag,'N') <> 'Y') THEN
7881           l_preceding_mr_hdr_id := NULL;
7882           EXIT;
7883         END IF;
7884 
7885         -- get first accomplishment or get calculated due date.
7886         IF (preceding_mr_rec.accomplished_ue_id IS NOT NULL) THEN
7887            -- get first accomplishment.
7888            AHL_UMP_UTIL_PKG.get_first_accomplishment(p_applicable_mrs_rec.csi_item_instance_id,
7889                                                      preceding_mr_rec.mr_header_id,
7890                                                      l_due_date,
7891                                                      l_acc_unit_effectivity_id,
7892                                                      l_acc_deferral_flag,
7893                                                      l_acc_status_code,
7894                                                      l_return_val);
7895         ELSE
7896           OPEN get_prec_mr_duedate_csr(preceding_mr_rec.MR_header_id,
7897                                        p_applicable_mrs_rec.csi_item_instance_id);
7898           FETCH get_prec_mr_duedate_csr INTO l_due_date, l_visit_end_date;
7899           CLOSE get_prec_mr_duedate_csr;
7900           -- if UE is assigned to visit, then consider l_visit_end_date
7901           -- added null check to fix bug# 13891719
7902           IF (l_visit_end_date IS NOT NULL) THEN
7903             l_due_date := l_visit_end_date;
7904           END IF;
7905         END IF;
7906 
7907         IF (l_due_date IS NULL) THEN
7908           l_max_due_date := NULL;
7909           l_preceding_mr_hdr_id := preceding_mr_rec.mr_header_id;
7910           EXIT;
7911         ELSE
7912           -- compare with previous values
7913           IF (l_preceding_mr_hdr_id IS NULL) THEN
7914              l_preceding_mr_hdr_id := preceding_mr_rec.mr_header_id;
7915              l_max_due_date := l_due_date;
7916           ELSIF trunc(l_due_date) > trunc(l_max_due_date) THEN
7917              l_max_due_date := l_due_date;
7918              l_preceding_mr_hdr_id := preceding_mr_rec.mr_header_id;
7919           END IF;
7920         END IF;
7921      END LOOP;
7922 
7923      -- process only if l_preceding_mr_hdr_id has been set.
7924      IF (l_preceding_mr_hdr_id IS NOT NULL) THEN
7925 
7926        IF G_DEBUG = 'Y' THEN
7927          AHL_DEBUG_PUB.Debug('Calculated l_preceding_mr_hdr_id:' || l_preceding_mr_hdr_id);
7928        END IF;
7929        -- update ahl_applicable_mrs with preceding mr ID for further processing.
7930        UPDATE AHL_APPLICABLE_MRS
7931           SET PRECEDING_MR_HEADER_ID = l_preceding_mr_hdr_id
7932         WHERE csi_item_instance_id = l_appl_rec.csi_item_instance_id
7933           AND MR_header_id = l_appl_rec.MR_header_id;
7934 
7935        -- Build applicable_mrs_rec.
7936        l_dependent_mr_rec.csi_item_instance_id := l_appl_rec.csi_item_instance_id;
7937        l_dependent_mr_rec.MR_header_id := l_appl_rec.MR_header_id;
7938        l_dependent_mr_rec.Implement_status_code := l_appl_rec.Implement_status_code;
7939        l_dependent_mr_rec.copy_accomplishment_code := l_appl_rec.copy_accomplishment_code;
7940        l_dependent_mr_rec.show_repetitive_code := l_appl_rec.show_repetitive_code;
7941        -- commented for SB Enh.
7942        -- l_dependent_mr_rec.preceding_mr_header_id := p_applicable_mrs_rec.mr_header_id;
7943        l_dependent_mr_rec.preceding_mr_header_id := l_preceding_mr_hdr_id;
7944        l_dependent_mr_rec.descendent_count := l_appl_rec.descendent_count;
7945        l_dependent_mr_rec.whichever_first_code := l_appl_rec.whichever_first_code;
7946        l_dependent_mr_rec.repetitive_flag := l_appl_rec.repetitive_flag;
7947        l_dependent_mr_rec.title := l_appl_rec.title;
7948        l_dependent_mr_rec.version_number := l_appl_rec.version_number;
7949        l_dependent_mr_rec.effective_to := l_appl_rec.effective_to;
7950        l_dependent_mr_rec.effective_from := l_appl_rec.effective_from;
7951 
7952        -- added for bug# 9263774
7953        IF (l_dependent_mr_rec.effective_to < sysdate) THEN
7954          l_dependent_mr_rec.expired_mr_flag := 'Y';
7955        ELSE
7956          l_dependent_mr_rec.expired_mr_flag := 'N';
7957        END IF;
7958        -- added for SB Enh
7959        l_dependent_mr_rec.terminate_trigger_check := l_appl_rec.terminate_trigger_check;
7960 
7961        IF G_DEBUG = 'Y' THEN
7962          AHL_DEBUG_PUB.Debug('Process_PrecedingMR: Build Effectivity for MR:CSI:' || l_appl_rec.MR_header_id ||':' || l_appl_rec.csi_item_instance_id);
7963        END IF;
7964 
7965        Build_Effectivity (p_applicable_mrs_rec => l_dependent_mr_rec,
7966                           p_current_usage_tbl  => p_current_usage_tbl,
7967                           p_counter_rules_tbl  => p_counter_rules_tbl);
7968      END IF;
7969 
7970   END LOOP;
7971 
7972   IF G_DEBUG = 'Y' THEN
7973      AHL_DEBUG_PUB.Debug('End Process PrecedingMR');
7974   END IF;
7975 
7976 
7977 END Process_PrecedingMR;
7978 
7979 --------------------------------------------------------------------------------
7980 -- To update the preceding_check_flag in the temporary unit effectivities table.
7981 
7982 PROCEDURE Update_check_flag (p_applicable_mrs_rec IN applicable_mrs_rec_type,
7983                              p_dependent_mr_flag IN BOOLEAN,
7984                              p_next_due_date_rec IN next_due_date_rec_type)
7985 IS
7986 
7987   l_preceding_check_flag VARCHAR2(1);
7988 
7989 BEGIN
7990 
7991   IF G_DEBUG = 'Y' THEN
7992      AHL_DEBUG_PUB.Debug('Start Update Check Flag');
7993   END IF;
7994 
7995   IF (p_dependent_mr_flag) THEN
7996    /* i.e accomplishment is based on preceding MR */
7997     IF (p_next_due_date_rec.due_date IS NULL) THEN
7998        null; /* leave all preceding_check_flag = 'Y' */
7999     ELSE
8000        -- modified to fix bug# 9263774(due date calc for prior MR versions).
8001        UPDATE ahl_temp_unit_effectivities
8002        SET preceding_check_flag = 'N'
8003        WHERE csi_item_instance_id = p_applicable_mrs_rec.csi_item_instance_id
8004              --AND mr_header_id = p_applicable_mrs_rec.mr_header_id
8005              AND mr_header_id IN (select mr.mr_header_id
8006                                   from ahl_mr_headers_b mr
8007                                   where mr.title = p_applicable_mrs_rec.title)
8008              AND due_date >= p_next_due_date_rec.due_date;
8009     END IF;
8010   ELSE
8011    /* this MR has its accomplishments; update all records irrespective of due date */
8012     -- modified to fix bug# 9263774(due date calc for prior MR versions).
8013     UPDATE ahl_temp_unit_effectivities
8014     SET preceding_check_flag = 'N'
8015     WHERE csi_item_instance_id = p_applicable_mrs_rec.csi_item_instance_id
8016           --AND mr_header_id = p_applicable_mrs_rec.mr_header_id;
8017           AND mr_header_id IN (select mr.mr_header_id
8018                                  from ahl_mr_headers_b mr
8019                                 where mr.title = p_applicable_mrs_rec.title);
8020 
8021   END IF;
8022 
8023   IF G_DEBUG = 'Y' THEN
8024      AHL_DEBUG_PUB.Debug('End Update Check Flag');
8025   END IF;
8026 
8027 END Update_check_flag;
8028 
8029 
8030 -----------------------------------------------------------
8031 -- To write a record into ahl_temp_unit_effectivities.
8032 
8033 PROCEDURE Create_temp_unit_effectivity (X_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE)
8034 
8035 IS
8036 
8037 BEGIN
8038   IF G_DEBUG = 'Y' THEN
8039      AHL_DEBUG_PUB.Debug('Start Create Temporary Unit Effect');
8040   END IF;
8041 
8042   -- insert into temporary table.
8043   insert into ahl_temp_unit_effectivities (
8044     csi_item_instance_id,
8045     MR_header_id,
8046     due_date,
8047     mr_interval_id,
8048     mr_effectivity_id,
8049     due_counter_value,
8050     parent_csi_item_instance_id,
8051     parent_mr_header_id,
8052     orig_csi_item_instance_id,
8053     orig_mr_header_id,
8054     orig_forecast_sequence,
8055     preceding_csi_item_instance_id,
8056     preceding_mr_header_id,
8057     preceding_forecast_seq,
8058     forecast_sequence,
8059     tolerance_before,
8060     tolerance_after,
8061     preceding_check_flag,
8062     unit_effectivity_id,
8063     repetitive_mr_flag,
8064     tolerance_flag,
8065     message_code,
8066     service_line_id,
8067     program_mr_header_id,
8068     earliest_due_date,
8069     latest_due_date,
8070     counter_id,
8071     visit_end_date,
8072     accomplish_trigger_type,
8073     loop_chain_seq_num,
8074     start_mr_header_id,
8075     start_lc_ue_id,
8076     -- JKJain, NR Analysis and Forecasting
8077     fleet_header_id)
8078   values (
8079     X_unit_effectivity_rec.csi_item_instance_id,
8080     X_unit_effectivity_rec.MR_header_id,
8081     X_unit_effectivity_rec.due_date,
8082     X_unit_effectivity_rec.mr_interval_id,
8083     X_unit_effectivity_rec.mr_effectivity_id,
8084     X_unit_effectivity_rec.due_counter_value,
8085     X_unit_effectivity_rec.parent_csi_item_instance_id,
8086     X_unit_effectivity_rec.parent_mr_header_id,
8087     X_unit_effectivity_rec.orig_csi_item_instance_id,
8088     X_unit_effectivity_rec.orig_mr_header_id,
8089     X_unit_effectivity_rec.orig_forecast_sequence,
8090     X_unit_effectivity_rec.preceding_csi_item_instance_id,
8091     X_unit_effectivity_rec.preceding_mr_header_id,
8092     X_unit_effectivity_rec.preceding_forecast_seq,
8093     X_unit_effectivity_rec.forecast_sequence,
8094     X_unit_effectivity_rec.tolerance_before,
8095     X_unit_effectivity_rec.tolerance_after,
8096     X_unit_effectivity_rec.preceding_check_flag,
8097     X_unit_effectivity_rec.unit_effectivity_id,
8098     X_unit_effectivity_rec.repetitive_mr_flag,
8099     X_unit_effectivity_rec.tolerance_flag,
8100     X_unit_effectivity_rec.message_code,
8101     X_unit_effectivity_rec.service_line_id,
8102     X_unit_effectivity_rec.program_mr_header_id,
8103     X_unit_effectivity_rec.earliest_due_date,
8104     X_unit_effectivity_rec.latest_due_date,
8105     X_unit_effectivity_rec.counter_id,
8106     X_unit_effectivity_rec.visit_end_date,
8107     X_unit_effectivity_rec.accomplish_trigger_type,
8108     X_unit_effectivity_rec.loop_chain_seq_num,
8109     X_unit_effectivity_rec.start_mr_header_id,
8110     X_unit_effectivity_rec.start_lc_ue_id,
8111     X_unit_effectivity_rec.fleet_header_id
8112   );
8113 
8114   IF G_DEBUG = 'Y' THEN
8115      AHL_DEBUG_PUB.Debug('End Create Temp Unit Effect.');
8116   END IF;
8117 
8118 END Create_temp_unit_effectivity;
8119 
8120 
8121 ---------------------------------------------------------------------------
8122 -- To log error messages into a log file if called from concurrent process.
8123 
8124 PROCEDURE log_error_messages IS
8125 
8126 l_msg_count      NUMBER;
8127 l_msg_index_out  NUMBER;
8128 l_msg_data       VARCHAR2(2000);
8129 
8130 BEGIN
8131 
8132 IF G_DEBUG = 'Y' THEN
8133      AHL_DEBUG_PUB.Debug('Start log error messages');
8134 END IF;
8135 
8136  -- Standard call to get message count.
8137 l_msg_count := FND_MSG_PUB.Count_Msg;
8138 
8139 FOR i IN 1..l_msg_count LOOP
8140   FND_MSG_PUB.get (
8141       p_msg_index      => i,
8142       p_encoded        => FND_API.G_FALSE,
8143       p_data           => l_msg_data,
8144       p_msg_index_out  => l_msg_index_out );
8145 
8146   fnd_file.put_line(FND_FILE.LOG, 'Err message-'||l_msg_index_out||':' || l_msg_data);
8147   IF G_DEBUG = 'Y' THEN
8148      AHL_DEBUG_PUB.Debug('Err message-'||l_msg_index_out||':' || substr(l_msg_data,1,240));
8149   END IF;
8150 
8151 END LOOP;
8152 
8153 IF G_DEBUG = 'Y' THEN
8154      AHL_DEBUG_PUB.Debug('End log error messages');
8155 END IF;
8156 
8157 
8158 END log_error_messages;
8159 
8160 -----------------------------------------------------------------------
8161 --  Function    : Calls FMP and populates the AHL_APPLICABLE_MRS table
8162 --                for preventive maintenance installation.
8163 --  Pre-reqs    :
8164 --  Parameters  :
8165 --
8166 --  PopulatePM_Appl_MRs Parameters:
8167 --       p_csi_ii_id       IN  csi item instance id  Required
8168 --
8169 --
8170 --  End of Comments.
8171 
8172 PROCEDURE PopulatePM_Appl_MRs (
8173     p_csi_ii_id           IN            NUMBER,
8174     x_return_status       OUT  NOCOPY   VARCHAR2,
8175     x_msg_count           OUT  NOCOPY   NUMBER,
8176     x_msg_data            OUT  NOCOPY   VARCHAR2,
8177     x_UnSch_programs_tbl  OUT  NOCOPY   PMprogram_tbl_type)
8178 
8179 IS
8180  l_api_version            CONSTANT NUMBER := 1.0;
8181  l_appl_activities_tbl    AHL_FMP_PVT.applicable_activities_tbl_type;
8182  l_appl_programs_tbl      AHL_FMP_PVT.applicable_programs_tbl_type;
8183  l_pm_install_flag        VARCHAR2(1);
8184 
8185  l_duplicate_pgm_flag  BOOLEAN;
8186  l_pgm_index           NUMBER;
8187  l_UnSch_programs_tbl  PMprogram_tbl_type;
8188 
8189  l_activity_sch_exists_flag BOOLEAN;
8190 
8191 BEGIN
8192 
8193   IF G_DEBUG = 'Y' THEN
8194     AHL_DEBUG_PUB.debug('Start of PopulatePM_Appl_MRs');
8195   END IF;
8196 
8197   -- call api to fetch all applicable mrs for PM installation.
8198   AHL_FMP_PVT.get_pm_applicable_mrs(
8199                        p_api_version            => l_api_version,
8200                        p_init_msg_list          => FND_API.G_FALSE,
8201                        p_commit                 => FND_API.G_FALSE,
8202                        p_validation_level       => FND_API.G_VALID_LEVEL_FULL,
8203                        x_return_status          => x_return_status,
8204                        x_msg_count              => x_msg_count,
8205                        x_msg_data               => x_msg_data,
8206            	       p_item_instance_id       => p_csi_ii_id,
8207    		       x_applicable_activities_tbl     => l_appl_activities_tbl,
8208                        x_applicable_programs_tbl      => l_appl_programs_tbl);
8209 
8210 
8211   -- Raise errors if exceptions occur
8212   IF (x_return_status = FND_API.G_RET_STS_ERROR) THEN
8213     RAISE FND_API.G_EXC_ERROR;
8214   ELSIF (x_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
8215     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
8216   END IF;
8217 
8218   -- initialize.
8219   l_pgm_index := 0;
8220 
8221   -- Read programs table.
8222   IF (l_appl_programs_tbl.COUNT > 0) THEN
8223 
8224      FOR i IN l_appl_programs_tbl.FIRST..l_appl_programs_tbl.LAST LOOP
8225 
8226          l_activity_sch_exists_flag := TRUE;
8227 
8228          -- find the corressponding activities in l_appl_activities_tbl for the program.
8229          IF (l_appl_activities_tbl.COUNT > 0) THEN
8230             FOR j IN l_appl_activities_tbl.FIRST..l_appl_activities_tbl.LAST LOOP
8231                IF (l_appl_activities_tbl(j).service_line_id = l_appl_programs_tbl(i).service_line_id)
8232                THEN
8233 
8234                     INSERT INTO AHL_APPLICABLE_MRS (
8235                         	CSI_ITEM_INSTANCE_ID,
8236                   	        MR_HEADER_ID,
8237                         	MR_EFFECTIVITY_ID,
8238                     	        REPETITIVE_FLAG   ,
8239                           	SHOW_REPETITIVE_CODE,
8240                       	        IMPLEMENT_STATUS_CODE,
8241                                 WHICHEVER_FIRST_CODE,
8242                                 SERVICE_LINE_ID,
8243                                 PROGRAM_MR_HEADER_ID,
8244                                 CONTRACT_START_DATE,
8245                                 CONTRACT_END_DATE,
8246                                 COVERAGE_IMP_LEVEL,
8247                                 PM_SCHEDULE_EXISTS)
8248                     VALUES (    l_appl_activities_tbl(j).ITEM_INSTANCE_ID,
8249                                 l_appl_activities_tbl(j).MR_HEADER_ID,
8250                                 l_appl_activities_tbl(j).MR_EFFECTIVITY_ID,
8251                                 l_appl_activities_tbl(j).REPETITIVE_FLAG,
8252                                 l_appl_activities_tbl(j).SHOW_REPETITIVE_CODE,
8253                                 l_appl_activities_tbl(j).IMPLEMENT_STATUS_CODE,
8254                                 l_appl_activities_tbl(j).WHICHEVER_FIRST_CODE,
8255                                 l_appl_activities_tbl(j).SERVICE_LINE_ID,
8256                                 l_appl_activities_tbl(j).PROGRAM_MR_HEADER_ID,
8257                                 l_appl_programs_tbl(i).SERVICE_START_DATE,
8258                                 l_appl_programs_tbl(i).SERVICE_END_DATE,
8259                                 l_appl_programs_tbl(i).COVERAGE_TYPE_IMP_LEVEL,
8260                                 nvl(l_appl_activities_tbl(j).ACT_SCHEDULE_EXISTS,'N')
8261                            );
8262                     -- Set activity_sch_exists_flag if any of the activities does
8263                     -- not have a schedule.
8264                     IF (nvl(l_appl_activities_tbl(j).act_schedule_exists,'N') = 'N') THEN
8265                       l_activity_sch_exists_flag := FALSE;
8266                     END IF;
8267                END IF;
8268 
8269                IF G_DEBUG = 'Y' THEN
8270                  AHL_DEBUG_PUB.debug('Successfully inserted for Act ID:' || l_appl_activities_tbl(j).MR_HEADER_ID);
8271                END IF;
8272 
8273             END LOOP; -- next activities record.
8274          END IF; -- activity COUNT.
8275 
8276          -- If this program does not have a schedule, add this program to table l_UnSch_programs_tbl
8277          -- if it is unique.
8278          IF (NOT(l_activity_sch_exists_flag)  AND
8279              l_appl_programs_tbl(i).mr_effectivity_id IS NOT NULL) THEN
8280 
8281             l_duplicate_pgm_flag := FALSE;
8282             -- Check if this program already exists in the table.
8283             IF (l_UnSch_programs_tbl.COUNT > 0) THEN
8284                FOR j IN l_UnSch_programs_tbl.FIRST..l_UnSch_programs_tbl.LAST LOOP
8285                   IF (l_UnSch_programs_tbl(j).program_mr_header_id = l_appl_programs_tbl(i).PM_program_id) THEN
8286                       l_duplicate_pgm_flag := TRUE;
8287                       EXIT;
8288                   END IF;
8289                END LOOP; -- chk next program.
8290             END IF; -- count > 0.
8291 
8292             -- if not duplicate add to program table.
8293             IF NOT(l_duplicate_pgm_flag) THEN
8294                 l_pgm_index := l_pgm_index + 1;
8295                 l_UnSch_programs_tbl(l_pgm_index).program_mr_header_id := l_appl_programs_tbl(i).PM_program_id;
8296                 l_UnSch_programs_tbl(l_pgm_index).mr_effectivity_id := l_appl_programs_tbl(i).mr_effectivity_id;
8297                 IF G_DEBUG = 'Y' THEN
8298                    AHL_DEBUG_PUB.debug('Successfully added Program to l_UnSch_programs_tbl:index:value:' || i || ':' ||
8299                                        l_UnSch_programs_tbl(l_pgm_index).program_mr_header_id);
8300                 END IF;
8301 
8302             END IF;
8303 
8304          END IF;
8305       END LOOP; -- next program record.
8306     END IF; -- count > 0.
8307 
8308   -- set output parameter.
8309   x_unsch_programs_tbl := l_UnSch_programs_tbl;
8310 
8311   IF G_DEBUG = 'Y' THEN
8312     AHL_DEBUG_PUB.debug('End of PopulatePM_Appl_MRs');
8313   END IF;
8314 
8315 END PopulatePM_Appl_MRs;
8316 
8317 ----------------------------------------------------------------------------------
8318 -- Process Unit for PM(preventive maintenance) installation.
8319 PROCEDURE Process_PM_Unit(p_csi_item_instance_id IN NUMBER,
8320                           p_UnSch_programs_tbl   IN PMprogram_tbl_type) IS
8321 
8322   l_current_usage_tbl    counter_values_tbl_type;
8323   /* contains current counter usage */
8324 
8325 BEGIN
8326 
8327   IF G_DEBUG = 'Y' THEN
8328      AHL_DEBUG_PUB.Debug('Start of Process_PM_Unit procedure');
8329   END IF;
8330 
8331   -- Get current usage of all the counters defined for the item instance.
8332   get_Current_Usage (p_csi_item_instance_id,
8333                      l_current_usage_tbl);
8334 
8335   -- Calculate program end date for all MR's where program is not scheduled.
8336   Calc_program_end_dates (p_UnSch_programs_tbl,
8337                           l_current_usage_tbl);
8338 
8339   -- Process records with program dates scheduled.
8340   Process_PMSch_Activities;
8341 
8342   -- Process records with no program dates.
8343   Process_PMUnSch_Activities(l_current_usage_tbl);
8344 
8345   -- Assign existing unit_effectivity ID's that have not been accomplished
8346   -- to the newly created ones in the temporary table.
8347   Assign_Unit_effectivity_IDs;
8348 
8349   IF G_DEBUG = 'Y' THEN
8350      AHL_DEBUG_PUB.Debug('End of Process_PM_Unit procedure');
8351   END IF;
8352 
8353 END Process_PM_Unit;
8354 
8355 
8356 --------------------------------------------------------------------------------
8357 
8358 -- To calculate the program end dates for all contracts with no due date schedule.
8359 PROCEDURE Calc_Program_End_Dates(p_UnSch_programs_tbl   IN PMprogram_tbl_type,
8360                                  p_current_usage_tbl    IN counter_values_tbl_type) IS
8361 
8362   -- get all programs which have no schedules.
8363   CURSOR ahl_cont_not_scheduled_csr IS
8364     SELECT DISTINCT appl.program_mr_header_id, mr.whichever_first_code
8365     FROM ahl_applicable_mrs appl, ahl_mr_headers_b mr
8366     -- replaced ahl_mr_headers_app_v with ahl_mr_headers_b as ahl_applicable_mrs has
8367     -- the filter of application_usg_code.
8368     WHERE appl.program_mr_header_id = mr.mr_header_id
8369        AND pm_schedule_exists = 'N';
8370 
8371   -- get details of program effectivity.
8372   CURSOR ahl_program_eff_csr (p_mr_effectivity_id IN NUMBER) IS
8373     SELECT mr_effectivity_id, program_duration, program_duration_uom_code,
8374            threshold_date
8375     FROM ahl_mr_effectivities
8376     where mr_effectivity_id = p_mr_effectivity_id;
8377 
8378   -- get all intervals for an effectivity.
8379   CURSOR ahl_mr_interval_csr (p_mr_effectivity_id IN NUMBER) IS
8380     SELECT start_value, stop_value, counter_id, counter_name, mr_interval_id
8381     FROM ahl_mr_intervals_v
8382     WHERE mr_effectivity_id = p_mr_effectivity_id;
8383 
8384   l_effectivity_rec   ahl_program_eff_csr%ROWTYPE;
8385 
8386   l_counter_rules_tbl counter_rules_tbl_type;
8387 
8388   l_program_due_date      DATE;
8389   l_program_calender_days NUMBER;
8390   l_UnSch_program_tbl     PMprogram_tbl_type;
8391   l_upd_SQLstmt_str       VARCHAR2(2000);
8392 
8393   l_program_expire_flag   BOOLEAN;
8394   /* indicates if a program has expired. */
8395 
8396   l_current_ctr_value NUMBER;
8397   l_counter_remain    NUMBER;
8398   l_ctr_found         BOOLEAN;
8399   l_current_ctr_uom   VARCHAR2(3);
8400   l_due_days          NUMBER;
8401   l_due_date          DATE;
8402   l_tbl_index         NUMBER;
8403   l_program_expired_flag  BOOLEAN;
8404 
8405 BEGIN
8406 
8407   IF G_DEBUG = 'Y' THEN
8408       AHL_DEBUG_PUB.Debug('Start of CALC_PROGRAM_END_DATES procedure');
8409   END IF;
8410 
8411   FOR program_rec IN ahl_cont_not_scheduled_csr LOOP
8412     -- Initialize variables.
8413     l_program_due_date := NULL;
8414     l_counter_remain := 0;
8415     l_program_calender_days := 0;
8416     l_UnSch_program_tbl.DELETE;
8417     l_tbl_index := 0;
8418 
8419     IF G_DEBUG = 'Y' THEN
8420       AHL_DEBUG_PUB.Debug('Calculating program end date for:' || program_rec.program_mr_header_id);
8421     END IF;
8422 
8423     -- build temporary table containing the effectivities associated to the program.
8424     IF (p_UnSch_programs_tbl.COUNT > 0) THEN
8425        FOR i IN p_UnSch_programs_tbl.FIRST..p_UnSch_programs_tbl.LAST LOOP
8426           IF (p_UnSch_programs_tbl(i).program_mr_header_id = program_rec.program_mr_header_id) THEN
8427              l_tbl_index := l_tbl_index + 1;
8428              l_UnSch_program_tbl(l_tbl_index) := p_UnSch_programs_tbl(i);
8429              --dbms_output.put_line('program id:' || l_UnSch_program_tbl(l_tbl_index).program_mr_header_id);
8430           END IF;
8431        END LOOP;
8432     END IF;
8433 
8434     -- read effectivity attributes for the program.
8435     IF (l_UnSch_program_tbl.COUNT > 0) THEN
8436        FOR i IN l_UnSch_program_tbl.FIRST..l_UnSch_program_tbl.LAST LOOP
8437 
8438          IF G_DEBUG = 'Y' THEN
8439             AHL_DEBUG_PUB.Debug('Processing for program effectivity-id:' || l_UnSch_program_tbl(l_tbl_index).mr_effectivity_id);
8440          END IF;
8441 
8442          OPEN ahl_program_eff_csr (l_UnSch_program_tbl(i).mr_effectivity_id);
8443          FETCH ahl_program_eff_csr INTO l_effectivity_rec;
8444          IF (ahl_program_eff_csr%FOUND) THEN
8445             -- read intervals for the effectivity.
8446             FOR interval_rec IN ahl_mr_interval_csr(l_effectivity_rec.mr_effectivity_id) LOOP
8447 
8448               IF G_DEBUG = 'Y' THEN
8449                  AHL_DEBUG_PUB.Debug('Processing for interval:' || interval_rec.mr_interval_id);
8450               END IF;
8451 
8452               -- Set current usage counter value.
8453               l_current_ctr_value := 0;
8454               l_ctr_found := FALSE;
8455               l_current_ctr_uom := NULL;
8456               -- Get the interval counter's  value from l_current_usage_tbl.
8457               FOR i IN p_current_usage_tbl.FIRST..p_current_usage_tbl.LAST LOOP
8458                 IF (p_current_usage_tbl(i).counter_name = interval_rec.counter_name) THEN
8459                    l_current_ctr_value := p_current_usage_tbl(i).counter_value;
8460                    l_current_ctr_uom := p_current_usage_tbl(i).uom_code;
8461                    l_ctr_found := TRUE;
8462                    EXIT;
8463                 END IF;
8464               END LOOP;
8465 
8466               IF (l_ctr_found) THEN
8467 
8468                  -- Check that the current counter value less than the program stop value.
8469                  l_counter_remain := interval_rec.stop_value - l_current_ctr_value;
8470 
8471                  /* indicates if a program has expired. */
8472                  l_program_expire_flag := FALSE;
8473 
8474                  -- Using forecast find the number of days to reach stop_value.
8475                  IF (l_counter_remain > 0) THEN
8476                      -- get date from forecast.
8477                      get_date_from_uf(l_counter_remain,
8478                                       l_current_ctr_uom,
8479                                       l_counter_rules_tbl, -- empty table.
8480                                       sysdate,
8481                                       l_due_date);
8482 
8483                      -- Compare dates.
8484                      IF (l_program_due_date IS NULL) THEN
8485                        l_program_due_date := l_due_date;
8486                      ELSE
8487                        IF (l_due_date IS NOT NULL) THEN
8488                           IF (program_rec.whichever_first_code = 'FIRST') THEN
8489                              IF (trunc(l_program_due_date) > trunc(l_due_date)) THEN
8490                                  l_program_due_date := l_due_date;
8491                              END IF;
8492                           ELSE /* whichever_first_code = 'LAST' */
8493                              IF (trunc(l_program_due_date) < trunc(l_due_date)) THEN
8494                                  l_program_due_date := l_due_date;
8495                              END IF;
8496                           END IF;
8497                        END IF; -- due date null.
8498                      END IF;
8499 
8500                  ELSE
8501                        l_program_expire_flag := TRUE;
8502                        -- if program expired for mr with whichever_code = FIRST, stop calculation.
8503                        IF (program_rec.whichever_first_code = 'FIRST') THEN
8504                           -- program expired for this instance.
8505                           l_due_date := NULL;
8506                           l_program_due_date := NULL;
8507                           EXIT; -- exit intervals loop.
8508                        END IF;
8509                  END IF;
8510 
8511               END IF; /* end l_ctr_found */
8512 
8513             END LOOP; /* next interval_rec */
8514 
8515             -- calculate due date using effectivity attributes.
8516             IF (program_rec.whichever_first_code = 'FIRST') AND (l_program_expired_flag) THEN
8517                 -- program expired for this instance.
8518                 null; -- do nothing.
8519             ELSIF (nvl(l_effectivity_rec.program_duration,0)) <> 0 AND
8520                l_effectivity_rec.program_duration_uom_code IS NOT NULL
8521             THEN
8522 
8523               --dbms_output.put_line('effectivity duration:' ||l_effectivity_rec.program_duration );
8524               --dbms_output.put_line('effectivity duration:' ||l_effectivity_rec.program_duration_uom_code );
8525 
8526               IF (l_effectivity_rec.program_duration_uom_code = 'YR') THEN
8527                  l_due_days := trunc(ADD_MONTHS(trunc(SYSDATE), 12 * l_effectivity_rec.program_duration)) - trunc(SYSDATE);
8528               ELSIF (l_effectivity_rec.program_duration_uom_code = 'MTH') THEN
8529                  l_due_days := trunc(ADD_MONTHS(trunc(SYSDATE), l_effectivity_rec.program_duration)) - trunc(SYSDATE);
8530               ELSIF (l_effectivity_rec.program_duration_uom_code = 'WK') THEN
8531                  l_due_days := 7 * l_effectivity_rec.program_duration;
8532               ELSIF (l_effectivity_rec.program_duration_uom_code = 'DAY') THEN
8533                  l_due_days := l_effectivity_rec.program_duration;
8534               END IF;
8535 
8536               --dbms_output.put_line('due days are:' || l_due_days );
8537 
8538               -- Compare the due days.
8539               IF (l_program_calender_days = 0) THEN
8540                   l_program_calender_days := l_due_days;
8541               ELSIF (program_rec.whichever_first_code = 'FIRST') THEN
8542                 IF (l_program_calender_days > l_due_days) THEN
8543                   l_program_calender_days := l_due_days;
8544                 END IF;
8545               ELSE /* whichever_first_code = 'LAST' */
8546                 IF (l_program_calender_days < l_due_days) THEN
8547                   l_program_calender_days := l_due_days;
8548                 END IF;
8549               END IF;
8550 
8551             END IF; /* effectivity_rec.program_duration */
8552 
8553          END IF; /* effectivity_rec found */
8554          CLOSE ahl_program_eff_csr;
8555 
8556          -- chk for program expired.
8557          IF (program_rec.whichever_first_code = 'FIRST') AND (l_program_expired_flag) THEN
8558              -- program expired for this instance.
8559              l_program_due_date := NULL;
8560              EXIT; -- exit program table loop.
8561          END IF;
8562 
8563       END LOOP; /* program table */
8564     END IF; /* count */
8565 
8566     IF G_DEBUG = 'Y' THEN
8567        AHL_DEBUG_PUB.Debug('Program end date:' || l_program_due_date );
8568        AHL_DEBUG_PUB.Debug('Program calender days:' || l_program_calender_days );
8569     END IF;
8570 
8571     -- Update record in ahl_applicable_mrs with the calculated program end date.
8572     IF (l_program_expired_flag) THEN
8573        -- For this case, set program end date = sysdate -1.
8574        l_upd_SQLstmt_str := 'UPDATE ahl_applicable_mrs' ||
8575                             ' SET program_end_date = :1' ||
8576                             ' WHERE program_mr_header_id = :2'||
8577                             ' AND PM_schedule_exists = :3';
8578 
8579        IF G_DEBUG = 'Y' THEN
8580           AHL_DEBUG_PUB.Debug('Expire SQL string:' || l_upd_SQLstmt_str);
8581        END IF;
8582 
8583        EXECUTE IMMEDIATE l_upd_SQLstmt_str USING SYSDATE - 1,
8584                                                  program_rec.program_mr_header_id,
8585                                                  'N';
8586     ELSE
8587 
8588        -- dbms_output.put_line('Not expired');
8589        -- set program end date = least of (program_calculated_date, contract_start + calender_days, contract_end_date)
8590        --UPDATE ahl_applicable_mrs
8591        --SET program_end_date = LEAST (nvl(l_program_due_date,contract_end_date),
8592        --                              decode(l_program_calender_days,0, contract_end_date, contract_start_date + l_program_calender_days),
8593        --                              contract_end_date)
8594        --WHERE program_mr_header_id = program_rec.program_mr_header_id
8595        --   AND PM_schedule_exists = 'N';
8596 
8597        -- for whichever_last, pick greatest of l_program_calender_days+ contract start date
8598        -- and l_program_due_date.
8599 
8600        IF (program_rec.whichever_first_code = 'FIRST') THEN
8601 
8602           l_upd_SQLstmt_str := 'UPDATE ahl_applicable_mrs' ||
8603                                ' SET program_end_date = LEAST (nvl(:1,contract_end_date),' ||
8604                                                             ' decode(:2,0, contract_end_date, contract_start_date + :3),' ||
8605                                                           ' contract_end_date)' ||
8606                             ' WHERE program_mr_header_id = :4' ||
8607                             '     AND PM_schedule_exists = :5';
8608        ELSE
8609 
8610           l_upd_SQLstmt_str := 'UPDATE ahl_applicable_mrs' ||
8611                                ' SET program_end_date = LEAST ( GREATEST (nvl(:1,contract_end_date),' ||
8612                                                             ' decode(:2,0, contract_end_date, contract_start_date + :3)),' ||
8613                                                           ' contract_end_date)' ||
8614                             ' WHERE program_mr_header_id = :4' ||
8615                             '     AND PM_schedule_exists = :5';
8616        END IF;
8617 
8618 
8619        IF G_DEBUG = 'Y' THEN
8620           AHL_DEBUG_PUB.Debug('SQL string:' || l_upd_SQLstmt_str);
8621        END IF;
8622 
8623        EXECUTE IMMEDIATE l_upd_SQLstmt_str USING l_program_due_date,
8624                                                  l_program_calender_days,
8625                                                  l_program_calender_days,
8626                                                  program_rec.program_mr_header_id,
8627                                                  'N';
8628     END IF;
8629 
8630   END LOOP; /* next program rec */
8631 
8632   IF G_DEBUG = 'Y' THEN
8633      AHL_DEBUG_PUB.Debug('End of CALC_PROGRAM_END_DATES procedure');
8634   END IF;
8635 
8636 END Calc_Program_End_Dates;
8637 
8638 --------------------------------------------------
8639 -- Process records with contract dates scheduled.
8640 PROCEDURE Process_PMSch_Activities  IS
8641 
8642   -- get distinct activities for which due dates have been scheduled for the service.
8643   CURSOR ahl_sch_activity_csr IS
8644     SELECT DISTINCT mr_header_id, csi_item_instance_id, service_line_id,
8645                     program_mr_header_id, contract_end_date, program_end_date,
8646                     show_repetitive_code,
8647                     repetitive_flag
8648     FROM ahl_applicable_mrs
8649     WHERE pm_schedule_exists = 'Y';
8650 
8651   -- Fix for FP bug# 6327241. We should be able to process multiple contracts.
8652   /*
8653   -- get program which have service dates scheduled in the order of importance
8654   -- and contract_start_date. Process only the first one.
8655   CURSOR ahl_cont_scheduled_csr(p_mr_header_id IN NUMBER) IS
8656     SELECT mr_header_id, service_line_id, mr_effectivity_id,
8657            program_mr_header_id, contract_end_date, program_end_date
8658     FROM ahl_applicable_mrs
8659     WHERE mr_header_id = p_mr_header_id
8660          AND pm_schedule_exists = 'Y'
8661     ORDER BY coverage_imp_level , contract_start_date;
8662   */
8663 
8664   -- Temporary fix for bug# 3022915.
8665   -- Get due date associated to the accomplishment date.
8666   /*
8667   -- fix for FP bug# 5223862.
8668   CURSOR ahl_due_date_csr(p_accomplishment_date IN DATE,
8669                           p_mr_header_id         IN NUMBER,
8670                           p_csi_item_instance_id IN NUMBER) IS
8671     SELECT due_date
8672     FROM ahl_unit_effectivities_b
8673     WHERE mr_header_id = p_mr_header_id
8674       AND csi_item_instance_id = p_csi_item_instance_id
8675       AND trunc(accomplished_date) = trunc(p_accomplishment_date)
8676       AND status_code IN ('ACCOMPLISHED','INIT-ACCOMPLISHED','TERMINATED')
8677     ORDER BY due_date desc;
8678   */
8679 
8680   -- Added filter by service_line_id to avoid issues caused by oks bug - 4574548
8681   -- wherein SRs associated to higher due dates are accomplished before lesser
8682   -- due date and the contract may have expired/terminated.
8683   -- 08/01/2012 changed order by clause to fix bug# 14588580 (avoid data fixes)
8684   CURSOR ahl_due_date_csr(--p_accomplishment_date  IN DATE,
8685                           p_mr_header_id         IN NUMBER,
8686                           p_csi_item_instance_id IN NUMBER,
8687                           p_service_line_id      IN NUMBER) IS
8688     SELECT due_date, accomplished_date
8689     FROM ahl_unit_effectivities_b
8690     WHERE mr_header_id = p_mr_header_id
8691       AND csi_item_instance_id = p_csi_item_instance_id
8692       AND service_line_id = p_service_line_id
8693       --AND trunc(accomplished_date) = trunc(p_accomplishment_date)
8694       AND status_code IN ('ACCOMPLISHED','INIT-ACCOMPLISHED','TERMINATED')
8695     --ORDER BY accomplished_date desc, due_date desc;
8696     ORDER BY due_date desc;
8697 
8698   --l_cont_scheduled_rec ahl_cont_scheduled_csr%ROWTYPE;
8699   /* record structure holding the service line and program details. */
8700 
8701   l_due_date        DATE;
8702   l_first_array_index  NUMBER;
8703   l_forecast_sequence  NUMBER := 0;
8704 
8705   -- parameters needed to call OKS API.
8706   l_pm_schedule_tbl OKS_PM_ENTITLEMENTS_PUB.pm_sch_tbl_type;
8707   l_inp_sch_rec     OKS_PM_ENTITLEMENTS_PUB.inp_sch_rec;
8708   l_return_status   VARCHAR2(1);
8709   l_msg_count       NUMBER;
8710   l_msg_data        VARCHAR2(2000);
8711 
8712 
8713   l_del_SQLstmt_str VARCHAR2(2000);
8714 
8715   l_temp_unit_effectivity_rec  ahl_temp_unit_effectivities%ROWTYPE;
8716   /* record structure to hold the activity and due date details */
8717 
8718   -- Added to fix bug# 3546136.
8719   l_temp_ue_initrec           ahl_temp_unit_effectivities%ROWTYPE;
8720 
8721   -- parameters needed to call get_accomplishment_details.
8722   l_last_accomplishment_date  DATE;
8723   l_last_acc_counter_val_tbl  counter_values_tbl_type;
8724   l_current_usage_tbl         counter_values_tbl_type;
8725   l_counter_rules_tbl         counter_rules_tbl_type;
8726   l_dependent_mr_flag         BOOLEAN;
8727   l_get_preceding_next_due    BOOLEAN;
8728   l_applicable_mrs_rec        applicable_mrs_rec_type;
8729   l_one_time_mr_flag          BOOLEAN;
8730   l_last_due_date             DATE;
8731 
8732   -- Added for bug# 6711228
8733   l_no_forecast_flag          BOOLEAN;
8734   l_mr_accomplish_exists      BOOLEAN;
8735 
8736 BEGIN
8737 
8738   IF G_DEBUG = 'Y' THEN
8739      AHL_DEBUG_PUB.Debug('Start of PROCESS_PMSCH_ACTIVITIES procedure');
8740   END IF;
8741 
8742   FOR sch_activity_rec IN ahl_sch_activity_csr LOOP
8743 
8744     IF G_DEBUG = 'Y' THEN
8745         AHL_DEBUG_PUB.Debug('Processing for:' || sch_activity_rec.mr_header_id);
8746         AHL_DEBUG_PUB.Debug('Processing for Item Instance:' || sch_activity_rec.csi_item_instance_id);
8747         AHL_DEBUG_PUB.Debug('Processing for Repetitive flag:' || sch_activity_rec.repetitive_flag);
8748         AHL_DEBUG_PUB.Debug('Processing for SHow Repetitive code:' || sch_activity_rec.show_repetitive_code);
8749     END IF;
8750 
8751     -- initialize forecast sequence for the activity.
8752     l_forecast_sequence := 0;
8753 
8754     -- Fix for FP bug# 6327241. We should be able to process multiple contracts.
8755     /*
8756     OPEN ahl_cont_scheduled_csr(sch_activity_rec.mr_header_id);
8757     FETCH ahl_cont_scheduled_csr INTO l_cont_scheduled_rec;
8758     IF (ahl_cont_scheduled_csr%NOTFOUND) THEN
8759        FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_PMPROGRAM_NOTFOUND');
8760        FND_MESSAGE.Set_Token('PMPROGRAM',sch_activity_rec.mr_header_id);
8761        FND_MSG_PUB.ADD;
8762        CLOSE ahl_cont_scheduled_csr;
8763        RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
8764     END IF;
8765 
8766     -- check for existence of accomplishments.
8767 
8768     -- initialize.
8769     l_one_time_mr_flag := FALSE;
8770 
8771     -- build applicable_mrs_rec.
8772     l_applicable_mrs_rec.mr_header_id := sch_activity_rec.mr_header_id;
8773     l_applicable_mrs_rec.csi_item_instance_id := sch_activity_rec.csi_item_instance_id;
8774     l_applicable_mrs_rec.repetitive_flag := sch_activity_rec.repetitive_flag;
8775 
8776     -- Check if accomplishment details exist.
8777     Get_accomplishment_details(p_applicable_mrs_rec => l_applicable_mrs_rec,
8778                                p_current_usage_tbl  => l_current_usage_tbl,
8779                                p_counter_rules_tbl  => l_counter_rules_tbl,
8780                                x_accomplishment_date => l_last_accomplishment_date,
8781                                x_last_acc_counter_val_tbl => l_last_acc_counter_val_tbl,
8782                                x_one_time_mr_flag         => l_one_time_mr_flag,
8783                                x_dependent_mr_flag => l_dependent_mr_flag,
8784                                x_get_preceding_next_due => l_get_preceding_next_due,
8785                                x_mr_accomplish_exists  => l_mr_accomplish_exists,
8786                                x_no_forecast_flag => l_no_forecast_flag );
8787 
8788     -- No need to check l_no_forecast_flag as this does not apply to PM flow.
8789     -- call OKS API to get due dates and process them in case one_time_mr_flag = false.
8790     IF NOT(l_one_time_mr_flag) THEN
8791     */
8792     -- get due date associated to the accomplishment date.
8793     OPEN ahl_due_date_csr (--l_last_accomplishment_date,
8794                            sch_activity_rec.mr_header_id,
8795                            sch_activity_rec.csi_item_instance_id,
8796                            sch_activity_rec.service_line_id);
8797     FETCH ahl_due_date_csr INTO l_last_due_date, l_last_accomplishment_date;
8798     IF (ahl_due_date_csr%FOUND) THEN
8799         IF (l_last_accomplishment_date IS NOT NULL) THEN
8800           IF G_DEBUG = 'Y' THEN
8801              AHL_DEBUG_PUB.debug('l_last_accomplishment_date:' || l_last_accomplishment_date);
8802           END IF;
8803 
8804           /* Fix for FP bug# 6327241
8805           -- get due date associated to the accomplishment date.
8806           OPEN ahl_due_date_csr (l_last_accomplishment_date,
8807                                  sch_activity_rec.mr_header_id,
8808                                  sch_activity_rec.csi_item_instance_id,
8809                                  l_cont_scheduled_rec.service_line_id);
8810           FETCH ahl_due_date_csr INTO l_last_due_date;
8811           CLOSE ahl_due_date_csr;
8812           */
8813           IF (l_last_due_date IS NOT NULL) THEN
8814             IF G_DEBUG = 'Y' THEN
8815                AHL_DEBUG_PUB.Debug('l_last_due_date is not null:' || l_last_due_date);
8816             END IF;
8817 
8818             l_last_accomplishment_date := l_last_due_date + 1;
8819           END IF;
8820         ELSE
8821           l_last_accomplishment_date := NULL;
8822         END IF;
8823     ELSE
8824      l_last_accomplishment_date := NULL;
8825     END IF;
8826     CLOSE ahl_due_date_csr;
8827 
8828         l_inp_sch_rec.service_line_id     := sch_activity_rec.service_line_id;
8829         l_inp_sch_rec.program_id          := sch_activity_rec.program_mr_header_id;
8830         l_inp_sch_rec.activity_id         := sch_activity_rec.mr_header_id;
8831         l_inp_sch_rec.schedule_start_date := l_last_accomplishment_date;
8832         l_inp_sch_rec.schedule_end_date   := G_last_day_of_window; /* uptill rolling window */
8833 
8834         -- Call contracts API to get due dates.
8835          OKS_PM_ENTITLEMENTS_PUB.Get_PM_Schedule (
8836                                p_api_version   => 1.0,
8837                                p_init_msg_list => OKC_API.G_FALSE,
8838                                p_sch_rec       => l_inp_sch_rec,
8839                                x_return_status => l_return_status,
8840                                x_msg_count     => l_msg_count,
8841                                x_msg_data      => l_msg_data,
8842                                x_pm_schedule   => l_pm_schedule_tbl);
8843 
8844         IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
8845           RAISE FND_API.G_EXC_ERROR;
8846         ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
8847           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
8848         END IF;
8849 
8850         IF G_DEBUG = 'Y' THEN
8851            AHL_DEBUG_PUB.debug('Service Line ID: ' || l_inp_sch_rec.service_line_id);
8852            AHL_DEBUG_PUB.debug('Program ID: ' || l_inp_sch_rec.program_id);
8853            AHL_DEBUG_PUB.debug('Activity ID: ' || l_inp_sch_rec.activity_id);
8854            AHL_DEBUG_PUB.debug('Start Date: ' || to_char(l_inp_sch_rec.schedule_start_date, 'DD-MON-YYYY HH24:MI:SS'));
8855            AHL_DEBUG_PUB.debug('End Date: ' || to_char(l_inp_sch_rec.schedule_end_date, 'DD-MON-YYYY HH24:MI:SS'));
8856            AHL_DEBUG_PUB.debug('Count of l_pm_schedule_tbl is: ' || l_pm_schedule_tbl.count);
8857 
8858            IF (l_pm_schedule_tbl.count > 0 ) THEN
8859                  for i in l_pm_schedule_tbl.first..l_pm_schedule_tbl.last loop
8860                     AHL_DEBUG_PUB.debug('Serv Line for ' || i ||':' || l_pm_schedule_tbl(i).service_line_id);
8861                     AHL_DEBUG_PUB.debug('Sch ON for ' || i ||':' || l_pm_schedule_tbl(i).schedule_on);
8862                     AHL_DEBUG_PUB.debug('Sch Start for ' || i ||':' || l_pm_schedule_tbl(i).schedule_from);
8863                     AHL_DEBUG_PUB.debug('Sch End for ' || i ||':' || l_pm_schedule_tbl(i).schedule_to);
8864                  end loop;
8865            END IF;
8866         END IF;
8867 
8868         -- Write due dates into ahl temporary table.
8869         IF (l_pm_schedule_tbl.COUNT > 0) THEN
8870           l_first_array_index := l_pm_schedule_tbl.FIRST;
8871           /* date associated to this index will be set as 'next due' occurrence */
8872 
8873           FOR i IN l_pm_schedule_tbl.FIRST..l_pm_schedule_tbl.LAST LOOP
8874 
8875             -- initialize.
8876             l_due_date := NULL;
8877             l_temp_unit_effectivity_rec := l_temp_ue_initrec;
8878 
8879             IF (l_pm_schedule_tbl(i).schedule_on IS NOT NULL) AND
8880              (l_pm_schedule_tbl(i).schedule_on <> FND_API.G_MISS_DATE) THEN
8881                  l_due_date := l_pm_schedule_tbl(i).schedule_on;
8882             ELSIF (l_pm_schedule_tbl(i).schedule_to IS NOT NULL) AND
8883              (l_pm_schedule_tbl(i).schedule_to <> FND_API.G_MISS_DATE) THEN
8884                  l_due_date := l_pm_schedule_tbl(i).schedule_to;
8885             END IF;
8886 
8887             -- write into temporary table if due date is not null.
8888             IF (l_due_date IS NOT NULL) THEN
8889 
8890               -- Build temporary table record.
8891               l_temp_unit_effectivity_rec.due_date := l_due_date;
8892               l_temp_unit_effectivity_rec.csi_item_instance_id := sch_activity_rec.csi_item_instance_id;
8893               l_temp_unit_effectivity_rec.mr_header_id := sch_activity_rec.mr_header_id;
8894               l_temp_unit_effectivity_rec.program_mr_header_id := sch_activity_rec.program_mr_header_id;
8895               l_temp_unit_effectivity_rec.service_line_id := sch_activity_rec.service_line_id;
8896               -- Added for ER# 2636001.
8897               IF (l_pm_schedule_tbl(i).schedule_from IS NOT NULL AND
8898                   l_pm_schedule_tbl(i).schedule_from <> FND_API.G_MISS_DATE) THEN
8899                  l_temp_unit_effectivity_rec.earliest_due_date := l_pm_schedule_tbl(i).schedule_from;
8900               END IF;
8901               IF (l_pm_schedule_tbl(i).schedule_to IS NOT NULL AND
8902                   l_pm_schedule_tbl(i).schedule_to <> FND_API.G_MISS_DATE) THEN
8903                  l_temp_unit_effectivity_rec.latest_due_date := l_pm_schedule_tbl(i).schedule_to;
8904               END IF;
8905 
8906               -- increment forecast sequence.
8907               l_forecast_sequence := l_forecast_sequence + 1;
8908               l_temp_unit_effectivity_rec.forecast_sequence := l_forecast_sequence;
8909 
8910               -- set repetitive mr flag.
8911               IF (i = l_first_array_index) THEN
8912                  l_temp_unit_effectivity_rec.repetitive_mr_flag := 'N';
8913               ELSE
8914                  l_temp_unit_effectivity_rec.repetitive_mr_flag := 'Y';
8915               END IF;
8916 
8917               -- create record in temporary table.
8918               Create_Temp_Unit_Effectivity (l_temp_unit_effectivity_rec);
8919 
8920             END IF;
8921 
8922             -- Check show_repetitive_code value.
8923             -- If it is = 'NEXT' then exit loop as repetities need not be shown in UMP.
8924             IF (sch_activity_rec.show_repetitive_code = 'NEXT') THEN
8925                EXIT;
8926             END IF;
8927 
8928           END LOOP; /* next record from pm_schedule */
8929 
8930         END IF; /* count */
8931     --END IF; /* one time mr flag */
8932 
8933     -- Delete duplicate programs/contracts for this mr_header_id if they exist.
8934     l_del_SQLstmt_str := 'DELETE FROM ahl_applicable_mrs' ||
8935                          ' WHERE mr_header_id = :1 AND pm_schedule_exists = ''N'' '||
8936                          ' AND service_line_id <> :2';
8937 
8938     IF G_DEBUG = 'Y' THEN
8939        AHL_DEBUG_PUB.Debug('SQL string:' || l_del_SQLstmt_str);
8940     END IF;
8941 
8942     EXECUTE IMMEDIATE l_del_SQLstmt_str USING  sch_activity_rec.mr_header_id,
8943                                                sch_activity_rec.service_line_id;
8944 
8945     --CLOSE ahl_cont_scheduled_csr;
8946   END LOOP; /* for ahl_sch_program_csr */
8947 
8948   IF G_DEBUG = 'Y' THEN
8949      AHL_DEBUG_PUB.debug('End of PROCESS_PMSCH_ACTIVITIES procedure');
8950   END IF;
8951 
8952 END Process_PMSch_Activities;
8953 ----------------------------------------------------------
8954 
8955 PROCEDURE Process_PMUnSch_Activities(p_current_usage_tbl IN counter_values_tbl_type)
8956 IS
8957 
8958   -- get all programs which have no contract dates scheduled.
8959   CURSOR ahl_UnSch_activity_csr IS
8960     SELECT DISTINCT appl.mr_header_id,
8961                     appl.csi_item_instance_id,
8962                     appl.whichever_first_code,
8963                     appl.repetitive_flag,
8964                     appl.show_repetitive_code,
8965                       mr.effective_to,
8966                       mr.effective_from
8967     FROM ahl_applicable_mrs appl, ahl_mr_headers_b mr
8968     WHERE appl.mr_header_id = mr.mr_header_id AND
8969           appl.pm_schedule_exists = 'N';
8970 
8971   l_last_day_of_window   DATE;
8972   l_next_due_flag        BOOLEAN;
8973   l_last_due_date        DATE;
8974   l_due_date             DATE;
8975   l_forecast_sequence    NUMBER;
8976   l_return_value         BOOLEAN;
8977   l_contract_found_flag  BOOLEAN;
8978   l_contract_override_due_date DATE;
8979   l_cont_override_earliest_due DATE;
8980   l_cont_override_latest_due   DATE;
8981 
8982   -- parameter for calculate_due_date procedure.
8983   l_next_due_date_rec         next_due_date_rec_type;
8984 
8985   l_program_mr_header_id NUMBER;
8986   l_service_line_id      NUMBER;
8987   l_contract_start_date  DATE;
8988 
8989   -- parameters to call get_accomplishment_details procedure.
8990   l_counter_rules_tbl         counter_rules_tbl_type;
8991   l_last_accomplishment_date  DATE;
8992   l_last_acc_counter_val_tbl  counter_values_tbl_type;
8993   l_dependent_mr_flag         BOOLEAN;
8994   l_get_preceding_next_due    BOOLEAN;
8995   l_one_time_mr_flag          BOOLEAN;
8996   l_last_due_counter_val_tbl  counter_values_tbl_type;
8997   l_due_at_counter_val_tbl    counter_values_tbl_type;
8998 
8999   l_applicable_mrs_rec        applicable_mrs_rec_type;
9000 
9001   l_temp_unit_effectivity_rec ahl_temp_unit_effectivities%ROWTYPE;
9002   l_temp_ue_initrec           ahl_temp_unit_effectivities%ROWTYPE;
9003 
9004   -- Added for bug# 6711228
9005   l_no_forecast_flag          BOOLEAN;
9006   l_mr_accomplish_exists      BOOLEAN;
9007 
9008   -- Added to fix bug# 6858788.
9009   l_last_due_mr_interval_id   NUMBER;
9010 
9011   -- Added to fix bug# 8994566
9012   l_accomplished_ue_id        NUMBER;
9013 
9014 BEGIN
9015 
9016   IF G_DEBUG = 'Y' THEN
9017      AHL_DEBUG_PUB.Debug('Start of process_pmunsch_activities procedure');
9018   END IF;
9019 
9020   FOR appl_mrs_rec IN ahl_UnSch_activity_csr LOOP
9021 
9022     -- initialize.
9023     l_forecast_sequence := 0;
9024 
9025     -- build applicable_mrs_rec.
9026     l_applicable_mrs_rec.mr_header_id := appl_mrs_rec.mr_header_id;
9027     l_applicable_mrs_rec.csi_item_instance_id := appl_mrs_rec.csi_item_instance_id;
9028     l_applicable_mrs_rec.whichever_first_code := appl_mrs_rec.whichever_first_code;
9029     l_applicable_mrs_rec.repetitive_flag := appl_mrs_rec.repetitive_flag;
9030     l_applicable_mrs_rec.show_repetitive_code := appl_mrs_rec.show_repetitive_code;
9031     l_applicable_mrs_rec.effective_to := appl_mrs_rec.effective_to;
9032     l_applicable_mrs_rec.effective_from := appl_mrs_rec.effective_from;
9033 
9034     IF G_DEBUG = 'Y' THEN
9035         AHL_DEBUG_PUB.Debug('Processing for:' || appl_mrs_rec.mr_header_id);
9036     END IF;
9037 
9038     -- Set last accomplishment details.
9039     Get_accomplishment_details(p_applicable_mrs_rec => l_applicable_mrs_rec,
9040                                p_current_usage_tbl  => p_current_usage_tbl,
9041                                p_counter_rules_tbl  => l_counter_rules_tbl, -- empty table. n/a for PM installation.
9042                                x_accomplishment_date => l_last_accomplishment_date,
9043                                x_last_acc_counter_val_tbl => l_last_acc_counter_val_tbl,
9044                                x_one_time_mr_flag         => l_one_time_mr_flag,
9045                                x_dependent_mr_flag => l_dependent_mr_flag,
9046                                x_get_preceding_next_due => l_get_preceding_next_due,
9047                                x_mr_accomplish_exists  => l_mr_accomplish_exists,
9048                                x_no_forecast_flag => l_no_forecast_flag,
9049                                x_accomplished_ue_id => l_accomplished_ue_id);
9050 
9051     IF G_DEBUG = 'Y' THEN
9052        AHL_DEBUG_PUB.Debug('Start of process_pmunsch_activities procedure');
9053     END IF;
9054 
9055     -- No need to check l_no_forecast_flag as this does not apply to PM flow.
9056     -- Check for one time MR case and process otherwise only.
9057     IF NOT(l_one_time_mr_flag) THEN
9058        --dbms_output.put_line('Not one time MR');
9059 
9060        -- Calculate next due date.
9061        -- Added parameter p_dependent_mr_flag to fix bug# 6711228. Issue does
9062        -- not impact PM calculation.
9063        Calculate_Due_Date (p_repetivity_flag => 'N',
9064                            p_applicable_mrs_rec => l_applicable_mrs_rec,
9065                            p_current_usage_tbl => p_current_usage_tbl,
9066                            p_counter_rules_tbl => l_counter_rules_tbl,   -- empty table. n/a for PM installation.
9067                            p_last_due_date => l_last_accomplishment_date,
9068                            p_last_due_counter_val_tbl => l_last_acc_counter_val_tbl,
9069                            p_dependent_mr_flag => l_dependent_mr_flag,
9070                            p_mr_accomplish_exists  => l_mr_accomplish_exists,
9071                            x_next_due_date_rec => l_next_due_date_rec);
9072       IF G_DEBUG = 'Y' THEN
9073         AHL_DEBUG_PUB.Debug('Aft calculate_due_date nextdue');
9074         AHL_DEBUG_PUB.Debug('due date is ' || l_next_due_date_rec.DUE_DATE);
9075       END IF;
9076 
9077       l_next_due_flag := TRUE;
9078       /* next due mr calculation. */
9079 
9080       -- set last due_date values to current values.
9081       l_last_due_date := sysdate;
9082       l_last_due_counter_val_tbl := p_current_usage_tbl;
9083 
9084       -- process next due and repetivity.
9085       LOOP
9086 
9087         -- initialize program and service line for the calculated due date.
9088         l_program_mr_header_id := NULL;
9089         l_service_line_id      := NULL;
9090         l_contract_found_flag  := FALSE;
9091         l_contract_override_due_date := NULL;
9092 
9093         -- Set due_date from l_next_due_date_rec.
9094         l_due_date := l_next_due_date_rec.DUE_DATE;
9095 
9096         IF (l_next_due_flag = TRUE) OR
9097               -- In the case of next-due, if l_due_date is null, get the earliest
9098               -- contract date and program available for the activity; else if
9099               -- l_due_date is not null, get the appropriate contract.
9100            (l_next_due_flag = FALSE AND l_due_date IS NOT NULL AND
9101             trunc(l_due_date) <= trunc(g_last_day_of_window))
9102               -- In the case of repetity and l_due_date is not null.
9103         THEN
9104 
9105            -- get program and service_line_id for the due date calculated.
9106            get_PMprogram(p_csi_item_instance_id   => appl_mrs_rec.csi_item_instance_id,
9107                          p_mr_header_id           => appl_mrs_rec.mr_header_id,
9108                          p_last_due_date          => l_last_due_date,
9109                          p_due_date               => l_due_date,
9110                          p_earliest_due           => l_next_due_date_rec.earliest_due_date,
9111                          p_latest_due             => l_next_due_date_rec.latest_due_date,
9112                          x_program_mr_header_id   => l_program_mr_header_id,
9113                          x_service_line_id        => l_service_line_id,
9114                          x_contract_override_due_date  => l_contract_override_due_date,
9115                          x_cont_override_earliest_due  => l_cont_override_earliest_due,
9116                          x_cont_override_latest_due    => l_cont_override_latest_due,
9117                          x_contract_found_flag         => l_contract_found_flag);
9118 
9119            -- write into temporary table if contract found.
9120            IF (l_contract_found_flag) THEN
9121 
9122                  IF G_DEBUG = 'Y' THEN
9123                     AHL_DEBUG_PUB.debug('contract found for due date:' ||l_due_date);
9124                     AHL_DEBUG_PUB.debug('contract found with override date:' || l_contract_override_due_date);
9125                     AHL_DEBUG_PUB.debug('contract found with override earliest:' || l_cont_override_earliest_due);
9126                     AHL_DEBUG_PUB.debug('contract found with override latest:' || l_cont_override_latest_due);
9127                  END IF;
9128 
9129                  IF (l_contract_override_due_date IS NOT NULL) THEN
9130 
9131                     l_next_due_date_rec.due_date := l_contract_override_due_date;
9132                     l_due_date := l_contract_override_due_date;
9133 
9134                     -- set due counter value and related data to null; as we do not know
9135                     -- the triggered counter value as on l_contract_override_due_date.
9136                     l_next_due_date_rec.due_at_counter_value := null;
9137                     l_next_due_date_rec.mr_effectivity_id    := null;
9138                     l_next_due_date_rec.mr_interval_id       := null;
9139                     l_next_due_date_rec.tolerance_flag       := null;
9140                     l_next_due_date_rec.tolerance_before      := null;
9141                     l_next_due_date_rec.tolerance_after      := null;
9142                     l_next_due_date_rec.message_code         := null;
9143                     l_next_due_date_rec.counter_id         := null;
9144 
9145                  END IF;
9146 
9147                  -- Added for ER# 2636001.
9148                  IF (l_cont_override_earliest_due IS NOT NULL) THEN
9149                     l_next_due_date_rec.earliest_due_date := l_cont_override_earliest_due;
9150                  END IF;
9151                  IF (l_cont_override_latest_due IS NOT NULL) THEN
9152                     l_next_due_date_rec.latest_due_date := l_cont_override_latest_due;
9153                  END IF;
9154 
9155                  -- Build temporary table record.
9156                  l_temp_unit_effectivity_rec := l_temp_ue_initrec; -- initialize.
9157 
9158                  l_temp_unit_effectivity_rec.due_date := l_due_date;
9159                  l_temp_unit_effectivity_rec.csi_item_instance_id := appl_mrs_rec.csi_item_instance_id;
9160                  l_temp_unit_effectivity_rec.mr_header_id := appl_mrs_rec.mr_header_id;
9161                  l_temp_unit_effectivity_rec.program_mr_header_id := l_program_mr_header_id;
9162                  l_temp_unit_effectivity_rec.service_line_id := l_service_line_id;
9163                  l_temp_unit_effectivity_rec.mr_effectivity_id := l_next_due_date_rec.mr_effectivity_id;
9164                  l_temp_unit_effectivity_rec.mr_interval_id := l_next_due_date_rec.mr_interval_id;
9165                  l_temp_unit_effectivity_rec.due_counter_value := l_next_due_date_rec.due_at_counter_value;
9166                  l_temp_unit_effectivity_rec.tolerance_flag := l_next_due_date_rec.tolerance_flag;
9167                  l_temp_unit_effectivity_rec.tolerance_before := l_next_due_date_rec.tolerance_before;
9168                  l_temp_unit_effectivity_rec.tolerance_after := l_next_due_date_rec.tolerance_after;
9169                  l_temp_unit_effectivity_rec.message_code := l_next_due_date_rec.message_code;
9170                  l_temp_unit_effectivity_rec.preceding_check_flag:= 'N';
9171                  --Added for ER# 2636001.
9172                  l_temp_unit_effectivity_rec.earliest_due_date := l_next_due_date_rec.earliest_due_date;
9173                  l_temp_unit_effectivity_rec.latest_due_date := l_next_due_date_rec.latest_due_date;
9174                  -- Added to fix bug#
9175                  l_temp_unit_effectivity_rec.counter_id := l_next_due_date_rec.counter_id;
9176 
9177                  -- increment forecast sequence.
9178                  l_forecast_sequence := l_forecast_sequence + 1;
9179                  l_temp_unit_effectivity_rec.forecast_sequence := l_forecast_sequence;
9180 
9181                  -- set repetivity based on next_due_flag.
9182                  IF (l_next_due_flag) THEN
9183                     l_temp_unit_effectivity_rec.repetitive_mr_flag := 'N';
9184                  ELSE
9185                     l_temp_unit_effectivity_rec.repetitive_mr_flag := 'Y';
9186                  END IF;
9187 
9188                  -- create record in temporary table.
9189                  Create_Temp_Unit_Effectivity (l_temp_unit_effectivity_rec);
9190 
9191                  -- Set next due flag to FALSE after writing record into temporary unit_effectivity.
9192                  IF (l_next_due_flag) THEN
9193                      l_next_due_flag := FALSE;
9194                  END IF;
9195 
9196                  -- Added to fix bug# 6858788
9197                  l_last_due_mr_interval_id := l_next_due_date_rec.mr_interval_id;
9198 
9199            END IF; -- l_contract_found_flag.
9200 
9201         END IF; --l_next_due_flag
9202 
9203         -- exit to process next activity.
9204         EXIT WHEN (l_next_due_flag = FALSE AND l_next_due_date_rec.DUE_DATE IS NULL) OR  -- calculate_due_date returns null.
9205                   (l_next_due_flag = FALSE AND trunc(l_next_due_date_rec.DUE_DATE) > trunc(g_last_day_of_window)) OR
9206                   (l_next_due_date_rec.due_date IS NOT NULL AND appl_mrs_rec.effective_to IS NOT NULL AND trunc(l_next_due_date_rec.due_date) > trunc(appl_mrs_rec.effective_to)) OR
9207                   (l_next_due_flag = FALSE AND appl_mrs_rec.show_repetitive_code = 'NEXT') OR
9208                   (l_contract_found_flag = FALSE);  -- contract not available.
9209 
9210         -- If due date is a past date, then set it to sysdate.
9211         -- This will happen only when calculating next-due date.
9212         IF (trunc(l_due_date) < trunc(sysdate)) THEN
9213           l_due_date := sysdate;
9214         END IF;
9215 
9216         IF G_DEBUG = 'Y' THEN
9217            AHL_DEBUG_PUB.Debug('Processing for repetivity');
9218            AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
9219            AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
9220            IF (l_last_due_counter_val_tbl.COUNT > 0) THEN
9221               FOR i in l_last_due_counter_val_tbl.FIRST..l_last_due_counter_val_tbl.LAST LOOP
9222                 AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_last_due_counter_val_tbl(i).counter_value || 'ID: ' || l_last_due_counter_val_tbl(i).counter_id);
9223               END LOOP;
9224            END IF;
9225         END IF;
9226 
9227 
9228         -- get all counter values as on l_due_date.
9229         Get_Due_at_Counter_Values (p_last_due_date => l_last_due_date,
9230                                    p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
9231                                    p_due_date => l_due_date,
9232                                    p_counter_rules_tbl => l_counter_rules_tbl,
9233                                    x_due_at_counter_val_tbl => l_due_at_counter_val_tbl,
9234                                    x_return_value => l_return_value);
9235 
9236         IF NOT(l_return_value) THEN  -- no forecast case.
9237            --dbms_output.put_line('l_return_value is false');
9238            EXIT;
9239         END IF;
9240 
9241         -- set current values to previous values.
9242         l_last_due_date := l_due_date;
9243         l_last_due_counter_val_tbl := l_due_at_counter_val_tbl;
9244 
9245         IF G_DEBUG = 'Y' THEN
9246            AHL_DEBUG_PUB.Debug('AFter get_due_at_counter_values');
9247            AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
9248            AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
9249            IF (l_due_at_counter_val_tbl.COUNT) > 0 THEN
9250                FOR i in l_due_at_counter_val_tbl.FIRST..l_due_at_counter_val_tbl.LAST LOOP
9251                    AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_due_at_counter_val_tbl(i).counter_value || 'ID: ' || l_due_at_counter_val_tbl(i).counter_id);
9252                end loop;
9253            END IF;
9254        END IF;
9255 
9256         -- Calculate next due date.
9257         Calculate_Due_Date (p_repetivity_flag => 'Y',
9258                             p_applicable_mrs_rec => l_applicable_mrs_rec,
9259                             p_current_usage_tbl => p_current_usage_tbl,
9260                             p_counter_rules_tbl => l_counter_rules_tbl,
9261                             p_last_due_date => l_last_due_date,
9262                             p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
9263                             p_mr_accomplish_exists  => l_mr_accomplish_exists,
9264                             p_last_due_mr_interval_id => l_last_due_mr_interval_id,
9265                             x_next_due_date_rec => l_next_due_date_rec);
9266 
9267         IF G_DEBUG = 'Y' THEN
9268            AHL_DEBUG_PUB.Debug('aft calculate_due_date - repetivity');
9269            AHL_DEBUG_PUB.Debug('due date is ' || l_next_due_date_rec.DUE_DATE);
9270         END IF;
9271 
9272         -- Check if calculated date is same as last due date. If they are the same then, add one day.
9273         IF (l_next_due_date_rec.due_date IS NOT NULL) THEN
9274            IF (trunc(l_last_due_date) = trunc(l_next_due_date_rec.due_date)) THEN
9275                l_next_due_date_rec.due_date := l_next_due_date_rec.due_date + 1;
9276                l_next_due_date_rec.EARLIEST_DUE_DATE := NULL;
9277                l_next_due_date_rec.latest_due_date := NULL;
9278 
9279                IF G_DEBUG = 'Y' THEN
9280                  AHL_DEBUG_PUB.Debug('Adding one day to l_next_due_date_rec.due_date:' || l_next_due_date_rec.due_date);
9281                END IF;
9282 
9283                --IF G_DEBUG = 'Y' THEN
9284                --   AHL_DEBUG_PUB.Debug('Exiting build effectivity as last due = due date');
9285                --END IF;
9286                --EXIT;
9287            END IF;
9288         END IF;
9289 
9290       END LOOP; /* process repetivity. */
9291 
9292     END IF; /* one time mr */
9293 
9294   END LOOP; /* ahl_UnSch_contracts_csr */
9295 
9296   IF G_DEBUG = 'Y' THEN
9297      AHL_DEBUG_PUB.debug('End of process_pmunsch_activities procedure');
9298   END IF;
9299 
9300 END Process_PMUnSch_Activities;
9301 
9302 ---------------------------------------------
9303 -- Procedure to find the service_line_id and program for a calculated due_date.
9304 -- The calculated due_date may be overridden by the contract/program dates.
9305 -- Also the earliest due and latest due date will get adjusted if they are not
9306 -- within the contract and program start/end dates.
9307 
9308 PROCEDURE Get_PMprogram(p_csi_item_instance_id       IN  NUMBER,
9309                         p_mr_header_id               IN  NUMBER,
9310                         p_last_due_date              IN  DATE,
9311                         p_due_date                   IN  DATE,
9312                         p_earliest_due               IN  DATE,
9313                         p_latest_due                 IN  DATE,
9314                         x_program_mr_header_id       OUT NOCOPY NUMBER,
9315                         x_service_line_id            OUT NOCOPY NUMBER,
9316                         x_contract_override_due_date OUT NOCOPY DATE,
9317                         x_cont_override_earliest_due OUT NOCOPY DATE,
9318                         x_cont_override_latest_due   OUT NOCOPY DATE,
9319                         x_contract_found_flag        OUT NOCOPY BOOLEAN)
9320 IS
9321 
9322   -- get contract/program for a given due date.
9323   CURSOR ahl_contract_exists_csr(p_mr_header_id  IN NUMBER,
9324                                  p_due_date      IN DATE) IS
9325     SELECT program_mr_header_id,
9326            service_line_id, contract_start_date, contract_end_date, program_end_date
9327     FROM ahl_applicable_mrs
9328     WHERE mr_header_id = p_mr_header_id
9329       AND pm_schedule_exists = 'N'
9330       AND trunc(program_end_date) >= trunc(p_due_date) -- eliminate expired programs.
9331       AND trunc(p_due_date) >= trunc(contract_start_date)
9332       AND trunc(p_due_date) <= LEAST(trunc(contract_end_date), nvl(trunc(program_end_date),trunc(contract_end_date)))
9333     ORDER BY contract_start_date;
9334 
9335   -- get the next contract (if available).
9336   CURSOR ahl_next_contract_csr (p_mr_header_id IN NUMBER,
9337                                 p_due_date     IN DATE) IS
9338     SELECT program_mr_header_id,
9339            service_line_id,
9340            contract_start_date, contract_end_date, program_end_date
9341     FROM ahl_applicable_mrs
9342     WHERE pm_schedule_exists = 'N'
9343       AND trunc(program_end_date) >= trunc(p_due_date) -- eliminate expired programs.
9344       AND mr_header_id = p_mr_header_id
9345       AND trunc(p_due_date) <= trunc(contract_start_date)
9346     ORDER BY contract_start_date;
9347 
9348 
9349   l_program_mr_header_id  NUMBER;
9350   /* program header id for the due date. */
9351 
9352   l_service_line_id    NUMBER;
9353   /* service line id for the due date. */
9354 
9355   l_due_date           DATE := p_due_date;
9356 
9357   l_contract_start_date DATE;
9358   l_program_end_date    DATE;
9359   l_contract_end_date   DATE;
9360 
9361   l_contract_override_due_date  DATE := NULL;
9362   -- this is set only if there exists no contract for the
9363   -- input due date but there is a contract that starts at
9364   -- a later date.
9365 
9366 
9367 BEGIN
9368 
9369   IF G_DEBUG = 'Y' THEN
9370      AHL_DEBUG_PUB.debug('Start of Get_PMprogram procedure for MR:Due Date is: ' ||
9371             p_mr_header_id || ':' || p_due_date);
9372   END IF;
9373 
9374   -- Initialize.
9375   x_program_mr_header_id := NULL;
9376   x_service_line_id := NULL;
9377   x_contract_override_due_date := NULL;
9378   x_contract_found_flag := FALSE;
9379   x_cont_override_earliest_due := NULL;
9380   x_cont_override_latest_due := NULL;
9381 
9382   -- if p_due_date is null, set it = sysdate; so that it picks ups the earliest contract.
9383   IF (l_due_date IS NULL) THEN
9384       l_due_date := sysdate;
9385   END IF;
9386 
9387   -- Check if calculated due date belongs to any contracts.
9388   OPEN ahl_contract_exists_csr (p_mr_header_id,
9389                                 l_due_date);
9390   FETCH ahl_contract_exists_csr INTO l_program_mr_header_id,
9391                                      l_service_line_id,
9392                                      l_contract_start_date,
9393                                      l_contract_end_date,
9394                                      l_program_end_date;
9395   IF (ahl_contract_exists_csr%FOUND) THEN
9396      x_program_mr_header_id := l_program_mr_header_id;
9397      x_service_line_id := l_service_line_id;
9398      x_contract_override_due_date := NULL;
9399      x_contract_found_flag := TRUE;
9400 
9401      -- In the case due_date is null, return sysdate as due date.
9402      IF (p_due_date IS NULL) THEN
9403         x_contract_override_due_date := l_due_date;
9404      END IF;
9405      -- Added for ER# 2636001.
9406      IF (trunc(p_earliest_due) < trunc(l_contract_start_date)) THEN
9407        x_cont_override_earliest_due := l_contract_start_date;
9408      END IF;
9409      -- if program end date not available, then replace with contract end date.
9410      IF (trunc(p_latest_due) > LEAST(trunc(l_contract_end_date),
9411                                      trunc(nvl(l_program_end_date, l_contract_end_date))))
9412      THEN
9413          x_cont_override_latest_due  := LEAST(trunc(l_contract_end_date),
9414                                               trunc(nvl(l_program_end_date,l_contract_end_date)));
9415      END IF;
9416 
9417   ELSE
9418     -- Look for next contract if exists.
9419     OPEN ahl_next_contract_csr (p_mr_header_id, l_due_date);
9420     FETCH ahl_next_contract_csr INTO l_program_mr_header_id,
9421                                      l_service_line_id,
9422                                      l_contract_start_date,
9423                                      l_contract_end_date,
9424                                      l_program_end_date;
9425       IF (ahl_next_contract_csr%FOUND) THEN
9426          x_program_mr_header_id := l_program_mr_header_id;
9427          x_service_line_id := l_service_line_id;
9428          x_contract_override_due_date := l_contract_start_date;
9429          x_contract_found_flag := TRUE;
9430 
9431          -- Added for ER# 2636001.
9432          IF (trunc(p_earliest_due) < trunc(l_contract_start_date)) THEN
9433            x_cont_override_earliest_due := l_contract_start_date;
9434          END IF;
9435          -- if program end date not available, then replace with contract end date.
9436          IF (trunc(p_latest_due) > LEAST(trunc(l_contract_end_date),
9437                                          trunc(nvl(l_program_end_date, l_contract_end_date))))
9438          THEN
9439              x_cont_override_latest_due  := LEAST(trunc(l_contract_end_date),
9440                                                   trunc(nvl(l_program_end_date,l_contract_end_date)));
9441          END IF;
9442 
9443       END IF;
9444 
9445     CLOSE ahl_next_contract_csr;
9446   END IF;
9447   CLOSE ahl_contract_exists_csr;
9448 
9449   IF G_DEBUG = 'Y' THEN
9450     IF NOT(x_contract_found_flag) THEN
9451       AHL_DEBUG_PUB.debug('Contract Not Found');
9452     END IF;
9453     AHL_DEBUG_PUB.debug('End of Get_PMprogram procedure');
9454   END IF;
9455 
9456 END Get_PMprogram;
9457 
9458 -------------------------------------------------------------
9459 -- After creation of all maintenance requirements for the instance in the temporary table,
9460 -- assign unit effectivity IDs from existing un-accomplished maintenance requirements
9461 -- belonging to the same instance from ahl_unit_effectivities_b.
9462 PROCEDURE Assign_Unit_Effectivity_IDs IS
9463 
9464   -- Added service_line_id to fix FP bug# 5481605.
9465   -- read temporary table sequentially.
9466   CURSOR ahl_mr_header_csr IS
9467     SELECT DISTINCT mr_header_id, csi_item_instance_id, service_line_id
9468     FROM ahl_temp_unit_effectivities;
9469 
9470   -- retrieve current unit effectivity records.
9471   CURSOR ahl_unit_effectivity_csr (p_csi_item_instance_id IN NUMBER,
9472                                    p_mr_header_id IN NUMBER,
9473                                    p_service_line_id IN NUMBER,
9474                                    p_appl_usg_code   IN VARCHAR2) IS
9475     SELECT ue.unit_effectivity_id
9476     FROM   ahl_unit_effectivities_b UE
9477     WHERE  mr_header_id = p_mr_header_id
9478        AND csi_item_instance_id = p_csi_item_instance_id
9479        AND application_usg_code = p_appl_usg_code
9480        AND service_line_id = p_service_line_id
9481        AND (UE.Status_code IS NULL OR status_code IN ('INIT-DUE','DEFERRED'))
9482     --ORDER BY forecast_sequence ASC;
9483     ORDER BY unit_effectivity_id ASC;  -- fix FP bug# 5481605.
9484 
9485   CURSOR ahl_temp_effectivity_csr(p_csi_item_instance_id IN NUMBER,
9486                                   p_mr_header_id IN NUMBER,
9487                                   p_service_line_id IN NUMBER) IS
9488     SELECT unit_effectivity_id
9489     FROM ahl_temp_unit_effectivities
9490     WHERE mr_header_id = p_mr_header_id
9491        AND csi_item_instance_id = p_csi_item_instance_id
9492        AND service_line_id = p_service_line_id
9493     FOR UPDATE OF unit_effectivity_id
9494     ORDER BY forecast_sequence ASC;
9495 
9496   l_unit_effectivity_id  NUMBER;
9497 
9498   l_ue_id_tbl      nbr_tbl_type;
9499   l_appl_usg_code  ahl_unit_effectivities_b.application_usg_code%TYPE;
9500 
9501 BEGIN
9502 
9503    IF G_DEBUG = 'Y' THEN
9504       AHL_DEBUG_PUB.debug('Start of assign_unit_effectivity_ids procedure');
9505    END IF;
9506 
9507    -- Application usage code.
9508    l_appl_usg_code := FND_PROFILE.VALUE('AHL_APPLN_USAGE');
9509 
9510    -- For each mr_header_id assign the unit effectivity IDs.
9511    -- note: All mr's are for one item instance only.
9512 
9513    FOR mr_header_rec IN ahl_mr_header_csr LOOP
9514      --dbms_output.put_line('Processing for:' ||  mr_header_rec.mr_header_id);
9515 
9516      -- Added service_line_id to fix FP bug# 5481605.
9517      -- open temporary table cursor.
9518      OPEN ahl_temp_effectivity_csr(mr_header_rec.csi_item_instance_id,
9519                                    mr_header_rec.mr_header_id,
9520                                    mr_header_rec.service_line_id);
9521 
9522      -- loop through all unit_effectivity records.
9523      /*FOR unit_effectivity_rec IN ahl_unit_effectivity_csr(mr_header_rec.csi_item_instance_id,
9524                                                           mr_header_rec.mr_header_id,
9525                                                           mr_header_rec.service_line_id)
9526      */
9527      OPEN ahl_unit_effectivity_csr(mr_header_rec.csi_item_instance_id,
9528                                    mr_header_rec.mr_header_id,
9529                                    mr_header_rec.service_line_id,
9530                                    l_appl_usg_code);
9531 
9532      LOOP
9533        FETCH ahl_unit_effectivity_csr BULK COLLECT INTO l_ue_id_tbl LIMIT 1000;
9534        EXIT WHEN (l_ue_id_tbl.count = 0);
9535 
9536        IF (l_ue_id_tbl.count > 0) THEN
9537          FOR i IN l_ue_id_tbl.FIRST..l_ue_id_tbl.LAST LOOP
9538 
9539            -- Fetch record from temporary table.
9540            FETCH  ahl_temp_effectivity_csr INTO l_unit_effectivity_id;
9541            IF (ahl_temp_effectivity_csr%NOTFOUND) THEN
9542               -- exit ahl_unit_effectivity_csr loop as no more records to assign.
9543               EXIT;
9544            ELSE
9545 
9546               --dbms_output.put_line('found ue.unit_effectivity_id:' || unit_effectivity_rec.unit_effectivity_id);
9547 
9548               --l_unit_effectivity_id := unit_effectivity_rec.unit_effectivity_id;
9549               l_unit_effectivity_id := l_ue_id_tbl(i);
9550 
9551               -- update record.
9552 
9553               UPDATE ahl_temp_unit_effectivities
9554               SET unit_effectivity_id = l_unit_effectivity_id
9555               WHERE CURRENT OF ahl_temp_effectivity_csr;
9556            END IF; -- ahl_temp_effectivity_csr%NOTFOUND
9557          END LOOP; -- l_ue_id_tbl.FIRST
9558        END IF; -- l_ue_id_tbl.count > 0
9559 
9560        IF (ahl_temp_effectivity_csr%NOTFOUND) THEN
9561          EXIT; -- exit ahl_unit_effectivity_csr LOOP
9562        END IF;
9563 
9564        l_ue_id_tbl.DELETE;
9565 
9566      END LOOP; -- ahl_unit_effectivity_csr
9567      CLOSE ahl_temp_effectivity_csr;
9568      CLOSE ahl_unit_effectivity_csr;
9569 
9570    END LOOP; -- ahl_mr_header_csr.
9571 
9572    IF G_DEBUG = 'Y' THEN
9573       AHL_DEBUG_PUB.debug('End of assign_unit_effectivity_ids procedure');
9574    END IF;
9575 
9576 END Assign_Unit_Effectivity_IDs;
9577 
9578 -------------------------------------------------------------
9579 -- Procedure to calculate due date based on deferral details.
9580 PROCEDURE Get_Deferred_Due_Date (p_unit_effectivity_id IN NUMBER,
9581                                  p_deferral_threshold_tbl IN  counter_values_tbl_type,
9582                                  x_due_date               OUT NOCOPY DATE,
9583                                  x_return_status          OUT NOCOPY VARCHAR2,
9584                                  x_msg_data               OUT NOCOPY VARCHAR2,
9585                                  x_msg_count              OUT NOCOPY NUMBER)
9586 IS
9587 
9588   -- Get Unit Effectivity details.
9589   -- added inventory_item_id, inv_master_organization_id to fix bug# 9284692
9590   CURSOR ahl_unit_effectivity_csr (p_unit_effectivity_id IN NUMBER) IS
9591     SELECT ue.csi_item_instance_id, ue.mr_header_id, cii.inventory_item_id,
9592            cii.inv_master_organization_id
9593     FROM ahl_unit_effectivities_app_v ue, csi_item_instances cii
9594     WHERE ue.unit_effectivity_id = p_unit_effectivity_id
9595           AND ue.csi_item_instance_id = cii.instance_id;
9596 
9597   -- Get MR details.
9598   CURSOR ahl_mr_headers_csr (p_mr_header_id IN NUMBER) IS
9599     SELECT whichever_first_code
9600     FROM ahl_mr_headers_app_v
9601     WHERE mr_header_id = p_mr_header_id;
9602 
9603   -- get the configuration structure.(G_config_node_tbl).
9604   CURSOR csi_reln_csr ( p_csi_item_instance_id IN NUMBER) IS
9605     SELECT position_reference
9606     FROM csi_ii_relationships
9607     WHERE subject_id = p_csi_item_instance_id
9608                AND relationship_type_code = 'COMPONENT-OF'
9609                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
9610                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1));
9611 
9612   -- get the counter usage
9613   CURSOR cs_ctr_counter_csr (--p_csi_item_instance_id  IN NUMBER,
9614                              p_counter_id            IN NUMBER) IS
9615   /*
9616   SELECT nvl(net_reading, 0)
9617   FROM csi_cp_counters_v
9618   WHERE customer_product_id = p_csi_item_instance_id
9619     AND counter_id = p_counter_id;
9620   */
9621 
9622   /*
9623   SELECT nvl(cv.net_reading,0) net_reading
9624      FROM csi_counter_values_v cv
9625      WHERE cv.counter_id = p_counter_id
9626        AND cv.counter_id IN (select counter_id
9627                              from   csi_counter_associations cca
9628                              where  source_object_code = 'CP'
9629                              AND    source_object_id = p_csi_item_instance_id
9630                              AND    cca.counter_id = cv.counter_id)
9631        AND rownum < 2;
9632   */
9633   select nvl(ccr.net_reading,0) net_reading
9634   FROM csi_counters_b cc, csi_counter_readings ccr
9635   WHERE cc.counter_id = p_counter_id
9636     and  ccr.counter_value_id = cc.CTR_VAL_MAX_SEQ_NO;
9637 
9638   i                       NUMBER;
9639   l_csi_item_instance_id  NUMBER;
9640   l_root_csi_instance_id  NUMBER;
9641   l_mr_header_id          NUMBER;
9642   l_uc_header_id          NUMBER;
9643   l_calc_due_date         DATE;
9644   l_due_date              DATE;
9645   l_whichever_first_code  ahl_mr_headers_app_v.whichever_first_code%TYPE;
9646   l_inv_master_organization_id number;
9647   l_inventory_item_id     number;
9648   l_position_reference    VARCHAR2(30);
9649   l_counter_rules_tbl     counter_rules_tbl_type;
9650   l_current_usage_tbl     counter_values_tbl_type;
9651   l_counter_value         number;
9652   l_counter_remain        number;
9653 
9654 BEGIN
9655 
9656   -- Set return status.
9657   x_return_status := FND_API.G_RET_STS_SUCCESS;
9658 
9659   -- Enable Debug.
9660   IF G_DEBUG = 'Y' THEN
9661     AHL_DEBUG_PUB.enable_debug;
9662   END IF;
9663 
9664   -- Add debug mesg.
9665   IF G_DEBUG = 'Y' THEN
9666     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Get_Deferred_Due_Date');
9667     AHL_DEBUG_PUB.debug('Dump of input parameters:');
9668     AHL_DEBUG_PUB.debug('Unit Effectivity ID:' || p_unit_effectivity_id);
9669     AHL_DEBUG_PUB.debug('Count on p_deferral_threshold_tbl:' || p_deferral_threshold_tbl.COUNT);
9670   END IF;
9671 
9672   -- Validate input parameters.
9673   IF (p_unit_effectivity_id IS NULL OR p_unit_effectivity_id = FND_API.G_MISS_NUM) THEN
9674      FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_UE_NULL');
9675      FND_MSG_PUB.ADD;
9676      RAISE FND_API.G_EXC_ERROR;
9677   ELSE
9678      OPEN ahl_unit_effectivity_csr (p_unit_effectivity_id);
9679      FETCH ahl_unit_effectivity_csr INTO l_csi_item_instance_id, l_mr_header_id,
9680                                           l_inventory_item_id, l_inv_master_organization_id;
9681      IF (ahl_unit_effectivity_csr%NOTFOUND) THEN
9682         FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_UE_INVALID');
9683         FND_MESSAGE.Set_Token('UE_ID', p_unit_effectivity_id);
9684         FND_MSG_PUB.ADD;
9685         RAISE FND_API.G_EXC_ERROR;
9686      END IF;
9687   END IF;
9688 
9689   IF (l_mr_header_id IS NOT NULL) THEN
9690      -- get MR details from ahl_mr_headers.
9691      OPEN ahl_mr_headers_csr(l_mr_header_id);
9692      FETCH ahl_mr_headers_csr INTO l_whichever_first_code;
9693      IF (ahl_mr_headers_csr%NOTFOUND) THEN
9694        FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_MR_INVALID');
9695        FND_MESSAGE.Set_Token('UE_ID', p_unit_effectivity_id);
9696        FND_MSG_PUB.ADD;
9697        RAISE FND_API.G_EXC_ERROR;
9698      END IF;
9699      CLOSE ahl_mr_headers_csr;
9700   ELSE
9701      -- SR case.
9702      l_whichever_first_code := 'FIRST';
9703   END IF;
9704 
9705   IF G_DEBUG = 'Y' THEN
9706     AHL_DEBUG_PUB.debug('Step 1');
9707     AHL_DEBUG_PUB.debug('MR Header ID:' || l_mr_header_id);
9708     AHL_DEBUG_PUB.debug('CSI Item Instance ID:' || l_csi_item_instance_id);
9709     AHL_DEBUG_PUB.debug('Inventory Item  ID:' || l_inventory_item_id);
9710     AHL_DEBUG_PUB.debug('INV master Org ID:' || l_inv_master_organization_id);
9711   END IF;
9712 
9713   -- Get Unit and Master Config IDs if available.
9714   -- Find the root item instance.
9715   l_root_csi_instance_id := Get_RootInstanceID(l_csi_item_instance_id);
9716 
9717   -- Get master and unit configuration for the root item instance.
9718   Get_Unit_Master_ConfigIDs (l_root_csi_instance_id,
9719                              l_uc_header_id, G_master_config_id);
9720 
9721   IF G_DEBUG = 'Y' THEN
9722     AHL_DEBUG_PUB.debug('Step 2');
9723   END IF;
9724 
9725   -- Check for errors.
9726   IF FND_MSG_PUB.Count_msg > 0 THEN
9727      RAISE FND_API.G_EXC_ERROR;
9728   END IF;
9729 
9730   IF G_DEBUG = 'Y' THEN
9731     AHL_DEBUG_PUB.debug('Step 3');
9732   END IF;
9733 
9734   -- Get utilization forecast for the unit/part.
9735   Get_Utilization_Forecast (l_root_csi_instance_id,
9736                             l_uc_header_id,
9737                             l_inventory_item_id,
9738                             l_inv_master_organization_id,
9739                             G_forecast_details_tbl);
9740 
9741   IF G_DEBUG = 'Y' THEN
9742     AHL_DEBUG_PUB.debug('Step 4');
9743     AHL_DEBUG_PUB.debug('Count on util forecast tbl:' || G_forecast_details_tbl.count);
9744   END IF;
9745 
9746   -- Get the position installed in.
9747   OPEN csi_reln_csr(l_csi_item_instance_id);
9748   FETCH csi_reln_csr INTO l_position_reference;
9749   IF (csi_reln_csr%NOTFOUND) THEN
9750      l_position_reference := G_master_config_id;
9751   END IF;
9752   CLOSE csi_reln_csr;
9753 
9754   IF G_DEBUG = 'Y' THEN
9755     AHL_DEBUG_PUB.debug('Step 5');
9756   END IF;
9757 
9758   -- Build counter rules ratio if node is not root node.
9759   IF (G_master_config_id IS NOT NULL AND l_position_reference IS NOT NULL) THEN
9760       build_Counter_Ratio(l_position_reference,
9761                           l_csi_item_instance_id,
9762                           G_master_config_id,
9763                           l_counter_rules_tbl);
9764   END IF;
9765 
9766   IF G_DEBUG = 'Y' THEN
9767     AHL_DEBUG_PUB.debug('Step 6');
9768   END IF;
9769 
9770   -- Calculate counter_remain and call get_date_from_uf.
9771   IF (p_deferral_threshold_tbl.COUNT > 0) THEN
9772      FOR i IN p_deferral_threshold_tbl.FIRST..p_deferral_threshold_tbl.LAST LOOP
9773        -- get current usage
9774        --OPEN cs_ctr_counter_csr(l_csi_item_instance_id, p_deferral_threshold_tbl(i).counter_id);
9775        OPEN cs_ctr_counter_csr(p_deferral_threshold_tbl(i).counter_id);
9776        FETCH cs_ctr_counter_csr INTO l_counter_value;
9777        IF (cs_ctr_counter_csr%NOTFOUND) THEN
9778           IF G_DEBUG = 'Y' THEN
9779             AHL_DEBUG_PUB.debug('Step 7');
9780           END IF;
9781           l_counter_value := 0;
9782        END IF;
9783 
9784        CLOSE cs_ctr_counter_csr;
9785 
9786        IF G_DEBUG = 'Y' THEN
9787          AHL_DEBUG_PUB.debug('l_counter_value:' || l_counter_value);
9788        END IF;
9789 
9790        -- Get due date for counter remain.
9791        l_counter_remain := p_deferral_threshold_tbl(i).counter_value - l_counter_value;
9792 
9793        IF G_DEBUG = 'Y' THEN
9794          AHL_DEBUG_PUB.debug('l_counter_remain:' || l_counter_remain);
9795        END IF;
9796 
9797        -- get date from forecast.
9798        get_date_from_uf(l_counter_remain,
9799                         p_deferral_threshold_tbl(i).uom_code,
9800                         l_counter_rules_tbl,
9801                         sysdate,
9802                         l_due_date);
9803 
9804        IF (l_due_date IS NULL) THEN
9805            l_calc_due_date := NULL;
9806            EXIT;
9807        ELSIF (l_calc_due_date IS NULL) THEN
9808            l_calc_due_date := l_due_date;
9809        ELSIF (l_whichever_first_code = 'FIRST') THEN
9810            IF (trunc(l_due_date) < trunc(l_calc_due_date)) THEN
9811              l_calc_due_date := l_due_date;
9812            END IF;
9813        ELSIF (l_whichever_first_code = 'LAST') THEN
9814            IF (trunc(l_due_date) > trunc(l_calc_due_date)) THEN
9815              l_calc_due_date := l_due_date;
9816            END IF;
9817        END IF;
9818 
9819      END LOOP;
9820   END IF;
9821   x_due_date := l_calc_due_date;
9822 
9823   -- Standard call to get message count and if count is 1, get message info
9824   FND_MSG_PUB.Count_And_Get
9825     ( p_count => x_msg_count,
9826       p_data  => x_msg_data,
9827       p_encoded => fnd_api.g_false
9828     );
9829 
9830 --
9831 EXCEPTION
9832  WHEN FND_API.G_EXC_ERROR THEN
9833    x_return_status := FND_API.G_RET_STS_ERROR;
9834    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
9835                               p_data  => x_msg_data,
9836                               p_encoded => fnd_api.g_false);
9837 
9838    -- Disable debug
9839    AHL_DEBUG_PUB.disable_debug;
9840 
9841  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
9842    x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
9843    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
9844                               p_data  => x_msg_data,
9845                               p_encoded => fnd_api.g_false);
9846 
9847    -- Disable debug
9848    AHL_DEBUG_PUB.disable_debug;
9849 
9850  WHEN OTHERS THEN
9851 
9852     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
9853     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
9854        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
9855                                p_procedure_name => 'Get_Deferred_Due_Date',
9856                                p_error_text     => SUBSTR(SQLERRM,1,240));
9857     END IF;
9858     FND_MSG_PUB.count_and_get( p_count => x_msg_count,
9859                                p_data  => x_msg_data,
9860                                p_encoded => fnd_api.g_false);
9861 
9862 
9863     -- Disable debug
9864     AHL_DEBUG_PUB.disable_debug;
9865 
9866 END Get_Deferred_Due_Date;
9867 ------------------------------------------------------------------
9868 
9869 -- Get the latest recorded counter reading for a given date.
9870 PROCEDURE get_ctr_reading_for_date (p_csi_item_instance_id IN NUMBER,
9871                                     p_counter_id           IN NUMBER,
9872                                     p_reading_date         IN DATE,
9873                                     x_net_reading        OUT NOCOPY NUMBER) IS
9874 
9875   -- get the latest reading recorded for a counter on any given date.
9876   CURSOR cs_ctr_reading_csr(p_csi_item_instance_id IN NUMBER,
9877                             p_counter_id           IN NUMBER,
9878                             p_reading_date IN DATE) IS
9879     /*SELECT net_reading
9880     FROM cs_ctr_counter_values_v cv, cs_counter_groups cg
9881     WHERE cv.counter_group_id = cg.counter_group_id
9882       AND cg.source_object_code = 'CP'
9883       AND cg.source_object_id = p_csi_item_instance_id
9884       AND cv.counter_id = p_counter_id
9885       AND trunc(VALUE_TIMESTAMP) <= trunc(p_reading_date)
9886     ORDER BY cv.value_timestamp desc; */
9887 
9888 	--priyan
9889 	--Query being changed due to performance related fixes
9890 	--Refer Bug # 4918744
9891 
9892         /* Commented out to fix bug# 6445866. In R12, IB is not instantiating
9893          * counter groups in CS_CSI_COUNTER_GROUPS.
9894 	SELECT --DISTINCT
9895 		CCR.NET_READING
9896 	FROM
9897 		CSI_COUNTERS_VL CC,
9898 		--CS_COUNTER_GROUPS CCA,
9899 		--priyan
9900 		--changes for Bug #5207990.
9901 		CS_CSI_COUNTER_GROUPS CCA,
9902 		CSI_COUNTER_READINGS CCR
9903 	WHERE
9904 		CC.DEFAULTED_GROUP_ID (+)  = CCA.COUNTER_GROUP_ID
9905 		AND CCA.SOURCE_OBJECT_CODE = 'CP'
9906 		AND CCR.COUNTER_ID		   = CC.COUNTER_ID
9907 		AND CCA.SOURCE_OBJECT_ID   = P_CSI_ITEM_INSTANCE_ID
9908 		AND CC.COUNTER_ID          = P_COUNTER_ID
9909 		AND TRUNC(CCR.VALUE_TIMESTAMP) <= TRUNC(P_READING_DATE)
9910 	ORDER BY
9911 		CCR.VALUE_TIMESTAMP DESC;
9912 
9913         */
9914 
9915         SELECT * FROM (
9916     	               SELECT CCR.NET_READING
9917   	               FROM
9918 		               CSI_COUNTER_READINGS CCR
9919 	               WHERE
9920 		               CCR.COUNTER_ID          = P_COUNTER_ID
9921                                AND nvl(CCR.disabled_flag,'N') = 'N'
9922 		               AND TRUNC(CCR.VALUE_TIMESTAMP) <= TRUNC(P_READING_DATE)
9923 	               ORDER BY
9924 		               CCR.VALUE_TIMESTAMP DESC
9925                       )
9926         WHERE rownum < 2;
9927 
9928 
9929   l_net_reading  NUMBER;
9930 
9931 BEGIN
9932 
9933     IF G_DEBUG = 'Y' THEN
9934       AHL_DEBUG_PUB.debug('Start of get_ctr_reading_for_date');
9935     END IF;
9936 
9937     OPEN cs_ctr_reading_csr(p_csi_item_instance_id,
9938                             p_counter_id,
9939                             p_reading_date);
9940     FETCH cs_ctr_reading_csr INTO l_net_reading;
9941     IF (cs_ctr_reading_csr%NOTFOUND) THEN
9942        l_net_reading := 0;
9943     END IF;
9944     CLOSE cs_ctr_reading_csr;
9945 
9946     x_net_reading := l_net_reading;
9947 
9948     IF G_DEBUG = 'Y' THEN
9949       AHL_DEBUG_PUB.debug('End of get_ctr_reading_for_date');
9950     END IF;
9951 
9952 END get_ctr_reading_for_date;
9953 -----------------------------------------------------------------------
9954 
9955 -- Get the earliest date on which a given reading was recorded.
9956 PROCEDURE get_ctr_date_for_reading (p_csi_item_instance_id IN NUMBER,
9957                                     p_counter_id           IN NUMBER,
9958                                     p_counter_value        IN NUMBER,
9959                                     x_ctr_record_date    OUT NOCOPY DATE,
9960                                     x_return_val         OUT NOCOPY BOOLEAN) IS
9961 
9962 
9963   -- get the earliest reading for which the given counter value exceeds.
9964   CURSOR cs_ctr_reading_csr(p_csi_item_instance_id IN NUMBER,
9965                             p_counter_id           IN NUMBER,
9966                             p_counter_value        IN NUMBER) IS
9967     /*
9968 	SELECT value_timestamp
9969     FROM cs_ctr_counter_values_v cv, cs_counter_groups cg
9970     WHERE cv.counter_group_id = cg.counter_group_id
9971       AND cg.source_object_code = 'CP'
9972       AND cg.source_object_id = p_csi_item_instance_id
9973       AND cv.counter_id = p_counter_id
9974       AND nvl(cv.net_reading,0) >= p_counter_value
9975     ORDER BY value_timestamp asc;
9976 	*/
9977 
9978 	--priyan
9979 	--Query being changed due to performance related fixes
9980 	--Refer Bug # 4918744
9981 
9982        /* Commented out to fix bug# 6445866. In R12, IB is not instantiating
9983         * counter groups in CS_CSI_COUNTER_GROUPS.
9984 
9985 	SELECT --DISTINCT
9986 		CCR.VALUE_TIMESTAMP
9987 	FROM
9988 		CSI_COUNTERS_VL CC,
9989 		--CS_COUNTER_GROUPS CCA,
9990 		--priyan
9991 		--Refer Bug # 5207990 for changes.
9992 		CS_CSI_COUNTER_GROUPS CCA,
9993 		CSI_COUNTER_READINGS CCR
9994 	WHERE
9995 		CC.DEFAULTED_GROUP_ID (+)       = CCA.COUNTER_GROUP_ID
9996 		 AND CCA.SOURCE_OBJECT_CODE		= 'CP'
9997 		 AND CCR.COUNTER_ID				= CC.COUNTER_ID
9998 		 AND CCA.SOURCE_OBJECT_ID		= P_CSI_ITEM_INSTANCE_ID
9999 		 AND CC.COUNTER_ID				= P_COUNTER_ID
10000 		 AND NVL(CCR.NET_READING,0)	>= P_COUNTER_VALUE
10001 	ORDER BY
10002 		CCR.VALUE_TIMESTAMP ASC;
10003         */
10004 
10005         SELECT * FROM (
10006                        SELECT CCR.VALUE_TIMESTAMP
10007                        FROM CSI_COUNTER_READINGS CCR
10008                        WHERE CCR.COUNTER_ID = P_COUNTER_ID
10009                          AND nvl(disabled_flag,'N') = 'N'
10010                          AND NVL(CCR.NET_READING,0) >= P_COUNTER_VALUE
10011                        ORDER BY CCR.VALUE_TIMESTAMP ASC
10012                       )
10013          WHERE rownum < 2;
10014 
10015   l_ctr_record_date    DATE;
10016   l_return_val         BOOLEAN := TRUE;
10017 
10018 BEGIN
10019 
10020 
10021   IF G_DEBUG = 'Y' THEN
10022     AHL_DEBUG_PUB.debug('Start of get_ctr_date_for_reading');
10023   END IF;
10024 
10025   OPEN cs_ctr_reading_csr (p_csi_item_instance_id,
10026                            p_counter_id,
10027                            p_counter_value);
10028   FETCH cs_ctr_reading_csr INTO l_ctr_record_date;
10029   IF (cs_ctr_reading_csr%NOTFOUND) THEN
10030      l_return_val := FALSE;
10031      l_ctr_record_date := NULL;
10032   END IF;
10033   CLOSE cs_ctr_reading_csr;
10034 
10035   x_ctr_record_date := l_ctr_record_date;
10036   x_return_val := l_return_val;
10037 
10038   IF G_DEBUG = 'Y' THEN
10039     AHL_DEBUG_PUB.debug('End of get_ctr_date_for_reading');
10040   END IF;
10041 
10042 END get_ctr_date_for_reading;
10043 
10044 -------------------------------------------------------------------------------
10045 -- Calculate due date for all deferred unit effectivities.
10046 PROCEDURE Process_Deferred_UE (p_csi_item_instance_id IN NUMBER,
10047                                p_current_usage_tbl  IN counter_values_tbl_type,
10048                                p_counter_rules_tbl  IN counter_rules_tbl_type)
10049 IS
10050 
10051   -- get all deferred unit effectivity records for the instance and MR.
10052   CURSOR ahl_deferred_ue_csr (p_csi_item_instance_id IN NUMBER,
10053                               p_appln_usage_code     IN VARCHAR2) IS
10054 
10055     SELECT
10056         UE.UNIT_EFFECTIVITY_ID,
10057         UE.OBJECT_TYPE,
10058         UE.CSI_ITEM_INSTANCE_ID,
10059         UE.MR_HEADER_ID,
10060         UE.STATUS_CODE,
10061         UE.DEFER_FROM_UE_ID,
10062         nvl(MR.whichever_first_code, 'FIRST') whichever_first_code,
10063         UDF.unit_deferral_type, UE.CS_INCIDENT_ID, UDF.DEFERRAL_EFFECTIVE_ON,
10064         UDF.AFFECT_DUE_CALC_FLAG, UDF.SET_DUE_DATE, UDF.unit_deferral_id,
10065         MR.title
10066     FROM ahl_unit_effectivities_b UE, ahl_unit_deferrals_b UDF, ahl_mr_headers_b MR
10067     WHERE UE.defer_from_ue_id = UDF.unit_effectivity_id
10068       AND UE.mr_header_id = MR.mr_header_id(+)
10069       AND UE.csi_item_instance_id = p_csi_item_instance_id
10070       AND UE.application_usg_code = p_appln_usage_code
10071       AND status_code IS NULL
10072       --AND defer_from_ue_id IS NOT NULL -- not required as joining table ahl_unit_deferrals_b
10073       AND UDF.unit_deferral_type IN ('DEFERRAL', 'MEL','CDL')
10074       AND NOT EXISTS (SELECT 'x'
10075                       FROM ahl_ue_relationships
10076                       WHERE related_ue_id = UE.unit_effectivity_id
10077                         AND relationship_code = 'PARENT')
10078       AND UDF.approval_status_code = 'DEFERRED'
10079     ORDER BY DEFERRAL_EFFECTIVE_ON ASC;
10080 
10081   /* Commented as we retrieve this info in ahl_deferred_ue_csr
10082   -- Get deferral detail from ahl_unit_deferrals.
10083   CURSOR ahl_unit_deferral_csr (p_deferred_from_ue_id IN NUMBER) IS
10084     SELECT AFFECT_DUE_CALC_FLAG, SET_DUE_DATE, unit_deferral_id, deferral_effective_on
10085     FROM ahl_unit_deferrals_b
10086     WHERE unit_effectivity_id = p_deferred_from_ue_id
10087       AND unit_deferral_type = 'DEFERRAL';
10088   */
10089 
10090   -- Get threshold details.
10091   CURSOR ahl_unit_threshold_csr (p_unit_deferral_id IN NUMBER) IS
10092     SELECT counter_id, counter_value, ctr_value_type_code
10093     FROM ahl_unit_thresholds
10094     WHERE unit_deferral_id = p_unit_deferral_id;
10095 
10096   -- Read applicable relns table for group MR details.
10097   CURSOR ahl_applicable_grp_csr( p_item_instance_id IN NUMBER,
10098                                  p_mr_header_id IN NUMBER) IS
10099 
10100     SELECT related_mr_header_id,
10101            related_csi_item_instance_id,
10102            csi_item_instance_id parent_csi_item_instance_id,
10103            mr_header_id parent_mr_header_id
10104     FROM ahl_applicable_mr_relns
10105     START WITH mr_header_id = p_mr_header_id AND
10106                csi_item_instance_id = p_item_instance_id AND
10107                orig_mr_header_id = p_mr_header_id AND
10108                orig_csi_item_instance_id = p_item_instance_id AND
10109                relationship_code = 'PARENT'
10110     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
10111                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
10112                orig_mr_header_id = p_mr_header_id AND
10113                orig_csi_item_instance_id = p_item_instance_id AND
10114                relationship_code = 'PARENT'
10115     ORDER BY   level;
10116 
10117    -- check repair category for time limit.
10118    cursor get_repair_category_csr(p_cs_incident_id IN NUMBER)
10119     is
10120        select nvl(repair_time,0), cs.expected_resolution_date
10121        from ahl_repair_categories rc, cs_incidents_all_b cs
10122        where rc.sr_urgency_id(+) = cs.incident_urgency_id
10123          and  cs.incident_id = p_cs_incident_id;
10124 
10125    -- Read immediate children of the SR.
10126    CURSOR ahl_ue_reln_csr (p_ue_id  IN NUMBER) IS
10127      SELECT ue.unit_effectivity_id, ue.status_code,
10128             UE.CSI_ITEM_INSTANCE_ID, UE.MR_HEADER_ID
10129      FROM ahl_ue_relationships uer, ahl_unit_effectivities_b ue
10130      WHERE ue.unit_effectivity_id = uer.related_ue_id
10131        AND uer.ue_id = p_ue_id;
10132 
10133 --
10134   l_due_at_counter_value   NUMBER;
10135   --l_affect_due_date_calc   VARCHAR2(1);
10136   l_set_due_date           DATE;
10137   l_unit_deferral_id       NUMBER;
10138   l_deferral_effective_on  DATE;
10139   l_net_reading            NUMBER;
10140   l_due_date               DATE;
10141   l_counter_read_date      DATE;
10142 
10143   l_counter_remain         NUMBER;
10144   l_current_ctr_value      NUMBER;
10145   k                        NUMBER;
10146   l_return_val             BOOLEAN;
10147 
10148   l_calc_due_date          DATE;
10149   l_calc_counter_id        NUMBER;
10150   l_calc_tolerance_flag    ahl_unit_effectivities_app_v.tolerance_flag%TYPE;
10151   l_calc_message_code      ahl_unit_effectivities_app_v.message_code%TYPE;
10152   l_calc_due_counter_value NUMBER;
10153 
10154   l_visit_start_date       DATE;
10155   l_visit_end_date         DATE;
10156   l_visit_assign_code      fnd_lookups.lookup_code%TYPE;
10157 
10158   l_grp_match              VARCHAR2(1);
10159   l_grp_match1             VARCHAR2(1);
10160 
10161   l_unit_deferral_type     VARCHAR2(30);
10162   l_repair_time            NUMBER;
10163   l_expected_resolutn_date DATE;
10164 
10165   l_visit_status           ahl_visits_b.status_code%TYPE;
10166 
10167   -- Added for SB Enh.
10168   l_junk                   VARCHAR2(1);
10169   CURSOR check_applicable_mr(p_mr_title IN VARCHAR2, p_item_instance_id IN NUMBER) IS
10170     SELECT 'x'
10171     FROM ahl_applicable_mrs
10172     WHERE csi_item_instance_id = p_item_instance_id
10173      AND mr_header_id IN (select mr_header_id from ahl_mr_headers_b where title = p_mr_title);
10174 
10175 BEGIN
10176 
10177   IF G_DEBUG = 'Y' THEN
10178     AHL_DEBUG_PUB.debug('Start of process_Deferred_ue');
10179   END IF;
10180 
10181   -- get all open deferred unit effectivities.
10182   FOR unit_effectivity_rec IN ahl_deferred_ue_csr(p_csi_item_instance_id, G_application_usg_code) LOOP
10183 
10184     IF G_DEBUG = 'Y' THEN
10185       AHL_DEBUG_PUB.debug('Processing ..ID:' || unit_effectivity_rec.unit_effectivity_id);
10186       AHL_DEBUG_PUB.debug('Processing ..unit_deferral_type:' || unit_effectivity_rec.unit_deferral_type);
10187     END IF;
10188 
10189     -- Initialize.
10190     l_calc_due_date := null;
10191     --l_calc_counter_id,
10192     l_calc_due_counter_value := null;
10193     l_calc_tolerance_flag := null;
10194     l_calc_message_code := null;
10195 
10196 IF (unit_effectivity_rec.unit_deferral_type = 'DEFERRAL') THEN
10197 
10198         -- added for SB Enh. MR can be terminated due to accomplish trigger.
10199         -- validate MR exists in applicable MRs table.
10200         OPEN check_applicable_mr(unit_effectivity_rec.title, p_csi_item_instance_id);
10201         FETCH check_applicable_mr INTO l_junk;
10202         IF (check_applicable_mr%NOTFOUND) THEN
10203            CLOSE check_applicable_mr;
10204            CONTINUE; -- next record.
10205         END IF;
10206         CLOSE check_applicable_mr;
10207 
10208         -- get deferral details.
10209         l_set_due_date         := unit_effectivity_rec.set_due_date;
10210         l_unit_deferral_id     := unit_effectivity_rec.unit_deferral_id;
10211         l_deferral_effective_on := unit_effectivity_rec.deferral_effective_on;
10212 
10213         /*
10214         OPEN ahl_unit_deferral_csr(unit_effectivity_rec.defer_from_ue_id);
10215         FETCH ahl_unit_deferral_csr INTO l_affect_due_date_calc, l_set_due_date, l_unit_deferral_id,
10216                                          l_deferral_effective_on;
10217         IF (ahl_unit_deferral_csr%NOTFOUND) THEN
10218            CLOSE  ahl_unit_deferral_csr;
10219            FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_NOTFOUND');
10220            FND_MESSAGE.Set_Token('UE_ID',unit_effectivity_rec.defer_from_ue_id);
10221            FND_MSG_PUB.ADD;
10222            RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
10223         END IF;
10224 
10225         CLOSE  ahl_unit_deferral_csr;
10226         */
10227         -- process threshold details for this deferral.
10228         FOR threshold_rec IN ahl_unit_threshold_csr(l_unit_deferral_id) LOOP
10229           l_due_at_counter_value := threshold_rec.counter_value;
10230           l_counter_remain := 0;
10231           l_current_ctr_value := 0;
10232           k := 0;
10233           -- search for the current counter value in p_current_usage_tbl.
10234           IF (p_current_usage_tbl.COUNT > 0) THEN
10235              FOR i IN p_current_usage_tbl.FIRST..p_current_usage_tbl.LAST LOOP
10236                IF (p_current_usage_tbl(i).counter_id = threshold_rec.counter_id) THEN
10237                   l_current_ctr_value := p_current_usage_tbl(i).counter_value;
10238                   k := i;
10239                   EXIT;
10240                END IF;
10241              END LOOP;
10242 
10243              IF G_DEBUG = 'Y' THEN
10244                AHL_DEBUG_PUB.debug('In threshold rec with current usg > 0: ctr val:eff on:ctr type:' || l_current_ctr_value ||':' || l_deferral_effective_on || ':' || threshold_rec.ctr_value_type_code);
10245 
10246              END IF;
10247 
10248              -- Calculate counter remain.
10249              IF (threshold_rec.ctr_value_type_code = 'DEFER_BY') THEN
10250                 -- get counter usage as on deferral_effective_on date.
10251                 get_ctr_reading_for_datetime (p_csi_item_instance_id => p_csi_item_instance_id,
10252                                               p_counter_id           => p_current_usage_tbl(k).counter_id,
10253                                               p_reading_date         => l_deferral_effective_on,
10254                                               x_net_reading          => l_net_reading);
10255 
10256                 -- add net reading to the threshold value.
10257                 l_due_at_counter_value := l_net_reading + l_due_at_counter_value;
10258              END IF; -- defer by.
10259 
10260              l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
10261 
10262              --dbms_output.put_line ('After reading:ctr remain' || l_counter_remain);
10263 
10264              -- calculate due date from forecast.
10265              IF (l_counter_remain > 0) THEN
10266                 --dbms_output.put_line ('counter remain greater than zero');
10267                 -- get date from forecast.
10268                 get_date_from_uf(l_counter_remain,
10269                                  p_current_usage_tbl(k).uom_code,
10270                                  p_counter_rules_tbl,
10271                                  null, /* start date = sysdate */
10272                                  l_due_date);
10273              ELSIF (l_counter_remain < 0) THEN
10274                  --dbms_output.put_line ('counter remain less than zero');
10275                  -- Due date = counter reading date.
10276                  get_ctr_date_for_reading (p_csi_item_instance_id => p_csi_item_instance_id,
10277                                            p_counter_id           => p_current_usage_tbl(k).counter_id,
10278                                            p_counter_value        => l_due_at_counter_value,
10279                                            x_ctr_record_date      => l_counter_read_date,
10280                                            x_return_val           => l_return_val);
10281 
10282                  IF NOT(l_return_val) THEN
10283                     l_due_date := sysdate;
10284                  ELSE
10285                     l_due_date := l_counter_read_date;
10286                  END IF;
10287 
10288              ELSIF (l_counter_remain = 0) THEN  /* due_date = sysdate */
10289                  --dbms_output.put_line ('counter remain is zero');
10290                  l_due_date := sysdate;
10291              END IF; -- counter remain.
10292 
10293              -- For MR type, based on whichever first code, set calculated due date.
10294              -- For SR type, whichever first code = 'FIRST'.
10295              IF (l_due_date IS NULL) THEN
10296                 l_calc_due_date := NULL;
10297                 l_calc_counter_id := p_current_usage_tbl(k).counter_id;
10298                 l_calc_due_counter_value := l_due_at_counter_value;
10299                 EXIT;
10300              ELSIF (l_calc_due_date IS NULL) THEN
10301                 l_calc_due_date := l_due_date;
10302                 l_calc_counter_id := p_current_usage_tbl(k).counter_id;
10303                 l_calc_due_counter_value := l_due_at_counter_value;
10304              ELSE
10305                 IF (unit_effectivity_rec.whichever_first_code = 'FIRST') THEN
10306                   IF (trunc(l_due_date) < trunc(l_calc_due_date)) THEN
10307                     l_calc_due_date := l_due_date;
10308                     l_calc_counter_id := p_current_usage_tbl(k).counter_id;
10309                     l_calc_due_counter_value := l_due_at_counter_value;
10310                   END IF;
10311                 ELSE  -- whichever_first_code = 'LAST'
10312                   IF (trunc(l_due_date) > trunc(l_calc_due_date)) THEN
10313                     l_calc_due_date := l_due_date;
10314                     l_calc_counter_id := p_current_usage_tbl(k).counter_id;
10315                     l_calc_due_counter_value := l_due_at_counter_value;
10316                   END IF;
10317                 END IF;
10318              END IF;
10319 
10320         --dbms_output.put_line ('Bl_calc_due_date:' || l_calc_due_date);
10321         --dbms_output.put_line ('Bset_due_date:' || l_set_due_date);
10322         --dbms_output.put_line ('Bdue_ctr_val:' || l_calc_due_counter_value);
10323         --dbms_output.put_line ('BcounterID:' || l_calc_counter_id);
10324 
10325           END IF; -- current_usage_tbl.
10326         END LOOP; -- threshold rec.
10327 
10328         IF G_DEBUG = 'Y' THEN
10329           AHL_DEBUG_PUB.debug('l_calc_due_date:' || l_calc_due_date);
10330           AHL_DEBUG_PUB.debug('set_due_date:' || l_set_due_date);
10331           AHL_DEBUG_PUB.debug('due_ctr_val:' || l_calc_due_counter_value);
10332           AHL_DEBUG_PUB.debug('counterID:' || l_calc_counter_id);
10333         END IF;
10334 
10335         -- Check calculated due date against set_due_date.
10336         IF (l_calc_due_date IS NOT NULL AND l_set_due_date IS NOT NULL) THEN
10337           IF (unit_effectivity_rec.whichever_first_code = 'FIRST') THEN
10338             IF (trunc(l_set_due_date) < trunc(l_calc_due_date)) THEN
10339                l_calc_due_date := l_set_due_date;
10340                l_calc_counter_id := null;
10341                l_calc_due_counter_value := null;
10342             END IF;
10343           ELSE  -- whichever_first_code = 'LAST'
10344             IF (trunc(l_set_due_date) > trunc(l_calc_due_date)) THEN
10345                l_calc_due_date := l_set_due_date;
10346                l_calc_counter_id := null;
10347                l_calc_due_counter_value := null;
10348             END IF;
10349           END IF;
10350         ELSIF (l_set_due_date IS NOT NULL) THEN
10351           l_calc_due_date := l_set_due_date;
10352           l_calc_counter_id := null;
10353           l_calc_due_counter_value := null;
10354         END IF;
10355 
10356     END IF;  -- unit_effectivity_rec.unit_deferral_type = 'DEFERRAL
10357 
10358 
10359     -- Added for R12: MEL/CDL due date.
10360     IF (unit_effectivity_rec.unit_deferral_type = 'MEL'
10361         OR unit_effectivity_rec.unit_deferral_type = 'CDL') THEN
10362 
10363         -- fix bug# 5217126. This variable is inserted into the temp table.
10364         l_deferral_effective_on := unit_effectivity_rec.deferral_effective_on;
10365 
10366         IF G_DEBUG = 'Y' THEN
10367           AHL_DEBUG_PUB.debug('Calculating due date for MEL/CDL');
10368           AHL_DEBUG_PUB.debug('Deferral Eff on:' || unit_effectivity_rec.DEFERRAL_EFFECTIVE_ON);
10369           AHL_DEBUG_PUB.debug('Processing ..object type:' || unit_effectivity_rec.object_type);
10370         END IF;
10371 
10372         -- validate repair category.
10373         -- Added expected_resolution_date to fix bug# 5217126.
10374         OPEN get_repair_category_csr(unit_effectivity_rec.cs_incident_id);
10375         FETCH get_repair_category_csr INTO l_repair_time, l_expected_resolutn_date;
10376         IF (get_repair_category_csr%NOTFOUND) THEN
10377           --l_calc_due_date := NULL;
10378           FND_MESSAGE.Set_Name('AHL','AHL_PUE_INCIDENT_ID_MISSING');
10379           FND_MESSAGE.Set_Token('CS_INC_ID',unit_effectivity_rec.cs_incident_id);
10380           FND_MSG_PUB.ADD;
10381           RAISE FND_API.G_EXC_ERROR;
10382         ELSE
10383 
10384           IF l_repair_time <> 0 AND
10385               unit_effectivity_rec.DEFERRAL_EFFECTIVE_ON IS NOT NULL
10386           THEN
10387             l_calc_due_date := unit_effectivity_rec.DEFERRAL_EFFECTIVE_ON +
10388                                trunc(l_repair_time/24);
10389           ELSE
10390             -- fix for bug# 5217126.
10391             l_calc_due_date := l_expected_resolutn_date;
10392           END IF;
10393 
10394         END IF; -- get_repair_category_csr%NOTFOUND
10395         CLOSE get_repair_category_csr;
10396 
10397         IF G_DEBUG = 'Y' THEN
10398           AHL_DEBUG_PUB.debug('MEL/CDL:Calculated due date is:' || l_calc_due_date);
10399           AHL_DEBUG_PUB.debug('MEL/CDL:DEFERRAL_EFFECTIVE_ON:' || l_deferral_effective_on);
10400         END IF;
10401 
10402     END IF; -- unit_effectivity_rec.unit_deferral_type = 'MEL'
10403 
10404     -- Call visit work package to get visit end date if unit effectivity has been assigned to a visit.
10405     AHL_UMP_UTIL_PKG.get_visit_details (unit_effectivity_rec.unit_effectivity_id,
10406                                         l_visit_start_date,
10407                                         l_visit_end_date,
10408                                         l_visit_assign_code);
10409 
10410     /*
10411     IF (l_visit_end_date IS NOT NULL AND l_calc_due_date IS NOT NULL) THEN
10412       IF G_DEBUG = 'Y' THEN
10413          AHL_DEBUG_PUB.Debug('Visit assigned:End Date:' || l_visit_end_date);
10414       END IF;
10415 
10416       IF (trunc(l_visit_end_date) < trunc(l_calc_due_date)) THEN
10417            l_calc_tolerance_flag := 'Y';
10418            l_calc_message_code := 'TOLERANCE-BEFORE';
10419       END IF;
10420     END IF;
10421     */
10422 
10423     IF (l_visit_start_date IS NOT NULL AND l_calc_due_date IS NOT NULL) THEN
10424       IF G_DEBUG = 'Y' THEN
10425          AHL_DEBUG_PUB.Debug('Visit assigned: Start Date:' || l_visit_start_date);
10426       END IF;
10427       IF (trunc(l_visit_start_date) > trunc(l_calc_due_date)) THEN
10428            l_calc_tolerance_flag := 'Y';
10429            l_calc_message_code := 'TOLERANCE-EXCEEDED';
10430       END IF;
10431     END IF;
10432 
10433     IF ( l_calc_due_date IS NOT NULL) THEN
10434       IF (trunc(l_calc_due_date) < trunc(sysdate)) THEN
10435          l_calc_tolerance_flag := 'Y';
10436          l_calc_message_code := 'TOLERANCE-EXCEEDED';
10437       END IF;
10438     END IF;
10439 
10440     --dbms_output.put_line ('Al_calc_due_date:' || l_calc_due_date);
10441     --dbms_output.put_line ('Aset_due_date:' || l_set_due_date);
10442     --dbms_output.put_line ('Adue_ctr_val:' || l_calc_due_counter_value);
10443 
10444 
10445     -- Check if workorder already created.
10446     l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status(unit_effectivity_rec.unit_effectivity_id);
10447 
10448     IF (nvl(l_visit_status,'X') IN ('RELEASED','CLOSED')) THEN
10449        -- if UE is on shop floor then keep UE structure as is.
10450        l_grp_match := 'Y';
10451     ELSE
10452        IF (unit_effectivity_rec.object_type = 'MR') THEN
10453 
10454            Match_Group_MR (p_orig_csi_item_instance_id  => unit_effectivity_rec.csi_item_instance_id,
10455                            p_orig_mr_header_id          => unit_effectivity_rec.mr_header_id,
10456                            p_unit_effectivity_id        => unit_effectivity_rec.unit_effectivity_id,
10457                            x_group_match_flag           => l_grp_match);
10458 
10459        ELSE
10460            l_grp_match := 'Y';
10461            -- For SR case, for each child group MR associated match the group MR.
10462            FOR ahl_ue_reln_rec IN ahl_ue_reln_csr(unit_effectivity_rec.unit_effectivity_id) LOOP
10463               IF (ahl_ue_reln_rec.status_code = 'MR-TERMINATE') THEN
10464                     -- skip mr-terminated records.
10465                    l_grp_match1 := 'Y';
10466               ELSE
10467 
10468                    Match_Group_MR (p_orig_csi_item_instance_id  => ahl_ue_reln_rec.csi_item_instance_id,
10469                                    p_orig_mr_header_id          => ahl_ue_reln_rec.mr_header_id,
10470                                    p_unit_effectivity_id        => ahl_ue_reln_rec.unit_effectivity_id,
10471                                    x_group_match_flag           => l_grp_match1);
10472 
10473                   IF (l_grp_match1 = 'N') THEN
10474                       l_grp_match := 'N';
10475                   END IF;
10476 
10477               END IF;
10478 
10479            END LOOP;
10480 
10481        END IF; -- unit_effectivity_rec.object_type
10482     END IF; -- l_visit_status
10483 
10484 
10485     IF G_DEBUG = 'Y' THEN
10486       AHL_DEBUG_PUB.Debug('Group Match flag:l_visit_status:' || l_grp_match || ':' || l_visit_status);
10487     END IF;
10488 
10489     -- insert into deferral temp table.
10490     insert into ahl_temp_unit_SR_deferrals (
10491         unit_effectivity_id,
10492         object_type,
10493         csi_item_instance_id,
10494         mr_header_id,
10495         due_date,
10496         counter_id,
10497         due_counter_value,
10498         tolerance_flag,
10499         message_code,
10500         parent_csi_item_instance_id,
10501         parent_mr_header_id,
10502         orig_csi_item_instance_id,
10503         orig_mr_header_id,
10504         orig_unit_effectivity_id,
10505         visit_end_date,
10506         deferral_effective_on,
10507         affect_due_calc_flag,
10508         group_match_flag)
10509     VALUES (
10510         unit_effectivity_rec.unit_effectivity_id,
10511         unit_effectivity_rec.object_type,
10512         unit_effectivity_rec.csi_item_instance_id,
10513         unit_effectivity_rec.mr_header_id,
10514         l_calc_due_date,
10515         l_calc_counter_id,
10516         l_calc_due_counter_value,
10517         l_calc_tolerance_flag,
10518         l_calc_message_code,
10519         null,
10520         null,
10521         null,
10522         null,
10523         null,
10524         l_visit_end_date,
10525         l_deferral_effective_on,
10526         --l_affect_due_date_calc,
10527         unit_effectivity_rec.AFFECT_DUE_CALC_FLAG,
10528         l_grp_match);
10529 
10530     -- Insert all child MRs for group MR.
10531     FOR ahl_applicable_grp_rec IN ahl_applicable_grp_csr(unit_effectivity_rec.csi_item_instance_id,
10532                                                          unit_effectivity_rec.mr_header_id)
10533     LOOP
10534            -- insert into deferral temp table.
10535            insert into ahl_temp_unit_SR_deferrals (
10536                unit_effectivity_id,
10537                object_type,
10538                csi_item_instance_id,
10539                mr_header_id,
10540                due_date,
10541                due_counter_value,
10542                tolerance_flag,
10543                message_code,
10544                parent_csi_item_instance_id,
10545                parent_mr_header_id,
10546                orig_csi_item_instance_id,
10547                orig_mr_header_id,
10548                orig_unit_effectivity_id,
10549                visit_end_date,
10550                deferral_effective_on,
10551                affect_due_calc_flag,
10552                group_match_flag)
10553            VALUES (
10554                null,
10555                'MR',
10556                ahl_applicable_grp_rec.related_csi_item_instance_id,
10557                ahl_applicable_grp_rec.related_mr_header_id,
10558                l_calc_due_date,
10559                l_calc_due_counter_value,
10560                l_calc_tolerance_flag,
10561                l_calc_message_code,
10562                ahl_applicable_grp_rec.parent_csi_item_instance_id,
10563                ahl_applicable_grp_rec.parent_mr_header_id,
10564                unit_effectivity_rec.csi_item_instance_id,
10565                unit_effectivity_rec.mr_header_id,
10566                unit_effectivity_rec.unit_effectivity_id,
10567                l_visit_end_date,
10568                l_deferral_effective_on,
10569                --l_affect_due_date_calc,
10570                unit_effectivity_rec.AFFECT_DUE_CALC_FLAG,
10571                l_grp_match);
10572 
10573     END LOOP;
10574     --fix for bug#5217126
10575     --CLOSE ahl_unit_deferral_csr;
10576 
10577   END LOOP; -- unit effectivity rec.
10578 
10579   IF G_DEBUG = 'Y' THEN
10580     AHL_DEBUG_PUB.debug('End of process_Deferred_ue');
10581   END IF;
10582 
10583 END Process_Deferred_UE;
10584 -----------------------------------------------
10585 
10586 -- Explode SR's having MRs for calculating MR due dates.
10587 PROCEDURE Process_SR_UE (p_csi_item_instance_id IN NUMBER)  IS
10588 
10589   CURSOR ahl_ue_sr_csr (p_csi_item_instance_id IN NUMBER,
10590                         p_appln_usg_code       IN VARCHAR2) IS
10591     SELECT
10592         UE.UNIT_EFFECTIVITY_ID,
10593         UE.OBJECT_TYPE,
10594         UE.CSI_ITEM_INSTANCE_ID,
10595         UE.MR_HEADER_ID,
10596         UE.STATUS_CODE,
10597         UE.DUE_DATE,
10598         UE.DUE_COUNTER_VALUE
10599     FROM ahl_unit_effectivities_b UE
10600     WHERE UE.OBJECT_TYPE = 'SR'
10601       AND UE.application_usg_code = p_appln_usg_code
10602       AND defer_from_ue_id IS NULL
10603       AND csi_item_instance_id = p_csi_item_instance_id
10604       -- added init-due status as part of USAF: Complex Assembly enhancements
10605       AND (status_code IS NULL OR status_code = 'INIT-DUE');
10606 
10607 
10608   -- Read applicable relns table for group MR details.
10609   CURSOR ahl_applicable_grp_csr( p_item_instance_id IN NUMBER,
10610                                  p_mr_header_id IN NUMBER) IS
10611 
10612     SELECT related_mr_header_id,
10613            related_csi_item_instance_id,
10614            csi_item_instance_id parent_csi_item_instance_id,
10615            mr_header_id parent_mr_header_id
10616     FROM ahl_applicable_mr_relns
10617     START WITH mr_header_id = p_mr_header_id AND
10618                csi_item_instance_id = p_item_instance_id AND
10619                orig_mr_header_id = p_mr_header_id AND
10620                orig_csi_item_instance_id = p_item_instance_id AND
10621                relationship_code = 'PARENT'
10622     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
10623                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
10624                orig_mr_header_id = p_mr_header_id AND
10625                orig_csi_item_instance_id = p_item_instance_id AND
10626                relationship_code = 'PARENT'
10627     ORDER BY   level;
10628 
10629 
10630   -- Read immediate children of the SR.
10631   CURSOR ahl_ue_reln_csr (p_ue_id  IN NUMBER) IS
10632     SELECT ue.unit_effectivity_id, ue.status_code,
10633            UE.CSI_ITEM_INSTANCE_ID, UE.MR_HEADER_ID
10634     FROM ahl_ue_relationships uer, ahl_unit_effectivities_app_v ue
10635     WHERE ue.unit_effectivity_id = uer.related_ue_id
10636       AND uer.ue_id = p_ue_id;
10637 
10638 
10639   l_calc_tolerance_flag    ahl_unit_effectivities_app_v.tolerance_flag%TYPE;
10640   l_calc_message_code      ahl_unit_effectivities_app_v.message_code%TYPE;
10641 
10642   l_visit_start_date       DATE;
10643   l_visit_end_date         DATE;
10644   l_visit_assign_code      fnd_lookups.lookup_code%TYPE;
10645 
10646   l_grp_match              VARCHAR2(1);
10647   l_grp_match1             VARCHAR2(1);
10648 
10649   l_visit_status           ahl_visits_b.status_code%TYPE;
10650 
10651   -- added for Complx Assy Enh
10652   l_due_date               DATE;
10653   l_due_counter_value      NUMBER;
10654   l_counter_id             NUMBER;
10655 
10656 BEGIN
10657 
10658   IF G_DEBUG = 'Y' THEN
10659     AHL_DEBUG_PUB.debug('Start of Process_SR_UE');
10660   END IF;
10661 
10662   -- Get all UE's with object-type = SR.
10663   FOR ahl_ue_sr_rec IN ahl_ue_sr_csr(p_csi_item_instance_id, G_application_usg_code) LOOP
10664 
10665     -- Start USAF: Complx Assy Enh: calculate due date if NR status is INIT-DUE.
10666     IF (ahl_ue_sr_rec.status_code = 'INIT-DUE') THEN
10667        Calculate_NR_due_date(p_unit_effectivity_id => ahl_ue_sr_rec.unit_effectivity_id,
10668                              x_due_date => l_due_date,
10669                              x_due_counter_value => l_due_counter_value,
10670                              x_counter_id        => l_counter_id);
10671     ELSE
10672        l_due_date := ahl_ue_sr_rec.due_date;
10673        l_due_counter_value := ahl_ue_sr_rec.due_counter_value;
10674        l_counter_id := null;
10675     END IF;
10676 
10677     -- Call visit work package to get visit end date if unit effectivity has been assigned to a visit.
10678     AHL_UMP_UTIL_PKG.get_visit_details (ahl_ue_sr_rec.unit_effectivity_id,
10679                                         l_visit_start_date,
10680                                         l_visit_end_date,
10681                                         l_visit_assign_code);
10682 
10683     IF (l_visit_end_date IS NOT NULL AND ahl_ue_sr_rec.due_date IS NOT NULL) THEN
10684       IF G_DEBUG = 'Y' THEN
10685          AHL_DEBUG_PUB.Debug('Visit assigned:End Date:' || l_visit_end_date);
10686       END IF;
10687 
10688       IF (trunc(l_visit_end_date) < trunc(ahl_ue_sr_rec.due_date )) THEN
10689            l_calc_tolerance_flag := 'Y';
10690            l_calc_message_code := 'TOLERANCE-BEFORE';
10691       END IF;
10692     END IF;
10693 
10694     IF (l_visit_start_date IS NOT NULL AND ahl_ue_sr_rec.due_date IS NOT NULL) THEN
10695       IF G_DEBUG = 'Y' THEN
10696          AHL_DEBUG_PUB.Debug('Visit assigned:Start Date:' || l_visit_start_date);
10697       END IF;
10698 
10699       IF (trunc(l_visit_start_date) > trunc(ahl_ue_sr_rec.due_date )) THEN
10700            l_calc_tolerance_flag := 'Y';
10701            l_calc_message_code := 'TOLERANCE-EXCEEDED';
10702       END IF;
10703     END IF;
10704 
10705     -- Check if workorder already created.
10706     l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status(ahl_ue_sr_rec.unit_effectivity_id);
10707 
10708     IF (nvl(l_visit_status,'X') IN ('RELEASED','CLOSED')) THEN
10709        -- if UE is on shop floor then keep UE structure as is.
10710        l_grp_match := 'Y';
10711     ELSE
10712       -- initialize.
10713       l_grp_match := 'Y';
10714 
10715       -- For each group MR associated match the group MR.
10716       FOR ahl_ue_reln_rec IN ahl_ue_reln_csr(ahl_ue_sr_rec.unit_effectivity_id) LOOP
10717         IF (ahl_ue_reln_rec.status_code = 'MR-TERMINATE') THEN
10718            -- skip mr-terminated records.
10719            l_grp_match1 := 'Y';
10720         ELSE
10721 
10722            Match_Group_MR (p_orig_csi_item_instance_id  => ahl_ue_reln_rec.csi_item_instance_id,
10723                            p_orig_mr_header_id          => ahl_ue_reln_rec.mr_header_id,
10724                            p_unit_effectivity_id        => ahl_ue_reln_rec.unit_effectivity_id,
10725                            x_group_match_flag           => l_grp_match1);
10726 
10727           IF (l_grp_match1 = 'N') THEN
10728             l_grp_match := 'N';
10729           END IF;
10730         END IF;
10731 
10732       END LOOP;
10733     END IF; --l_visit_status
10734 
10735     -- Write SR UE into temporary table.
10736     insert into ahl_temp_unit_SR_deferrals (
10737         unit_effectivity_id,
10738         object_type,
10739         csi_item_instance_id,
10740         mr_header_id,
10741         due_date,
10742         due_counter_value,
10743         counter_id,
10744         tolerance_flag,
10745         message_code,
10746         parent_csi_item_instance_id,
10747         parent_mr_header_id,
10748         orig_mr_header_id,
10749         orig_csi_item_instance_id,
10750         orig_unit_effectivity_id,
10751         visit_end_date,
10752         deferral_effective_on,
10753         affect_due_calc_flag,
10754         group_match_flag)
10755      VALUES (
10756         ahl_ue_sr_rec.unit_effectivity_id,
10757         ahl_ue_sr_rec.object_type,
10758         ahl_ue_sr_rec.csi_item_instance_id,
10759         null,
10760         --ahl_ue_sr_rec.due_date,
10761         --ahl_ue_sr_rec.due_counter_value,
10762         l_due_date,
10763         l_due_counter_value,
10764         l_counter_id,
10765         l_calc_tolerance_flag,
10766         l_calc_message_code,
10767         null,
10768         null,
10769         null,
10770         null,
10771         null,
10772         l_visit_end_date,
10773         null,
10774         'Y',
10775         l_grp_match);
10776 
10777 
10778       -- Write child MRs into temporary table.
10779 
10780       FOR ahl_applicable_grp_rec IN ahl_applicable_grp_csr(ahl_ue_sr_rec.csi_item_instance_id,
10781                                                            ahl_ue_sr_rec.mr_header_id)
10782       LOOP
10783            -- insert into deferral temp table.
10784            insert into ahl_temp_unit_SR_deferrals (
10785                unit_effectivity_id,
10786                object_type,
10787                csi_item_instance_id,
10788                mr_header_id,
10789                due_date,
10790                due_counter_value,
10791                tolerance_flag,
10792                message_code,
10793                parent_csi_item_instance_id,
10794                parent_mr_header_id,
10795                orig_csi_item_instance_id,
10796                orig_mr_header_id,
10797                orig_unit_effectivity_id,
10798                visit_end_date,
10799                deferral_effective_on,
10800                affect_due_calc_flag,
10801                group_match_flag)
10802            VALUES (
10803                null,
10804                null,
10805                ahl_applicable_grp_rec.related_csi_item_instance_id,
10806                ahl_applicable_grp_rec.related_mr_header_id,
10807                ahl_ue_sr_rec.due_date,
10808                ahl_ue_sr_rec.due_counter_value,
10809                l_calc_tolerance_flag,
10810                l_calc_message_code,
10811                ahl_applicable_grp_rec.parent_csi_item_instance_id,
10812                ahl_applicable_grp_rec.parent_mr_header_id,
10813                ahl_ue_sr_rec.csi_item_instance_id,
10814                ahl_ue_sr_rec.mr_header_id,
10815                ahl_ue_sr_rec.unit_effectivity_id,
10816                l_visit_end_date,
10817                null,
10818                'Y',
10819                l_grp_match);
10820 
10821       END LOOP;
10822 
10823   END LOOP;
10824 
10825   IF G_DEBUG = 'Y' THEN
10826     AHL_DEBUG_PUB.debug('End of Process_SR_UE');
10827   END IF;
10828 
10829 END Process_SR_UE;
10830 
10831 -----------------------------------------------
10832 
10833 -- Match if current UE group MR matches the applicable group MR.
10834 PROCEDURE Match_Group_MR (p_orig_csi_item_instance_id  IN NUMBER,
10835                           p_orig_mr_header_id          IN NUMBER,
10836                           p_unit_effectivity_id        IN NUMBER,
10837                           x_group_match_flag       OUT NOCOPY VARCHAR2)
10838 IS
10839 
10840   -- Get all child UE's for a given unit effectivity.
10841   CURSOR ahl_ue_relns_csr (p_unit_effectivity_id  IN NUMBER) IS
10842     SELECT related_ue_id, ue_id, level
10843     FROM  ahl_ue_relationships
10844     START WITH ue_id = p_unit_effectivity_id
10845            AND relationship_code = 'PARENT'
10846     CONNECT BY PRIOR related_ue_id = ue_id
10847            AND relationship_code = 'PARENT'
10848     ORDER BY level;
10849 
10850   -- get unit effectivities details.
10851   CURSOR ahl_ue_csr ( p_ue_id IN NUMBER,
10852                       p_related_ue_id IN NUMBER ) IS
10853     SELECT ue1.mr_header_id, ue1.csi_item_instance_id,
10854            ue2.mr_header_id related_mr_header_id,
10855            ue2.csi_item_instance_id related_csi_item_instance_id
10856     FROM ahl_unit_effectivities_b ue1, ahl_unit_effectivities_b ue2
10857     WHERE ue1.unit_effectivity_id = p_ue_id AND
10858           ue2.unit_effectivity_id = p_related_ue_id;
10859 
10860   -- Read applicable relns table for group MR details.
10861   CURSOR ahl_applicable_grp_csr( p_item_instance_id IN NUMBER,
10862                                  p_mr_header_id IN NUMBER) IS
10863 
10864     SELECT mr_header_id, csi_item_instance_id,
10865            related_mr_header_id,
10866            related_csi_item_instance_id, level
10867     FROM ahl_applicable_mr_relns
10868     START WITH mr_header_id = p_mr_header_id AND
10869                csi_item_instance_id = p_item_instance_id AND
10870                orig_mr_header_id = p_mr_header_id AND
10871                orig_csi_item_instance_id = p_item_instance_id AND
10872                relationship_code = 'PARENT'
10873     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
10874                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
10875                orig_mr_header_id = p_mr_header_id AND
10876                orig_csi_item_instance_id = p_item_instance_id AND
10877                relationship_code = 'PARENT'
10878     ORDER BY   level;
10879 
10880 
10881   TYPE ue_details_rec_type IS RECORD (
10882      mr_header_id NUMBER,
10883      csi_item_instance_id NUMBER,
10884      related_mr_header_id NUMBER,
10885      related_csi_item_instance_id NUMBER,
10886      level                NUMBER,
10887      unit_effectivity_id  NUMBER,
10888      match_flag           VARCHAR2(1));
10889 
10890   l_ue_details_rec       ue_details_rec_type;
10891 
10892   TYPE l_ue_details_tbl_type IS TABLE OF ue_details_rec_type INDEX BY BINARY_INTEGER;
10893 
10894   l_ue_details_tbl       l_ue_details_tbl_type;
10895   l_grp_details_tbl      l_ue_details_tbl_type;
10896   i                      NUMBER;
10897 
10898 BEGIN
10899 
10900     IF G_DEBUG = 'Y' THEN
10901       AHL_DEBUG_PUB.debug('Start of Match_Group_MR');
10902     END IF;
10903 
10904     -- Match the ue relations tree with the group applicablilty tree.
10905     i := 1;
10906     FOR ahl_ue_relns_rec in ahl_ue_relns_csr(p_unit_effectivity_id) LOOP
10907        OPEN ahl_ue_csr(ahl_ue_relns_rec.ue_id, ahl_ue_relns_rec.related_ue_id);
10908        FETCH ahl_ue_csr INTO l_ue_details_tbl(i).mr_header_id,
10909                              l_ue_details_tbl(i).csi_item_instance_id,
10910                              l_ue_details_tbl(i).related_mr_header_id,
10911                              l_ue_details_tbl(i).related_csi_item_instance_id;
10912        IF (ahl_ue_csr%NOTFOUND) THEN
10913            FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_RELN_NOTFOUND');
10914            FND_MESSAGE.Set_Token('UE_ID',ahl_ue_relns_rec.ue_id);
10915            FND_MESSAGE.Set_Token('RELATED_UE_ID', ahl_ue_relns_rec.related_ue_id);
10916            FND_MSG_PUB.ADD;
10917            RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
10918        END IF;
10919 
10920        l_ue_details_tbl(i).level := ahl_ue_relns_rec.level;
10921        l_ue_details_tbl(i).unit_effectivity_id := ahl_ue_relns_rec.related_ue_id;
10922        l_ue_details_tbl(i).match_flag := 'N';
10923 
10924        --dbms_output.put_line ('found ue relns');
10925        i := i + 1;
10926        CLOSE ahl_ue_csr;
10927     END LOOP;
10928 
10929     i := 1;
10930     -- from applicable_mrs_relations.
10931     FOR l_appl_grp_rec IN ahl_applicable_grp_csr(p_orig_csi_item_instance_id,
10932                                                  p_orig_mr_header_id)
10933 
10934     LOOP
10935       l_grp_details_tbl(i).mr_header_id := l_appl_grp_rec.mr_header_id;
10936       l_grp_details_tbl(i).csi_item_instance_id := l_appl_grp_rec.csi_item_instance_id;
10937       l_grp_details_tbl(i).related_mr_header_id := l_appl_grp_rec.related_mr_header_id;
10938       l_grp_details_tbl(i).related_csi_item_instance_id := l_appl_grp_rec.related_csi_item_instance_id;
10939       l_grp_details_tbl(i).level := l_appl_grp_rec.level;
10940       l_grp_details_tbl(i).match_flag := 'N';
10941       i := i + 1;
10942     END LOOP;
10943 
10944     -- Now compare l_grp_details_tbl with l_ue_details_tbl.
10945     IF (l_grp_details_tbl.COUNT > 0) THEN
10946        FOR i IN l_grp_details_tbl.FIRST..l_grp_details_tbl.LAST LOOP
10947          -- match if entry present in l_ue_details_tbl.
10948          IF (l_ue_details_tbl.COUNT > 0 ) THEN
10949             FOR j IN l_ue_details_tbl.FIRST..l_ue_details_tbl.LAST LOOP
10950               IF (l_ue_details_tbl(j).mr_header_id = l_grp_details_tbl(i).mr_header_id AND
10951                  l_ue_details_tbl(j).csi_item_instance_id = l_grp_details_tbl(i).csi_item_instance_id AND
10952                  l_ue_details_tbl(j).related_csi_item_instance_id = l_grp_details_tbl(i).related_csi_item_instance_id AND
10953                  l_ue_details_tbl(j).related_mr_header_id = l_grp_details_tbl(i).related_mr_header_id AND
10954                  l_ue_details_tbl(j).level = l_grp_details_tbl(i).level AND
10955                  l_ue_details_tbl(j).match_flag = 'N' AND
10956                  l_grp_details_tbl(i).match_flag = 'N') THEN
10957                      --l_ue_details_tbl.DELETE(j);
10958                      --l_grp_details_tbl.DELETE(i);
10959                      l_ue_details_tbl(j).match_flag := 'Y';
10960                      l_grp_details_tbl(i).match_flag := 'Y';
10961                      EXIT;
10962               END IF;
10963             END LOOP; /* ue_details */
10964          END IF; /* count - ue_details */
10965        END LOOP; /* grp_details */
10966     END IF; /* count - grp_details */
10967 
10968     -- delete records from table where match flag is Y.
10969     IF (l_ue_details_tbl.COUNT > 0 ) THEN
10970       FOR j IN l_ue_details_tbl.FIRST..l_ue_details_tbl.LAST LOOP
10971         IF (l_ue_details_tbl(j).match_flag = 'Y') THEN
10972            l_ue_details_tbl.DELETE(j);
10973         END IF;
10974       END LOOP;
10975     END IF;
10976 
10977     IF (l_grp_details_tbl.COUNT > 0 ) THEN
10978       FOR i IN l_grp_details_tbl.FIRST..l_grp_details_tbl.LAST LOOP
10979          IF (l_grp_details_tbl(i).match_flag = 'Y') THEN
10980            l_grp_details_tbl.DELETE(i);
10981          END IF;
10982       END LOOP;
10983     END IF;
10984 
10985     IF (l_ue_details_tbl.COUNT = 0) AND (l_grp_details_tbl.COUNT = 0) THEN
10986       x_group_match_flag := 'Y';
10987 
10988     ELSE
10989       x_group_match_flag := 'N';
10990 
10991     END IF;
10992 
10993     IF G_DEBUG = 'Y' THEN
10994       AHL_DEBUG_PUB.debug('End of Match_Group_MR');
10995     END IF;
10996 
10997 END Match_Group_MR;
10998 
10999 -----------------------------------------------
11000 
11001 PROCEDURE Process_Unplanned_UE(p_csi_item_instance_id IN NUMBER,
11002                                p_current_usage_tbl    IN counter_values_tbl_type,
11003                                p_counter_rules_tbl    IN counter_rules_tbl_type) IS
11004 
11005   -- Read Unplanned MRs.(only top nodes)
11006   CURSOR ahl_unplanned_ue_csr(p_csi_item_instance_id IN NUMBER,
11007                               p_appln_usage_code     IN VARCHAR2) IS
11008     SELECT ue.mr_header_id,
11009            ue.csi_item_instance_id,
11010            ue.unit_effectivity_id,
11011            ue.status_code
11012     FROM ahl_unit_effectivities_b ue
11013     /*
11014     WHERE NOT EXISTS ( SELECT 'x'
11015                        --FROM ahl_ue_relationships uer, ahl_unit_effectivities_app_v ue1
11016                        FROM ahl_ue_relationships uer, ahl_unit_effectivities_b ue1
11017                        WHERE uer.related_ue_id = ue.unit_effectivity_id AND
11018                              uer.originator_ue_id = ue1.unit_effectivity_id AND
11019                              ue1.object_type <> 'SR' )
11020     */
11021     -- pick up only top nodes.
11022     WHERE NOT EXISTS (SELECT 'x'
11023                       FROM ahl_ue_relationships uer
11024                       WHERE uer.related_ue_id = ue.unit_effectivity_id
11025                         AND relationship_code = 'PARENT')
11026         AND ue.csi_item_instance_id = p_csi_item_instance_id
11027         AND ue.application_usg_code = p_appln_usage_code
11028         AND nvl(ue.manually_planned_flag,'N') = 'Y'
11029         AND ue.object_type = 'MR'
11030         AND ue.defer_from_ue_id IS NULL
11031         AND (ue.status_code IS NULL OR ue.status_code = 'EXCEPTION');
11032 
11033   -- modified to check for end date as part of fix for bug# 9263774.
11034   -- added select columns for SB Enh.
11035   CURSOR ahl_applicable_mr_csr (p_csi_item_instance_id IN NUMBER,
11036                                 p_mr_header_id         IN NUMBER) IS
11037     SELECT 'x'
11038     FROM ahl_applicable_mrs appl, ahl_mr_headers_b mr
11039     WHERE appl.mr_header_id = p_mr_header_id AND
11040           appl.csi_item_instance_id = p_csi_item_instance_id AND
11041           appl.mr_header_id = mr.mr_header_id AND
11042           trunc(sysdate) <= trunc(nvl(mr.effective_to,sysdate+1));
11043 
11044   -- Cursor to get all details of a unit effectivity record.
11045   CURSOR ahl_unit_effectivity_csr ( p_unit_effectivity_id IN NUMBER) IS
11046      SELECT
11047         UNIT_EFFECTIVITY_ID ,
11048         CSI_ITEM_INSTANCE_ID,
11049         MR_INTERVAL_ID,
11050         MR_EFFECTIVITY_ID ,
11051         MR_HEADER_ID,
11052         STATUS_CODE ,
11053         DUE_DATE   ,
11054         DUE_COUNTER_VALUE ,
11055         FORECAST_SEQUENCE ,
11056         REPETITIVE_MR_FLAG ,
11057         TOLERANCE_FLAG ,
11058         REMARKS ,
11059         MESSAGE_CODE ,
11060         PRECEDING_UE_ID ,
11061         DATE_RUN ,
11062         SET_DUE_DATE ,
11063         ACCOMPLISHED_DATE ,
11064         CANCEL_REASON_CODE,
11065         EARLIEST_DUE_DATE,
11066         LATEST_DUE_DATE,
11067         SERVICE_LINE_ID,
11068         PROGRAM_MR_HEADER_ID,
11069         defer_from_ue_id,
11070         cs_incident_id,
11071         qa_collection_id,
11072         orig_deferral_ue_id,
11073         application_usg_code,
11074         object_type,
11075         counter_id,
11076         manually_planned_flag,
11077         LOG_SERIES_CODE,
11078         LOG_SERIES_NUMBER, FLIGHT_NUMBER, MEL_CDL_TYPE_CODE,
11079         POSITION_PATH_ID,
11080         ATA_CODE, UNIT_CONFIG_HEADER_ID,
11081         ATTRIBUTE_CATEGORY ,
11082         ATTRIBUTE1,
11083         ATTRIBUTE2 ,
11084         ATTRIBUTE3 ,
11085         ATTRIBUTE4 ,
11086         ATTRIBUTE5 ,
11087         ATTRIBUTE6 ,
11088         ATTRIBUTE7 ,
11089         ATTRIBUTE8 ,
11090         ATTRIBUTE9 ,
11091         ATTRIBUTE10,
11092         ATTRIBUTE11 ,
11093         ATTRIBUTE12 ,
11094         ATTRIBUTE13 ,
11095         ATTRIBUTE14 ,
11096         ATTRIBUTE15 ,
11097         OBJECT_VERSION_NUMBER
11098      FROM ahl_unit_effectivities_vl
11099      WHERE unit_effectivity_id = p_unit_effectivity_id
11100      FOR UPDATE OF message_code NOWAIT;
11101 
11102   -- Read group from ahl_ue_relationships.
11103   CURSOR decendent_csr (p_unit_effectivity_id IN NUMBER) IS
11104     SELECT related_ue_id
11105     FROM ahl_ue_relationships
11106     WHERE relationship_code = 'PARENT' AND
11107           originator_ue_id = p_unit_effectivity_id;
11108 
11109   l_exception_flag  BOOLEAN;
11110   l_grp_match_flag  VARCHAR2(1);
11111   l_message_code    ahl_unit_effectivities_b.message_code%TYPE;
11112   l_status_code     ahl_unit_effectivities_b.status_code%TYPE;
11113   l_junk            VARCHAR2(1);
11114 
11115   l_ue_rec          ahl_unit_effectivity_csr%ROWTYPE;
11116 
11117   l_visit_status    VARCHAR2(30);
11118 
11119   -- Added for SB Enh. Process unplanned 'chain' MRs.
11120   l_applicable_mr_rec  applicable_mrs_rec_type;
11121 
11122   CURSOR chain_appl_mr_csr (p_csi_item_instance_id IN NUMBER) IS
11123     SELECT DISTINCT mr.Title,
11124            mr.version_number,
11125            appl.mr_header_id,
11126            appl.Implement_status_code,
11127            appl.copy_accomplishment_code,
11128            appl.repetitive_flag,
11129            appl.show_repetitive_code,
11130            appl.descendent_count,
11131            mr.whichever_first_code,
11132            mr.effective_to,
11133            mr.effective_from,
11134            appl.terminate_trigger_check,
11135            appl.accomplish_trigger_type,
11136            appl.loop_chain_seq_num
11137     FROM ahl_applicable_mrs appl, ahl_mr_headers_b mr
11138     WHERE appl.csi_item_instance_id = p_csi_item_instance_id AND
11139           appl.mr_header_id = mr.mr_header_id AND
11140           trunc(sysdate) <= trunc(nvl(mr.effective_to,sysdate+1)) AND
11141           appl.Implement_status_code = 'OPTIONAL_DO_NOT_IMPLEMENT' AND
11142           appl.accomplish_trigger_type = 'CHAIN' AND
11143           appl.mr_header_id = appl.start_mr_header_id;
11144 
11145     l_lc_mr_tbl    loop_chain_MR_tbl_type;
11146 BEGIN
11147 
11148   IF G_DEBUG = 'Y' THEN
11149     AHL_DEBUG_PUB.debug('Start of Process_Unplanned_UE');
11150   END IF;
11151 
11152   -- Loop through all Unplanned MRs.
11153   FOR ahl_unplanned_ue_rec IN ahl_unplanned_ue_csr(p_csi_item_instance_id,G_application_usg_code) LOOP
11154     -- initialize.
11155     l_exception_flag := FALSE;
11156 
11157     -- Check if workorder already created.
11158     l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status (ahl_unplanned_ue_rec.unit_effectivity_id);
11159 
11160     -- only if visit is in planning status we must mark an exception.
11161     -- if visit is already on the floor, we do nothing.
11162     IF (nvl(l_visit_status,'X') NOT IN ('RELEASED','CLOSED')) THEN
11163 
11164       -- Check if top node applicable.
11165       OPEN ahl_applicable_mr_csr(ahl_unplanned_ue_rec.csi_item_instance_id,
11166                                  ahl_unplanned_ue_rec.mr_header_id);
11167       FETCH ahl_applicable_mr_csr INTO l_junk;
11168       IF (ahl_applicable_mr_csr%FOUND) THEN
11169         --Match the group.
11170         Match_Group_MR (p_orig_csi_item_instance_id  => ahl_unplanned_ue_rec.csi_item_instance_id,
11171                         p_orig_mr_header_id          => ahl_unplanned_ue_rec.mr_header_id,
11172                         p_unit_effectivity_id        => ahl_unplanned_ue_rec.unit_effectivity_id,
11173                         x_group_match_flag           => l_grp_match_flag);
11174 
11175         IF (l_grp_match_flag = 'N') THEN
11176           l_exception_flag := TRUE;
11177         END IF;
11178       ELSE
11179         l_exception_flag := TRUE;
11180       END IF; -- ahl_applicable_mr_csr found chk.
11181       CLOSE ahl_applicable_mr_csr;
11182 
11183       IF G_DEBUG = 'Y' THEN
11184         AHL_DEBUG_PUB.debug('Group Match Flag for UE:' || ahl_unplanned_ue_rec.unit_effectivity_id || 'is:' ||
11185              l_grp_match_flag);
11186       END IF;
11187 
11188       -- If exception, then update the UE status to exception.
11189       -- If no longer an exception, then update the UE status to NULL.
11190       IF ((ahl_unplanned_ue_rec.status_code IS NULL) AND (l_exception_flag = TRUE)) OR
11191          ((ahl_unplanned_ue_rec.status_code = 'EXCEPTION') AND (l_exception_flag = FALSE)) THEN
11192 
11193          OPEN ahl_unit_effectivity_csr(ahl_unplanned_ue_rec.unit_effectivity_id);
11194          FETCH ahl_unit_effectivity_csr INTO l_ue_rec;
11195          IF (ahl_unit_effectivity_csr%NOTFOUND) THEN
11196            FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_UE_NOTFOUND');
11197            FND_MESSAGE.Set_Token('UE_ID',l_ue_rec.unit_effectivity_id);
11198            FND_MSG_PUB.ADD;
11199            -- dbms_output.put_line('unit effectivity not found for ue id' ||l_ue_rec.unit_effectivity_id );
11200            ClOSE ahl_unit_effectivity_csr;
11201            RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
11202          ELSE
11203            -- set UE attributes.
11204            IF (ahl_unplanned_ue_rec.status_code IS NULL) AND (l_exception_flag = TRUE) THEN
11205               IF G_DEBUG = 'Y' THEN
11206                 AHL_DEBUG_PUB.Debug('Updating Unplanned UE..' || l_ue_rec.unit_effectivity_id || ' to an exception');
11207               END IF;
11208               -- update unit effectivity.
11209               l_message_code := 'VISIT-ASSIGN';
11210               l_status_code := 'EXCEPTION';
11211            ELSE
11212               IF G_DEBUG = 'Y' THEN
11213                 AHL_DEBUG_PUB.Debug('Updating Unplanned UE..' || l_ue_rec.unit_effectivity_id || ' from an exception');
11214               END IF;
11215                -- update unit effectivity.
11216               l_message_code := NULL;
11217               l_status_code := NULL;
11218            END IF;
11219            ClOSE ahl_unit_effectivity_csr;
11220 
11221            -- Update unit effectivity.
11222            AHL_UNIT_EFFECTIVITIES_PKG.Update_Row(
11223                   X_UNIT_EFFECTIVITY_ID   => l_ue_rec.unit_effectivity_id,
11224                   X_CSI_ITEM_INSTANCE_ID  => l_ue_rec.csi_item_instance_id,
11225                   X_MR_INTERVAL_ID        => l_ue_rec.mr_interval_id,
11226                   X_MR_EFFECTIVITY_ID     => l_ue_rec.mr_effectivity_id,
11227                   X_MR_HEADER_ID          => l_ue_rec.mr_header_id,
11228                   X_STATUS_CODE           => l_status_code,
11229                   X_DUE_DATE              => l_ue_rec.due_date,
11230                   X_DUE_COUNTER_VALUE     => l_ue_rec.due_counter_value,
11231                   X_FORECAST_SEQUENCE     => l_ue_rec.forecast_sequence,
11232                   X_REPETITIVE_MR_FLAG    => l_ue_rec.repetitive_mr_flag,
11233                   X_TOLERANCE_FLAG        => l_ue_rec.tolerance_flag,
11234                   X_REMARKS               => l_ue_rec.remarks,
11235                   X_MESSAGE_CODE          => l_message_code,
11236                   X_PRECEDING_UE_ID       => l_ue_rec.preceding_ue_id,
11237                   X_DATE_RUN              => sysdate,
11238                   X_SET_DUE_DATE          => l_ue_rec.set_due_date,
11239                   X_ACCOMPLISHED_DATE     => l_ue_rec.accomplished_date,
11240                   X_SERVICE_LINE_ID       => l_ue_rec.service_line_id,
11241                   X_PROGRAM_MR_HEADER_ID  => l_ue_rec.program_mr_header_id,
11242                   X_CANCEL_REASON_CODE    => l_ue_rec.cancel_reason_code,
11243                   X_EARLIEST_DUE_DATE     => l_ue_rec.earliest_due_date,
11244                   X_LATEST_DUE_DATE       => l_ue_rec.latest_due_date,
11245                   X_defer_from_ue_id      => l_ue_rec.defer_from_ue_id,
11246                   X_cs_incident_id        => l_ue_rec.cs_incident_id,
11247                   X_qa_collection_id      => l_ue_rec.qa_collection_id,
11248                   X_orig_deferral_ue_id   => l_ue_rec.orig_deferral_ue_id,
11249                   X_application_usg_code  => l_ue_rec.application_usg_code,
11250                   X_object_type           => l_ue_rec.object_type,
11251                   X_counter_id          => l_ue_rec.counter_id,
11252                   X_MANUALLY_PLANNED_FLAG => l_ue_rec.MANUALLY_PLANNED_FLAG,
11253                   X_LOG_SERIES_CODE       => l_ue_rec.log_series_code,
11254                   X_LOG_SERIES_NUMBER     => l_ue_rec.log_series_number,
11255                   X_FLIGHT_NUMBER         => l_ue_rec.flight_number,
11256                   X_MEL_CDL_TYPE_CODE     => l_ue_rec.mel_cdl_type_code,
11257                   X_POSITION_PATH_ID      => l_ue_rec.position_path_id,
11258                   X_ATA_CODE              => l_ue_rec.ATA_CODE,
11259                   X_UNIT_CONFIG_HEADER_ID  => l_ue_rec.unit_config_header_id,
11260                   X_ATTRIBUTE_CATEGORY    => l_ue_rec.attribute_category,
11261                   X_ATTRIBUTE1            => l_ue_rec.attribute1,
11262                   X_ATTRIBUTE2            => l_ue_rec.attribute2,
11263                   X_ATTRIBUTE3            => l_ue_rec.attribute3,
11264                   X_ATTRIBUTE4            => l_ue_rec.attribute4,
11265                   X_ATTRIBUTE5            => l_ue_rec.attribute5,
11266                   X_ATTRIBUTE6            => l_ue_rec.attribute6,
11267                   X_ATTRIBUTE7            => l_ue_rec.attribute7,
11268                   X_ATTRIBUTE8            => l_ue_rec.attribute8,
11269                   X_ATTRIBUTE9            => l_ue_rec.attribute9,
11270                   X_ATTRIBUTE10           => l_ue_rec.attribute10,
11271                   X_ATTRIBUTE11           => l_ue_rec.attribute11,
11272                   X_ATTRIBUTE12           => l_ue_rec.attribute12,
11273                   X_ATTRIBUTE13           => l_ue_rec.attribute13,
11274                   X_ATTRIBUTE14           => l_ue_rec.attribute14,
11275                   X_ATTRIBUTE15           => l_ue_rec.attribute15,
11276                   X_OBJECT_VERSION_NUMBER => l_ue_rec.object_version_number + 1,
11277                   X_LAST_UPDATE_DATE => sysdate,
11278                   X_LAST_UPDATED_BY => fnd_global.user_id,
11279                   X_LAST_UPDATE_LOGIN  => fnd_global.login_id);
11280 
11281            -- Now update all the child MRs status too.
11282            FOR ue_reln_rec IN decendent_csr(ahl_unplanned_ue_rec.unit_effectivity_id) LOOP
11283 
11284              OPEN ahl_unit_effectivity_csr (ue_reln_rec.related_ue_id);
11285              FETCH ahl_unit_effectivity_csr INTO l_ue_rec;
11286              IF (ahl_unit_effectivity_csr%FOUND) THEN
11287                AHL_UNIT_EFFECTIVITIES_PKG.Update_Row(
11288                   X_UNIT_EFFECTIVITY_ID   => l_ue_rec.unit_effectivity_id,
11289                   X_CSI_ITEM_INSTANCE_ID  => l_ue_rec.csi_item_instance_id,
11290                   X_MR_INTERVAL_ID        => l_ue_rec.mr_interval_id,
11291                   X_MR_EFFECTIVITY_ID     => l_ue_rec.mr_effectivity_id,
11292                   X_MR_HEADER_ID          => l_ue_rec.mr_header_id,
11293                   X_STATUS_CODE           => l_status_code,
11294                   X_DUE_DATE              => l_ue_rec.due_date,
11295                   X_DUE_COUNTER_VALUE     => l_ue_rec.due_counter_value,
11296                   X_FORECAST_SEQUENCE     => l_ue_rec.forecast_sequence,
11297                   X_REPETITIVE_MR_FLAG    => l_ue_rec.repetitive_mr_flag,
11298                   X_TOLERANCE_FLAG        => l_ue_rec.tolerance_flag,
11299                   X_REMARKS               => l_ue_rec.remarks,
11300                   X_MESSAGE_CODE          => l_message_code,
11301                   X_PRECEDING_UE_ID       => l_ue_rec.preceding_ue_id,
11302                   X_DATE_RUN              => sysdate,
11303                   X_SET_DUE_DATE          => l_ue_rec.set_due_date,
11304                   X_ACCOMPLISHED_DATE     => l_ue_rec.accomplished_date,
11305                   X_SERVICE_LINE_ID       => l_ue_rec.service_line_id,
11306                   X_PROGRAM_MR_HEADER_ID  => l_ue_rec.program_mr_header_id,
11307                   X_CANCEL_REASON_CODE    => l_ue_rec.cancel_reason_code,
11308                   X_EARLIEST_DUE_DATE     => l_ue_rec.earliest_due_date,
11309                   X_LATEST_DUE_DATE       => l_ue_rec.latest_due_date,
11310                   X_defer_from_ue_id      => l_ue_rec.defer_from_ue_id,
11311                   X_cs_incident_id        => l_ue_rec.cs_incident_id,
11312                   X_qa_collection_id      => l_ue_rec.qa_collection_id,
11313                   X_orig_deferral_ue_id   => l_ue_rec.orig_deferral_ue_id,
11314                   X_application_usg_code  => l_ue_rec.application_usg_code,
11315                   X_object_type           => l_ue_rec.object_type,
11316                   X_counter_id          => l_ue_rec.counter_id,
11317                   X_MANUALLY_PLANNED_FLAG => l_ue_rec.MANUALLY_PLANNED_FLAG,
11318                   X_LOG_SERIES_CODE       => l_ue_rec.log_series_code,
11319                   X_LOG_SERIES_NUMBER     => l_ue_rec.log_series_number,
11320                   X_FLIGHT_NUMBER         => l_ue_rec.flight_number,
11321                   X_MEL_CDL_TYPE_CODE     => l_ue_rec.mel_cdl_type_code,
11322                   X_POSITION_PATH_ID      => l_ue_rec.position_path_id,
11323                   X_ATA_CODE              => l_ue_rec.ATA_CODE,
11324                   X_UNIT_CONFIG_HEADER_ID  => l_ue_rec.unit_config_header_id,
11325                   X_ATTRIBUTE_CATEGORY    => l_ue_rec.attribute_category,
11326                   X_ATTRIBUTE1            => l_ue_rec.attribute1,
11327                   X_ATTRIBUTE2            => l_ue_rec.attribute2,
11328                   X_ATTRIBUTE3            => l_ue_rec.attribute3,
11329                   X_ATTRIBUTE4            => l_ue_rec.attribute4,
11330                   X_ATTRIBUTE5            => l_ue_rec.attribute5,
11331                   X_ATTRIBUTE6            => l_ue_rec.attribute6,
11332                   X_ATTRIBUTE7            => l_ue_rec.attribute7,
11333                   X_ATTRIBUTE8            => l_ue_rec.attribute8,
11334                   X_ATTRIBUTE9            => l_ue_rec.attribute9,
11335                   X_ATTRIBUTE10           => l_ue_rec.attribute10,
11336                   X_ATTRIBUTE11           => l_ue_rec.attribute11,
11337                   X_ATTRIBUTE12           => l_ue_rec.attribute12,
11338                   X_ATTRIBUTE13           => l_ue_rec.attribute13,
11339                   X_ATTRIBUTE14           => l_ue_rec.attribute14,
11340                   X_ATTRIBUTE15           => l_ue_rec.attribute15,
11341                   X_OBJECT_VERSION_NUMBER => l_ue_rec.object_version_number + 1,
11342                   X_LAST_UPDATE_DATE => sysdate,
11343                   X_LAST_UPDATED_BY => fnd_global.user_id,
11344                   X_LAST_UPDATE_LOGIN  => fnd_global.login_id);
11345              ELSE
11346                FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_UE_NOTFOUND');
11347                FND_MESSAGE.Set_Token('UE_ID',l_ue_rec.unit_effectivity_id);
11348                FND_MSG_PUB.ADD;
11349                -- dbms_output.put_line('descendent mr not found for ue id');
11350                ClOSE ahl_unit_effectivity_csr;
11351                RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
11352              END IF;
11353              ClOSE ahl_unit_effectivity_csr;
11354            END LOOP; -- decendent_csr
11355 
11356           END IF; -- ahl_unit_effectivity_csr%NOTFOUND chk.
11357       END IF;  -- unplanned status code check.
11358     END IF; -- l_visit_status
11359 
11360   END LOOP; -- next unplanned MR.
11361 
11362   -- Added for SB Enh to process unplanned chain MRs.
11363   FOR l_chain_appl_mr_rec IN chain_appl_mr_csr(p_csi_item_instance_id) LOOP
11364          l_applicable_mr_rec.csi_item_instance_id := p_csi_item_instance_id;
11365          l_applicable_mr_rec.MR_header_id := l_chain_appl_mr_rec.MR_header_id;
11366          l_applicable_mr_rec.title := l_chain_appl_mr_rec.title;
11367          l_applicable_mr_rec.version_number := l_chain_appl_mr_rec.version_number;
11368          l_applicable_mr_rec.Implement_status_code := l_chain_appl_mr_rec.Implement_status_code;
11369          l_applicable_mr_rec.copy_accomplishment_code := l_chain_appl_mr_rec.copy_accomplishment_code;
11370          l_applicable_mr_rec.repetitive_flag := l_chain_appl_mr_rec.repetitive_flag;
11371          l_applicable_mr_rec.show_repetitive_code := l_chain_appl_mr_rec.show_repetitive_code;
11372          --l_applicable_mr_rec.preceding_mr_header_id := l_chain_appl_mr_rec.preceding_mr_header_id;
11373          l_applicable_mr_rec.descendent_count := l_chain_appl_mr_rec.descendent_count;
11374          l_applicable_mr_rec.whichever_first_code := l_chain_appl_mr_rec.whichever_first_code;
11375          l_applicable_mr_rec.effective_to := l_chain_appl_mr_rec.effective_to;
11376          l_applicable_mr_rec.effective_from := l_chain_appl_mr_rec.effective_from;
11377 
11378          -- added for bug# 9263774
11379          IF (l_applicable_mr_rec.effective_to < sysdate) THEN
11380             l_applicable_mr_rec.expired_mr_flag := 'Y';
11381          ELSE
11382             l_applicable_mr_rec.expired_mr_flag := 'N';
11383          END IF;
11384 
11385          -- Added for SB Effectivity Enh
11386          l_applicable_mr_rec.terminate_trigger_check := l_chain_appl_mr_rec.terminate_trigger_check;
11387          l_applicable_mr_rec.accomplish_trigger_type := l_chain_appl_mr_rec.accomplish_trigger_type;
11388          l_applicable_mr_rec.loop_chain_seq_num      := l_chain_appl_mr_rec.loop_chain_seq_num;
11389 
11390          Process_Chain_Init(p_applicable_mrs_rec => l_applicable_mr_rec,
11391                             p_current_usage_tbl  => p_current_usage_tbl,
11392                             p_counter_rules_tbl  => p_counter_rules_tbl,
11393                             x_loop_chain_MR_tbl  => l_lc_mr_tbl);
11394   END LOOP;
11395 
11396   IF (G_DEBUG = 'Y') THEN
11397     AHL_DEBUG_PUB.debug('End of Process_Unplanned_UE');
11398   END IF;
11399 
11400 END Process_Unplanned_UE;
11401 
11402 
11403 -----------------------------------------------
11404 
11405 -- Procedure to calculate counter values at a given forecasted date for Reliability Fwk use.
11406 PROCEDURE Get_Forecasted_Counter_Values(
11407               x_return_status          OUT NOCOPY VARCHAR2,
11408               x_msg_data               OUT NOCOPY VARCHAR2,
11409               x_msg_count              OUT NOCOPY NUMBER,
11410               p_init_msg_list          IN         VARCHAR2 := FND_API.G_FALSE,
11411               p_csi_item_instance_id   IN         NUMBER,   -- Instance Id
11412               p_forecasted_date        IN         DATE,
11413               x_counter_values_tbl    OUT NOCOPY counter_values_tbl_type) -- Forecasted Counter Vals.
11414 IS
11415 
11416   l_csi_item_instance_id        NUMBER;
11417   l_uc_header_id                NUMBER;
11418   l_inventory_item_id           NUMBER;
11419   l_inv_master_organization_id  NUMBER;
11420   i                             NUMBER;
11421 
11422   l_current_usage_tbl    counter_values_tbl_type;
11423   /* contains current counter usage */
11424 
11425   l_counter_rules_tbl    counter_rules_tbl_type;
11426   /* contains current counter rules for the position */
11427 
11428   l_due_at_counter_val_tbl  counter_values_tbl_type;
11429   /* local variable to hold due at p_forecasted_date ctr values. */
11430 
11431   l_return_value                BOOLEAN;
11432   l_expired_flag                VARCHAR2(1);
11433 
11434 BEGIN
11435 
11436   IF G_DEBUG = 'Y' THEN
11437         AHL_DEBUG_PUB.Debug('Start API Get_Forecasted_Counter_Values');
11438   END IF;
11439 
11440   -- Initialize message list if p_init_msg_list is set to TRUE
11441   IF FND_API.To_Boolean(p_init_msg_list) THEN
11442     FND_MSG_PUB.Initialize;
11443   END IF;
11444 
11445   -- Initialize Procedure return status to success
11446   x_return_status := FND_API.G_RET_STS_SUCCESS;
11447 
11448   -- Enable Debug.
11449   IF G_DEBUG = 'Y' THEN
11450     AHL_DEBUG_PUB.enable_debug;
11451   END IF;
11452 
11453   -- Add debug mesg.
11454   IF G_DEBUG = 'Y' THEN
11455     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Get_Forcasted_Counter_Values');
11456 
11457     -- Dump input parameters.
11458     AHL_DEBUG_PUB.debug(' Csi Item instance ID:' || p_csi_item_instance_id);
11459     AHL_DEBUG_PUB.debug(' Forecasted Date:' || p_forecasted_date);
11460 
11461   END IF;
11462 
11463   -- validate item instance.
11464   Validate_item_instance(p_csi_item_instance_id, l_inventory_item_id,
11465                          l_inv_master_organization_id, l_expired_flag);
11466 
11467 
11468   IF (l_expired_flag = 'Y') THEN
11469     FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_INST_EXPIRED');
11470     FND_MESSAGE.Set_Token('NUMBER', p_csi_item_instance_id);
11471     FND_MSG_PUB.ADD;
11472     --dbms_output.put_line('Instance has expired');
11473   END IF;
11474 
11475   IF FND_MSG_PUB.Count_msg > 0 THEN
11476      RAISE FND_API.G_EXC_ERROR;
11477   END IF;
11478 
11479   -- set instance variable.
11480   l_csi_item_instance_id := p_csi_item_instance_id;
11481 
11482 
11483   -- Set configuration variables based on installation type.
11484   -- If item instance is not top node, find the root item instance.
11485   l_csi_item_instance_id := Get_RootInstanceID(l_csi_item_instance_id);
11486 
11487   -- Get master and unit configuration IDs if they exist for this item instance.
11488   Get_Unit_Master_ConfigIDs (l_csi_item_instance_id,
11489                              l_uc_header_id, G_master_config_id);
11490 
11491   -- Check for errors.
11492   IF FND_MSG_PUB.Count_msg > 0 THEN
11493      RAISE FND_API.G_EXC_ERROR;
11494   END IF;
11495 
11496   -- Build the Configuration tree structure.(G_config_node_tbl).
11497   Build_Config_Tree(l_csi_item_instance_id, G_master_config_id, G_CONFIG_NODE_TBL);
11498 
11499   -- Add debug mesg.
11500   IF G_DEBUG = 'Y' THEN
11501     AHL_DEBUG_PUB.debug(' Count on Config Node Tbl:' || G_config_node_tbl.COUNT);
11502     AHL_DEBUG_PUB.debug(' Root Node:' || l_csi_item_instance_id );
11503     AHL_DEBUG_PUB.debug(' Unit Config ID:' || l_uc_header_id);
11504     AHL_DEBUG_PUB.debug(' Master Config ID:' || G_master_config_id);
11505   END IF;
11506 
11507   -- Read applicable utilization forecast for the configuration.
11508   Get_Utilization_Forecast (l_csi_item_instance_id,
11509                             l_uc_header_id,
11510                             l_inventory_item_id,
11511                             l_inv_master_organization_id,
11512                             G_forecast_details_tbl);
11513 
11514   -- Build counter rules ratio if node is not root node.
11515   IF (G_master_config_id IS NOT NULL AND p_csi_item_instance_id <> l_csi_item_instance_id) THEN
11516     IF (G_config_node_tbl.count > 0) THEN
11517        FOR j IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
11518          IF (G_config_node_tbl(j).csi_item_instance_id = p_csi_item_instance_id) THEN
11519             i := j;
11520          END IF;
11521        END LOOP;
11522     END IF; -- G_config_node_tbl.count.
11523     build_Counter_Ratio(G_config_node_tbl(i).position_reference,
11524                         G_config_node_tbl(i).csi_item_instance_id,
11525                         G_master_config_id,
11526                         l_counter_rules_tbl);
11527   END IF; -- G_master_config_id IS NOT NULL.
11528 
11529   -- Get current usage for all the counters defined for the item instance.
11530   get_Current_Usage (p_csi_item_instance_id,
11531                      l_current_usage_tbl);
11532 
11533 
11534   -- get all counter values as on p_forecasted_date.
11535   Get_Due_at_Counter_Values (p_last_due_date => sysdate,
11536                              p_last_due_counter_val_tbl => l_current_usage_tbl,
11537                              p_due_date => p_forecasted_date,
11538                              p_counter_rules_tbl => l_counter_rules_tbl,
11539                              x_due_at_counter_val_tbl => l_due_at_counter_val_tbl,
11540                              x_return_value => l_return_value);
11541 
11542   IF G_DEBUG = 'Y' THEN
11543      AHL_DEBUG_PUB.Debug('AFter get_due_at_counter_values');
11544      AHL_DEBUG_PUB.Debug('l_last_due_date: '|| sysdate);
11545      AHL_DEBUG_PUB.Debug('l_due_date: '|| p_forecasted_date);
11546      IF (l_due_at_counter_val_tbl.COUNT) > 0 THEN
11547           for i in l_due_at_counter_val_tbl.FIRST..l_due_at_counter_val_tbl.LAST LOOP
11548             AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_due_at_counter_val_tbl(i).counter_value || 'ID: ' || l_due_at_counter_val_tbl(i).counter_id);
11549           end loop;
11550      END IF; -- count.
11551   END IF; -- Debug = Y
11552 
11553   IF NOT(l_return_value) THEN
11554      RAISE FND_API.G_EXC_ERROR;  /* no forecast available */
11555   ELSE
11556      x_counter_values_tbl := l_due_at_counter_val_tbl;
11557   END IF;
11558 
11559   -- Standard call to get message count and if count is 1, get message info
11560   FND_MSG_PUB.Count_And_Get
11561     ( p_count => x_msg_count,
11562       p_data  => x_msg_data,
11563       p_encoded => fnd_api.g_false
11564     );
11565 
11566   IF G_DEBUG = 'Y' THEN
11567         AHL_DEBUG_PUB.Debug('End API Get_Forecasted_Counter_Values');
11568   END IF;
11569 
11570 --
11571 EXCEPTION
11572  WHEN FND_API.G_EXC_ERROR THEN
11573    x_return_status := FND_API.G_RET_STS_ERROR;
11574    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
11575                               p_data  => x_msg_data,
11576                               p_encoded => fnd_api.g_false);
11577 
11578    -- Disable debug
11579    AHL_DEBUG_PUB.disable_debug;
11580 
11581  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
11582    x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
11583    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
11584                               p_data  => x_msg_data,
11585                               p_encoded => fnd_api.g_false);
11586 
11587    -- Disable debug
11588    AHL_DEBUG_PUB.disable_debug;
11589 
11590  WHEN OTHERS THEN
11591     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
11592     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
11593        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
11594                                p_procedure_name => 'Get_Forecasted_Counter_Values',
11595                                p_error_text     => SUBSTR(SQLERRM,1,240));
11596     END IF;
11597     FND_MSG_PUB.count_and_get( p_count => x_msg_count,
11598                                p_data  => x_msg_data,
11599                                p_encoded => fnd_api.g_false);
11600 
11601     -- Disable debug
11602     AHL_DEBUG_PUB.disable_debug;
11603 
11604 END Get_Forecasted_Counter_Values;
11605 ----------------------------------------------
11606 -- Added in R12 to fix bug# 4224867.
11607 -- find usage forecast for a given date.
11608 PROCEDURE get_usage_for_date(p_due_date          IN DATE,
11609                              p_counter_uom_code  IN VARCHAR2,
11610                              p_counter_rules_tbl IN Counter_rules_tbl_type,
11611                              x_usage_per_day     OUT NOCOPY NUMBER)
11612 IS
11613   l_next_index  NUMBER;
11614 
11615 BEGIN
11616 
11617   x_usage_per_day := 0;
11618 
11619   -- Read g_forecast_details_tbl to get forecast values.
11620   l_next_index := G_forecast_details_tbl.FIRST;
11621 
11622   IF (l_next_index IS NOT NULL) THEN
11623     FOR i IN G_forecast_details_tbl.FIRST..G_forecast_details_tbl.LAST LOOP
11624       IF (G_forecast_details_tbl(i).uom_code = p_counter_uom_code) AND
11625          (trunc(G_forecast_details_tbl(i).start_date) <= trunc(p_due_date) AND
11626           trunc(p_due_date) <= trunc(nvl(G_forecast_details_tbl(i).end_date,p_due_date)))
11627       THEN
11628          x_usage_per_day := G_forecast_details_tbl(i).usage_per_day;
11629          EXIT;
11630       END IF;
11631     END LOOP;
11632   END IF;
11633 
11634   --dbms_output.put_line ('counter remain input to forecast' || l_counter_remain );
11635   --dbms_output.put_line ('counter uom' ||p_counter_uom_code);
11636 
11637   x_usage_per_day := Apply_ReverseCounter_Ratio ( x_usage_per_day,
11638                                                   p_counter_uom_code,
11639                                                   p_counter_rules_tbl);
11640 
11641 
11642 END get_usage_for_date;
11643 ----------------------------------------------
11644 -- Added to fix bug# 6875650.
11645 -- Get the latest recorded counter reading for a given datetime.
11646 PROCEDURE get_ctr_reading_for_datetime (p_csi_item_instance_id IN NUMBER,
11647                                         p_counter_id           IN NUMBER,
11648                                         p_reading_date         IN DATE,
11649                                         x_net_reading        OUT NOCOPY NUMBER) IS
11650 
11651   -- get the latest reading recorded for a counter on any given date.
11652   CURSOR cs_ctr_reading_csr(p_csi_item_instance_id IN NUMBER,
11653                             p_counter_id           IN NUMBER,
11654                             p_reading_date IN DATE) IS
11655         SELECT * FROM (
11656 	               SELECT CCR.NET_READING
11657 	               FROM
11658 		            CSI_COUNTER_READINGS CCR
11659 	               WHERE
11660 		            CCR.COUNTER_ID          = P_COUNTER_ID
11661                          AND nvl(disabled_flag,'N') = 'N'
11662 		         AND CCR.VALUE_TIMESTAMP   <= P_READING_DATE
11663       	               ORDER BY CCR.VALUE_TIMESTAMP DESC
11664                       )
11665         WHERE ROWNUM < 2;
11666 
11667   l_net_reading  NUMBER;
11668 
11669 BEGIN
11670 
11671     IF G_DEBUG = 'Y' THEN
11672       AHL_DEBUG_PUB.debug('Start of get_ctr_reading_for_datetime');
11673     END IF;
11674 
11675     OPEN cs_ctr_reading_csr(p_csi_item_instance_id,
11676                             p_counter_id,
11677                             p_reading_date);
11678     FETCH cs_ctr_reading_csr INTO l_net_reading;
11679     IF (cs_ctr_reading_csr%NOTFOUND) THEN
11680        l_net_reading := 0;
11681     END IF;
11682     CLOSE cs_ctr_reading_csr;
11683 
11684     x_net_reading := l_net_reading;
11685 
11686     IF G_DEBUG = 'Y' THEN
11687       AHL_DEBUG_PUB.debug('End of get_ctr_reading_for_datetime');
11688     END IF;
11689 
11690 END get_ctr_reading_for_datetime;
11691 
11692 ----------------------------------------------
11693 -- added to fix bug# 6907562.
11694 -- function that compares previous due date and uom remain with current values
11695 -- and return Y is the current due date replaces the prev one.
11696 FUNCTION validate_for_duedate_reset(p_due_date        IN DATE,
11697                                     p_uom_remain      IN NUMBER,
11698                                     p_prev_due_date   IN DATE,
11699                                     p_prev_counter_id IN NUMBER,
11700                                     p_prev_uom_remain IN NUMBER)
11701 RETURN VARCHAR2 IS
11702   l_return_status  VARCHAR2(1);
11703 
11704 BEGIN
11705   IF G_DEBUG = 'Y' THEN
11706     AHL_DEBUG_PUB.debug('Start of validate_for_duedate_reset');
11707   END IF;
11708 
11709   l_return_status := 'N';
11710   IF (p_due_date IS NULL) THEN
11711     -- check if p_prev_counter_id is null or not. If null then this is first due date calculation.
11712     IF (p_prev_counter_id IS NULL) THEN
11713       l_return_status := 'Y';
11714     ELSE
11715       -- check prior date; it could either be null or not null.
11716       IF (p_prev_due_date IS NULL) THEN
11717         -- trigger ctr based on uom remain.
11718         IF (p_uom_remain < p_prev_uom_remain) THEN
11719            l_return_status := 'Y';
11720         END IF;
11721       ELSE -- p_prev_due_date is not null.
11722         -- check UOM remaining.
11723         IF (p_prev_uom_remain <= 0 AND p_uom_remain > 0) OR
11724            (p_prev_uom_remain < p_uom_remain AND p_uom_remain < 0) THEN
11725             null; -- do nothing
11726         ELSE
11727            l_return_status := 'Y';
11728         END IF; -- p_prev_uom_remain < 0
11729       END IF; -- p_prev_due_date
11730     END IF; -- p_prev_counter_id
11731   ELSE -- p_due_date is not null.
11732     IF (p_prev_due_date IS NULL) THEN
11733       IF (p_prev_counter_id IS NULL) THEN
11734         -- this is first time due due calculation.
11735         l_return_status := 'Y';
11736       ELSE
11737         -- prior due date is a null due date.
11738         -- swap based on uom remain.
11739         IF (p_uom_remain < p_prev_uom_remain AND p_prev_uom_remain < 0) OR
11740            (p_uom_remain <= 0 AND p_prev_uom_remain > 0) THEN
11741            l_return_status := 'Y';
11742         END IF;
11743       END IF; -- p_prev_counter_id
11744     END IF; -- p_prev_due_date
11745   END IF; -- p_due_date
11746 
11747   IF G_DEBUG = 'Y' THEN
11748     AHL_DEBUG_PUB.debug('End of validate_for_duedate_reset');
11749   END IF;
11750 
11751   RETURN l_return_status;
11752 
11753 END validate_for_duedate_reset;
11754 
11755 -----------------------------------------------
11756 -- Added procedure to replace call to ahl_fmp_pvt.get_mr_affected_items for Prev. Maint
11757 -- Called when processing based on MR invoked through concurrent program.
11758 -- Perf fix for bug# 5093064.
11759 PROCEDURE Process_PM_MR_Affected_Items(
11760     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
11761     x_msg_count              OUT NOCOPY    NUMBER,
11762     x_msg_data               OUT NOCOPY    VARCHAR2,
11763     x_return_status          OUT NOCOPY    VARCHAR2,
11764     p_mr_header_id           IN            NUMBER,
11765     p_old_mr_header_id       IN            NUMBER    := NULL,
11766     p_concurrent_flag        IN            VARCHAR2  := 'N',
11767     p_num_of_workers         IN            NUMBER    := 10)
11768 
11769 IS
11770 
11771   l_msg_count             NUMBER;
11772   l_return_status         VARCHAR2(1);
11773   l_msg_data              VARCHAR2(30);
11774   i                       NUMBER;
11775   l_debug                 VARCHAR2(1) := AHL_DEBUG_PUB.is_log_enabled;
11776   l_master_org_id         NUMBER;
11777   l_mr_header_id          NUMBER;
11778 
11779   l_csi_min_id            NUMBER;
11780   l_csi_max_id            NUMBER;
11781   l_csi_eff_min_id        NUMBER;
11782   l_csi_eff_max_id        NUMBER;
11783   l_num_workers           NUMBER;
11784   l_end_csi_id            NUMBER;
11785   l_start_csi_id          NUMBER;
11786   l_step                  NUMBER;
11787   l_req_id                NUMBER;
11788   l_count                 NUMBER;
11789   l_total_count           NUMBER := 0;
11790 
11791   l_csi_inst_tbl         nbr_tbl_type;
11792 
11793   --check whether the given mr exists
11794   CURSOR check_mr_exists(c_mr_header_id number)
11795   IS
11796     SELECT mr_header_id
11797       FROM ahl_mr_headers_app_v
11798      WHERE mr_header_id = c_mr_header_id;
11799 
11800   --get all the MR effectivity definitions for a given MR
11801   CURSOR get_mr_effect(c_mr_header_id NUMBER)
11802   IS
11803    SELECT mr_header_id, mr_effectivity_id, inventory_item_id
11804    FROM ahl_mr_effectivities_app_v
11805    WHERE mr_header_id = c_mr_header_id;
11806 
11807   -- get master org id.
11808   CURSOR get_master_org_id_csr (c_inventory_item_id IN NUMBER)
11809   IS
11810     SELECT itm.organization_id
11811     FROM mtl_system_items_b itm, mtl_parameters mtl
11812     WHERE itm.inventory_item_id = c_inventory_item_id
11813       AND   itm.organization_id = mtl.organization_id
11814       AND   mtl.master_organization_id = mtl.organization_id;
11815 
11816   -- Get min/max instance ID for a given INV ID.
11817   CURSOR get_minmax_inst_csr(c_inventory_item_id IN NUMBER,
11818                              c_inventory_org_id  IN NUMBER)
11819   IS
11820     SELECT min(instance_id), max(instance_id), count(instance_id)
11821     FROM csi_item_instances
11822     WHERE inventory_item_id = c_inventory_item_id
11823     AND   inv_master_organization_id = c_inventory_org_id
11824     AND SYSDATE between trunc(nvl(active_start_date,sysdate)) and
11825         trunc(nvl(active_end_date,sysdate+1))
11826     GROUP BY inventory_item_id, inv_master_organization_id;
11827 
11828   -- get instances when mr_header_id is provided.
11829   CURSOR get_inst( p_mr_header_id      IN NUMBER,
11830                    c_start_inst_id     IN NUMBER,
11831                    c_end_inst_id       IN NUMBER)
11832   IS
11833   SELECT cii.instance_id
11834     FROM csi_item_instances cii, ahl_mr_effectivities mre, mtl_system_items_b msi
11835     WHERE cii.inventory_item_id = msi.inventory_item_id
11836     AND cii.inv_master_organization_id = msi.organization_id
11837     AND cii.inventory_item_id = mre.inventory_item_id
11838     AND mre.mr_header_id = p_mr_header_id
11839     AND SYSDATE between trunc(nvl(cii.active_start_date,sysdate)) and
11840         trunc(nvl(cii.active_end_date,sysdate+1))
11841     AND cii.instance_id >= c_start_inst_id
11842     AND cii.instance_id <= c_end_inst_id;
11843 
11844 BEGIN
11845 
11846   IF l_debug = 'Y' THEN
11847     AHL_DEBUG_PUB.enable_debug;
11848     AHL_DEBUG_PUB.debug('Begin private API: AHL_UMP_PROCESSUNIT_PVT.PROCESS_PM_MR_AFFECTED_ITEMS');
11849   END IF;
11850 
11851   -- Check whether the mr_header_id exists --
11852   OPEN check_mr_exists(p_mr_header_id);
11853   FETCH check_mr_exists INTO l_mr_header_id;
11854   IF check_mr_exists%NOTFOUND THEN
11855     CLOSE check_mr_exists;
11856     FND_MESSAGE.SET_NAME('AHL','AHL_FMP_INVALID_MR');
11857     FND_MSG_PUB.ADD;
11858     RAISE FND_API.G_EXC_ERROR;
11859   END IF;
11860   CLOSE check_mr_exists;
11861 
11862   IF l_debug = 'Y' THEN
11863     AHL_DEBUG_PUB.debug(' Phase 1');
11864   END IF;
11865 
11866   -- validate # of workers.
11867   l_num_workers := p_num_of_workers;
11868 
11869   IF (p_num_of_workers > 30) THEN
11870      l_num_workers := 30;
11871   END IF;
11872 
11873   IF l_debug = 'Y' THEN
11874     AHL_DEBUG_PUB.debug(' Phase 2:l_num_workers:' || l_num_workers);
11875   END IF;
11876 
11877   FOR l_mr_effect IN get_mr_effect(p_mr_header_id)
11878   LOOP
11879     IF (l_mr_effect.inventory_item_id IS NOT NULL) THEN
11880 
11881         IF l_debug = 'Y' THEN
11882            AHL_DEBUG_PUB.debug(' Phase 3:Inv Item ID:' || l_mr_effect.inventory_item_id);
11883         END IF;
11884 
11885         --DBMS_OUTPUT.put_line('API1: Come here in case 1B and l_index is: '||l_index);
11886 
11887         AHL_FMP_COMMON_PVT.validate_item(x_return_status => l_return_status,
11888                                          x_msg_data => l_msg_data,
11889                                          p_item_number => NULL,
11890                                          p_x_inventory_item_id => l_mr_effect.inventory_item_id);
11891         IF (l_return_status = 'S') THEN
11892 
11893            IF l_debug = 'Y' THEN
11894               AHL_DEBUG_PUB.debug('Phase 4: Inv Item ID is Valid');
11895            END IF;
11896            -- get master organization id.
11897            OPEN get_master_org_id_csr(l_mr_effect.inventory_item_id);
11898            FETCH get_master_org_id_csr INTO l_master_org_id;
11899            IF (get_master_org_id_csr%NOTFOUND) THEN
11900               FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_MASORG_NOTFOUND');
11901               FND_MESSAGE.Set_Token('INV_ID',l_mr_effect.inventory_item_id);
11902               FND_MSG_PUB.ADD;
11903               --DBMS_OUTPUT.put_line('Master org not found for inventory item:' || l_mr_effect.inventory_item_id);
11904               ClOSE get_master_org_id_csr;
11905               RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
11906            END IF;
11907            CLOSE get_master_org_id_csr;
11908 
11909            OPEN get_minmax_inst_csr(l_mr_effect.inventory_item_id,l_master_org_id);
11910            FETCH get_minmax_inst_csr INTO l_csi_eff_min_id, l_csi_eff_max_id, l_count;
11911            IF (get_minmax_inst_csr%FOUND) THEN
11912               IF ((l_csi_min_id IS NULL) OR (l_csi_eff_min_id < l_csi_min_id)) THEN
11913                   l_csi_min_id := l_csi_eff_min_id;
11914               END IF;
11915 
11916               IF ((l_csi_max_id IS NULL) OR (l_csi_max_id < l_csi_eff_max_id)) THEN
11917                  l_csi_max_id := l_csi_eff_max_id;
11918               END IF;
11919               l_total_count := l_count + l_total_count;
11920 
11921            END IF;
11922            CLOSE get_minmax_inst_csr;
11923 
11924            IF l_debug = 'Y' THEN
11925               AHL_DEBUG_PUB.debug(' Phase 5:csi_min:csi_max:count:' || l_csi_min_id || ':' || l_csi_max_id || ':' ||
11926                                     l_total_count);
11927            END IF;
11928 
11929         END IF; -- l_return_status = 'S'
11930       END IF; -- l_mr_effect.inventory_item_id IS NOT NULL
11931     END LOOP; -- l_mr_effect
11932 
11933     IF (p_concurrent_flag = 'Y') THEN
11934        -- launch workers after assigning instance range.
11935        IF (l_num_workers < 15) THEN
11936           Instance_Split_BTree(p_csi_max_id  => l_csi_max_id,
11937                                p_csi_min_id  => l_csi_min_id,
11938                                p_num_workers => p_num_of_workers,
11939                                p_mr_header_id => p_mr_header_id,
11940                                p_total_inst_count  => l_total_count);
11941        ELSE
11942           Instance_Split_Sequential(p_csi_max_id  => l_csi_max_id,
11943                                     p_csi_min_id  => l_csi_min_id,
11944                                     p_num_workers => p_num_of_workers,
11945                                     p_mr_header_id => p_mr_header_id);
11946 
11947        END IF;
11948     ELSE
11949        -- process all instances.
11950        OPEN get_inst(p_mr_header_id, l_csi_min_id, l_csi_max_id);
11951        LOOP
11952 
11953          FETCH get_inst BULK COLLECT INTO l_csi_inst_tbl LIMIT 1000;
11954          IF (l_csi_inst_tbl.count > 0) THEN
11955            -- call process unit for all instances.
11956 
11957            FOR i IN l_csi_inst_tbl.FIRST..l_csi_inst_tbl.LAST  LOOP
11958              -- Call Process Unit for the item instance.
11959              Process_Unit (
11960                          p_commit               => FND_API.G_TRUE,
11961                          p_init_msg_list        => FND_API.G_TRUE,
11962                          x_msg_count            => x_msg_count,
11963                          x_msg_data             => x_msg_data,
11964                          x_return_status        => x_return_status,
11965                          p_csi_item_instance_id => l_csi_inst_tbl(i),
11966                          p_concurrent_flag      => 'N');
11967 
11968              IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
11969                EXIT;
11970              END IF;
11971 
11972            END LOOP; -- l_csi_inst_tbl.FIRST
11973          END IF; -- l_csi_inst_tbl.count
11974          IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
11975            EXIT;
11976          END IF;
11977 
11978          EXIT WHEN get_inst%NOTFOUND;
11979        END LOOP; -- get_inst.
11980        CLOSE get_inst;
11981     END IF; -- p_concurrent_flag
11982 
11983 END Process_PM_MR_Affected_Items;
11984 
11985 ----------------------------------------------
11986 -- Split instance range into blocks based on instance IDs.
11987 PROCEDURE Instance_Split_Sequential(p_csi_max_id  in NUMBER,
11988                                     p_csi_min_id  IN NUMBER,
11989                                     p_num_workers IN NUMBER,
11990                                     p_mr_header_id IN NUMBER)
11991 IS
11992 
11993   l_debug                 VARCHAR2(1) := AHL_DEBUG_PUB.is_log_enabled;
11994 
11995   l_csi_min_id            NUMBER;
11996   l_csi_max_id            NUMBER;
11997   l_csi_eff_min_id        NUMBER;
11998   l_csi_eff_max_id        NUMBER;
11999   l_num_workers           NUMBER;
12000   l_end_csi_id            NUMBER;
12001   l_start_csi_id          NUMBER;
12002   l_step                  NUMBER;
12003   l_req_id                NUMBER;
12004 
12005 BEGIN
12006 
12007     l_num_workers := p_num_workers;
12008     l_csi_min_id := p_csi_min_id;
12009     l_csi_max_id := p_csi_max_id;
12010 
12011     -- split the instances based on # of workers and launch seperate concurrent
12012     -- programs to process a group of instances.
12013     IF (l_csi_max_id IS NOT NULL) AND (l_csi_min_id IS NOT NULL) THEN
12014        l_step := round((l_csi_max_id - l_csi_min_id) / l_num_workers);
12015 
12016        IF (l_step < 1) THEN
12017           l_step := l_csi_max_id - l_csi_min_id;
12018           l_num_workers := 1;
12019        END IF;
12020 
12021        l_start_csi_id := l_csi_min_id;
12022 
12023        IF l_debug = 'Y' THEN
12024           AHL_DEBUG_PUB.debug('l_step:' || l_step  || 'start csi: end csi' || l_start_csi_id || ':' || l_end_csi_id);
12025        END IF;
12026 
12027        -- loop through
12028        WHILE (l_start_csi_id < l_csi_max_id) LOOP
12029          l_end_csi_id := l_start_csi_id + l_step;
12030          IF (l_end_csi_id > l_csi_max_id) THEN
12031             l_end_csi_id := l_csi_max_id;
12032          END IF;
12033 
12034          IF l_debug = 'Y' THEN
12035           AHL_DEBUG_PUB.debug('Loop start csi: end csi' || l_start_csi_id || ':' || l_end_csi_id);
12036          END IF;
12037 
12038          -- launch BUE worker request.
12039          l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, p_mr_header_id, l_start_csi_id, l_end_csi_id);
12040 
12041          IF (l_req_id = 0 OR l_req_id IS NULL) THEN
12042             IF l_debug = 'Y' THEN
12043               AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
12044             END IF;
12045             fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
12046             fnd_file.new_line(FND_FILE.LOG,1);
12047             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
12048 
12049          ELSE
12050               fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id || ' launched to process instances between:' || l_start_csi_id || ' and ' || l_end_csi_id);
12051 
12052             IF l_debug = 'Y' THEN
12053               AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id || ' launched to process instances between:' || l_start_csi_id || ' and ' || l_end_csi_id);
12054             END IF;
12055          END IF;
12056 
12057          l_start_csi_id := l_end_csi_id + 1;
12058 
12059        END LOOP;
12060     END IF;
12061 
12062 END Instance_Split_Sequential;
12063 
12064 ----------------------------------------------
12065 -- Split instances based on instance count.
12066 PROCEDURE Instance_Split_BTree(p_csi_max_id  in NUMBER,
12067                                p_csi_min_id  IN NUMBER,
12068                                p_num_workers IN NUMBER,
12069                                p_mr_header_id IN NUMBER,
12070                                p_total_inst_count  IN NUMBER)
12071 IS
12072 
12073   l_debug                 VARCHAR2(1) := AHL_DEBUG_PUB.is_log_enabled;
12074   l_step number;
12075   l_start_csi_id number;
12076   l_launched_workers number;
12077   l_mid_point_inst_id number;
12078   l_count number;
12079   l_req_id number;
12080   l_end_csi_id number;
12081   l_begin_count_csi_id number;
12082 
12083   l_tol_after number;
12084   l_tol_bef   number;
12085 
12086   l_num_workers number;
12087 
12088   cursor csi_inst_count_csr (p_start_inst_id in number,
12089                              p_end_inst_id   in number,
12090                              p_mr_header_id  in number) IS
12091     SELECT count(instance_id)
12092     FROM csi_item_instances csi, ahl_mr_effectivities me
12093     WHERE csi.instance_id >= p_start_inst_id and csi.instance_id <= p_end_inst_id
12094     AND csi.inventory_item_id = me.inventory_item_id
12095     AND me.mr_header_id = p_mr_header_id
12096     AND SYSDATE between trunc(nvl(active_start_date,sysdate)) and
12097         trunc(nvl(active_end_date,sysdate+1));
12098 
12099 BEGIN
12100     IF l_debug = 'Y' THEN
12101        AHL_DEBUG_PUB.debug('Start of procedure: Instance_Split_BTree');
12102        AHL_DEBUG_PUB.debug('p_mr_header_id:' || p_mr_header_id);
12103        AHL_DEBUG_PUB.debug('p_num_workers:' || p_num_workers);
12104        AHL_DEBUG_PUB.debug('p_csi_max_id:' || p_csi_max_id);
12105        AHL_DEBUG_PUB.debug('p_csi_min_id:' || p_csi_min_id);
12106        AHL_DEBUG_PUB.debug('p_total_inst_count:' || p_total_inst_count);
12107     END IF;
12108 
12109     l_num_workers := p_num_workers;
12110 
12111     IF (p_total_inst_count > 0 ) THEN
12112        IF (l_num_workers = 1) THEN
12113          -- launch BUE worker request.
12114          l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, p_mr_header_id,
12115                                                 p_csi_min_id, p_csi_max_id);
12116 
12117          IF (l_req_id = 0 OR l_req_id IS NULL) THEN
12118             IF l_debug = 'Y' THEN
12119               AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
12120             END IF;
12121             fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
12122             fnd_file.new_line(FND_FILE.LOG,1);
12123             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
12124 
12125          ELSE
12126               fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id || ' launched to process instances between:' || p_csi_min_id || ' and ' || p_csi_min_id);
12127 
12128             IF l_debug = 'Y' THEN
12129               AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id || ' launched to process instances between:' || p_csi_min_id || ' and ' || p_csi_min_id);
12130             END IF;
12131          END IF;
12132 
12133        ELSE
12134          -- find optimal and tolerant count of instances and hence the start and
12135          -- end instance ID for each worker.
12136          l_step := round(p_total_inst_count/l_num_workers);
12137          IF (l_step = 0) THEN
12138            l_num_workers := p_total_inst_count;
12139            l_step := 1;
12140          END IF;
12141          l_tol_bef := l_step - trunc((0.1 * l_step));
12142          l_tol_after := l_step + trunc((0.1 * l_step));
12143 
12144          IF l_debug = 'Y' THEN
12145             AHL_DEBUG_PUB.debug('l_step:' || l_step);
12146             AHL_DEBUG_PUB.debug('l_tol_bef:' || l_tol_bef);
12147             AHL_DEBUG_PUB.debug('l_tol_after:' || l_tol_after);
12148          END IF;
12149 
12150          --dbms_output.put_line('l_Step:' || l_step);
12151          --dbms_output.put_line('l_tol_minus:' || l_tol_bef);
12152          --dbms_output.put_line('l_tol_plus:' || l_tol_after);
12153 
12154          -- use binary search logic to find the start and end points for every worker.
12155          l_begin_count_csi_id := p_csi_min_id;
12156          l_start_csi_id := p_csi_min_id;
12157          l_end_csi_id := p_csi_max_id;
12158 
12159          l_launched_workers := 0;
12160 
12161          --l_mid_point_inst_id := trunc((p_csi_min_id + p_csi_max_id) / 2);
12162          l_mid_point_inst_id := p_csi_max_id; -- start with full interval.
12163 
12164          WHILE (l_launched_workers < l_num_workers) loop
12165 
12166              WHILE (true) LOOP
12167 
12168                IF l_debug = 'Y' THEN
12169                   AHL_DEBUG_PUB.debug('Start loop:l_begin_count_csi_id:' || l_begin_count_csi_id);
12170                   AHL_DEBUG_PUB.debug('l_start_csi_id:' || l_start_csi_id);
12171                   AHL_DEBUG_PUB.debug('l_mid_point_inst_id:' || l_mid_point_inst_id);
12172                   --dbms_output.put_line('l_start_csi_id:' || l_start_csi_id);
12173                   --dbms_output.put_line('l_mid_point_inst_id:' || l_mid_point_inst_id);
12174                END IF;
12175 
12176                OPEN csi_inst_count_csr(l_begin_count_csi_id, l_mid_point_inst_id, p_mr_header_id);
12177                FETCH csi_inst_count_csr INTO l_count;
12178                CLOSE csi_inst_count_csr;
12179 
12180                IF l_debug = 'Y' THEN
12181                   AHL_DEBUG_PUB.debug('l_count:' || l_count);
12182                END IF;
12183                -- dbms_output.put_line('l_count:' || l_count);
12184 
12185                IF (l_count >= l_tol_bef AND l_count <= l_tol_after) THEN
12186 
12187                   l_launched_workers := l_launched_workers + 1;
12188 
12189                   -- launch BUE worker request.
12190                   l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, p_mr_header_id,
12191                                                          l_begin_count_csi_id, l_mid_point_inst_id);
12192 
12193                   --dbms_output.put_line('new l_launched_workers:' || l_launched_workers);
12194                   --dbms_output.put_line('newB l_begin_count_csi_id:' || l_begin_count_csi_id);
12195                   --dbms_output.put_line('newB l_mid_point_inst_id:' || l_mid_point_inst_id);
12196 
12197                   IF (l_req_id = 0 OR l_req_id IS NULL) THEN
12198                      IF l_debug = 'Y' THEN
12199                        AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
12200                      END IF;
12201                      fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
12202                      fnd_file.new_line(FND_FILE.LOG,1);
12203                      RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
12204 
12205                   ELSE
12206                      fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id ||
12207                      ' launched to process instances between:' || l_begin_count_csi_id || ' and ' ||
12208                       l_mid_point_inst_id);
12209 
12210                      IF l_debug = 'Y' THEN
12211                        AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id ||
12212                        ' launched to process instances between:' || l_begin_count_csi_id || ' and ' ||
12213                        l_mid_point_inst_id);
12214                      END IF;
12215                   END IF;
12216                   IF (l_launched_workers = l_num_workers - 1) THEN
12217                      -- launch last worker.
12218                      l_begin_count_csi_id := l_mid_point_inst_id + 1;
12219                      l_mid_point_inst_id := p_csi_max_id;
12220                      l_launched_workers := l_launched_workers + 1;
12221                      l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, p_mr_header_id,
12222                                                             l_begin_count_csi_id, l_mid_point_inst_id);
12223                      IF (l_req_id = 0 OR l_req_id IS NULL) THEN
12224                         IF l_debug = 'Y' THEN
12225                           AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
12226                         END IF;
12227                         fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
12228                         fnd_file.new_line(FND_FILE.LOG,1);
12229                         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
12230 
12231                      ELSE
12232                         fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id ||
12233                         ' launched to process instances between:' || l_begin_count_csi_id || ' and ' ||
12234                          l_mid_point_inst_id);
12235 
12236                         IF l_debug = 'Y' THEN
12237                           AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id ||
12238                           ' launched to process instances between:' || l_begin_count_csi_id || ' and ' ||
12239                           l_mid_point_inst_id);
12240                         END IF;
12241                      END IF; -- l_req_id = 0 OR ..
12242                   END IF;
12243                   EXIT;
12244                ELSIF (l_count < l_step) THEN
12245                   l_start_csi_id := l_mid_point_inst_id;
12246                   l_mid_point_inst_id := trunc((l_mid_point_inst_id + l_end_csi_id) /2);
12247                   --dbms_output.put_line('new l_mid_point_inst_id:<' || l_mid_point_inst_id);
12248                ELSIF (l_count > l_step) THEN
12249                   l_end_csi_id := l_mid_point_inst_id;
12250                   l_mid_point_inst_id := trunc((l_mid_point_inst_id + l_start_csi_id)/2);
12251                   --dbms_output.put_line('new l_mid_point_inst_id:>' || l_mid_point_inst_id);
12252 
12253                END IF; -- l_count >= l_tol_bef..
12254              END LOOP; -- WHILE (true)
12255              -- initialize begin, start and end points for next worker.
12256              l_begin_count_csi_id := l_mid_point_inst_id+1;
12257              l_start_csi_id := l_mid_point_inst_id+1;
12258              l_end_csi_id := p_csi_max_id;
12259              l_mid_point_inst_id := trunc((l_start_csi_id + l_end_csi_id) / 2);
12260          END LOOP;
12261 
12262      END IF;
12263   END IF;
12264 
12265   IF l_debug = 'Y' THEN
12266      AHL_DEBUG_PUB.debug('End of procedure: Instance_Split_BTree');
12267   END IF;
12268 
12269 END Instance_Split_BTree;
12270 
12271 ----------------------------------------------
12272 -- PM Build unit Effectivities worker concurrent program.
12273 PROCEDURE Process_Unit_Range (
12274                      errbuf                 OUT NOCOPY  VARCHAR2,
12275                      retcode                OUT NOCOPY  NUMBER,
12276                      p_mr_header_id         IN NUMBER,
12277                      p_start_instance_id    IN NUMBER,
12278                      p_end_instance_id      IN NUMBER)
12279 IS
12280 
12281   -- get instances when mr_header_id is provided.
12282   CURSOR get_inst( p_mr_header_id      IN NUMBER,
12283                    c_start_inst_id     IN NUMBER,
12284                    c_end_inst_id       IN NUMBER)
12285   IS
12286   SELECT cii.instance_id
12287     FROM csi_item_instances cii, ahl_mr_effectivities mre, mtl_system_items_b msi
12288     -- repalced mtl_system_items_kfv with mtl_system items_b.
12289     WHERE cii.inventory_item_id = msi.inventory_item_id
12290     AND cii.inv_master_organization_id = msi.organization_id
12291     AND cii.inventory_item_id = mre.inventory_item_id
12292     AND mre.mr_header_id = p_mr_header_id
12293     AND SYSDATE between trunc(nvl(cii.active_start_date,sysdate)) and
12294         trunc(nvl(cii.active_end_date,sysdate+1))
12295     AND cii.instance_id >= c_start_inst_id
12296     AND cii.instance_id <= c_end_inst_id;
12297 
12298   -- get instances when no mr_header_id.
12299   CURSOR get_all_inst( c_start_inst_id IN NUMBER,
12300                        c_end_inst_id   IN NUMBER)
12301   IS
12302   SELECT cii.instance_id
12303    FROM  csi_item_instances cii, ahl_mr_effectivities mre, mtl_system_items_b msi,
12304          (select mr_header_id
12305           from ahl_mr_headers_app_v
12306           where type_code = 'PROGRAM') mr
12307    WHERE cii.inventory_item_id = msi.inventory_item_id
12308      AND cii.inv_master_organization_id = msi.organization_id
12309      AND cii.inventory_item_id = mre.inventory_item_id
12310      AND mre.mr_header_id = mr.mr_header_id
12311      AND SYSDATE between trunc(nvl(cii.active_start_date,sysdate)) and
12312          trunc(nvl(cii.active_end_date,sysdate+1))
12313      AND cii.instance_id >= c_start_inst_id
12314      AND cii.instance_id <= c_end_inst_id;
12315 
12316   l_msg_count  NUMBER;
12317   l_msg_data   VARCHAR2(3000);
12318   l_return_status VARCHAR2(1);
12319 
12320   -- added for performance fix 6511501.
12321   TYPE nbr_tbl_type IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
12322   l_csi_inst_tbl  nbr_tbl_type;
12323 
12324 BEGIN
12325 
12326     IF G_DEBUG = 'Y' THEN
12327       fnd_file.put_line(FND_FILE.LOG,'MR Header ID = '||p_mr_header_id);
12328       fnd_file.put_line(FND_FILE.LOG,'CSI Start Instance = '||p_start_instance_id);
12329       fnd_file.put_line(FND_FILE.LOG,'CSI End Instance = '||p_end_instance_id);
12330       fnd_file.put_line(FND_FILE.LOG,'Start Time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
12331       fnd_file.new_line(FND_FILE.LOG,1);
12332     END IF;
12333 
12334     -- initialize return status.
12335     retcode := 0;
12336     IF (p_mr_header_id IS NOT NULL) THEN
12337       OPEN get_inst(p_mr_header_id, p_start_instance_id, p_end_instance_id);
12338     ELSE
12339       OPEN get_all_inst(p_start_instance_id, p_end_instance_id);
12340     END IF;
12341 
12342 
12343     LOOP
12344       IF (p_mr_header_id IS NOT NULL) THEN
12345         FETCH get_inst BULK COLLECT INTO l_csi_inst_tbl LIMIT 1000;
12346       ELSE
12347         FETCH get_all_inst BULK COLLECT INTO l_csi_inst_tbl LIMIT 1000;
12348       END IF;
12349 
12350       IF (l_csi_inst_tbl.count > 0) THEN
12351         -- call process unit for all instances.
12352         --FOR inst_rec IN get_inst(p_mr_header_id, p_start_instance_id, p_end_instance_id) LOOP
12353         FOR i IN l_csi_inst_tbl.FIRST..l_csi_inst_tbl.LAST  LOOP
12354            -- Call Process Unit for the item instance.
12355            Process_Unit (
12356                          p_commit               => FND_API.G_TRUE,
12357                          p_init_msg_list        => FND_API.G_TRUE,
12358                          x_msg_count            => l_msg_count,
12359                          x_msg_data             => l_msg_data,
12360                          x_return_status        => l_return_status,
12361                          p_csi_item_instance_id => l_csi_inst_tbl(i),
12362                                                    --inst_rec.instance_id,
12363                          p_concurrent_flag      => 'Y');
12364 
12365            l_msg_count := FND_MSG_PUB.Count_Msg;
12366            IF (l_return_status <> FND_API.G_RET_STS_SUCCESS)
12367            THEN
12368                retcode := 2;  -- error based only on return status
12369            ELSIF (l_msg_count > 0 AND l_return_status = FND_API.G_RET_STS_SUCCESS)
12370            THEN
12371                retcode := 1;  -- warning based on return status + msg count
12372            END IF;
12373 
12374         END LOOP; -- l_csi_inst_tbl.FIRST
12375       END IF; -- l_csi_inst_tbl.count
12376 
12377       IF (p_mr_header_id IS NOT NULL) THEN
12378         EXIT WHEN get_inst%NOTFOUND;
12379       ELSE
12380         EXIT WHEN get_all_inst%NOTFOUND;
12381       END IF;
12382 
12383     END LOOP; -- get_inst.
12384     IF (p_mr_header_id IS NOT NULL) THEN
12385       CLOSE get_inst;
12386     ELSE
12387       CLOSE get_all_inst;
12388     END IF;
12389 
12390     IF G_DEBUG = 'Y' THEN
12391       fnd_file.new_line(FND_FILE.LOG,1);
12392       fnd_file.put_line(FND_FILE.LOG,'End Time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
12393     END IF;
12394 
12395 --
12396 EXCEPTION
12397  WHEN OTHERS THEN
12398    retcode := 2;
12399    errbuf := 'Process_Unit_Range:PM:OTHERS:' || substrb(sqlerrm,1,60);
12400 
12401 END Process_Unit_Range;
12402 
12403 ----------------------------------------------
12404 -- Added for performance bug# 6893404.
12405 PROCEDURE Split_Process_All_Instances(p_concurrent_flag  IN  VARCHAR2,
12406                                       p_commit_flag      IN  VARCHAR2,
12407                                       p_num_of_workers   IN  NUMBER,
12408                                       p_mr_header_id     IN  NUMBER,
12409                                       p_mtl_category_id  IN  NUMBER,
12410                                       p_process_option   IN  VARCHAR2,
12411                                       x_msg_count        OUT NOCOPY  NUMBER,
12412                                       x_msg_data         OUT NOCOPY  NUMBER,
12413                                       x_return_status    OUT NOCOPY  VARCHAR2)
12414 IS
12415 
12416   l_req_id        number;
12417   l_conc_req_id   number;
12418   l_instance_id   number;
12419 
12420   l_num_of_workers number;
12421 
12422   dml_errors EXCEPTION;
12423   PRAGMA EXCEPTION_INIT(dml_errors, -24381);
12424 
12425   -- added for bug# 10185468
12426   l_err_mesg               VARCHAR2(4000);
12427   l_return_status          VARCHAR2(1);
12428 
12429 BEGIN
12430 
12431   IF G_debug = 'Y' THEN
12432      AHL_DEBUG_PUB.debug('Start Split_Process_All_Instances:p_concurrent_flag:' || p_concurrent_flag);
12433      AHL_DEBUG_PUB.debug('Input MR Header ID:' || p_mr_header_id);
12434      AHL_DEBUG_PUB.debug('Input p_num_of_workers:' || p_num_of_workers);
12435   END IF;
12436 
12437   -- initialize return status.
12438   x_return_status := FND_API.G_RET_STS_SUCCESS;
12439 
12440   IF (p_concurrent_flag = 'Y') THEN
12441     l_conc_req_id := fnd_global.conc_request_id;
12442   ELSE
12443     l_conc_req_id := fnd_global.session_id;
12444   END IF;
12445 
12446   -- validate p_num_of_workers.
12447   l_num_of_workers := trunc(p_num_of_workers);
12448 
12449   IF (l_num_of_workers IS NULL OR l_num_of_workers <= 0) THEN
12450     l_num_of_workers := 1;
12451   ELSIF l_num_of_workers > 30 THEN
12452     l_num_of_workers := 30;
12453   END IF;
12454 
12455   Populate_BUE_Worker(p_conc_request_id => l_conc_req_id,
12456                       p_concurrent_flag => p_concurrent_flag,
12457                       p_mtl_category_id => p_mtl_category_id,
12458                       p_process_option  => p_process_option,
12459                       errbuf            => x_msg_data,
12460                       x_return_status   => x_return_status);
12461 
12462   IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
12463     RETURN;
12464   END IF;
12465 
12466   -- launch worker programs.
12467   IF (p_concurrent_flag = 'Y') THEN
12468       -- submit worker programs to process units.
12469       FOR i IN 1..l_num_of_workers LOOP
12470          l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, l_conc_req_id);
12471          IF (l_req_id = 0 OR l_req_id IS NULL) THEN
12472             IF G_debug = 'Y' THEN
12473                AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
12474             END IF;
12475             fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
12476             fnd_file.new_line(FND_FILE.LOG,1);
12477             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
12478 
12479          ELSE
12480             fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id );
12481             IF G_debug = 'Y' THEN
12482                AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id );
12483             END IF;
12484          END IF; -- l_req_id = 0 OR ..
12485 
12486       END LOOP;
12487 
12488       -- call cleanup BUE for previously failed deletes.
12489       Cleanup_BUE_Worker(p_parent_conc_request_id => l_conc_req_id,
12490                          p_child_conc_request_id  => NULL,
12491                          x_return_status          => l_return_status,
12492                          x_errbuf                 => l_err_mesg);
12493       IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
12494         -- ignore error returned from this procedure
12495         -- log message in concurrent request log.
12496         fnd_file.put_line(FND_FILE.LOG, 'Warning: Error from Cleanup_BUE_Worker:' || l_err_mesg);
12497       END IF;
12498   ELSE
12499 
12500      LOOP
12501         -- initialize return status.
12502         x_return_status := FND_API.G_RET_STS_SUCCESS;
12503 
12504         Get_Next_BUE_Row(p_parent_conc_pgm_id  => l_conc_req_id,
12505                          p_conc_child_req_id   => l_conc_req_id,
12506                          x_return_status       => x_return_status,
12507                          errbuf                => x_msg_data,
12508                          x_item_instance_id    => l_instance_id);
12509 
12510         IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
12511            EXIT;
12512         END IF;
12513 
12514         EXIT WHEN (l_instance_id IS NULL);
12515 
12516         IF G_DEBUG = 'Y' THEN
12517            AHL_DEBUG_PUB.debug('Now processing..:' || l_instance_id);
12518         END IF;
12519 
12520         -- Call Process Unit for the item instance.
12521         Process_Unit (
12522                 p_commit               => p_commit_flag,
12523                 p_init_msg_list        => FND_API.G_TRUE,
12524                 x_msg_count            => x_msg_count,
12525                 x_msg_data             => x_msg_data,
12526                 x_return_status        => x_return_status,
12527                 p_csi_item_instance_id => l_instance_id,
12528                 p_concurrent_flag      => p_concurrent_flag,
12529                 -- added sim plan for NR Analysis Enh.
12530                 p_simulation_plan_id   => G_SIMULATION_PLAN_ID);
12531 
12532         IF ( x_return_status <> FND_API.G_RET_STS_SUCCESS) AND (p_commit_flag = FND_API.G_FALSE) THEN
12533           EXIT;
12534         END IF;
12535 
12536      END LOOP;
12537 
12538      -- cleanup worker table after processing.
12539      Cleanup_BUE_Worker(p_parent_conc_request_id => l_conc_req_id,
12540                         p_child_conc_request_id  => l_conc_req_id,
12541                         x_return_status          => l_return_status,
12542                         x_errbuf                 => l_err_mesg);
12543      IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
12544        -- ignore error returned from this procedure
12545        IF G_DEBUG = 'Y' THEN
12546            AHL_DEBUG_PUB.debug('Warning: Error from Cleanup_BUE_Worker:' || l_err_mesg);
12547        END IF;
12548      END IF;
12549 
12550   END IF;
12551 
12552   IF G_debug = 'Y' THEN
12553      AHL_DEBUG_PUB.debug('End Split_Process_All_Instances:Return Status:' || x_return_status);
12554   END IF;
12555 
12556 END Split_Process_All_Instances;
12557 
12558 ----------------------------------------------
12559 -- BUE Worker program for AHL processing.
12560 -- Called from BUE concurrent pgm when all units option is chosen..
12561 -- or when BUE is run for an MR or MR revision.
12562 PROCEDURE Process_Unit_Range (errbuf                 OUT NOCOPY  VARCHAR2,
12563                               retcode                OUT NOCOPY  NUMBER,
12564                               p_parent_conc_pgm_id   IN NUMBER)
12565 IS
12566 
12567   -- JKJain, NR Analysis and Forecasting
12568   CURSOR get_sim_plan_id (p_parent_conc_pgm_id IN NUMBER)
12569   IS
12570     SELECT simulation_plan_id
12571     FROM ahl_bue_worker_data
12572     WHERE parent_conc_request_id = p_parent_conc_pgm_id
12573       AND child_conc_request_id IS NULL;
12574 
12575   l_simulation_plan_id NUMBER := NULL;
12576   -- End NR Analysis and Forecasting
12577 
12578   l_instance_id     NUMBER;
12579   l_conc_child_req_id NUMBER;
12580 
12581   l_msg_count  NUMBER;
12582   l_msg_data   VARCHAR2(3000);
12583   l_return_status VARCHAR2(1);
12584 
12585 BEGIN
12586 
12587   fnd_file.put_line(FND_FILE.LOG,'Start time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
12588 
12589   G_DEBUG_LINE_NUM := 1;
12590 
12591   -- initialize return status.
12592   retcode := 0;
12593 
12594   l_conc_child_req_id := fnd_global.conc_request_id;
12595 
12596   -- JKJain, NR Analysis and Forecasting
12597   --Fetch simulation_plan_id for the first record.
12598   OPEN get_sim_plan_id(p_parent_conc_pgm_id);
12599   FETCH get_sim_plan_id into l_simulation_plan_id;
12600   CLOSE get_sim_plan_id;
12601 
12602   IF G_debug = 'Y' THEN
12603      AHL_DEBUG_PUB.debug('Start Process_Unit_Range for concurrent pgm ID:' || l_conc_child_req_id);
12604      AHL_DEBUG_PUB.debug('Parent concurrent pgm ID:' || p_parent_conc_pgm_id);
12605      -- JKJain, NR Analysis and Forecasting
12606      AHL_DEBUG_PUB.debug('Process_Unit_Range =>  p_simulation_plan_id :' || l_simulation_plan_id);
12607 
12608   END IF;
12609 
12610   -- AHL processing.
12611   LOOP
12612     -- initialize return status.
12613     l_return_status := FND_API.G_RET_STS_SUCCESS;
12614 
12615     G_DEBUG_LINE_NUM := 10;
12616 
12617     -- get next unit to process.
12618     Get_Next_BUE_Row(p_parent_conc_pgm_id  => p_parent_conc_pgm_id,
12619                      p_conc_child_req_id   => l_conc_child_req_id,
12620                      x_return_status       => l_return_status,
12621                      errbuf                => errbuf,
12622                      x_item_instance_id    => l_instance_id);
12623 
12624     IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
12625        EXIT;
12626     END IF;
12627 
12628     EXIT WHEN (l_instance_id IS NULL);
12629 
12630     fnd_file.new_line(FND_FILE.LOG,1);
12631     fnd_file.put_line(FND_FILE.LOG,'Now processing..:' || l_instance_id);
12632     fnd_file.put_line(FND_FILE.LOG,'Start time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
12633 
12634     G_DEBUG_LINE_NUM := 20;
12635 
12636     -- Call Process Unit for the item instance.
12637     Process_Unit (
12638            p_commit               => FND_API.G_TRUE,
12639            p_init_msg_list        => FND_API.G_TRUE,
12640            x_msg_count            => l_msg_count,
12641            x_msg_data             => l_msg_data,
12642            x_return_status        => l_return_status,
12643            p_csi_item_instance_id => l_instance_id,
12644            p_concurrent_flag      => 'Y',
12645            -- JKJain, NR Analysis and Forecasting
12646            p_simulation_plan_id   => l_simulation_plan_id);
12647 
12648     fnd_file.put_line(FND_FILE.LOG,'End time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
12649 
12650     l_msg_count := FND_MSG_PUB.Count_Msg;
12651     IF (retcode <> 2 AND l_return_status <> FND_API.G_RET_STS_SUCCESS)
12652     THEN
12653        retcode := 2;  -- error based only on return status
12654     ELSIF (retcode = 0 AND l_msg_count > 0 AND l_return_status = FND_API.G_RET_STS_SUCCESS)
12655     THEN
12656        retcode := 1;  -- warning based on return status + msg count
12657     END IF;
12658 
12659   END LOOP;
12660 
12661   G_DEBUG_LINE_NUM := 30;
12662 
12663   -- cleanup worker table after processing.
12664   Cleanup_BUE_Worker(p_parent_conc_request_id => p_parent_conc_pgm_id,
12665                      p_child_conc_request_id  => l_conc_child_req_id,
12666                      x_return_status          => l_return_status,
12667                      x_errbuf                 => l_msg_data);
12668   IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
12669     -- ignore error returned from this procedure
12670     -- log message in concurrent request log.
12671     fnd_file.put_line(FND_FILE.LOG, 'Warning: Error from Cleanup_BUE_Worker:' || l_msg_data);
12672     retcode := 1; -- warning based on return status
12673   END IF;
12674 
12675 
12676   IF G_debug = 'Y' THEN
12677      AHL_DEBUG_PUB.debug('Concurrent pgm retcode:' || retcode);
12678      AHL_DEBUG_PUB.debug('Concurrent pgm l_return_status:' || l_return_status);
12679      AHL_DEBUG_PUB.debug('End Process_Unit_Range for concurrent pgm ID:' || l_conc_child_req_id);
12680   END IF;
12681 
12682 --
12683 EXCEPTION
12684  WHEN FND_API.G_EXC_ERROR THEN
12685    retcode := 2;
12686    errbuf := 'Process_Unit_Range:EXC:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
12687 
12688  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
12689    retcode := 2;
12690    errbuf := 'Process_Unit_Range:UNEXP:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
12691 
12692  WHEN OTHERS THEN
12693    IF (SQLCODE = -54) THEN
12694      retcode := 1;
12695      errbuf := 'Process_Unit_Range:54:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
12696    ELSIF (SQLCODE = -6519) THEN
12697      retcode := 1;
12698      errbuf := 'Process_Unit_Range:6519:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
12699    ELSE
12700      retcode := 2;
12701      errbuf := 'Process_Unit_Range:OTH:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
12702    END IF;
12703 
12704 END Process_Unit_Range;
12705 ------------------------
12706 -- BUE Worker program for AHL processing.
12707 -- This procedure is called after a MR is revised.
12708 PROCEDURE Process_Unit_Range (errbuf                 OUT NOCOPY  VARCHAR2,
12709                               retcode                OUT NOCOPY  NUMBER,
12710                               p_old_mr_header_id     IN          NUMBER,
12711                               p_new_mr_header_id     IN          NUMBER)
12712 
12713 IS
12714 
12715   l_return_status      varchar2(1);
12716   l_msg_count          number;
12717   l_msg_data           varchar2(2000);
12718 
12719 BEGIN
12720 
12721     fnd_file.put_line(FND_FILE.LOG,'Start time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
12722 
12723     IF G_debug = 'Y' THEN
12724        AHL_DEBUG_PUB.debug('Start Process_Unit_Range for MR: Old ID:New ID:' || p_old_mr_header_id || ':' || p_new_mr_header_id);
12725     END IF;
12726 
12727     -- initialize return status.
12728     retcode := 0;
12729 
12730     -- After commit call UMP BUE api to build UEs.
12731     AHL_UMP_PROCESSUNIT_PVT.Process_MRAffected_Units (
12732            p_commit          => FND_API.G_TRUE,
12733            x_msg_count       => l_msg_count,
12734            x_msg_data        => l_msg_data,
12735            x_return_status   => l_return_status, -- ignore status returned by this api.
12736            p_old_mr_header_id  => p_old_mr_header_id,
12737            p_mr_header_id      => p_new_mr_header_id,
12738            p_concurrent_flag   => 'Y',
12739            p_num_of_workers    => 5);
12740 
12741     l_msg_count := FND_MSG_PUB.Count_Msg;
12742     IF (l_return_status <> FND_API.G_RET_STS_SUCCESS)
12743     THEN
12744        retcode := 2;  -- error based only on return status
12745        log_error_messages;
12746     ELSIF (l_msg_count > 0 AND l_return_status = FND_API.G_RET_STS_SUCCESS)
12747     THEN
12748        retcode := 1;  -- warning based on return status + msg count
12749        log_error_messages;
12750     END IF;
12751 
12752     IF G_debug = 'Y' THEN
12753        AHL_DEBUG_PUB.debug('End Process_Unit_Range for MR: retcode:' || retcode);
12754     END IF;
12755 
12756 --
12757 EXCEPTION
12758  WHEN FND_API.G_EXC_ERROR THEN
12759    retcode := 2;
12760    errbuf := 'Process_Unit_Range:MR:EXC:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
12761 
12762  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
12763    retcode := 2;
12764    errbuf := 'Process_Unit_Range:MR:UNEXP:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
12765 
12766  WHEN OTHERS THEN
12767    IF (SQLCODE = -54) THEN
12768      retcode := 1;
12769      errbuf := 'Process_Unit_Range:54:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,70);
12770    ELSIF (SQLCODE = -6519) THEN
12771      retcode := 1;
12772      errbuf := 'Process_Unit_Range:6519:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,70);
12773    ELSE
12774      retcode := 2;
12775      errbuf := 'Process_Unit_Range:MR:OTH:' || substrb(sqlerrm,1,60);
12776    END IF;
12777 
12778 END Process_Unit_Range;
12779 
12780 ------------------------
12781 -- Added for performance bug# 6893404.
12782 PROCEDURE Populate_BUE_Worker(p_conc_request_id IN  NUMBER,
12783                               p_concurrent_flag IN  VARCHAR2,
12784                               p_mtl_category_id IN  NUMBER,
12785                               p_process_option  IN  VARCHAR2,
12786                               errbuf            OUT NOCOPY VARCHAR2,
12787                               x_return_status   OUT NOCOPY VARCHAR2)
12788 IS
12789   PRAGMA AUTONOMOUS_TRANSACTION;
12790 
12791   l_instance_id_tbl   nbr_tbl_type;
12792   l_unit_name_tbl     vchar_tbl_type;
12793 
12794   -- get all valid uc headers
12795   -- It is possible to have UC with parent_uc_header_id as NULL but
12796   -- installed on a instance which is not a UC.
12797   -- see second issue reported in bug# 8326078
12798   CURSOR ahl_unit_config_header_csr IS
12799     SELECT csi_item_instance_id
12800     FROM  ahl_unit_config_headers uc, csi_item_instances ii
12801     WHERE uc.csi_item_instance_id = ii.instance_id
12802       AND trunc(nvl(uc.active_start_date,sysdate)) <= trunc(sysdate)
12803       AND trunc(sysdate) < trunc(nvl(uc.active_end_date,sysdate+1))
12804       AND trunc(nvl(ii.active_start_date,sysdate)) <= trunc(sysdate)
12805       AND sysdate < nvl(ii.active_end_date,sysdate+1)
12806       AND unit_config_status_code <> 'DRAFT'
12807       AND parent_uc_header_id IS NULL
12808       AND NOT EXISTS (select 'x'
12809                       from csi_ii_relationships iir
12810                       where iir.relationship_type_code = 'COMPONENT-OF'
12811                         and iir.subject_id = uc.csi_item_instance_id
12812                         and trunc(nvl(iir.active_start_date, sysdate)) <= trunc(sysdate)
12813                         and trunc(sysdate) < trunc(nvl(iir.active_end_date,sysdate+1))
12814                      );
12815 
12816   -- get all valid uc headers that match item category.
12817   -- It is possible to have UC with parent_uc_header_id as NULL but
12818   -- installed on a instance which is not a UC.
12819   -- see second issue reported in bug# 8326078
12820   CURSOR ahl_unit_itemcat_csr(p_mtl_category_id IN NUMBER) IS
12821     SELECT csi_item_instance_id
12822     FROM  ahl_unit_config_headers uc, csi_item_instances ii
12823     WHERE uc.csi_item_instance_id = ii.instance_id
12824       AND trunc(nvl(uc.active_start_date,sysdate)) <= trunc(sysdate)
12825       AND trunc(sysdate) < trunc(nvl(uc.active_end_date,sysdate+1))
12826       AND trunc(nvl(ii.active_start_date,sysdate)) <= trunc(sysdate)
12827       AND sysdate < nvl(ii.active_end_date,sysdate+1)
12828       AND unit_config_status_code <> 'DRAFT'
12829       AND parent_uc_header_id IS NULL
12830       AND NOT EXISTS (select 'x'
12831                       from csi_ii_relationships iir
12832                       where iir.relationship_type_code = 'COMPONENT-OF'
12833                         and iir.subject_id = uc.csi_item_instance_id
12834                         and trunc(nvl(iir.active_start_date, sysdate)) <= trunc(sysdate)
12835                         and trunc(sysdate) < trunc(nvl(iir.active_end_date,sysdate+1))
12836                      )
12837       AND exists (select 'x'
12838                   from mtl_category_set_valid_cats cs, mtl_item_categories itc,
12839                        csi_item_instances cii2
12840                   where cs.category_set_id = fnd_profile.value('AHL_BUE_ITEM_CATEGORY_SET')
12841                     AND cs.category_set_id = itc.category_set_id
12842                     AND cs.category_id = itc.category_id
12843                     AND itc.category_id = p_mtl_category_id
12844                     AND cii2.instance_id = uc.csi_item_instance_id
12845                     AND itc.organization_id = cii2.inv_master_organization_id
12846                     AND itc.inventory_item_id = cii2.inventory_item_id
12847                   ); -- get units matching item category.
12848 
12849 
12850   -- get item instances matching inventory item id.
12851   -- when no item category and process option = 'Units or Components' or all
12852   CURSOR get_uc_item_inst_csr(p_opt_uc IN NUMBER) IS
12853     SELECT instance_id from
12854      (SELECT DISTINCT nvl(root_instance_id, instance_id) instance_id from
12855        (
12856         SELECT cii.instance_id,
12857               (select object_id from csi_ii_relationships parent
12858                where not exists (select 'x' from csi_ii_relationships
12859                                  where subject_id = parent.object_id and
12860                                  relationship_type_code = 'COMPONENT-OF' and
12861                                  trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) and
12862                                  trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
12863                start with parent.subject_id = cii.instance_id and
12864                parent.relationship_type_code = 'COMPONENT-OF' and
12865                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
12866                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
12867                connect by prior parent.object_id = parent.subject_id and
12868                parent.relationship_type_code = 'COMPONENT-OF' and
12869                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
12870                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
12871                ) Root_instance_id
12872 
12873         FROM csi_item_instances cii, ahl_mr_effectivities mre
12874         WHERE mre.inventory_item_id = nvl(null, mre.inventory_item_id)
12875           AND mre.mr_header_id = nvl(null,mre.mr_header_id)
12876           -- added nvl conditions above as this seems to force use of index on
12877           -- ahl_mr_headers_b and also brings query cost down.
12878           AND mre.relationship_id is null
12879           AND mre.inventory_item_id = cii.inventory_item_id
12880           AND exists (SELECT 'x' from ahl_mr_headers_app_v MR
12881                        WHERE MR.mr_header_id = mre.mr_header_id
12882                          AND MR.program_type_code NOT IN ('MO_PROC')
12883                          AND MR.version_number in (SELECT max(MRM.version_number)
12884                                                    FROM ahl_mr_headers_app_v MRM
12885                                                    WHERE mrm.title = mr.title
12886                                                      AND SYSDATE between trunc(MR.effective_from)
12887                                                      AND trunc(nvl(MR.effective_to,SYSDATE+1))
12888                                                      AND mr_status_code='COMPLETE'
12889                                                   )
12890                      )
12891           AND trunc(nvl(cii.active_start_date, sysdate)) <= trunc(sysdate)
12892           AND trunc(sysdate) < trunc(nvl(cii.active_end_date, sysdate+1))
12893        )
12894      ) valid_inst
12895     WHERE /*(p_opt_uc = 1 AND exists (select 'x' from ahl_unit_config_headers
12896                                     where csi_item_instance_id = valid_inst.instance_id
12897                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
12898                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
12899                                       AND unit_config_status_code <> 'DRAFT'
12900                                       AND parent_uc_header_id IS NULL
12901                                    ) -- get UCs only.
12902           )
12903           OR */  -- this cursor is not used when p_opt_uc = 1
12904           -- get components.
12905           (p_opt_uc = 2 AND not exists (select 'x' from ahl_unit_config_headers
12906                                         where csi_item_instance_id = valid_inst.instance_id
12907                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
12908                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
12909                                           -- instance is a UC if in status draft.
12910                                           --AND unit_config_status_code <> 'DRAFT'
12911                                           --AND parent_uc_header_id IS NULL
12912                                        )
12913           )
12914           OR
12915           -- get all but ignore UCs as they have alredy been selected.
12916           (p_opt_uc = 0 AND not exists (select 'x' from ahl_unit_config_headers
12917                                         where csi_item_instance_id = valid_inst.instance_id
12918                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
12919                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
12920                                           -- instance is a UC if in status draft.
12921                                           --AND unit_config_status_code <> 'DRAFT'
12922                                           --AND parent_uc_header_id IS NULL
12923                                        )
12924           );
12925 
12926   -- get item instances matching inventory item id, item cat and is a UC.
12927   -- when item category selected with process option of ALL, Units or Components.
12928   CURSOR get_uc_itemcat_inst_csr (p_mtl_category_id IN NUMBER,
12929                                   p_opt_uc          IN NUMBER) IS
12930     SELECT instance_id from
12931      (SELECT DISTINCT nvl(root_instance_id, instance_id) instance_id from
12932        (
12933         SELECT cii.instance_id,
12934               (select object_id from csi_ii_relationships parent
12935                where not exists (select 'x' from csi_ii_relationships
12936                                  where subject_id = parent.object_id and
12937                                  relationship_type_code = 'COMPONENT-OF' and
12938                                  trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) and
12939                                  trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
12940                start with parent.subject_id = cii.instance_id and
12941                parent.relationship_type_code = 'COMPONENT-OF' and
12942                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
12943                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
12944                connect by prior parent.object_id = parent.subject_id and
12945                parent.relationship_type_code = 'COMPONENT-OF' and
12946                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
12947                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
12948                ) Root_instance_id
12949 
12950         FROM csi_item_instances cii,
12951              (select distinct me.inventory_item_id
12952               from ahl_mr_headers_app_v mr, ahl_mr_effectivities me
12953               where mr.mr_header_id = me.mr_header_id AND
12954                     mr.mr_status_code = 'COMPLETE' AND
12955                     MR.program_type_code NOT IN ('MO_PROC') AND -- added in R12
12956                     trunc(effective_from) <= trunc(sysdate) AND
12957                     trunc(nvl(effective_to,sysdate)) >= trunc(sysdate)
12958                     and me.inventory_item_id is not null
12959              ) mre
12960         WHERE trunc(nvl(cii.active_start_date, sysdate)) <= trunc(sysdate) AND
12961               trunc(sysdate) < trunc(nvl(cii.active_end_date, sysdate+1))
12962           AND mre.inventory_item_id = cii.inventory_item_id
12963        )
12964      ) valid_inst
12965     WHERE exists (select 'x'
12966                   from mtl_category_set_valid_cats cs, mtl_item_categories itc,
12967                        csi_item_instances cii2
12968                   where cs.category_set_id = fnd_profile.value('AHL_BUE_ITEM_CATEGORY_SET')
12969                     AND cs.category_set_id = itc.category_set_id
12970                     AND cs.category_id = itc.category_id
12971                     AND itc.category_id = p_mtl_category_id
12972                     AND cii2.instance_id = valid_inst.instance_id
12973                     AND itc.organization_id = cii2.inv_master_organization_id
12974                     AND itc.inventory_item_id = cii2.inventory_item_id
12975                   ) -- get root nodes matching item category.
12976 
12977       AND ((p_opt_uc = 1 AND exists (select 'x' from ahl_unit_config_headers
12978                                     where csi_item_instance_id = valid_inst.instance_id
12979                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
12980                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
12981                                       AND unit_config_status_code <> 'DRAFT'
12982                                       AND parent_uc_header_id IS NULL
12983                                    ) -- get UCs only.
12984           )
12985           OR
12986           -- get components.
12987           (p_opt_uc = 2 AND not exists (select 'x' from ahl_unit_config_headers
12988                                         where csi_item_instance_id = valid_inst.instance_id
12989                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
12990                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
12991                                           -- instance is a UC if in status draft.
12992                                           --AND unit_config_status_code <> 'DRAFT'
12993                                           --AND parent_uc_header_id IS NULL
12994                                        )
12995           )
12996           OR
12997           -- when process option is ALL.
12998           -- get components in this case too as UC's have already been selected.
12999           (p_opt_uc = 0 AND not exists (select 'x' from ahl_unit_config_headers
13000                                         where csi_item_instance_id = valid_inst.instance_id
13001                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
13002                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
13003                                           -- instance is a UC if in status draft.
13004                                           --AND unit_config_status_code <> 'DRAFT'
13005                                           --AND parent_uc_header_id IS NULL
13006                                        )
13007           )
13008           );
13009 
13010   -- added to fix bug#8543402
13011   -- check if UMP data exists for expired instances.
13012   CURSOR chk_expire_inst_csr IS
13013     SELECT cii.instance_id
13014       FROM csi_item_instances cii,
13015            (select distinct me.inventory_item_id
13016             from ahl_mr_headers_app_v mr, ahl_mr_effectivities me
13017             where mr.mr_header_id = me.mr_header_id AND
13018                   mr.mr_status_code = 'COMPLETE' AND
13019                   MR.program_type_code NOT IN ('MO_PROC') AND -- added in R12
13020                   trunc(effective_from) <= trunc(sysdate) AND
13021                   trunc(nvl(effective_to,sysdate)) >= trunc(sysdate)
13022                   and me.inventory_item_id is not null
13023            ) mre
13024       WHERE cii.active_end_date <= sysdate
13025        AND mre.inventory_item_id = cii.inventory_item_id
13026        AND EXISTS (select 'x' from ahl_unit_effectivities_b UE
13027                    where ue.csi_item_instance_id = cii.instance_id
13028                      and (ue.status_code IS NULL OR ue.status_code IN ('INIT-DUE','EXCEPTION'))
13029                   );
13030 
13031   -- JKJain, NR Analysis and Forecasting
13032   -- get all valid uc headers in a simulation plan
13033   CURSOR get_sim_plan_uc_root_csr (c_simulation_plan_id IN NUMBER)IS
13034    SELECT distinct UC.csi_item_instance_id
13035     from  AHL_UNIT_CONFIG_HEADERS UC, AHL_FLEET_UNIT_ASSOCS FU
13036     WHERE FU.simulation_plan_id = c_simulation_plan_id
13037     and UC.UNIT_CONFIG_HEADER_ID = FU.UNIT_CONFIG_HEADER_ID
13038     and nvl(FU.association_end,sysdate) >= sysdate ;
13039 
13040   l_buffer_limit  number := 5000;
13041   l_opt_uc        number;
13042 
13043   dml_errors EXCEPTION;
13044   PRAGMA EXCEPTION_INIT(dml_errors, -24381);
13045 
13046 BEGIN
13047 
13048   IF G_debug = 'Y' THEN
13049      AHL_DEBUG_PUB.debug('Start Populate_BUE_Worker for pgm ID:' || p_conc_request_id);
13050      AHL_DEBUG_PUB.debug('Concurrent flag:' || p_concurrent_flag);
13051   END IF;
13052 
13053   -- initialize return status.
13054   x_return_status := FND_API.G_RET_STS_SUCCESS;
13055 
13056   IF (p_process_option = 'AHL_BUE_ALL_COMPONENTS') THEN
13057      l_opt_uc := 2;
13058     -- JKJain, NR Analysis and Forecasting
13059   ELSIF (p_process_option = 'AHL_BUE_ALL_UNITS' OR G_PRIMARY_PLAN = 'N') THEN
13060      l_opt_uc := 1;
13061   ELSE
13062      l_opt_uc := 0; -- when opt is null or AHL_BUE_ALL
13063   END IF;
13064 
13065   -- get all unit configurations.
13066   IF (l_opt_uc IN (0,1)) THEN
13067 
13068       -- JKJain, NR Analysis and Forecasting
13069       IF (G_PRIMARY_PLAN = 'N') THEN
13070         OPEN get_sim_plan_uc_root_csr(G_SIMULATION_PLAN_ID);
13071       ELSIF (p_mtl_category_id IS NULL) THEN
13072         OPEN ahl_unit_config_header_csr;
13073       ELSE
13074         OPEN ahl_unit_itemcat_csr(p_mtl_category_id);
13075       END IF;
13076 
13077       LOOP
13078         -- JKJain, NR Analysis and Forecasting
13079         IF (G_PRIMARY_PLAN = 'N') THEN
13080           FETCH get_sim_plan_uc_root_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13081         ELSIF (p_mtl_category_id IS NULL) THEN
13082           FETCH ahl_unit_config_header_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13083         ELSE
13084           FETCH ahl_unit_itemcat_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13085         END IF;
13086 
13087         EXIT WHEN (l_instance_id_tbl.count = 0);
13088 
13089         -- insert into BUE table.
13090         FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST
13091           INSERT INTO AHL_BUE_WORKER_DATA
13092           (parent_conc_request_id,
13093            csi_item_instance_id,
13094            child_conc_request_id,
13095            last_update_date,
13096            last_updated_by,
13097            creation_date,
13098            created_by,
13099            last_update_login,
13100            object_version_number,
13101            -- JKJain, NR Analysis and Forecasting
13102            simulation_plan_id) VALUES
13103            (p_conc_request_id,
13104             l_instance_id_tbl(instance_indx),
13105             null,
13106             sysdate,
13107             fnd_global.user_id,
13108             sysdate,
13109             fnd_global.user_id,
13110             fnd_global.conc_login_id,
13111             1,
13112             G_SIMULATION_PLAN_ID);
13113 
13114         l_instance_id_tbl.DELETE;
13115 
13116       END LOOP;
13117 
13118       -- JKJain, NR Analysis and Forecasting
13119       IF (G_PRIMARY_PLAN = 'N') THEN
13120         CLOSE get_sim_plan_uc_root_csr;
13121       ELSIF (p_mtl_category_id IS NULL) THEN
13122          CLOSE ahl_unit_config_header_csr;
13123       ELSE
13124          CLOSE ahl_unit_itemcat_csr;
13125       END IF;
13126 
13127   END IF; -- (l_opt_uc IN (0,1))
13128 
13129   IF (l_opt_uc <> 1) THEN -- skip when only processing units.
13130     -- now process instances based on inventory_item_id.
13131     IF (p_mtl_category_id IS NULL) THEN
13132         OPEN get_uc_item_inst_csr(l_opt_uc);
13133     ELSE
13134         OPEN get_uc_itemcat_inst_csr(p_mtl_category_id, l_opt_uc);
13135     END IF;
13136 
13137     LOOP
13138       IF (p_mtl_category_id IS NULL) THEN
13139           FETCH get_uc_item_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13140       ELSE
13141           FETCH get_uc_itemcat_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13142       END IF;
13143 
13144       EXIT WHEN (l_instance_id_tbl.count = 0);
13145 
13146       BEGIN
13147         -- insert into BUE table.
13148         FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST SAVE EXCEPTIONS
13149           INSERT INTO AHL_BUE_WORKER_DATA
13150           (parent_conc_request_id,
13151            csi_item_instance_id,
13152            child_conc_request_id,
13153            last_update_date,
13154            last_updated_by,
13155            creation_date,
13156            created_by,
13157            last_update_login,
13158            object_version_number,
13159            -- JKJain, NR Analysis and Forecasting
13160            simulation_plan_id) VALUES
13161            (p_conc_request_id,
13162             l_instance_id_tbl(instance_indx),
13163             null,
13164             sysdate,
13165             fnd_global.user_id,
13166             sysdate,
13167             fnd_global.user_id,
13168             fnd_global.conc_login_id,
13169             1,
13170             -- JKJain, NR Analysis and Forecasting
13171             G_SIMULATION_PLAN_ID);
13172 
13173         EXCEPTION
13174           WHEN DML_ERRORS THEN
13175             IF (get_uc_item_inst_csr%ISOPEN) THEN
13176               CLOSE get_uc_item_inst_csr;
13177             END IF;
13178             IF (get_uc_itemcat_inst_csr%ISOPEN) THEN
13179               CLOSE get_uc_itemcat_inst_csr;
13180             END IF;
13181 
13182             x_return_status := 'E';
13183 
13184             IF (p_concurrent_flag = 'Y') THEN
13185               fnd_file.put_line(fnd_file.log, 'Following error(s) occured while inserting into table ahl_bue_worker_data');
13186               FOR j IN 1..sql%bulk_exceptions.count
13187               LOOP
13188                 fnd_file.put_line(fnd_file.log, sql%bulk_exceptions(j).error_index || ', ' ||
13189                 sqlerrm(-sql%bulk_exceptions(j).error_code) );
13190               END LOOP;
13191             END IF;
13192 
13193             FND_MESSAGE.set_name('AHL', 'AHL_UMP_BUE_WORKER_ERR');
13194             FND_MSG_PUB.add;
13195             errbuf := FND_MSG_PUB.Get;
13196 
13197             RETURN;
13198       END;
13199 
13200       l_instance_id_tbl.DELETE;
13201 
13202     END LOOP;
13203 
13204     IF (p_mtl_category_id IS NULL) THEN
13205        CLOSE get_uc_item_inst_csr;
13206     ELSE
13207        CLOSE get_uc_itemcat_inst_csr;
13208     END IF;
13209   END IF; -- l_opt_uc
13210 
13211   IF(G_PRIMARY_PLAN <> 'N') THEN -- bug 13739681
13212   -- process expired instances.
13213   l_instance_id_tbl.DELETE;
13214 
13215   OPEN chk_expire_inst_csr;
13216   LOOP
13217       FETCH chk_expire_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13218       EXIT WHEN (l_instance_id_tbl.count = 0);
13219 
13220       BEGIN
13221         -- insert into BUE table.
13222         FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST SAVE EXCEPTIONS
13223            INSERT INTO AHL_BUE_WORKER_DATA
13224               (parent_conc_request_id,
13225                csi_item_instance_id,
13226                child_conc_request_id,
13227                last_update_date,
13228                last_updated_by,
13229                creation_date,
13230                created_by,
13231                last_update_login,
13232                object_version_number) VALUES
13233                (p_conc_request_id,
13234                 l_instance_id_tbl(instance_indx),
13235                 null,
13236                 sysdate,
13237                 fnd_global.user_id,
13238                 sysdate,
13239                 fnd_global.user_id,
13240                 fnd_global.conc_login_id,
13241                 1);
13242 
13243       EXCEPTION
13244          WHEN DML_ERRORS THEN
13245               IF (chk_expire_inst_csr%ISOPEN) THEN
13246                 CLOSE chk_expire_inst_csr;
13247               END IF;
13248 
13249               x_return_status := 'E';
13250 
13251               IF (p_concurrent_flag = 'Y') THEN
13252                 fnd_file.put_line(fnd_file.log, 'Following error(s) occured while inserting into table ahl_bue_worker_data');
13253                 FOR j IN 1..sql%bulk_exceptions.count
13254                 LOOP
13255                   fnd_file.put_line(fnd_file.log, sql%bulk_exceptions(j).error_index || ', ' ||
13256                   sqlerrm(-sql%bulk_exceptions(j).error_code) );
13257                 END LOOP;
13258               END IF;
13259 
13260               FND_MESSAGE.set_name('AHL', 'AHL_UMP_BUE_WORKER_ERR');
13261               FND_MSG_PUB.add;
13262               errbuf := FND_MSG_PUB.Get;
13263 
13264               RETURN;
13265     END;
13266 
13267     l_instance_id_tbl.DELETE;
13268 
13269   END LOOP;
13270   CLOSE chk_expire_inst_csr;
13271   END IF; -- G_PRIMARY_PLAN <> 'N'
13272 
13273   -- delete duplicate rows.
13274   /* fix for performance bug# 16003176 (10g to 11g upgrade)
13275   DELETE FROM ahl_bue_worker_data
13276   WHERE parent_conc_request_id = p_conc_request_id
13277     AND rowid not in (SELECT MIN(rowid)
13278                       FROM ahl_bue_worker_data
13279                       WHERE parent_conc_request_id = p_conc_request_id
13280                       GROUP BY csi_item_instance_id, parent_conc_request_id) ;
13281   */
13282   --DELETE FROM ahl_bue_worker_data wrk1
13283   --WHERE wrk1.parent_conc_request_id = p_conc_request_id
13284   --  AND wrk1.rowid > ANY ( SELECT wrk2.rowid
13285   --                         FROM ahl_bue_worker_data wrk2
13286   --                         WHERE wrk2.parent_conc_request_id = p_conc_request_id
13287   --                           AND wrk2.csi_item_instance_id = wrk1.csi_item_instance_id) ;
13288 
13289   --DELETE FROM ahl_bue_worker_data ad1
13290   --WHERE ad1.parent_conc_request_id = p_conc_request_id
13291   --  AND ad1.rowid not in (SELECT /*+ UNNEST  INDEX(ad2 AHL_BUE_WORKER_DATA_N2) */ MIN(ad2.rowid)
13292   --                    FROM ahl_bue_worker_data ad2
13293   --                    WHERE ad2.parent_conc_request_id = p_conc_request_id
13294   --                    GROUP BY ad2.csi_item_instance_id, ad2.parent_conc_request_id) ;
13295 
13296   --delete /*+ rowid(a) use_nl(a) */
13297   -- from ahl_bue_worker_data a
13298   -- where rowid in
13299   --  (select /*+ unnest */ rowid
13300   --    from
13301   --       (select /*+ parallel(b) cardinality(b,10) */
13302   --          rowid, row_number() over (partition by
13303   --              csi_item_instance_id, parent_conc_request_id
13304   --          order by 1
13305   --          ) dup
13306   --          from ahl_bue_worker_data b
13307   --          where b.parent_conc_request_id = p_conc_request_id)
13308   --  where dup > 1);
13309 
13310   DELETE /*+ parallel(a) */ FROM ahl_bue_worker_data a
13311    where  a.parent_conc_request_id = p_conc_request_id
13312    and exists (select 'x' from ahl_bue_worker_data b
13313                 where b.parent_conc_request_id = a.parent_conc_request_id
13314                   and b.csi_item_instance_id = a.csi_item_instance_id
13315                   and b.rowid      > a.rowid);
13316 
13317   -- save changes.
13318   COMMIT WORK;
13319 
13320   IF G_debug = 'Y' THEN
13321      AHL_DEBUG_PUB.debug('Concurrent pgm x_return_status:' || x_return_status);
13322      AHL_DEBUG_PUB.debug('End Populate_BUE_Worker for pgm ID:' || p_conc_request_id);
13323   END IF;
13324 
13325 END Populate_BUE_Worker;
13326 
13327 -- Added for performance bug# 6893404.
13328 PROCEDURE Get_Next_BUE_Row(p_parent_conc_pgm_id    IN  NUMBER,
13329                            p_conc_child_req_id     IN  NUMBER,
13330                            x_return_status         OUT NOCOPY VARCHAR2,
13331                            errbuf                  OUT NOCOPY VARCHAR2,
13332                            x_item_instance_id      OUT NOCOPY NUMBER)
13333 IS
13334 
13335   PRAGMA AUTONOMOUS_TRANSACTION;
13336 
13337   -- added hint to resolve perf bug# 16003176
13338   CURSOR ahl_bue_worker_csr (p_parent_conc_pgm_id IN NUMBER)
13339   IS
13340     SELECT /*+ INDEX(BUEWD AHL_BUE_WORKER_DATA_N1) */ BUEWD.rowid, BUEWD.csi_item_instance_id, BUEWD.object_version_number
13341     FROM ahl_bue_worker_data BUEWD
13342     WHERE BUEWD.parent_conc_request_id = p_parent_conc_pgm_id
13343       AND BUEWD.child_conc_request_id IS NULL;
13344     --FOR UPDATE OF child_conc_request_id;
13345 
13346  CURSOR bue_lock_row (p_rowid IN urowid, p_parent_conc_pgm_id IN NUMBER )
13347   IS
13348     SELECT rowid, csi_item_instance_id
13349     FROM ahl_bue_worker_data
13350     WHERE parent_conc_request_id = p_parent_conc_pgm_id
13351       AND child_conc_request_id IS NULL
13352       AND ROWID = p_rowid
13353     FOR UPDATE OF child_conc_request_id NOWAIT;
13354 
13355   l_instance_id  NUMBER;
13356 
13357   record_locked   EXCEPTION;
13358   pragma exception_init (record_locked, -54);
13359 
13360   l_status        NUMBER;
13361   l_rowid         UROWID;
13362   l_object_version_number  NUMBER;
13363 
13364 BEGIN
13365   IF G_debug = 'Y' THEN
13366      AHL_DEBUG_PUB.debug('Start Get_Next_BUE_Row: Parent Conc Request ID:' || p_parent_conc_pgm_id);
13367      AHL_DEBUG_PUB.debug('Child Conc Request ID:' || p_conc_child_req_id);
13368   END IF;
13369 
13370   --DBMS_LOCK.SLEEP(60);
13371 
13372   -- get next unprocessed row.
13373   OPEN ahl_bue_worker_csr(p_parent_conc_pgm_id);
13374   LOOP
13375      l_status := 0;
13376      BEGIN
13377         FETCH ahl_bue_worker_csr INTO l_rowid, l_instance_id, l_object_version_number;
13378         IF (ahl_bue_worker_csr%FOUND) THEN
13379             -- lock row
13380             OPEN bue_lock_row(l_rowid, p_parent_conc_pgm_id);
13381             FETCH bue_lock_row into l_rowid, l_instance_id;
13382             IF (bue_lock_row%FOUND) THEN
13383               -- update only if ovn remains the same.
13384               UPDATE ahl_bue_worker_data
13385               set child_conc_request_id = p_conc_child_req_id,
13386               last_update_date = sysdate,
13387               object_version_number = object_version_number + 1,
13388               last_update_login = fnd_global.login_id,
13389               last_updated_by = fnd_global.user_id
13390               WHERE ROWID = l_rowid
13391                 AND object_version_number = l_object_version_number;
13392                 --WHERE CURRENT OF ahl_bue_worker_csr;
13393 
13394               COMMIT WORK;
13395             ELSE
13396               l_status := 100;
13397               ROLLBACK;
13398             END IF;
13399             CLOSE bue_lock_row;
13400 
13401         ELSE
13402             l_instance_id := NULL;
13403             ROLLBACK;
13404         END IF;
13405       EXCEPTION
13406         WHEN record_locked THEN
13407           -- select next row.
13408           l_status := -54;
13409           ROLLBACK;
13410           IF (bue_lock_row%ISOPEN) THEN
13411              CLOSE bue_lock_row;
13412           END IF;
13413 
13414         WHEN NO_DATA_FOUND THEN
13415           -- select next row.
13416           l_status := 100;
13417           ROLLBACK;
13418           IF (bue_lock_row%ISOPEN) THEN
13419              CLOSE bue_lock_row;
13420           END IF;
13421 
13422         WHEN OTHERS THEN
13423           ROLLBACK;
13424           l_status := SQLCODE;
13425           errbuf := 'Get_Next_BUE_Row:' || substrb(sqlerrm,1,60);
13426           l_instance_id := NULL;
13427           x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
13428           IF (bue_lock_row%ISOPEN) THEN
13429              CLOSE bue_lock_row;
13430           END IF;
13431      END;
13432 
13433      IF (l_status = 0) THEN
13434         -- success or end of rows.
13435         EXIT;
13436      ELSIF (l_status <> -54 AND l_status <> 100) THEN
13437         EXIT;
13438      END IF;
13439 
13440   END LOOP; -- select next row.
13441 
13442   CLOSE ahl_bue_worker_csr;
13443   x_item_instance_id := l_instance_id;
13444 
13445   IF G_debug = 'Y' THEN
13446      AHL_DEBUG_PUB.debug('End Get_Next_BUE_Row: x_item_instance_id:' || x_item_instance_id);
13447   END IF;
13448 
13449 EXCEPTION
13450   WHEN OTHERS THEN
13451     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
13452     errbuf := 'AHL_UMP_ProcessUnit_Pvt.Process.Get_Next_BUE_Row:' || SUBSTR(SQLERRM,1,240);
13453     x_item_instance_id := NULL;
13454 
13455 END Get_Next_BUE_Row;
13456 
13457 ------------------------------------------------------------------
13458 -- Added for performance bug# 6893404.
13459 -- procedure deletes the worker data after processing is complete.
13460 PROCEDURE Cleanup_BUE_Worker(p_parent_conc_request_id IN  NUMBER,
13461                              p_child_conc_request_id  IN  NUMBER,
13462                              x_return_status          OUT NOCOPY VARCHAR2,
13463                              x_errbuf                 OUT NOCOPY VARCHAR2)
13464 IS
13465    PRAGMA AUTONOMOUS_TRANSACTION;
13466 
13467    CURSOR get_undeleted_parents(p_conc_request_id IN NUMBER) IS
13468      SELECT DISTINCT parent_conc_request_id
13469      FROM ahl_bue_worker_data
13470      WHERE parent_conc_request_id <> p_conc_request_id;
13471 
13472    CURSOR get_undeleted_child(p_conc_request_id IN NUMBER) IS
13473      SELECT DISTINCT child_conc_request_id
13474      FROM ahl_bue_worker_data
13475      WHERE parent_conc_request_id = p_conc_request_id
13476        AND child_conc_request_id IS NOT NULL;
13477 
13478    CURSOR lock_child_rows(p_parent_conc_id IN NUMBER,
13479                           p_child_conc_id  IN NUMBER) IS
13480      SELECT rowid
13481      FROM ahl_bue_worker_data
13482      WHERE parent_conc_request_id = p_parent_conc_id
13483        AND child_conc_request_id = p_child_conc_id
13484        FOR UPDATE OF object_version_number NOWAIT;
13485 
13486    CURSOR fnd_concur_csr(p_conc_req_id IN NUMBER) IS
13487     SELECT 'x'
13488     FROM fnd_concurrent_requests
13489     WHERE REQUEST_ID = p_conc_req_id;
13490 
13491    record_locked   EXCEPTION;
13492    pragma exception_init (record_locked, -54);
13493 
13494    l_req_status boolean;
13495    l_rphase     varchar2(80);
13496    l_rstatus    varchar2(80);
13497    l_dphase     varchar2(30);
13498    lc_dphase    varchar2(30);
13499    l_dstatus    varchar2(30);
13500    l_message    varchar2(240);
13501 
13502    l_buffer_limit number := 100;
13503 
13504    TYPE urowid_tbl_type IS TABLE OF urowid INDEX BY BINARY_INTEGER;
13505 
13506    l_rowid_tbl  urowid_tbl_type;
13507    l_junk       VARCHAR2(1);
13508 
13509 BEGIN
13510 
13511   IF G_debug = 'Y' THEN
13512      AHL_DEBUG_PUB.debug('Start Cleanup_BUE_Worker: Parent Conc Request ID:' || p_parent_conc_request_id);
13513      AHL_DEBUG_PUB.debug('Child Conc Request ID:' || p_child_conc_request_id);
13514   END IF;
13515 
13516   IF (p_parent_conc_request_id IS NULL) THEN
13517     RETURN; -- do nothing
13518   END IF;
13519 
13520   IF (p_child_conc_request_id IS NOT NULL) THEN
13521     G_DEBUG_LINE_NUM := 300;
13522     -- cleanup rows processed by this worker.
13523     DELETE from ahl_bue_worker_data
13524     WHERE parent_conc_request_id = p_parent_conc_request_id
13525       AND child_conc_request_id = p_child_conc_request_id ;
13526     COMMIT WORK;
13527   END IF;
13528 
13529   IF (p_child_conc_request_id IS NULL) OR
13530      (p_child_conc_request_id IS NOT NULL AND p_child_conc_request_id = p_parent_conc_request_id) THEN
13531     -- this routine is executed by parent conc request. Modified due to ORA-00054 errors reported
13532     -- when workers are deleting the rows.
13533 
13534     G_DEBUG_LINE_NUM := 310;
13535     -- cleanup any orphaned rows left from other parent requests.
13536     FOR undeleted_parent IN get_undeleted_parents(p_parent_conc_request_id) LOOP
13537        /* not needed - check only child conc request status
13538        -- check parent status.
13539        l_req_status := FND_CONCURRENT.GET_REQUEST_STATUS(request_id => undeleted_parent.parent_conc_request_id,
13540                                                          --appl_shortname => 'AHL',
13541                                                          --program   => 'AHLUEFF',
13542                                                          phase      => l_rphase,
13543                                                          status     => l_rstatus,
13544                                                          dev_phase  => l_dphase,
13545                                                          dev_status => l_dstatus,
13546                                                          message    => l_message);
13547        IF (l_req_status = TRUE) AND (l_dphase = 'COMPLETE' OR l_dphase IS NULL) THEN
13548        */
13549 
13550        G_DEBUG_LINE_NUM := 312;
13551        -- delete all rows where child conc request is NULL and when parent concurrent does not exist in fnd_concurrent_request table.
13552        OPEN fnd_concur_csr(undeleted_parent.parent_conc_request_id);
13553        FETCH fnd_concur_csr INTO l_junk;
13554        IF (fnd_concur_csr%NOTFOUND) THEN
13555          G_DEBUG_LINE_NUM := 315;
13556 
13557          DELETE FROM AHL_BUE_WORKER_DATA
13558          WHERE parent_conc_request_id = undeleted_parent.parent_conc_request_id
13559            AND child_conc_request_id IS NULL;
13560          COMMIT WORK;
13561        END IF;
13562        CLOSE fnd_concur_csr;
13563 
13564        FOR undeleted_child IN get_undeleted_child(undeleted_parent.parent_conc_request_id) LOOP
13565            G_DEBUG_LINE_NUM := 320;
13566            l_req_status := FND_CONCURRENT.GET_REQUEST_STATUS(request_id => undeleted_child.child_conc_request_id,
13567                                                              --appl_shortname => 'AHL',
13568                                                              --program   => 'AHLWUEFF',
13569                                                              phase      => l_rphase,
13570                                                              status     => l_rstatus,
13571                                                              dev_phase  => lc_dphase,
13572                                                              dev_status => l_dstatus,
13573                                                              message    => l_message);
13574            IF NOT(l_req_status) THEN
13575               -- check if request exists in fnd_concurrent_requests table
13576               OPEN fnd_concur_csr(undeleted_child.child_conc_request_id);
13577               FETCH fnd_concur_csr INTO l_junk;
13578               IF (fnd_concur_csr%NOTFOUND) THEN
13579                 G_DEBUG_LINE_NUM := 325;
13580                 l_req_status := TRUE;
13581                 lc_dphase := NULL;
13582               END IF;
13583               CLOSE fnd_concur_csr;
13584            END IF;
13585 
13586            IF (l_req_status = TRUE) AND (lc_dphase = 'COMPLETE' OR lc_dphase IS NULL) THEN
13587               G_DEBUG_LINE_NUM := 330;
13588 
13589               LOOP
13590                   -- lock and delete rows for undeleted_child.child_conc_request_id.
13591                   OPEN lock_child_rows(undeleted_parent.parent_conc_request_id,
13592                                        undeleted_child.child_conc_request_id);
13593                   G_DEBUG_LINE_NUM := 340;
13594                   FETCH lock_child_rows BULK COLLECT INTO l_rowid_tbl LIMIT l_buffer_limit;
13595                   --EXIT WHEN (l_rowid_tbl.count = 0);
13596                   IF (l_rowid_tbl.count = 0) THEN
13597                     ROLLBACK;
13598                     CLOSE lock_child_rows;
13599                     EXIT;
13600                   END IF;
13601 
13602                   G_DEBUG_LINE_NUM := 350;
13603 
13604                   BEGIN
13605                     SAVEPOINT lock_child_rows_upd_s;
13606                     FORALL j IN l_rowid_tbl.FIRST..l_rowid_tbl.LAST
13607                        -- delete for parent concurrent.
13608                        DELETE FROM ahl_bue_worker_data
13609                        WHERE rowid = l_rowid_tbl(j);
13610 
13611                     COMMIT;
13612                     --
13613                     EXCEPTION
13614                         WHEN OTHERS THEN
13615                           rollback to lock_child_rows_upd_s;
13616                           EXIT; -- abort delete for child.
13617                           -- dbms_output.put_line('Record Locked');
13618                   END;
13619 
13620                   l_rowid_tbl.delete;
13621                   CLOSE lock_child_rows;
13622 
13623               END LOOP;
13624               IF (lock_child_rows%ISOPEN) THEN
13625                 CLOSE lock_child_rows;
13626               END IF;
13627 
13628            END IF; -- l_req_status and lc_dphase
13629        END LOOP; -- undeleted_child IN
13630 
13631      --END IF; -- (l_dphase = 'COMPLETE')
13632     END LOOP; -- undeleted_parent IN
13633   END IF; -- p_child_conc_request_id IS NULL
13634 
13635   IF G_debug = 'Y' THEN
13636      AHL_DEBUG_PUB.debug('End Cleanup_BUE_Worker');
13637   END IF;
13638 
13639 EXCEPTION
13640   WHEN record_locked THEN
13641     IF (lock_child_rows%ISOPEN) THEN
13642       CLOSE lock_child_rows;
13643     END IF;
13644     ROLLBACK;
13645     -- dbms_output.put_line('Record Locked');
13646 
13647   WHEN OTHERS THEN
13648     ROLLBACK;
13649     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
13650     x_errbuf := 'AHL_UMP_ProcessUnit_Pvt.Process.Cleanup_BUE_Worker:line:' || G_DEBUG_LINE_NUM || ':' || SUBSTR(SQLERRM,1,240);
13651 
13652 END Cleanup_BUE_Worker;
13653 
13654 -- Added for performance bug# 6893404.
13655 PROCEDURE Populate_BUE_Worker_for_MR(p_conc_request_id IN  NUMBER,
13656                                      p_mr_header_id    IN  NUMBER,
13657                                      p_concurrent_flag IN  VARCHAR2,
13658                                      p_mtl_category_id IN  NUMBER,
13659                                      p_process_option  IN  VARCHAR2,
13660                                      x_return_status   OUT NOCOPY VARCHAR2)
13661 IS
13662   PRAGMA AUTONOMOUS_TRANSACTION;
13663 
13664   -- get item instances that are either components
13665   -- or a UC when no item category and process option = Units or Components or all.
13666   CURSOR get_inst_csr (p_mr_header_id IN NUMBER,
13667                        p_opt_uc       IN NUMBER) IS
13668     SELECT instance_id from
13669      (SELECT DISTINCT nvl(root_instance_id, instance_id) instance_id from
13670        (
13671         SELECT cii.instance_id,
13672               (select object_id from csi_ii_relationships parent
13673                where not exists (select 'x' from csi_ii_relationships
13674                                  where subject_id = parent.object_id and
13675                                  relationship_type_code = 'COMPONENT-OF' and
13676                                  trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) and
13677                                  trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
13678                start with parent.subject_id = cii.instance_id and
13679                parent.relationship_type_code = 'COMPONENT-OF' and
13680                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
13681                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
13682                connect by prior parent.object_id = parent.subject_id and
13683                parent.relationship_type_code = 'COMPONENT-OF' and
13684                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
13685                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
13686                ) Root_instance_id
13687 
13688         FROM csi_item_instances cii, ahl_mr_instances_temp mr
13689         WHERE trunc(nvl(cii.active_start_date, sysdate)) <= trunc(sysdate) AND
13690               trunc(sysdate) < trunc(nvl(cii.active_end_date, sysdate+1))
13691           AND mr.item_instance_id  = cii.instance_id
13692        )
13693      ) valid_inst
13694     WHERE (p_opt_uc = 1 AND exists (select 'x' from ahl_unit_config_headers
13695                                     where csi_item_instance_id = valid_inst.instance_id
13696                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
13697                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
13698                                       AND unit_config_status_code <> 'DRAFT'
13699                                       AND parent_uc_header_id IS NULL
13700                                    ) -- get UCs only.
13701           )
13702           OR
13703           -- get components.
13704           (p_opt_uc = 2 AND not exists (select 'x' from ahl_unit_config_headers
13705                                         where csi_item_instance_id = valid_inst.instance_id
13706                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
13707                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
13708                                           -- instance is a UC if in status draft.
13709                                           --AND unit_config_status_code <> 'DRAFT'
13710                                           --AND parent_uc_header_id IS NULL
13711                                        )
13712           )
13713           OR
13714           -- get all but do not select draft UCs as Process Unit will raise error.
13715           (p_opt_uc = 0 AND not exists (select 'x' from ahl_unit_config_headers
13716                                         where csi_item_instance_id = valid_inst.instance_id
13717                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
13718                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
13719                                           AND unit_config_status_code = 'DRAFT'
13720                                        )
13721           );
13722 
13723 
13724   -- get item instances when item category selected with process option of ALL, Units or Components.
13725   CURSOR get_itemcat_inst_csr (p_mr_header_id IN NUMBER,
13726                                p_mtl_category_id IN NUMBER,
13727                                p_opt_uc          IN NUMBER) IS
13728     SELECT instance_id from
13729      (SELECT DISTINCT nvl(root_instance_id, instance_id) instance_id from
13730        (
13731         SELECT cii.instance_id,
13732               (select object_id from csi_ii_relationships parent
13733                where not exists (select 'x' from csi_ii_relationships
13734                                  where subject_id = parent.object_id and
13735                                  relationship_type_code = 'COMPONENT-OF' and
13736                                  trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) and
13737                                  trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
13738                start with parent.subject_id = cii.instance_id and
13739                parent.relationship_type_code = 'COMPONENT-OF' and
13740                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
13741                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
13742                connect by prior parent.object_id = parent.subject_id and
13743                parent.relationship_type_code = 'COMPONENT-OF' and
13744                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
13745                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
13746                ) Root_instance_id
13747 
13748         FROM csi_item_instances cii,ahl_mr_instances_temp mr
13749         WHERE trunc(nvl(cii.active_start_date, sysdate)) <= trunc(sysdate) AND
13750               trunc(sysdate) < trunc(nvl(cii.active_end_date, sysdate+1))
13751           AND mr.item_instance_id  = cii.instance_id
13752        )
13753      ) valid_inst
13754     WHERE exists (select 'x'
13755                   from mtl_category_set_valid_cats cs, mtl_item_categories itc,
13756                        csi_item_instances cii2
13757                   where cs.category_set_id = fnd_profile.value('AHL_BUE_ITEM_CATEGORY_SET')
13758                     AND cs.category_set_id = itc.category_set_id
13759                     AND cs.category_id = itc.category_id
13760                     AND itc.category_id = p_mtl_category_id
13761                     AND cii2.instance_id = valid_inst.instance_id
13762                     AND itc.organization_id = cii2.inv_master_organization_id
13763                     AND itc.inventory_item_id = cii2.inventory_item_id
13764                   ) -- get root nodes matching item category.
13765       -- either UC or components.
13766       AND ((p_opt_uc = 1 AND exists (select 'x' from ahl_unit_config_headers
13767                                     where csi_item_instance_id = valid_inst.instance_id
13768                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
13769                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
13770                                       AND unit_config_status_code <> 'DRAFT'
13771                                       AND parent_uc_header_id IS NULL
13772                                    ) -- get UCs only.
13773           )
13774           OR
13775           -- get components.
13776           (p_opt_uc = 2 AND not exists (select 'x' from ahl_unit_config_headers
13777                                         where csi_item_instance_id = valid_inst.instance_id
13778                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
13779                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
13780                                           -- instance is a UC if in status draft.
13781                                           --AND unit_config_status_code <> 'DRAFT'
13782                                           --AND parent_uc_header_id IS NULL
13783                                        )
13784           )
13785           OR
13786           -- when process option is ALL. Ignore Draft UC's
13787           (p_opt_uc = 0 AND not exists (select 'x' from ahl_unit_config_headers
13788                                         where csi_item_instance_id = valid_inst.instance_id
13789                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
13790                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
13791                                           AND unit_config_status_code = 'DRAFT'
13792                                        )
13793           )
13794           );
13795 
13796 
13797   -- get UEs for the MR that are not existing in BUE worker table.
13798   CURSOR get_extra_ue_na(p_mr_header_id IN NUMBER,
13799                          p_conc_request_id IN NUMBER)  IS
13800     SELECT csi_item_instance_id
13801     FROM (
13802           SELECT DISTINCT nvl(Root_instance_id, csi_item_instance_id) csi_item_instance_id
13803           FROM (
13804                 SELECT DISTINCT UE.csi_item_instance_id,
13805                                 (select object_id from csi_ii_relationships parent
13806                                  where not exists (select 'x' from csi_ii_relationships
13807                                                    where subject_id = parent.object_id and
13808                                                    trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
13809                                  start with parent.subject_id = UE.CSI_ITEM_INSTANCE_ID and
13810                                  parent.relationship_type_code = 'COMPONENT-OF' and
13811                                  trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
13812                                  trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
13813                                  connect by prior parent.object_id = parent.subject_id and
13814                                  parent.relationship_type_code = 'COMPONENT-OF' and
13815                                  trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
13816                                  trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
13817                                 ) Root_instance_id
13818 
13819                 FROM  ahl_unit_effectivities_app_v UE
13820                 WHERE UE.mr_header_id = p_mr_header_id
13821                   AND (UE.status_code IS NULL OR UE.status_code IN ('INIT-DUE','EXCEPTION'))
13822                   AND  NOT EXISTS (Select 1
13823                                    FROM ahl_mr_instances_temp
13824                                    WHERE item_instance_id = ue.csi_item_instance_id)
13825                                   )
13826          ) valid_inst
13827     WHERE NOT EXISTS (Select 1
13828                       FROM AHL_BUE_WORKER_DATA
13829                       WHERE csi_item_instance_id = valid_inst.csi_item_instance_id
13830                         AND parent_conc_request_id = p_conc_request_id) ;
13831 
13832   l_relationship_tbl  nbr_tbl_type;
13833   l_instance_id_tbl   nbr_tbl_type;
13834 
13835   l_opt           number;
13836   l_opt_uc        number;
13837 
13838   l_buffer_limit  number := 1000;
13839 
13840   l_api_version   number := 1.0;
13841   l_msg_count     number;
13842   l_msg_data      varchar2(4000);
13843 
13844   dml_errors EXCEPTION;
13845   PRAGMA EXCEPTION_INIT(dml_errors, -24381);
13846 
13847   l_mr_item_instances_tbl  AHL_FMP_PVT.MR_ITEM_INSTANCE_TBL_TYPE;
13848 
13849 BEGIN
13850 
13851   IF G_debug = 'Y' THEN
13852      AHL_DEBUG_PUB.debug('Start Populate_BUE_Worker_for_MR: Input MR Header ID:' || p_mr_header_id);
13853      AHL_DEBUG_PUB.debug('Input Concurrent Flag:' || p_conc_request_id);
13854      AHL_DEBUG_PUB.debug('Input Conc Request ID:' || p_concurrent_flag);
13855   END IF;
13856 
13857   -- initialize return status.
13858   x_return_status := FND_API.G_RET_STS_SUCCESS;
13859 
13860   -- get instances applicable to the MR.
13861   -- this API will insert the applicable MRs into temp table ahl_mr_instances_temp
13862   AHL_FMP_PVT.GET_MR_AFFECTED_ITEMS (
13863          p_api_version => 1.0,
13864          p_init_msg_list => FND_API.G_TRUE,
13865          x_return_status => x_return_status,
13866          x_msg_count     => l_msg_count,
13867          x_msg_data      => l_msg_data,
13868          p_mr_header_id  => p_mr_header_id,
13869          p_top_node_flag => 'N',
13870          p_unique_inst_flag => 'Y',
13871          -- JKJain, NR Analysis and Forecasting
13872          p_consider_fleet_flag  => 'N',
13873          x_mr_item_inst_tbl => l_mr_item_instances_tbl );
13874 
13875   IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
13876     ROLLBACK;
13877     RETURN;
13878   END IF;
13879 
13880 
13881   IF (p_process_option = 'AHL_BUE_ALL_COMPONENTS') THEN
13882      l_opt_uc := 2;
13883   ELSIF (p_process_option = 'AHL_BUE_ALL_UNITS') THEN
13884      l_opt_uc := 1;
13885   ELSE
13886      l_opt_uc := 0;  -- when null or input is AHL_BUE_ALL
13887   END IF;
13888 
13889   -- process effectivity
13890   IF (p_mtl_category_id IS NULL) THEN
13891       OPEN get_inst_csr(p_mr_header_id, l_opt_uc);
13892   ELSE
13893       OPEN get_itemcat_inst_csr(p_mr_header_id, p_mtl_category_id, l_opt_uc);
13894   END IF;
13895 
13896   LOOP
13897       IF (p_mtl_category_id IS NULL) THEN
13898           FETCH get_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13899       ELSE
13900           FETCH get_itemcat_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13901       END IF;
13902 
13903       EXIT WHEN (l_instance_id_tbl.count = 0);
13904 
13905       BEGIN
13906         -- insert into BUE table.
13907         FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST SAVE EXCEPTIONS
13908           INSERT INTO AHL_BUE_WORKER_DATA
13909           (parent_conc_request_id,
13910            csi_item_instance_id,
13911            child_conc_request_id,
13912            last_update_date,
13913            last_updated_by,
13914            creation_date,
13915            created_by,
13916            last_update_login,
13917            object_version_number) VALUES
13918            (p_conc_request_id,
13919             l_instance_id_tbl(instance_indx),
13920             null,
13921             sysdate,
13922             fnd_global.user_id,
13923             sysdate,
13924             fnd_global.user_id,
13925             fnd_global.conc_login_id,
13926             1);
13927 
13928         EXCEPTION
13929           WHEN DML_ERRORS THEN
13930             IF (get_inst_csr%ISOPEN) THEN
13931               CLOSE get_inst_csr;
13932             END IF;
13933             IF (get_itemcat_inst_csr%ISOPEN) THEN
13934               CLOSE get_itemcat_inst_csr;
13935             END IF;
13936 
13937             x_return_status := 'E';
13938 
13939             IF (p_concurrent_flag = 'Y') THEN
13940               fnd_file.put_line(fnd_file.log, 'Following error(s) occured while inserting into table ahl_bue_worker_data');
13941               FOR j IN 1..sql%bulk_exceptions.count
13942               LOOP
13943                 fnd_file.put_line(fnd_file.log, sql%bulk_exceptions(j).error_index || ', ' ||
13944                 sqlerrm(-sql%bulk_exceptions(j).error_code) );
13945               END LOOP;
13946             END IF;
13947 
13948             FND_MESSAGE.set_name('AHL', 'AHL_UMP_BUE_WORKER_ERR');
13949             FND_MSG_PUB.add;
13950 
13951             RETURN;
13952         END;
13953 
13954         l_instance_id_tbl.DELETE;
13955 
13956   END LOOP;
13957 
13958   IF (p_mtl_category_id IS NULL) THEN
13959      CLOSE get_inst_csr;
13960   ELSE
13961      CLOSE get_itemcat_inst_csr;
13962   END IF;
13963 
13964   l_instance_id_tbl.DELETE;
13965 
13966   -- process extra UE instances
13967   OPEN get_extra_ue_na(p_mr_header_id, p_conc_request_id);
13968   LOOP
13969     FETCH get_extra_ue_na BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
13970     EXIT WHEN (l_instance_id_tbl.COUNT = 0);
13971     BEGIN
13972       -- insert into BUE table.
13973       FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST SAVE EXCEPTIONS
13974         INSERT INTO AHL_BUE_WORKER_DATA
13975           (parent_conc_request_id,
13976            csi_item_instance_id,
13977            child_conc_request_id,
13978            last_update_date,
13979            last_updated_by,
13980            creation_date,
13981            created_by,
13982            last_update_login,
13983            object_version_number) VALUES
13984            (p_conc_request_id,
13985             l_instance_id_tbl(instance_indx),
13986             null,
13987             sysdate,
13988             fnd_global.user_id,
13989             sysdate,
13990             fnd_global.user_id,
13991             fnd_global.conc_login_id,
13992             1);
13993 
13994     EXCEPTION
13995       WHEN DML_ERRORS THEN
13996 
13997         IF (get_extra_ue_na%ISOPEN) THEN
13998           CLOSE get_extra_ue_na;
13999         END IF;
14000         x_return_status := 'E';
14001 
14002         IF (p_concurrent_flag = 'Y') THEN
14003           fnd_file.put_line(fnd_file.log, 'Following error(s) occured while inserting into table ahl_bue_worker_data');
14004           FOR j IN 1..sql%bulk_exceptions.count
14005           LOOP
14006             fnd_file.put_line(fnd_file.log, sql%bulk_exceptions(j).error_index || ', ' ||
14007             sqlerrm(-sql%bulk_exceptions(j).error_code) );
14008           END LOOP;
14009         END IF;
14010 
14011         FND_MESSAGE.set_name('AHL', 'AHL_UMP_BUE_WORKER_ERR');
14012         FND_MSG_PUB.add;
14013 
14014         RETURN;
14015       END;
14016 
14017       l_instance_id_tbl.DELETE;
14018 
14019   END LOOP;
14020   CLOSE get_extra_ue_na;
14021 
14022   -- delete duplicate rows.
14023   /* fix for performance bug# 16003176 (10g to 11g upgrade)
14024   DELETE FROM ahl_bue_worker_data
14025   WHERE parent_conc_request_id = p_conc_request_id
14026     AND rowid not in (SELECT MIN(rowid)
14027                       FROM ahl_bue_worker_data
14028                       WHERE parent_conc_request_id = p_conc_request_id
14029                       GROUP BY csi_item_instance_id, parent_conc_request_id) ;
14030   */
14031 
14032   --DELETE FROM ahl_bue_worker_data wrk1
14033   --WHERE wrk1.parent_conc_request_id = p_conc_request_id
14034   --  AND wrk1.rowid > ANY ( SELECT wrk2.rowid
14035   --                         FROM ahl_bue_worker_data wrk2
14036   --                         WHERE wrk2.parent_conc_request_id = p_conc_request_id
14037   --                           AND wrk2.csi_item_instance_id = wrk1.csi_item_instance_id) ;
14038 
14039   --DELETE FROM ahl_bue_worker_data ad1
14040   --WHERE ad1.parent_conc_request_id = p_conc_request_id
14041   --  AND ad1.rowid not in (SELECT /*+ UNNEST  INDEX(ad2 AHL_BUE_WORKER_DATA_N2) */ MIN(ad2.rowid)
14042   --                    FROM ahl_bue_worker_data ad2
14043   --                    WHERE ad2.parent_conc_request_id = p_conc_request_id
14044   --                    GROUP BY ad2.csi_item_instance_id, ad2.parent_conc_request_id) ;
14045 
14046   --delete /*+ rowid(a) use_nl(a) */
14047   -- from ahl_bue_worker_data a
14048   -- where rowid in
14049   --  (select /*+ unnest */ rowid
14050   --    from
14051   --       (select /*+ parallel(b) cardinality(b,10) */
14052   --          rowid, row_number() over (partition by
14053   --              csi_item_instance_id, parent_conc_request_id
14054   --          order by 1
14055   --          ) dup
14056   --          from ahl_bue_worker_data b
14057   --          where b.parent_conc_request_id = p_conc_request_id)
14058   --  where dup > 1);
14059 
14060   DELETE /*+ parallel(a) */ FROM ahl_bue_worker_data a
14061    where  a.parent_conc_request_id = p_conc_request_id
14062    and exists (select 'x' from ahl_bue_worker_data b
14063                 where b.parent_conc_request_id = a.parent_conc_request_id
14064                   and b.csi_item_instance_id = a.csi_item_instance_id
14065                   and b.rowid      > a.rowid);
14066 
14067 
14068   -- save changes.
14069   COMMIT WORK;
14070 
14071   IF G_debug = 'Y' THEN
14072     AHL_DEBUG_PUB.debug('End Populate_BUE_Worker_for_MR: x_return_status:' || x_return_status);
14073   END IF;
14074 
14075 END Populate_BUE_Worker_for_MR;
14076 
14077 -- Added for performance bug# 6893404.
14078 FUNCTION get_latest_ctr_reading(p_counter_id IN NUMBER) RETURN NUMBER
14079 IS
14080 
14081   -- get net reading.
14082   CURSOR get_ctr_reading_csr (p_counter_id IN NUMBER) IS
14083      SELECT * FROM
14084         (SELECT net_reading
14085          FROM csi_counter_readings
14086          WHERE counter_id = p_counter_id
14087            AND nvl(disabled_flag,'N') = 'N'
14088          ORDER BY value_timestamp desc)
14089      WHERE rownum < 2;
14090 
14091   l_net_reading NUMBER;
14092 
14093 BEGIN
14094 
14095   OPEN get_ctr_reading_csr(p_counter_id);
14096   FETCH get_ctr_reading_csr INTO l_net_reading;
14097   IF (get_ctr_reading_csr%NOTFOUND) THEN
14098      l_net_reading := 0;
14099   END IF;
14100   CLOSE get_ctr_reading_csr;
14101 
14102   RETURN l_net_reading;
14103 
14104 END get_latest_ctr_reading;
14105 ----
14106 
14107 -- procedure checks if forecast exists for all of instance's UOM and adds
14108 -- zero forecast row if missing forecast.
14109 PROCEDURE validate_uf_for_ctr(p_current_usage_tbl       IN counter_values_tbl_type,
14110                               p_x_forecast_details_tbl  IN OUT NOCOPY forecast_details_tbl_type)
14111 IS
14112   l_last_index  NUMBER;
14113   l_uom_found_flag BOOLEAN;
14114 
14115 BEGIN
14116 
14117   IF G_DEBUG = 'Y' THEN
14118      AHL_DEBUG_PUB.debug ('Start validate_uf_for_ctr');
14119   END IF;
14120 
14121   l_last_index := p_x_forecast_details_tbl.LAST + 1;
14122 
14123   IF (p_current_usage_tbl.COUNT > 0) THEN
14124     FOR j IN p_current_usage_tbl.FIRST..p_current_usage_tbl.LAST LOOP
14125        l_uom_found_flag := FALSE;
14126        IF (p_x_forecast_details_tbl.COUNT > 0) THEN
14127          FOR i IN p_x_forecast_details_tbl.FIRST..p_x_forecast_details_tbl.LAST LOOP
14128            IF (p_x_forecast_details_tbl(i).uom_code = p_current_usage_tbl(j).uom_code) THEN
14129              l_uom_found_flag := TRUE;
14130              EXIT;
14131            END IF;
14132          END LOOP;  -- i
14133 
14134          IF (l_uom_found_flag = FALSE) THEN
14135             p_x_forecast_details_tbl(l_last_index).uom_code := p_current_usage_tbl(j).uom_code;
14136             p_x_forecast_details_tbl(l_last_index).start_date := trunc(sysdate);
14137             p_x_forecast_details_tbl(l_last_index).end_date := NULL;
14138             p_x_forecast_details_tbl(l_last_index).usage_per_day := 0;
14139 
14140             l_last_index := l_last_index + 1;
14141          END IF;
14142        END IF;
14143 
14144     END LOOP; -- j
14145   END IF; -- p_current_usage_tbl.COUNT
14146 
14147   IF G_DEBUG = 'Y' THEN
14148      AHL_DEBUG_PUB.debug ('Count on forecast_details' || p_x_forecast_details_tbl.COUNT);
14149 
14150      IF (p_x_forecast_details_tbl.COUNT > 0) THEN
14151        FOR i IN p_x_forecast_details_tbl.FIRST..p_x_forecast_details_tbl.LAST LOOP
14152              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Uom_Code' || p_x_forecast_details_tbl(i).uom_code);
14153              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Start Date' || p_x_forecast_details_tbl(i).start_date);
14154              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') End Date' || p_x_forecast_details_tbl(i).end_date);
14155              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Usage' || p_x_forecast_details_tbl(i).usage_per_day);
14156        END LOOP;
14157      END IF;
14158      AHL_DEBUG_PUB.debug ('End validate_uf_for_ctr');
14159   END IF;
14160 
14161 END validate_uf_for_ctr;
14162 --------------------------------------------------------------
14163 -- Added to fix bug# 9263774
14164 -- Process prior MR versions.
14165 PROCEDURE Process_Prior_MR_Version (p_applicable_mrs_rec  IN applicable_mrs_rec_type,
14166                                     p_new_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE,
14167                                     p_unit_effectivity_tbl IN unit_effectivity_tbl_type,
14168                                     p_old_UE_forecast_sequence IN NUMBER)
14169 IS
14170 
14171   -- for reading unit effectivity table.
14172   CURSOR ahl_ue_relns_csr ( p_unit_effectivity_id IN NUMBER ) IS
14173     SELECT ue_id, related_ue_id
14174     FROM ahl_ue_relationships relns
14175     START WITH ue_id = p_unit_effectivity_id AND
14176                relationship_code = 'PARENT'
14177     CONNECT BY PRIOR related_ue_id = ue_id AND
14178                originator_ue_id = p_unit_effectivity_id AND
14179                relationship_code = 'PARENT'
14180     ORDER BY   level;
14181 
14182   -- get related unit effectivities details.
14183   CURSOR ahl_ue_csr ( p_ue_id IN NUMBER,
14184                       p_related_ue_id IN NUMBER ) IS
14185     SELECT ue1.mr_header_id, ue1.csi_item_instance_id,
14186            ue2.mr_header_id related_mr_header_id,
14187            ue2.csi_item_instance_id related_csi_item_instance_id
14188     --FROM ahl_unit_effectivities_app_v ue1, ahl_unit_effectivities_app_v ue2
14189     FROM ahl_unit_effectivities_b ue1, ahl_unit_effectivities_b ue2
14190     WHERE ue1.unit_effectivity_id = p_ue_id AND
14191           ue2.unit_effectivity_id = p_related_ue_id;
14192 
14193 
14194   -- To check if mr has a preceding mr.
14195   CURSOR ahl_appl_mr_csr (p_item_instance_id IN NUMBER,
14196                           p_mr_header_id IN NUMBER) IS
14197    SELECT 'x'
14198    FROM ahl_applicable_mrs
14199    WHERE csi_item_instance_id = p_item_instance_id AND
14200          mr_header_id = p_mr_header_id AND
14201          implement_status_code <> 'OPTIONAL_DO_NOT_IMPLEMENT' AND
14202          --preceding_mr_header_id IS NOT NULL;
14203          accomplish_trigger_type = 'INITIATED_BY';
14204 
14205   l_new_unit_effectivity_rec  ahl_temp_unit_effectivities%ROWTYPE;
14206   l_initialize_ue_rec         ahl_temp_unit_effectivities%ROWTYPE;
14207 
14208   l_junk  VARCHAR2(1);
14209   l_visit_end_date DATE;
14210 
14211   l_visit_status    VARCHAR2(30);
14212 
14213   -- Added for bug# 9263774
14214   l_top_node_mr_id  NUMBER;
14215   l_top_node_ue_id  NUMBER;
14216   l_group_flag      BOOLEAN;
14217 
14218   l_mr_header_id                  NUMBER;
14219   l_csi_item_instance_id          NUMBER;
14220   l_related_mr_header_id          NUMBER;
14221   l_related_csi_item_instance_id  NUMBER;
14222 
14223   -- group UE check.
14224   CURSOR chk_grp_mr(p_ue_id IN NUMBER) IS
14225     SELECT 'x'
14226     FROM ahl_ue_relationships
14227     WHERE originator_ue_id = p_ue_id;
14228 
14229   -- Added for SB Enh.
14230   -- for prior MR, retain accomplishment trigger details.
14231   CURSOR get_accomplish_trig_dtls(p_unit_effectivity_id in number) IS
14232     SELECT accomplish_trigger_type, loop_chain_seq_num, start_lc_ue_id
14233     FROM ahl_unit_effectivities_b
14234     WHERE unit_effectivity_id = p_unit_effectivity_id;
14235 
14236 
14237 BEGIN
14238 
14239   IF G_DEBUG = 'Y' THEN
14240      AHL_DEBUG_PUB.Debug('Start Process Prior MR');
14241   END IF;
14242 
14243   -- initialize - needed for preceding MR info.
14244   l_new_unit_effectivity_rec := p_new_unit_effectivity_rec;
14245 
14246   -- update the temp table record for orig MR with visit_end_date and unit_effectivity ID.
14247   -- get visit end date from unit_effectivity_tbl for l_old_UE_Forecast_sequence.
14248   l_visit_end_date := p_unit_effectivity_tbl(p_old_UE_forecast_sequence).visit_end_date;
14249   l_new_unit_effectivity_rec.unit_effectivity_id :=
14250                         p_unit_effectivity_tbl(p_old_UE_forecast_sequence).unit_effectivity_id;
14251 
14252   -- construct temporary unit effectivity for top node.
14253 
14254   l_new_unit_effectivity_rec.due_date := p_new_unit_effectivity_rec.due_date;
14255   l_new_unit_effectivity_rec.mr_interval_id := p_new_unit_effectivity_rec.mr_interval_id;
14256   l_new_unit_effectivity_rec.mr_effectivity_id := p_new_unit_effectivity_rec.mr_effectivity_id;
14257   l_new_unit_effectivity_rec.due_counter_value := p_new_unit_effectivity_rec.due_counter_value;
14258   l_new_unit_effectivity_rec.csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
14259   IF (p_applicable_mrs_rec.expired_mr_flag = 'Y') THEN
14260     l_new_unit_effectivity_rec.mr_header_id := p_applicable_mrs_rec.mr_header_id;
14261   ELSE
14262     l_new_unit_effectivity_rec.mr_header_id := p_unit_effectivity_tbl(p_old_UE_forecast_sequence).prior_mr_header_id;
14263   END IF;
14264 
14265   l_new_unit_effectivity_rec.repetitive_mr_flag := p_new_unit_effectivity_rec.repetitive_mr_flag;
14266   l_new_unit_effectivity_rec.visit_end_date := l_visit_end_date;
14267   l_new_unit_effectivity_rec.forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
14268 
14269 
14270   -- find out if this is a group MR.
14271   OPEN chk_grp_mr(l_new_unit_effectivity_rec.unit_effectivity_id);
14272   FETCH chk_grp_mr INTO l_junk;
14273   IF (chk_grp_mr%FOUND) THEN
14274      l_group_flag := TRUE;
14275   ELSE
14276      l_group_flag := FALSE;
14277   END IF;
14278   CLOSE chk_grp_mr;
14279 
14280 
14281   IF (l_group_flag) THEN
14282     -- to indicate group.
14283    l_new_unit_effectivity_rec.orig_csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
14284 
14285    -- modified orig_mr_header_id for bug# 9263774
14286    l_new_unit_effectivity_rec.orig_mr_header_id := l_new_unit_effectivity_rec.mr_header_id;
14287    l_new_unit_effectivity_rec.orig_forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
14288   END IF;
14289 
14290   -- Added for ER# 2636001.
14291   l_new_unit_effectivity_rec.earliest_due_date := p_new_unit_effectivity_rec.earliest_due_date;
14292   l_new_unit_effectivity_rec.latest_due_date := p_new_unit_effectivity_rec.latest_due_date;
14293   l_new_unit_effectivity_rec.counter_id := p_new_unit_effectivity_rec.counter_id;
14294 
14295   l_new_unit_effectivity_rec.tolerance_flag := p_new_unit_effectivity_rec.tolerance_flag;
14296   l_new_unit_effectivity_rec.tolerance_before := p_new_unit_effectivity_rec.tolerance_before;
14297   l_new_unit_effectivity_rec.tolerance_after := p_new_unit_effectivity_rec.tolerance_after;
14298 
14299   -- Added for SB Enh
14300   OPEN get_accomplish_trig_dtls(l_new_unit_effectivity_rec.unit_effectivity_id);
14301   FETCH get_accomplish_trig_dtls INTO l_new_unit_effectivity_rec.accomplish_trigger_type, l_new_unit_effectivity_rec.loop_chain_seq_num,
14302                                       l_new_unit_effectivity_rec.start_lc_ue_id;
14303   CLOSE get_accomplish_trig_dtls;
14304   l_new_unit_effectivity_rec.start_mr_header_id := l_new_unit_effectivity_rec.mr_header_id;
14305   -- End SB Enh
14306 
14307   -- write into temp table.
14308   Create_temp_unit_effectivity(l_new_unit_effectivity_rec);
14309 
14310   l_top_node_mr_id := l_new_unit_effectivity_rec.mr_header_id;
14311   l_top_node_ue_id := l_new_unit_effectivity_rec.unit_effectivity_id;
14312 
14313   IF (l_group_flag) THEN
14314     -- Read UE tree and apply details from p_next_due_rec_type.
14315     FOR l_ue_relns_rec IN ahl_ue_relns_csr(l_top_node_ue_id) LOOP
14316       OPEN ahl_ue_csr(l_ue_relns_rec.ue_id, l_ue_relns_rec.related_ue_id);
14317       FETCH ahl_ue_csr INTO l_mr_header_id,
14318                             l_csi_item_instance_id,
14319                             l_related_mr_header_id,
14320                             l_related_csi_item_instance_id;
14321       IF (ahl_ue_csr%NOTFOUND) THEN
14322            FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_RELN_NOTFOUND');
14323            FND_MESSAGE.Set_Token('UE_ID',l_ue_relns_rec.ue_id);
14324            FND_MESSAGE.Set_Token('RELATED_UE_ID', l_ue_relns_rec.related_ue_id);
14325            FND_MSG_PUB.ADD;
14326            CLOSE ahl_ue_csr;
14327            RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
14328       END IF;
14329       CLOSE ahl_ue_csr;
14330 
14331       l_new_unit_effectivity_rec := l_initialize_ue_rec;
14332 
14333       -- Build temp_unit_effectivity record and write into temporary table.
14334 
14335       l_new_unit_effectivity_rec.due_date := p_new_unit_effectivity_rec.due_date;
14336       l_new_unit_effectivity_rec.mr_interval_id := p_new_unit_effectivity_rec.mr_interval_id;
14337       l_new_unit_effectivity_rec.mr_effectivity_id := p_new_unit_effectivity_rec.mr_effectivity_id;
14338       l_new_unit_effectivity_rec.due_counter_value := p_new_unit_effectivity_rec.due_counter_value;
14339       l_new_unit_effectivity_rec.csi_item_instance_id := l_related_csi_item_instance_id;
14340       l_new_unit_effectivity_rec.parent_csi_item_instance_id := l_csi_item_instance_id;
14341       l_new_unit_effectivity_rec.mr_header_id := l_related_mr_header_id;
14342       l_new_unit_effectivity_rec.parent_mr_header_id := l_mr_header_id;
14343       l_new_unit_effectivity_rec.orig_csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
14344       l_new_unit_effectivity_rec.orig_mr_header_id := l_top_node_mr_id;
14345       l_new_unit_effectivity_rec.orig_forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
14346       l_new_unit_effectivity_rec.repetitive_mr_flag := p_new_unit_effectivity_rec.repetitive_mr_flag;
14347       l_new_unit_effectivity_rec.visit_end_date := l_visit_end_date;
14348       l_new_unit_effectivity_rec.earliest_due_date := p_new_unit_effectivity_rec.earliest_due_date;
14349       l_new_unit_effectivity_rec.latest_due_date := p_new_unit_effectivity_rec.latest_due_date;
14350       l_new_unit_effectivity_rec.counter_id := p_new_unit_effectivity_rec.counter_id;
14351 
14352       l_new_unit_effectivity_rec.tolerance_flag := p_new_unit_effectivity_rec.tolerance_flag;
14353       l_new_unit_effectivity_rec.tolerance_before := p_new_unit_effectivity_rec.tolerance_before;
14354       l_new_unit_effectivity_rec.tolerance_after := p_new_unit_effectivity_rec.tolerance_after;
14355 
14356       l_new_unit_effectivity_rec.unit_effectivity_id := null;
14357 
14358       -- check if this mr has a preceding mr.
14359       OPEN ahl_appl_mr_csr (l_related_csi_item_instance_id,
14360                             l_related_mr_header_id);
14361       FETCH ahl_appl_mr_csr INTO l_junk;
14362       IF (ahl_appl_mr_csr%FOUND) THEN
14363          l_new_unit_effectivity_rec.preceding_check_flag:= 'Y';
14364       ELSE
14365          l_new_unit_effectivity_rec.preceding_check_flag:= 'N';
14366       END IF;
14367       CLOSE ahl_appl_mr_csr;
14368 
14369       -- write into temp table.
14370       Create_temp_unit_effectivity(l_new_unit_effectivity_rec);
14371 
14372     END LOOP;
14373 
14374   END IF;
14375 
14376 
14377   IF G_DEBUG = 'Y' THEN
14378      AHL_DEBUG_PUB.Debug('End Process PriorMR');
14379   END IF;
14380 
14381 
14382 END Process_Prior_MR_Version;
14383 ----------------------------------------------------
14384 
14385 -- Get applicability for expired MRs.
14386 -- Added to fix bug# 9263774
14387 PROCEDURE Process_Appl_Expired_MRs
14388 IS
14389 
14390   CURSOR get_mr_csr(p_item_instance_id IN NUMBER) IS
14391     SELECT csi_item_instance_id, (select mr_header_id from ahl_mr_headers_b mr
14392                                   where mr.title = exp_mr.title
14393                                   and mr.version_number = exp_mr.version_number) mr_header_id
14394     FROM
14395     (
14396       SELECT ue.csi_item_instance_id,
14397            mr.Title,
14398            max(mr.version_number) version_number
14399       FROM ahl_unit_effectivities_app_v UE, ahl_mr_headers_b mr
14400       -- pick up only top nodes.
14401       WHERE ue.mr_header_id = mr.mr_header_id
14402       AND NOT EXISTS (SELECT 'x'
14403                       FROM ahl_ue_relationships uer
14404                       WHERE uer.related_ue_id = ue.unit_effectivity_id
14405                         AND relationship_code = 'PARENT')
14406       -- not applicable
14407       AND NOT EXISTS (SELECT 'x'
14408                       FROM ahl_applicable_mrs aamr, ahl_mr_headers_b mr1
14409                       WHERE aamr.csi_item_instance_id = ue.csi_item_instance_id
14410                         AND aamr.mr_header_id = mr1.mr_header_id
14411                         AND mr1.title = mr.title
14412                       )
14413       AND ue.csi_item_instance_id = p_item_instance_id
14414       AND nvl(ue.manually_planned_flag,'N') = 'N'
14415       AND ue.object_type = 'MR'
14416       AND ue.defer_from_ue_id IS NULL
14417       AND (ue.status_code IS NULL OR ue.status_code = 'INIT-DUE')
14418       AND mr.effective_to < sysdate
14419       GROUP BY UE.csi_item_instance_id, mr.Title
14420      ) exp_mr;
14421 
14422   l_inst_id_tbl       nbr_tbl_type;
14423   l_mr_id_tbl         nbr_tbl_type;
14424 
14425   l_return_status   VARCHAR2(1);
14426   l_msg_count       NUMBER;
14427   l_msg_data        VARCHAR2(2000);
14428 
14429   l_appl_mrs_tbl    AHL_FMP_PVT.applicable_mr_tbl_type;
14430 
14431 BEGIN
14432 
14433   IF G_config_node_tbl.COUNT > 0 THEN
14434      FOR i IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
14435        IF G_DEBUG = 'Y' THEN
14436          AHL_DEBUG_PUB.debug('Processing for..:' || G_config_node_tbl(i).csi_item_instance_id );
14437        END IF;
14438 
14439        OPEN get_mr_csr (G_config_node_tbl(i).csi_item_instance_id);
14440 
14441        LOOP
14442          FETCH get_mr_csr BULK COLLECT INTO l_inst_id_tbl, l_mr_id_tbl LIMIT 1000;
14443          EXIT WHEN l_inst_id_tbl.count = 0;
14444 
14445          FOR j IN l_mr_id_tbl.FIRST..l_mr_id_tbl.LAST LOOP
14446            -- call FMP API to get MR effectivities
14447            AHL_FMP_PVT.GET_MR_APPLICABILITY(p_api_version => 1.0,
14448                                             p_init_msg_list => FND_API.G_FALSE,
14449                                             p_validation_level => FND_API.G_VALID_LEVEL_FULL,
14450                                             x_return_status => l_return_status,
14451                                             x_msg_count     => l_msg_count,
14452                                             x_msg_data      => l_msg_data,
14453                                             p_item_instance_id => G_config_node_tbl(i).csi_item_instance_id,
14454                                             p_mr_header_id     => l_mr_id_tbl(j),
14455                                             p_components_flag  => 'N',
14456                                             p_include_doNotImplmt => 'Y',
14457                                             x_applicable_mr_tbl   => l_appl_mrs_tbl);
14458 
14459 
14460            -- Raise errors if exceptions occur
14461            IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
14462              RAISE FND_API.G_EXC_ERROR;
14463            ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
14464              RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
14465            END IF;
14466 
14467            -- Populate temporary table ahl_applicable_mrs.
14468            IF (l_appl_mrs_tbl.COUNT > 0) THEN
14469               FOR i IN l_appl_mrs_tbl.FIRST..l_appl_mrs_tbl.LAST LOOP
14470                  INSERT INTO AHL_APPLICABLE_MRS (
14471                      CSI_ITEM_INSTANCE_ID,
14472                      MR_HEADER_ID,
14473                      MR_EFFECTIVITY_ID,
14474                      REPETITIVE_FLAG   ,
14475                      SHOW_REPETITIVE_CODE,
14476                      COPY_ACCOMPLISHMENT_CODE,
14477                      PRECEDING_MR_HEADER_ID,
14478                      IMPLEMENT_STATUS_CODE,
14479                      DESCENDENT_COUNT,
14480                      PROCESS_STATUS_FLAG,
14481                      PROCESSING_ORDER
14482                      )
14483                  VALUES (
14484                      l_appl_mrs_tbl(i).item_instance_id,
14485                      l_appl_mrs_tbl(i).mr_header_id,
14486                      l_appl_mrs_tbl(i).mr_effectivity_id,
14487                      l_appl_mrs_tbl(i).repetitive_flag,
14488                      l_appl_mrs_tbl(i).show_repetitive_code,
14489                      l_appl_mrs_tbl(i).copy_accomplishment_flag,
14490                      l_appl_mrs_tbl(i).preceding_mr_header_id,
14491                      l_appl_mrs_tbl(i).implement_status_code,
14492                      l_appl_mrs_tbl(i).descendent_count,
14493                      'N',
14494                      1
14495                      );
14496               END LOOP;
14497            END IF;
14498          END LOOP; -- l_mr_id_tbl
14499        END LOOP; -- FETCH
14500        CLOSE get_mr_csr;
14501 
14502      END LOOP; -- G_Config_Node
14503   END IF; -- IF G_Config_Node
14504 
14505 END Process_Appl_Expired_MRs;
14506 
14507 -------------------------------------------------------------
14508 -- JKJain
14509 -- Added this procedure for R12.2 Supplier Warranty Enhancements
14510 -- Procedure to calculate Expiration Date of Contract based on Counter details.
14511 PROCEDURE Get_Cont_Ctr_Expiration_Date (p_item_instance_id       IN  NUMBER,
14512                                         p_x_warranty_counter_tbl IN OUT NOCOPY warranty_counter_tbl_type,
14513                                         x_expiration_date        OUT NOCOPY DATE,
14514                                         x_return_status          OUT NOCOPY VARCHAR2,
14515                                         x_msg_data               OUT NOCOPY VARCHAR2,
14516                                         x_msg_count              OUT NOCOPY NUMBER)
14517 IS
14518 
14519   -- Get Item Detailsdetails.
14520 
14521   CURSOR ahl_item_instance_csr (p_item_instance_id IN NUMBER) IS
14522     SELECT cii.inventory_item_id,
14523            cii.inv_master_organization_id
14524     FROM  csi_item_instances cii
14525     WHERE cii.instance_id = p_item_instance_id;
14526 
14527 
14528   -- get the configuration structure.(G_config_node_tbl).
14529   CURSOR csi_reln_csr ( p_csi_item_instance_id IN NUMBER) IS
14530     SELECT position_reference
14531     FROM csi_ii_relationships
14532     WHERE subject_id = p_csi_item_instance_id
14533                AND relationship_type_code = 'COMPONENT-OF'
14534                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
14535                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1));
14536 
14537   -- get the counter usage
14538   CURSOR cs_ctr_counter_csr (--p_csi_item_instance_id  IN NUMBER,
14539                              p_counter_id            IN NUMBER) IS
14540 
14541   select nvl(ccr.net_reading,0) net_reading
14542   FROM csi_counters_b cc, csi_counter_readings ccr
14543   WHERE cc.counter_id = p_counter_id
14544     and  ccr.counter_value_id = cc.CTR_VAL_MAX_SEQ_NO;
14545 
14546   i                       NUMBER;
14547   l_root_csi_instance_id  NUMBER;
14548   l_uc_header_id          NUMBER;
14549   l_calc_due_date         DATE;
14550   l_due_date              DATE;
14551   l_inv_master_organization_id number;
14552   l_inventory_item_id     number;
14553   l_position_reference    VARCHAR2(30);
14554   l_counter_rules_tbl     counter_rules_tbl_type;
14555   l_counter_value         number;
14556   l_counter_remain        number;
14557   l_user_id                   NUMBER;
14558   l_login_id                  NUMBER;
14559 
14560 
14561 BEGIN
14562 
14563   -- Set return status.
14564   x_return_status := FND_API.G_RET_STS_SUCCESS;
14565 
14566   -- Enable Debug.
14567   IF G_DEBUG = 'Y' THEN
14568     AHL_DEBUG_PUB.enable_debug;
14569   END IF;
14570 
14571   -- Add debug mesg.
14572   IF G_DEBUG = 'Y' THEN
14573     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Get_Cont_Ctr_Expiration_Date');
14574     AHL_DEBUG_PUB.debug('Dump of input parameters:');
14575     AHL_DEBUG_PUB.debug('Item Instance ID:' || p_item_instance_id);
14576     AHL_DEBUG_PUB.debug('Count on p_x_warranty_counter_tbl:' || p_x_warranty_counter_tbl.COUNT);
14577   END IF;
14578 
14579   -- Validate input parameters.
14580   IF (p_item_instance_id IS NULL OR p_item_instance_id = FND_API.G_MISS_NUM) THEN
14581      FND_MESSAGE.Set_Name('AHL','AHL_UMP_CONT_ITEM_ID_NULL');
14582      FND_MSG_PUB.ADD;
14583      RAISE FND_API.G_EXC_ERROR;
14584   ELSE
14585      OPEN ahl_item_instance_csr (p_item_instance_id);
14586      FETCH ahl_item_instance_csr INTO l_inventory_item_id, l_inv_master_organization_id;
14587      IF (ahl_item_instance_csr%NOTFOUND) THEN
14588         FND_MESSAGE.Set_Name('AHL','AHL_UMP_CONT_ITEM_ID_INVALID');
14589         FND_MESSAGE.Set_Token('Item_Instance_ID', p_item_instance_id);
14590         FND_MSG_PUB.ADD;
14591 		CLOSE ahl_item_instance_csr;
14592         RAISE FND_API.G_EXC_ERROR;
14593      END IF;
14594      CLOSE ahl_item_instance_csr;
14595   END IF;
14596 
14597 
14598   IF G_DEBUG = 'Y' THEN
14599     AHL_DEBUG_PUB.debug('Step 1');
14600     AHL_DEBUG_PUB.debug('Inventory Item  ID:' || l_inventory_item_id);
14601     AHL_DEBUG_PUB.debug('INV master Org ID:' || l_inv_master_organization_id);
14602   END IF;
14603 
14604   -- Get Unit and Master Config IDs if available.
14605   -- Find the root item instance.
14606   l_root_csi_instance_id := Get_RootInstanceID(p_item_instance_id);
14607 
14608   -- Get master and unit configuration for the root item instance.
14609   Get_Unit_Master_ConfigIDs (l_root_csi_instance_id,
14610                              l_uc_header_id, G_master_config_id);
14611 
14612 
14613   -- Check for errors.
14614   IF FND_MSG_PUB.Count_msg > 0 THEN
14615      RAISE FND_API.G_EXC_ERROR;
14616   END IF;
14617 
14618   -- Get utilization forecast for the unit/part.
14619   Get_Utilization_Forecast (l_root_csi_instance_id,
14620                             l_uc_header_id,
14621                             l_inventory_item_id,
14622                             l_inv_master_organization_id,
14623                             G_forecast_details_tbl);
14624 
14625   IF G_DEBUG = 'Y' THEN
14626     AHL_DEBUG_PUB.debug('Count on util forecast tbl:' || G_forecast_details_tbl.count);
14627   END IF;
14628 
14629   -- Get the position installed in.
14630   OPEN csi_reln_csr(p_item_instance_id);
14631   FETCH csi_reln_csr INTO l_position_reference;
14632   IF (csi_reln_csr%NOTFOUND) THEN
14633      l_position_reference := G_master_config_id;
14634   END IF;
14635   CLOSE csi_reln_csr;
14636 
14637   -- Build counter rules ratio if node is not root node.
14638   IF (G_master_config_id IS NOT NULL AND l_position_reference IS NOT NULL) THEN
14639       build_Counter_Ratio(l_position_reference,
14640                           p_item_instance_id,
14641                           G_master_config_id,
14642                           l_counter_rules_tbl);
14643   END IF;
14644 
14645   -- Calculate counter_remain and call get_date_from_uf.
14646   IF (p_x_warranty_counter_tbl.COUNT > 0) THEN
14647 
14648     l_user_id  := to_number(fnd_global.USER_ID);
14649     l_login_id := to_number(fnd_global.LOGIN_ID);
14650     l_calc_due_date := null ;
14651     l_due_date := null;
14652 
14653     FOR i IN p_x_warranty_counter_tbl.FIRST..p_x_warranty_counter_tbl.LAST LOOP
14654        -- get current usage
14655        --OPEN cs_ctr_counter_csr(l_csi_item_instance_id, p_x_warranty_counter_tbl(i).counter_id);
14656        OPEN cs_ctr_counter_csr(p_x_warranty_counter_tbl(i).counter_id);
14657        FETCH cs_ctr_counter_csr INTO l_counter_value;
14658        IF (cs_ctr_counter_csr%NOTFOUND) THEN
14659           IF G_DEBUG = 'Y' THEN
14660             AHL_DEBUG_PUB.debug('Step 7');
14661           END IF;
14662           l_counter_value := 0;
14663        END IF;
14664 
14665        CLOSE cs_ctr_counter_csr;
14666 
14667        IF G_DEBUG = 'Y' THEN
14668          AHL_DEBUG_PUB.debug('l_counter_value:' || l_counter_value);
14669        END IF;
14670 
14671        -- Get due date for counter remain.
14672        l_counter_remain := p_x_warranty_counter_tbl(i).max_counter_value - l_counter_value;
14673 
14674        IF G_DEBUG = 'Y' THEN
14675          AHL_DEBUG_PUB.debug('l_counter_remain:' || l_counter_remain);
14676        END IF;
14677 
14678        -- get date from forecast.
14679        get_date_from_uf(l_counter_remain,
14680                         p_x_warranty_counter_tbl(i).uom_code,
14681                         l_counter_rules_tbl,
14682                         sysdate,
14683                         l_due_date);
14684 
14685        IF (l_due_date IS NOT NULL) THEN
14686           IF(l_calc_due_date IS NULL) THEN
14687              l_calc_due_date := l_due_date;
14688           ELSIF(l_calc_due_date > l_due_date) THEN
14689              l_calc_due_date := l_due_date;
14690           END IF;
14691        END IF;
14692 
14693        IF G_DEBUG = 'Y' THEN
14694          AHL_DEBUG_PUB.debug('Table AHL_WARRANTY_CONT_CTR_B  will be updated by  Expiration Date ' || l_due_date || ' where WARRANTY_CNTRT_COUNTER_ID = '||p_x_warranty_counter_tbl(i).warranty_cntrt_counter_id);
14695        END IF;
14696          p_x_warranty_counter_tbl(i).counter_expiration_date	:= l_due_date;
14697     END LOOP;
14698   END IF;
14699   x_expiration_date := l_calc_due_date;
14700 
14701   -- Standard call to get message count and if count is 1, get message info
14702   FND_MSG_PUB.Count_And_Get
14703     ( p_count => x_msg_count,
14704       p_data  => x_msg_data,
14705       p_encoded => fnd_api.g_false
14706     );
14707 
14708 --
14709 EXCEPTION
14710  WHEN FND_API.G_EXC_ERROR THEN
14711    x_return_status := FND_API.G_RET_STS_ERROR;
14712    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
14713                               p_data  => x_msg_data,
14714                               p_encoded => fnd_api.g_false);
14715 
14716    -- Disable debug
14717    AHL_DEBUG_PUB.disable_debug;
14718 
14719  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
14720    x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
14721    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
14722                               p_data  => x_msg_data,
14723                               p_encoded => fnd_api.g_false);
14724 
14725    -- Disable debug
14726    AHL_DEBUG_PUB.disable_debug;
14727 
14728  WHEN OTHERS THEN
14729 
14730     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
14731     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
14732        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
14733                                p_procedure_name => 'Get_Cont_Ctr_Expiration_Date',
14734                                p_error_text     => SUBSTR(SQLERRM,1,240));
14735     END IF;
14736     FND_MSG_PUB.count_and_get( p_count => x_msg_count,
14737                                p_data  => x_msg_data,
14738                                p_encoded => fnd_api.g_false);
14739 
14740 
14741     -- Disable debug
14742     AHL_DEBUG_PUB.disable_debug;
14743 
14744 END Get_Cont_Ctr_Expiration_Date;
14745 -------------------------------------------------------
14746 
14747 -- If MR has a accomplishment trigger of 'terminated_by' then check if parent MRs are processed
14748 -- and if not, process them.
14749 -- added for SB Enh.
14750 PROCEDURE Process_Terminating_Parent_MRs(p_applicable_mrs_rec IN applicable_mrs_rec_type,
14751                                          p_current_usage_tbl  IN counter_values_tbl_type,
14752                                          p_counter_rules_tbl  IN counter_rules_tbl_type,
14753                                          x_mr_termination_date OUT NOCOPY DATE)
14754 
14755 IS
14756 
14757   CURSOR get_parent_csr (p_mr_header_id IN NUMBER,
14758                          p_item_instance_id IN NUMBER) IS
14759     SELECT amr.mr_header_id,
14760            mr.version_number,
14761            apmr.csi_item_instance_id,
14762            apmr.Implement_status_code,
14763            apmr.copy_accomplishment_code,
14764            apmr.show_repetitive_code,
14765            apmr.descendent_count,
14766            mr.whichever_first_code,
14767            apmr.repetitive_flag,
14768            mr.title,
14769            mr.effective_from,
14770            mr.effective_to,
14771            apmr.process_status_flag,
14772            apmr.accomplished_ue_id,
14773            apmr.terminate_trigger_check
14774      FROM ahl_mr_relationships amr, ahl_applicable_mrs apmr, ahl_mr_headers_b mr
14775     WHERE amr.related_mr_header_id = p_mr_header_id
14776       AND amr.mr_header_id = apmr.mr_header_id
14777       AND amr.relationship_code = 'TERMINATES'
14778       AND amr.mr_header_id = mr.mr_header_id
14779       AND apmr.csi_item_instance_id = p_item_instance_id;
14780       -- select only those MRs that are unprocessed
14781       -- AND apmr.process_status_flag = 'N';
14782 
14783   l_unprocessed_parent_rec applicable_mrs_rec_type;
14784 
14785   CURSOR get_earliest_date_csr(p_mr_header_id IN NUMBER,
14786                                p_instance_id IN NUMBER) IS
14787    SELECT * FROM (
14788        SELECT due_date, visit_end_date
14789        FROM ahl_temp_unit_effectivities
14790        WHERE csi_item_instance_id = p_instance_id AND
14791              mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1
14792                               where mr1.title = (select mr2.title from ahl_mr_headers_b mr2 where mr2.mr_header_id = p_mr_header_id)
14793                              ) AND
14794              preceding_check_flag = 'N'
14795 
14796        UNION
14797        SELECT due_date, visit_end_date
14798        FROM ahl_temp_unit_SR_deferrals
14799        WHERE csi_item_instance_id = p_instance_id AND
14800              mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1
14801                               where mr1.title = (select mr2.title from ahl_mr_headers_b mr2 where mr2.mr_header_id = p_mr_header_id)
14802                              )
14803        ORDER by due_date
14804    )
14805    WHERE ROWNUM < 2;
14806 
14807    l_termination_date  DATE;
14808    l_terminating_mr_header_id NUMBER;
14809    l_due_date          DATE;
14810    l_visit_end_date    DATE;
14811 
14812    l_acc_unit_effectivity_id  NUMBER;
14813    l_acc_deferral_flag        BOOLEAN;
14814    l_acc_status_code          VARCHAR2(30);
14815    l_return_val               BOOLEAN;
14816 
14817 BEGIN
14818   IF G_DEBUG = 'Y' THEN
14819      AHL_DEBUG_PUB.Debug('Start Process_Terminating_Parent_MRs');
14820      AHL_DEBUG_PUB.Debug('For applicable MR:CSI:' || p_applicable_mrs_rec.MR_header_id || ':' || p_applicable_mrs_rec.csi_item_instance_id);
14821   END IF;
14822   --dbms_output.put_line('Start Process_Terminating_Parent_MRs:' || p_applicable_mrs_rec.MR_header_id || ':' || p_applicable_mrs_rec.csi_item_instance_id);
14823 
14824   -- process parent MRs
14825   FOR l_appl_rec IN get_parent_csr(p_applicable_mrs_rec.mr_header_id,
14826                                    p_applicable_mrs_rec.csi_item_instance_id)
14827   LOOP
14828 
14829      IF G_DEBUG = 'Y' THEN
14830        AHL_DEBUG_PUB.Debug('Found applicable Terminating parent MR:CSI:' || l_appl_rec.MR_header_id || ':' || l_appl_rec.csi_item_instance_id);
14831      END IF;
14832      --dbms_output.put_line('Found applicable Terminating parent MR:CSI:' || l_appl_rec.MR_header_id || ':' || l_appl_rec.csi_item_instance_id || ':' || l_appl_rec.process_status_flag);
14833 
14834      l_due_date := null;
14835 
14836      IF (l_appl_rec.process_status_flag = 'N' OR l_appl_rec.accomplished_ue_id IS NOT NULL) THEN
14837        -- in the case of unprocessed parent, check if parent MR is already accomplished. If yes, we do not need to process
14838        -- parent and instead we use the first accomplishment date.
14839        -- in case parent is already processed and has at least one accomplishment, we get the first one.
14840        -- get first accomplishment.
14841        AHL_UMP_UTIL_PKG.get_first_accomplishment(l_appl_rec.csi_item_instance_id,
14842                                                  l_appl_rec.mr_header_id,
14843                                                  l_due_date,
14844                                                  l_acc_unit_effectivity_id,
14845                                                  l_acc_deferral_flag,
14846                                                  l_acc_status_code,
14847                                                  l_return_val);
14848        IF G_DEBUG = 'Y' THEN
14849          AHL_DEBUG_PUB.Debug('first accomplishment:due date:UEID:' || l_due_date || ':' || l_acc_unit_effectivity_id);
14850          --dbms_output.put_line('first accomplishment:due date:UEID:' || l_due_date || ':' || l_acc_unit_effectivity_id);
14851        END IF;
14852      END IF;
14853 
14854      IF (l_appl_rec.process_status_flag = 'N' AND l_acc_unit_effectivity_id IS NULL) THEN
14855 
14856        -- Build applicable_mrs_rec.
14857        l_unprocessed_parent_rec.csi_item_instance_id := l_appl_rec.csi_item_instance_id;
14858        l_unprocessed_parent_rec.MR_header_id := l_appl_rec.MR_header_id;
14859        l_unprocessed_parent_rec.Implement_status_code := l_appl_rec.Implement_status_code;
14860        l_unprocessed_parent_rec.copy_accomplishment_code := l_appl_rec.copy_accomplishment_code;
14861        l_unprocessed_parent_rec.show_repetitive_code := l_appl_rec.show_repetitive_code;
14862        l_unprocessed_parent_rec.preceding_mr_header_id := null;
14863        l_unprocessed_parent_rec.descendent_count := l_appl_rec.descendent_count;
14864        l_unprocessed_parent_rec.whichever_first_code := l_appl_rec.whichever_first_code;
14865        l_unprocessed_parent_rec.repetitive_flag := l_appl_rec.repetitive_flag;
14866        l_unprocessed_parent_rec.title := l_appl_rec.title;
14867        l_unprocessed_parent_rec.version_number := l_appl_rec.version_number;
14868        l_unprocessed_parent_rec.effective_to := l_appl_rec.effective_to;
14869        l_unprocessed_parent_rec.effective_from := l_appl_rec.effective_from;
14870 
14871        -- added for bug# 9263774
14872        IF (l_appl_rec.effective_to < sysdate) THEN
14873          l_unprocessed_parent_rec.expired_mr_flag := 'Y';
14874        ELSE
14875          l_unprocessed_parent_rec.expired_mr_flag := 'N';
14876        END IF;
14877 
14878        l_unprocessed_parent_rec.terminate_trigger_check := l_appl_rec.terminate_trigger_check;
14879 
14880        --dbms_output.put_line('Calling Build Unit Effe for terminationg parent MR and CSI:exp flag:' || l_unprocessed_parent_rec.expired_mr_flag);
14881 
14882        Build_Effectivity (p_applicable_mrs_rec => l_unprocessed_parent_rec,
14883                           p_current_usage_tbl  => p_current_usage_tbl,
14884                           p_counter_rules_tbl  => p_counter_rules_tbl);
14885 
14886 
14887        -- get earliest date.
14888        OPEN get_earliest_date_csr(l_appl_rec.MR_header_id, l_appl_rec.csi_item_instance_id);
14889        FETCH get_earliest_date_csr INTO l_due_date, l_visit_end_date;
14890        IF (get_earliest_date_csr%NOTFOUND) THEN
14891          CLOSE get_earliest_date_csr;
14892          l_termination_date := NULL;
14893          l_terminating_mr_header_id := l_appl_rec.MR_header_id;
14894          EXIT;
14895        END IF;
14896        CLOSE get_earliest_date_csr;
14897        -- if UE is assigned to visit, then consider l_visit_end_date
14898        IF (l_visit_end_date IS NOT NULL) THEN
14899          l_due_date := l_visit_end_date;
14900        END IF;
14901      ELSIF (l_acc_unit_effectivity_id IS NULL) THEN
14902        -- processed case.
14903        -- get date from temp tables
14904        OPEN get_earliest_date_csr(l_appl_rec.MR_header_id, l_appl_rec.csi_item_instance_id);
14905        FETCH get_earliest_date_csr INTO l_due_date, l_visit_end_date;
14906        IF (get_earliest_date_csr%NOTFOUND) THEN
14907          CLOSE get_earliest_date_csr;
14908          l_termination_date := NULL;
14909          l_terminating_mr_header_id := l_appl_rec.MR_header_id;
14910          EXIT;
14911        END IF;
14912        CLOSE get_earliest_date_csr;
14913        -- if UE is assigned to visit, then consider l_visit_end_date
14914        IF (l_visit_end_date IS NOT NULL) THEN
14915          l_due_date := l_visit_end_date;
14916        END IF;
14917      END IF;
14918 
14919      -- dbms_output.put_line('dates:term:due date:' || l_termination_date || ':' || l_due_date);
14920      -- evaluate later of termination date or due date
14921      IF (l_terminating_mr_header_id IS NULL) THEN
14922        l_terminating_mr_header_id := l_appl_rec.MR_header_id;
14923        l_termination_date := l_due_date;
14924      ELSIF (trunc(l_termination_date) < trunc(l_due_date)) THEN
14925        l_terminating_mr_header_id := l_appl_rec.MR_header_id;
14926        l_termination_date := l_due_date;
14927      END IF; -- l_terminating_mr_header_id
14928   END LOOP;
14929 
14930   l_termination_date := trunc(l_termination_date);
14931 
14932   IF (l_termination_date IS NOT NULL) THEN
14933      UPDATE AHL_APPLICABLE_MRS
14934      set TERMINATION_DATE = l_termination_date,
14935          TERMINATING_MR_HEADER_ID = l_terminating_mr_header_id
14936      where mr_header_id = p_applicable_mrs_rec.mr_header_id
14937        and csi_item_instance_id = p_applicable_mrs_rec.csi_item_instance_id;
14938   END IF;
14939   x_mr_termination_date := l_termination_date;
14940 
14941   -- dbms_output.put_line('term date:' || l_termination_date );
14942 
14943   IF G_DEBUG = 'Y' THEN
14944      AHL_DEBUG_PUB.Debug('End Process_Terminating_Parent_MRs');
14945   END IF;
14946 
14947 END Process_Terminating_Parent_MRs;
14948 --------------------------------------------------------------------
14949 
14950 -- initialization procedure for loops
14951 PROCEDURE Process_Loop_Init(p_applicable_mrs_rec     IN applicable_mrs_rec_type,
14952                             p_current_usage_tbl      IN counter_values_tbl_type,
14953                             p_counter_rules_tbl      IN counter_rules_tbl_type,
14954                             x_loop_chain_MR_tbl         OUT NOCOPY loop_chain_MR_tbl_type,
14955                             x_next_due_skip_flag        OUT NOCOPY VARCHAR2,
14956                             x_loop_last_due_date        OUT NOCOPY DATE,
14957                             x_loop_last_counter_val_tbl OUT NOCOPY counter_values_tbl_type)
14958 IS
14959 
14960   -- get child loop or chain MRs
14961   CURSOR get_lp_chain_mrs(p_start_mr_header_id   IN NUMBER,
14962                           p_csi_item_instance_id IN NUMBER) IS
14963      SELECT apmr.mr_header_id, apmr.loop_chain_seq_num, mr.title
14964      FROM ahl_applicable_MRs apmr, ahl_mr_headers_b mr
14965      WHERE apmr.mr_header_id = mr.mr_header_id
14966        AND apmr.csi_item_instance_id = p_csi_item_instance_id
14967        AND apmr.start_mr_header_id = p_start_mr_header_id
14968      ORDER BY loop_chain_seq_num ASC;
14969 
14970   -- get deferrals for all loop MRs.
14971   -- only 1 deferral to exist
14972   CURSOR ahl_defer_csr (p_csi_instance_id IN NUMBER,
14973                         p_mr_header_id    IN NUMBER) IS
14974     SELECT * FROM
14975     (SELECT
14976     decode (def.affect_due_calc_flag, 'N', def.deferral_effective_on, nvl(def.visit_end_date, def.due_date)) accomplishment_date,
14977     unit_effectivity_id
14978     FROM ahl_temp_unit_SR_deferrals def, ahl_mr_headers_b mr1,
14979          (select title from ahl_mr_headers_b
14980           where mr_header_id IN (select mr_header_id from ahl_applicable_MRs
14981                                   where csi_item_instance_id = p_csi_instance_id
14982                                     and start_mr_header_id = p_mr_header_id)
14983          ) mr2
14984     WHERE def.csi_item_instance_id = p_csi_instance_id
14985           AND def.mr_header_id = mr1.mr_header_id
14986           AND mr1.title = mr2.title
14987           AND def.object_type = 'MR'
14988           AND def.deferral_effective_on IS NOT NULL
14989     ORDER BY def.deferral_effective_on DESC
14990     ) WHERE ROWNUM < 2;
14991     -- get the latest deferral.
14992     -- pick only deferrals and not SR related MRs.
14993 
14994   CURSOR ahl_ue_csr (p_unit_effectivity_id IN NUMBER) IS
14995     SELECT loop_chain_seq_num, start_lc_ue_id
14996     FROM ahl_unit_effectivities_b
14997     WHERE unit_effectivity_id = p_unit_effectivity_id;
14998 
14999 
15000   l_mr_tbl                     nbr_tbl_type;
15001   l_mr_seq_num                 nbr_tbl_type;
15002   l_mr_title_tbl               vchar_tbl_type;
15003 
15004   l_loop_chain_MR_tbl          loop_chain_MR_tbl_type;
15005   --l_unit_effectivity_rec       ahl_temp_unit_effectivities%ROWTYPE;
15006 
15007   l_lc_mr_accomplishment_date  DATE;
15008   l_lc_acc_ue_id               NUMBER;
15009   l_lc_acc_deferral_flag       BOOLEAN;
15010   l_lc_acc_status_code         ahl_unit_effectivities_app_v.status_code%TYPE;
15011   l_lc_return_val              BOOLEAN;
15012 
15013   l_max_acc_date               DATE;
15014   l_last_acc_ue_id             NUMBER;
15015   l_loop_chain_seq_num         NUMBER;
15016   l_start_lc_ue_id             NUMBER;
15017   l_found_deferral             VARCHAR2(1);
15018 
15019   l_no_forecast_flag           BOOLEAN;
15020   l_last_acc_counter_val_tbl   counter_values_tbl_type;
15021   l_new_unit_effectivity_rec   ahl_temp_unit_effectivities%ROWTYPE;
15022 
15023   l_loop_due_date              DATE;
15024   l_loop_last_due_date         DATE;
15025   l_loop_last_counter_val_tbl  counter_values_tbl_type;
15026 
15027 BEGIN
15028   IF G_DEBUG = 'Y' THEN
15029      AHL_DEBUG_PUB.Debug('Start Process_Loop_Init:CSI:MR:' || p_applicable_mrs_rec.csi_item_instance_id || ':' || p_applicable_mrs_rec.mr_header_id);
15030   END IF;
15031 
15032   -- get loop or chain MRs.
15033   OPEN get_lp_chain_mrs(p_applicable_mrs_rec.mr_header_id,
15034                         p_applicable_mrs_rec.csi_item_instance_id);
15035   FETCH get_lp_chain_mrs BULK COLLECT INTO l_mr_tbl, l_mr_seq_num, l_mr_title_tbl;
15036   CLOSE get_lp_chain_mrs;
15037 
15038 
15039   IF (l_mr_tbl.count > 0) THEN
15040      FOR i IN l_mr_tbl.FIRST..l_mr_tbl.LAST LOOP
15041          l_loop_chain_MR_tbl(i).mr_header_id := l_mr_tbl(i);
15042          l_loop_chain_MR_tbl(i).loop_chain_seq_num := l_mr_seq_num(i);
15043          l_loop_chain_MR_tbl(i).accomplishment_exists := 'N';
15044          l_loop_chain_MR_tbl(i).mr_title := l_mr_title_tbl(i);
15045 
15046          -- check if MR is accomplished at least once.
15047          AHL_UMP_UTIL_PKG.get_last_accomplishment(p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
15048 	                                          p_mr_header_id => l_mr_tbl(i),
15049 	                                          x_accomplishment_date => l_lc_mr_accomplishment_date,
15050 	                                          x_unit_effectivity_id => l_lc_acc_ue_id,
15051 	                                          x_deferral_flag => l_lc_acc_deferral_flag,
15052 	                                          x_status_code => l_lc_acc_status_code,
15053                                                   x_return_val => l_lc_return_val);
15054          IF (NOT(l_lc_return_val)) THEN
15055            RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
15056          ELSE
15057            IF (l_lc_acc_ue_id IS NOT NULL) THEN
15058               l_loop_chain_MR_tbl(i).accomplishment_exists := 'Y';
15059               l_loop_chain_MR_tbl(i).accomplished_ue_id := l_lc_acc_ue_id;
15060               IF (l_max_acc_date IS NULL) THEN
15061                 l_max_acc_date := l_lc_mr_accomplishment_date;
15062                 l_last_acc_ue_id := l_lc_acc_ue_id;
15063               -- consider = as well to pick the later loop seq.
15064               ELSIF (l_max_acc_date <= l_lc_mr_accomplishment_date) THEN
15065                 l_max_acc_date := l_lc_mr_accomplishment_date;
15066                 l_last_acc_ue_id := l_lc_acc_ue_id;
15067               END IF;
15068            END IF;
15069          END IF; -- l_acc_unit_effectivity_id
15070      END LOOP;
15071 
15072      x_loop_chain_MR_tbl := l_loop_chain_MR_tbl;
15073 
15074      l_found_deferral := 'N';
15075      -- check if there are any deferrals. If yes, start loop from there.
15076      OPEN ahl_defer_csr (p_applicable_mrs_rec.csi_item_instance_id,
15077                          p_applicable_mrs_rec.mr_header_id);
15078      FETCH ahl_defer_csr INTO l_max_acc_date, l_last_acc_ue_id;
15079      IF (ahl_defer_csr%FOUND) THEN
15080        l_found_deferral := 'Y';
15081      END IF;
15082      CLOSE ahl_defer_csr;
15083 
15084      IF (l_last_acc_ue_id IS NOT NULL) THEN
15085         -- get ue details
15086         OPEN ahl_ue_csr(l_last_acc_ue_id);
15087         FETCH ahl_ue_csr INTO l_loop_chain_seq_num, l_start_lc_ue_id;
15088         IF (ahl_ue_csr%NOTFOUND) THEN
15089           FND_MESSAGE.Set_Name('AHL','AHL_UMP_UE_INVALID');
15090           FND_MESSAGE.Set_Token('UE_ID',l_last_acc_ue_id );
15091           FND_MSG_PUB.ADD;
15092           CLOSE ahl_ue_csr;
15093           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
15094         END IF;
15095         CLOSE ahl_ue_csr;
15096      END IF;
15097 
15098      -- check if loop seq is last seq.
15099      IF (l_last_acc_ue_id IS NULL) OR (l_loop_chain_seq_num IS NOT NULL AND l_loop_chain_seq_num = l_mr_seq_num.count) THEN
15100        x_next_due_skip_flag := 'N';
15101        RETURN; -- start at the beginning of the loop
15102      END IF;
15103 
15104      -- start calculation from l_loop_chain_seq_num
15105      -- get counter values for date.
15106      get_instance_ctr_for_date (p_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
15107                                 p_last_accomplishment_date => l_max_acc_date,
15108                                 p_deferral_flag            => l_found_deferral,
15109                                 p_unit_effectivity_id      => l_last_acc_ue_id,
15110                                 p_current_usage_tbl        => p_current_usage_tbl,
15111                                 p_counter_rules_tbl        => p_counter_rules_tbl,
15112                                 x_no_forecast_flag         => l_no_forecast_flag,
15113                                 x_last_acc_counter_val_tbl => l_last_acc_counter_val_tbl);
15114 
15115      -- ignore l_no_forecast_flag check as we need to create null rows for due date.
15116      -- initialize l_new_unit_effectivity_rec
15117      l_new_unit_effectivity_rec.due_date := l_max_acc_date;
15118      l_new_unit_effectivity_rec.unit_effectivity_id := l_last_acc_ue_id;
15119      l_new_unit_effectivity_rec.loop_chain_seq_num := l_loop_chain_seq_num;
15120      l_new_unit_effectivity_rec.start_lc_ue_id := l_start_lc_ue_id;
15121      l_new_unit_effectivity_rec.start_mr_header_id := p_applicable_mrs_rec.mr_header_id;
15122      l_new_unit_effectivity_rec.accomplish_trigger_type := p_applicable_mrs_rec.accomplish_trigger_type;
15123      l_new_unit_effectivity_rec.visit_end_date := null;
15124      l_new_unit_effectivity_rec.repetitive_mr_flag := 'N';
15125      l_new_unit_effectivity_rec.forecast_sequence := 1;
15126 
15127      Process_Loop_Chain_MRs (p_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
15128                              p_repetivity_flag => 'N',
15129                              p_new_unit_effectivity_rec => l_new_unit_effectivity_rec,
15130                              p_current_usage_tbl => p_current_usage_tbl,
15131                              p_counter_rules_tbl => p_counter_rules_tbl,
15132                              p_last_due_date => l_max_acc_date,
15133                              p_last_due_counter_val_tbl => l_last_acc_counter_val_tbl,
15134                              p_loop_chain_MR_tbl  => l_loop_chain_MR_tbl,
15135                              x_loop_due_date => l_loop_due_date,
15136                              x_loop_last_due_date => l_loop_last_due_date,
15137                              x_loop_last_counter_val_tbl => l_loop_last_counter_val_tbl);
15138 
15139 
15140   END IF; -- l_mr_tbl.count
15141 
15142   IF (p_applicable_mrs_rec.accomplish_trigger_type = 'LOOP') THEN
15143     --x_loop_due_date := l_loop_due_date;
15144     x_next_due_skip_flag := 'Y';
15145     x_loop_last_due_date := l_loop_last_due_date;
15146     x_loop_last_counter_val_tbl := l_loop_last_counter_val_tbl;
15147     IF G_DEBUG = 'Y' THEN
15148       AHL_DEBUG_PUB.Debug('Start MR due date:' || x_loop_last_due_date);
15149       IF (x_loop_last_counter_val_tbl.count > 0) THEN
15150         FOR i in x_loop_last_counter_val_tbl.FIRST..x_loop_last_counter_val_tbl.LAST LOOP
15151            AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || x_loop_last_counter_val_tbl(i).counter_value || 'ID: ' || x_loop_last_counter_val_tbl(i).counter_id);
15152         END LOOP;
15153       END IF;
15154     END IF;
15155   END IF;
15156 
15157 
15158   IF G_DEBUG = 'Y' THEN
15159      AHL_DEBUG_PUB.Debug('End Process_Loop_Init');
15160   END IF;
15161 
15162 
15163 END Process_Loop_Init;
15164 ------------------------------------------------------------
15165 
15166 -- initialization procedure for chains
15167 PROCEDURE Process_Chain_Init(p_applicable_mrs_rec IN applicable_mrs_rec_type,
15168                              p_current_usage_tbl  IN counter_values_tbl_type,
15169                              p_counter_rules_tbl  IN counter_rules_tbl_type,
15170                              x_loop_chain_MR_tbl     OUT NOCOPY loop_chain_MR_tbl_type)
15171 
15172 IS
15173 
15174   -- get child loop or chain MRs
15175   CURSOR get_lp_chain_mrs(p_start_mr_header_id   IN NUMBER,
15176                           p_csi_item_instance_id IN NUMBER) IS
15177      SELECT apmr.mr_header_id, apmr.loop_chain_seq_num, mr.title
15178      FROM ahl_applicable_MRs apmr, ahl_mr_headers_b mr
15179      WHERE apmr.mr_header_id = mr.mr_header_id
15180        AND apmr.csi_item_instance_id = p_csi_item_instance_id
15181        AND apmr.start_mr_header_id = p_start_mr_header_id
15182      ORDER BY loop_chain_seq_num ASC;
15183 
15184  /*
15185   -- get inprogress chain MRs
15186   CURSOR ahl_inprogress_chain_MRs(p_csi_item_instance_id IN NUMBER,
15187                                   p_mr_header_id         IN NUMBER) IS
15188     SELECT ue.start_lc_ue_id,
15189            min(loop_chain_seq_num)
15190     FROM ahl_unit_effectivities_b ue1, ahl_unit_effectivities_b ue2
15191     WHERE ue1.unit_effectivity_id = ue2.start_lc_ue_id
15192       AND ue.csi_item_instance_id = p_csi_item_instance_id
15193       AND ue.status_code IS NOT NULL AND ue.status_code <> 'INIT-DUE'
15194       AND EXISTS (select 'x'
15195                    from ahl_mr_headers_b mr_title
15196                         (select mr_header_id from ahl_unit_effectivities_b ue1
15197                           where unit_effectivity_id = ue.start_lc_ue_id) start_mr
15198                    where
15199                          and appl_mr.start_mr_header_id = p_mr_header_id
15200                          and appl_mr.mr_header_id = mr1.mr_header_id)
15201       AND ue.object_type = 'MR'
15202       AND ue.defer_from_ue_id IS NULL
15203       AND ue.accomplish_trigger_type = 'CHAIN'
15204       AND (ue.status_code IS NULL)
15205       -- parent is accomplished
15206       AND NOT EXISTS (select 'x' from ahl_unit_effectivities_b
15207                       where unit_effectivity_id = ue.start_lc_ue_id
15208                       AND (status_code is NULL or status_code = 'INIT-DUE')
15209                      )
15210       GROUP BY ue.start_lc_ue_id;
15211   */
15212 
15213   -- get inprogress chain MRs
15214   CURSOR get_inprogress_chain_MRs(p_start_mr_header_id   IN NUMBER,
15215                                   p_csi_item_instance_id IN NUMBER) IS
15216     SELECT ue.start_lc_ue_id, max(ue.loop_chain_seq_num)
15217       from ahl_unit_effectivities_b ue, ahl_mr_headers_b mr
15218      where ue.csi_item_instance_id = p_csi_item_instance_id
15219        and ue.mr_header_id = mr.mr_header_id
15220        and ue.status_code IN ('ACCOMPLISHED','TERMINATED','INIT-ACCOMPLISHED')
15221        and mr.title in (select title from ahl_applicable_mrs appl, ahl_mr_headers_b mr1
15222                          where appl.start_mr_header_id = p_start_mr_header_id
15223                            and appl.csi_item_instance_id = p_csi_item_instance_id
15224                            and appl.mr_header_id = mr1.mr_header_id
15225                        )
15226        and exists (select 'x' from ahl_unit_effectivities_b ue1
15227                    where ue1.csi_item_instance_id = p_csi_item_instance_id
15228                      and ue1.start_lc_ue_id = ue.start_lc_ue_id
15229                      and (ue.STATUS_CODE IS NULL or ue.STATUS_CODE = 'INIT-DUE')
15230                   )
15231     group by ue.start_lc_ue_id;
15232 
15233   -- get unplanned MRs (where start mr is unplanned and is not accomplished)
15234   CURSOR get_unplanned_start_MRs(p_start_mr_title       IN VARCHAR2,
15235                                  p_csi_item_instance_id IN NUMBER) IS
15236     SELECT ue.unit_effectivity_id,
15237            ue.due_date,
15238            ue.mr_header_id,
15239            to_date(null) visit_end_date
15240       FROM ahl_unit_effectivities_b ue
15241      WHERE ue.mr_header_id IN (select amh.mr_header_id from ahl_mr_headers_b amh where amh.title = p_start_mr_title)
15242        AND ue.csi_item_instance_id = p_csi_item_instance_id
15243        AND ue.status_code IS NULL
15244        AND ue.manually_planned_flag = 'Y'
15245        AND ue.defer_from_ue_id IS NULL
15246        -- Do not pick MRs associated to a SR.
15247        AND NOT EXISTS (SELECT 'x'
15248                        FROM ahl_ue_relationships uer, ahl_unit_effectivities_b ue1
15249                        WHERE uer.related_ue_id = ue.unit_effectivity_id
15250                          AND uer.originator_ue_id = ue1.unit_effectivity_id
15251                          AND ue1.object_type = 'SR');
15252 
15253   -- get deferrals and MRs associated to a SR
15254   CURSOR get_start_def_SR(p_start_mr_title       IN VARCHAR2,
15255                           p_csi_item_instance_id IN NUMBER) IS
15256     SELECT unit_effectivity_id,
15257            due_date,
15258            mr_header_id,
15259            visit_end_date
15260      FROM ahl_temp_unit_SR_deferrals
15261      WHERE csi_item_instance_id = p_csi_item_instance_id
15262        AND mr_header_id IN (select mr1.mr_header_id from ahl_mr_headers_b mr1 where mr1.title = p_start_mr_title);
15263 
15264   -- get chain UE id
15265   CURSOR get_chain_ue_csr(p_start_lc_ue_id in number,
15266                           p_chain_seq_num  in number) is
15267     SELECT ue.unit_effectivity_id, AHL_UMP_UTIL_PKG.get_Visit_Status (ue.unit_effectivity_id) l_visit_status,
15268            ue.defer_from_ue_id, ue.mr_header_id, mr.title
15269     FROM ahl_unit_effectivities_b ue, ahl_mr_headers_b mr
15270     where ue.mr_header_id = mr.mr_header_id
15271       and ue.start_lc_ue_id = p_start_lc_ue_id
15272       and ue.loop_chain_seq_num = p_chain_seq_num
15273       and ue.accomplish_trigger_type = 'CHAIN';
15274 
15275   -- get chain accomplishment
15276   CURSOR get_acc_chain_seq(p_start_lc_ue_id in number,
15277                            p_chain_seq_num  in number) is
15278    SELECT ue.accomplished_date, ue.unit_effectivity_id, ue.loop_chain_seq_num, ue.mr_header_id,
15279           decode(ue.status_code, 'TERMINATED', ter.affect_due_calc_flag, def.affect_due_calc_flag),
15280           decode(ue.status_code, 'TERMINATED', ter.deferral_effective_on, def.deferral_effective_on)
15281    FROM ahl_unit_effectivities_b ue, ahl_unit_deferrals_b def, ahl_unit_deferrals_b ter
15282    WHERE ue.defer_from_ue_id = def.unit_effectivity_id (+)
15283       AND ue.unit_effectivity_id = ter.unit_effectivity_id(+)
15284       AND ue.status_code IN ('ACCOMPLISHED','INIT-ACCOMPLISHED','TERMINATED')
15285       AND def.unit_deferral_type(+) = 'DEFERRAL'
15286       AND ter.unit_deferral_type(+) = 'DEFERRAL'
15287       AND ue.start_lc_ue_id = p_start_lc_ue_id
15288       AND ue.loop_chain_seq_num = p_chain_seq_num
15289    ORDER BY decode (ue.status_code, 'TERMINATED', ter.deferral_effective_on, ue.accomplished_date) DESC;
15290 
15291   -- get deferred or unplanned chain MRs.
15292   CURSOR get_defer_chain_MRs(p_chain_ue_id IN NUMBER) IS
15293     SELECT * FROM
15294     ( SELECT
15295       decode (def.affect_due_calc_flag, 'N', def.deferral_effective_on, nvl(def.visit_end_date, def.due_date)) due_date
15296       FROM ahl_temp_unit_SR_deferrals def
15297       WHERE def.unit_effectivity_id = p_chain_ue_id
15298         AND def.object_type = 'MR'
15299         AND EXISTS (select 'x' from ahl_applicable_mrs
15300                     where csi_item_instance_id = def.csi_item_instance_id
15301                       and mr_header_id = def.mr_header_id
15302                       and accomplish_trigger_type = 'CHAIN')
15303         AND def.deferral_effective_on IS NOT NULL
15304     )
15305     WHERE ROWNUM < 2;
15306 
15307   -- get visit end date
15308   CURSOR get_vst_date(p_ue_id IN NUMBER) IS
15309     SELECT vst.close_date_time
15310     from ahl_visits_b vst, ahl_visit_tasks_b tsk
15311     where tsk.unit_effectivity_id = p_ue_id
15312       and tsk.visit_id = vst.visit_id
15313       and tsk.task_type_code = 'SUMMARY';
15314 
15315   l_mr_tbl                     nbr_tbl_type;
15316   l_mr_seq_num                 nbr_tbl_type;
15317   l_mr_title_tbl               vchar_tbl_type;
15318 
15319   l_loop_chain_MR_tbl          loop_chain_MR_tbl_type;
15320   --l_unit_effectivity_rec       ahl_temp_unit_effectivities%ROWTYPE;
15321 
15322   l_lc_mr_accomplishment_date  DATE;
15323   l_lc_acc_ue_id               NUMBER;
15324   l_lc_acc_deferral_flag       BOOLEAN;
15325   l_lc_acc_status_code         ahl_unit_effectivities_app_v.status_code%TYPE;
15326   l_lc_return_val              BOOLEAN;
15327 
15328   l_max_acc_date               DATE;
15329   --l_last_acc_ue_id             NUMBER;
15330   --l_loop_chain_seq_num         NUMBER;
15331   --l_start_lc_ue_id             NUMBER;
15332   l_found_deferral             VARCHAR2(1);
15333 
15334   l_no_forecast_flag           BOOLEAN;
15335   l_last_acc_counter_val_tbl   counter_values_tbl_type;
15336   l_new_unit_effectivity_rec   ahl_temp_unit_effectivities%ROWTYPE;
15337 
15338   l_loop_due_date              DATE;
15339   l_loop_last_due_date         DATE;
15340   l_loop_last_counter_val_tbl  counter_values_tbl_type;
15341 
15342   -- chain
15343   l_chain_start_lc_ue_tbl     nbr_tbl_type;
15344   l_chain_seq_num_tbl         nbr_tbl_type;
15345   l_c_accomplishment_date     date;
15346   l_c_unit_effectivity_id     number;
15347   l_c_loop_chain_seq_num      number;
15348   l_c_mr_header_id            number;
15349   l_c_affect_due_calc_flag    varchar2(2);
15350   l_c_deferral_effective_on   date;
15351 
15352   l_chain_ue_id               number;
15353   l_visit_status              varchar2(30);
15354   l_defer_from_ue_id          number;
15355   l_mr_header_id              number;
15356   l_mr_title                  ahl_mr_headers_b.title%TYPE;
15357 
15358   l_start_ue_id_tbl           nbr_tbl_type;
15359   l_start_due_date_tbl        date_tbl_type;
15360   l_start_mr_id_tbl           nbr_tbl_type;
15361   l_start_vst_end_tbl         date_tbl_type;
15362 
15363   l_unplan_unit_effectivity_rec  ahl_temp_unit_effectivities%ROWTYPE;
15364   l_new_unit_effectivity_initrec ahl_temp_unit_effectivities%ROWTYPE;
15365   l_iteration_seq            number;
15366 
15367   l_visit_start_date       DATE;
15368   l_visit_end_date         DATE;
15369   l_visit_assign_code      fnd_lookups.lookup_code%TYPE;
15370 
15371 BEGIN
15372 
15373   IF G_DEBUG = 'Y' THEN
15374      AHL_DEBUG_PUB.Debug('Start Process_Chain_Init for MR:CSI:' || p_applicable_mrs_rec.mr_header_id || ':' || p_applicable_mrs_rec.csi_item_instance_id);
15375   END IF;
15376 
15377   -- get loop or chain MRs.
15378   OPEN get_lp_chain_mrs(p_applicable_mrs_rec.mr_header_id,
15379                         p_applicable_mrs_rec.csi_item_instance_id);
15380   FETCH get_lp_chain_mrs BULK COLLECT INTO l_mr_tbl, l_mr_seq_num, l_mr_title_tbl;
15381   CLOSE get_lp_chain_mrs;
15382 
15383 
15384   IF (l_mr_tbl.count > 0) THEN
15385     FOR i IN l_mr_tbl.FIRST..l_mr_tbl.LAST LOOP
15386        l_loop_chain_MR_tbl(i).mr_header_id := l_mr_tbl(i);
15387        l_loop_chain_MR_tbl(i).loop_chain_seq_num := l_mr_seq_num(i);
15388        l_loop_chain_MR_tbl(i).accomplishment_exists := 'N';
15389        l_loop_chain_MR_tbl(i).mr_title := l_mr_title_tbl(i);
15390 
15391        -- check if MR is accomplished at least once.
15392        AHL_UMP_UTIL_PKG.get_last_accomplishment(p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
15393                                                 p_mr_header_id => l_mr_tbl(i),
15394                                                 x_accomplishment_date => l_lc_mr_accomplishment_date,
15395                                                 x_unit_effectivity_id => l_lc_acc_ue_id,
15396                                                 x_deferral_flag => l_lc_acc_deferral_flag,
15397                                                 x_status_code => l_lc_acc_status_code,
15398                                                 x_return_val => l_lc_return_val);
15399        IF (NOT(l_lc_return_val)) THEN
15400           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
15401        ELSE
15402           IF (l_lc_acc_ue_id IS NOT NULL) THEN
15403               l_loop_chain_MR_tbl(i).accomplishment_exists := 'Y';
15404               l_loop_chain_MR_tbl(i).accomplished_ue_id := l_lc_acc_ue_id;
15405           END IF;
15406        END IF; -- l_acc_unit_effectivity_id
15407     END LOOP;
15408 
15409     x_loop_chain_MR_tbl := l_loop_chain_MR_tbl;
15410   END IF;
15411 
15412   -- process chains that are partially accomplished
15413   OPEN get_inprogress_chain_MRs(p_applicable_mrs_rec.mr_header_id,
15414                                 p_applicable_mrs_rec.csi_item_instance_id);
15415   FETCH get_inprogress_chain_MRs BULK COLLECT INTO l_chain_start_lc_ue_tbl, l_chain_seq_num_tbl;
15416   CLOSE get_inprogress_chain_MRs;
15417 
15418   IF G_DEBUG = 'Y' THEN
15419     AHL_DEBUG_PUB.Debug('In progress MRs:count:' || l_chain_start_lc_ue_tbl.count);
15420   END IF;
15421 
15422   IF (l_chain_start_lc_ue_tbl.count > 0) THEN
15423     FOR h IN l_chain_start_lc_ue_tbl.FIRST..l_chain_start_lc_ue_tbl.LAST LOOP
15424        -- initialize
15425        l_found_deferral := 'N';
15426 
15427        -- get next chain UE details.
15428        OPEN get_chain_ue_csr(l_chain_start_lc_ue_tbl(h), l_chain_seq_num_tbl(h)+1);
15429        FETCH get_chain_ue_csr INTO l_chain_ue_id, l_visit_status, l_defer_from_ue_id, l_mr_header_id, l_mr_title;
15430        IF (get_chain_ue_csr%NOTFOUND) THEN
15431           -- error
15432           FND_MESSAGE.Set_Name('AHL','AHL_UMP_UE_INVALID');
15433           FND_MESSAGE.Set_Token('START_LC_UE_ID',l_chain_start_lc_ue_tbl(h));
15434           FND_MESSAGE.Set_Token('CHAIN_SEQ', l_chain_seq_num_tbl(h)+1);
15435           FND_MSG_PUB.ADD;
15436           CLOSE get_chain_ue_csr;
15437           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
15438        END IF;
15439        CLOSE get_chain_ue_csr;
15440 
15441        IF G_DEBUG = 'Y' THEN
15442          AHL_DEBUG_PUB.Debug('Chain UE:' || l_chain_ue_id || ':' || l_defer_from_ue_id || ':' || l_mr_header_id || ':' || l_mr_title);
15443        END IF;
15444 
15445        IF (l_loop_chain_MR_tbl.count <= l_chain_seq_num_tbl(h)) OR (l_loop_chain_MR_tbl(l_chain_seq_num_tbl(h)+1).mr_title <> l_mr_title) THEN
15446            IF (l_visit_status IN ('RELEASED','CLOSED')) THEN
15447            -- ue is on shop floor.
15448              IF (l_defer_from_ue_id IS NULL) THEN
15449                -- *****calculate due date only for this instance - rest will not be in a visit and will be deleted.
15450                -- if ue is deferred, due date is already calculated
15451 
15452                CONTINUE;
15453              END IF;
15454            END IF;
15455          END IF;
15456 
15457          -- if control reaches here, mr title matches
15458          -- start with accomplishment or deferral date.
15459          IF (l_defer_from_ue_id IS NOT NULL) THEN
15460             -- get deferral ue.
15461             OPEN get_defer_chain_MRs(l_chain_ue_id);
15462             FETCH get_defer_chain_MRs INTO l_c_accomplishment_date;
15463             IF (get_defer_chain_MRs%FOUND) THEN
15464               l_found_deferral := 'Y';
15465             END IF;
15466          ELSE
15467             -- get accomplishment dates.
15468             OPEN get_acc_chain_seq(l_chain_start_lc_ue_tbl(h), l_chain_seq_num_tbl(h));
15469             FETCH get_acc_chain_seq INTO l_c_accomplishment_date,
15470                                          l_c_unit_effectivity_id,
15471                                          l_c_loop_chain_seq_num,
15472                                          l_c_mr_header_id,
15473                                          l_c_affect_due_calc_flag,
15474                                          l_c_deferral_effective_on;
15475 
15476             IF (get_acc_chain_seq%FOUND) THEN
15477               -- dbms_output.put_line ('ue id' || l_unit_effectivity_id);
15478               -- Added for deferral enhancements.
15479               -- Use deferral_effective_on date instead of accomplishment date.
15480               IF (l_c_affect_due_calc_flag = 'N') THEN
15481                  l_c_accomplishment_date := l_c_deferral_effective_on;
15482               END IF;
15483             ELSE
15484               -- error
15485               FND_MESSAGE.Set_Name('AHL','AHL_UMP_UE_INVALID');
15486               FND_MESSAGE.Set_Token('START_LC_UE_ID',l_chain_start_lc_ue_tbl(h));
15487               FND_MESSAGE.Set_Token('CHAIN_SEQ', l_chain_seq_num_tbl(h));
15488               FND_MSG_PUB.ADD;
15489               CLOSE get_acc_chain_seq;
15490               RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
15491             END IF;
15492          END IF;
15493          CLOSE get_acc_chain_seq;
15494 
15495          -- start calculation from l_loop_chain_seq_num
15496          -- get counter values for date.
15497          get_instance_ctr_for_date (p_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
15498                                     p_last_accomplishment_date => l_c_accomplishment_date,
15499                                     p_deferral_flag            => l_found_deferral,
15500                                     p_unit_effectivity_id      => l_c_unit_effectivity_id,
15501                                     p_current_usage_tbl        => p_current_usage_tbl,
15502                                     p_counter_rules_tbl        => p_counter_rules_tbl,
15503                                     x_no_forecast_flag         => l_no_forecast_flag,
15504                                     x_last_acc_counter_val_tbl => l_last_acc_counter_val_tbl);
15505 
15506          -- ignore l_no_forecast_flag check as we need to create null rows for due date.
15507          -- initialize l_new_unit_effectivity_rec
15508          l_new_unit_effectivity_rec := l_new_unit_effectivity_initrec;
15509          l_new_unit_effectivity_rec.due_date := l_c_accomplishment_date;
15510          l_new_unit_effectivity_rec.unit_effectivity_id := l_c_unit_effectivity_id;
15511          l_new_unit_effectivity_rec.loop_chain_seq_num := l_chain_seq_num_tbl(h);
15512          l_new_unit_effectivity_rec.start_lc_ue_id := l_chain_start_lc_ue_tbl(h);
15513          l_new_unit_effectivity_rec.start_mr_header_id := p_applicable_mrs_rec.mr_header_id;
15514          l_new_unit_effectivity_rec.accomplish_trigger_type := p_applicable_mrs_rec.accomplish_trigger_type;
15515          l_new_unit_effectivity_rec.visit_end_date := null;
15516          l_new_unit_effectivity_rec.repetitive_mr_flag := 'Y';
15517          l_new_unit_effectivity_rec.forecast_sequence := null;
15518 
15519          Process_Loop_Chain_MRs (p_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
15520                              p_repetivity_flag => 'Y',
15521                              p_new_unit_effectivity_rec => l_new_unit_effectivity_rec,
15522                              p_current_usage_tbl => p_current_usage_tbl,
15523                              p_counter_rules_tbl => p_counter_rules_tbl,
15524                              p_last_due_date => l_max_acc_date,
15525                              p_last_due_counter_val_tbl => l_last_acc_counter_val_tbl,
15526                              p_loop_chain_MR_tbl  => l_loop_chain_MR_tbl,
15527                              x_loop_due_date => l_loop_due_date,
15528                              x_loop_last_due_date => l_loop_last_due_date,
15529                              x_loop_last_counter_val_tbl => l_loop_last_counter_val_tbl);
15530 
15531       END LOOP; -- l_chain_start_lc_ue_tbl
15532 
15533     END IF; -- l_chain_start_lc_ue_tbl.count
15534 
15535 
15536   -- process chain MRs following any open deferred or unplanned MRs that could be
15537   -- start MR
15538   -- Loop MR unlike chain MRs cannot be added as Unplanned so there will not be
15539   -- multiple instances of a loop for an item instance. The deferred loop MR(if exists)
15540   -- will be processed in build effectivity procedure.
15541 
15542   l_iteration_seq := 1;
15543 
15544   LOOP
15545     IF (l_iteration_seq = 1) THEN
15546       OPEN get_unplanned_start_MRs (p_applicable_mrs_rec.title,
15547                                     p_applicable_mrs_rec.csi_item_instance_id);
15548       FETCH get_unplanned_start_MRs BULK COLLECT INTO l_start_ue_id_tbl, l_start_due_date_tbl,
15549                                                       l_start_mr_id_tbl, l_start_vst_end_tbl;
15550       CLOSE get_unplanned_start_MRs;
15551 
15552 
15553     ELSE
15554       OPEN get_start_def_SR (p_applicable_mrs_rec.title,
15555                              p_applicable_mrs_rec.csi_item_instance_id);
15556       FETCH get_start_def_SR BULK COLLECT INTO l_start_ue_id_tbl, l_start_due_date_tbl,
15557                                                l_start_mr_id_tbl, l_start_vst_end_tbl;
15558       CLOSE get_start_def_SR;
15559 
15560     END IF;
15561 
15562     IF (l_start_ue_id_tbl.count > 0) THEN
15563       FOR i IN l_start_ue_id_tbl.FIRST..l_start_ue_id_tbl.LAST LOOP
15564 
15565          IF (l_iteration_seq = 1) THEN
15566             -- Call visit work package to get visit end date if unit effectivity has been assigned to a visit.
15567             AHL_UMP_UTIL_PKG.get_visit_details (l_start_ue_id_tbl(i),
15568                                                 l_visit_start_date,
15569                                                 l_visit_end_date,
15570                                                 l_visit_assign_code);
15571 
15572             IF (l_visit_end_date IS NOT NULL AND trunc(l_visit_end_date) <  trunc(sysdate)) THEN
15573               l_visit_end_date := sysdate;
15574             /*
15575             ELSE
15576               -- get visit end date
15577               open get_vst_date(l_start_ue_id_tbl(i));
15578               fetch get_vst_date into l_visit_end_date;
15579               close get_vst_date;
15580             */
15581             END IF;
15582             l_start_due_date_tbl(i) := l_visit_end_date;
15583 
15584          END IF;
15585 
15586          IF G_DEBUG = 'Y' THEN
15587             AHL_DEBUG_PUB.Debug('Process_Chain_Init:UE:DueDate:End Date:' || l_start_ue_id_tbl(i) || ':' || l_start_due_date_tbl(i) || ':' || l_start_vst_end_tbl(i));
15588          END IF;
15589 
15590          -- calculate due date for following chain MRs.
15591          -- form input for Process_Loop_Chain_MRs
15592          l_unplan_unit_effectivity_rec := l_new_unit_effectivity_initrec;
15593          l_unplan_unit_effectivity_rec.due_date := l_start_due_date_tbl(i);
15594          l_unplan_unit_effectivity_rec.unit_effectivity_id := l_start_ue_id_tbl(i);
15595          l_unplan_unit_effectivity_rec.loop_chain_seq_num := p_applicable_mrs_rec.loop_chain_seq_num;
15596          l_unplan_unit_effectivity_rec.start_lc_ue_id := l_start_ue_id_tbl(i);
15597          l_unplan_unit_effectivity_rec.start_mr_header_id := l_start_mr_id_tbl(i);
15598          l_unplan_unit_effectivity_rec.accomplish_trigger_type := p_applicable_mrs_rec.accomplish_trigger_type;
15599          l_unplan_unit_effectivity_rec.visit_end_date := l_start_vst_end_tbl(i);
15600          l_unplan_unit_effectivity_rec.repetitive_mr_flag := 'Y';
15601          l_unplan_unit_effectivity_rec.forecast_sequence := null;
15602 
15603          -- update ahl_unit_effectivities_b for chain trigger
15604          UPDATE ahl_unit_effectivities_b
15605             SET accomplish_trigger_type = p_applicable_mrs_rec.accomplish_trigger_type,
15606                 start_lc_ue_id = l_start_ue_id_tbl(i),
15607                 loop_chain_seq_num = p_applicable_mrs_rec.loop_chain_seq_num
15608          WHERE  unit_effectivity_id = l_start_ue_id_tbl(i);
15609 
15610          Process_Loop_Chain_MRs (p_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
15611                                  p_repetivity_flag => 'Y',
15612                                  p_new_unit_effectivity_rec => l_unplan_unit_effectivity_rec,
15613                                  p_current_usage_tbl => p_current_usage_tbl,
15614                                  p_counter_rules_tbl => p_counter_rules_tbl,
15615                                  p_last_due_date => sysdate,
15616                                  p_last_due_counter_val_tbl => p_current_usage_tbl,
15617                                  p_loop_chain_MR_tbl  => l_loop_chain_MR_tbl,
15618                                  x_loop_due_date => l_loop_due_date,
15619                                  x_loop_last_due_date => l_loop_last_due_date,
15620                                  x_loop_last_counter_val_tbl => l_loop_last_counter_val_tbl
15621                                  --x_return_status => l_return_status
15622                                  );
15623 
15624 
15625       END LOOP;
15626     END IF;
15627 
15628     IF (l_iteration_seq = 1) THEN
15629         l_iteration_seq := 2;
15630         l_start_ue_id_tbl.delete;
15631         l_start_due_date_tbl.delete;
15632         l_start_mr_id_tbl.delete;
15633         l_start_vst_end_tbl.delete;
15634     ELSE
15635         EXIT;
15636     END IF;
15637   END LOOP;
15638 
15639 
15640   IF G_DEBUG = 'Y' THEN
15641      AHL_DEBUG_PUB.Debug('End Process_Chain_Init');
15642   END IF;
15643 
15644 END Process_Chain_Init;
15645 -----------------------------------------------------------
15646 
15647 PROCEDURE Process_Loop_Chain_MRs (p_item_instance_id         IN NUMBER,
15648                                   p_new_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE,
15649                                   p_repetivity_flag          IN VARCHAR2 := 'Y',
15650 			          p_current_usage_tbl        IN counter_values_tbl_type,
15651 			          p_counter_rules_tbl        IN counter_rules_tbl_type,
15652 			          p_last_due_date            IN DATE,
15653 			          p_last_due_counter_val_tbl IN counter_values_tbl_type,
15654                                   p_loop_chain_MR_tbl        IN loop_chain_MR_tbl_type,
15655                                   x_loop_due_date             OUT NOCOPY DATE,
15656                                   x_loop_last_due_date        OUT NOCOPY DATE,
15657                                   x_loop_last_counter_val_tbl OUT NOCOPY counter_values_tbl_type)
15658 
15659 IS
15660 
15661 
15662   CURSOR get_appl_mr_dtls_csr(p_mr_header_id IN NUMBER,
15663                               p_csi_item_instance_id IN NUMBER) IS
15664     SELECT DISTINCT appl.csi_item_instance_id,
15665                     appl.MR_header_id,
15666                     mr.Title,
15667                     mr.version_number,
15668                     appl.Implement_status_code,
15669                     appl.copy_accomplishment_code,
15670                     appl.repetitive_flag,
15671                     appl.show_repetitive_code,
15672                     appl.descendent_count,
15673                     mr.whichever_first_code,
15674                     mr.effective_to,
15675                     mr.effective_from,
15676                     appl.loop_chain_seq_num
15677     FROM ahl_applicable_MRs appl, ahl_mr_headers_b mr
15678     WHERE appl.csi_item_instance_id = p_csi_item_instance_id
15679        AND appl.mr_header_id = p_mr_header_id
15680        AND (appl.implement_status_code <> 'OPTIONAL_DO_NOT_IMPLEMENT')
15681        AND appl.mr_header_id = mr.mr_header_id
15682        AND trunc(nvl(mr.effective_from,sysdate)) <= trunc(sysdate);
15683 
15684   CURSOR ahl_ue_csr (p_start_lc_ue_id     IN NUMBER,
15685                      p_loop_chain_seq_num IN NUMBER) IS
15686     SELECT unit_effectivity_id, mr.title
15687     FROM ahl_unit_effectivities_b ue, ahl_mr_headers_b mr
15688     WHERE ue.mr_header_id = mr.mr_header_id
15689       AND ue.start_lc_ue_id = p_start_lc_ue_id
15690       AND ue.loop_chain_seq_num = p_loop_chain_seq_num
15691       AND (ue.STATUS_CODE IS NULL or ue.STATUS_CODE = 'INIT-DUE');
15692 
15693     l_loop_chain_seq_num   NUMBER;
15694     l_appl_rec          get_appl_mr_dtls_csr%ROWTYPE;
15695     l_appl_mr_dtls_rec  applicable_mrs_rec_type;
15696 
15697     l_due_date       DATE;
15698     l_last_due_date  DATE;
15699 
15700     l_last_due_counter_val_tbl  counter_values_tbl_type;
15701     l_due_at_counter_val_tbl    counter_values_tbl_type;
15702     l_return_value              BOOLEAN;
15703     l_no_forecast_available     VARCHAR2(1) := 'N';
15704 
15705     l_next_due_date_rec         next_due_date_rec_type;
15706     l_mr_accomplish_exists      BOOLEAN;
15707     l_new_unit_effectivity_rec  ahl_temp_unit_effectivities%ROWTYPE;
15708     l_new_unit_effectivity_initrec  ahl_temp_unit_effectivities%ROWTYPE;
15709 
15710     l_first_time_calc           VARCHAR2(1);
15711     l_repetivity_flag           VARCHAR2(1);
15712 
15713     l_visit_start_date   DATE;
15714     l_visit_end_date     DATE;
15715     l_visit_assign_code  VARCHAR2(30);
15716 
15717     l_ue_id              NUMBER;
15718     l_ue_mr_title        ahl_mr_headers_b.title%TYPE;
15719 
15720 BEGIN
15721 
15722   IF G_DEBUG = 'Y' THEN
15723      AHL_DEBUG_PUB.Debug('Start Process_Loop_Chain_MRs');
15724   END IF;
15725 
15726       -- find the start point to process.
15727       l_loop_chain_seq_num := p_new_unit_effectivity_rec.loop_chain_seq_num;
15728       IF (p_loop_chain_MR_tbl.EXISTS(l_loop_chain_seq_num+1)) THEN
15729         l_loop_chain_seq_num := l_loop_chain_seq_num + 1;
15730       ELSE
15731         RETURN; -- nothing to process.
15732       END IF;
15733 
15734       -- Set values for next MR calculation.
15735       IF (p_new_unit_effectivity_rec.visit_end_date IS NOT NULL) THEN
15736           l_due_date := p_new_unit_effectivity_rec.visit_end_date;
15737       ELSE
15738           l_due_date := p_new_unit_effectivity_rec.due_date;
15739       END IF;
15740 
15741       l_last_due_date := p_last_due_date;
15742       l_last_due_counter_val_tbl := p_last_due_counter_val_tbl;
15743 
15744       l_first_time_calc := 'Y';
15745 
15746       IF (p_repetivity_flag = 'Y' AND l_due_date IS NOT NULL) THEN
15747           -- get due counter values on due date.
15748           Get_Due_at_Counter_Values (p_last_due_date => p_last_due_date,
15749                                      p_last_due_counter_val_tbl => p_last_due_counter_val_tbl,
15750   	                             p_due_date => l_due_date,
15751 	                             p_counter_rules_tbl => p_counter_rules_tbl,
15752 	                             x_due_at_counter_val_tbl => l_due_at_counter_val_tbl,
15753 	                             x_return_value => l_return_value);
15754           IF NOT(l_return_value) THEN
15755             l_no_forecast_available := 'Y';
15756           ELSE
15757             l_no_forecast_available := 'N';
15758           END IF;
15759           --  dbms_output.put_line ('step1.45:l_due_at_counter_val_tbl.count:' || l_due_at_counter_val_tbl.count);
15760 
15761 
15762           l_last_due_date := l_due_date;
15763           l_last_due_counter_val_tbl := l_due_at_counter_val_tbl;
15764       END IF;
15765 
15766       IF G_DEBUG = 'Y' THEN
15767          AHL_DEBUG_PUB.Debug('Start MR due date:' || l_last_due_date);
15768          IF (l_last_due_counter_val_tbl.COUNT) > 0 THEN
15769             FOR i in l_last_due_counter_val_tbl.FIRST..l_last_due_counter_val_tbl.LAST LOOP
15770               AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_last_due_counter_val_tbl(i).counter_value || 'ID: ' || l_last_due_counter_val_tbl(i).counter_id);
15771             END LOOP;
15772          END IF;
15773       END IF;
15774       --
15775       IF (l_no_forecast_available = 'Y') THEN
15776         RETURN;
15777       END IF;
15778       --
15779       -- calc due date only if due date is not null and forecast available.
15780       IF (l_due_date is NOT NULL) AND (l_no_forecast_available = 'N') THEN
15781         LOOP
15782 
15783           -- get MR details.
15784           OPEN get_appl_mr_dtls_csr(p_loop_chain_MR_tbl(l_loop_chain_seq_num).mr_header_id,
15785                                     p_item_instance_id);
15786           FETCH get_appl_mr_dtls_csr INTO l_appl_rec;
15787           CLOSE get_appl_mr_dtls_csr;
15788 
15789           -- set applicable MR record.
15790           l_appl_mr_dtls_rec.csi_item_instance_id := l_appl_rec.csi_item_instance_id;
15791           l_appl_mr_dtls_rec.MR_header_id := l_appl_rec.MR_header_id;
15792           l_appl_mr_dtls_rec.title := l_appl_rec.title;
15793           l_appl_mr_dtls_rec.version_number := l_appl_rec.version_number;
15794           l_appl_mr_dtls_rec.Implement_status_code := l_appl_rec.Implement_status_code;
15795           l_appl_mr_dtls_rec.copy_accomplishment_code := l_appl_rec.copy_accomplishment_code;
15796           l_appl_mr_dtls_rec.repetitive_flag := l_appl_rec.repetitive_flag;
15797           l_appl_mr_dtls_rec.show_repetitive_code := 'NEXT';
15798           l_appl_mr_dtls_rec.preceding_mr_header_id := null;
15799           l_appl_mr_dtls_rec.descendent_count := l_appl_rec.descendent_count;
15800           l_appl_mr_dtls_rec.whichever_first_code := l_appl_rec.whichever_first_code;
15801           l_appl_mr_dtls_rec.effective_to := l_appl_rec.effective_to;
15802           l_appl_mr_dtls_rec.effective_from := l_appl_rec.effective_from;
15803 
15804           -- added for bug# 9263774
15805           IF (l_appl_mr_dtls_rec.effective_to < sysdate) THEN
15806              l_appl_mr_dtls_rec.expired_mr_flag := 'Y';
15807           ELSE
15808              l_appl_mr_dtls_rec.expired_mr_flag := 'N';
15809           END IF;
15810 
15811           IF (l_first_time_calc = 'Y') THEN
15812             l_repetivity_flag := p_repetivity_flag;
15813             -- check if UE exists and if associated to a visit.
15814             open ahl_ue_csr(p_new_unit_effectivity_rec.unit_effectivity_id,
15815                             p_loop_chain_MR_tbl(l_loop_chain_seq_num).loop_chain_seq_num);
15816             fetch ahl_ue_csr INTO l_ue_id, l_ue_mr_title;
15817             if (ahl_ue_csr%found) THEN
15818                -- check if associcated to a visit.
15819                AHL_UMP_UTIL_PKG.get_visit_details (l_ue_id,
15820                                                    l_visit_start_date,
15821                                                    l_visit_end_date,
15822                                                    l_visit_assign_code);
15823                IF (nvl(l_visit_assign_code,'x') NOT IN ('RELEASED','CLOSED')) THEN
15824                  if (l_ue_mr_title <> l_appl_rec.title) THEN
15825                    l_visit_end_date := null;
15826                  end if;
15827                end if;
15828             end if;
15829             close ahl_ue_csr;
15830             l_first_time_calc := 'N';
15831 
15832           ELSE
15833             l_repetivity_flag := 'Y';
15834             l_visit_end_date := null;
15835           END IF;
15836 
15837             -- Calculate next due date.
15838   	    Calculate_Due_Date (p_repetivity_flag => p_repetivity_flag,
15839   	                        p_applicable_mrs_rec => l_appl_mr_dtls_rec,
15840   	                        p_current_usage_tbl => p_current_usage_tbl,
15841   	                        p_counter_rules_tbl => p_counter_rules_tbl,
15842   	                        p_last_due_date => l_last_due_date,
15843 	                        p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
15844 	                        p_dependent_mr_flag => FALSE,
15845 	                        --p_mr_accomplish_exists  => l_mr_accomplish_exists,
15846 	                        p_mr_accomplish_exists  => FALSE,
15847 	                        x_next_due_date_rec => l_next_due_date_rec);
15848 
15849 	    IF G_DEBUG = 'Y' THEN
15850 	      AHL_DEBUG_PUB.Debug('Aft loop/chain calculate_due_date nextdue');
15851 	      AHL_DEBUG_PUB.Debug('loop/chain due date is ' || l_next_due_date_rec.DUE_DATE);
15852 	      AHL_DEBUG_PUB.Debug('loop/chain earliest due date is ' || l_next_due_date_rec.EARLIEST_DUE_DATE);
15853 	      AHL_DEBUG_PUB.Debug('loop/chain latest due date is ' || l_next_due_date_rec.latest_due_date);
15854 	    END IF;
15855 
15856           IF (l_next_due_date_rec.DUE_DATE IS NOT NULL) OR (p_new_unit_effectivity_rec.repetitive_mr_flag = 'N') THEN
15857             -- Insert into temp table
15858             -- construct ahl_unit_effectivity record and write into temporary table.
15859             l_new_unit_effectivity_rec := l_new_unit_effectivity_initrec; -- initialise.
15860 
15861             l_new_unit_effectivity_rec.csi_item_instance_id := p_item_instance_id;
15862             l_new_unit_effectivity_rec.mr_header_id := l_appl_mr_dtls_rec.mr_header_id;
15863 
15864             l_new_unit_effectivity_rec.due_date := l_next_due_date_rec.due_date;
15865             l_new_unit_effectivity_rec.mr_interval_id := l_next_due_date_rec.mr_interval_id;
15866             l_new_unit_effectivity_rec.mr_effectivity_id := l_next_due_date_rec.mr_effectivity_id;
15867             l_new_unit_effectivity_rec.due_counter_value := l_next_due_date_rec.due_at_counter_value;
15868 
15869             l_new_unit_effectivity_rec.tolerance_flag := l_next_due_date_rec.tolerance_flag;
15870 
15871             l_new_unit_effectivity_rec.tolerance_before := l_next_due_date_rec.tolerance_before;
15872             l_new_unit_effectivity_rec.tolerance_after := l_next_due_date_rec.tolerance_after;
15873             l_new_unit_effectivity_rec.message_code := l_next_due_date_rec.message_code;
15874             l_new_unit_effectivity_rec.preceding_check_flag:= 'N';
15875 
15876             l_new_unit_effectivity_rec.earliest_due_date := l_next_due_date_rec.earliest_due_date;
15877             l_new_unit_effectivity_rec.latest_due_date := l_next_due_date_rec.latest_due_date;
15878 
15879             l_new_unit_effectivity_rec.counter_id := l_next_due_date_rec.counter_id;
15880             l_new_unit_effectivity_rec.forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
15881 
15882             -- set repetivity based on next_due_flag.
15883             l_new_unit_effectivity_rec.repetitive_mr_flag := p_new_unit_effectivity_rec.repetitive_mr_flag;
15884 
15885             -- update loop / chain details
15886             l_new_unit_effectivity_rec.start_mr_header_id := p_new_unit_effectivity_rec.start_mr_header_id;
15887             l_new_unit_effectivity_rec.accomplish_trigger_type := p_new_unit_effectivity_rec.accomplish_trigger_type;
15888             l_new_unit_effectivity_rec.start_lc_ue_id := p_new_unit_effectivity_rec.unit_effectivity_id;
15889             l_new_unit_effectivity_rec.loop_chain_seq_num := p_loop_chain_MR_tbl(l_loop_chain_seq_num).loop_chain_seq_num;
15890 
15891             Create_Temp_Unit_Effectivity (l_new_unit_effectivity_rec);
15892 
15893           END IF;
15894 
15895           l_due_date := l_next_due_date_rec.due_date;
15896 
15897           IF (l_visit_end_date IS NOT NULL) THEN
15898             l_due_date := l_visit_end_date;
15899           END IF;
15900 
15901           -- get all counter values as on l_due_date.
15902           Get_Due_at_Counter_Values (p_last_due_date => l_last_due_date,
15903                                      p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
15904                                      p_due_date => l_due_date,
15905                                      p_counter_rules_tbl => p_counter_rules_tbl,
15906                                      x_due_at_counter_val_tbl => l_due_at_counter_val_tbl,
15907                                      x_return_value => l_return_value);
15908           l_last_due_date := l_due_date;
15909           l_last_due_counter_val_tbl := l_due_at_counter_val_tbl;
15910 
15911           IF G_DEBUG = 'Y' THEN
15912              AHL_DEBUG_PUB.Debug('AFter get_due_at_counter_values');
15913              AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
15914              AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
15915              IF (l_due_at_counter_val_tbl.COUNT) > 0 THEN
15916                 for i in l_due_at_counter_val_tbl.FIRST..l_due_at_counter_val_tbl.LAST LOOP
15917              AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_due_at_counter_val_tbl(i).counter_value || 'ID: ' || l_due_at_counter_val_tbl(i).counter_id);
15918                 end loop;
15919              END IF;
15920           END IF;
15921 
15922           -- next MR.
15923           IF (p_loop_chain_MR_tbl.EXISTS(l_loop_chain_seq_num + 1)) THEN
15924             l_loop_chain_seq_num := l_loop_chain_seq_num + 1;
15925           ELSE
15926             EXIT;
15927           END IF;
15928 
15929         END LOOP;
15930 
15931         -- set return values only for loop.
15932         IF (p_new_unit_effectivity_rec.accomplish_trigger_type = 'LOOP') THEN
15933            x_loop_last_counter_val_tbl := l_last_due_counter_val_tbl;
15934            x_loop_last_due_date := l_last_due_date;
15935            x_loop_due_date := l_next_due_date_rec.due_date;
15936         END IF;
15937 
15938       END IF;
15939 
15940   IF G_DEBUG = 'Y' THEN
15941      AHL_DEBUG_PUB.Debug('End Process_Loop_Chain_MRs');
15942   END IF;
15943 
15944 END Process_Loop_Chain_MRs;
15945 --------------------------------------
15946 PROCEDURE get_instance_ctr_for_date (p_item_instance_id         IN NUMBER,
15947                                      p_last_accomplishment_date IN DATE,
15948                                      p_deferral_flag            IN VARCHAR2,
15949                                      p_unit_effectivity_id      IN NUMBER,
15950                                      p_current_usage_tbl        IN counter_values_tbl_type,
15951                                      p_counter_rules_tbl        IN counter_rules_tbl_type,
15952                                      x_no_forecast_flag         OUT NOCOPY BOOLEAN,
15953                                      x_last_acc_counter_val_tbl OUT NOCOPY counter_values_tbl_type)
15954 IS
15955 
15956   -- Get last accomplishment counter values.
15957   CURSOR ahl_unit_accomplish_csr (p_unit_effectivity_id IN NUMBER) IS
15958         SELECT
15959                 UA.COUNTER_ID,
15960                 UA.COUNTER_VALUE,
15961                 CS.UOM_CODE,
15962                 CS.COUNTER_TEMPLATE_NAME COUNTER_NAME
15963         FROM
15964                 AHL_UNIT_ACCOMPLISHMNTS UA,
15965                 CSI_COUNTERS_VL CS
15966         WHERE
15967                 UA.COUNTER_ID = CS.COUNTER_ID AND
15968                 UA.UNIT_EFFECTIVITY_ID = P_UNIT_EFFECTIVITY_ID
15969         ORDER BY
15970                 CS.UOM_CODE ;
15971 
15972   -- Get instance counter details.
15973   CURSOR csi_cp_counters_csr (p_csi_instance_id IN NUMBER) IS
15974      SELECT cc.counter_id, cc.uom_code,
15975             cc.counter_template_name counter_name
15976      from   csi_counter_associations cca, csi_counters_vl cc
15977      where  cca.counter_id = cc.counter_id
15978      AND    source_object_code = 'CP'
15979      AND    source_object_id = p_csi_instance_id;
15980 
15981 
15982   l_net_reading               NUMBER;
15983   l_last_acc_counter_val_tbl  counter_values_tbl_type;
15984 
15985   l_due_counter_val_tbl       counter_values_tbl_type;
15986   l_due_date                  DATE;
15987 
15988   l_return_val                BOOLEAN;
15989   i                           NUMBER;
15990 
15991 BEGIN
15992 
15993   -- initialize out parameters
15994   x_no_forecast_flag  := FALSE;
15995 
15996 
15997   IF (p_deferral_flag = 'Y') THEN
15998     IF (p_last_accomplishment_date IS NULL) OR (p_item_instance_id IS NULL) THEN
15999        RETURN;
16000     ELSIF (p_last_accomplishment_date <= sysdate) THEN
16001       -- get counter values from counter values tables.
16002       i := 1;
16003       FOR instance_counter_rec IN csi_cp_counters_csr(p_item_instance_id) LOOP
16004           l_net_reading := 0;
16005           get_ctr_reading_for_datetime (p_csi_item_instance_id => p_item_instance_id,
16006                                         p_counter_id           => instance_counter_rec.counter_id,
16007                                         p_reading_date         => p_last_accomplishment_date,
16008                                         x_net_reading          => l_net_reading);
16009 
16010           l_last_acc_counter_val_tbl(i).uom_code := instance_counter_rec.uom_code;
16011           l_last_acc_counter_val_tbl(i).counter_id := instance_counter_rec.counter_id;
16012           l_last_acc_counter_val_tbl(i).counter_name := instance_counter_rec.counter_name;
16013           l_last_acc_counter_val_tbl(i).counter_value := l_net_reading;
16014           i := i + 1;
16015 
16016       END LOOP;
16017     ELSE  -- deferral due date is a future date.
16018        -- get all counter values as on l_preceding_next_due_date.
16019        Get_Due_at_Counter_Values (p_last_due_date => sysdate,
16020                                   p_last_due_counter_val_tbl => p_current_usage_tbl,
16021                                   p_due_date => p_last_accomplishment_date,
16022                                   p_counter_rules_tbl => p_counter_rules_tbl,
16023                                   x_due_at_counter_val_tbl => l_last_acc_counter_val_tbl,
16024                                   x_return_value => l_return_val);
16025 
16026        IF G_DEBUG = 'Y' THEN
16027          AHL_DEBUG_PUB.Debug('l_deferral_due_date: ' || p_last_accomplishment_date);
16028          IF (l_last_acc_counter_val_tbl.COUNT) > 0 THEN
16029             for i in l_last_acc_counter_val_tbl.FIRST..l_last_acc_counter_val_tbl.LAST LOOP
16030                AHL_DEBUG_PUB.Debug('i:'|| i|| ' value:' || l_last_acc_counter_val_tbl(i).counter_value || 'ID: ' || l_last_acc_counter_val_tbl(i).counter_id);
16031             end loop;
16032          END IF;
16033        END IF;
16034 
16035        -- check return value.
16036        IF NOT(l_return_val) THEN  -- no forecast case.
16037          x_no_forecast_flag := TRUE;
16038        END IF;
16039 
16040     END IF;  -- Last accomplishment date.
16041   ELSE  -- not based on deferral_effective_date.
16042     IF (p_unit_effectivity_id IS NOT NULL) THEN
16043       i := 1;
16044       -- Build last accomplishment counter values.
16045       FOR l_acc_counter_rec IN ahl_unit_accomplish_csr(p_unit_effectivity_id) LOOP
16046         l_last_acc_counter_val_tbl(i).uom_code := l_acc_counter_rec.uom_code;
16047         l_last_acc_counter_val_tbl(i).counter_id := l_acc_counter_rec.counter_id;
16048         l_last_acc_counter_val_tbl(i).counter_name := l_acc_counter_rec.counter_name;
16049         l_last_acc_counter_val_tbl(i).counter_value := l_acc_counter_rec.counter_value;
16050         i := i + 1;
16051       END LOOP;
16052 
16053     END IF;
16054   END IF; -- p_deferral_flag.
16055 
16056   x_last_acc_counter_val_tbl := l_last_acc_counter_val_tbl;
16057 
16058 END get_instance_ctr_for_date;
16059 -----------------------------------
16060 
16061 -- JKJain, NR Analysis and Forecasting
16062 FUNCTION get_primary_plan_id RETURN NUMBER
16063 IS
16064 
16065   -- get fleet for the unit on the date given.
16066 CURSOR get_primary_plan IS
16067   SELECT simulation_plan_id
16068   FROM AHL_SIMULATION_PLANS_B
16069   WHERE primary_plan_flag = 'Y'
16070   AND  status_code = 'ACTIVE'
16071 --  AND  nvl(simulation_type,'UMP') = 'UMP'; Removed NVL condition as primary plan is seeded with UMP.
16072   AND  simulation_type = 'UMP';
16073 
16074   l_primary_plan_id NUMBER := NULL;
16075 
16076 BEGIN
16077 
16078   OPEN get_primary_plan;
16079   FETCH get_primary_plan INTO l_primary_plan_id;
16080   CLOSE get_primary_plan;
16081 
16082   RETURN l_primary_plan_id;
16083 
16084 END get_primary_plan_id;
16085 
16086 FUNCTION get_fleet_from_unit_asso(p_uc_header_id IN NUMBER,
16087                                   p_date IN DATE,
16088                                   p_plan_id IN NUMBER) RETURN NUMBER
16089 IS
16090 
16091   -- get fleet for the unit on the date given.
16092 CURSOR date_withing_flt_asso(c_unit_config_header_id  NUMBER,
16093                              c_due_date DATE,
16094                              c_plan_id NUMBER) IS
16095   SELECT FUA.fleet_header_id
16096     FROM ahl_fleet_unit_assocs FUA, ahl_fleet_headers_b FLT
16097     WHERE unit_config_header_id = c_unit_config_header_id
16098        AND c_due_date between ASSOCIATION_START and nvl(ASSOCIATION_END,c_due_date)
16099        AND FLT.fleet_header_id = FUA.fleet_header_id
16100        AND FLT.status_code = 'COMPLETE'
16101        AND FUA.simulation_plan_id = nvl(c_plan_id, get_primary_plan_id);
16102 
16103   l_fleet_header_id NUMBER := NULL;
16104 
16105 BEGIN
16106 
16107   OPEN date_withing_flt_asso(p_uc_header_id,p_date,p_plan_id);
16108   FETCH date_withing_flt_asso INTO l_fleet_header_id;
16109   CLOSE date_withing_flt_asso;
16110 
16111   RETURN l_fleet_header_id;
16112 
16113 END get_fleet_from_unit_asso;
16114 -----------------------------
16115 
16116 -- Added for Complex Assembly enhancements.
16117 -- Procedure to calculate NR due date for init-due definition.
16118 -- due date details will be updated in ahl_unit_effectivities_b table.
16119 PROCEDURE Calculate_Init_DueDate (
16120               x_return_status          OUT NOCOPY VARCHAR2,
16121               x_msg_data               OUT NOCOPY VARCHAR2,
16122               x_msg_count              OUT NOCOPY NUMBER,
16123               x_due_date               OUT NOCOPY DATE,
16124               p_init_msg_list          IN         VARCHAR2 := FND_API.G_FALSE,
16125               p_unit_effectivity_id    IN         NUMBER)
16126 IS
16127 
16128   l_due_date                   DATE;
16129   l_due_counter_value          NUMBER;
16130   l_counter_id                 NUMBER;
16131 
16132 BEGIN
16133   x_return_status := FND_API.G_RET_STS_SUCCESS;
16134 
16135   -- Enable Debug.
16136   IF G_DEBUG = 'Y' THEN
16137     AHL_DEBUG_PUB.enable_debug;
16138   END IF;
16139 
16140   -- Add debug mesg.
16141   IF G_DEBUG = 'Y' THEN
16142     AHL_DEBUG_PUB.debug('At start of procedure:' ||  G_PKG_NAME || '.' || 'Calculate_Init_DueDate');
16143     AHL_DEBUG_PUB.debug('Dump of input parameters:');
16144     AHL_DEBUG_PUB.debug('Unit Effectivity ID:' || p_unit_effectivity_id);
16145   END IF;
16146 
16147   -- Validate input parameters.
16148   IF (p_unit_effectivity_id IS NULL OR p_unit_effectivity_id = FND_API.G_MISS_NUM) THEN
16149      FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_UE_NULL');
16150      FND_MSG_PUB.ADD;
16151      RAISE FND_API.G_EXC_ERROR;
16152   END IF;
16153 
16154   IF G_DEBUG = 'Y' THEN
16155          AHL_DEBUG_PUB.debug('Before call to Calculate_NR_due_date');
16156   END IF;
16157 
16158   Calculate_NR_due_date(p_unit_effectivity_id, l_due_date, l_due_counter_value, l_counter_id);
16159   x_due_date := l_due_date;
16160 
16161   IF G_DEBUG = 'Y' THEN
16162     AHL_DEBUG_PUB.debug('After call to Calculate_NR_due_date');
16163   END IF;
16164 
16165 
16166   IF (l_due_counter_value IS NOT NULL OR l_due_date IS NOT NULL) THEN
16167 
16168     IF G_DEBUG = 'Y' THEN
16169       AHL_DEBUG_PUB.debug('Before updating UE table:UE:DDT:DCV:CTR_ID:' || p_unit_effectivity_id || ':' || l_due_date || ':' || l_due_counter_value || ':' || l_counter_id);
16170     END IF;
16171 
16172     -- Update table.
16173     UPDATE ahl_unit_effectivities_b
16174     SET due_date = l_due_date,
16175       due_counter_value = l_due_counter_value,
16176       counter_id = l_counter_id,
16177       last_update_date = sysdate,
16178       last_updated_by = fnd_global.user_id,
16179       object_version_number = object_version_number + 1
16180     WHERE unit_effectivity_id = p_unit_effectivity_id;
16181 
16182     -- update child UEs.
16183     UPDATE ahl_unit_effectivities_b
16184     SET due_date = l_due_date,
16185       due_counter_value = l_due_counter_value,
16186       counter_id = l_counter_id,
16187       last_update_date = sysdate,
16188       last_updated_by = fnd_global.user_id,
16189       object_version_number = object_version_number + 1
16190     WHERE unit_effectivity_id IN (select related_ue_id
16191                                   from ahl_ue_relationships
16192                                   where originator_ue_id = p_unit_effectivity_id);
16193 
16194   END IF;
16195 
16196 
16197 EXCEPTION
16198 
16199  WHEN OTHERS THEN
16200   IF (SQLCODE = -54) THEN
16201      FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_ALREADY_RUNNING');
16202      FND_MSG_PUB.ADD;
16203      RAISE  FND_API.G_EXC_ERROR;
16204   ELSE
16205     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
16206        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
16207                                p_procedure_name => 'Calculate_Init_DueDate',
16208                                p_error_text     => SUBSTR(SQLERRM,1,240));
16209     END IF;
16210     RAISE  FND_API.G_EXC_UNEXPECTED_ERROR;
16211   END IF;
16212 
16213 END Calculate_Init_DueDate;
16214 ---------------------------
16215 
16216 -- added for Complex Assembly Enh: To calculate due date for nonroutine when UE status is init-due.
16217 PROCEDURE Calculate_NR_due_date(p_unit_effectivity_id  IN NUMBER,
16218                                 x_due_date             OUT NOCOPY  DATE,
16219                                 x_due_counter_value    OUT NOCOPY  NUMBER,
16220                                 x_counter_id           OUT NOCOPY  NUMBER)
16221 
16222 IS
16223 
16224   -- Get Unit Effectivity details.
16225   -- added inventory_item_id, inv_master_organization_id to fix bug# 9284692
16226   CURSOR ahl_unit_effectivity_csr (p_unit_effectivity_id IN NUMBER) IS
16227     SELECT ue.csi_item_instance_id, ue.mr_header_id, cii.inventory_item_id,
16228            cii.inv_master_organization_id
16229     FROM ahl_unit_effectivities_app_v ue, csi_item_instances cii
16230     WHERE ue.unit_effectivity_id = p_unit_effectivity_id
16231           AND ue.csi_item_instance_id = cii.instance_id;
16232 
16233   -- Get MR details.
16234   CURSOR ahl_mr_headers_csr (p_mr_header_id IN NUMBER) IS
16235     SELECT whichever_first_code
16236     FROM ahl_mr_headers_app_v
16237     WHERE mr_header_id = p_mr_header_id;
16238 
16239   -- get the configuration structure.(G_config_node_tbl).
16240   CURSOR csi_reln_csr ( p_csi_item_instance_id IN NUMBER) IS
16241     SELECT position_reference
16242     FROM csi_ii_relationships
16243     WHERE subject_id = p_csi_item_instance_id
16244                AND relationship_type_code = 'COMPONENT-OF'
16245                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
16246                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1));
16247 
16248 
16249   -- get the counter usage
16250   CURSOR cs_ctr_counter_csr (p_counter_id  IN NUMBER) IS
16251     select nvl(ccr.net_reading,0) net_reading
16252     FROM csi_counters_b cc, csi_counter_readings ccr
16253     WHERE cc.counter_id = p_counter_id
16254       and  ccr.counter_value_id = cc.CTR_VAL_MAX_SEQ_NO;
16255 
16256 
16257   -- added for USAF: Assembly Maint. Enh.: Support for initializing a NR.
16258   -- Get threshold details.
16259   CURSOR ahl_unit_threshold_csr (p_ue_id IN NUMBER) IS
16260     SELECT aut.counter_id, aut.counter_value, (select uom_code from csi_counters_b where counter_id = aut.counter_id) uom_code
16261     FROM ahl_unit_thresholds aut, ahl_unit_deferrals_b udf
16262     WHERE udf.unit_effectivity_id = p_ue_id
16263       AND udf.unit_deferral_id = aut.unit_deferral_id
16264       AND udf.unit_deferral_type = 'INIT-DUE';
16265 
16266   i                       NUMBER;
16267   l_csi_item_instance_id  NUMBER;
16268   l_root_csi_instance_id  NUMBER;
16269   l_mr_header_id          NUMBER;
16270   l_uc_header_id          NUMBER;
16271 
16272 
16273 
16274   l_inv_master_organization_id number;
16275   l_inventory_item_id     number;
16276   l_position_reference    VARCHAR2(30);
16277   l_counter_rules_tbl     counter_rules_tbl_type;
16278   l_current_usage_tbl     counter_values_tbl_type;
16279   --l_counter_value         number;
16280   l_uom_code              VARCHAR2(3);
16281   l_counter_read_date     DATE;
16282 
16283   l_expected_resolution_date   DATE;
16284   l_calc_due_date              DATE;
16285   l_calc_counter_id            NUMBER;
16286   l_calc_due_counter_value     NUMBER;
16287 
16288   l_due_date                   DATE;
16289   l_due_at_counter_value       NUMBER;
16290   k                            NUMBER;
16291   l_counter_remain             NUMBER;
16292   l_current_ctr_value          NUMBER;
16293   l_return_val                 BOOLEAN;
16294 
16295 BEGIN
16296 
16297 
16298   OPEN ahl_unit_effectivity_csr (p_unit_effectivity_id);
16299   FETCH ahl_unit_effectivity_csr INTO l_csi_item_instance_id, l_mr_header_id,
16300                                       l_inventory_item_id, l_inv_master_organization_id;
16301   IF (ahl_unit_effectivity_csr%NOTFOUND) THEN
16302      FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_UE_INVALID');
16303      FND_MESSAGE.Set_Token('UE_ID', p_unit_effectivity_id);
16304      FND_MSG_PUB.ADD;
16305      RAISE FND_API.G_EXC_ERROR;
16306   END IF;
16307 
16308    IF G_DEBUG = 'Y' THEN
16309      AHL_DEBUG_PUB.debug('Step 1');
16310      AHL_DEBUG_PUB.debug('CSI Item Instance ID:' || l_csi_item_instance_id);
16311      AHL_DEBUG_PUB.debug('Inventory Item  ID:' || l_inventory_item_id);
16312      AHL_DEBUG_PUB.debug('INV master Org ID:' || l_inv_master_organization_id);
16313    END IF;
16314 
16315    -- Get Unit and Master Config IDs if available.
16316    -- Find the root item instance.
16317    l_root_csi_instance_id := Get_RootInstanceID(l_csi_item_instance_id);
16318 
16319    -- Get master and unit configuration for the root item instance.
16320    Get_Unit_Master_ConfigIDs (l_root_csi_instance_id,
16321                               l_uc_header_id, G_master_config_id);
16322 
16323    IF G_DEBUG = 'Y' THEN
16324      AHL_DEBUG_PUB.debug('Step 2: ROOT CSI: UCH: MCH:' || l_root_csi_instance_id || ':' || l_uc_header_id || ':' || G_master_config_id);
16325    END IF;
16326 
16327    -- Check for errors.
16328    IF FND_MSG_PUB.Count_msg > 0 THEN
16329       RAISE FND_API.G_EXC_ERROR;
16330    END IF;
16331 
16332    IF G_DEBUG = 'Y' THEN
16333      AHL_DEBUG_PUB.debug('Step 3');
16334    END IF;
16335 
16336    -- Get utilization forecast for the unit/part.
16337    Get_Utilization_Forecast (l_root_csi_instance_id,
16338                              l_uc_header_id,
16339                              l_inventory_item_id,
16340                              l_inv_master_organization_id,
16341                              G_forecast_details_tbl);
16342 
16343    IF G_DEBUG = 'Y' THEN
16344      AHL_DEBUG_PUB.debug('Step 4');
16345      AHL_DEBUG_PUB.debug('Count on util forecast tbl:' || G_forecast_details_tbl.count);
16346    END IF;
16347 
16348    -- Get the position installed in.
16349    OPEN csi_reln_csr(l_csi_item_instance_id);
16350    FETCH csi_reln_csr INTO l_position_reference;
16351    IF (csi_reln_csr%NOTFOUND) THEN
16352       l_position_reference := G_master_config_id;
16353    END IF;
16354    CLOSE csi_reln_csr;
16355 
16356    IF G_DEBUG = 'Y' THEN
16357      AHL_DEBUG_PUB.debug('Step 5');
16358    END IF;
16359 
16360    -- Build counter rules ratio if node is not root node.
16361    IF (G_master_config_id IS NOT NULL AND l_position_reference IS NOT NULL) THEN
16362        build_Counter_Ratio(l_position_reference,
16363                            l_csi_item_instance_id,
16364                            G_master_config_id,
16365                            l_counter_rules_tbl);
16366    END IF;
16367 
16368    IF G_DEBUG = 'Y' THEN
16369      AHL_DEBUG_PUB.debug('Step 6');
16370    END IF;
16371 
16372 
16373   -- read thresholds table.
16374   FOR unit_threshold_rec IN ahl_unit_threshold_csr(p_unit_effectivity_id) LOOP
16375 
16376         l_counter_remain := 0;
16377         l_due_at_counter_value := 0;
16378         l_current_ctr_value := 0;
16379 
16380        -- get counter usage.
16381        OPEN cs_ctr_counter_csr(unit_threshold_rec.counter_id);
16382        FETCH cs_ctr_counter_csr INTO l_current_ctr_value;
16383        IF (cs_ctr_counter_csr%NOTFOUND) THEN
16384           IF G_DEBUG = 'Y' THEN
16385             AHL_DEBUG_PUB.debug('Step 7');
16386           END IF;
16387           l_current_ctr_value := 0;
16388        END IF;
16389 
16390        CLOSE cs_ctr_counter_csr;
16391 
16392        IF G_DEBUG = 'Y' THEN
16393          AHL_DEBUG_PUB.debug('l_current_ctr_value:' || l_current_ctr_value);
16394        END IF;
16395 
16396       l_due_at_counter_value := unit_threshold_rec.counter_value;
16397       l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
16398 
16399       -- calculate due date from forecast.
16400       IF (l_counter_remain > 0) THEN
16401          -- get date from forecast.
16402          get_date_from_uf(l_counter_remain,
16403                           unit_threshold_rec.uom_code,
16404                           l_counter_rules_tbl,
16405                           null, -- start date = sysdate
16406                           l_due_date);
16407       ELSIF (l_counter_remain < 0) THEN
16408          -- Due date = counter reading date.
16409          get_ctr_date_for_reading (p_csi_item_instance_id => l_csi_item_instance_id,
16410                                    p_counter_id           => unit_threshold_rec.counter_id,
16411                                    p_counter_value        => l_due_at_counter_value,
16412                                    x_ctr_record_date      => l_counter_read_date,
16413                                    x_return_val           => l_return_val);
16414 
16415          IF NOT(l_return_val) THEN
16416             l_due_date := sysdate;
16417          ELSE
16418             l_due_date := l_counter_read_date;
16419          END IF;
16420 
16421       ELSIF (l_counter_remain = 0) THEN  -- due_date = sysdate
16422          --dbms_output.put_line ('counter remain less than zero');
16423          l_due_date := sysdate;
16424       END IF;
16425 
16426       IF (l_due_date IS NULL) THEN
16427            l_calc_due_date := NULL;
16428            l_calc_counter_id := unit_threshold_rec.counter_id;
16429            l_calc_due_counter_value := l_due_at_counter_value;
16430            EXIT;
16431       ELSIF (l_calc_due_date IS NULL) THEN
16432            l_calc_due_date := l_due_date;
16433            l_calc_counter_id := unit_threshold_rec.counter_id;
16434            l_calc_due_counter_value := l_due_at_counter_value;
16435       ELSE
16436          IF (trunc(l_due_date) < trunc(l_calc_due_date)) THEN
16437             l_calc_due_date := l_due_date;
16438             l_calc_counter_id := unit_threshold_rec.counter_id;
16439             l_calc_due_counter_value := l_due_at_counter_value;
16440          END IF;
16441       END IF;
16442 
16443   END LOOP;
16444   -- match due date with resolution date and pick earliest.
16445   -- get resolution date.
16446   BEGIN
16447     SELECT cs.expected_resolution_date
16448     INTO l_expected_resolution_date
16449     FROM ahl_unit_effectivities_b ue, cs_incidents_all_b cs
16450     WHERE ue.unit_effectivity_id = p_unit_effectivity_id
16451       AND cs.incident_id = ue.cs_incident_id;
16452   EXCEPTION
16453     WHEN OTHERS THEN
16454        null;
16455   END;
16456 
16457   IF (l_expected_resolution_date IS NOT NULL) AND (l_calc_due_date IS NOT NULL) THEN
16458     IF (trunc(l_expected_resolution_date) < trunc(l_calc_due_date)) THEN
16459        l_calc_due_date := l_expected_resolution_date;
16460        l_calc_counter_id := null;
16461        l_calc_due_counter_value := null;
16462     END IF;
16463   END IF;
16464 
16465   x_due_date          := l_calc_due_date;
16466   x_due_counter_value := l_calc_due_counter_value;
16467   x_counter_id        := l_calc_counter_id;
16468 
16469 END Calculate_NR_due_date;
16470 --------------------------
16471 
16472 END AHL_UMP_ProcessUnit_PVT;