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.26.12010000.2 2008/12/27 01:48:48 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 ----------------------------------------------------------------
14 -- Define local record structures used by Process Unit Procedure.
15 ----------------------------------------------------------------
16 -- To hold the counter rules.
17 TYPE counter_rules_rec_type IS RECORD(
18    UOM_CODE  VARCHAR2(3),
19    RATIO     NUMBER);
20 
21 -- To hold the applicable MRs table record.
22 TYPE applicable_mrs_rec_type IS RECORD(
23    CSI_ITEM_INSTANCE_ID      NUMBER,
24    MR_HEADER_ID              NUMBER,
25    TITLE                     AHL_MR_HEADERS_VL.TITLE%TYPE,
26    VERSION_NUMBER            NUMBER,
27    REPETITIVE_FLAG           VARCHAR2(1),
28    SHOW_REPETITIVE_CODE      VARCHAR2(30),
29    IMPLEMENT_STATUS_CODE     VARCHAR2(30),
30    COPY_ACCOMPLISHMENT_CODE  VARCHAR2(30),
31    PRECEDING_MR_HEADER_ID    NUMBER,
32    DESCENDENT_COUNT          NUMBER,
33    WHICHEVER_FIRST_CODE      VARCHAR2(30),
34    PROGRAM_MR_HEADER_ID      NUMBER,
35    SERVICE_LINE_ID           NUMBER,      -- from service contracts for PM installation.
36    PM_SCHEDULE_EXISTS        VARCHAR2(1), -- used only for PM installation.
37    CONTRACT_START_DATE       DATE,        -- used only for PM installation.
38    CONTRACT_END_DATE         DATE,        -- used only for PM installation.
39    PROGRAM_END_DATE          DATE,        -- used only for PM installation.
40    COVERAGE_IMP_LEVEL        NUMBER,      -- used only for PM installation.
41    EFFECTIVE_TO              DATE,
42    EFFECTIVE_FROM            DATE
43    );
44 
45 -- To hold the forecast details.
46 TYPE forecast_details_rec_type IS RECORD(
47    START_DATE     DATE,
48    END_DATE       DATE,
49    UOM_CODE       VARCHAR2(3),
50    USAGE_PER_DAY  NUMBER);
51 
52 -- To hold the ahl unit effectivity record details.
53 TYPE unit_effectivity_rec_type IS RECORD(
54    UNIT_EFFECTIVITY_ID  NUMBER,
55    STATUS_CODE          VARCHAR2(30),
56    DUE_DATE             DATE,
57    FORECAST_SEQUENCE    NUMBER,
58    RELATED_UE_ID        NUMBER,
59    ORIGINATOR_UE_ID     NUMBER,
60    VISIT_ASSIGN_FLAG    VARCHAR2(1),
61    VISIT_END_DATE       DATE);
62 
63 -- To hold the calculated next due details.
64 TYPE next_due_date_rec_type IS RECORD(
65    MR_EFFECTIVITY_ID     NUMBER,
66    MR_INTERVAL_ID        NUMBER,
67    DUE_DATE              DATE,
68    DUE_AT_COUNTER_VALUE  NUMBER,
69    CURRENT_CTR_VALUE     NUMBER,
70    LAST_CTR_VALUE        NUMBER,
71    MESSAGE_CODE          VARCHAR2(30),
72    TOLERANCE_AFTER       NUMBER,
73    TOLERANCE_BEFORE      NUMBER,
74    TOLERANCE_FLAG        VARCHAR2(1),
75    CTR_UOM_CODE          VARCHAR2(3),
76    EARLIEST_DUE_DATE     DATE,
77    LATEST_DUE_DATE       DATE,
78    COUNTER_ID            NUMBER,
79    -- Added to fix bug# 4224867.
80    COUNTER_REMAIN        NUMBER);
81 
82 /*TYPE MR_RELATIONSHIP_REC IS RECORD (
83    MR_HEADER_ID          NUMBER,
84    RELATED_MR_HEADER_ID  NUMBER,
85    RELATIONSHIP_CODE     VARCHAR2(30)); */
86 
87 -- To hold the PM program details.
88 TYPE PMprogram_rec_type IS RECORD(
89    PROGRAM_MR_HEADER_ID   NUMBER,
90    MR_EFFECTIVITY_ID      NUMBER);
91 
92 -- Begin -- Added for performance fix bug# 6893404.
93 -- number table.
94 TYPE nbr_tbl_type IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
95 
96 -- varchar2 table.
97 TYPE vchar_tbl_type IS TABLE OF VARCHAR2(400) INDEX BY BINARY_INTEGER;
98 -- End -- Added for performance fix bug# 6893404.
99 
100 ----------------------------------------------
101 -- Define Table Types for record structures --
102 ----------------------------------------------
103 TYPE unit_effectivity_tbl_type IS TABLE OF unit_effectivity_rec_type INDEX BY BINARY_INTEGER;
104 TYPE counter_rules_tbl_type IS TABLE OF counter_rules_rec_type INDEX BY BINARY_INTEGER;
105 TYPE forecast_details_tbl_type IS TABLE OF forecast_details_rec_type INDEX BY BINARY_INTEGER;
106 
107 --TYPE MR_RELATIONSHIP_TBL IS TABLE OF MR_RELATIONSHIP_REC INDEX BY BINARY_INTEGER;
108 
109 TYPE PMprogram_tbl_type IS TABLE OF PMprogram_rec_type INDEX BY BINARY_INTEGER;
110 
111 ------------------------------
112 -- Declare Local Procedures --
113 ------------------------------
114 -- To get the unit and master configurations IDs for the input item instance.
115 PROCEDURE Get_Unit_Master_ConfigIDs (p_csi_item_instance_id IN NUMBER,
116                                      x_uc_header_id OUT NOCOPY NUMBER,
117                                      x_master_config_id OUT NOCOPY NUMBER);
118 
119 -- To get the root item instance for the input item instance if exists.
120 FUNCTION Get_RootInstanceID(p_csi_item_instance_id IN NUMBER)
121 RETURN NUMBER;
122 
123 -- Validate the input item instance.
124 PROCEDURE Validate_Item_Instance (p_csi_item_instance_id       IN NUMBER,
125                                   x_inventory_item_id          OUT NOCOPY NUMBER,
126                                   x_inv_master_organization_id OUT NOCOPY NUMBER);
127 
128 -- Build the item instance tree containing root nodes and its components.
129 PROCEDURE Build_Config_Tree(p_csi_root_instance_id  IN         NUMBER,
130                             p_master_config_id      IN         NUMBER,
131                             x_config_node_tbl       OUT NOCOPY AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type);
132 
133 
134 -- To get the last day of the rolling window from profile values.
135 FUNCTION Get_Rolling_Window_Date RETURN DATE;
136 
137 -- Procedure to build unit effectivity for ASO Installation.
138 -- Called from Process_Unit API. This procedure uses the global variables
139 -- set in 'Process Unit' API for processing.
140 PROCEDURE Process_ASO_Unit;
141 
142 -- Get the utilization forecast applicable to the input item instance/unit.
143 PROCEDURE Get_Utilization_Forecast (p_csi_item_instance_id IN         NUMBER,
144                                     p_uc_header_id         IN         NUMBER,
145                                     p_inventory_item_id    IN         NUMBER,
146                                     p_inventory_org_id     IN         NUMBER,
147                                     x_forecast_details_tbl OUT NOCOPY forecast_details_tbl_type);
148 
149 -- Lock all existing unit effectivity records.
150 PROCEDURE Lock_UnitEffectivity_Records(x_ret_code  OUT NOCOPY VARCHAR2);
151 
152 -- Build the counter ratio that needs to be applied to the item instance based
153 -- on its master configuration position. Input is the item instance.
154 PROCEDURE build_Counter_Ratio(p_position_reference   IN         VARCHAR2,
155                               p_csi_item_instance_id IN         NUMBER,
156                               p_master_config_id     IN         NUMBER,
157                               x_counter_rules_tbl    OUT NOCOPY counter_rules_tbl_type);
158 
159 -- Build the current usage on the item instance's counters based on counters attached
160 -- to the item instance.
161 PROCEDURE get_Current_Usage ( p_csi_item_instance_id IN         NUMBER,
162                               x_current_usage_tbl    OUT NOCOPY counter_values_tbl_type );
163 
164 -- Get accomplishment details for an MR.
165 -- Added parameter x_no_forecast to fix bug# 6711228
166 PROCEDURE get_accomplishment_details (p_applicable_mrs_rec       IN         applicable_mrs_rec_type,
167                                       p_current_usage_tbl        IN         counter_values_tbl_type,
168                                       p_counter_rules_tbl        IN         counter_rules_tbl_type,
169                                       x_accomplishment_date      OUT NOCOPY DATE,
170                                       x_last_acc_counter_val_tbl OUT NOCOPY counter_values_tbl_type,
171                                       x_one_time_mr_flag         OUT NOCOPY BOOLEAN,
172                                       x_dependent_mr_flag        OUT NOCOPY BOOLEAN,
173                                       x_get_preceding_next_due   OUT NOCOPY BOOLEAN,
174                                       x_mr_accomplish_exists     OUT NOCOPY BOOLEAN,
175                                       x_no_forecast_flag         OUT NOCOPY BOOLEAN);
176 
177 
178 -- Build unit effectivity for a given item instance and a maintenance requirement.
179 -- The unit effectivities created here will be written into a temporary table.
180 PROCEDURE Build_Effectivity ( p_applicable_mrs_rec IN applicable_mrs_rec_type,
181                               p_current_usage_tbl  IN counter_values_tbl_type,
182                               p_counter_rules_tbl  IN counter_rules_tbl_type );
183 
184 -- Calculate due date for the item instance and mr using current usage, counter rules,
185 -- last accomplishment counters and forecast (defined in global variable).
186 -- Added parameter p_dependent_mr_flag to fix bug# 6711228.
187 -- Added parameters p_mr_accomplish_exists and p_last_due_mr_interval_id to fix bug# 6858788.
188 PROCEDURE Calculate_Due_Date ( p_repetivity_flag    IN VARCHAR2 := 'Y',
189                                p_applicable_mrs_rec IN applicable_mrs_rec_type,
190                                p_current_usage_tbl  IN counter_values_tbl_type,
191                                p_counter_rules_tbl  IN counter_rules_tbl_type,
192                                p_last_due_date      IN DATE,
193                                p_last_due_counter_val_tbl IN counter_values_tbl_type,
194                                p_dependent_mr_flag  IN BOOLEAN := FALSE,
195                                p_mr_accomplish_exists IN BOOLEAN,
196                                p_last_due_mr_interval_id IN NUMBER := NULL,
197                                x_next_due_date_rec  OUT NOCOPY next_due_date_rec_type);
198 
199 
200 -- Calculate due at counter values for a given due due from last due date and last due counters using
201 -- counter rules and forecast (defined in global variable).
202 PROCEDURE Get_Due_At_Counter_Values ( p_last_due_date IN DATE,
203                                       p_last_due_counter_val_tbl IN counter_values_tbl_type,
204                                       p_due_date IN DATE,
205                                       p_counter_rules_tbl IN counter_rules_tbl_type,
206                                       x_due_at_counter_val_tbl OUT NOCOPY counter_values_tbl_type,
207                                       x_return_value      OUT NOCOPY BOOLEAN);
208 
209 -- Calculates the due date for the counter_remain from a given start date using forecast, counter rules
210 -- and counter uom.
211 PROCEDURE Get_Date_from_UF ( p_counter_remain IN NUMBER,
212                              p_counter_uom_code IN VARCHAR2,
213                              p_counter_rules_tbl IN counter_rules_tbl_type,
214                              p_start_date IN DATE := NULL,
215                              x_due_date         OUT NOCOPY DATE);
216 
217 -- Apply the counter ratio factor to convert a given counter value at a component level to the
218 -- root instance. This is needed as forecast is only defined at root instance.
219 FUNCTION Apply_Counter_Ratio ( p_counter_remain IN NUMBER,
220                                p_counter_uom_code IN VARCHAR2,
221                                p_counter_rules_tbl IN counter_rules_tbl_type)
222 RETURN NUMBER;
223 
224 -- Apply the counter ratio factor to convert a given counter value at a root instance level to the
225 -- component. This is needed as forecast is only defined at root instance.
226 FUNCTION Apply_ReverseCounter_Ratio ( p_counter_remain IN NUMBER,
227                                       p_counter_uom_code IN VARCHAR2,
228                                       p_counter_rules_tbl IN counter_rules_tbl_type)
229 RETURN NUMBER;
230 
231 -- This will return the adjusted interval value if the next due counter value overlaps two intervals.
232 -- It will be used where the overflow condition occurs based on the interval's start value and stop value.
233 PROCEDURE Adjust_Interval_Value ( p_mr_effectivity_id IN NUMBER,
234                                   p_counter_id IN NUMBER,
235                                   p_counter_value IN NUMBER,
236                                   p_interval_value IN NUMBER,
237                                   p_stop_value IN NUMBER,
238                                   x_adjusted_int_value OUT NOCOPY NUMBER,
239                                   x_nxt_interval_found OUT NOCOPY BOOLEAN);
240 
241 -- This will return the adjusted due date if the next due date overlaps two intervals.
242 -- It will be used where the overflow condition occurs based on the interval's start date and stop date.
243 PROCEDURE Adjust_Due_Date ( p_mr_effectivity_id IN NUMBER,
244                             p_start_counter_rec IN counter_values_rec_type,
245                             p_start_due_date    IN DATE,
246                             p_counter_rules_tbl IN counter_rules_tbl_type,
247                             p_interval_value IN NUMBER,
248                             p_stop_date IN DATE,
249                             p_due_date IN DATE,
250                             x_adjusted_due_date OUT NOCOPY DATE,
251                             x_adjusted_due_ctr  OUT NOCOPY NUMBER,
252                             x_nxt_interval_found OUT NOCOPY BOOLEAN);
253 
254 -- This procedure will return due date based on the next interval(if exists), whenever an interval
255 -- is not found for the current start/stop values or dates.
256 -- Added parameter p_dependent_mr_flag to fix bug# 6711228.
257 -- Added parameter p_mr_accomplish_exists and p_last_due_mr_interval_id to fix bug# 6858788. Commented
258 -- p_last_accomplishment_date and will instead use p_mr_accomplish_exists.
259 PROCEDURE Get_DueDate_from_NxtInterval(p_applicable_mrs_rec      IN  applicable_mrs_rec_type,
260                                        p_repetivity_flag         IN  VARCHAR2,
261                                        p_mr_effectivity_id       IN  NUMBER,
262                                        p_current_ctr_rec         IN  Counter_values_rec_type,
263                                        p_current_ctr_at_date     IN  DATE,
264                                        p_counter_rules_tbl       IN  Counter_rules_tbl_type,
265                                        p_start_int_match_at_ctr  IN  NUMBER,
266                                        p_last_accomplish_ctr_val IN  NUMBER,
267                                        --p_last_accomplishment_date IN DATE,
268                                        p_dependent_mr_flag       IN  BOOLEAN,
269                                        p_mr_accomplish_exists    IN  BOOLEAN,
270                                        p_last_due_mr_interval_id IN  NUMBER,
271                                        x_next_due_date_rec       OUT NOCOPY next_due_date_rec_type,
272                                        x_mr_interval_found       OUT NOCOPY BOOLEAN,
273                                        x_return_val              OUT NOCOPY BOOLEAN);
274 
275 -- To write a record into ahl_temp_unit_effectivities.
276 PROCEDURE Create_temp_unit_effectivity (X_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE);
277 
278 -- To process the decendents in case the mr is a group MR.
279 PROCEDURE Process_GroupMR (p_applicable_mrs_rec  IN applicable_mrs_rec_type,
280                            p_new_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE,
281                            p_unit_effectivity_tbl IN unit_effectivity_tbl_type,
282                            p_old_UE_forecast_sequence IN NUMBER := -1);
283 
284 -- To process the dependent MRs based on the value of preceding MR.
285 PROCEDURE Process_PrecedingMR (p_applicable_mrs_rec IN applicable_mrs_rec_type,
286                                p_counter_rules_tbl  IN counter_rules_tbl_type,
287                                p_current_usage_tbl  IN counter_values_tbl_type);
288 
289 
290 -- To update the preceding_check_flag in the temporary unit effectivities table.
291 PROCEDURE Update_check_flag (p_applicable_mrs_rec IN applicable_mrs_rec_type,
292                              p_dependent_mr_flag IN BOOLEAN,
293                              p_next_due_date_rec IN next_due_date_rec_type);
294 
295 -- To log error messages into a log file if called from concurrent process.
296 PROCEDURE log_error_messages;
297 
298 
299 -------------------------------------------------
300 -- Procedures for Preventive Maintenance Logic --
301 -------------------------------------------------
302 -- Populate applicable MRs temporary table from the output of FMP API.
303 PROCEDURE PopulatePM_Appl_MRs (p_csi_ii_id      IN  NUMBER,
304                                x_return_status  OUT NOCOPY VARCHAR2,
305                                x_msg_count      OUT NOCOPY NUMBER,
306                                x_msg_data       OUT NOCOPY VARCHAR2,
307                                x_UnSch_programs_tbl OUT NOCOPY PMprogram_tbl_type);
308 
309 -- Procedure to build instance level effectivity for PM installation
310 -- using service contracts.
311 -- Called from Process_Unit API.
312 PROCEDURE Process_PM_Unit(p_csi_item_instance_id IN    NUMBER,
313                           p_UnSch_programs_tbl   IN    PMprogram_tbl_type);
314 
315 
316 -- Calculate program end date for all MR's where contract is not scheduled.
317 PROCEDURE Calc_program_end_dates (p_UnSch_programs_tbl IN PMprogram_tbl_type,
318                                   p_current_usage_tbl  IN counter_values_tbl_type);
319 
320 -- Process records with contract dates scheduled.
321 PROCEDURE Process_PMSch_Activities;
322 
323 -- Process records with no contract dates.
324 PROCEDURE Process_PMUnSch_Activities(p_current_usage_tbl IN counter_values_tbl_type);
325 
326 -- Procedure to find the service_line_id and program for a calculated due_date.
327 -- The calculated due_date may be overridden by the contract/program dates.
328 -- Also the earliest due and latest due date will get adjusted if they are not
329 -- within the contract and program start/end dates.
330 PROCEDURE Get_PMprogram(p_csi_item_instance_id       IN  NUMBER,
331                         p_mr_header_id               IN  NUMBER,
332                         p_last_due_date              IN  DATE,
333                         p_due_date                   IN  DATE,
334                         p_earliest_due               IN  DATE,
335                         p_latest_due                 IN  DATE,
336                         x_program_mr_header_id       OUT NOCOPY NUMBER,
337                         x_service_line_id            OUT NOCOPY NUMBER,
338                         x_contract_override_due_date OUT NOCOPY DATE,
339                         x_cont_override_earliest_due OUT NOCOPY DATE,
340                         x_cont_override_latest_due   OUT NOCOPY DATE,
341                         x_contract_found_flag        OUT NOCOPY BOOLEAN);
342 
343 -- After creation of all maintenance requirements for the instance in the temporary table,
344 -- assign unit effectivity IDs from existing un-accomplished maintenance requirements
345 -- from ahl_unit_effectivities_b.
346 PROCEDURE Assign_Unit_effectivity_IDs;
347 
348 -- Fix for Prev. Maint. performance bug# 5093064.
349 -- instead of calling procedure AHL_FMP_PVT.GET_MR_AFFECTED_ITEMS,
350 -- write PM effectivity logic in this procedure.
351 PROCEDURE Process_PM_MR_Affected_Items(p_commit           IN            VARCHAR2 := FND_API.G_FALSE,
352                                        x_msg_count           OUT NOCOPY NUMBER,
353                                        x_msg_data            OUT NOCOPY VARCHAR2,
354                                        x_return_status       OUT NOCOPY VARCHAR2,
355                                        p_mr_header_id     IN            NUMBER,
356                                        p_old_mr_header_id IN            NUMBER := NULL,
357                                        p_concurrent_flag  IN            VARCHAR2 := 'N',
358                                        p_num_of_workers   IN            NUMBER := 10);
359 
360 --------------------------------------------------------------------
361 -- Following procedures have been added for 11.5.10 Enhancements. --
362 --------------------------------------------------------------------
363 -- Get the latest recorded counter reading for a given date.
364 PROCEDURE get_ctr_reading_for_date (p_csi_item_instance_id IN NUMBER,
365                                     p_counter_id           IN NUMBER,
366                                     p_reading_date         IN DATE,
367                                     x_net_reading        OUT NOCOPY NUMBER);
368 
369 -- Get the earliest date on which a given reading was recorded.
370 PROCEDURE get_ctr_date_for_reading (p_csi_item_instance_id IN NUMBER,
371                                     p_counter_id           IN NUMBER,
372                                     p_counter_value        IN NUMBER,
373                                     x_ctr_record_date    OUT NOCOPY DATE,
374                                     x_return_val         OUT NOCOPY BOOLEAN);
375 
376 -- Calculate due date all deferred unit effectivities.
377 PROCEDURE Process_Deferred_UE (p_csi_item_instance_id IN NUMBER,
378                                p_current_usage_tbl  IN counter_values_tbl_type,
379                                p_counter_rules_tbl  IN counter_rules_tbl_type);
380 
381 -- Explode SR's having MRs for calculating MR due dates.
382 PROCEDURE Process_SR_UE (p_csi_item_instance_id IN NUMBER);
383 
384 -- Match if current UE group MR matches the applicable group MR.
385 PROCEDURE Match_Group_MR (p_orig_csi_item_instance_id  IN  NUMBER,
386                           p_orig_mr_header_id          IN  NUMBER,
387                           p_unit_effectivity_id        IN  NUMBER,
388                           x_group_match_flag           OUT NOCOPY VARCHAR2);
389 
390 -----------------------------------------------------------------------------------
391 -- Following procedures have been added for 11.5.10+ Transit Check Enhancements. --
392 -----------------------------------------------------------------------------------
393 
394 -- Validate applicability for Unplanned MRs (MRs directly planned into a Visit from FMP).
395 PROCEDURE Process_Unplanned_UE(p_csi_item_instance_id IN NUMBER);
396 
397 ---------------------------------------
398 -- added to fix performance bug 5093064.
399 ---------------------------------------
400 -- Split instances based on instance count.
401 PROCEDURE Instance_Split_BTree(p_csi_max_id  in NUMBER,
402                                p_csi_min_id  IN NUMBER,
403                                p_num_workers IN NUMBER,
404                                p_mr_header_id IN NUMBER,
405                                p_total_inst_count  IN NUMBER);
406 
407 
408 -- Split instance range into blocks based on instance IDs.
409 PROCEDURE Instance_Split_Sequential(p_csi_max_id  in NUMBER,
410                                     p_csi_min_id  IN NUMBER,
411                                     p_num_workers IN NUMBER,
412                                     p_mr_header_id IN NUMBER);
413 
414 ----------------------------------------------
415 -- Following procedures have been added R12 --
416 ----------------------------------------------
417 -- Added to fix bug# 4224867.
418 -- find usage forecast for a given date.
419 PROCEDURE get_usage_for_date(p_due_date          IN DATE,
420                              p_counter_uom_code  IN VARCHAR2,
421                              p_counter_rules_tbl IN Counter_rules_tbl_type,
422                              x_usage_per_day     OUT NOCOPY NUMBER);
423 
424 -- Added to fix bug# 6875650.
425 -- Get the latest recorded counter reading for a given date-time.
426 PROCEDURE get_ctr_reading_for_datetime (p_csi_item_instance_id IN NUMBER,
427                                         p_counter_id           IN NUMBER,
428                                         p_reading_date         IN DATE,
429                                         x_net_reading          OUT NOCOPY NUMBER);
430 
431 
432 -- Added for performance bug# 6893404.
433 -- Identify affected units and process or launch concurrent workers for AHL processing.
434 PROCEDURE Split_Process_All_Instances(p_concurrent_flag  IN  VARCHAR2,
435                                       p_commit_flag      IN  VARCHAR2,
436                                       p_num_of_workers   IN  NUMBER,
437                                       p_mr_header_id     IN  NUMBER,
438                                       p_mtl_category_id  IN  NUMBER,
439                                       p_process_option   IN  VARCHAR2,
440                                       x_msg_count        OUT NOCOPY  NUMBER,
441                                       x_msg_data         OUT NOCOPY  NUMBER,
442                                       x_return_status    OUT NOCOPY  VARCHAR2);
443 
444 -- Added for performance bug# 6893404.
445 -- Write into BUW worker table when processing all units.
446 PROCEDURE Populate_BUE_Worker(p_conc_request_id IN  NUMBER,
447                               p_concurrent_flag IN  VARCHAR2,
448                               p_mtl_category_id IN  NUMBER,
449                               p_process_option  IN  VARCHAR2,
450                               errbuf            OUT NOCOPY VARCHAR2,
451                               x_return_status   OUT NOCOPY VARCHAR2);
452 
453 
454 -- Write into BUW worker table when processing for a MR.
455 PROCEDURE Populate_BUE_Worker_for_MR(p_conc_request_id IN  NUMBER,
456                                      p_mr_header_id    IN  NUMBER,
457                                      p_concurrent_flag IN  VARCHAR2,
458                                      p_mtl_category_id IN  NUMBER,
459                                      p_process_option  IN  VARCHAR2,
460                                      x_return_status   OUT NOCOPY VARCHAR2);
461 
462 -- Added for performance bug# 6893404.
463 -- get next instance from BUE worker table to process.
464 PROCEDURE Get_Next_BUE_Row(p_parent_conc_pgm_id    IN  NUMBER,
465                            p_conc_child_req_id     IN  NUMBER,
466                            x_return_status         OUT NOCOPY VARCHAR2,
467                            errbuf                  OUT NOCOPY VARCHAR2,
468                            x_item_instance_id      OUT NOCOPY NUMBER);
469 
470 
471 -- Added for performance bug# 6893404.
472 -- cleanup worker table
473 PROCEDURE Cleanup_BUE_Worker(p_parent_conc_request_id IN  NUMBER,
474                              p_child_conc_request_id  IN  NUMBER);
475 
476 
477 -- added to fix bug# 6907562.
478 -- function that compares previous due date and uom remain with current values
479 -- and return Y is the current due date replaces the prev one.
480 FUNCTION validate_for_duedate_reset(p_due_date        IN DATE,
481                                     p_uom_remain      IN NUMBER,
482                                     p_prev_due_date   IN DATE,
483                                     p_prev_counter_id IN NUMBER,
484                                     p_prev_uom_remain IN NUMBER) RETURN VARCHAR2;
485 
486 -- procedure checks forecast and adds zero forecast row if missing forecast.
487 PROCEDURE validate_uf_for_ctr(p_current_usage_tbl       IN counter_values_tbl_type,
488                               p_x_forecast_details_tbl IN OUT NOCOPY forecast_details_tbl_type);
489 
490 ------------------------------
491 -- Declare global variables --
492 ------------------------------
493 G_config_node_tbl      AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type;
494 -- This variable holds all the item instances that are contained in a configuration.
495 -- For AHL installation, this will hold the top node and all of its components.
496 -- For PM installation, this will contain only one item instance, because each
497 -- component of a configuration is processed as a unit for this case.
498 
499 G_forecast_details_tbl forecast_details_tbl_type;
500 -- This variable holds the forecast information for the unit that is being
501 -- processed. This variable is set in procedure Process_Unit.
502 
503 G_last_day_of_window   DATE;
504 -- This variable holds the last day of the rolling window, calculated based on
505 -- the profile values set. This is set in procedure Process_Unit.
506 
507 G_master_config_id  NUMBER;
508 -- This variable holds the Master config ID if configuration has a master Configuration.
509 -- Not Applicable for PM installation.
510 
511 G_application_usg_code VARCHAR2(30);
512 -- This variable is populated based on the AHL_APPLN_USAGE profile value.
513 -- 11.5.10 enhancement.
514 
515 -----------------------
516 -- Define Procedures --
517 -----------------------
518 
519 -- Start of Comments --
520 --  Procedure name    : Process_Unit
521 --  Type        : Private
522 --  Function    : Manages Create/Modify/Delete operations of applicable maintenance
523 --                requirements on a unit.
524 --  Pre-reqs    :
525 --  Parameters  :
526 --
527 --  Standard OUT Parameters :
528 --      x_return_status                 OUT     VARCHAR2               Required
529 --      x_msg_count                     OUT     NUMBER                 Required
530 --      x_msg_data                      OUT     VARCHAR2               Required
531 --
532 --  Process_Unit Parameters :
533 --      Unit's Effectivity will be built for the input item instance.
534 --
535 
536 PROCEDURE Process_Unit (
537     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
538     p_init_msg_list          IN            VARCHAR2  := FND_API.G_FALSE,
539     x_msg_count              OUT  NOCOPY   NUMBER,
540     x_msg_data               OUT  NOCOPY   VARCHAR2,
541     x_return_status          OUT  NOCOPY   VARCHAR2,
542     p_csi_item_instance_id   IN            NUMBER,
543     p_concurrent_flag        IN            VARCHAR2 := 'N')
544 IS
545 
546   l_inventory_item_id  NUMBER;
547   l_inv_master_organization_id NUMBER;
548 
549   l_uc_header_id    NUMBER;
550   -- This variable holds the Unit config ID if configuration is a Unit Configuration.
551   -- Not Applicable for PM installation.
552 
553   l_csi_item_instance_id  NUMBER;
554   -- This variable holds the Root item instance id.
555   -- For AHL installation, this is the root item instance of the input parameter p_csi_item_instance_id
556   -- For PM installation, this is the item instance input to this procedure(i.e p_csi_item_instance_id).
557 
558   l_config_node_tbl      AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type;
559   l_forecast_details_tbl forecast_details_tbl_type;
560 
561   l_UnSch_programs_tbl   PMprogram_tbl_type;
562   -- contains programs and their effectivities.
563 
564   l_ret_code             VARCHAR2(30);
565 
566 BEGIN
567 
568   -- Standard start of API savepoint
569   SAVEPOINT Process_Unit_PVT;
570 
571  -- Initialize message list if p_init_msg_list is set to TRUE
572   IF FND_API.To_Boolean(p_init_msg_list) THEN
573     FND_MSG_PUB.Initialize;
574   END IF;
575 
576   -- Initialize Procedure return status to success
577   x_return_status := FND_API.G_RET_STS_SUCCESS;
578 
579   -- Enable Debug.
580   IF G_DEBUG = 'Y' THEN
581     AHL_DEBUG_PUB.enable_debug;
582   END IF;
583 
584   -- Add debug mesg.
585   IF G_DEBUG = 'Y' THEN
586     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'ProcessUnit');
587 
588     -- Dump input parameters.
589     AHL_DEBUG_PUB.debug(' Csi Item instance ID:' || p_csi_item_instance_id);
590     AHL_DEBUG_PUB.debug(' p_concurrent_flag:' || p_concurrent_flag );
591     AHL_DEBUG_PUB.debug(' p_commit:' || p_commit);
592 
593   END IF;
594 
595   G_concurrent_flag := p_concurrent_flag;
596 
597   IF (p_concurrent_flag = 'Y') THEN
598      fnd_file.put_line(fnd_file.log, 'Starting Process Unit for item instance: '|| p_csi_item_instance_id);
599      --fnd_file.put_line(fnd_file.log, 'G_IS_PM_INSTALLED: '|| G_IS_PM_INSTALLED);
600   END IF;
601 
602   -- Initialize temporary tables.
603 
604   DELETE FROM AHL_TEMP_UNIT_EFFECTIVITIES;
605   DELETE FROM AHL_TEMP_UNIT_SR_DEFERRALS;
606 
607   -- validate item instance.
608   Validate_item_instance(p_csi_item_instance_id, l_inventory_item_id,
609                          l_inv_master_organization_id);
610 
611   IF FND_MSG_PUB.Count_msg > 0 THEN
612      RAISE FND_API.G_EXC_ERROR;
613   END IF;
614 
615   -- Log success message if called by concurrent program.
616   IF (p_concurrent_flag = 'Y') THEN
617     fnd_file.put_line (FND_FILE.LOG, 'Validated Instance:'||p_csi_item_instance_id);
618   END IF;
619 
620   -- set instance variable.
621   l_csi_item_instance_id := p_csi_item_instance_id;
622 
623 
624   -- Set configuration variables based on installation type.
625   IF (G_IS_PM_INSTALLED = 'N') THEN
626   -- Only for AHL installation.
627 
628       -- If item instance is not top node, find the root item instance.
629       l_csi_item_instance_id := Get_RootInstanceID(l_csi_item_instance_id);
630 
631       -- Get master and unit configuration IDs if they exist for this item instance.
632       Get_Unit_Master_ConfigIDs (l_csi_item_instance_id,
633                                  l_uc_header_id, G_master_config_id);
634 
635       -- Check for errors.
636       IF FND_MSG_PUB.Count_msg > 0 THEN
637          RAISE FND_API.G_EXC_ERROR;
638       END IF;
639 
640       -- Build the Configuration tree structure.(G_config_node_tbl).
641       Build_Config_Tree(l_csi_item_instance_id, G_master_config_id, G_CONFIG_NODE_TBL);
642 
643   ELSE
644   -- For PM installation.
645 
646       -- Intialize config node table consisting of the input item instance.
647       G_config_node_tbl(1).csi_item_instance_id := p_csi_item_instance_id;
648 
649   END IF;  -- pm_install check
650 
651   -- Add debug mesg.
652   IF G_DEBUG = 'Y' THEN
653     AHL_DEBUG_PUB.debug(' Count on Config Node Tbl:' || G_config_node_tbl.COUNT);
654     AHL_DEBUG_PUB.debug(' Root Node:' || l_csi_item_instance_id );
655     AHL_DEBUG_PUB.debug(' Unit Config ID:' || l_uc_header_id);
656     AHL_DEBUG_PUB.debug(' Master Config ID:' || G_master_config_id);
657   END IF;
658 
659   -- Get rolling window end date.
660   G_last_day_of_window := Get_Rolling_Window_Date;
661 
662   -- Call FMP to get applicable MRs.
663   IF (G_IS_PM_INSTALLED = 'N') THEN
664    -- Only for AHL installation.
665 
666       IF G_DEBUG = 'Y' THEN
667         AHL_DEBUG_PUB.debug('AHL Installation processing');
668       END IF;
669 
670        -- Call FMP api to build applicable MRs for the unit.
671        AHL_UMP_UTIL_PKG.Populate_Appl_MRs ( p_csi_ii_id => l_csi_item_instance_id,
672                                             --p_include_doNotImplmt => 'N',
673                                             p_include_doNotImplmt => 'Y',
674                                             x_return_status => x_return_status,
675                                             x_msg_count => x_msg_count,
676                                             x_msg_data => x_msg_data );
677 
678        IF (x_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
679           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
680        ELSIF (x_return_status = FND_API.G_RET_STS_ERROR) THEN
681           RAISE FND_API.G_EXC_ERROR;
682        END IF;
683 
684        -- Build applicability for group MRs.
685        AHL_UMP_UTIL_PKG.Process_Group_MRs;
686 
687   ELSE  -- for PM installation.
688        IF G_DEBUG = 'Y' THEN
689          AHL_DEBUG_PUB.debug('PM Installation processing');
690        END IF;
691 
692        -- Call FMP-PM api to build applicable MRs for an instance.
693        PopulatePM_Appl_MRs (p_csi_ii_id => l_csi_item_instance_id,
694                             x_return_status => x_return_status,
695                             x_msg_count => x_msg_count,
696                             x_msg_data => x_msg_data,
697                             x_UnSch_programs_tbl => l_UnSch_programs_tbl);
698 
699        IF (x_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
700          RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
701        ELSIF (x_return_status = FND_API.G_RET_STS_ERROR) THEN
702          RAISE FND_API.G_EXC_ERROR;
703        END IF;
704 
705   END IF; -- pm_install check.
706 
707   IF G_DEBUG = 'Y' THEN
708     AHL_DEBUG_PUB.debug('After calling FMP API and process group MRs');
709   END IF;
710 
711   -- Read applicable utilization forecast for the configuration.
712   Get_Utilization_Forecast (l_csi_item_instance_id,
713                             l_uc_header_id,
714                             l_inventory_item_id,
715                             l_inv_master_organization_id,
716                             G_forecast_details_tbl);
717 
718 
719   -- Lock records.
720   FOR i IN 1..4 LOOP
721     Lock_UnitEffectivity_Records(x_ret_code => l_ret_code);
722     EXIT WHEN (l_ret_code <> '-54');
723     DBMS_LOCK.SLEEP(30);
724   END LOOP;
725 
726   IF (l_ret_code = -54) THEN
727     FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_ALREADY_RUNNING');
728     FND_MSG_PUB.ADD;
729     RAISE  FND_API.G_EXC_ERROR;
730   END IF;
731 
732   /*
733   -- Log success message if called by concurrent program.
734   IF (p_concurrent_flag = 'Y') THEN
735     fnd_file.put_line (FND_FILE.LOG, 'G Config Tbl:' || G_config_node_tbl.COUNT);
736     fnd_file.put_line (FND_FILE.LOG, 'G_forecast_details_tbl:' || G_forecast_details_tbl.count);
737     fnd_file.put_line (FND_FILE.LOG, 'Last Day window:' || G_last_day_of_window);
738     fnd_file.put_line (FND_FILE.LOG, 'UC Header ID:' || l_uc_header_id);
739   END IF;
740   */
741 
742   -- Note: Both of the procedures Process_ASO_Unit and Process_PM_Unit use global variables
743   -- set by this procedure in addition to any input parameters.
744   IF (G_IS_PM_INSTALLED = 'N') THEN
745      Process_ASO_Unit;
746   ELSE
747      Process_PM_Unit(p_csi_item_instance_id  => l_csi_item_instance_id,
748                      p_UnSch_programs_tbl    => l_UnSch_programs_tbl);
749   END IF;
750 
751   -- Flush from temporary table to ahl_unit_effectivities.
752   AHL_UMP_PROCESSUNIT_EXTN_PVT.Flush_From_Temp_Table(G_config_node_tbl);
753 
754   -- Check for errors.
755   IF FND_MSG_PUB.Count_msg > 0 THEN
756      RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
757   END IF;
758 
759   /* -- commented for performance fix - bug# 6893404
760   IF (G_IS_PM_INSTALLED = 'N') THEN
761    -- Only for AHL installation.
762 
763     --call for material requirement forecst
764     AHL_UMP_FORECAST_REQ_PVT.process_mrl_req_forecast
765     (
766      p_api_version                => 1.0,
767      p_init_msg_list              => FND_API.G_TRUE,
768      p_commit                     => FND_API.G_FALSE,
769      p_validation_level           => FND_API.G_VALID_LEVEL_FULL,
770      x_return_status              => x_return_status,
771      x_msg_count                  => x_msg_count,
772      x_msg_data                   => x_msg_data,
773      p_applicable_instances_tbl   => G_config_node_tbl
774     );
775 
776     -- Check for errors.
777     IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
778        RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
779     END IF;
780 
781   END IF;
782   */
783 
784   -- Standard check of p_commit
785   IF FND_API.TO_BOOLEAN(p_commit) THEN
786       COMMIT WORK;
787   END IF;
788 
789   -- Log success message if called by concurrent program.
790   IF (p_concurrent_flag = 'Y') THEN
791     fnd_file.put_line (FND_FILE.LOG, 'Message-Successfully processed:'||p_csi_item_instance_id);
792   END IF;
793 
794   -- Standard call to get message count and if count is 1, get message info
795   FND_MSG_PUB.Count_And_Get
796     ( p_count => x_msg_count,
797       p_data  => x_msg_data,
798       p_encoded => fnd_api.g_false
799     );
800 
801 --
802 EXCEPTION
803  WHEN FND_API.G_EXC_ERROR THEN
804    x_return_status := FND_API.G_RET_STS_ERROR;
805    Rollback to Process_Unit_PVT;
806    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
807                               p_data  => x_msg_data,
808                               p_encoded => fnd_api.g_false);
809 
810    IF (p_concurrent_flag = 'Y') THEN
811 
812      fnd_file.put_line(fnd_file.log, 'Process Unit failed for item instance: '|| p_csi_item_instance_id);
813      log_error_messages;
814    END IF;
815 
816    -- Disable debug
817    AHL_DEBUG_PUB.disable_debug;
818 
819  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
820    x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
821    Rollback to Process_Unit_PVT;
822    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
823                               p_data  => x_msg_data,
824                               p_encoded => fnd_api.g_false);
825 
826    IF (p_concurrent_flag = 'Y') THEN
827      fnd_file.put_line(fnd_file.log, 'Process Unit failed for item instance: '|| p_csi_item_instance_id);
828      log_error_messages;
829    END IF;
830 
831    -- Disable debug
832    AHL_DEBUG_PUB.disable_debug;
833 
834  WHEN OTHERS THEN
835 
836     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
837     Rollback to Process_Unit_PVT;
838     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
839        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
840                                p_procedure_name => 'Process_Unit_PVT',
841                                p_error_text     => SUBSTR(SQLERRM,1,240));
842     END IF;
843     FND_MSG_PUB.count_and_get( p_count => x_msg_count,
844                                p_data  => x_msg_data,
845                                p_encoded => fnd_api.g_false);
846 
847 
848     IF (p_concurrent_flag = 'Y') THEN
849      fnd_file.put_line(fnd_file.log, 'Process Unit failed for item instance: '|| p_csi_item_instance_id);
850      log_error_messages;
851     END IF;
852 
853     -- Disable debug
854     AHL_DEBUG_PUB.disable_debug;
855 
856 END Process_Unit;
857 
858 -------------------------------------------------------------------------------
859 -- Start of Comments --
860 --  Procedure name    : Process_MRAffected_Units
861 --  Type        : Private
862 --  Function    : Processes all units that are affected for a Maintenance requirement.
863 --  Pre-reqs    :
864 --  Parameters  :
865 --
866 --  Process_MR_Affected_Units Parameters :
867 --  Effectivity will be built for all units having p_mr_id as a maintenance requirement.
868 --  This procedure will also be called from terminate_MRs; in which case p_old_mr_header_id
869 --  will also be passed.p_old_mr_header_id is the MR that was terminated. Effectivity will
870 --  be re-build for all units that had p_old_mr_header_id as applicability.
871 --
872 --  p_concurrent_flag                   IN      VARCHAR2
873 --  This flag will be 'Y' if called from a concurrent program. Based on this flag, the error
874 --  and informational messages will be logged into the log file.
875 --
876 
877 PROCEDURE Process_MRAffected_Units (
878     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
879     x_msg_count              OUT NOCOPY    NUMBER,
880     x_msg_data               OUT NOCOPY    VARCHAR2,
881     x_return_status          OUT NOCOPY    VARCHAR2,
882     p_mr_header_id           IN            NUMBER,
883     p_old_mr_header_id       IN            NUMBER    := NULL,
884     p_concurrent_flag        IN            VARCHAR2  := 'N',
885     p_num_of_workers         IN            NUMBER    := 1,
886     p_mtl_category_id        IN            NUMBER    := NULL,
887     p_process_option         IN            VARCHAR2  := NULL)
888 
889 
890 IS
891 
892   l_commit VARCHAR2(1) := p_commit;
893 
894   l_conc_request_id        NUMBER;
895   l_req_id                 NUMBER;
896   l_instance_id            NUMBER;
897   l_num_of_workers         NUMBER;
898 
899 BEGIN
900 
901   -- Initialize Procedure return status to success
902   x_return_status := FND_API.G_RET_STS_SUCCESS;
903 
904   -- Enable Debug.
905   IF G_DEBUG = 'Y' THEN
906     AHL_DEBUG_PUB.enable_debug;
907   END IF;
908 
909   -- Add debug mesg.
910   IF G_DEBUG = 'Y' THEN
911     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Process_MRAffected_Units');
912     AHL_DEBUG_PUB.debug('Application Usage Profile:' || fnd_profile.value('AHL_APPLN_USAGE'));
913   END IF;
914 
915   IF (p_concurrent_flag = 'Y') THEN
916      l_commit := FND_API.G_TRUE;
917      l_conc_request_id := fnd_global.conc_request_id;
918      IF (l_conc_request_id = -1) OR (l_conc_request_id IS NULL) OR (l_conc_request_id <= 0) THEN
919         -- this will happen only when called from UMP Terminate_MR_Instances api.
920         l_conc_request_id := fnd_global.login_id;
921      END IF;
922   ELSE
923      l_conc_request_id := fnd_global.session_id;
924   END IF;
925 
926   -- validate p_num_of_workers.
927   l_num_of_workers := trunc(p_num_of_workers);
928 
929   IF (l_num_of_workers IS NULL OR l_num_of_workers <= 0) THEN
930     l_num_of_workers := 1;
931   ELSIF l_num_of_workers > 30 THEN
932     l_num_of_workers := 30;
933   END IF;
934 
935   -- Set FMP parameter based on PM installation.
936   IF (G_IS_PM_INSTALLED = 'Y') THEN
937      -- PM processing(fix for performance bug# 5093064).
938      Process_PM_MR_Affected_Items(
939                    p_commit       => l_commit,
940  	           x_msg_count    => x_msg_count,
941  	           x_msg_data       => x_msg_data,
942  	           x_return_status  => x_return_status,
943  	           p_mr_header_id    => p_mr_header_id,
944  	           p_old_mr_header_id  => p_old_mr_header_id,
945                    p_concurrent_flag   => p_concurrent_flag,
946                    p_num_of_workers   => l_num_of_workers);
947   ELSE
948 
949      Populate_BUE_Worker_for_MR(p_conc_request_id => l_conc_request_id,
950                                 p_mr_header_id    => p_mr_header_id,
951                                 p_concurrent_flag => p_concurrent_flag,
952                                 p_mtl_category_id => p_mtl_category_id,
953                                 p_process_option  => p_process_option,
954                                 x_return_status   => x_return_status);
955 
956      IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
957        RETURN;
958      END IF;
959 
960      IF (p_old_mr_header_id IS NOT NULL AND p_old_mr_header_id <> FND_API.G_MISS_NUM) THEN
961          -- Call FMP API to get all items instances which have old mr_id in its applicability.
962          Populate_BUE_Worker_for_MR(p_conc_request_id => l_conc_request_id,
963                                     p_mr_header_id    => p_old_mr_header_id,
964                                     p_concurrent_flag => p_concurrent_flag,
965                                     p_mtl_category_id => p_mtl_category_id,
966                                     p_process_option  => p_process_option,
967                                     x_return_status   => x_return_status);
968          IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
969            RETURN;
970          END IF;
971      END IF; -- p_old_mr_header_id I
972 
973      IF (p_concurrent_flag = 'Y') THEN
974        -- submit worker programs to process units.
975        FOR i IN 1..l_num_of_workers LOOP
976          l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, l_conc_request_id);
977          IF (l_req_id = 0 OR l_req_id IS NULL) THEN
978             IF G_debug = 'Y' THEN
979                AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
980             END IF;
981             fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
982             fnd_file.new_line(FND_FILE.LOG,1);
983             x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
984             EXIT; -- abort and return to calling pgm.
985 
986          ELSE
987             fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id);
988             IF G_debug = 'Y' THEN
989                AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id );
990             END IF;
991          END IF; -- l_req_id = 0 OR ..
992 
993        END LOOP;
994 
995        -- call cleanup BUE for previously failed deletes.
996        Cleanup_BUE_Worker(p_parent_conc_request_id => l_conc_request_id,
997                           p_child_conc_request_id  => NULL);
998 
999      ELSE
1000          LOOP
1001             -- initialize return status.
1002             x_return_status := FND_API.G_RET_STS_SUCCESS;
1003 
1004             -- process each unit from worker table.
1005             Get_Next_BUE_Row(p_parent_conc_pgm_id  => l_conc_request_id,
1006                              p_conc_child_req_id   => l_conc_request_id,
1007                              errbuf                => x_msg_data,
1008                              x_return_status       => x_return_status,
1009                              x_item_instance_id    => l_instance_id);
1010 
1011             IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1012               EXIT; -- abort and return to calling pgm.
1013             END IF;
1014 
1015             EXIT WHEN (l_instance_id IS NULL);
1016 
1017             IF G_DEBUG = 'Y' THEN
1018                AHL_DEBUG_PUB.debug('Now processing..:' || l_instance_id);
1019             END IF;
1020 
1021             -- Call Process Unit for the item instance.
1022             Process_Unit (
1023                   p_commit               => l_commit,
1024                   p_init_msg_list        => FND_API.G_TRUE,
1025                   x_msg_count            => x_msg_count,
1026                   x_msg_data             => x_msg_data,
1027                   x_return_status        => x_return_status,
1028                   p_csi_item_instance_id => l_instance_id,
1029                   p_concurrent_flag      => p_concurrent_flag);
1030 
1031             IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1032               EXIT; -- abort and return to calling pgm.
1033             END IF;
1034 
1035          END LOOP;
1036 
1037          -- cleanup worker table after processing.
1038          Cleanup_BUE_Worker(p_parent_conc_request_id => l_conc_request_id,
1039                             p_child_conc_request_id  => l_conc_request_id);
1040 
1041      END IF; -- p_concurrent_flag
1042 
1043   END IF; -- G_IS_PM_INSTALLED.
1044 
1045 END Process_MRAffected_Units;
1046 
1047 -- Tamal: Bug #4207212, #4114368: Begin
1048 ------------------------------------------------------------------------------
1049 -- Start of Comments --
1050 --  Procedure name    : Process_PM_Contracts
1051 --  Type        : Private
1052 --  Function    : Retrieves all instances for a contract and calls Process_Unit for each unit.
1053 --  Pre-reqs    :
1054 --  Parameters  :
1055 --
1056 --  p_concurrent_flag                   IN      VARCHAR2
1057 --  This flag will be 'Y' if called from a concurrent program. Based on this flag, the error
1058 --  and informational messages will be logged into the log file.
1059 --  p_contract_number			IN	VARCHAR2
1060 --  The contract number for which want to process csi_item_instances entitlement
1061 --  p_contract_number			IN	VARCHAR2
1062 --  The contract number modifier for above contract number
1063 
1064 PROCEDURE Process_PM_Contracts
1065 (
1066     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
1067     p_init_msg_list          IN            VARCHAR2  := FND_API.G_FALSE,
1068     x_msg_count              OUT  NOCOPY   NUMBER,
1069     x_msg_data               OUT  NOCOPY   VARCHAR2,
1070     x_return_status          OUT  NOCOPY   VARCHAR2,
1071     p_contract_number        IN            VARCHAR2  := NULL,
1072     p_contract_modifier      IN            VARCHAR2  := NULL,
1073     p_concurrent_flag        IN            VARCHAR2  := 'N'
1074 )
1075 IS
1076     l_msg_count		number;
1077     l_commit		varchar2(1) := p_commit;
1078 
1079     l_inp_cont_rec           OKS_ENTITLEMENTS_PUB.inp_cont_rec;
1080     l_ent_cont_tbl           OKS_ENTITLEMENTS_PUB.ent_cont_tbl;
1081 
1082     -- Fix for bug# 5639852.
1083     CURSOR get_oks_line_end_dt1(p_contract_number IN VARCHAR2,
1084                                 p_contract_modifier IN VARCHAR2)
1085     IS
1086       SELECT trunc(min(okl.end_date)), trunc(okh.start_date)
1087       FROM okc_k_headers_b okh, okc_k_lines_b okl
1088       WHERE OKL.DNZ_CHR_ID = OKH.ID
1089         AND OKH.CONTRACT_NUMBER = p_contract_number
1090         AND OKH.CONTRACT_NUMBER_MODIFIER = p_contract_modifier
1091         GROUP BY OKH.ID, OKH.start_date;
1092 
1093     CURSOR get_oks_line_end_dt2(p_contract_number IN VARCHAR2)
1094     IS
1095       SELECT trunc(min(okl.end_date)), trunc(okh.start_date)
1096       FROM okc_k_headers_b okh, okc_k_lines_b okl
1097       WHERE OKL.DNZ_CHR_ID = OKH.ID
1098         AND OKH.CONTRACT_NUMBER = p_contract_number
1099         GROUP BY OKH.ID, OKH.start_date;
1100 
1101     l_end_date  DATE;
1102     l_start_date  DATE;
1103 
1104 BEGIN
1105     -- Standard start of API savepoint
1106     SAVEPOINT Process_PM_Contracts_PVT;
1107 
1108     -- Initialize message list if p_init_msg_list is set to TRUE
1109     IF FND_API.To_Boolean(p_init_msg_list) THEN
1110         FND_MSG_PUB.Initialize;
1111     END IF;
1112 
1113     -- Initialize Procedure return status to success
1114     x_return_status := FND_API.G_RET_STS_SUCCESS;
1115 
1116     -- Enable Debug.
1117     IF G_DEBUG = 'Y' THEN
1118         AHL_DEBUG_PUB.enable_debug;
1119     END IF;
1120 
1121     -- Add debug mesg.
1122     IF G_DEBUG = 'Y' THEN
1123         AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Process_PM_Contracts');
1124         -- Dump input parameters.
1125         AHL_DEBUG_PUB.debug('Contract Number:' || p_contract_number );
1126         AHL_DEBUG_PUB.debug('Contract Modifier:' || p_contract_modifier );
1127         AHL_DEBUG_PUB.debug('p_concurrent_flag:' || p_concurrent_flag );
1128         AHL_DEBUG_PUB.debug('p_commit:' || p_commit );
1129     END IF;
1130 
1131     IF (p_concurrent_flag = 'Y') THEN
1132         fnd_file.put_line(fnd_file.log, 'Starting processing for contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1133     	-- If the call is from concurrent program, then commit should default to TRUE
1134     	l_commit := FND_API.G_TRUE;
1135     END IF;
1136 
1137     l_inp_cont_rec.contract_number := p_contract_number;
1138     l_inp_cont_rec.contract_number_modifier := p_contract_modifier;
1139     l_inp_cont_rec.validate_flag := 'Y';
1140 
1141     -- Fix for bug# 5639852 -- Begin.
1142     l_inp_cont_rec.request_date := NULL;  -- defaults to sysdate.
1143 
1144     -- For signed contracts we need to send a future date.
1145     -- find out the minimum end date for the contract lines to ensure date
1146     -- coverage for all service lines.
1147     IF (p_contract_modifier IS NULL) THEN
1148        OPEN get_oks_line_end_dt2(p_contract_number);
1149        FETCH get_oks_line_end_dt2 INTO l_end_date, l_start_date;
1150        CLOSE get_oks_line_end_dt2;
1151     ELSE
1152        OPEN get_oks_line_end_dt1(p_contract_number, p_contract_modifier);
1153        FETCH get_oks_line_end_dt1 INTO l_end_date, l_start_date;
1154        CLOSE get_oks_line_end_dt1;
1155     END IF;
1156 
1157     IF (l_start_date > trunc(sysdate)) THEN
1158       IF (l_end_date IS NOT NULL) THEN
1159          l_inp_cont_rec.request_date := l_end_date;
1160       END IF;
1161     END IF;
1162     -- Fix for bug# 5639852 -- End.
1163 
1164     OKS_ENTITLEMENTS_PUB.get_contracts
1165     (
1166         p_api_version   => 1.0,
1167         p_init_msg_list => FND_API.G_FALSE,
1168         p_inp_rec       => l_inp_cont_rec,
1169         x_return_status => x_return_status,
1170         x_msg_count     => x_msg_count,
1171         x_msg_data      => x_msg_data,
1172         x_ent_contracts => l_ent_cont_tbl
1173     );
1174 
1175     -- Check Error Message stack.
1176     l_msg_count := FND_MSG_PUB.count_msg;
1177     IF (l_msg_count > 0 or x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1178         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1179     END IF;
1180 
1181     IF (l_ent_cont_tbl.count > 0)
1182     THEN
1183         FOR i IN l_ent_cont_tbl.FIRST..l_ent_cont_tbl.LAST
1184         LOOP
1185             IF (l_ent_cont_tbl(i).coverage_level_code = 'COVER_PROD')
1186             THEN
1187                 IF (p_concurrent_flag = 'Y') THEN
1188                     fnd_file.put_line(fnd_file.log, 'Calling Process_Unit for instance: ' || l_ent_cont_tbl(i).coverage_level_id);
1189                 END IF;
1190                 AHL_UMP_ProcessUnit_PVT.Process_Unit
1191                 (
1192                     p_commit               => l_commit,
1193                     x_msg_count            => x_msg_count,
1194                     x_msg_data             => x_msg_data,
1195                     x_return_status        => x_return_status,
1196                     p_csi_item_instance_id => l_ent_cont_tbl(i).coverage_level_id,
1197                     p_concurrent_flag      => p_concurrent_flag
1198                 );
1199                 IF (p_concurrent_flag = 'Y' and (FND_MSG_PUB.count_msg > 0 or x_return_status <> FND_API.G_RET_STS_SUCCESS)) THEN
1200                     fnd_file.put_line(fnd_file.log, 'Process_Unit failed for instance: ' || l_ent_cont_tbl(i).coverage_level_id);
1201                 END IF;
1202             END IF;
1203         END LOOP;
1204     END IF;
1205 
1206     -- Check Error Message stack.
1207     l_msg_count := FND_MSG_PUB.count_msg;
1208     IF (l_msg_count > 0 or x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1209         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1210     END IF;
1211 
1212     -- Standard check of p_commit
1213     IF FND_API.TO_BOOLEAN(p_commit) THEN
1214         COMMIT WORK;
1215     END IF;
1216 
1217     -- Log success message if called by concurrent program.
1218     IF (p_concurrent_flag = 'Y') THEN
1219         fnd_file.put_line(fnd_file.log, 'Message-Successfully processed: contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1220     END IF;
1221 
1222     -- Standard call to get message count and if count is 1, get message info
1223     FND_MSG_PUB.Count_And_Get
1224     (
1225         p_count => x_msg_count,
1226         p_data  => x_msg_data,
1227         p_encoded => fnd_api.g_false
1228     );
1229 
1230 EXCEPTION
1231     WHEN FND_API.G_EXC_ERROR THEN
1232         x_return_status := FND_API.G_RET_STS_ERROR;
1233         Rollback to Process_PM_Contracts_PVT;
1234         FND_MSG_PUB.count_and_get
1235         (
1236             p_count => x_msg_count,
1237             p_data  => x_msg_data,
1238             p_encoded => fnd_api.g_false
1239         );
1240         IF (p_concurrent_flag = 'Y') THEN
1241             fnd_file.put_line(fnd_file.log, 'Process_PM_Contracts failed for: contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1242             log_error_messages;
1243         END IF;
1244         AHL_DEBUG_PUB.disable_debug;
1245 
1246     WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
1247         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1248         Rollback to Process_PM_Contracts_PVT;
1249         FND_MSG_PUB.count_and_get
1250         (
1251             p_count => x_msg_count,
1252             p_data  => x_msg_data,
1253             p_encoded => fnd_api.g_false
1254         );
1255         IF (p_concurrent_flag = 'Y') THEN
1256             fnd_file.put_line(fnd_file.log, 'Process_PM_Contracts failed for: contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1257             log_error_messages;
1258         END IF;
1259         AHL_DEBUG_PUB.disable_debug;
1260 
1261     WHEN OTHERS THEN
1262         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1263         Rollback to Process_PM_Contracts_PVT;
1264         IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1265             fnd_msg_pub.add_exc_msg
1266             (
1267                 p_pkg_name       => G_PKG_NAME,
1268                 p_procedure_name => 'Process_PM_Contracts',
1269                 p_error_text     => SUBSTR(SQLERRM,1,240)
1270             );
1271         END IF;
1272         FND_MSG_PUB.count_and_get
1273         (
1274             p_count => x_msg_count,
1275             p_data  => x_msg_data,
1276             p_encoded => fnd_api.g_false
1277         );
1278         IF (p_concurrent_flag = 'Y') THEN
1279             fnd_file.put_line(fnd_file.log, 'Process_PM_Contracts failed for: contract Number '|| p_contract_number || ' and contract modifier' || p_contract_modifier);
1280             log_error_messages;
1281         END IF;
1282         AHL_DEBUG_PUB.disable_debug;
1283 END Process_PM_Contracts;
1284 -- Tamal: Bug #4207212, #4114368: End
1285 
1286 ------------------------------------------------------------------------------
1287 -- Start of Comments --
1288 --  Procedure name    : Process_All_Units
1289 --  Type        : Private
1290 --  Function    : Loops through all units and calls Process_Unit for each unit.
1291 --  Pre-reqs    :
1292 --  Parameters  :
1293 --
1294 --  p_concurrent_flag                   IN      VARCHAR2
1295 --  This flag will be 'Y' if called from a concurrent program. Based on this flag, the error
1296 --  and informational messages will be logged into the log file by Process_Unit.
1297 
1298 PROCEDURE Process_All_Units (
1299     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
1300     x_msg_count              OUT  NOCOPY   NUMBER,
1301     x_msg_data               OUT  NOCOPY   VARCHAR2,
1302     x_return_status          OUT  NOCOPY   VARCHAR2,
1303     p_concurrent_flag        IN            VARCHAR2  := 'N',
1304     p_num_of_workers         IN            NUMBER    := 1,
1305     p_mtl_category_id        IN            NUMBER    := NULL,
1306     p_process_option         IN            VARCHAR2  := NULL)
1307 
1308 IS
1309 
1310   -- uncommented query to fix performance issue 6893404
1311   -- declare cursor to retrieve min/max instances from Installed Base for PM installation.
1312   CURSOR csi_pm_instance_csr IS
1313      SELECT min(instance_id), max(instance_id)
1314      FROM csi_item_instances csi,
1315      (select me.inventory_item_id
1316       from ahl_mr_effectivities me, ahl_mr_headers_app_v mr
1317       where mr.mr_header_id = me.mr_header_id
1318         and mr.type_code = 'PROGRAM') mre
1319      WHERE trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) AND
1320            trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
1321      AND mre.inventory_item_id = csi.inventory_item_id;
1322 
1323 
1324   l_commit VARCHAR2(1) := p_commit;
1325 
1326   l_min_csi_id             NUMBER;
1327   l_max_csi_id             NUMBER;
1328 
1329 BEGIN
1330 
1331   -- Initialize Procedure return status to success
1332   x_return_status := FND_API.G_RET_STS_SUCCESS;
1333 
1334   -- Enable Debug.
1335   -- Add api start debug mesg.
1336   IF G_DEBUG = 'Y' THEN
1337     AHL_DEBUG_PUB.enable_debug;
1338     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Process_All_Units');
1339   END IF;
1340 
1341   -- For concurrent program.
1342   IF (p_concurrent_flag = 'Y') THEN
1343      l_commit := FND_API.G_TRUE;
1344   END IF;
1345 
1346   IF (G_IS_PM_INSTALLED = 'N') THEN
1347      -- AHL processing.
1348      Split_Process_All_Instances(p_concurrent_flag => p_concurrent_flag,
1349                                  p_commit_flag     => l_commit,
1350                                  p_num_of_workers  => p_num_of_workers,
1351                                  p_mr_header_id    => null,
1352                                  p_mtl_category_id => p_mtl_category_id,
1353                                  p_process_option  => p_process_option,
1354                                  x_msg_count       => x_msg_count,
1355                                  x_msg_data        => x_msg_data,
1356                                  x_return_status   => x_return_status);
1357 
1358      IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1359        RETURN;
1360      END IF;
1361 
1362   ELSE
1363      -- PM processing.
1364      OPEN csi_pm_instance_csr;
1365      FETCH csi_pm_instance_csr INTO l_min_csi_id, l_max_csi_id;
1366      CLOSE csi_pm_instance_csr;
1367 
1368      Instance_Split_Sequential(p_csi_max_id  => l_max_csi_id,
1369                                p_csi_min_id  => l_min_csi_id,
1370                                p_num_workers => p_num_of_workers,
1371                                p_mr_header_id => null);
1372   END IF; -- pm installation check.
1373 
1374 END Process_All_Units;
1375 
1376 --------------------------------------------------------------------------
1377 PROCEDURE Validate_Item_Instance (p_csi_item_instance_id IN NUMBER,
1378                                   x_inventory_item_id    OUT NOCOPY NUMBER,
1379                                   x_inv_master_organization_id OUT NOCOPY NUMBER)
1380 IS
1381 
1382 -- To validate instance.
1383   CURSOR csi_item_instances_csr(p_csi_item_instance_id IN  NUMBER) IS
1384     SELECT instance_number, active_end_date, inventory_item_id,
1385            inv_master_organization_id
1386     FROM csi_item_instances
1387     WHERE instance_id = p_csi_item_instance_id;
1388 
1389 l_inventory_item_id           NUMBER;
1390 l_inv_master_organization_id  NUMBER;
1391 l_instance_number             csi_item_instances.instance_number%TYPE;
1392 l_active_end_date             DATE;
1393 
1394 BEGIN
1395 
1396   IF G_DEBUG = 'Y' THEN
1397      AHL_DEBUG_PUB.debug('Start Validate Item Instance');
1398   END IF;
1399 
1400   -- Validate csi_item_instance_id.
1401   IF (p_csi_item_instance_id IS NOT NULL) THEN
1402     OPEN csi_item_instances_csr (p_csi_item_instance_id);
1403     FETCH csi_item_instances_csr INTO l_instance_number, l_active_end_date,
1404                                      l_inventory_item_id, l_inv_master_organization_id;
1405     IF (csi_item_instances_csr%NOTFOUND) THEN
1406       FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_INSTID_NOTFOUND');
1407       FND_MESSAGE.Set_Token('INST_ID', p_csi_item_instance_id);
1408       FND_MSG_PUB.ADD;
1409       CLOSE csi_item_instances_csr;
1410       --dbms_output.put_line('Instance not found');
1411       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1412     ELSIF (trunc(l_active_end_date) < trunc(sysdate)) THEN
1413       FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_INST_EXPIRED');
1414       FND_MESSAGE.Set_Token('NUMBER', l_instance_number);
1415       FND_MSG_PUB.ADD;
1416       --dbms_output.put_line('Instance has expired');
1417     END IF;
1418 
1419     CLOSE csi_item_instances_csr;
1420   END IF;
1421 
1422   x_inventory_item_id := l_inventory_item_id;
1423   x_inv_master_organization_id := l_inv_master_organization_id;
1424 
1425   IF G_DEBUG = 'Y' THEN
1426         AHL_DEBUG_PUB.debug('End Validate Item Instance');
1427   END IF;
1428 
1429 END Validate_Item_Instance;
1430 
1431 -----------------------------------------------------------------------------
1432 -- To get the unit and master configurations IDs for the input item instance.
1433 
1434 PROCEDURE Get_Unit_Master_ConfigIDs (p_csi_item_instance_id IN NUMBER,
1435                                      x_uc_header_id OUT NOCOPY NUMBER,
1436                                      x_master_config_id OUT NOCOPY NUMBER)
1437 IS
1438 
1439   -- To get unit config id.
1440   CURSOR ahl_unit_config_header_csr (p_item_instance_id IN NUMBER) IS
1441     SELECT name, active_start_date, active_end_date, master_config_id, unit_config_header_id,
1442            unit_config_status_code
1443     FROM  ahl_unit_config_headers
1444     WHERE csi_item_instance_id = p_item_instance_id
1445       --AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate) AND
1446       --    trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
1447       AND parent_uc_header_id IS NULL;
1448 
1449   l_name              ahl_unit_config_headers.name%TYPE;
1450   l_active_start_date DATE;
1451   l_active_end_date   DATE;
1452   l_master_config_id  NUMBER;
1453   l_unit_config_header_id NUMBER;
1454   l_config_status_code    fnd_lookup_values_vl.lookup_code%TYPE;
1455 
1456 BEGIN
1457 
1458     IF G_DEBUG = 'Y' THEN
1459         AHL_DEBUG_PUB.debug('Start Get_Unit_Master_ConfigIDs');
1460     END IF;
1461 
1462      x_uc_header_id := null;
1463      x_master_config_id := null;
1464 
1465     IF (p_csi_item_instance_id IS NOT NULL) THEN
1466       OPEN ahl_unit_config_header_csr (p_csi_item_instance_id);
1467       FETCH ahl_unit_config_header_csr INTO l_name, l_active_start_date,
1468                                             l_active_end_date, l_master_config_id,
1469                                             l_unit_config_header_id,
1470                                             l_config_status_code;
1471       IF (ahl_unit_config_header_csr%FOUND) THEN
1472         --IF (l_config_status_code <> 'COMPLETE' AND l_config_status_code <> 'INCOMPLETE') THEN
1473         --modified for quaratine statuses.
1474         IF (l_config_status_code = 'DRAFT') THEN
1475            FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_STATUS_INVALID');
1476            FND_MESSAGE.Set_Token('NAME',l_name);
1477            FND_MSG_PUB.ADD;
1478            --dbms_output.put_line('UC is in draft status');
1479         ELSE
1480            x_uc_header_id := l_unit_config_header_id;
1481            x_master_config_id := l_master_config_id;
1482         END IF;
1483       END IF;
1484       CLOSE ahl_unit_config_header_csr;
1485     END IF;
1486 
1487     IF (G_concurrent_flag = 'Y') THEN
1488       fnd_file.put_line (FND_FILE.LOG, 'Unit Config Name:' || l_name);
1489     END IF;
1490 
1491     IF G_DEBUG = 'Y' THEN
1492         AHL_DEBUG_PUB.debug('Unit Config ID:' || x_uc_header_id);
1493         AHL_DEBUG_PUB.debug('Master Config ID:' || x_master_config_id);
1494         AHL_DEBUG_PUB.debug('End Get_Unit_Master_ConfigIDs');
1495     END IF;
1496 
1497 END Get_Unit_Master_ConfigIDs;
1498 
1499 -----------------------------------------------------------------------
1500 -- To get the root item instance for the input item instance if exists.
1501 
1502 FUNCTION Get_RootInstanceID(p_csi_item_instance_id IN NUMBER)
1503 RETURN NUMBER
1504 IS
1505 
1506   CURSOR csi_root_instance_csr (p_instance_id IN NUMBER) IS
1507     SELECT root.object_id
1508     FROM csi_ii_relationships root
1509     WHERE NOT EXISTS (SELECT 'x'
1510                       FROM csi_ii_relationships
1511                       WHERE subject_id = root.object_id
1512                         AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
1513                       )
1514     START WITH root.subject_id = p_instance_id
1515                AND root.relationship_type_code = 'COMPONENT-OF'
1516                AND trunc(nvl(root.active_start_date,sysdate)) <= trunc(sysdate)
1517                AND trunc(sysdate) < trunc(nvl(root.active_end_date, sysdate+1))
1518     CONNECT BY PRIOR root.object_id = root.subject_id
1519                      AND root.relationship_type_code = 'COMPONENT-OF'
1520                      AND trunc(nvl(root.active_start_date,sysdate)) <= trunc(sysdate)
1521                      AND trunc(sysdate) < trunc(nvl(root.active_end_date, sysdate+1));
1522 
1523   l_csi_instance_id  NUMBER;
1524 
1525 BEGIN
1526 
1527   -- get root instance given an item instance_id.
1528   OPEN csi_root_instance_csr (p_csi_item_instance_id);
1529   FETCH csi_root_instance_csr INTO l_csi_instance_id;
1530   IF (csi_root_instance_csr%NOTFOUND) THEN
1531      -- input id is root instance.
1532      l_csi_instance_id := p_csi_item_instance_id;
1533   END IF;
1534   CLOSE csi_root_instance_csr;
1535   --dbms_output.put_line ('root instance' || l_csi_instance_id);
1536 
1537   RETURN  l_csi_instance_id;
1538 
1539 END Get_RootInstanceID;
1540 
1541 -------------------------------------------------------------
1542 -- Validate the input item instance.
1543 
1544 PROCEDURE Build_Config_Tree(p_csi_root_instance_id IN         NUMBER,
1545                             p_master_config_id     IN         NUMBER,
1546                             x_config_node_tbl      OUT NOCOPY AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type)
1547 
1548 IS
1549 
1550   CURSOR csi_config_tree_csr ( p_csi_root_instance_id IN NUMBER) IS
1551     SELECT subject_id , object_id, position_reference
1552     FROM csi_ii_relationships
1553     START WITH object_id = p_csi_root_instance_id
1554                AND relationship_type_code = 'COMPONENT-OF'
1555                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
1556                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
1557     CONNECT BY PRIOR subject_id = object_id
1558                      AND relationship_type_code = 'COMPONENT-OF'
1559                      AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
1560                      AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
1561     ORDER BY level;
1562 
1563   i  NUMBER;
1564   l_config_node_tbl   AHL_UMP_PROCESSUNIT_PVT.config_node_tbl_type := x_config_node_tbl;
1565 
1566   -- added for perf fix for bug# 6893404.
1567   l_buffer_limit      number := 1000;
1568 
1569   l_subj_id_tbl       nbr_tbl_type;
1570   l_obj_id_tbl        nbr_tbl_type;
1571   l_posn_ref_tbl      vchar_tbl_type;
1572 
1573 BEGIN
1574 
1575   IF G_DEBUG = 'Y' THEN
1576         AHL_DEBUG_PUB.debug('Start Build_Config_Tree');
1577   END IF;
1578 
1579    -- For top node.
1580   l_config_node_tbl(1).csi_item_instance_id := p_csi_root_instance_id;
1581 
1582   -- For position reference.
1583   IF (p_master_config_id IS NOT NULL) THEN
1584     l_config_node_tbl(1).position_reference := to_char(p_master_config_id);
1585   END IF;
1586 
1587   i := 1;
1588 
1589   -- add child nodes.
1590   -- added for perf fix for bug# 6893404.
1591   OPEN csi_config_tree_csr(p_csi_root_instance_id);
1592   LOOP
1593     FETCH csi_config_tree_csr BULK COLLECT INTO l_subj_id_tbl, l_obj_id_tbl, l_posn_ref_tbl
1594                               LIMIT l_buffer_limit;
1595 
1596     EXIT WHEN (l_subj_id_tbl.count = 0);
1597 
1598     FOR j IN l_subj_id_tbl.FIRST..l_subj_id_tbl.LAST LOOP
1599 
1600       -- Loop through to get all components of the configuration.
1601       -- FOR node_rec IN csi_config_tree_csr(p_csi_root_instance_id) LOOP
1602       i := i + 1;
1603 
1604       --l_config_node_tbl(i).csi_item_instance_id := node_rec.subject_id;
1605       --l_config_node_tbl(i).object_id := node_rec.object_id;
1606       --l_config_node_tbl(i).position_reference := node_rec.position_reference;
1607 
1608       l_config_node_tbl(i).csi_item_instance_id := l_subj_id_tbl(j);
1609       l_config_node_tbl(i).object_id            := l_obj_id_tbl(j);
1610       l_config_node_tbl(i).position_reference   := l_posn_ref_tbl(j);
1611 
1612     END LOOP; -- l_subj_id_tbl.FIRST
1613 
1614     -- reset tables and get the next batch of nodes.
1615     l_subj_id_tbl.DELETE;
1616     l_obj_id_tbl.DELETE;
1617     l_posn_ref_tbl.DELETE;
1618 
1619   END LOOP; -- FETCH csi_config_tree_csr
1620   CLOSE csi_config_tree_csr;
1621 
1622   X_CONFIG_NODE_TBL := l_config_node_tbl;
1623 
1624   IF G_DEBUG = 'Y' THEN
1625      AHL_DEBUG_PUB.debug('End Build_Config_Tree');
1626      AHL_DEBUG_PUB.debug('Count on config' || x_config_node_tbl.COUNT);
1627   END IF;
1628 
1629 END Build_Config_Tree;
1630 
1631 -----------------------------------------------------------------------
1632 -- This function calculates the last day of the rolling window based on
1633 -- profile values.
1634 
1635 FUNCTION Get_Rolling_Window_Date RETURN DATE  IS
1636 
1637   l_date_uom            VARCHAR2(30);
1638   l_value               NUMBER;
1639   l_last_day_of_window  DATE;
1640 
1641 BEGIN
1642 
1643    BEGIN
1644      l_date_uom := FND_PROFILE.VALUE('AHL_UMP_MAX_PLANNING_UOM');
1645      l_value    := to_number(FND_PROFILE.VALUE('AHL_UMP_MAX_PLANNING_VALUE'));
1646 
1647      IF (l_date_uom IS NULL) THEN
1648         l_last_day_of_window := SYSDATE;
1649      ELSIF (l_value <= 0 OR l_value IS NULL) THEN
1650         l_last_day_of_window := SYSDATE;
1651      ELSIF (l_date_uom = 'YR') THEN
1652         l_last_day_of_window := ADD_MONTHS(SYSDATE, 12 * l_value);
1653      ELSIF (l_date_uom = 'MTH') THEN
1654         l_last_day_of_window := ADD_MONTHS(SYSDATE, l_value);
1655      ELSIF (l_date_uom = 'WK') THEN
1656         l_last_day_of_window := SYSDATE + (7 * l_value);
1657      ELSIF (l_date_uom = 'DAY') THEN
1658         l_last_day_of_window := SYSDATE + l_value;
1659      END IF;
1660 
1661      -- Add debug mesg.
1662      IF G_DEBUG = 'Y' THEN
1663        AHL_DEBUG_PUB.debug('last day of window' || l_last_day_of_window);
1664        AHL_DEBUG_PUB.debug('profile uom:' || l_date_uom);
1665        AHL_DEBUG_PUB.debug('profile value:' || l_value);
1666      END IF;
1667 
1668    EXCEPTION
1669      WHEN VALUE_ERROR THEN
1670         l_last_day_of_window := SYSDATE;
1671 
1672      WHEN INVALID_NUMBER THEN
1673         l_last_day_of_window := SYSDATE;
1674 
1675    END;
1676 
1677    -- return date.
1678    RETURN l_last_day_of_window;
1679 
1680 END Get_Rolling_Window_Date;
1681 
1682 --------------------------------------------------------------------
1683 -- Get the utilization forecast applicable to the input item instance/unit.
1684 -- For preventive maintenance, forecast definition is at either instance level
1685 -- or item level.
1686 PROCEDURE Get_Utilization_Forecast (p_csi_item_instance_id IN NUMBER,
1687                                     p_uc_header_id         IN NUMBER,
1688                                     p_inventory_item_id    IN NUMBER,
1689                                     p_inventory_org_id     IN NUMBER,
1690                                     x_forecast_details_tbl OUT NOCOPY forecast_details_tbl_type)
1691 IS
1692 
1693   CURSOR ahl_uf_headers_csr(p_uc_header_id IN NUMBER) IS
1694     SELECT uf_header_id, use_unit_flag
1695     FROM ahl_uf_headers
1696     WHERE unit_config_header_id = p_uc_header_id;
1697 
1698   CURSOR ahl_uf_details_csr(p_uf_header_id IN NUMBER) IS
1699     SELECT uom_code, start_date, end_date, usage_per_day
1700     FROM   ahl_uf_details
1701     WHERE uf_header_id = p_uf_header_id
1702     AND trunc(nvl(end_date, sysdate)) >= trunc(sysdate)
1703     order by uom_code, start_date;
1704 
1705   CURSOR ahl_pm_uf_headers_csr(p_csi_item_instance_id IN NUMBER) IS
1706     SELECT uf_header_id, use_unit_flag
1707     FROM ahl_uf_headers
1708     WHERE csi_item_instance_id = p_csi_item_instance_id;
1709 
1710   CURSOR ahl_pm_item_uf_csr (p_csi_item_instance_id  IN  NUMBER) IS
1711     SELECT uom_code, start_date, end_date, usage_per_day
1712     FROM ahl_uf_headers uh, ahl_uf_details ud, csi_item_instances csi
1713     WHERE uh.uf_header_id = ud.uf_header_id
1714     AND csi.instance_id = p_csi_item_instance_id
1715     AND csi.inventory_item_id = uh.inventory_item_id
1716     AND trunc(nvl(end_date, sysdate)) >= trunc(sysdate)
1717     order by uom_code, start_date;
1718 
1719   l_uf_header_id  NUMBER;
1720   l_use_unit_flag   AHL_UF_HEADERS.USE_UNIT_FLAG%TYPE;
1721   l_uf_details_tbl  AHL_UMP_UF_PVT.uf_details_tbl_type;
1722 
1723   l_index  NUMBER := 1;
1724   l_forecast_details_tbl  forecast_details_tbl_type;
1725   l_return_status   VARCHAR2(1);
1726 
1727   -- Added to fix bug# 6326056.
1728   l_duplicate_flag  VARCHAR2(1);
1729 
1730 BEGIN
1731 
1732   IF G_DEBUG = 'Y' THEN
1733      AHL_DEBUG_PUB.debug('Start Get_Utilization_Forecast');
1734      AHL_DEBUG_PUB.debug ('Input csi'|| p_csi_item_instance_id);
1735      AHL_DEBUG_PUB.debug ('Input uc'|| p_uc_header_id);
1736      AHL_DEBUG_PUB.debug ('Input invID' || p_inventory_item_id);
1737      AHL_DEBUG_PUB.debug ('Input invORGID' || p_inventory_org_id);
1738   END IF;
1739 
1740   -- Check installation to get appropriate forecast.
1741   IF (G_IS_PM_INSTALLED = 'Y') THEN
1742     -- pm is installed.
1743 
1744     IF G_DEBUG = 'Y' THEN
1745        AHL_DEBUG_PUB.debug('PM forecast');
1746     END IF;
1747 
1748     -- Check if forecast available at instance level.
1749     OPEN ahl_pm_uf_headers_csr(p_csi_item_instance_id);
1750     FETCH ahl_pm_uf_headers_csr INTO l_uf_header_id, l_use_unit_flag;
1751     IF (ahl_pm_uf_headers_csr%FOUND) AND (l_use_unit_flag = 'Y') THEN
1752        --dbms_output.put_line('Found uf header and use_unit_flag' || l_uf_header_id);
1753 
1754        -- initialize.
1755        l_index := 1;
1756        FOR l_forecast_detail_rec IN ahl_uf_details_csr(l_uf_header_id) LOOP
1757            l_forecast_details_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
1758            l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_detail_rec.start_date);
1759            l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_detail_rec.end_date);
1760            l_forecast_details_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
1761 
1762            l_index := l_index + 1;
1763 
1764        END LOOP;
1765     ELSE  -- use item forecast.
1766        --dbms_output.put_line ('item forecast');
1767 
1768        -- initialize.
1769        l_index := 1;
1770        FOR l_forecast_detail_rec IN ahl_pm_item_uf_csr(p_csi_item_instance_id) LOOP
1771            l_forecast_details_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
1772            l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_detail_rec.start_date);
1773            l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_detail_rec.end_date);
1774            l_forecast_details_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
1775 
1776            l_index := l_index + 1;
1777 
1778        END LOOP;
1779     END IF;
1780     CLOSE ahl_pm_uf_headers_csr;
1781   ELSE -- is_pm_installed.
1782   -- forecast for AHL installation.
1783     IF G_DEBUG = 'Y' THEN
1784        AHL_DEBUG_PUB.debug('AHL Installation forecast');
1785     END IF;
1786 
1787     -- If Utlization forecast defined at unit level
1788     IF (p_uc_header_id IS NOT NULL) THEN
1789        --dbms_output.put_line ('uc header not null');
1790        -- check if forecast defined.
1791        OPEN ahl_uf_headers_csr (p_uc_header_id);
1792        FETCH ahl_uf_headers_csr INTO l_uf_header_id, l_use_unit_flag;
1793        IF (ahl_uf_headers_csr%FOUND) AND (l_use_unit_flag = 'Y') THEN
1794           FOR l_forecast_detail_rec IN ahl_uf_details_csr(l_uf_header_id) LOOP
1795             l_forecast_details_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
1796             l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_detail_rec.start_date);
1797             l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_detail_rec.end_date);
1798             l_forecast_details_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
1799 
1800             l_index := l_index + 1;
1801 
1802           END LOOP;
1803        ELSE /* forecast not defined at UC */
1804           --dbms_output.put_line ('use_unit_flag not Y');
1805           IF G_DEBUG = 'Y' THEN
1806              AHL_DEBUG_PUB.debug('AHL PC forecast for UNIT');
1807           END IF;
1808 
1809           -- added parameter p_add_unit_item_forecast to fix bug# 6749351.
1810           AHL_UMP_UF_PVT.Get_UF_FROM_PC (p_unit_config_header_id => p_uc_header_id,
1811                                          p_add_unit_item_forecast => 'Y',
1812                                          x_uf_details_tbl => l_uf_details_tbl,
1813                                          x_return_status => l_return_status);
1814           /* This will give forecast defined item/pc_node level. */
1815 
1816           IF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
1817             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1818           ELSIF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1819             RAISE FND_API.G_EXC_ERROR;
1820           END IF;
1821 
1822           -- populate l_forecast_details_tbl based on l_uf_details_tbl.
1823           IF (l_uf_details_tbl.COUNT) > 0 THEN
1824             l_index := 1;
1825 
1826             FOR i IN l_uf_details_tbl.FIRST..l_uf_details_tbl.LAST LOOP
1827               l_forecast_details_tbl(l_index).uom_code := l_uf_details_tbl(i).uom_code;
1828               l_forecast_details_tbl(l_index).start_date := trunc(l_uf_details_tbl(i).start_date);
1829               l_forecast_details_tbl(l_index).end_date   := trunc(l_uf_details_tbl(i).end_date);
1830               l_forecast_details_tbl(l_index).usage_per_day := l_uf_details_tbl(i).usage_per_day;
1831 
1832               l_index := l_index + 1;
1833 
1834             END LOOP;
1835 
1836           END IF; /* count > 0 */
1837 
1838        END IF; -- %found.
1839        CLOSE ahl_uf_headers_csr;
1840     ELSE
1841        IF G_DEBUG = 'Y' THEN
1842           AHL_DEBUG_PUB.debug('AHL PC forecast for ITEM');
1843        END IF;
1844        --dbms_output.put_line ('inv case');
1845 
1846        /* following taken care by get_uf_from_pc as part fix for bug# 6749351.
1847        -- first get forecast at item level (fix for bug# 6002569).
1848        -- initialize.
1849        l_index := 1;
1850        FOR l_forecast_detail_rec IN ahl_pm_item_uf_csr(p_csi_item_instance_id)
1851        LOOP
1852            l_forecast_details_tbl(l_index).uom_code := l_forecast_detail_rec.uom_code;
1853            l_forecast_details_tbl(l_index).start_date := trunc(l_forecast_detail_rec.start_date);
1854            l_forecast_details_tbl(l_index).end_date   := trunc(l_forecast_detail_rec.end_date);
1855            l_forecast_details_tbl(l_index).usage_per_day := l_forecast_detail_rec.usage_per_day;
1856 
1857            l_index := l_index + 1;
1858 
1859        END LOOP;
1860        */
1861        /* Next, get forecast defined at instance's item/pc node level. */
1862        -- set parameter to get forecast at item level as well.
1863        AHL_UMP_UF_PVT.Get_UF_FROM_PC (p_inventory_item_id => p_inventory_item_id,
1864                                       p_inventory_org_id => p_inventory_org_id,
1865                                       p_add_unit_item_forecast => 'Y',
1866                                       x_uf_details_tbl => l_uf_details_tbl,
1867                                       x_return_status => l_return_status);
1868 
1869        IF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
1870           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1871        ELSIF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1872           RAISE FND_API.G_EXC_ERROR;
1873        END IF;
1874 
1875        -- Bug# 6749351:Removed duplicate check which is now taken care by get_uf_from_pc.
1876        IF (l_uf_details_tbl.count > 0) THEN
1877            l_index := 1;
1878 
1879            FOR i IN l_uf_details_tbl.FIRST..l_uf_details_tbl.LAST LOOP
1880 
1881               l_forecast_details_tbl(l_index).uom_code := l_uf_details_tbl(i).uom_code;
1882               l_forecast_details_tbl(l_index).start_date := trunc(l_uf_details_tbl(i).start_date);
1883               l_forecast_details_tbl(l_index).end_date   := trunc(l_uf_details_tbl(i).end_date);
1884               l_forecast_details_tbl(l_index).usage_per_day := l_uf_details_tbl(i).usage_per_day;
1885               l_index := l_index + 1;
1886 
1887            END LOOP; -- l_uf_details_tbl
1888        END IF; -- l_uf_details_tbl.count
1889 
1890     END IF; -- p_uc_header_id is not null.
1891 
1892   END IF; -- end pm installed check.
1893 
1894   -- Set output variable for forecast.
1895   x_forecast_details_tbl := l_forecast_details_tbl;
1896 
1897   IF G_DEBUG = 'Y' THEN
1898      AHL_DEBUG_PUB.debug ('Count on forecast_details' || x_forecast_details_tbl.COUNT);
1899 
1900      IF (x_forecast_details_tbl.COUNT > 0) THEN
1901        FOR i IN x_forecast_details_tbl.FIRST..x_forecast_details_tbl.LAST LOOP
1902              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Uom_Code' || x_forecast_details_tbl(i).uom_code);
1903              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Start Date' || x_forecast_details_tbl(i).start_date);
1904              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') End Date' || x_forecast_details_tbl(i).end_date);
1905              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Usage' || x_forecast_details_tbl(i).usage_per_day);
1906        END LOOP;
1907      END IF;
1908 
1909      AHL_DEBUG_PUB.debug ('End Get_Utilization_Forecast');
1910 
1911   END IF;
1912 
1913 END Get_Utilization_Forecast;
1914 
1915 -----------------------------------------
1916 -- Lock all existing unit effectivity records.
1917 -- Modified for perf. bug# 6893404.
1918 PROCEDURE Lock_UnitEffectivity_Records(x_ret_code  OUT NOCOPY VARCHAR2) IS
1919 
1920   /*
1921   CURSOR ahl_unit_effectivities_csr (p_csi_item_instance_id IN NUMBER) IS
1922     SELECT UNIT_EFFECTIVITY_ID
1923     FROM AHL_UNIT_EFFECTIVITIES_APP_V
1924     WHERE csi_item_instance_id = p_csi_item_instance_id
1925     AND (status_code IS NULL OR status_code = 'INIT-DUE')
1926     FOR UPDATE OF object_version_number NOWAIT;
1927   */
1928 
1929   /* 13 Jul 08: Modified query for performance. Instead of looping for every
1930    * instance, we loop for the configuration.
1931   -- 13 Jul 08: Modified query to use status_code instead of object_version_number
1932   CURSOR ahl_unit_effectivities_csr (p_csi_item_instance_id IN NUMBER) IS
1933     --SELECT UNIT_EFFECTIVITY_ID
1934     SELECT 1
1935     FROM AHL_UNIT_EFFECTIVITIES_APP_V
1936     WHERE csi_item_instance_id = p_csi_item_instance_id
1937     AND (status_code IS NULL OR status_code IN ('INIT-DUE','EXCEPTION'))
1938     FOR UPDATE OF status_code NOWAIT;
1939   */
1940 
1941   CURSOR ahl_unit_effectivities_csr (p_csi_item_instance_id IN NUMBER) IS
1942     WITH II AS (SELECT p_csi_item_instance_id instance_id
1943                 FROM DUAL
1944                 UNION ALL
1945                 SELECT A.SUBJECT_ID INSTANCE_ID
1946                 FROM CSI_II_RELATIONSHIPS A
1947                 START WITH OBJECT_ID = p_csi_item_instance_id
1948                   AND RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF'
1949                   AND SYSDATE BETWEEN TRUNC(NVL(ACTIVE_START_DATE,SYSDATE))
1950                   AND TRUNC(NVL(ACTIVE_END_DATE, SYSDATE+1))
1951                 CONNECT BY OBJECT_ID = PRIOR SUBJECT_ID
1952                   AND RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF'
1953                   AND SYSDATE BETWEEN TRUNC(NVL(ACTIVE_START_DATE,SYSDATE))
1954                   AND TRUNC(NVL(ACTIVE_END_DATE, SYSDATE+1))
1955                )
1956     SELECT 1
1957     FROM AHL_UNIT_EFFECTIVITIES_APP_V UE, II
1958     WHERE UE.csi_item_instance_id = II.INSTANCE_ID
1959     AND (status_code IS NULL OR status_code IN ('INIT-DUE','EXCEPTION'))
1960     FOR UPDATE OF status_code NOWAIT;
1961 
1962   --l_next_rec_flag  BOOLEAN;
1963   --l_unit_effectivity_id NUMBER;
1964 
1965   l_ue_id_tbl      nbr_tbl_type;
1966 
1967 BEGIN
1968 
1969   IF G_DEBUG = 'Y' THEN
1970      AHL_DEBUG_PUB.debug ('Start Lock Effectivity records');
1971   END IF;
1972 
1973   x_ret_code := '0';
1974 
1975   /*
1976   -- Lock all records for all item instances in G_config_node_tbl.
1977   IF G_config_node_tbl.COUNT > 0 THEN
1978      FOR i IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
1979         OPEN ahl_unit_effectivities_csr(G_config_node_tbl(i).csi_item_instance_id);
1980         IF ahl_unit_effectivities_csr%NOTFOUND THEN
1981           --dbms_output.put_line (' in lock effecti - no record found');
1982           CLOSE ahl_unit_effectivities_csr;
1983           EXIT;
1984         END IF;
1985         l_next_rec_flag := TRUE;  -- there is at least one record
1986         WHILE (l_next_rec_flag) LOOP
1987            FETCH ahl_unit_effectivities_csr INTO l_unit_effectivity_id;
1988            IF ahl_unit_effectivities_csr%NOTFOUND THEN
1989               l_next_rec_flag := FALSE;
1990            END IF;
1991         END LOOP;
1992         CLOSE ahl_unit_effectivities_csr;
1993      END LOOP;
1994   END IF;
1995   */
1996 
1997   /* 13 Jul 08: Modified query for performance. Instead of looping for every
1998    * instance, we loop for the configuration.
1999   -- Lock all records for all item instances in G_config_node_tbl.
2000   IF G_config_node_tbl.COUNT > 0 THEN
2001     FOR i IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
2002        OPEN ahl_unit_effectivities_csr(G_config_node_tbl(i).csi_item_instance_id);
2003        LOOP
2004          FETCH ahl_unit_effectivities_csr BULK COLLECT INTO l_ue_id_tbl LIMIT 5000;
2005          IF G_DEBUG = 'Y' THEN
2006            AHL_DEBUG_PUB.debug ('Rows processed for instance: ' || G_config_node_tbl(i).csi_item_instance_id
2007                                   || 'is: ' || ahl_unit_effectivities_csr%ROWCOUNT);
2008          END IF;
2009          --EXIT WHEN ahl_unit_effectivities_csr%NOTFOUND;
2010          EXIT WHEN (l_ue_id_tbl.count = 0);
2011 
2012          -- delete tbl
2013          l_ue_id_tbl.delete;
2014 
2015        END LOOP;
2016        CLOSE ahl_unit_effectivities_csr;
2017     END LOOP;
2018   END IF;
2019   */
2020 
2021   IF (G_config_node_tbl.COUNT <= 0) THEN
2022     -- this should never happen.
2023     RETURN;
2024   END IF;
2025 
2026   -- G_config_node_tbl(1).csi_item_instance_id contains root node.
2027   -- Lock all records for all item instances in G_config_node_tbl.
2028   OPEN ahl_unit_effectivities_csr(G_config_node_tbl(1).csi_item_instance_id);
2029   LOOP
2030        FETCH ahl_unit_effectivities_csr BULK COLLECT INTO l_ue_id_tbl LIMIT 5000;
2031        IF G_DEBUG = 'Y' THEN
2032          AHL_DEBUG_PUB.debug ('Rows processed are: ' || ahl_unit_effectivities_csr%ROWCOUNT);
2033        END IF;
2034        --EXIT WHEN ahl_unit_effectivities_csr%NOTFOUND;
2035        EXIT WHEN (l_ue_id_tbl.count = 0);
2036 
2037        -- delete tbl
2038        l_ue_id_tbl.delete;
2039   END LOOP;
2040 
2041   CLOSE ahl_unit_effectivities_csr;
2042 
2043 
2044   IF G_DEBUG = 'Y' THEN
2045      AHL_DEBUG_PUB.debug ('End Lock Effectivity records');
2046   END IF;
2047 
2048 EXCEPTION
2049 
2050 WHEN OTHERS THEN
2051   IF (SQLCODE = -54) THEN
2052      --FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_ALREADY_RUNNING');
2053      --FND_MSG_PUB.ADD;
2054      --RAISE  FND_API.G_EXC_ERROR;
2055      x_ret_code := '-54';
2056   ELSE
2057     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
2058        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
2059                                p_procedure_name => 'Lock_UnitEffectivity_Records',
2060                                p_error_text     => SUBSTR(SQLERRM,1,240));
2061     END IF;
2062     RAISE  FND_API.G_EXC_UNEXPECTED_ERROR;
2063   END IF;
2064 
2065 END Lock_UnitEffectivity_Records;
2066 
2067 --------------------------------------------------------------------------------
2068 -- Process Unit for ASO installation.
2069 PROCEDURE Process_ASO_Unit IS
2070 
2071   CURSOR ahl_applicable_MRs (p_csi_item_instance_id IN NUMBER) IS
2072     SELECT DISTINCT appl.csi_item_instance_id,
2073                     appl.MR_header_id,
2074                     mr.Title,
2075                     mr.version_number,
2076                     appl.Implement_status_code,
2077                     appl.copy_accomplishment_code,
2078                     appl.repetitive_flag,
2079                     appl.show_repetitive_code,
2080                     appl.preceding_mr_header_id,
2081                     appl.descendent_count,
2082                     mr.whichever_first_code,
2083                     mr.effective_to,
2084                     mr.effective_from
2085     --FROM ahl_applicable_MRs appl, ahl_mr_headers_vl mr
2086     FROM ahl_applicable_MRs appl, ahl_mr_headers_b mr
2087     WHERE appl.csi_item_instance_id = p_csi_item_instance_id
2088        AND (appl.implement_status_code <> 'OPTIONAL_DO_NOT_IMPLEMENT')
2089        AND appl.preceding_mr_header_id IS NULL
2090        AND appl.mr_header_id = mr.mr_header_id
2091        AND trunc(nvl(mr.effective_from,sysdate)) <= trunc(sysdate)
2092        AND trunc(sysdate) <= trunc(nvl(mr.effective_to,sysdate+1))
2093     ORDER BY descendent_count DESC;
2094 
2095   l_applicable_mr_rec applicable_mrs_rec_type;
2096 
2097   l_current_usage_tbl    counter_values_tbl_type;
2098   /* contains current counter usage */
2099 
2100   l_counter_rules_tbl    counter_rules_tbl_type;
2101   /* contains current counter rules for the position */
2102 
2103 BEGIN
2104 
2105   -- Process Unit beginning with top node.
2106   IF G_config_node_tbl.COUNT > 0 THEN
2107     FOR i IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
2108        IF G_DEBUG = 'Y' THEN
2109           AHL_DEBUG_PUB.debug('Processing for..:' || G_config_node_tbl(i).csi_item_instance_id );
2110        END IF;
2111 
2112        -- Build counter rules ratio if node is not root node.
2113        IF (G_master_config_id IS NOT NULL AND G_config_node_tbl(i).object_id IS NOT NULL) THEN
2114            build_Counter_Ratio(G_config_node_tbl(i).position_reference,
2115                                G_config_node_tbl(i).csi_item_instance_id,
2116                                G_master_config_id,
2117                                l_counter_rules_tbl);
2118        END IF;
2119 
2120        -- Get current usage for all the counters defined for the item instance.
2121        get_Current_Usage (G_config_node_tbl(i).csi_item_instance_id,
2122                           l_current_usage_tbl);
2123 
2124        -- Add zero forecast row to G_forecast_details_tbl if forecast missing for a UOM.
2125        validate_uf_for_ctr(p_current_usage_tbl => l_current_usage_tbl,
2126                            p_x_forecast_details_tbl => G_forecast_details_tbl);
2127 
2128        -- Calculate due dates for all deferred MRs.
2129        Process_Deferred_UE (p_csi_item_instance_id => G_config_node_tbl(i).csi_item_instance_id,
2130                             p_current_usage_tbl    => l_current_usage_tbl,
2131                             p_counter_rules_tbl    => l_counter_rules_tbl);
2132 
2133        -- For UE's of type SR, re-validate MR applicability and explode group MR for next due
2134        -- date calculation.
2135        Process_SR_UE (p_csi_item_instance_id => G_config_node_tbl(i).csi_item_instance_id);
2136 
2137        -- For Unplanned MRs (MRs directly planned into a Visit from FMP), validate applicability.
2138        Process_Unplanned_UE(p_csi_item_instance_id => G_config_node_tbl(i).csi_item_instance_id);
2139 
2140        -- Read ahl_applicable_mrs for all MRs applicable to the item instance.
2141        FOR l_appl_rec IN ahl_applicable_MRs(G_config_node_tbl(i).csi_item_instance_id) LOOP
2142 
2143          IF G_DEBUG = 'Y' THEN
2144             AHL_DEBUG_PUB.debug('Found applicable MR-ID:Title' || l_appl_rec.mr_header_id || '[' || l_appl_rec.title || ']');
2145          END IF;
2146 
2147          /*
2148          IF (G_concurrent_flag = 'Y') THEN
2149            fnd_file.put_line (FND_FILE.LOG, 'Found applicable MR-ID:title:' || l_appl_rec.mr_header_id || ':'
2150                               || l_appl_rec.title);
2151          END IF;
2152          */
2153 
2154          l_applicable_mr_rec.csi_item_instance_id := l_appl_rec.csi_item_instance_id;
2155          l_applicable_mr_rec.MR_header_id := l_appl_rec.MR_header_id;
2156          l_applicable_mr_rec.title := l_appl_rec.title;
2157          l_applicable_mr_rec.version_number := l_appl_rec.version_number;
2158          l_applicable_mr_rec.Implement_status_code := l_appl_rec.Implement_status_code;
2159          l_applicable_mr_rec.copy_accomplishment_code := l_appl_rec.copy_accomplishment_code;
2160          l_applicable_mr_rec.repetitive_flag := l_appl_rec.repetitive_flag;
2161          l_applicable_mr_rec.show_repetitive_code := l_appl_rec.show_repetitive_code;
2162          l_applicable_mr_rec.preceding_mr_header_id := l_appl_rec.preceding_mr_header_id;
2163          l_applicable_mr_rec.descendent_count := l_appl_rec.descendent_count;
2164          l_applicable_mr_rec.whichever_first_code := l_appl_rec.whichever_first_code;
2165          l_applicable_mr_rec.effective_to := l_appl_rec.effective_to;
2166          l_applicable_mr_rec.effective_from := l_appl_rec.effective_from;
2167 
2168          -- call procedure to build effectivity.
2169          Build_Effectivity ( p_applicable_mrs_rec => l_applicable_mr_rec,
2170                              p_current_usage_tbl  => l_current_usage_tbl,
2171                              p_counter_rules_tbl  => l_counter_rules_tbl );
2172 
2173          IF G_DEBUG = 'Y' THEN
2174             AHL_DEBUG_PUB.debug('Process Unit:LOOP to next MR-ID');
2175          END IF;
2176 
2177        END LOOP; /* loop through next mr */
2178 
2179        IF G_DEBUG = 'Y' THEN
2180           AHL_DEBUG_PUB.debug('Process Unit:LOOP to next NODE');
2181        END IF;
2182 
2183     END LOOP; /* loop to process next node. */
2184   END IF; /* for count > 0 */
2185 
2186 END Process_ASO_Unit;
2187 
2188 --------------------------------------------------------------------------------
2189 -- Build the counter ratio that needs to be applied to the item instance based
2190 -- on its master configuration position. Input is the item instance.
2191 -- Modified per 11.5.10 UC enhancements.
2192 
2193 PROCEDURE build_Counter_Ratio(p_position_reference   IN VARCHAR2,
2194                               p_csi_item_instance_id IN NUMBER,
2195                               p_master_config_id     IN NUMBER,
2196                               x_counter_rules_tbl    OUT NOCOPY counter_rules_tbl_type)
2197 IS
2198 
2199   -- for counter rules given a relationship_id.
2200   CURSOR ahl_ctr_rule_csr ( p_relationship_id IN NUMBER) IS
2201     SELECT uom_code, ratio
2202     FROM ahl_ctr_update_rules
2203     WHERE relationship_id = p_relationship_id
2204         AND rule_code = 'STANDARD';
2205 
2206   -- traverse up the master configuration to top node.
2207 /*  CURSOR ahl_master_config_csr (p_start_node_id IN NUMBER) IS
2208     SELECT relationship_id
2209     FROM   ahl_relationships_b
2210     START WITH relationship_id = p_start_node_id
2211     CONNECT BY PRIOR parent_relationship_id = relationship_id
2212        AND trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate)
2213        AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate + 1));
2214 */
2215 
2216   -- Per UC 11.5.10 enhancements, instead of traversing MC; we traverse UC and get the position
2217   -- reference.
2218   CURSOR ahl_unit_config_csr (p_csi_item_instance_id IN NUMBER) IS
2219     SELECT to_number(position_reference) position_reference
2220     FROM csi_ii_relationships
2221     START WITH subject_id = p_csi_item_instance_id
2222                AND relationship_type_code = 'COMPONENT-OF'
2223                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
2224                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1))
2225     CONNECT BY PRIOR subject_id = object_id
2226                AND relationship_type_code = 'COMPONENT-OF'
2227                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
2228                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1));
2229 
2230   -- get root master configuration for the item's position reference.
2231   CURSOR ahl_posn_master_config_csr (p_start_node_id IN NUMBER) IS
2232     SELECT relationship_id
2233     FROM   ahl_mc_relationships
2234     WHERE parent_relationship_id IS NULL
2235     START WITH relationship_id = p_start_node_id
2236     CONNECT BY PRIOR parent_relationship_id = relationship_id
2237        AND trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate)
2238        AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate + 1));
2239 
2240 
2241   l_position_ref           NUMBER;
2242   l_uom_code               ahl_ctr_update_rules.uom_code%TYPE;
2243   l_ratio                  NUMBER;
2244   l_match_found_flag       BOOLEAN;
2245   l_table_count            NUMBER;
2246   l_posn_master_config_id  NUMBER;
2247 
2248   l_counter_rules_tbl  counter_rules_tbl_type;
2249 
2250 
2251 BEGIN
2252 
2253   IF G_DEBUG = 'Y' THEN
2254      AHL_DEBUG_PUB.debug ('Start Build Counter Ratio');
2255   END IF;
2256 
2257   -- If there is no master configuration
2258   IF (p_master_config_id IS NOT NULL) THEN
2259 
2260       l_position_ref := to_number(p_position_reference);
2261       x_counter_rules_tbl := l_counter_rules_tbl;
2262 
2263       -- Check if position reference belongs to master configuration.
2264       OPEN ahl_posn_master_config_csr(l_position_ref);
2265       FETCH ahl_posn_master_config_csr INTO l_posn_master_config_id;
2266       IF (ahl_posn_master_config_csr%FOUND) THEN
2267         IF (l_posn_master_config_id = p_master_config_id) THEN
2268 
2269            l_table_count := 0;
2270            -- Build counter rules table.
2271            FOR l_relationship_id IN ahl_unit_config_csr(p_csi_item_instance_id) LOOP
2272              FOR l_ratio_rec IN ahl_ctr_rule_csr (l_relationship_id.position_reference) LOOP
2273                l_uom_code := l_ratio_rec.uom_code;
2274                l_ratio    := l_ratio_rec.ratio;
2275 
2276                -- Check if uom_code already exists in x_counter_rules_tbl.
2277                l_match_found_flag := FALSE;
2278 
2279                IF (l_table_count > 0) THEN
2280                  FOR i IN x_counter_rules_tbl.FIRST..x_counter_rules_tbl.LAST LOOP
2281                    IF (x_counter_rules_tbl(i).uom_code = l_uom_code) THEN
2282                       x_counter_rules_tbl(i).ratio := x_counter_rules_tbl(i).ratio * l_ratio;
2283                       l_match_found_flag := TRUE;
2284                    END IF;
2285                  END LOOP; /* counter_rules_tbl */
2286                END IF; /* count > 0 */
2287 
2288                -- Add new row if match not found.
2289                IF NOT (l_match_found_flag) THEN
2290                  l_table_count := l_table_count + 1;
2291                  x_counter_rules_tbl(l_table_count).uom_code := l_uom_code;
2292                  x_counter_rules_tbl(l_table_count).ratio    := l_ratio;
2293                END IF;
2294              END LOOP; /* for ahl_ctr_rule_csr */
2295 
2296            END LOOP; /* for ahl_master-config_csr */
2297         END IF; /* master config id matches */
2298       END IF; /* found */
2299       CLOSE ahl_posn_master_config_csr;
2300   END IF; /* master config not null */
2301 
2302   IF G_DEBUG = 'Y' THEN
2303      AHL_DEBUG_PUB.debug ('End Build Counter Ratio');
2304      AHL_DEBUG_PUB.debug ('Counter Rules tbl count' || x_counter_rules_tbl.COUNT);
2305   END IF;
2306 
2307 EXCEPTION
2308 
2309   WHEN INVALID_NUMBER THEN
2310     x_counter_rules_tbl := l_counter_rules_tbl;
2311 
2312 END build_Counter_Ratio;
2313 
2314 ----------------------------------------------------------------------------------
2315 -- Build the current usage on the item instance's counters based on counters attached
2316 -- to the item instance.
2317 
2318 PROCEDURE get_Current_Usage ( p_csi_item_instance_id IN NUMBER,
2319                               x_current_usage_tbl    OUT NOCOPY counter_values_tbl_type )
2320 IS
2321 
2322   CURSOR csi_cp_counters_csr (p_csi_instance_id IN NUMBER) IS
2323      /*
2324      SELECT counter_id, uom_code, net_reading, counter_name
2325      FROM   csi_cp_counters_v
2326      WHERE  customer_product_id = p_csi_item_instance_id
2327      ORDER BY uom_code;
2328 
2329      SELECT cc.counter_id, cc.uom_code,
2330             cc.counter_template_name counter_name
2331      from   csi_counter_associations cca, csi_counters_vl cc
2332      where  cca.counter_id = cc.counter_id
2333      AND    source_object_code = 'CP'
2334      AND    source_object_id = p_csi_instance_id;
2335      */
2336 
2337      /* reverted to old code - see bug# 7355947
2338      SELECT cc.counter_id, cc.uom_code,
2339             cc.counter_template_name counter_name,
2340             (select ccr.net_reading
2341             from csi_counter_readings ccr
2342             where ccr.counter_id = cc.counter_id
2343             and value_timestamp = (select max(value_timestamp) from csi_counter_readings rd
2344                                    where counter_id = cc.counter_id
2345                                    and nvl(disabled_flag,'N') = 'N')) net_reading
2346      FROM   csi_counter_associations cca, csi_counters_vl cc
2347      WHERE  cca.counter_id = cc.counter_id
2348      AND    source_object_code = 'CP'
2349      AND    source_object_id = p_csi_item_instance_id;
2350      */
2351 
2352      -- 15 Sept 08: Modified based on IB changes - refer bug# 7374316
2353      SELECT cc.counter_id, cc.uom_code,
2354             cc.counter_template_name counter_name,
2355             (select ccr.net_reading
2356              from csi_counter_readings ccr
2357              where ccr.counter_value_id = cc.CTR_VAL_MAX_SEQ_NO
2358                and nvl(ccr.disabled_flag,'N') = 'N')
2359      FROM   csi_counter_associations cca, csi_counters_vl cc
2360      WHERE  cca.counter_id = cc.counter_id
2361      AND    source_object_code = 'CP'
2362      AND    source_object_id = p_csi_instance_id;
2363 
2364   /*
2365   -- get net reading.
2366   CURSOR csi_cp_counters_val_csr (p_counter_id IN NUMBER) IS
2367      SELECT nvl(cv.net_reading,0) net_reading
2368      FROM csi_counter_values_v cv
2369      WHERE cv.counter_id = p_counter_id
2370        AND rownum < 2;
2371 
2372   -- get net reading.
2373   CURSOR csi_cp_counters_val_csr (p_counter_id IN NUMBER) IS
2374      SELECT * FROM
2375         (SELECT net_reading
2376          FROM csi_counter_readings
2377          WHERE counter_id = p_counter_id
2378            AND nvl(disabled_flag,'N') = 'N'
2379          ORDER BY value_timestamp desc)
2380      WHERE rownum < 2;
2381   */
2382 
2383   i  NUMBER;
2384 
2385   l_current_usage_tbl  counter_values_tbl_type;
2386 
2387   -- added for perf fix.
2388   l_ctr_id_tbl       nbr_tbl_type;
2389   l_ctr_uom_tbl      vchar_tbl_type;
2390   l_ctr_name_tbl     vchar_tbl_type;
2391   l_ctr_net_read_tbl nbr_tbl_type;
2392 
2393 BEGIN
2394 
2395   IF G_DEBUG = 'Y' THEN
2396      AHL_DEBUG_PUB.debug ('Start Get Current Usage');
2397   END IF;
2398 
2399   -- Build current usage counters.
2400   OPEN csi_cp_counters_csr(p_csi_item_instance_id);
2401   FETCH csi_cp_counters_csr BULK COLLECT INTO l_ctr_id_tbl, l_ctr_uom_tbl, l_ctr_name_tbl,
2402                                               l_ctr_net_read_tbl;
2403   CLOSE csi_cp_counters_csr;
2404 
2405   /*
2406   LOOP
2407     FETCH csi_cp_counters_csr INTO l_current_usage_tbl(i).counter_id,
2408                                    l_current_usage_tbl(i).uom_code,
2409                                    l_current_usage_tbl(i).counter_name;
2410     EXIT WHEN csi_cp_counters_csr%NOTFOUND;
2411 
2412     -- get latest net reading.
2413     OPEN csi_cp_counters_val_csr(l_current_usage_tbl(i).counter_id);
2414     FETCH csi_cp_counters_val_csr INTO l_current_usage_tbl(i).counter_value;
2415     CLOSE csi_cp_counters_val_csr;
2416 
2417     IF (l_current_usage_tbl(i).counter_value IS NULL) THEN
2418        l_current_usage_tbl(i).counter_value := 0;
2419     END IF;
2420 
2421     i := i + 1;
2422   END LOOP;
2423   */
2424 
2425   IF (l_ctr_id_tbl.COUNT > 0) THEN
2426 
2427     i := 1;
2428     FOR j IN l_ctr_id_tbl.FIRST..l_ctr_id_tbl.LAST LOOP
2429       l_current_usage_tbl(i).counter_id := l_ctr_id_tbl(j);
2430       l_current_usage_tbl(i).uom_code   := l_ctr_uom_tbl(j);
2431       l_current_usage_tbl(i).counter_name := l_ctr_name_tbl(j);
2432 
2433       /* 15 Sept 08: commented to incorporate IB changes - see bug# 7374316
2434       -- get latest net reading.
2435       OPEN csi_cp_counters_val_csr(l_current_usage_tbl(i).counter_id);
2436       FETCH csi_cp_counters_val_csr INTO l_current_usage_tbl(i).counter_value;
2437       CLOSE csi_cp_counters_val_csr;
2438 
2439       IF (l_current_usage_tbl(i).counter_value IS NULL) THEN
2440         l_current_usage_tbl(i).counter_value := 0;
2441       END IF;
2442       */
2443 
2444       IF (l_ctr_net_read_tbl(j) IS NULL) THEN
2445          l_current_usage_tbl(i).counter_value := 0;
2446       ELSE
2447          l_current_usage_tbl(i).counter_value := l_ctr_net_read_tbl(j);
2448       END IF;
2449 
2450       i := i + 1;
2451     END LOOP;
2452   END IF; -- l_ctr_id_tbl.COUNT
2453 
2454   -- Set return value.
2455   x_current_usage_tbl := l_current_usage_tbl;
2456 
2457   IF G_DEBUG = 'Y' THEN
2458      AHL_DEBUG_PUB.debug ('Counter Usage tbl count' || x_current_usage_tbl.COUNT);
2459      AHL_DEBUG_PUB.debug ('End Get Current Usage');
2460   END IF;
2461 
2462 END get_Current_Usage;
2463 
2464 --------------------------------------------------------------------------------------------
2465 -- Get accomplishment details for an MR.
2466 -- Added parameter x_no_forecast_flag to fix bug# 6711228.
2467 PROCEDURE get_accomplishment_details (p_applicable_mrs_rec IN applicable_mrs_rec_type,
2468                                       p_current_usage_tbl  IN counter_values_tbl_type,
2469                                       p_counter_rules_tbl  IN counter_rules_tbl_type,
2470                                       x_accomplishment_date OUT NOCOPY DATE,
2471                                       x_last_acc_counter_val_tbl OUT NOCOPY counter_values_tbl_type,
2472                                       x_one_time_mr_flag     OUT NOCOPY BOOLEAN,
2473                                       -- x_update_check_flag OUT NOCOPY BOOLEAN,
2474                                       x_dependent_mr_flag  OUT NOCOPY BOOLEAN,
2475                                       x_get_preceding_next_due OUT NOCOPY BOOLEAN,
2476                                       x_mr_accomplish_exists   OUT NOCOPY BOOLEAN,
2477                                       x_no_forecast_flag       OUT NOCOPY BOOLEAN)
2478 IS
2479 
2480   -- Get last accomplishment counter values.
2481   CURSOR ahl_unit_accomplish_csr (p_unit_effectivity_id IN NUMBER) IS
2482 
2483   /*
2484   SELECT ua.counter_id, ua.counter_value, cs.uom_code, cs.name counter_name
2485    FROM   ahl_unit_accomplishmnts ua, cs_counters_v cs
2486    WHERE  ua.counter_id = cs.counter_id AND
2487           ua.unit_effectivity_id = p_unit_effectivity_id
2488    ORDER BY cs.uom_code;
2489 */
2490 
2491 	 --Priyan
2492 	 --Query being changed due to performance related fixes
2493 	 --Refer Bug # 4918744
2494 	 --Changed the usage of CS_COUNTERS_V to CSI_COUNTERS_VL
2495 
2496 	SELECT
2497 		UA.COUNTER_ID,
2498 		UA.COUNTER_VALUE,
2499 		CS.UOM_CODE,
2500 		--CS.NAME COUNTER_NAME
2501                 CS.COUNTER_TEMPLATE_NAME COUNTER_NAME
2502 	FROM
2503 		AHL_UNIT_ACCOMPLISHMNTS UA,
2504 		CSI_COUNTERS_VL CS
2505 	WHERE
2506 		UA.COUNTER_ID = CS.COUNTER_ID AND
2507 		UA.UNIT_EFFECTIVITY_ID = P_UNIT_EFFECTIVITY_ID
2508 	ORDER BY
2509 		CS.UOM_CODE ;
2510 
2511   -- Get instance counter details.
2512   CURSOR csi_cp_counters_csr (p_csi_instance_id IN NUMBER) IS
2513      /*
2514      SELECT counter_id, uom_code, counter_name
2515      FROM   csi_cp_counters_v
2516      WHERE  customer_product_id = p_csi_instance_id
2517      ORDER BY uom_code;
2518      */
2519      SELECT cc.counter_id, cc.uom_code,
2520             cc.counter_template_name counter_name
2521      from   csi_counter_associations cca, csi_counters_vl cc
2522      where  cca.counter_id = cc.counter_id
2523      AND    source_object_code = 'CP'
2524      AND    source_object_id = p_csi_instance_id;
2525 
2526   -- Get deferred MRs.
2527   -- consider deferral_effective_on instead of due date, only if l_affect_calc_due_date is 'N'.
2528   CURSOR ahl_def_csr (p_csi_instance_id IN NUMBER,
2529                       p_mr_header_id    IN NUMBER) IS
2530     SELECT
2531     -- fix for bug# 6875650. Deferral date includes timestamp.
2532     --decode (affect_due_calc_flag, 'N', trunc(nvl(visit_end_date, deferral_effective_on)), trunc(nvl(visit_end_date, due_date)))
2533 
2534     decode (affect_due_calc_flag, 'N', deferral_effective_on, nvl(visit_end_date, due_date))
2535     FROM ahl_temp_unit_SR_deferrals
2536     WHERE csi_item_instance_id = p_csi_instance_id
2537           AND mr_header_id = p_mr_header_id
2538           AND object_type = 'MR'
2539           AND deferral_effective_on IS NOT NULL
2540     ORDER BY deferral_effective_on DESC;
2541     -- get the latest deferral.
2542     -- pick only deferrals and not SR related MRs.
2543 
2544   l_acc_unit_effectivity_id   NUMBER;
2545   l_acc_status_code           ahl_unit_effectivities_app_v.status_code%TYPE;
2546 
2547   l_last_accomplishment_date  DATE;
2548   l_last_acc_counter_val_tbl  counter_values_tbl_type;
2549   l_due_counter_val_tbl       counter_values_tbl_type;
2550   l_due_date      DATE;
2551 
2552   l_return_val   BOOLEAN;
2553   i NUMBER;
2554   l_acc_deferral_flag  BOOLEAN;
2555 
2556   l_dependent_mr_flag  BOOLEAN;
2557   /* set based on preceding mr and accomplishment */
2558 
2559   --l_update_check_flag  BOOLEAN := FALSE;
2560   l_get_preceding_next_due BOOLEAN := FALSE;
2561 
2562   l_one_time_mr_flag  BOOLEAN := FALSE;
2563   /* set to true if the MR is a one time MR and already has an accomplishment */
2564   /* or there exists a deferral with it's due date = null. */
2565 
2566   l_net_reading  NUMBER;
2567 
2568   l_no_forecast_flag  BOOLEAN := FALSE;
2569   -- set this flag to true if no forecast available when calculating deferral due date.
2570 
2571   l_mr_accomplish_exists BOOLEAN := FALSE;
2572   -- set this flag if a mr accomplishment exists.
2573 
2574 BEGIN
2575 
2576   IF G_DEBUG = 'Y' THEN
2577      AHL_DEBUG_PUB.debug ('Start Get Accomplishment Details');
2578   END IF;
2579 
2580   -- Check if any deferrals exist.
2581   OPEN ahl_def_csr (p_applicable_mrs_rec.csi_item_instance_id,
2582                     p_applicable_mrs_rec.mr_header_id);
2583   FETCH ahl_def_csr INTO l_last_accomplishment_date;
2584   IF (ahl_def_csr%FOUND) THEN
2585     l_acc_deferral_flag := TRUE;
2586     l_mr_accomplish_exists := TRUE; -- deferral record.
2587   ELSE
2588     -- Lookup if any accomplishments exist.
2589 
2590     -- Get last accomplishment for the MR..
2591     AHL_UMP_UTIL_PKG.get_last_accomplishment(p_applicable_mrs_rec.csi_item_instance_id,
2592                                              p_applicable_mrs_rec.mr_header_id,
2593                                              l_last_accomplishment_date,
2594                                              l_acc_unit_effectivity_id,
2595                                              l_acc_deferral_flag,
2596                                              l_acc_status_code,
2597                                              l_return_val);
2598     IF (l_acc_unit_effectivity_id IS NOT NULL) THEN
2599       l_mr_accomplish_exists := TRUE;
2600     END IF;
2601 
2602   END IF;
2603 
2604   -- Check for one time MR.
2605   IF (l_acc_unit_effectivity_id IS NOT NULL AND p_applicable_mrs_rec.repetitive_flag = 'N') OR
2606      (l_acc_deferral_flag = TRUE AND p_applicable_mrs_rec.repetitive_flag = 'N') THEN
2607      --dbms_output.put_line('one time true');
2608      l_one_time_mr_flag := TRUE;
2609   END IF;
2610 
2611   l_dependent_mr_flag := FALSE;
2612   -- Set this flag only if there are no accomplishments for the MR and this MR has
2613   -- a preceding MR.
2614 
2615   IF (p_applicable_mrs_rec.preceding_mr_header_id IS NOT NULL AND
2616      l_acc_unit_effectivity_id IS NULL)
2617   THEN
2618      l_dependent_mr_flag := TRUE;
2619      --dbms_output.put_line ('dependent flag true');
2620      -- Modified to get first accomplishment to fix bug#6711228
2621      AHL_UMP_UTIL_PKG.get_first_accomplishment(p_applicable_mrs_rec.csi_item_instance_id,
2622                                                p_applicable_mrs_rec.preceding_mr_header_id,
2623                                                l_last_accomplishment_date,
2624                                                l_acc_unit_effectivity_id,
2625                                                l_acc_deferral_flag,
2626                                                l_acc_status_code,
2627                                                l_return_val);
2628   END IF;
2629 
2630   IF (l_acc_deferral_flag) THEN
2631     IF (l_last_accomplishment_date IS NULL) THEN
2632        --l_one_time_mr_flag := TRUE;  -- no forecast and cannot calculate deferral due date.
2633        l_no_forecast_flag := TRUE;  -- no forecast and cannot calculate deferral due date.
2634     -- fix for bug# 6875650.
2635     -- ELSIF (trunc(l_last_accomplishment_date) <= trunc(sysdate)) THEN
2636     ELSIF (l_last_accomplishment_date <= sysdate) THEN
2637       -- get counter values from counter values tables.
2638       i := 1;
2639       FOR instance_counter_rec IN csi_cp_counters_csr(p_applicable_mrs_rec.csi_item_instance_id) LOOP
2640           l_net_reading := 0;
2641           get_ctr_reading_for_datetime (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
2642                                         p_counter_id           => instance_counter_rec.counter_id,
2643                                         p_reading_date         => l_last_accomplishment_date,
2644                                         x_net_reading          => l_net_reading);
2645 
2646           l_last_acc_counter_val_tbl(i).uom_code := instance_counter_rec.uom_code;
2647           l_last_acc_counter_val_tbl(i).counter_id := instance_counter_rec.counter_id;
2648           l_last_acc_counter_val_tbl(i).counter_name := instance_counter_rec.counter_name;
2649           l_last_acc_counter_val_tbl(i).counter_value := l_net_reading;
2650           i := i + 1;
2651 
2652       END LOOP;
2653     ELSE  -- deferral due date is a future date.
2654        -- get all counter values as on l_preceding_next_due_date.
2655        Get_Due_at_Counter_Values (p_last_due_date => sysdate,
2656                                   p_last_due_counter_val_tbl => p_current_usage_tbl,
2657                                   p_due_date => l_last_accomplishment_date,
2658                                   p_counter_rules_tbl => p_counter_rules_tbl,
2659                                   x_due_at_counter_val_tbl => l_last_acc_counter_val_tbl,
2660                                   x_return_value => l_return_val);
2661 
2662        IF G_DEBUG = 'Y' THEN
2663          AHL_DEBUG_PUB.Debug('l_deferral_due_date: ' || l_last_accomplishment_date);
2664          IF (l_last_acc_counter_val_tbl.COUNT) > 0 THEN
2665             for i in l_last_acc_counter_val_tbl.FIRST..l_last_acc_counter_val_tbl.LAST LOOP
2666                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);
2667             end loop;
2668          END IF;
2669        END IF;
2670 
2671        -- check return value.
2672        IF NOT(l_return_val) THEN  -- no forecast case.
2673          --l_one_time_mr_flag := TRUE;
2674          l_no_forecast_flag := TRUE;
2675        END IF;
2676 
2677     END IF;  -- Last accomplishment date.
2678   ELSE  -- not based on deferral_effective_date.
2679     IF (l_acc_unit_effectivity_id IS NOT NULL) THEN
2680       i := 1;
2681       -- Build last accomplishment counter values.
2682       FOR l_acc_counter_rec IN ahl_unit_accomplish_csr(l_acc_unit_effectivity_id) LOOP
2683         l_last_acc_counter_val_tbl(i).uom_code := l_acc_counter_rec.uom_code;
2684         l_last_acc_counter_val_tbl(i).counter_id := l_acc_counter_rec.counter_id;
2685         l_last_acc_counter_val_tbl(i).counter_name := l_acc_counter_rec.counter_name;
2686         l_last_acc_counter_val_tbl(i).counter_value := l_acc_counter_rec.counter_value;
2687         i := i + 1;
2688       END LOOP;
2689 
2690     ELSIF (l_dependent_mr_flag) THEN
2691        -- no accomplishment for preceding MR available.
2692        -- get the next due date from temporary table for calculation.
2693        l_get_preceding_next_due := TRUE;
2694     END IF;
2695   END IF; -- l_acc_deferral_flag.
2696 
2697   -- set return parameters.
2698   x_accomplishment_date := l_last_accomplishment_date;
2699   x_last_acc_counter_val_tbl := l_last_acc_counter_val_tbl;
2700   x_one_time_mr_flag := l_one_time_mr_flag;
2701   x_dependent_mr_flag := l_dependent_mr_flag;
2702   x_get_preceding_next_due := l_get_preceding_next_due;
2703   x_no_forecast_flag := l_no_forecast_flag;
2704   x_mr_accomplish_exists := l_mr_accomplish_exists;
2705 
2706   IF G_DEBUG = 'Y' THEN
2707      AHL_DEBUG_PUB.debug ('Last Accomplished Date:' || x_accomplishment_date);
2708      AHL_DEBUG_PUB.debug ('Count of ctr values:' || x_last_acc_counter_val_tbl.COUNT);
2709      AHL_DEBUG_PUB.debug ('End Get Accomplishment Details');
2710   END IF;
2711 
2712 END get_accomplishment_details;
2713 
2714 ------------------------------------------------------------------------------
2715 -- Build unit effectivity for a given item instance and a maintenance requirement.
2716 -- The unit effectivities created here will be written into a temporary table.
2717 
2718 PROCEDURE Build_Effectivity ( p_applicable_mrs_rec IN applicable_mrs_rec_type,
2719                               p_current_usage_tbl  IN counter_values_tbl_type,
2720                               p_counter_rules_tbl  IN counter_rules_tbl_type )
2721 
2722 IS
2723 
2724   -- retrieve current unit effectivity records.
2725   CURSOR ahl_unit_effectivity_csr (p_mr_header_id IN NUMBER,
2726                                    p_csi_item_instance_id IN NUMBER) IS
2727   SELECT ue.unit_effectivity_id, ue.status_code, reln.related_ue_id, reln.originator_ue_id
2728   FROM   ahl_unit_effectivities_app_v UE, ahl_UE_relationships reln
2729   WHERE  UE.unit_effectivity_id = RELN.RELATED_UE_ID(+)
2730        AND mr_header_id = p_mr_header_id
2731        AND csi_item_instance_id = p_csi_item_instance_id
2732        AND (UE.Status_code IS NULL OR status_code = 'INIT-DUE')
2733        AND UE.defer_from_ue_id IS NULL  -- do not pick deferred unit effectivities.
2734        AND nvl(UE.manually_planned_flag,'N') = 'N'   -- do not pick manually planned UEs.
2735        -- do not pick up child UEs if parent init-accomplished.
2736        AND NOT EXISTS (SELECT 'x' FROM AHL_UNIT_EFFECTIVITIES_B PARENT_UE
2737                        WHERE PARENT_UE.UNIT_EFFECTIVITY_ID = RELN.ORIGINATOR_UE_ID
2738                          AND PARENT_UE.STATUS_CODE = 'INIT-ACCOMPLISHED')
2739   ORDER BY forecast_sequence ASC;
2740 
2741   -- Get group MRs if any, from ahl_temp_unit_effectivities for the item instance.
2742   -- select only the first row.
2743   CURSOR ahl_temp_ue_csr (p_item_instance_id IN NUMBER,
2744                           p_mr_header_id     IN NUMBER,
2745                           p_last_due_date    IN DATE,
2746                           p_due_date         IN DATE ) IS
2747    SELECT *
2748    FROM (
2749         SELECT due_date,
2750                orig_csi_item_instance_id,
2751                orig_mr_header_id,
2752                --orig_forecast_sequence,
2753                visit_end_date
2754         FROM ahl_temp_unit_effectivities
2755         WHERE csi_item_instance_id = p_item_instance_id AND
2756               mr_header_id = p_mr_header_id AND
2757               orig_csi_item_instance_id IS NOT NULL AND
2758               orig_mr_header_id IS NOT NULL AND
2759               trunc(nvl(visit_end_date, nvl(due_date, p_last_due_date))) > trunc(p_last_due_date) AND
2760               trunc(nvl(visit_end_date, nvl(due_date, p_due_date+1))) <= trunc(p_due_date) AND
2761               preceding_check_flag = 'N'
2762         /* ignore records with null due dates */
2763         /* order selected rows so that the record with max due date is first */
2764         /* consider visit end date instead of due date, if it is available. */
2765 
2766         UNION
2767 
2768         -- Get SR's.
2769         SELECT due_date,
2770                csi_item_instance_id orig_csi_item_instance_id,
2771                mr_header_id orig_mr_header_id,
2772                visit_end_date
2773         FROM ahl_temp_unit_SR_deferrals
2774         WHERE csi_item_instance_id = p_item_instance_id
2775               AND mr_header_id = p_mr_header_id
2776                   AND trunc(nvl(visit_end_date, nvl(due_date, p_last_due_date))) > trunc(p_last_due_date)
2777               AND trunc(nvl(visit_end_date, nvl(due_date, p_due_date+1))) <= trunc(p_due_date)
2778               AND deferral_effective_on IS NULL -- pick only SR related MRs.
2779         -- ignore records with null due dates.
2780         -- ignore deferral records.
2781 
2782         ORDER BY due_date DESC
2783         )
2784    WHERE ROWNUM < 2;
2785 
2786   -- in case of 'next-due', we need to check p_last_due_date equality condition too.
2787   -- Get group MRs if any, from ahl_temp_unit_effectivities for the item instance.
2788   -- select only the first row.
2789   CURSOR ahl_temp_ue_csr1 (p_item_instance_id IN NUMBER,
2790                            p_mr_header_id     IN NUMBER,
2791                            p_last_due_date    IN DATE,
2792                            p_due_date         IN DATE ) IS
2793    SELECT *
2794    FROM (
2795         SELECT due_date,
2796                orig_csi_item_instance_id,
2797                orig_mr_header_id,
2798                --orig_forecast_sequence,
2799                visit_end_date
2800         FROM ahl_temp_unit_effectivities
2801         WHERE csi_item_instance_id = p_item_instance_id AND
2802               mr_header_id = p_mr_header_id AND
2803               orig_csi_item_instance_id IS NOT NULL AND
2804               orig_mr_header_id IS NOT NULL AND
2805               trunc(nvl(visit_end_date, nvl(due_date, p_last_due_date))) >= trunc(p_last_due_date) AND
2806               trunc(nvl(visit_end_date, nvl(due_date, p_due_date+1))) <= trunc(p_due_date) AND
2807               preceding_check_flag = 'N'
2808         /* ignore records with null due dates */
2809         /* order selected rows so that the record with max due date is first */
2810         /* consider visit end date instead of due date, if it is available. */
2811 
2812         UNION
2813 
2814         -- Get SR's.
2815         SELECT due_date,
2816                csi_item_instance_id orig_csi_item_instance_id,
2817                mr_header_id orig_mr_header_id,
2818                visit_end_date
2819         FROM ahl_temp_unit_SR_deferrals
2820         WHERE csi_item_instance_id = p_item_instance_id
2821               AND mr_header_id = p_mr_header_id
2822               AND trunc(nvl(visit_end_date, nvl(due_date, p_last_due_date))) >= trunc(p_last_due_date)
2823               AND trunc(nvl(visit_end_date, nvl(due_date, p_due_date+1))) <= trunc(p_due_date)
2824               AND deferral_effective_on IS NULL -- pick only SR related MRs.
2825         -- ignore records with null due dates.
2826         -- ignore deferral records.
2827         ORDER BY due_date DESC
2828         )
2829    WHERE ROWNUM < 2;
2830 
2831   -- Check if MR is a group MR.
2832   CURSOR group_check_csr (p_item_instance_id IN NUMBER,
2833                           p_mr_header_id IN NUMBER) IS
2834    SELECT 'x'
2835    FROM ahl_applicable_mr_relns
2836    WHERE orig_csi_item_instance_id = p_item_instance_id AND
2837          orig_mr_header_id = p_mr_header_id;
2838 
2839   -- Get next due date of preceding MR from temporary table.
2840   CURSOR preceding_due_date_csr (p_preceding_instance_id IN NUMBER,
2841                                  p_preceding_mr_header_id IN NUMBER) IS
2842    SELECT due_date
2843    FROM ahl_temp_unit_effectivities
2844    WHERE csi_item_instance_id = p_preceding_instance_id AND
2845          mr_header_id = p_preceding_mr_header_id AND
2846          preceding_check_flag = 'N'
2847    ORDER by due_date;
2848 
2849   -- Added for 11.5.10+ enhancements for Unplanned MRs.
2850   -- Read open Unplanned MRs.
2851   CURSOR ahl_unplanned_MRs_csr(p_item_instance_id IN NUMBER,
2852                                p_mr_header_id     IN NUMBER) IS
2853     SELECT ue.unit_effectivity_id
2854     FROM ahl_unit_effectivities_app_v ue
2855     WHERE ue.csi_item_instance_id = p_item_instance_id
2856        AND ue.mr_header_id = p_mr_header_id
2857        AND ue.status_code IS NULL
2858        AND ue.manually_planned_flag = 'Y'
2859        AND NOT EXISTS (SELECT 'x'
2860                        FROM ahl_ue_relationships uer, ahl_unit_effectivities_b ue1
2861                        WHERE uer.related_ue_id = ue.unit_effectivity_id
2862                          AND uer.originator_ue_id = ue1.unit_effectivity_id
2863                          AND ue1.object_type = 'SR');
2864     -- Do not pick MRs associated to a SR.
2865   --
2866   l_unit_effectivity_tbl  unit_effectivity_tbl_type;
2867   /* this table will contain the current unit effectivity definitions for the mr and item instance */
2868 
2869   i    NUMBER := 0;
2870   /* running index for unit effectivity tbl */
2871 
2872   l_visit_start_date   DATE;
2873   l_visit_end_date     DATE;
2874   l_visit_assign_code  VARCHAR2(30);
2875 
2876   l_forecast_sequence  NUMBER;
2877   l_old_UE_forecast_sequence  NUMBER;
2878   l_next_due_date_rec         next_due_date_rec_type;
2879 
2880   l_new_unit_effectivity_rec      ahl_temp_unit_effectivities%ROWTYPE;
2881   l_new_unit_effectivity_initrec  ahl_temp_unit_effectivities%ROWTYPE;
2882 
2883   l_temp_grp_mr_rec   ahl_temp_ue_csr%ROWTYPE;
2884 
2885   l_last_accomplishment_date  DATE;
2886   l_last_acc_counter_val_tbl  counter_values_tbl_type;
2887   l_dependent_mr_flag BOOLEAN;
2888   l_get_preceding_next_due BOOLEAN; -- to indicate that the dependent MR calculation is based on preceding MR's next due.
2889   l_preceding_next_due_date DATE;
2890 
2891   l_one_time_mr_flag  BOOLEAN;
2892 
2893   l_calc_due_date_flag   BOOLEAN := TRUE;
2894   -- set to true if preceding MR due date is null. So the dependent's due date
2895   -- will also be null. Calc due date must not be done.
2896 
2897   --l_bef_tolr_due_date  DATE;
2898   --l_aft_tolr_due_date  DATE;
2899 
2900   l_last_due_date  DATE;
2901   l_last_due_counter_val_tbl  counter_values_tbl_type;
2902   l_due_at_counter_val_tbl    counter_values_tbl_type;
2903   l_due_date       DATE;
2904 
2905   l_next_due_flag  BOOLEAN;
2906   l_grp_duedate_found  BOOLEAN;
2907   l_old_UE_forecast_found BOOLEAN := TRUE;
2908 
2909   l_return_value BOOLEAN;
2910   l_junk    VARCHAR2(1);
2911   group_check_flag  BOOLEAN := FALSE;  -- flag to check if it is a group MR.
2912 
2913   -- Added for 11.5.10+ enhancements for Unplanned MRs.
2914   -- Define rec and table type to hold Unplanned MRs.
2915   TYPE Unplanned_UE_rec_type IS RECORD(
2916      UNIT_EFFECTIVITY_ID  NUMBER,
2917      VISIT_END_DATE       DATE);
2918 
2919   TYPE Unplanned_UE_Tbl_type IS TABLE OF Unplanned_UE_rec_type INDEX BY BINARY_INTEGER;
2920 
2921   l_unplanned_MRs_tbl     Unplanned_UE_Tbl_type;
2922   l_min_visit_date        DATE;
2923 
2924   -- R12 to fix bug# 4224867.
2925   l_duplicate_MRs         NUMBER;
2926   l_usage_per_day         NUMBER;
2927 
2928   -- Added to fix bug# 6711228.
2929   l_no_forecast_flag      BOOLEAN;
2930   l_mr_accomplish_exists  BOOLEAN;
2931 
2932   -- Added to fix bug# 6858788
2933   l_last_due_mr_interval_id NUMBER;
2934 
2935   -- Added for performance.
2936   l_ue_id_tbl              nbr_tbl_type;
2937   l_ue_status_tbl          vchar_tbl_type;
2938   l_related_ue_tbl         nbr_tbl_type;
2939   l_orig_ue_tbl            nbr_tbl_type;
2940 
2941   l_buffer_limit           NUMBER := 1000;
2942 
2943 BEGIN
2944 
2945 
2946   IF G_DEBUG = 'Y' THEN
2947      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 );
2948   END IF;
2949 
2950   -- Set last accomplishment details.
2951   Get_accomplishment_details(p_applicable_mrs_rec => p_applicable_mrs_rec,
2952                              p_current_usage_tbl  => p_current_usage_tbl,
2953                              p_counter_rules_tbl  => p_counter_rules_tbl,
2954                              x_accomplishment_date => l_last_accomplishment_date,
2955                              x_last_acc_counter_val_tbl => l_last_acc_counter_val_tbl,
2956                              x_one_time_mr_flag         => l_one_time_mr_flag,
2957                              x_dependent_mr_flag => l_dependent_mr_flag,
2958                              x_get_preceding_next_due => l_get_preceding_next_due,
2959                              x_mr_accomplish_exists  => l_mr_accomplish_exists,
2960                              x_no_forecast_flag => l_no_forecast_flag );
2961 
2962   -- Check for one time MR case.
2963   IF (l_one_time_mr_flag) THEN
2964      --dbms_output.put_line('one time true in build');
2965      GOTO process_preceding_mr;
2966   ELSIF (l_no_forecast_flag) THEN
2967      RETURN;  -- no more MRs needed.
2968   END IF;
2969 
2970   -- get next accomplishment details for the preceding MR if needed.
2971   IF (l_get_preceding_next_due) THEN
2972     OPEN preceding_due_date_csr (p_applicable_mrs_rec.csi_item_instance_id,
2973                                  p_applicable_mrs_rec.preceding_mr_header_id);
2974 
2975     FETCH preceding_due_date_csr INTO l_preceding_next_due_date;
2976     IF (preceding_due_date_csr%NOTFOUND) OR (l_preceding_next_due_date IS NULL) THEN
2977         --dbms_output.put_line ('not found preceding');
2978         l_calc_due_date_flag := FALSE;
2979     ELSE
2980         l_last_accomplishment_date := l_preceding_next_due_date;
2981         --dbms_output.put_line ('found preceding due_date' ||l_preceding_next_due_date );
2982         -- get all counter values as on l_preceding_next_due_date.
2983         Get_Due_at_Counter_Values (p_last_due_date => sysdate,
2984                                    p_last_due_counter_val_tbl => p_current_usage_tbl,
2985                                    p_due_date => l_preceding_next_due_date,
2986                                    p_counter_rules_tbl => p_counter_rules_tbl,
2987                                    x_due_at_counter_val_tbl => l_last_acc_counter_val_tbl,
2988                                    x_return_value => l_return_value);
2989 
2990         IF G_DEBUG = 'Y' THEN
2991            AHL_DEBUG_PUB.Debug('l_preceding_due_date: '|| l_preceding_next_due_date);
2992            IF (l_last_acc_counter_val_tbl.COUNT) > 0 THEN
2993               for i in l_last_acc_counter_val_tbl.FIRST..l_last_acc_counter_val_tbl.LAST LOOP
2994                 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);
2995               end loop;
2996            END IF;
2997         END IF;
2998 
2999         -- check return value.
3000         IF NOT(l_return_value) THEN  -- no forecast case.
3001           --l_preceding_next_due_date := NULL;
3002           l_calc_due_date_flag := FALSE;
3003         END IF;
3004     END IF;
3005     CLOSE preceding_due_date_csr;
3006   END IF;
3007 
3008   -- Read existing unit effectivity records for the mr and item instance.
3009   OPEN ahl_unit_effectivity_csr(p_applicable_mrs_rec.mr_header_id,
3010                                 p_applicable_mrs_rec.csi_item_instance_id);
3011   i := 0;
3012   l_forecast_sequence := 0;
3013   LOOP
3014     /*
3015     FETCH ahl_unit_effectivity_csr INTO l_unit_effectivity_tbl(i).unit_effectivity_id,
3016                                         l_unit_effectivity_tbl(i).status_code,
3017                                         l_unit_effectivity_tbl(i).related_ue_id,
3018                                         l_unit_effectivity_tbl(i).originator_ue_id;
3019     */
3020 
3021     FETCH ahl_unit_effectivity_csr BULK COLLECT INTO l_ue_id_tbl, l_ue_status_tbl, l_related_ue_tbl,
3022                                                      l_orig_ue_tbl LIMIT l_buffer_limit;
3023 
3024     --EXIT WHEN ahl_unit_effectivity_csr%NOTFOUND;
3025     EXIT WHEN (l_ue_id_tbl.count = 0);
3026 
3027     IF G_DEBUG = 'Y' THEN
3028        AHL_DEBUG_PUB.debug ('Rows fetched for instance-mr is: ' || ahl_unit_effectivity_csr%ROWCOUNT);
3029     END IF;
3030 
3031     --dbms_output.put_line ('unit eff load i:' || l_unit_effectivity_tbl(i).unit_effectivity_id);
3032 
3033     FOR j IN l_ue_id_tbl.FIRST..l_ue_id_tbl.LAST LOOP
3034        i := i + 1;
3035        -- initialize
3036        l_unit_effectivity_tbl(i).unit_effectivity_id := l_ue_id_tbl(j);
3037        l_unit_effectivity_tbl(i).status_code := l_ue_status_tbl(j);
3038        l_unit_effectivity_tbl(i).related_ue_id := l_related_ue_tbl(j);
3039        l_unit_effectivity_tbl(i).originator_ue_id := l_orig_ue_tbl(j);
3040 
3041        -- Call visit work package to get visit end date if unit effectivity has been assigned to a visit.
3042        AHL_UMP_UTIL_PKG.get_visit_details (l_unit_effectivity_tbl(i).unit_effectivity_id,
3043                                            l_visit_start_date,
3044                                            l_visit_end_date,
3045                                            l_visit_assign_code);
3046 
3047        IF (l_visit_end_date IS NOT NULL AND trunc(l_visit_end_date) >= trunc(sysdate)) THEN
3048            IF G_DEBUG = 'Y' THEN
3049               AHL_DEBUG_PUB.Debug('Visit assigned:End Date:' || l_visit_end_date);
3050            END IF;
3051 
3052            l_unit_effectivity_tbl(i).visit_assign_flag := 'Y';
3053            l_unit_effectivity_tbl(i).visit_end_date := l_visit_end_date;
3054        ELSE
3055            l_unit_effectivity_tbl(i).visit_assign_flag := 'N';
3056            l_unit_effectivity_tbl(i).visit_end_date := null;
3057        END IF;
3058 
3059        -- Assign forecast sequence for single (non-group) MRs.
3060        IF (l_unit_effectivity_tbl(i).originator_ue_id IS NULL) THEN
3061            l_forecast_sequence := l_forecast_sequence + 1;
3062            l_unit_effectivity_tbl(i).forecast_sequence := l_forecast_sequence;
3063        END IF;
3064     END LOOP; -- l_ue_id_tbl
3065 
3066     -- clean up.
3067     l_ue_id_tbl.DELETE;
3068     l_ue_status_tbl.DELETE;
3069     l_related_ue_tbl.DELETE;
3070     l_orig_ue_tbl.DELETE;
3071 
3072   END LOOP;
3073   CLOSE ahl_unit_effectivity_csr;
3074 
3075   -- Added for 11.5.10+ enhancements for Unplanned MRs.
3076   -- Build table of visit end dates for Unplanned MRs.
3077   i := 0;
3078   FOR ahl_unplanned_MRs_rec IN ahl_unplanned_MRs_csr(p_applicable_mrs_rec.csi_item_instance_id,
3079                                                      p_applicable_mrs_rec.mr_header_id)
3080   LOOP
3081     -- Get visit end date; unplanned MRs is always assigned to a visit.
3082     AHL_UMP_UTIL_PKG.get_visit_details (ahl_unplanned_MRs_rec.unit_effectivity_id,
3083                                         l_visit_start_date,
3084                                         l_visit_end_date,
3085                                         l_visit_assign_code);
3086     IF (l_visit_end_date IS NOT NULL) THEN
3087       i := i + 1;
3088       l_unplanned_MRs_tbl(i).unit_effectivity_id := ahl_unplanned_MRs_rec.unit_effectivity_id;
3089       l_unplanned_MRs_tbl(i).visit_end_date := trunc(l_visit_end_date);
3090 
3091     END IF;
3092 
3093   END LOOP; -- unplanned MRs.
3094 
3095   -- Check for group MR.
3096   OPEN group_check_csr(p_applicable_mrs_rec.csi_item_instance_id,
3097                        p_applicable_mrs_rec.mr_header_id);
3098   FETCH group_check_csr INTO l_junk;
3099   IF (group_check_csr%NOTFOUND) THEN
3100       --dbms_output.put_line ('group check false');
3101       group_check_flag := FALSE;
3102   ELSE
3103       group_check_flag := TRUE;
3104   END IF;
3105   CLOSE group_check_csr;
3106 
3107   -- Initialize forecast sequence numbers.
3108   l_forecast_sequence := 0;
3109   l_old_UE_forecast_sequence := 0;
3110   l_old_UE_forecast_found := TRUE;
3111 
3112   -- Calculate Due date.
3113   IF (l_calc_due_date_flag) THEN -- no calculation needed if preceding mr's next due has no due date.
3114 
3115     --dbms_output.put_line ('bef calculate_due_date');
3116     --dbms_output.put_line ('accomplish:date:' || l_last_accomplishment_date);
3117 
3118     -- Calculate next due date.
3119     -- Added parameter p_dependent_mr_flag to fix bug# 6711228.
3120     Calculate_Due_Date (p_repetivity_flag => 'N',
3121                         p_applicable_mrs_rec => p_applicable_mrs_rec,
3122                         p_current_usage_tbl => p_current_usage_tbl,
3123                         p_counter_rules_tbl => p_counter_rules_tbl,
3124                         p_last_due_date => l_last_accomplishment_date,
3125                         p_last_due_counter_val_tbl => l_last_acc_counter_val_tbl,
3126                         p_dependent_mr_flag => l_dependent_mr_flag,
3127                         p_mr_accomplish_exists  => l_mr_accomplish_exists,
3128                         x_next_due_date_rec => l_next_due_date_rec);
3129   END IF;
3130 
3131   IF G_DEBUG = 'Y' THEN
3132     AHL_DEBUG_PUB.Debug('Aft calculate_due_date nextdue');
3133     AHL_DEBUG_PUB.Debug('due date is ' || l_next_due_date_rec.DUE_DATE);
3134     AHL_DEBUG_PUB.Debug('earliest due date is ' || l_next_due_date_rec.EARLIEST_DUE_DATE);
3135     AHL_DEBUG_PUB.Debug('latest due date is ' || l_next_due_date_rec.latest_due_date);
3136   END IF;
3137 
3138   l_next_due_flag := TRUE;
3139   /* next due mr calculation. */
3140 
3141   -- set last_due values to current values.
3142   l_last_due_date := sysdate;
3143   l_last_due_counter_val_tbl := p_current_usage_tbl;
3144 
3145   -- If the MR is a dependent MR: (1) If calculated due date is earlier than preceding MR due date,
3146   --                                  then change due date to be equal to preceding MR due date.
3147   --                              (2) Update the preceding_check_flag, based on due date.
3148   IF (p_applicable_mrs_rec.preceding_mr_header_id IS NOT NULL) THEN
3149     IF (trunc(l_next_due_date_rec.DUE_DATE) < trunc(l_last_accomplishment_date)) THEN
3150        l_next_due_date_rec.DUE_DATE := l_last_accomplishment_date;
3151     END IF;
3152 
3153     Update_check_flag (p_applicable_mrs_rec => p_applicable_mrs_rec,
3154                        p_dependent_mr_flag => l_dependent_mr_flag,
3155                        p_next_due_date_rec => l_next_due_date_rec);
3156   END IF;
3157 
3158   -- process next due and repetivity.
3159   LOOP
3160      -- At this time assume, that there are no MRs with due dates less than the calc due date.
3161      l_grp_duedate_found := FALSE;
3162 
3163      -- Check output from calculate_due_date.
3164      IF (l_next_due_date_rec.due_date IS NOT NULL) THEN
3165 
3166         IF (l_next_due_flag) THEN
3167           -- read ahl_temp_unit_effectivity
3168           IF (l_last_due_date < l_next_due_date_rec.due_date) THEN
3169             OPEN ahl_temp_ue_csr1(p_applicable_mrs_rec.csi_item_instance_id,
3170                                   p_applicable_mrs_rec.mr_header_id,
3171                                   l_last_due_date,
3172                                   l_next_due_date_rec.due_date);
3173           ELSE
3174             OPEN ahl_temp_ue_csr1(p_applicable_mrs_rec.csi_item_instance_id,
3175                                   p_applicable_mrs_rec.mr_header_id,
3176                                   l_next_due_date_rec.due_date,
3177                                   l_last_due_date);
3178           END IF;
3179 
3180           FETCH ahl_temp_ue_csr1 INTO l_temp_grp_mr_rec;
3181           IF (ahl_temp_ue_csr1%FOUND) THEN
3182             --dbms_output.put_line ('exists grp rec' || l_temp_grp_mr_rec.due_date);
3183             /* there exists a group record with due date less than the calculated * one */
3184             l_grp_duedate_found := TRUE;
3185 
3186             -- added to fix bug# 6530920.
3187             -- this is to avoid creation of one child UMP row at the end of the
3188             -- planning window when the child MR and parent MR have the same interval
3189             -- threshold. Next due MR can be individual MR or part of a group MR.
3190             l_next_due_flag := FALSE;
3191 
3192           END IF;
3193           CLOSE ahl_temp_ue_csr1;
3194         ELSE
3195           -- read ahl_temp_unit_effectivity
3196           OPEN ahl_temp_ue_csr(p_applicable_mrs_rec.csi_item_instance_id,
3197                                p_applicable_mrs_rec.mr_header_id,
3198                                l_last_due_date,
3199                                l_next_due_date_rec.due_date);
3200           FETCH ahl_temp_ue_csr INTO l_temp_grp_mr_rec;
3201           IF (ahl_temp_ue_csr%FOUND) THEN
3202                 --dbms_output.put_line ('exists grp rec' || l_temp_grp_mr_rec.due_date);
3203            /* there exists a group record with due date less than the calculated one */
3204             l_grp_duedate_found := TRUE;
3205           END IF;
3206           CLOSE ahl_temp_ue_csr;
3207         END IF;
3208         -- Added for 11.5.10+ Unplanned MRs enhancement.
3209         l_min_visit_date := NULL;
3210         IF (l_unplanned_MRs_tbl.COUNT > 0) THEN
3211           FOR i IN l_unplanned_MRs_tbl.FIRST..l_unplanned_MRs_tbl.LAST LOOP
3212             IF (l_unplanned_MRs_tbl(i).visit_end_date > l_last_due_date AND
3213                 l_unplanned_MRs_tbl(i).visit_end_date <= l_next_due_date_rec.due_date) THEN
3214                 IF (l_min_visit_date IS NULL) THEN
3215                    l_min_visit_date := l_unplanned_MRs_tbl(i).visit_end_date;
3216                 ELSIF (l_min_visit_date > l_unplanned_MRs_tbl(i).visit_end_date) THEN
3217                    l_min_visit_date := l_unplanned_MRs_tbl(i).visit_end_date;
3218                 END IF;
3219             END IF;
3220           END LOOP; -- l_unplanned_MRs_tbl.
3221         END IF; -- Count.
3222 
3223         -- Compare dates from ahl_temp_ue_csr and l_min_visit_date.
3224         IF (l_grp_duedate_found) THEN
3225            IF (l_min_visit_date IS NOT NULL) THEN
3226               IF (l_temp_grp_mr_rec.visit_end_date IS NOT NULL) THEN
3227                  IF (l_min_visit_date < l_temp_grp_mr_rec.visit_end_date) THEN
3228                     l_temp_grp_mr_rec.visit_end_date := l_min_visit_date;
3229                     l_temp_grp_mr_rec.due_date := NULL;
3230                  END IF;
3231               ELSIF (l_temp_grp_mr_rec.due_date IS NOT NULL) THEN
3232                  IF (l_min_visit_date < l_temp_grp_mr_rec.due_date) THEN
3233                     l_temp_grp_mr_rec.visit_end_date := l_min_visit_date;
3234                     l_temp_grp_mr_rec.due_date := NULL;
3235                  END IF;
3236               ELSE -- both due date and visit end dates are null.
3237                  l_temp_grp_mr_rec.visit_end_date := l_min_visit_date;
3238                  l_temp_grp_mr_rec.due_date := NULL;
3239               END IF;
3240            END IF; -- l_min_visit_date chk.
3241         ELSE
3242           IF (l_min_visit_date IS NOT NULL) THEN
3243             l_temp_grp_mr_rec.visit_end_date := l_min_visit_date;
3244             l_temp_grp_mr_rec.due_date := NULL;
3245             l_grp_duedate_found := TRUE;
3246             /*
3247             -- added to fix bug# 6530920.
3248             -- this is to avoid creation of one child UMP row at the end of the
3249             -- planning window when the child MR and parent MR have the same interval
3250             -- threshold. Next due MR can be individual MR or part of a group MR.
3251             l_next_due_flag := FALSE;
3252             */
3253           END IF;
3254         END IF; -- l_grp_duedate_found.
3255 
3256      END IF; -- l_next_due_date_rec.due_date chk.
3257 
3258      IF (l_next_due_date_rec.due_date IS NULL AND l_next_due_flag = TRUE) OR  /* no repetivity as due_date is null */
3259         (NOT(l_grp_duedate_found) AND l_next_due_flag = TRUE) OR
3260         (NOT(l_grp_duedate_found) AND l_next_due_date_rec.due_date IS NOT NULL AND l_next_due_flag = FALSE
3261           AND trunc(l_next_due_date_rec.due_date) <= trunc(G_last_day_of_window))
3262      THEN
3263 
3264         -- R12:Added following logic to fix bug# 4224867.
3265         l_duplicate_MRs := 1; -- default to create only one occurrence of UMP for a day.
3266 
3267         -- find out if multiple UMPs need to be created for a given day.
3268         IF (l_next_due_date_rec.due_date IS NOT NULL AND l_last_due_date = l_next_due_date_rec.due_date
3269             AND l_next_due_date_rec.counter_remain IS NOT NULL AND l_next_due_date_rec.counter_remain > 0)
3270         THEN
3271            IF G_DEBUG = 'Y' THEN
3272               AHL_DEBUG_PUB.Debug('Check Multiple UMPs for due date:' || l_next_due_date_rec.due_date);
3273               AHL_DEBUG_PUB.Debug('Counter Remain:' || l_next_due_date_rec.counter_remain );
3274            END IF;
3275 
3276            -- get usage for due date.
3277            get_usage_for_date(l_next_due_date_rec.due_date,
3278                               l_next_due_date_rec.ctr_uom_code,
3279                               p_counter_rules_tbl,
3280                               l_usage_per_day);
3281 
3282            l_duplicate_MRs := trunc(l_usage_per_day/l_next_due_date_rec.counter_remain);
3283            IF (l_duplicate_MRs = 0) THEN
3284               l_duplicate_MRs := 1;
3285            END IF;
3286 
3287            IF G_DEBUG = 'Y' THEN
3288               AHL_DEBUG_PUB.Debug('get_usage_for_date:' || l_usage_per_day);
3289               AHL_DEBUG_PUB.Debug('l_duplicate_MRs:' || l_duplicate_MRs);
3290            END IF;
3291 
3292         END IF; -- l_next_due_date_rec.due_date IS NOT NULL
3293 
3294         -- Now loop to create temp unit effectivities l_duplicate_MRs times.
3295         FOR m IN 1..l_duplicate_MRs LOOP
3296         -- R12:End code added to fix bug# 4224867.
3297 
3298            -- construct ahl_unit_effectivity record and write into temporary table.
3299            l_new_unit_effectivity_rec := l_new_unit_effectivity_initrec; -- initialise.
3300 
3301            -- find the corressponding match in l_unit_effectivity_tbl if exists.
3302            IF (l_old_UE_forecast_found = TRUE) AND (l_unit_effectivity_tbl.EXISTS(l_old_UE_forecast_sequence+1))
3303            THEN
3304 
3305              -- loop to find the next individual MR.
3306              LOOP
3307                 l_old_UE_forecast_sequence := l_old_UE_forecast_sequence + 1;
3308                 IF (l_unit_effectivity_tbl(l_old_UE_forecast_sequence).forecast_sequence is not null) THEN
3309                     l_new_unit_effectivity_rec.unit_effectivity_id :=
3310                         l_unit_effectivity_tbl(l_old_UE_forecast_sequence).unit_effectivity_id;
3311                         EXIT; -- matched record found.
3312                 ELSIF NOT(l_unit_effectivity_tbl.EXISTS(l_old_UE_forecast_sequence+1)) THEN
3313                         l_new_unit_effectivity_rec.unit_effectivity_id := null;
3314                         l_old_UE_forecast_sequence := -1;
3315                         l_old_UE_forecast_found := FALSE;
3316                         EXIT;
3317                 END IF;
3318              END LOOP;
3319 
3320            ELSE
3321              l_new_unit_effectivity_rec.unit_effectivity_id := null;
3322              l_old_UE_forecast_sequence := -1;
3323              l_old_UE_forecast_found := FALSE;
3324            END IF;
3325 
3326 
3327            -- Check for tolerance if visit has been assigned.
3328            IF (l_old_UE_forecast_found = TRUE) AND (l_next_due_date_rec.due_date IS NOT NULL) THEN
3329               IF (l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_assign_flag = 'Y') THEN
3330                  IF l_next_due_date_rec.tolerance_before IS NOT NULL THEN
3331                        -- calculate due date based on forecast.
3332                        -- get date from forecast.
3333                        /*--get_date_from_uf(l_next_due_date_rec.due_at_counter_value - l_next_due_date_rec.tolerance_before,
3334                                         l_next_due_date_rec.ctr_uom_code,
3335                                         p_counter_rules_tbl,
3336                                         l_last_due_date,
3337                                         l_bef_tolr_due_date); */
3338                        IF ((trunc(l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_end_date))
3339                             < trunc(l_next_due_date_rec.earliest_due_date)) THEN
3340                             -- tolerance before.
3341                             l_next_due_date_rec.tolerance_flag := 'Y';
3342                             l_next_due_date_rec.message_code := 'TOLERANCE-BEFORE';
3343 
3344                        END IF;
3345                  END IF;
3346 
3347                  IF l_next_due_date_rec.tolerance_after IS NOT NULL THEN
3348                        -- calculate due date based on forecast.
3349                        -- get date from forecast.
3350                        /*get_date_from_uf(l_next_due_date_rec.tolerance_after,
3351                                         l_next_due_date_rec.ctr_uom_code,
3352                                         p_counter_rules_tbl,
3353                                         l_next_due_date_rec.due_date,
3354                                         l_aft_tolr_due_date); */
3355                        IF ((trunc(l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_end_date))
3356                                > trunc(l_next_due_date_rec.latest_due_date)) THEN
3357                             -- tolerance after.
3358                             l_next_due_date_rec.tolerance_flag := 'Y';
3359                             l_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
3360 
3361                        END IF;
3362                  END IF;
3363               END IF;
3364            END IF;
3365 
3366 
3367            l_new_unit_effectivity_rec.due_date := l_next_due_date_rec.due_date;
3368            l_new_unit_effectivity_rec.mr_interval_id := l_next_due_date_rec.mr_interval_id;
3369            l_new_unit_effectivity_rec.mr_effectivity_id := l_next_due_date_rec.mr_effectivity_id;
3370            l_new_unit_effectivity_rec.due_counter_value := l_next_due_date_rec.due_at_counter_value;
3371            l_new_unit_effectivity_rec.tolerance_flag := l_next_due_date_rec.tolerance_flag;
3372            l_new_unit_effectivity_rec.tolerance_before := l_next_due_date_rec.tolerance_before;
3373            l_new_unit_effectivity_rec.tolerance_after := l_next_due_date_rec.tolerance_after;
3374            l_new_unit_effectivity_rec.message_code := l_next_due_date_rec.message_code;
3375            l_new_unit_effectivity_rec.csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
3376            l_new_unit_effectivity_rec.mr_header_id := p_applicable_mrs_rec.mr_header_id;
3377            l_new_unit_effectivity_rec.preceding_check_flag:= 'N';
3378            -- Added for ER# 2636001.
3379            l_new_unit_effectivity_rec.earliest_due_date := l_next_due_date_rec.earliest_due_date;
3380            l_new_unit_effectivity_rec.latest_due_date := l_next_due_date_rec.latest_due_date;
3381            -- Added to fix bug#2780716.
3382            l_new_unit_effectivity_rec.counter_id := l_next_due_date_rec.counter_id;
3383 
3384 
3385            -- increment forecast sequence.
3386            l_forecast_sequence := l_forecast_sequence + 1;
3387            l_new_unit_effectivity_rec.forecast_sequence := l_forecast_sequence;
3388 
3389            IF G_DEBUG = 'Y' THEN
3390               AHL_DEBUG_PUB.Debug('New Unit eff:' || l_new_unit_effectivity_rec.unit_effectivity_id);
3391               AHL_DEBUG_PUB.Debug('Old forecast seq:'|| l_old_UE_forecast_sequence);
3392            END IF;
3393 
3394            -- set repetivity based on next_due_flag.
3395            IF (l_next_due_flag) THEN
3396               l_new_unit_effectivity_rec.repetitive_mr_flag := 'N';
3397            ELSE
3398               l_new_unit_effectivity_rec.repetitive_mr_flag := 'Y';
3399            END IF;
3400 
3401 
3402            -- Update preceding MR details.
3403            IF (l_dependent_mr_flag AND l_forecast_sequence = 1) THEN
3404               l_new_unit_effectivity_rec.preceding_mr_header_id := p_applicable_mrs_rec.preceding_mr_header_id;
3405               l_new_unit_effectivity_rec.preceding_csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
3406               l_new_unit_effectivity_rec.preceding_forecast_seq := l_forecast_sequence;
3407               l_dependent_mr_flag := FALSE; -- this is required only for next due.
3408            END IF;
3409 
3410            -- write into temporary table.
3411            IF NOT(group_check_flag) THEN
3412 
3413              -- create record in temporary table.
3414              Create_Temp_Unit_Effectivity (l_new_unit_effectivity_rec);
3415 
3416              IF G_DEBUG = 'Y' THEN
3417                 AHL_DEBUG_PUB.Debug('After create_temp_unit_effectivity');
3418              END IF;
3419 
3420            ELSE
3421               -- Process group MR.
3422               Process_groupMR (p_applicable_mrs_rec,
3423                                l_new_unit_effectivity_rec,
3424                                l_unit_effectivity_tbl,
3425                                l_old_UE_forecast_sequence);
3426            END IF;
3427 
3428            -- Set next due flag to FALSE after writing record into temporary unit_effectivity.
3429            IF (l_next_due_flag) THEN
3430                 l_next_due_flag := FALSE;
3431            END IF;
3432 
3433            -- Fix for bug# 6858788
3434            l_last_due_mr_interval_id := l_next_due_date_rec.mr_interval_id;
3435 
3436        END LOOP; -- m (Duplicate_MRs)
3437      END IF; -- l_next_due_date_rec.due_date IS NULL
3438 
3439      /* exit if one next due mr has been calculated and its due date is null
3440         or if next due date is beyond the rolling window date */
3441      EXIT WHEN ((l_next_due_flag = FALSE AND l_next_due_date_rec.due_date IS NULL) OR
3442                 (l_next_due_flag = FALSE AND p_applicable_mrs_rec.show_repetitive_code = 'NEXT') OR
3443                 (l_next_due_date_rec.due_date IS NOT NULL 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
3444                 (l_next_due_flag = FALSE AND trunc(l_next_due_date_rec.due_date) > trunc(G_last_day_of_window))
3445                );
3446 
3447      -- Set from l_next_due_date_rec.
3448      l_due_date := l_next_due_date_rec.due_date;
3449 
3450      -- If grp MR exists with due date less than calculated date, then re-calculate due date.
3451      IF (l_grp_duedate_found) THEN
3452 
3453        -- Set due date to be either visit_end_date or due_date.
3454        IF (l_temp_grp_mr_rec.visit_end_date IS NOT NULL) THEN
3455           l_due_date := l_temp_grp_mr_rec.visit_end_date;
3456        ELSE
3457           l_due_date := l_temp_grp_mr_rec.due_date;
3458        END IF;
3459 
3460        -- Fix for bug# 6858788. Reset l_last_due_mr_interval_id if duedate based on group MR.
3461        l_last_due_mr_interval_id := NULL;
3462 
3463      ELSE
3464 
3465        -- Set values for next repetivity calculation.
3466        IF (l_unit_effectivity_tbl.EXISTS(l_old_UE_forecast_sequence)) THEN
3467          IF (l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_assign_flag = 'Y') THEN
3468               l_due_date := l_unit_effectivity_tbl(l_old_UE_forecast_sequence).visit_end_date;
3469          END IF;
3470        END IF;
3471      END IF;
3472 
3473      -- If due date is a past date, then set it to sysdate.
3474      -- This will happen only when calculating next-due date.
3475      IF (trunc(l_due_date) < trunc(sysdate)) THEN
3476        l_due_date := sysdate;
3477      END IF;
3478 
3479      IF G_DEBUG = 'Y' THEN
3480         AHL_DEBUG_PUB.Debug('Processing for repetivity');
3481         AHL_DEBUG_PUB.Debug('Before get_due_at_counter_values');
3482         AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
3483         AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
3484         IF (l_last_due_counter_val_tbl.COUNT > 0) THEN
3485           FOR i in l_last_due_counter_val_tbl.FIRST..l_last_due_counter_val_tbl.LAST LOOP
3486             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);
3487           END LOOP;
3488         END IF;
3489      END IF;
3490 
3491      -- get all counter values as on l_due_date.
3492      Get_Due_at_Counter_Values (p_last_due_date => l_last_due_date,
3493                                 p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
3494                                 p_due_date => l_due_date,
3495                                 p_counter_rules_tbl => p_counter_rules_tbl,
3496                                 x_due_at_counter_val_tbl => l_due_at_counter_val_tbl,
3497                                 x_return_value => l_return_value);
3498      l_last_due_date := l_due_date;
3499      l_last_due_counter_val_tbl := l_due_at_counter_val_tbl;
3500 
3501      IF G_DEBUG = 'Y' THEN
3502         AHL_DEBUG_PUB.Debug('AFter get_due_at_counter_values');
3503         AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
3504         AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
3505         IF (l_due_at_counter_val_tbl.COUNT) > 0 THEN
3506            for i in l_due_at_counter_val_tbl.FIRST..l_due_at_counter_val_tbl.LAST LOOP
3507              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);
3508            end loop;
3509         END IF;
3510      END IF;
3511 
3512      IF NOT(l_return_value) THEN
3513         EXIT; /* no forecast available so exit */
3514      END IF;
3515 
3516      -- Calculate next due date.
3517      Calculate_Due_Date (p_repetivity_flag => 'Y',
3518                          p_applicable_mrs_rec => p_applicable_mrs_rec,
3519                          p_current_usage_tbl => p_current_usage_tbl,
3520                          p_counter_rules_tbl => p_counter_rules_tbl,
3521                          p_last_due_date => l_last_due_date,
3522                          p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
3523                          p_mr_accomplish_exists  => l_mr_accomplish_exists,
3524                          p_last_due_mr_interval_id => l_last_due_mr_interval_id,
3525                          x_next_due_date_rec => l_next_due_date_rec);
3526 
3527      IF G_DEBUG = 'Y' THEN
3528         AHL_DEBUG_PUB.Debug('aft calculate_due_date - repetivity');
3529         AHL_DEBUG_PUB.Debug('due date is ' || l_next_due_date_rec.DUE_DATE);
3530         AHL_DEBUG_PUB.Debug('earliest due date is ' || l_next_due_date_rec.EARLIEST_DUE_DATE);
3531         AHL_DEBUG_PUB.Debug('latest due date is ' || l_next_due_date_rec.latest_due_date);
3532      END IF;
3533 
3534      -- Check if calculated date is same as last due date. If they are the same then, add one day.
3535      IF (l_next_due_date_rec.due_date IS NOT NULL) THEN
3536         IF (trunc(l_last_due_date) = trunc(l_next_due_date_rec.due_date)) THEN
3537                l_next_due_date_rec.due_date := l_next_due_date_rec.due_date + 1;
3538                l_next_due_date_rec.EARLIEST_DUE_DATE := NULL;
3539                l_next_due_date_rec.latest_due_date := NULL;
3540 
3541                IF G_DEBUG = 'Y' THEN
3542                  AHL_DEBUG_PUB.Debug('Adding one day to l_next_due_date_rec.due_date:' || l_next_due_date_rec.due_date);
3543                END IF;
3544 
3545             --IF G_DEBUG = 'Y' THEN
3546             --   AHL_DEBUG_PUB.Debug('Exiting build effectivity as last due = due date');
3547             --END IF;
3548             --EXIT;
3549         END IF;
3550      END IF;
3551 
3552   END LOOP;
3553 
3554   -- Fix for bug# 6711228.
3555   <<process_preceding_mr>>
3556   -- Process preceding MRs.
3557   IF ((p_applicable_mrs_rec.implement_status_code = 'MANDATORY') OR
3558      (l_mr_accomplish_exists)) THEN
3559       Process_PrecedingMR (p_applicable_mrs_rec => p_applicable_mrs_rec,
3560                            p_counter_rules_tbl  => p_counter_rules_tbl,
3561                            p_current_usage_tbl  => p_current_usage_tbl);
3562 
3563   END IF;
3564 
3565 END Build_Effectivity;
3566 
3567 --------------------------------------------------------------------------------------
3568 -- Calculate due date for the item instance and mr using current usage, counter rules,
3569 -- last accomplishment counters and forecast (defined in global variable).
3570 -- Added parameter p_dependent_mr_flag to fix bug# 6711228 used when
3571 -- calculating nextdue date.
3572 -- Added parameters p_mr_accomplish_exists and p_last_due_mr_interval_id to fix bug# 6858788.
3573 PROCEDURE Calculate_Due_Date ( p_repetivity_flag    IN VARCHAR2 := 'Y',
3574                                p_applicable_mrs_rec IN applicable_mrs_rec_type,
3575                                p_current_usage_tbl  IN counter_values_tbl_type,
3576                                p_counter_rules_tbl  IN counter_rules_tbl_type,
3577                                p_last_due_date      IN DATE,
3578                                p_last_due_counter_val_tbl IN counter_values_tbl_type,
3579                                p_dependent_mr_flag  IN BOOLEAN := FALSE,
3580                                p_mr_accomplish_exists IN BOOLEAN,
3581                                p_last_due_mr_interval_id IN NUMBER := NULL,
3582                                x_next_due_date_rec  OUT NOCOPY next_due_date_rec_type)
3583 
3584 IS
3585 
3586   -- Read all effectivities for the mr and item instance.
3587   CURSOR ahl_applicable_csr (p_instance_id IN NUMBER,
3588                              p_mr_header_id IN NUMBER) IS
3589      SELECT DISTINCT mr.mr_effectivity_id, threshold_date
3590      FROM ahl_applicable_mrs mr, ahl_mr_effectivities eff
3591      WHERE mr.mr_effectivity_id = eff.mr_effectivity_id AND
3592            csi_item_instance_id = p_instance_id AND
3593            mr.mr_header_id = p_mr_header_id;
3594 
3595   -- read all intervals for the effectivity id.
3596   CURSOR ahl_mr_interval_csr (p_mr_effectivity_id IN NUMBER,
3597                               --p_counter_id  IN NUMBER,
3598                               p_counter_name  IN VARCHAR2,
3599                               p_counter_value IN NUMBER,
3600                               p_start_date IN DATE) IS
3601      SELECT INT.mr_interval_id, INT.start_date, INT.stop_date,
3602             INT.start_value, INT.stop_value, INT.counter_id,
3603             INT.interval_value, INT.tolerance_after, INT.tolerance_before,
3604             INT.earliest_due_value -- added for bug# 6358940.
3605      --Replaced cs_counters_v with cs_counters to fix perf bug# 3786647.
3606      --FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
3607      --replaced cs_counters CTR with csi_counter_template_vl
3608      --and cs_counters CN with csi_counters_vl CN to fix bug# 5918525.
3609      FROM   ahl_mr_intervals INT, csi_counter_template_vl CTR --, csi_counters_vl CN
3610      WHERE  INT.counter_id = CTR.counter_id AND
3611             --CTR.name = CN.name AND -- bug# 5918525.
3612             --CTR.name = CN.counter_template_name AND -- removed for perf fix.
3613             CTR.name = p_counter_name AND
3614             INT.mr_effectivity_id = p_mr_effectivity_id AND
3615             --CN.counter_id = p_counter_id AND -- removed for perf fix.
3616             (
3617               ( (nvl(start_value, p_counter_value+1) <= p_counter_value AND
3618                  --p_counter_value < nvl(stop_value, p_counter_value+1)) OR
3619                  -- Fix for bug# 3482307.
3620                  p_counter_value <= nvl(stop_value, p_counter_value+1)) OR
3621                 (trunc(nvl(start_date, p_start_date+1)) <= trunc(p_start_date) AND
3622                  --trunc(p_start_date) < trunc(nvl(stop_date, p_start_date+1)) )
3623                  -- Fix for bug# 3482307.
3624                  trunc(p_start_date) <= trunc(nvl(stop_date, p_start_date+1)) )
3625               )
3626              OR
3627                /* pick records with no start/stop values/dates. */
3628               (start_value IS NULL AND stop_value IS NULL AND start_date IS NULL AND stop_date IS NULL
3629                AND interval_value IS NOT NULL)
3630             );
3631 
3632   -- get the unit effectivity record for init-due for this mr and item.
3633   CURSOR ahl_init_due_csr (p_csi_item_instance_id IN NUMBER,
3634                            p_mr_header_id IN NUMBER)  IS
3635     SELECT ud.set_due_date, ue.unit_effectivity_id, ud.unit_deferral_id
3636     FROM ahl_unit_effectivities_app_v ue, ahl_unit_deferrals_vl ud
3637     WHERE ue.unit_effectivity_id = ud.unit_effectivity_id AND
3638           ud.unit_deferral_type = 'INIT-DUE' AND
3639           ue.csi_item_instance_id = p_csi_item_instance_id AND
3640           ue.mr_header_id = p_mr_header_id AND
3641           ue.status_code = 'INIT-DUE';
3642 
3643   -- get all init-due counter records setup for this unit effectivity.
3644   CURSOR ahl_unit_thresholds_csr (p_unit_deferral_id IN NUMBER) IS
3645     SELECT counter_id, counter_value
3646     FROM ahl_unit_thresholds
3647     WHERE unit_deferral_id = p_unit_deferral_id;
3648 
3649   -- added for performance fix bug# 6893404.
3650   CURSOR get_interval_ctr_name(p_mr_effectivity_id IN NUMBER) IS
3651     SELECT DISTINCT name counter_name
3652     FROM ahl_mr_intervals int, csi_counter_template_vl ctr
3653     WHERE int.mr_effectivity_id = p_mr_effectivity_id
3654       AND int.counter_id = ctr.counter_id;
3655 
3656   --
3657   DUE_DATE_NULL EXCEPTION ;
3658   NO_VALID_INTERVAL EXCEPTION;
3659 
3660   l_next_due_date_rec  Next_Due_Date_Rec_Type;
3661 
3662   l_due_date DATE; /* due date returned back after forecast calculation */
3663   l_calc_due_date  DATE; /* next due date that will be returned by this procedure */
3664   l_adjusted_due_date DATE; /* adjusted due date returned in case of overflow into next interval */
3665   l_adjusted_int_value NUMBER; /* adjusted interval value returned in case of overflow into next interval */
3666   l_nxt_interval_found BOOLEAN;
3667 
3668   l_mr_interval_id  NUMBER; /* the interval id that triggered this mr due date */
3669   l_due_at_counter_value NUMBER; /* next due counter value */
3670   l_counter_remain NUMBER;
3671   l_mr_interval_found BOOLEAN; /*indicates if at one mr_interval exists for the effectivity */
3672 
3673   -- modified to fix bug# 6725769.
3674   --l_old_mr_interval_found  BOOLEAN;
3675   l_old_ctr_interval_found  BOOLEAN;
3676   -- added to fix bug# 6725769.
3677   l_ctr_interval_found      BOOLEAN; -- indicates if a mr interval was found for a counter.
3678 
3679   l_temp_counter_tbl  counter_values_tbl_type;
3680   l_counter_value  NUMBER;
3681   l_current_ctr_value NUMBER;
3682   l_set_due_date  DATE;
3683   l_threshold_date  DATE;
3684   l_start_date DATE;
3685   l_start_int_match_at_ctr  NUMBER; /* interval match start counter value. */
3686 
3687   l_mr_interval_rec ahl_mr_interval_csr%ROWTYPE;
3688 
3689   l_unit_effectivity_id NUMBER;
3690   k   NUMBER; /* for l_temp_counter_tbl */
3691 
3692   l_return_val   BOOLEAN; -- return status indicator.
3693   l_counter_read_date   DATE;
3694   l_unit_deferral_id    NUMBER;
3695 
3696   l_reset_start_value_flag  BOOLEAN;
3697   l_due_counter_tbl         counter_values_tbl_type;
3698   l_last_due_counter_tbl    counter_values_tbl_type;
3699 
3700   l_adjusted_due_ctr        NUMBER;
3701 
3702   -- added to fix calculation of before and after tolerance dates when
3703   -- uom_remain < 0.
3704   l_calc_due_date_ctr_id    NUMBER;
3705 
3706   -- added to fix bug# 6358940.
3707   l_reset_start_date_flag   BOOLEAN;
3708 
3709   -- added to fix perf bug# 6893404.
3710   i  NUMBER; -- setting l_temp_counter_tbl index.
3711 
3712 BEGIN
3713 
3714   IF G_DEBUG = 'Y' THEN
3715         AHL_DEBUG_PUB.Debug('In calculate due date');
3716   END IF;
3717 
3718   -- Initialize due date.
3719   l_calc_due_date := null;
3720   l_calc_due_date_ctr_id := null;
3721 
3722   -- Initialize OUT record.
3723   x_next_due_date_rec := l_next_due_date_rec;
3724 
3725   IF (p_repetivity_flag = 'N') THEN
3726     l_temp_counter_tbl := p_current_usage_tbl;
3727   ELSE
3728     l_temp_counter_tbl := p_last_due_counter_val_tbl;
3729   END IF;
3730 
3731   -- Fix for bug# 6358940. Due Date should be based only on init-due if it
3732   -- exists. MR thresholds should not be used.
3733   -- Calculate due date based on init-due defination; if exists.
3734   IF (p_repetivity_flag = 'N') THEN
3735      --dbms_output.put_line ('in INIT-due part');
3736 
3737      -- Check if there is any init-due record for this item instance and mr exists.
3738      OPEN ahl_init_due_csr(p_applicable_mrs_rec.csi_item_instance_id,
3739                            p_applicable_mrs_rec.mr_header_id);
3740      FETCH ahl_init_due_csr INTO l_set_due_date, l_unit_effectivity_id, l_unit_deferral_id;
3741      IF (ahl_init_due_csr%FOUND) THEN
3742 
3743         IF G_DEBUG = 'Y' THEN
3744           AHL_DEBUG_PUB.Debug('INIT-Due processing: Set due_date:' || l_set_due_date);
3745         END IF;
3746         --dbms_output.put_line ('in INIT-due part: due_date' || l_set_due_date);
3747 
3748         FOR threshold_rec IN ahl_unit_thresholds_csr (l_unit_deferral_id)
3749         LOOP
3750           -- for init due, ctr_value_type_code is always 'defer_to'.
3751           l_due_at_counter_value := threshold_rec.counter_value;
3752           l_counter_remain := 0;
3753           l_current_ctr_value := 0;
3754           k := 0;
3755           -- search for the current counter value in l_current_usage_tbl.
3756           IF (l_temp_counter_tbl.COUNT > 0) THEN
3757             FOR i IN l_temp_counter_tbl.FIRST..l_temp_counter_tbl.LAST LOOP
3758                IF (l_temp_counter_tbl(i).counter_id = threshold_rec.counter_id) THEN
3759                   l_current_ctr_value := l_temp_counter_tbl(i).counter_value;
3760                   k := i;
3761                   EXIT;
3762                END IF;
3763             END LOOP;
3764             l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
3765           END IF;
3766 
3767           -- calculate due date from forecast.
3768           IF (l_counter_remain > 0) THEN
3769             -- get date from forecast.
3770             get_date_from_uf(l_counter_remain,
3771                              l_temp_counter_tbl(k).uom_code,
3772                              p_counter_rules_tbl,
3773                              null, -- start date = sysdate
3774                              l_due_date);
3775           ELSIF (l_counter_remain < 0) THEN
3776             -- Due date = counter reading date.
3777              get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
3778                                        p_counter_id           => l_temp_counter_tbl(k).counter_id,
3779                                        p_counter_value        => l_due_at_counter_value,
3780                                        x_ctr_record_date      => l_counter_read_date,
3781                                        x_return_val           => l_return_val);
3782 
3783              IF NOT(l_return_val) THEN
3784                 l_due_date := sysdate;
3785              ELSE
3786                 l_due_date := l_counter_read_date;
3787              END IF;
3788 
3789           ELSIF (l_counter_remain = 0) THEN  -- due_date = sysdate
3790             --dbms_output.put_line ('counter remain less than zero');
3791             l_due_date := sysdate;
3792           END IF;
3793 
3794           -- Compare with whichever first code and set l_calc_due_date.
3795           IF (l_due_date IS NULL) THEN
3796              -- Added to fix bug# 6907562.
3797              IF (validate_for_duedate_reset(l_due_date,
3798                                             l_counter_remain,
3799                                             l_calc_due_date,
3800                                             l_calc_due_date_ctr_id,
3801                                             x_next_due_date_rec.counter_remain)) = 'Y' THEN
3802 
3803                --dbms_output.put_line ('due date null');
3804                l_calc_due_date := l_due_date;
3805                x_next_due_date_rec.due_date := null;
3806                x_next_due_date_rec.tolerance_after := null;
3807                x_next_due_date_rec.tolerance_before := null;
3808                x_next_due_date_rec.mr_interval_id := null;
3809                x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
3810                x_next_due_date_rec.mr_effectivity_id := null;
3811                x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
3812                x_next_due_date_rec.last_ctr_value := null;
3813                x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
3814                x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
3815                x_next_due_date_rec.counter_remain := l_counter_remain;
3816                l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
3817                -- fix for bug# 6907562. Loop to next threshold when due date is null.
3818                --EXIT;
3819              END IF;
3820           ELSE
3821             IF (l_calc_due_date IS NULL) THEN
3822                -- Added to fix bug# 6907562.
3823                IF (validate_for_duedate_reset(l_due_date,
3824                                               l_counter_remain,
3825                                               l_calc_due_date,
3826                                               l_calc_due_date_ctr_id,
3827                                               x_next_due_date_rec.counter_remain)) = 'Y' THEN
3828                  --dbms_output.put_line ('calc due date null');
3829                  l_calc_due_date := l_due_date;
3830                  x_next_due_date_rec.due_date := l_due_date;
3831                  x_next_due_date_rec.tolerance_after := null;
3832                  x_next_due_date_rec.tolerance_before := null;
3833                  x_next_due_date_rec.mr_interval_id := null;
3834                  x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
3835                  x_next_due_date_rec.mr_effectivity_id := null;
3836                  x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
3837                  x_next_due_date_rec.last_ctr_value := null;
3838                  x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
3839                  x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
3840                  x_next_due_date_rec.counter_remain := l_counter_remain;
3841                  l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
3842                END IF;
3843             ELSE
3844                IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
3845                  -- Check due date based on whichever_first_code.
3846                  -- if dates are equal, switch based on lower uom remain value. (bug# 6907562).
3847                  IF (l_calc_due_date > l_due_date) OR
3848                     (trunc(l_calc_due_date) = trunc(l_due_date) AND l_counter_remain IS NOT NULL
3849                         AND x_next_due_date_rec.counter_remain IS NOT NULL
3850                         AND l_counter_remain < x_next_due_date_rec.counter_remain) THEN
3851                       l_calc_due_date := l_due_date;
3852                       x_next_due_date_rec.due_date := l_due_date;
3853                       x_next_due_date_rec.tolerance_after := null;
3854                       x_next_due_date_rec.tolerance_before := null;
3855                       x_next_due_date_rec.mr_interval_id := null;
3856                       x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
3857                       x_next_due_date_rec.mr_effectivity_id := null;
3858                       x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
3859                       x_next_due_date_rec.last_ctr_value := null;
3860                       x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
3861                       x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
3862                       x_next_due_date_rec.counter_remain := l_counter_remain;
3863                       l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
3864 
3865                     END IF;
3866                  ELSE  -- whichever_first_code = 'LAST'
3867                     -- if dates are equal, switch based on higher uom remain value. (bug# 6907562).
3868                     IF (l_calc_due_date < l_due_date) OR
3869                        (trunc(l_calc_due_date) = trunc(l_due_date) AND l_counter_remain IS NOT NULL
3870                         AND x_next_due_date_rec.counter_remain IS NOT NULL
3871                         AND l_counter_remain > x_next_due_date_rec.counter_remain) THEN
3872                         --dbms_output.put_line ('set due date');
3873                         l_calc_due_date := l_due_date;
3874                         x_next_due_date_rec.due_date := l_due_date;
3875                         x_next_due_date_rec.tolerance_after := null;
3876                         x_next_due_date_rec.tolerance_before := null;
3877                         x_next_due_date_rec.mr_interval_id := null;
3878                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
3879                         x_next_due_date_rec.mr_effectivity_id := null;
3880                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
3881                         x_next_due_date_rec.last_ctr_value := null;
3882                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
3883                         x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
3884                         x_next_due_date_rec.counter_remain := l_counter_remain;
3885                         l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
3886 
3887                     END IF;
3888                  END IF; -- applicable_mrs_rec
3889             END IF; -- calc_due_date null
3890           END IF; -- l_due_date IS NULL
3891         END LOOP; -- set_threshold_rec
3892 
3893         -- Check for set due date.
3894         IF (l_set_due_date IS NOT NULL) THEN
3895               IF (l_calc_due_date IS NULL) THEN
3896                  -- added to fix bug# 6907562.
3897                  -- reset only when l_calc_due_date_ctr_id is also null.
3898                  IF (l_calc_due_date_ctr_id IS NULL) THEN
3899                    l_calc_due_date := l_set_due_date;
3900                    x_next_due_date_rec.due_date := l_set_due_date;
3901                    x_next_due_date_rec.tolerance_after := null;
3902                    x_next_due_date_rec.tolerance_before := null;
3903                    x_next_due_date_rec.mr_effectivity_id := null;
3904                    x_next_due_date_rec.due_at_counter_value := null;
3905                    x_next_due_date_rec.current_ctr_value := null;
3906                    x_next_due_date_rec.last_ctr_value := null;
3907                    x_next_due_date_rec.mr_interval_id := null;
3908                    x_next_due_date_rec.ctr_uom_code := null;
3909                    x_next_due_date_rec.counter_id := null;
3910                    x_next_due_date_rec.counter_remain := null;
3911                    l_calc_due_date_ctr_id := null;
3912                  END IF;
3913               ELSE
3914                  IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
3915                      IF (l_calc_due_date > l_set_due_date) THEN
3916                        --dbms_output.put_line ('set due da te');
3917                        l_calc_due_date := l_set_due_date;
3918                        x_next_due_date_rec.due_date := l_set_due_date;
3919                        x_next_due_date_rec.tolerance_after := null;
3920                        x_next_due_date_rec.tolerance_before := null;
3921                        x_next_due_date_rec.mr_interval_id := null;
3922                        x_next_due_date_rec.due_at_counter_value := null;
3923                        x_next_due_date_rec.mr_effectivity_id := null;
3924                        x_next_due_date_rec.current_ctr_value := null;
3925                        x_next_due_date_rec.last_ctr_value := null;
3926                        x_next_due_date_rec.ctr_uom_code := null;
3927                        x_next_due_date_rec.counter_id := null;
3928                        x_next_due_date_rec.counter_remain := null;
3929                        l_calc_due_date_ctr_id := null;
3930 
3931                      END IF;
3932                  ELSE
3933                     -- Check for set due date.
3934                     IF (l_calc_due_date < l_set_due_date) THEN
3935                         l_calc_due_date := l_set_due_date;
3936                         x_next_due_date_rec.due_date := l_set_due_date;
3937                         x_next_due_date_rec.tolerance_after := null;
3938                         x_next_due_date_rec.tolerance_before := null;
3939                         x_next_due_date_rec.mr_interval_id := null;
3940                         x_next_due_date_rec.due_at_counter_value := null;
3941                         x_next_due_date_rec.mr_effectivity_id := null;
3942                         x_next_due_date_rec.current_ctr_value := null;
3943                         x_next_due_date_rec.last_ctr_value := null;
3944                         x_next_due_date_rec.ctr_uom_code := null;
3945                         x_next_due_date_rec.counter_id := null;
3946                         x_next_due_date_rec.counter_remain := null;
3947                         l_calc_due_date_ctr_id := null;
3948 
3949                     END IF;
3950                  END IF; -- applicable
3951                END IF;
3952          END IF;  -- set due date
3953         -- If due date is less than sysdate, then flag tolerance.
3954         IF (x_next_due_date_rec.due_date IS NOT NULL) AND
3955            (trunc(x_next_due_date_rec.due_date) < trunc(sysdate)) THEN
3956             x_next_due_date_rec.tolerance_flag := 'Y';
3957             x_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
3958         END IF;
3959         CLOSE ahl_init_due_csr;
3960         RETURN; -- exit calculation.
3961      END IF; -- init_due_csr
3962      CLOSE ahl_init_due_csr;
3963   END IF; -- repetitive_flag
3964 
3965   -- Loop through each effectivity record.
3966   <<mr_effectivity_loop>>
3967   FOR effectivity_rec IN ahl_applicable_csr(p_applicable_mrs_rec.csi_item_instance_id,
3968                                             p_applicable_mrs_rec.mr_header_id)
3969   LOOP
3970 
3971      IF G_DEBUG = 'Y' THEN
3972         AHL_DEBUG_PUB.Debug('eff ID' || effectivity_rec.mr_effectivity_id );
3973      END IF;
3974 
3975      l_threshold_date := effectivity_rec.threshold_date;
3976      l_mr_interval_found := FALSE;
3977      --l_old_mr_interval_found := FALSE;
3978 
3979      -- Loop through all counters in l_temp_counter_tbl.
3980      IF (l_temp_counter_tbl.COUNT > 0) THEN
3981 
3982        -- instead of looping through all counters, loop through interval counters
3983        -- and match counter name in l_temp_counter_tbl and set index i.
3984        --FOR i IN l_temp_counter_tbl.FIRST..l_temp_counter_tbl.LAST LOOP
3985 
3986        FOR ctr_name_rec IN get_interval_ctr_name(effectivity_rec.mr_effectivity_id)  LOOP
3987          -- set l_temp_counter_tbl row for matching counter.
3988          i := -1;
3989 
3990          FOR k IN l_temp_counter_tbl.FIRST..l_temp_counter_tbl.LAST LOOP
3991            IF (l_temp_counter_tbl(k).counter_name = ctr_name_rec.counter_name) THEN
3992                i := k;
3993                EXIT;
3994            END IF;
3995          END LOOP;
3996 
3997          -- if no match for interval counter then
3998          -- proceed to next counter.
3999          IF (i = -1) THEN
4000            GOTO next_counter_loop;
4001          END IF;
4002 
4003          -- Added for fix 6725769.
4004          l_ctr_interval_found := FALSE;
4005          l_old_ctr_interval_found := FALSE;
4006 
4007          -- find the counter value from p_last_due_counter_val_tbl
4008          -- for this counter id.
4009          IF (p_repetivity_flag = 'N') THEN
4010             -- set current ctr value from l_current_usage_tbl.
4011             l_start_date := sysdate; /* interval start/stop dates validation on sysdate */
4012             l_current_ctr_value := l_temp_counter_tbl(i).counter_value;
4013             l_counter_value := 0; /* initialize last due counter value */
4014 
4015             IF (p_last_due_counter_val_tbl.COUNT > 0) THEN
4016                 --dbms_output.put_line ('in last due counter loop-count'||p_last_due_counter_val_tbl.COUNT );
4017               FOR j IN p_last_due_counter_val_tbl.FIRST..p_last_due_counter_val_tbl.LAST
4018               LOOP
4019                 --dbms_output.put_line ('in last due counter loop');
4020                 IF (p_last_due_counter_val_tbl(j).counter_id = l_temp_counter_tbl(i).counter_id) THEN
4021                     -- counter value will be just from last due.
4022                     l_counter_value := p_last_due_counter_val_tbl(j).counter_value;
4023 
4024                     -- start interval matching at last accomplishment data as it is available.
4025                     l_start_int_match_at_ctr := l_counter_value;
4026                 END IF;
4027               END LOOP;
4028             ELSE
4029               -- start interval matching at current counter value as last accomplishment data
4030               -- is not available.
4031               l_start_int_match_at_ctr := l_current_ctr_value;
4032             END IF; /* count > 0 */
4033          ELSE
4034            -- For repetity, set current_ctr_value to zero.
4035            -- Set l_counter_value from l_temp_counter_tbl.
4036            l_counter_value := l_temp_counter_tbl(i).counter_value;
4037            l_current_ctr_value := 0; /* initialize current usage on counter */
4038            l_start_date := p_last_due_date; /* interval start/stop dates validation on last due date */
4039 
4040            -- For repetity, l_start_int_match_at_ctr is last counter value.
4041            l_start_int_match_at_ctr := l_counter_value;
4042 
4043          END IF; /* repetivity */
4044 
4045          --dbms_output.put_line ('CounterID' || l_temp_counter_tbl(i).counter_id);
4046          --dbms_output.put_line ('counter_value' || l_counter_value);
4047 
4048          -- For each effectivity, loop through mr intervals.
4049          FOR mr_interval_rec IN ahl_mr_interval_csr(effectivity_rec.mr_effectivity_id,
4050                                                       --l_temp_counter_tbl(i).counter_id,
4051                                                       l_temp_counter_tbl(i).counter_name,
4052                                                       l_start_int_match_at_ctr,
4053                                                       l_start_date)
4054          LOOP
4055 
4056            -- reset loop variables.
4057            l_old_ctr_interval_found := l_ctr_interval_found;
4058            l_reset_start_value_flag := FALSE;
4059            l_reset_start_date_flag  := FALSE;
4060 
4061            -- added to fix bug#	6725769
4062            IF NOT(l_ctr_interval_found) THEN
4063              l_ctr_interval_found := TRUE; /* found a interval. */
4064            END IF;
4065 
4066            --l_mr_interval_found := TRUE; /* found a interval. */
4067            l_mr_interval_rec := mr_interval_rec;
4068 
4069            IF G_DEBUG = 'Y' THEN
4070              AHL_DEBUG_PUB.Debug('In interval table loop');
4071              AHL_DEBUG_PUB.Debug('mr interval:' || l_mr_interval_rec.mr_interval_id );
4072              AHL_DEBUG_PUB.Debug('start value:' ||l_mr_interval_rec.start_value);
4073              AHL_DEBUG_PUB.Debug('stop value:' ||l_mr_interval_rec.start_value);
4074              AHL_DEBUG_PUB.Debug('start date:' ||l_mr_interval_rec.start_date);
4075              AHL_DEBUG_PUB.Debug('stop date:' ||l_mr_interval_rec.start_date);
4076              AHL_DEBUG_PUB.Debug('Interval Value:' ||l_mr_interval_rec.tolerance_before);
4077              AHL_DEBUG_PUB.Debug('tolerance bef:' ||l_mr_interval_rec.tolerance_before);
4078              AHL_DEBUG_PUB.Debug('tolerance aft:' ||l_mr_interval_rec.tolerance_after);
4079              AHL_DEBUG_PUB.Debug('earliest_due_value:' ||l_mr_interval_rec.earliest_due_value);
4080              AHL_DEBUG_PUB.Debug('CounterID:' || l_temp_counter_tbl(i).counter_id);
4081              AHL_DEBUG_PUB.Debug('CounterName:' || l_temp_counter_tbl(i).counter_name);
4082              AHL_DEBUG_PUB.Debug('counter_value:' || l_counter_value);
4083              AHL_DEBUG_PUB.Debug('current ctr:' ||l_current_ctr_value);
4084            END IF;
4085 
4086            l_counter_remain := 0; /* initialize */
4087 
4088            l_due_at_counter_value := l_mr_interval_rec.interval_value + l_counter_value;
4089 
4090            -- Added for bug# 6358940(start_value).
4091            -- if at least one MR is accomplished and earliest_due_value is defined.
4092            IF (p_last_due_date IS NOT NULL AND p_repetivity_flag = 'N' AND
4093                mr_interval_rec.start_value IS NOT NULL AND
4094                p_dependent_mr_flag = FALSE) THEN
4095              IF (l_mr_interval_rec.earliest_due_value IS NOT NULL) THEN
4096                 IF (l_counter_value < l_mr_interval_rec.earliest_due_value) THEN
4097                   l_due_at_counter_value := l_mr_interval_rec.start_value;
4098                   l_reset_start_value_flag := TRUE;
4099                 END IF;
4100              END IF;
4101            -- fix for bug#6711228(issue described in problem#2).
4102            -- l_counter_value for this case contains the counter value as of
4103            -- preceding MR's due date so we need to handle this seperately.
4104            ELSIF (p_repetivity_flag = 'N' AND p_dependent_mr_flag = TRUE AND
4105                   mr_interval_rec.start_value IS NOT NULL) THEN
4106                   l_due_at_counter_value := l_mr_interval_rec.start_value;
4107                   l_reset_start_value_flag := TRUE;
4108            ELSE
4109              -- Check if due counter less than start value or start date. If yes, set it
4110              -- to start value.
4111              IF (l_mr_interval_rec.start_value IS NOT NULL) THEN
4112                IF (l_counter_value < l_mr_interval_rec.start_value) THEN
4113                  l_due_at_counter_value := l_mr_interval_rec.start_value;
4114                  l_reset_start_value_flag := TRUE;
4115                END IF;
4116              END IF;
4117            END IF;
4118 
4119            -- Added for bug# 6358940(start_date).
4120            IF (p_repetivity_flag = 'N') AND (mr_interval_rec.start_date IS NOT NULL) THEN
4121              IF (p_last_due_date IS NOT NULL AND p_dependent_mr_flag = FALSE) THEN
4122                 -- MR accomplished
4123                 IF (mr_interval_rec.earliest_due_value IS NOT NULL) THEN
4124                   IF (l_counter_value < mr_interval_rec.earliest_due_value) THEN
4125                     l_due_date := mr_interval_rec.start_date;
4126                     l_reset_start_date_flag := TRUE;
4127                   END IF;
4128                 END IF;
4129              ELSE  -- no accomplishment. first time MR must be done on start date.
4130                 l_due_date := mr_interval_rec.start_date;
4131                 l_reset_start_date_flag := TRUE;
4132              END IF;
4133 
4134              -- calculate due counter value.
4135              IF (l_reset_start_date_flag) THEN
4136                IF (l_due_date < trunc(sysdate)) THEN
4137                  get_ctr_reading_for_date (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
4138                                            p_counter_id           => l_temp_counter_tbl(i).counter_id,
4139                                            p_reading_date         => l_due_date,
4140                                            x_net_reading          => l_due_at_counter_value);
4141 
4142                ELSIF (l_due_date = trunc(sysdate)) THEN
4143                   -- current counter value.
4144                   l_due_at_counter_value := l_temp_counter_tbl(i).counter_value;
4145                ELSE
4146                   -- calculate due counter value.
4147                   l_last_due_counter_tbl(1) := l_temp_counter_tbl(i); -- current ctr
4148 
4149                   -- before the due counter value.
4150                   Get_Due_At_Counter_Values (p_last_due_date => p_last_due_date,
4151                                              p_last_due_counter_val_tbl => l_last_due_counter_tbl,
4152                                              p_due_date => l_due_date,
4153                                              p_counter_rules_tbl => p_counter_rules_tbl,
4154                                              x_due_at_counter_val_tbl => l_due_counter_tbl,
4155                                              x_return_value  => l_return_val);
4156 
4157                   -- if forecast not setup, cannot calculate due counter value for
4158                   -- start date.
4159                   IF NOT(l_return_val) THEN
4160                     l_due_date := NULL;
4161                     RAISE DUE_DATE_NULL;
4162                   ELSE
4163                     l_due_at_counter_value := l_due_counter_tbl(1).counter_value;
4164                   END IF;
4165 
4166                END IF; -- l_due_date < trunc(sysdate)
4167              END IF; -- (l_reset_start_date_flag)
4168            END IF; -- p_repetivity_flag = 'N') AND ..
4169 
4170            --dbms_output.put_line ('due at counter' || l_due_at_counter_value );
4171 
4172            -- Check for interval value overflow.
4173            IF (mr_interval_rec.stop_value IS NOT NULL) THEN
4174              --IF (l_due_at_counter_value  >= mr_interval_rec.stop_value) THEN
4175              -- Fix for bug# 3482307.
4176              IF (l_due_at_counter_value  > mr_interval_rec.stop_value) THEN
4177 
4178                 Adjust_Interval_Value (p_mr_effectivity_id => effectivity_rec.mr_effectivity_id,
4179                                        p_counter_id        => l_temp_counter_tbl(i).counter_id,
4180                                        p_counter_value     => l_counter_value,
4181                                        p_interval_value    => mr_interval_rec.interval_value,
4182                                        p_stop_value        => mr_interval_rec.stop_value,
4183                                        x_adjusted_int_value => l_adjusted_int_value,
4184                                        x_nxt_interval_found => l_nxt_interval_found);
4185                 -- Fix for bug# 3461118.
4186                 IF NOT(l_nxt_interval_found) THEN
4187                   IF (l_ctr_interval_found = TRUE AND l_old_ctr_interval_found = FALSE) THEN
4188                     l_ctr_interval_found := FALSE;
4189                   END IF;
4190                   GOTO next_mr_interval_loop;
4191                 ELSE
4192                   l_due_at_counter_value := l_adjusted_int_value + l_counter_value;
4193                 END IF;
4194              END IF;
4195            END IF;
4196 
4197 
4198            IF (p_repetivity_flag = 'N') THEN
4199              l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
4200            ELSE
4201              l_counter_remain := l_due_at_counter_value - l_counter_value;
4202            END IF;
4203 
4204            --dbms_output.put_line ('counter remain' || l_counter_remain );
4205 
4206            IF G_DEBUG = 'Y' THEN
4207              AHL_DEBUG_PUB.Debug('due at counter_value:' || l_due_at_counter_value);
4208              AHL_DEBUG_PUB.Debug('counter remain:' || l_counter_remain);
4209            END IF;
4210 
4211            -- if due date already set based on start date then skip date calculation.
4212            IF NOT(l_reset_start_date_flag) THEN
4213              -- calculate due date based on forecast.
4214              IF (l_counter_remain > 0) THEN
4215                 -- get date from forecast.
4216                 get_date_from_uf(l_counter_remain,
4217                                  l_temp_counter_tbl(i).uom_code,
4218                                  p_counter_rules_tbl,
4219                                  l_start_date,
4220                                  --null, /* start date = sysdate */
4221                                  l_due_date);
4222 
4223                 --dbms_output.put_line ('due date by forecast' || l_due_date );
4224 
4225              ELSIF (l_counter_remain < 0) THEN
4226                -- Due date = counter reading date.
4227                get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
4228                                          p_counter_id           => l_temp_counter_tbl(i).counter_id,
4229                                          p_counter_value        => l_due_at_counter_value,
4230                                          x_ctr_record_date      => l_counter_read_date,
4231                                          x_return_val           => l_return_val);
4232 
4233                IF NOT(l_return_val) THEN
4234                   l_due_date := sysdate;
4235                ELSE
4236                   l_due_date := l_counter_read_date;
4237                END IF;
4238 
4239              ELSIF (l_counter_remain = 0) THEN  /* due_date = sysdate */
4240                --dbms_output.put_line ('counter remain less than zero');
4241                l_due_date := sysdate;
4242              END IF;
4243            END IF; -- l_reset_start_date_flag
4244 
4245            /* commented out to fix bug# 6907562
4246            -- Check the due date value.
4247            IF (l_due_date IS NULL) THEN
4248               RAISE DUE_DATE_NULL;
4249            END IF;
4250            */
4251 
4252            -- Check Due date overflow to next interval.
4253            IF (mr_interval_rec.stop_date IS NOT NULL) THEN
4254               IF (l_due_date > mr_interval_rec.stop_date) THEN
4255 
4256                  -- Call procedure to adjust due date.
4257                  Adjust_Due_Date ( p_mr_effectivity_id => effectivity_rec.mr_effectivity_id,
4258                                    p_start_counter_rec => l_temp_counter_tbl(i),
4259                                    p_start_due_date    => p_last_due_date,
4260                                    p_counter_rules_tbl => p_counter_rules_tbl,
4261                                    p_interval_value    => mr_interval_rec.interval_value,
4262                                    p_stop_date         => mr_interval_rec.stop_date,
4263                                    p_due_date          => l_due_date,
4264                                    x_adjusted_due_date => l_adjusted_due_date,
4265                                    x_adjusted_due_ctr  => l_adjusted_due_ctr,
4266                                    x_nxt_interval_found => l_nxt_interval_found);
4267 
4268                  -- Fix for bug# 3461118.
4269                  IF NOT(l_nxt_interval_found) THEN
4270                    IF (l_ctr_interval_found = TRUE AND l_old_ctr_interval_found = FALSE) THEN
4271                      l_ctr_interval_found := FALSE;
4272                    END IF;
4273                    GOTO next_mr_interval_loop;
4274                  ELSE
4275                    IF (l_due_date <> l_adjusted_due_date) THEN
4276                      l_due_at_counter_value := l_adjusted_due_ctr + l_counter_value;
4277                    END IF;
4278                    l_due_date := l_adjusted_due_date;
4279                  END IF;
4280                  --dbms_output.put_line ('adjusted_due_date' || l_due_date );
4281 
4282               END IF;
4283            END IF;
4284 
4285            /* fix for bug# 6858788: this causes next repetity to be over
4286             * interval value
4287            -- Call Get_Due_At_Counter_Values only if due date is a future date.
4288            IF (l_reset_start_value_flag) AND (trunc(l_due_date) > trunc(sysdate)) THEN
4289               -- Check if the counter value on the due date is less than the due counter value.
4290               -- If less, add a day to the due date. This would ensure that the MR is performed not
4291               -- before due date.
4292               l_last_due_counter_tbl(1) := l_temp_counter_tbl(i);
4293 
4294               -- before the due counter value.
4295               Get_Due_At_Counter_Values (p_last_due_date => p_last_due_date,
4296                                          p_last_due_counter_val_tbl => l_last_due_counter_tbl,
4297                                          p_due_date => l_due_date,
4298                                          p_counter_rules_tbl => p_counter_rules_tbl,
4299                                          x_due_at_counter_val_tbl => l_due_counter_tbl,
4300                                          x_return_value  => l_return_val);
4301 
4302               IF (l_return_val) THEN
4303                 IF (l_due_counter_tbl(1).counter_value < l_due_at_counter_value) THEN
4304                    l_due_date := l_due_date + 1;
4305                 END IF;
4306               END IF;
4307 
4308            END IF;
4309            */
4310            -- Compare with whichever first code and set l_calc_due_date.
4311            -- logic modified to fix bug# 6907562. Here l_due_date can be null.
4312            IF (l_due_date IS NULL) THEN
4313                -- Added to fix bug# 6907562.
4314                IF (validate_for_duedate_reset(l_due_date,
4315                                               l_counter_remain,
4316                                               l_calc_due_date,
4317                                               l_calc_due_date_ctr_id,
4318                                               x_next_due_date_rec.counter_remain)) = 'Y' THEN
4319                    --dbms_output.put_line ('due date is null');
4320                    l_calc_due_date := l_due_date;
4321                    x_next_due_date_rec.due_date := l_due_date;
4322                    x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
4323                    x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
4324                    x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
4325                    x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4326                    x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4327                    x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4328                    x_next_due_date_rec.last_ctr_value := l_counter_value;
4329                    x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
4330                    x_next_due_date_rec.counter_id := null;
4331                    x_next_due_date_rec.counter_remain := l_counter_remain;
4332                    l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
4333                END IF;
4334            ELSE  -- due date is not null
4335                IF (l_calc_due_date IS NULL) THEN
4336                    -- Added to fix bug# 6907562.
4337                    IF (validate_for_duedate_reset(l_due_date,
4338                                                   l_counter_remain,
4339                                                   l_calc_due_date,
4340                                                   l_calc_due_date_ctr_id,
4341                                                   x_next_due_date_rec.counter_remain)) = 'Y' THEN
4342 
4343                      --dbms_output.put_line ('calc due date is null');
4344                      l_calc_due_date := l_due_date;
4345                      x_next_due_date_rec.due_date := l_due_date;
4346                      x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
4347                      x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
4348                      x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
4349                      x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4350                      x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4351                      x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4352                      x_next_due_date_rec.last_ctr_value := l_counter_value;
4353                      x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
4354                      x_next_due_date_rec.counter_id := null;
4355                      x_next_due_date_rec.counter_remain := l_counter_remain;
4356                      l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
4357                    END IF;
4358                ELSE
4359                    IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
4360                      -- dbms_output.put_line ('applicable mr which code = first');
4361                      -- Check due date based on whichever_first_code.
4362                      -- if dates are equal, switch based on lower uom remain value. (bug# 6907562).
4363                      IF (l_calc_due_date > l_due_date) OR
4364                        (trunc(l_calc_due_date) = trunc(l_due_date) AND l_counter_remain IS NOT NULL
4365                         AND x_next_due_date_rec.counter_remain IS NOT NULL
4366                         AND l_counter_remain < x_next_due_date_rec.counter_remain) THEN
4367 
4368                         --dbms_output.put_line ('calc_due_date > l_due date');
4369                         l_calc_due_date := l_due_date;
4370                         x_next_due_date_rec.due_date := l_due_date;
4371                         x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
4372                         x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
4373                         x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
4374                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4375                         x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4376                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4377                         x_next_due_date_rec.last_ctr_value := l_counter_value;
4378                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
4379                         x_next_due_date_rec.counter_id := null;
4380                         x_next_due_date_rec.counter_remain := l_counter_remain;
4381                         l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
4382                      END IF;
4383                    ELSE  /* whichever_first_code = 'LAST' */
4384                      --dbms_output.put_line ('applicable mr which code = last');
4385                      -- if dates are equal, switch based on higher uom remain value. (bug# 6907562).
4386                      IF (l_calc_due_date < l_due_date) OR
4387                         (trunc(l_calc_due_date) = trunc(l_due_date) AND l_counter_remain IS NOT NULL
4388                         AND x_next_due_date_rec.counter_remain IS NOT NULL
4389                         AND l_counter_remain > x_next_due_date_rec.counter_remain) THEN
4390 
4391                         --dbms_output.put_line ('calc_due_date < l_due date');
4392                         l_calc_due_date := l_due_date;
4393                         x_next_due_date_rec.due_date := l_due_date;
4394                         x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
4395                         x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
4396                         x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
4397                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4398                         x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4399                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4400                         x_next_due_date_rec.last_ctr_value := l_counter_value;
4401                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
4402                         x_next_due_date_rec.counter_id := null;
4403                         x_next_due_date_rec.counter_remain := l_counter_remain;
4404                         l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
4405                      END IF;
4406                    END IF;
4407                END IF; /* calc_due_date null */
4408                --dbms_output.put_line ('Next mr interval');
4409            END IF; -- due date is null.
4410 
4411            IF G_DEBUG = 'Y' THEN
4412              AHL_DEBUG_PUB.Debug('Before Next interval table loop');
4413              AHL_DEBUG_PUB.Debug('l_due_date:' || l_due_date );
4414              AHL_DEBUG_PUB.Debug('l_calc_due_date:' || l_calc_due_date);
4415              AHL_DEBUG_PUB.Debug('l_calc_due_date_ctr_id:' || l_calc_due_date_ctr_id);
4416            END IF;
4417 
4418            -- Fix for bug# 3461118.
4419            <<next_mr_interval_loop>>
4420            NULL;
4421          END LOOP; /* mr_interval_rec */
4422 
4423          -- If no interval found, then check if future intervals exist
4424          -- and calculate date based on that interval.
4425          -- Added p_mr_accomplish_exists and p_last_due_mr_interval_id to fix bug# 6858788.
4426          -- Commented p_last_accomplishment_date and will instead use p_mr_accomplish_exists.
4427          IF NOT(l_ctr_interval_found) THEN
4428            Get_DueDate_from_NxtInterval (p_applicable_mrs_rec => p_applicable_mrs_rec,
4429                                          p_repetivity_flag    => p_repetivity_flag,
4430                                          p_mr_effectivity_id => effectivity_rec.mr_effectivity_id,
4431                                          p_current_ctr_rec   => l_temp_counter_tbl(i),
4432                                          p_counter_rules_tbl => p_counter_rules_tbl,
4433                                          p_current_ctr_at_date => l_start_date,
4434                                          p_start_int_match_at_ctr => l_start_int_match_at_ctr,
4435                                          p_last_accomplish_ctr_val => l_counter_value,
4436                                          --p_last_accomplishment_date => p_last_due_date,
4437                                          p_dependent_mr_flag => p_dependent_mr_flag,
4438                                          p_mr_accomplish_exists => p_mr_accomplish_exists,
4439                                          p_last_due_mr_interval_id => p_last_due_mr_interval_id,
4440                                          x_next_due_date_rec => l_next_due_date_rec,
4441                                                                 --x_next_due_date_rec,
4442                                          x_mr_interval_found => l_ctr_interval_found,
4443                                          x_return_val        => l_return_val);
4444            IF (l_ctr_interval_found) THEN
4445              IF NOT(l_return_val) THEN
4446                RAISE DUE_DATE_NULL; -- forecast not available hence uom remain is not known.
4447              END IF;
4448 
4449              IF (l_next_due_date_rec.due_date IS NOT NULL) THEN
4450                 IF (l_calc_due_date IS NULL) THEN
4451                    -- Added to fix bug# 6907562.
4452                    IF (validate_for_duedate_reset(l_next_due_date_rec.due_date,
4453                                                   l_next_due_date_rec.counter_remain,
4454                                                   l_calc_due_date,
4455                                                   l_calc_due_date_ctr_id,
4456                                                   x_next_due_date_rec.counter_remain)) = 'Y' THEN
4457 
4458                       x_next_due_date_rec := l_next_due_date_rec;
4459                       l_calc_due_date := x_next_due_date_rec.due_date;
4460                       x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4461                       x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4462                       x_next_due_date_rec.last_ctr_value := l_counter_value;
4463                       x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
4464                       x_next_due_date_rec.counter_id := null;
4465                       l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
4466                    END IF; -- validate_for_duedate_reset
4467 
4468                 ELSIF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
4469                   -- if dates are equal, switch based on lower uom remain value. (bug# 6907562).
4470                   IF (l_calc_due_date > l_next_due_date_rec.due_date) OR
4471                      (trunc(l_calc_due_date) = trunc(l_next_due_date_rec.due_date)
4472                      AND l_next_due_date_rec.counter_remain IS NOT NULL
4473                      AND x_next_due_date_rec.counter_remain IS NOT NULL
4474                      AND l_next_due_date_rec.counter_remain < x_next_due_date_rec.counter_remain) THEN
4475 
4476                       x_next_due_date_rec := l_next_due_date_rec;
4477                       l_calc_due_date := x_next_due_date_rec.due_date;
4478                       x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4479                       x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4480                       x_next_due_date_rec.last_ctr_value := l_counter_value;
4481                       x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
4482                       x_next_due_date_rec.counter_id := null;
4483                       l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
4484                   END IF;
4485                 ELSIF (p_applicable_mrs_rec.whichever_first_code = 'LAST') THEN
4486                    -- if dates are equal, switch based on higher uom remain value. (bug# 6907562).
4487                    IF (l_calc_due_date < l_next_due_date_rec.due_date) OR
4488                       (trunc(l_calc_due_date) = trunc(l_next_due_date_rec.due_date)
4489                         AND l_next_due_date_rec.counter_remain IS NOT NULL
4490                         AND x_next_due_date_rec.counter_remain IS NOT NULL
4491                         AND l_next_due_date_rec.counter_remain > x_next_due_date_rec.counter_remain) THEN
4492                        x_next_due_date_rec := l_next_due_date_rec;
4493                        l_calc_due_date := x_next_due_date_rec.due_date;
4494                        x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4495                        x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4496                        x_next_due_date_rec.last_ctr_value := l_counter_value;
4497                        x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
4498                        x_next_due_date_rec.counter_id := null;
4499                        l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
4500                   END IF;
4501                 END IF; -- l_calc_due_date IS NULL
4502              -- else added to fix bug# 6907562.
4503              ELSE -- due date is null.
4504                -- Added to fix bug# 6907562.
4505                IF (validate_for_duedate_reset(l_next_due_date_rec.due_date,
4506                                               l_next_due_date_rec.counter_remain,
4507                                               l_calc_due_date,
4508                                               l_calc_due_date_ctr_id,
4509                                               x_next_due_date_rec.counter_remain)) = 'Y' THEN
4510                     x_next_due_date_rec := l_next_due_date_rec;
4511                     l_calc_due_date := x_next_due_date_rec.due_date;
4512                     x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4513                     x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4514                     x_next_due_date_rec.last_ctr_value := l_counter_value;
4515                     x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(i).uom_code;
4516                     x_next_due_date_rec.counter_id := null;
4517                     l_calc_due_date_ctr_id := l_temp_counter_tbl(i).counter_id;
4518 
4519                END IF; -- validate_for_duedate_reset
4520              END IF; -- x_next_due_date_rec.due_date IS NOT NULL
4521            END IF; -- l_ctr_interval_found.
4522          END IF; -- NOT(l_ctr_interval_found)
4523 
4524          -- added to fix bug# 6725769.
4525          IF NOT(l_mr_interval_found) THEN
4526             IF (l_ctr_interval_found) THEN
4527                 l_mr_interval_found := TRUE;
4528             END IF;
4529          END IF;
4530          --dbms_output.put_line ('next counter');
4531 
4532          <<next_counter_loop>>
4533          NULL;
4534        END LOOP; /* temp_counter_tbl */
4535      END IF; /* count > 0 */
4536 
4537      -- Check due date with threshold date.
4538      -- If threshold date exists, then the MR is not repetitive.
4539      IF (effectivity_rec.threshold_date IS NOT NULL) AND (p_repetivity_flag = 'N') AND
4540         ( (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 */
4541           (l_mr_interval_found = FALSE) ) /* case of no intervals defined for an effectivity */
4542         THEN
4543          --dbms_output.put_line ('in threshold');
4544          IF (l_calc_due_date IS NULL) THEN
4545              l_calc_due_date := effectivity_rec.threshold_date;
4546              x_next_due_date_rec.due_date := effectivity_rec.threshold_date;
4547              x_next_due_date_rec.tolerance_after := null;
4548              x_next_due_date_rec.tolerance_before := null;
4549              x_next_due_date_rec.mr_interval_id := null;
4550              x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4551              x_next_due_date_rec.due_at_counter_value := null;
4552              x_next_due_date_rec.current_ctr_value := null;
4553              x_next_due_date_rec.last_ctr_value := null;
4554              x_next_due_date_rec.ctr_uom_code := null;
4555              x_next_due_date_rec.counter_id := null;
4556              x_next_due_date_rec.counter_remain := null;
4557              l_calc_due_date_ctr_id := null;
4558          ELSIF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
4559              IF (l_calc_due_date > effectivity_rec.threshold_date) THEN
4560                   l_calc_due_date := effectivity_rec.threshold_date;
4561                   x_next_due_date_rec.due_date := effectivity_rec.threshold_date;
4562                   x_next_due_date_rec.tolerance_after := null;
4563                   x_next_due_date_rec.tolerance_before := null;
4564                   x_next_due_date_rec.mr_interval_id := null;
4565                   x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4566                   x_next_due_date_rec.due_at_counter_value := null;
4567                   x_next_due_date_rec.current_ctr_value := null;
4568                   x_next_due_date_rec.last_ctr_value := null;
4569                   x_next_due_date_rec.ctr_uom_code := null;
4570                   x_next_due_date_rec.counter_id := null;
4571                   x_next_due_date_rec.counter_remain := null;
4572                   l_calc_due_date_ctr_id := null;
4573 
4574               END IF;
4575          ELSIF (p_applicable_mrs_rec.whichever_first_code = 'LAST') THEN
4576            /* whichever_first_code = 'LAST' */
4577             IF (l_calc_due_date < effectivity_rec.threshold_date) THEN
4578                   l_calc_due_date := effectivity_rec.threshold_date;
4579                   x_next_due_date_rec.due_date := effectivity_rec.threshold_date;
4580                   x_next_due_date_rec.tolerance_after := null;
4581                   x_next_due_date_rec.tolerance_before := null;
4582                   x_next_due_date_rec.mr_interval_id := null;
4583                   x_next_due_date_rec.due_at_counter_value := null;
4584                   x_next_due_date_rec.mr_effectivity_id := effectivity_rec.mr_effectivity_id;
4585                   x_next_due_date_rec.current_ctr_value := null;
4586                   x_next_due_date_rec.last_ctr_value := null;
4587                   x_next_due_date_rec.ctr_uom_code := null;
4588                   x_next_due_date_rec.counter_id := null;
4589                   x_next_due_date_rec.counter_remain := null;
4590                   l_calc_due_date_ctr_id := null;
4591 
4592             END IF;
4593          END IF; /* whichever_first_code */
4594       END IF; /* threshold_date not null */
4595 
4596       --dbms_output.put_line ('NEXT effectivity');
4597   END LOOP mr_effectivity_loop; /* effectivity_rec */
4598 
4599   -- Fix for bug# 6358940. Due Date should be based only on init-due if it
4600   -- exists. MR thresholds should not be used.
4601   -- Moved below logic to the beginning of the this procedure before processing
4602   -- effectivities.
4603   -- Calculate due date based on init-due defination; if exists.
4604   /*
4605   IF (p_repetivity_flag = 'N') THEN
4606      --dbms_output.put_line ('in INIT-due part');
4607 
4608      -- Check if there is any init-due record for this item instance and mr exists.
4609      OPEN ahl_init_due_csr(p_applicable_mrs_rec.csi_item_instance_id,
4610                            p_applicable_mrs_rec.mr_header_id);
4611      FETCH ahl_init_due_csr INTO l_set_due_date, l_unit_effectivity_id, l_unit_deferral_id;
4612      IF (ahl_init_due_csr%FOUND) THEN
4613 
4614         --dbms_output.put_line ('in INIT-due part: due_date' || l_set_due_date);
4615 
4616         FOR threshold_rec IN ahl_unit_thresholds_csr (l_unit_deferral_id)
4617         LOOP
4618           -- for init due, ctr_value_type_code is always 'defer_to'.
4619           l_due_at_counter_value := threshold_rec.counter_value;
4620           l_counter_remain := 0;
4621           l_current_ctr_value := 0;
4622           k := 0;
4623           -- search for the current counter value in l_current_usage_tbl.
4624           IF (l_temp_counter_tbl.COUNT > 0) THEN
4625             FOR i IN l_temp_counter_tbl.FIRST..l_temp_counter_tbl.LAST LOOP
4626                IF (l_temp_counter_tbl(i).counter_id = threshold_rec.counter_id) THEN
4627                   l_current_ctr_value := l_temp_counter_tbl(i).counter_value;
4628                   k := i;
4629                   EXIT;
4630                END IF;
4631             END LOOP;
4632             l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
4633           END IF;
4634 
4635           -- calculate due date from forecast.
4636           IF (l_counter_remain > 0) THEN
4637             -- get date from forecast.
4638             get_date_from_uf(l_counter_remain,
4639                              l_temp_counter_tbl(k).uom_code,
4640                              p_counter_rules_tbl,
4641                              null, -- start date = sysdate
4642                              l_due_date);
4643           ELSIF (l_counter_remain < 0) THEN
4644             -- Due date = counter reading date.
4645              get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
4646                                        p_counter_id           => l_temp_counter_tbl(k).counter_id,
4647                                        p_counter_value        => l_due_at_counter_value,
4648                                        x_ctr_record_date      => l_counter_read_date,
4649                                        x_return_val           => l_return_val);
4650 
4651              IF NOT(l_return_val) THEN
4652                 l_due_date := sysdate;
4653              ELSE
4654                 l_due_date := l_counter_read_date;
4655              END IF;
4656 
4657           ELSIF (l_counter_remain = 0) THEN  -- due_date = sysdate
4658             --dbms_output.put_line ('counter remain less than zero');
4659             l_due_date := sysdate;
4660           END IF;
4661 
4662           IF (l_calc_due_date IS NOT NULL AND l_mr_interval_found = TRUE) OR  -- case where intervals exist.
4663              (l_mr_interval_found = FALSE)  THEN    -- case where no intervals.
4664             -- Compare with whichever first code and set l_calc_due_date.
4665             IF (l_due_date IS NULL) THEN
4666                --dbms_output.put_line ('due date null');
4667                l_calc_due_date := l_due_date;
4668                x_next_due_date_rec.due_date := null;
4669                x_next_due_date_rec.tolerance_after := null;
4670                x_next_due_date_rec.tolerance_before := null;
4671                x_next_due_date_rec.mr_interval_id := null;
4672                x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4673                x_next_due_date_rec.mr_effectivity_id := null;
4674                x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4675                x_next_due_date_rec.last_ctr_value := null;
4676                x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
4677                x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
4678                x_next_due_date_rec.counter_remain := l_counter_remain;
4679                l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
4680                EXIT;
4681             ELSE  -- happens when no interval
4682               IF (l_calc_due_date IS NULL) THEN
4683                  --dbms_output.put_line ('calc due date null');
4684                  l_calc_due_date := l_due_date;
4685                  x_next_due_date_rec.due_date := l_due_date;
4686                  x_next_due_date_rec.tolerance_after := null;
4687                  x_next_due_date_rec.tolerance_before := null;
4688                  x_next_due_date_rec.mr_interval_id := null;
4689                  x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4690                  x_next_due_date_rec.mr_effectivity_id := null;
4691                  x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4692                  x_next_due_date_rec.last_ctr_value := null;
4693                  x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
4694                  x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
4695                  x_next_due_date_rec.counter_remain := l_counter_remain;
4696                  l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
4697 
4698               ELSE
4699                  IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
4700                     -- Check due date based on whichever_first_code.
4701                     IF (l_calc_due_date > l_due_date) THEN
4702                         l_calc_due_date := l_due_date;
4703                         x_next_due_date_rec.due_date := l_due_date;
4704                         x_next_due_date_rec.tolerance_after := null;
4705                         x_next_due_date_rec.tolerance_before := null;
4706                         x_next_due_date_rec.mr_interval_id := null;
4707                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4708                         x_next_due_date_rec.mr_effectivity_id := null;
4709                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4710                         x_next_due_date_rec.last_ctr_value := null;
4711                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
4712                         x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
4713                         x_next_due_date_rec.counter_remain := l_counter_remain;
4714                         l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
4715 
4716                     END IF;
4717                  ELSE  -- whichever_first_code = 'LAST'
4718                     IF (l_calc_due_date < l_due_date) THEN
4719                         --dbms_output.put_line ('set due date');
4720                         l_calc_due_date := l_due_date;
4721                         x_next_due_date_rec.due_date := l_due_date;
4722                         x_next_due_date_rec.tolerance_after := null;
4723                         x_next_due_date_rec.tolerance_before := null;
4724                         x_next_due_date_rec.mr_interval_id := null;
4725                         x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4726                         x_next_due_date_rec.mr_effectivity_id := null;
4727                         x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4728                         x_next_due_date_rec.last_ctr_value := null;
4729                         x_next_due_date_rec.ctr_uom_code := l_temp_counter_tbl(k).uom_code;
4730                         x_next_due_date_rec.counter_id := l_temp_counter_tbl(k).counter_id;
4731                         x_next_due_date_rec.counter_remain := l_counter_remain;
4732                         l_calc_due_date_ctr_id := l_temp_counter_tbl(k).counter_id;
4733 
4734                     END IF;
4735                  END IF; -- applicable_mrs_rec
4736               END IF; -- calc_due_date null
4737             END IF;
4738           END IF; -- calc due date and l_mr_interval_found.
4739         END LOOP; -- set_threshold_rec
4740 
4741         -- Check for set due date.
4742         IF (l_set_due_date IS NOT NULL) THEN
4743            IF (l_calc_due_date IS NOT NULL AND l_mr_interval_found = TRUE) OR  -- case where intervals exist.
4744               (l_mr_interval_found = FALSE)  THEN    -- case where no intervals.
4745 
4746               IF (l_calc_due_date IS NULL) THEN
4747                  l_calc_due_date := l_set_due_date;
4748                  x_next_due_date_rec.due_date := l_set_due_date;
4749                  x_next_due_date_rec.tolerance_after := null;
4750                  x_next_due_date_rec.tolerance_before := null;
4751                  x_next_due_date_rec.mr_effectivity_id := null;
4752                  x_next_due_date_rec.due_at_counter_value := null;
4753                  x_next_due_date_rec.current_ctr_value := null;
4754                  x_next_due_date_rec.last_ctr_value := null;
4755                  x_next_due_date_rec.mr_interval_id := null;
4756                  x_next_due_date_rec.ctr_uom_code := null;
4757                  x_next_due_date_rec.counter_id := null;
4758                  x_next_due_date_rec.counter_remain := null;
4759                  l_calc_due_date_ctr_id := null;
4760 
4761               ELSE
4762                  IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
4763                      IF (l_calc_due_date > l_set_due_date) THEN
4764                        --dbms_output.put_line ('set due da te');
4765                        l_calc_due_date := l_set_due_date;
4766                        x_next_due_date_rec.due_date := l_set_due_date;
4767                        x_next_due_date_rec.tolerance_after := null;
4768                        x_next_due_date_rec.tolerance_before := null;
4769                        x_next_due_date_rec.mr_interval_id := null;
4770                        x_next_due_date_rec.due_at_counter_value := null;
4771                        x_next_due_date_rec.mr_effectivity_id := null;
4772                        x_next_due_date_rec.current_ctr_value := null;
4773                        x_next_due_date_rec.last_ctr_value := null;
4774                        x_next_due_date_rec.ctr_uom_code := null;
4775                        x_next_due_date_rec.counter_id := null;
4776                        x_next_due_date_rec.counter_remain := null;
4777                        l_calc_due_date_ctr_id := null;
4778 
4779                      END IF;
4780                  ELSE
4781                     -- Check for set due date.
4782                     IF (l_calc_due_date < l_set_due_date) THEN
4783                         l_calc_due_date := l_set_due_date;
4784                         x_next_due_date_rec.due_date := l_set_due_date;
4785                         x_next_due_date_rec.tolerance_after := null;
4786                         x_next_due_date_rec.tolerance_before := null;
4787                         x_next_due_date_rec.mr_interval_id := null;
4788                         x_next_due_date_rec.due_at_counter_value := null;
4789                         x_next_due_date_rec.mr_effectivity_id := null;
4790                         x_next_due_date_rec.current_ctr_value := null;
4791                         x_next_due_date_rec.last_ctr_value := null;
4792                         x_next_due_date_rec.ctr_uom_code := null;
4793                         x_next_due_date_rec.counter_id := null;
4794                         x_next_due_date_rec.counter_remain := null;
4795                         l_calc_due_date_ctr_id := null;
4796 
4797                     END IF;
4798                  END IF; -- applicable
4799                END IF;
4800             END IF;
4801          END IF;  -- set due date
4802      END IF; -- init_due_csr
4803      CLOSE ahl_init_due_csr;
4804   END IF; -- repetitive_flag
4805   */
4806   -- After processing all effectivities, check if any interval got triggered.
4807   -- If not, set all values to null and exit procedure.
4808   IF (x_next_due_date_rec.mr_effectivity_id IS NULL) AND
4809      (x_next_due_date_rec.mr_interval_id IS NULL) AND (l_calc_due_date IS NULL) AND
4810      (x_next_due_date_rec.counter_id IS NULL) THEN
4811       RAISE NO_VALID_INTERVAL;
4812   END IF;
4813 
4814   -- Evaluate tolerance condition.
4815   IF (x_next_due_date_rec.mr_interval_id IS NOT NULL) THEN
4816      IF ((x_next_due_date_rec.due_at_counter_value +
4817          x_next_due_date_rec.tolerance_after) < x_next_due_date_rec.current_ctr_value) THEN
4818          x_next_due_date_rec.tolerance_flag := 'Y';
4819          x_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
4820      END IF;
4821 
4822      -- Added for ER#2636001.
4823      -- Calculate earliest due date.
4824      IF x_next_due_date_rec.tolerance_before IS NOT NULL THEN
4825        -- Not required: If due date is today's date then earliest due = due date.
4826        IF (x_next_due_date_rec.due_date IS NOT NULL) THEN
4827           --IF (trunc(x_next_due_date_rec.due_date) = trunc(sysdate)) THEN
4828           --    x_next_due_date_rec.earliest_due_date := x_next_due_date_rec.due_date;
4829           --ELSE
4830             -- find the left over counter value
4831             IF (p_repetivity_flag = 'N') THEN
4832               l_counter_remain := (x_next_due_date_rec.due_at_counter_value -
4833                                    x_next_due_date_rec.tolerance_before) -
4834                                    x_next_due_date_rec.current_ctr_value;
4835             ELSE
4836               l_counter_remain := (x_next_due_date_rec.due_at_counter_value -
4837                                    x_next_due_date_rec.tolerance_before) -
4838                                    x_next_due_date_rec.last_ctr_value;
4839             END IF;
4840 
4841             IF (l_counter_remain < 0) THEN
4842                -- Due date = counter reading date.
4843                get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
4844                                          p_counter_id           => l_calc_due_date_ctr_id,
4845                                          p_counter_value        => x_next_due_date_rec.due_at_counter_value -
4846                                                                    x_next_due_date_rec.tolerance_before,
4847                                          x_ctr_record_date      => l_counter_read_date,
4848                                          x_return_val           => l_return_val);
4849                IF NOT(l_return_val) THEN
4850                   x_next_due_date_rec.earliest_due_date := null;
4851                ELSE
4852                   x_next_due_date_rec.earliest_due_date := l_counter_read_date;
4853                END IF;
4854                -- if earliest_due_date > due date (when no counters readings exist before counter remain).
4855                IF (x_next_due_date_rec.earliest_due_date > x_next_due_date_rec.due_date) THEN
4856                    x_next_due_date_rec.earliest_due_date := x_next_due_date_rec.due_date;
4857                END IF;
4858 
4859             ELSE /* counter_remain > 0 */
4860                -- get date from forecast.
4861                get_date_from_uf(l_counter_remain,
4862                                 x_next_due_date_rec.ctr_uom_code,
4863                                 p_counter_rules_tbl,
4864                                 l_start_date,
4865                                 x_next_due_date_rec.earliest_due_date);
4866                --IF (trunc(x_next_due_date_rec.earliest_due_date) < trunc(sysdate)) THEN
4867                -- x_next_due_date_rec.earliest_due_date := sysdate;
4868                --END IF;
4869             END IF; -- counter_remain.
4870          --END IF; -- due_date = sysdate.
4871        END IF; -- due date is not null.
4872      END IF; -- tolerance before.
4873 
4874      IF (x_next_due_date_rec.tolerance_after) IS NOT NULL THEN
4875        -- Calculate counter remain.
4876        IF (p_repetivity_flag = 'N') THEN
4877          l_counter_remain := (x_next_due_date_rec.due_at_counter_value +
4878                               x_next_due_date_rec.tolerance_after) -
4879                               x_next_due_date_rec.current_ctr_value;
4880        ELSE
4881          l_counter_remain := (x_next_due_date_rec.due_at_counter_value +
4882                               x_next_due_date_rec.tolerance_after) -
4883                               x_next_due_date_rec.last_ctr_value;
4884        END IF;
4885 
4886        IF (l_counter_remain < 0) THEN
4887           -- Due date = counter reading date.
4888           get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
4889                                     p_counter_id           => l_calc_due_date_ctr_id,
4890                                     p_counter_value        => x_next_due_date_rec.due_at_counter_value +
4891                                                               x_next_due_date_rec.tolerance_after,
4892                                     x_ctr_record_date      => l_counter_read_date,
4893                                     x_return_val           => l_return_val);
4894 
4895           IF NOT(l_return_val) THEN
4896              x_next_due_date_rec.latest_due_date := null;
4897           ELSE
4898              x_next_due_date_rec.latest_due_date := l_counter_read_date;
4899           END IF;
4900 
4901        ELSE   /* counter_remain > 0 */
4902           -- Calculate latest tolerance.
4903           get_date_from_uf(x_next_due_date_rec.tolerance_after,
4904                            x_next_due_date_rec.ctr_uom_code,
4905                            p_counter_rules_tbl,
4906                            x_next_due_date_rec.due_date,
4907                            x_next_due_date_rec.latest_due_date);
4908        END IF; -- counter_remain.
4909      ELSE
4910         -- If due date is less than sysdate, then flag tolerance.
4911         IF (x_next_due_date_rec.due_date IS NOT NULL) AND
4912            (trunc(x_next_due_date_rec.due_date) < trunc(sysdate)) THEN
4913             x_next_due_date_rec.tolerance_flag := 'Y';
4914             x_next_due_date_rec.message_code := 'TOLERANCE-EXCEEDED';
4915         END IF;
4916 
4917      END IF;
4918      -- End of ER modifications.
4919   END IF;
4920 
4921   IF G_DEBUG = 'Y' THEN
4922         AHL_DEBUG_PUB.Debug('End calculate due date');
4923   END IF;
4924 
4925 
4926 EXCEPTION
4927   WHEN DUE_DATE_NULL THEN
4928        x_next_due_date_rec.due_date := null;
4929        x_next_due_date_rec.tolerance_after := l_mr_interval_rec.tolerance_after;
4930        x_next_due_date_rec.tolerance_before := l_mr_interval_rec.tolerance_before;
4931        x_next_due_date_rec.mr_interval_id := l_mr_interval_rec.mr_interval_id;
4932        x_next_due_date_rec.due_at_counter_value := l_due_at_counter_value;
4933        x_next_due_date_rec.mr_effectivity_id := null;
4934        x_next_due_date_rec.current_ctr_value := l_current_ctr_value;
4935        x_next_due_date_rec.counter_remain := l_counter_remain;
4936 
4937   WHEN NO_VALID_INTERVAL THEN
4938        x_next_due_date_rec.due_date := null;
4939        x_next_due_date_rec.tolerance_after := null;
4940        x_next_due_date_rec.tolerance_before := null;
4941        x_next_due_date_rec.mr_interval_id := null;
4942        x_next_due_date_rec.due_at_counter_value := null;
4943        x_next_due_date_rec.mr_effectivity_id := null;
4944        x_next_due_date_rec.current_ctr_value := null;
4945        x_next_due_date_rec.counter_remain := null;
4946 
4947 END Calculate_Due_Date;
4948 
4949 -------------------------------------------------------------------------------------------
4950 -- Calculate due at counter values for a given due due from last due date and last due counters using
4951 -- counter rules and forecast (defined in global variable).
4952 
4953 PROCEDURE Get_Due_At_Counter_Values ( p_last_due_date IN DATE,
4954                                       p_last_due_counter_val_tbl IN counter_values_tbl_type,
4955                                       p_due_date IN DATE,
4956                                       p_counter_rules_tbl IN counter_rules_tbl_type,
4957                                       x_due_at_counter_val_tbl OUT NOCOPY counter_values_tbl_type,
4958                                       x_return_value           OUT NOCOPY BOOLEAN)
4959 IS
4960 
4961   l_diff_days  NUMBER := 0;
4962   l_counter_value NUMBER := 0;
4963   l_forecast_days NUMBER := 0;
4964   l_no_forecast BOOLEAN := FALSE;
4965   l_next_index NUMBER;
4966   l_start_date DATE;
4967   l_total_days_in_period NUMBER;
4968 
4969   l_index_found BOOLEAN;
4970 
4971 BEGIN
4972 
4973 
4974   IF G_DEBUG = 'Y' THEN
4975         AHL_DEBUG_PUB.Debug('Start get_due_at_counter_values');
4976   END IF;
4977 
4978   -- Initialize return value.
4979   x_return_value := TRUE;
4980 
4981   -- find the difference between last due and due dates.
4982   l_diff_days := ABS(trunc(p_due_date) - trunc(p_last_due_date));
4983   --dbms_output.put_line ('l_diff_days'|| l_diff_days);
4984 
4985   IF (SIGN(p_due_date - p_last_due_date) = -1) THEN
4986      l_start_date := p_due_date;
4987   ELSE
4988      l_start_date := p_last_due_date;
4989   END IF;
4990 
4991   --dbms_output.put_line ('l_start_date' || l_start_date);
4992   --dbms_output.put_line ('count on last due ctr val' ||   p_last_due_counter_val_tbl.COUNT);
4993 
4994   -- Loop through last due counter tbl.
4995   IF (p_last_due_counter_val_tbl.COUNT > 0) THEN
4996     FOR i IN p_last_due_counter_val_tbl.FIRST..p_last_due_counter_val_tbl.LAST LOOP
4997       l_next_index := G_forecast_details_tbl.FIRST;
4998       -- set the starting index matching the start date and uom in forecast table.
4999       IF (l_next_index IS NULL) THEN
5000            l_no_forecast := TRUE;
5001       ELSE
5002         l_no_forecast := TRUE;
5003         FOR k IN G_forecast_details_tbl.FIRST..G_forecast_details_tbl.LAST LOOP
5004           IF (G_forecast_details_tbl(k).uom_code = p_last_due_counter_val_tbl(i).uom_code)
5005              AND (trunc(G_forecast_details_tbl(k).start_date) <= trunc(l_start_date)
5006              AND trunc(l_start_date) <= trunc(nvl(G_forecast_details_tbl(k).end_date,l_start_date)))
5007           THEN
5008              l_next_index := k;
5009              l_no_forecast := FALSE;
5010              EXIT;
5011           END IF;
5012         END LOOP;
5013       END IF;
5014 
5015       -- Based on counter uom_code, last_due_date, l_diff_days and G_forecast_details_tbl build counter value.
5016       WHILE (l_diff_days <> 0 AND l_no_forecast <> TRUE) LOOP
5017         IF (G_forecast_details_tbl(l_next_index).uom_code = p_last_due_counter_val_tbl(i).uom_code) THEN
5018            IF (trunc(G_forecast_details_tbl(l_next_index).start_date) <= trunc(l_start_date) AND
5019              trunc(nvl(G_forecast_details_tbl(l_next_index).end_date,l_start_date)) >= trunc(l_start_date)) THEN
5020              IF (G_forecast_details_tbl(l_next_index).end_date) IS NOT NULL THEN
5021                l_total_days_in_period := trunc(G_forecast_details_tbl(l_next_index).end_date - l_start_date) + 1;
5022                --dbms_output.put_line ('total days in period' || l_total_days_in_period);
5023                IF (l_total_days_in_period >= l_diff_days) THEN
5024                   l_counter_value := l_counter_value + trunc(l_diff_days * G_forecast_details_tbl(l_next_index).usage_per_day);
5025                   l_diff_days := 0;
5026                   --dbms_output.put_line ('total >= ldiff; ctr val' || l_counter_value );
5027                ELSE
5028                   l_diff_days := l_diff_days - l_total_days_in_period;
5029                   l_counter_value := l_counter_value + trunc(l_total_days_in_period * G_forecast_details_tbl(l_next_index).usage_per_day);
5030                   --dbms_output.put_line ('total < ldiff; ctr val' || l_counter_value );
5031                   -- Get next forecast record.
5032                   l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
5033                   IF (l_next_index IS NULL) THEN
5034                     l_no_forecast := TRUE;
5035                   ELSE
5036                     l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
5037                   END IF;
5038                END IF; /* total days */
5039              ELSE
5040                 l_counter_value := l_counter_value + trunc(l_diff_days * G_forecast_details_tbl(l_next_index).usage_per_day);
5041                 l_diff_days := 0;
5042              END IF; /* end date */
5043            ELSE
5044              -- get next forecast record.
5045              l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
5046              IF (l_next_index IS NULL) THEN
5047                l_no_forecast := TRUE;
5048              ELSE
5049                l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
5050              END IF;
5051            END IF; /* start date */
5052         ELSE
5053           l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
5054           IF (l_next_index IS NULL) THEN
5055             l_no_forecast := TRUE;
5056           ELSE
5057             l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
5058           END IF;
5059         END IF; /* uom_code */
5060       END LOOP; /* while loop */
5061 
5062       IF (l_no_forecast = TRUE AND l_diff_days <> 0 ) THEN
5063         x_return_value := FALSE;
5064         EXIT;
5065       END IF;
5066 
5067       l_counter_value := Apply_ReverseCounter_Ratio ( l_counter_value,
5068                                                       p_last_due_counter_val_tbl(i).uom_code,
5069                                                       p_counter_rules_tbl);
5070 
5071       -- Add new counter values to return parameter.
5072       x_due_at_counter_val_tbl(i).counter_id := p_last_due_counter_val_tbl(i).counter_id;
5073       x_due_at_counter_val_tbl(i).counter_name := p_last_due_counter_val_tbl(i).counter_name;
5074 
5075       IF (SIGN(p_due_date - p_last_due_date) = -1) THEN
5076           l_counter_value := p_last_due_counter_val_tbl(i).counter_value - l_counter_value;
5077       ELSE
5078           l_counter_value := p_last_due_counter_val_tbl(i).counter_value + l_counter_value;
5079       END IF;
5080 
5081       x_due_at_counter_val_tbl(i).counter_value := l_counter_value;
5082       x_due_at_counter_val_tbl(i).uom_code := p_last_due_counter_val_tbl(i).uom_code;
5083 
5084       -- initialize start date.
5085       IF (SIGN(p_due_date - p_last_due_date) = -1) THEN
5086           l_start_date := p_due_date;
5087       ELSE
5088           l_start_date := p_last_due_date;
5089       END IF;
5090       -- Initialize counter value.
5091       l_counter_value := 0;
5092 
5093       l_diff_days := ABS(trunc(p_due_date) - trunc(p_last_due_date));
5094 
5095     END LOOP; /* for loop */
5096   END IF; /* count */
5097 
5098   IF G_DEBUG = 'Y' THEN
5099         AHL_DEBUG_PUB.Debug('End get_due_at_counter_values');
5100   END IF;
5101 
5102 END Get_Due_At_Counter_Values;
5103 
5104 ---------------------------------------------------------------------------
5105 -- Calculates the due date for the counter_remain from a given start date using forecast,
5106 -- counter rules and counter uom.
5107 
5108 PROCEDURE Get_Date_from_UF ( p_counter_remain IN NUMBER,
5109                              p_counter_uom_code IN VARCHAR2,
5110                              p_counter_rules_tbl IN counter_rules_tbl_type,
5111                              p_start_date IN DATE := NULL,
5112                              x_due_date         OUT NOCOPY DATE)
5113 IS
5114 
5115   l_counter_remain NUMBER := p_counter_remain;
5116   l_forecast_days NUMBER := 0;
5117   l_no_forecast BOOLEAN := FALSE;
5118   l_total_days_in_period NUMBER := 0;
5119   l_index_found BOOLEAN;
5120   l_next_index NUMBER := 0;
5121 
5122   l_start_date DATE;
5123 
5124 BEGIN
5125 
5126   IF G_DEBUG = 'Y' THEN
5127      AHL_DEBUG_PUB.Debug('Start get_date from UF');
5128      AHL_DEBUG_PUB.Debug('counter remain input to forecast' || p_counter_remain );
5129      AHL_DEBUG_PUB.Debug('counter uom' || p_counter_uom_code);
5130      AHL_DEBUG_PUB.Debug('Start date' || p_start_date);
5131   END IF;
5132 
5133   l_counter_remain := trunc(apply_counter_ratio (l_counter_remain,
5134                                                  p_counter_uom_code,
5135                                                  p_counter_rules_tbl));
5136   IF G_DEBUG = 'Y' THEN
5137     AHL_DEBUG_PUB.DEBUG('counter remain after ctr_ratio' || l_counter_remain );
5138   END IF;
5139 
5140   -- Start date to begin calculation.
5141   IF (p_start_date IS NULL) THEN
5142     l_start_date := trunc(sysdate);
5143   ELSE
5144     l_start_date:= p_start_date;
5145   END IF;
5146 
5147   -- Read g_forecast_details_tbl to get forecast values.
5148   l_next_index := G_forecast_details_tbl.FIRST;
5149   IF (l_next_index IS NULL) THEN
5150     --dbms_output.put_line ('l_next_index is null');
5151     x_due_date := null;
5152     RETURN;
5153   ELSE
5154     l_no_forecast := TRUE;
5155     FOR i IN G_forecast_details_tbl.FIRST..G_forecast_details_tbl.LAST LOOP
5156       IF (G_forecast_details_tbl(i).uom_code = p_counter_uom_code) AND
5157          (trunc(G_forecast_details_tbl(i).start_date) <= trunc(l_start_date) AND
5158           trunc(l_start_date) <= trunc(nvl(G_forecast_details_tbl(i).end_date,l_start_date)))
5159       THEN
5160          l_next_index := i;
5161          l_no_forecast := FALSE;
5162          EXIT;
5163       END IF;
5164     END LOOP;
5165   END IF;
5166 
5167    --dbms_output.put_line ('counter remain input to forecast' || l_counter_remain );
5168    --dbms_output.put_line ('counter uom' ||p_counter_uom_code);
5169 
5170   -- Calculate due date.
5171   WHILE ((l_counter_remain <> 0) AND (l_no_forecast <> TRUE )) LOOP
5172      IF (G_forecast_details_tbl(l_next_index).uom_code = p_counter_uom_code) THEN
5173         IF (trunc(G_forecast_details_tbl(l_next_index).start_date) <= trunc(l_start_date) AND
5174             trunc(nvl(G_forecast_details_tbl(l_next_index).end_date,sysdate)) >= trunc(sysdate)) THEN
5175 
5176             IF (G_forecast_details_tbl(l_next_index).end_date) IS NOT NULL THEN
5177                l_total_days_in_period := trunc(G_forecast_details_tbl(l_next_index).end_date - l_start_date) + 1;
5178 
5179                IF (G_forecast_details_tbl(l_next_index).usage_per_day <> 0) THEN
5180                  IF (trunc(l_total_days_in_period * G_forecast_details_tbl(l_next_index).usage_per_day) >= l_counter_remain) THEN
5181                     l_forecast_days := l_forecast_days + trunc(l_counter_remain/G_forecast_details_tbl(l_next_index).usage_per_day);
5182                     l_counter_remain := 0;
5183                  ELSE
5184                     l_counter_remain := l_counter_remain - trunc(l_total_days_in_period * G_forecast_details_tbl(l_next_index).usage_per_day);
5185                     l_forecast_days := l_forecast_days + l_total_days_in_period;
5186 
5187                     -- Get next forecast record.
5188                     l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
5189                     IF (l_next_index IS NULL) THEN
5190                       l_no_forecast := TRUE;
5191                     ELSE
5192                       l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
5193                     END IF;
5194 
5195                  END IF; /* total days */
5196                ELSE -- usage_per_day = 0
5197                  -- Get next forecast record.
5198                  l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
5199                  IF (l_next_index IS NULL) THEN
5200                     l_no_forecast := TRUE;
5201                  ELSE
5202                     l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
5203                  END IF;
5204                END IF; -- usage_per_day <> 0
5205             ELSE
5206                IF (G_forecast_details_tbl(l_next_index).usage_per_day <> 0) THEN
5207                  l_forecast_days := l_forecast_days + trunc(l_counter_remain/G_forecast_details_tbl(l_next_index).usage_per_day);
5208                  l_counter_remain := 0;
5209                ELSE -- usage = 0
5210                  -- Get next forecast record.
5211                  l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
5212                  IF (l_next_index IS NULL) THEN
5213                    l_no_forecast := TRUE;
5214                  ELSE
5215                    l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
5216                  END IF;
5217                END IF; -- usage_per_day <> 0
5218             END IF; /* end date */
5219         END IF; /* start date */
5220      ELSE
5221        l_next_index := G_forecast_details_tbl.NEXT(l_next_index);
5222        IF (l_next_index IS NULL) THEN
5223          l_no_forecast := TRUE;
5224        ELSE
5225          l_start_date := G_forecast_details_tbl(l_next_index).START_DATE;
5226        END IF;
5227      END IF; /* uom_code */
5228 
5229   END LOOP; /* while */
5230 
5231   IF (l_no_forecast = TRUE AND l_counter_remain <> 0) THEN
5232     x_due_date  := null;
5233   ELSE
5234     IF (p_start_date IS NULL) THEN
5235       -- Added condition to avoid due date > 31-dec-9999 when forecast
5236       -- is very less (like .00001, .000001 etc)
5237       IF (l_forecast_days > (to_date('31/12/9999','DD/MM/YYYY') - trunc(sysdate))) THEN
5238           x_due_date  := null;
5239       ELSE
5240           x_due_date := trunc(sysdate + l_forecast_days);
5241       END IF;
5242     ELSE
5243       -- Added condition to avoid due date > 31-dec-9999 when forecast
5244       -- is very less (like .00001, .000001 etc)
5245       IF (l_forecast_days > (to_date('31/12/9999','DD/MM/YYYY') - trunc(p_start_date))) THEN
5246           x_due_date  := null;
5247       ELSE
5248           x_due_date := trunc(p_start_date + l_forecast_days);
5249       END IF;
5250     END IF;
5251   END IF;
5252 
5253   IF G_DEBUG = 'Y' THEN
5254      AHL_DEBUG_PUB.Debug('Date calculated by forecast:' || x_due_date);
5255      AHL_DEBUG_PUB.Debug('End Get_Date_from_UF');
5256   END IF;
5257 
5258 
5259 END Get_Date_from_UF;
5260 
5261 -------------------------------------------------------------------------------
5262 -- This will return the adjusted interval value if the next due counter value
5263 -- overlaps two intervals. It will be used where the overflow condition occurs
5264 -- based on the interval's start value and stop value.
5265 
5266 PROCEDURE Adjust_Interval_Value ( p_mr_effectivity_id IN NUMBER,
5267                                   p_counter_id IN NUMBER,
5268                                   p_counter_value IN NUMBER,
5269                                   p_interval_value IN NUMBER,
5270                                   p_stop_value IN NUMBER,
5271                                   x_adjusted_int_value OUT NOCOPY NUMBER,
5272                                   x_nxt_interval_found OUT NOCOPY BOOLEAN)
5273 IS
5274   -- read intervals for the effectivity id.
5275   CURSOR ahl_mr_intervalvalue_csr (p_mr_effectivity_id IN NUMBER,
5276                                    p_counter_id  IN NUMBER,
5277                                    p_counter_value IN NUMBER) IS
5278      /*
5279 	 SELECT INT.start_value, INT.stop_value,
5280             INT.interval_value
5281      FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
5282      WHERE  INT.counter_id = CTR.counter_id AND
5283             CTR.name = CN.name AND
5284             INT.mr_effectivity_id = p_mr_effectivity_id AND
5285             CN.counter_id = p_counter_id AND
5286             ( nvl(start_value, p_counter_value+1) <= p_counter_value AND
5287               --p_counter_value < nvl(stop_value, p_counter_value)
5288               p_counter_value < nvl(stop_value, p_counter_value + 1)--fix for bug number 3713078
5289             );
5290 	 */
5291 
5292 	 --Priyan
5293 	 --Query being changed due to performance related fixes
5294 	 --Refer Bug # 4918744
5295 
5296 	SELECT
5297 		INT.START_VALUE,
5298 		INT.STOP_VALUE,
5299 		INT.INTERVAL_VALUE
5300 	FROM
5301 		AHL_MR_INTERVALS INT,
5302 		CSI_COUNTER_TEMPLATE_VL CTR,
5303 		--CSI_COUNTER_TEMPLATE_VL CN --bug# 5918525
5304                 csi_counters_vl CN
5305 	WHERE
5306 		 INT.COUNTER_ID = CTR.COUNTER_ID AND
5307 		 --CTR.NAME = CN.NAME AND -- bug# 5918525
5308                  CTR.NAME = CN.counter_template_name AND
5309 		 INT.MR_EFFECTIVITY_ID = P_MR_EFFECTIVITY_ID AND
5310 		 CN.COUNTER_ID = P_COUNTER_ID AND
5311 		 (
5312 			NVL(START_VALUE, P_COUNTER_VALUE +1) <= P_COUNTER_VALUE AND
5313 			P_COUNTER_VALUE < NVL(STOP_VALUE, P_COUNTER_VALUE + 1)
5314 		 ) ;
5315 
5316   l_remaining_ctr_fraction NUMBER;  /* reminder fraction that needs to be interpolated with
5317                                     the interval value of the next mr interval record */
5318   l_overflow_value  NUMBER; /* the counter value that overflows to the next interval. */
5319   l_next_due_counter_value NUMBER;
5320 
5321   -- variables used in cursor fetch.
5322   l_start_value  NUMBER;
5323   l_stop_value NUMBER;
5324   l_interval_value NUMBER;
5325 
5326 BEGIN
5327 
5328   IF G_DEBUG = 'Y' THEN
5329         AHL_DEBUG_PUB.Debug('Start Adjust Interval Value');
5330   END IF;
5331 
5332   IF (p_stop_value IS NULL) THEN
5333     x_adjusted_int_value := p_interval_value;
5334     x_nxt_interval_found := TRUE;
5335   ELSE
5336     l_next_due_counter_value := p_counter_value + p_interval_value;
5337     l_overflow_value := l_next_due_counter_value - p_stop_value;
5338 
5339     x_adjusted_int_value := p_stop_value - p_counter_value;
5340 
5341     l_remaining_ctr_fraction := (l_overflow_value/p_interval_value);
5342 
5343     -- Get next record to match this interval.
5344     OPEN ahl_mr_intervalvalue_csr (p_mr_effectivity_id,
5345                                    p_counter_id,
5346                                    p_stop_value + 1);
5347     FETCH ahl_mr_intervalvalue_csr INTO l_start_value, l_stop_value, l_interval_value;
5348     IF (ahl_mr_intervalvalue_csr%NOTFOUND) THEN
5349 
5350         -- Fix for bug# 3461118.
5351         x_nxt_interval_found := FALSE;
5352         x_adjusted_int_value := p_interval_value;
5353     ELSE
5354         x_nxt_interval_found := TRUE;
5355         x_adjusted_int_value := x_adjusted_int_value + (l_remaining_ctr_fraction * l_interval_value);
5356     END IF; /* end ahl_mr_intervalvalue_csr if */
5357 
5358     CLOSE ahl_mr_intervalvalue_csr;
5359 
5360   END IF; /* p_stop_value if */
5361 
5362   --x_adjusted_int_value := trunc(x_adjusted_int_value);
5363   x_adjusted_int_value := x_adjusted_int_value;
5364 
5365   IF G_DEBUG = 'Y' THEN
5366         AHL_DEBUG_PUB.Debug('End Adjust Interval Value');
5367   END IF;
5368 
5369 
5370 END Adjust_Interval_Value;
5371 
5372 -----------------------------------------------------------------------------
5373 -- This will return the adjusted due date if the next due date overlaps two intervals.
5374 -- It will be used where the overflow condition occurs based on the interval's start
5375 -- date and stop date.
5376 
5377 PROCEDURE Adjust_Due_Date ( p_mr_effectivity_id IN NUMBER,
5378                             p_start_counter_rec IN counter_values_rec_type,
5379                             p_start_due_date    IN DATE,
5380                             p_counter_rules_tbl IN counter_rules_tbl_type,
5381                             p_interval_value IN NUMBER,
5382                             p_stop_date IN DATE,
5383                             p_due_date IN DATE,
5384                             x_adjusted_due_date OUT NOCOPY DATE,
5385                             x_adjusted_due_ctr  OUT NOCOPY NUMBER,
5386                             x_nxt_interval_found OUT NOCOPY BOOLEAN)
5387 
5388 IS
5389 
5390   l_return_val BOOLEAN;
5391 
5392   l_start_counter_tbl counter_values_tbl_type;
5393   l_stop_counter_tbl  counter_values_tbl_type;
5394 
5395   l_forecast_days NUMBER;
5396   l_temp_due_date DATE;
5397   l_next_due_counter_remain NUMBER;
5398   l_remaining_ctr_fraction NUMBER;
5399 --  l_remaining_ctr_value NUMBER;
5400 
5401   l_start_date DATE;
5402   l_stop_date  DATE;
5403   l_interval_value NUMBER;
5404   l_adjusted_due_ctr NUMBER;
5405 
5406   -- get the next interval record for the provided stop value.
5407   CURSOR ahl_mr_intervaldate_csr (p_mr_effectivity_id IN NUMBER,
5408                                   p_counter_id  IN NUMBER,
5409                                   p_stop_date   IN DATE) IS
5410     /* SELECT INT.start_date, INT.stop_date,
5411             INT.interval_value
5412      FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
5413      WHERE  INT.counter_id = CTR.counter_id AND
5414             CTR.name = CN.name AND
5415             INT.mr_effectivity_id = p_mr_effectivity_id AND
5416             CN.counter_id = p_counter_id AND
5417             trunc(INT.start_date) = trunc(p_stop_date);
5418 	*/
5419 
5420 	 --Priyan
5421 	 --Query being changed due to performance related fixes
5422 	 --Refer Bug # 4918744
5423 	 --Changes the usage of CS_COUNTERS_V to CSI_COUNTER_TEMPLATE_VL
5424 
5425 	SELECT
5426 	   INT.START_DATE,
5427 	   INT.STOP_DATE,
5428 	   INT.INTERVAL_VALUE
5429 	FROM
5430 	   AHL_MR_INTERVALS INT,
5431 	   CSI_COUNTER_TEMPLATE_VL CTR,
5432 	   --CSI_COUNTER_TEMPLATE_VL CN --bug# 5918525
5433            csi_counters_vl CN
5434 	WHERE
5435 	   INT.COUNTER_ID = CTR.COUNTER_ID
5436 	   --AND CTR.NAME = CN.NAME --bug# 5918525
5437            AND CTR.NAME = CN.counter_template_name
5438 	   AND INT.MR_EFFECTIVITY_ID = P_MR_EFFECTIVITY_ID
5439 	   AND CN.COUNTER_ID = P_COUNTER_ID
5440 	   AND TRUNC(INT.START_DATE) = TRUNC(P_STOP_DATE) ;
5441 
5442 BEGIN
5443 
5444   IF G_DEBUG = 'Y' THEN
5445         AHL_DEBUG_PUB.Debug('Start Adjust Due Date');
5446   END IF;
5447 
5448   IF (trunc(p_due_date) <= trunc(p_stop_date)) THEN
5449     x_adjusted_due_date := p_due_date;
5450     x_nxt_interval_found := TRUE;
5451   ELSE
5452     l_start_counter_tbl(1) := p_start_counter_rec;
5453 
5454     -- Get counter values for stop date.
5455     Get_Due_At_Counter_Values (p_last_due_date => p_start_due_date,
5456                                p_last_due_counter_val_tbl => l_start_counter_tbl,
5457                                p_due_date => p_stop_date,
5458                                p_counter_rules_tbl => p_counter_rules_tbl,
5459                                x_due_at_counter_val_tbl => l_stop_counter_tbl,
5460                                x_return_value  => l_return_val);
5461 
5462     IF NOT(l_return_val) THEN
5463       x_adjusted_due_date := p_due_date;
5464       x_nxt_interval_found := FALSE;
5465     ELSE
5466       l_next_due_counter_remain := l_stop_counter_tbl(1).counter_value - p_start_counter_rec.counter_value;
5467       l_adjusted_due_ctr := l_next_due_counter_remain;
5468       l_remaining_ctr_fraction := 1 - (l_next_due_counter_remain/p_interval_value);
5469 
5470       -- Get next record to match this interval.
5471 
5472       OPEN ahl_mr_intervalDate_csr (p_mr_effectivity_id,
5473                                      p_start_counter_rec.counter_id,
5474                                      p_stop_date+1);
5475       FETCH ahl_mr_intervalDate_csr INTO l_start_date, l_stop_date, l_interval_value;
5476       IF (ahl_mr_intervalDate_csr%NOTFOUND) THEN
5477           -- Fix for bug# 3461118.
5478           x_adjusted_due_date := p_due_date;
5479           x_nxt_interval_found := FALSE;
5480       ELSE
5481 
5482           l_next_due_counter_remain := trunc(l_remaining_ctr_fraction * l_interval_value);
5483           x_nxt_interval_found := TRUE;
5484 
5485           -- Based on forecast get the due date.
5486           Get_Date_from_UF ( p_counter_remain => l_next_due_counter_remain,
5487                              p_counter_uom_code => p_start_counter_rec.uom_code,
5488                              p_counter_rules_tbl => p_counter_rules_tbl,
5489                              p_start_date => p_stop_date,
5490                              x_due_date => l_temp_due_date );
5491           -- l_temp_due_date is with respect to sysdate.
5492           IF (l_temp_due_date IS NULL) THEN
5493             x_adjusted_due_date := p_due_date;
5494           ELSE
5495             x_adjusted_due_date := l_temp_due_date;
5496             x_adjusted_due_ctr  := l_adjusted_due_ctr + l_next_due_counter_remain;
5497           END IF;
5498       END IF; /* end ahl_mr_intervalDate_csr if */
5499       CLOSE ahl_mr_intervalDate_csr;
5500     END IF;
5501   END IF;
5502 
5503   IF G_DEBUG = 'Y' THEN
5504         AHL_DEBUG_PUB.Debug('End Adjust Interval Value');
5505   END IF;
5506 
5507 
5508 END Adjust_Due_Date;
5509 
5510 -----------------------------------------------------------------------------
5511 -- This procedure will return due date based on the next interval(if exists),
5512 -- whenever an interval is not found for the current start/stop values or dates.
5513 -- Added parameter p_dependent_mr_flag to fix bug# 6711228.
5514 -- Added parameter p_mr_accomplish_exists and p_last_due_mr_interval_id to fix
5515 -- bug# 6858788. Commented p_last_accomplishment_date and will instead use p_mr_accomplish_exists.
5516 PROCEDURE Get_DueDate_from_NxtInterval(p_applicable_mrs_rec       IN  applicable_mrs_rec_type,
5517                                        p_repetivity_flag          IN  VARCHAR2,
5518                                        p_mr_effectivity_id        IN  NUMBER,
5519                                        p_current_ctr_rec          IN  Counter_values_rec_type,
5520                                        p_current_ctr_at_date      IN  DATE,
5521                                        p_counter_rules_tbl        IN  Counter_rules_tbl_type,
5522                                        p_start_int_match_at_ctr   IN  NUMBER,
5523                                        p_last_accomplish_ctr_val  IN  NUMBER,
5524                                        --p_last_accomplishment_date IN  DATE,
5525                                        p_dependent_mr_flag        IN  BOOLEAN,
5526                                        p_mr_accomplish_exists     IN  BOOLEAN,
5527                                        p_last_due_mr_interval_id  IN  NUMBER,
5528                                        x_next_due_date_rec        OUT NOCOPY next_due_date_rec_type,
5529                                        x_mr_interval_found        OUT NOCOPY BOOLEAN,
5530                                        x_return_val               OUT NOCOPY BOOLEAN)
5531 IS
5532 
5533   CURSOR ahl_next_interval_ctr_csr (p_mr_effectivity_id IN NUMBER,
5534                                     --p_counter_id        IN NUMBER,
5535                                     p_counter_name      IN VARCHAR2,
5536                                     p_counter_value     IN NUMBER) IS
5537     /*
5538 	SELECT  INT.mr_interval_id, INT.start_date, INT.stop_date,
5539             INT.start_value, INT.stop_value, INT.counter_id,
5540             INT.interval_value, INT.tolerance_after, INT.tolerance_before
5541      -- Replaced cs_counters_v with cs_counters to fix perf bug# 3786647.
5542      --FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
5543      FROM   ahl_mr_intervals INT, cs_counters CTR, cs_counters CN
5544      WHERE  INT.counter_id = CTR.counter_id AND
5545             CTR.name = CN.name AND
5546             INT.mr_effectivity_id = p_mr_effectivity_id AND
5547             CN.counter_id = p_counter_id AND
5548             INT.start_value > p_counter_value
5549      ORDER BY INT.start_value;
5550 	*/
5551 
5552 	 --Priyan
5553 	 --Query being changed due to performance related fixes
5554 	 --Refer Bug # 4918744
5555 	 --Changes the usage of CS_COUNTERS_V to CSI_COUNTER_TEMPLATE_VL
5556      -- select first row only.
5557      SELECT *
5558      FROM (
5559 	  SELECT
5560 	   INT.MR_INTERVAL_ID,
5561 	   INT.START_DATE,
5562   	   INT.STOP_DATE,
5563 	   INT.START_VALUE,
5564 	   INT.STOP_VALUE,
5565 	   INT.COUNTER_ID,
5566 	   INT.INTERVAL_VALUE,
5567 	   INT.TOLERANCE_AFTER,
5568 	   INT.TOLERANCE_BEFORE,
5569            INT.EARLIEST_DUE_VALUE
5570 	  FROM
5571 	   AHL_MR_INTERVALS INT,
5572 	   CSI_COUNTER_TEMPLATE_VL CTR --,
5573 	   --CSI_COUNTER_TEMPLATE_VL CN --bug# 5918525
5574            --csi_counters_vl CN
5575 	  WHERE
5576 	   INT.COUNTER_ID = CTR.COUNTER_ID
5577 	   -- AND CTR.NAME = CN.NAME --bug# 5918525
5578            --AND CTR.NAME = CN.counter_template_name
5579            AND CTR.NAME = p_counter_name
5580 	   AND INT.MR_EFFECTIVITY_ID = P_MR_EFFECTIVITY_ID
5581 	   --AND CN.COUNTER_ID = P_COUNTER_ID
5582 	   AND INT.START_VALUE > P_COUNTER_VALUE
5583 	  ORDER BY
5584 	   INT.START_VALUE ASC
5585           )
5586      WHERE ROWNUM < 2;
5587 
5588   CURSOR ahl_next_interval_date_csr (p_mr_effectivity_id IN NUMBER,
5589                                      --p_counter_id        IN NUMBER,
5590                                      p_counter_name      IN VARCHAR2,
5591                                      p_start_date        IN DATE) IS
5592 
5593     /*SELECT  INT.mr_interval_id, INT.start_date, INT.stop_date,
5594             INT.tolerance_after, INT.tolerance_before, INT.interval_value
5595      -- Replaced cs_counters_v with cs_counters to fix perf bug# 3786647.
5596      --FROM   ahl_mr_intervals INT, cs_counters_v CTR, cs_counters_v CN
5597      FROM   ahl_mr_intervals INT, cs_counters CTR, cs_counters CN
5598      WHERE  INT.counter_id = CTR.counter_id AND
5599             CTR.name = CN.name AND
5600             INT.mr_effectivity_id = p_mr_effectivity_id AND
5601             CN.counter_id = p_counter_id AND
5602             INT.start_date > p_start_date
5603      ORDER BY INT.start_date;
5604 	*/
5605 
5606 	--Priyan
5607 	 --Query being changed due to performance related fixes
5608 	 --Refer Bug # 4918744
5609 	 --Changes the usage of CS_COUNTERS_V to CSI_COUNTER_TEMPLATE_VL
5610      -- select first row only.
5611      SELECT *
5612      FROM (
5613 	  SELECT
5614 	   INT.MR_INTERVAL_ID,
5615 	   INT.START_DATE,
5616 	   INT.STOP_DATE,
5617 	   INT.TOLERANCE_AFTER,
5618 	   INT.TOLERANCE_BEFORE,
5619 	   INT.INTERVAL_VALUE,
5620            INT.EARLIEST_DUE_VALUE
5621 	  FROM
5622 	   AHL_MR_INTERVALS INT,
5623 	   CSI_COUNTER_TEMPLATE_VL CTR --,
5624 	   --CSI_COUNTER_TEMPLATE_VL CN --bug# 5918525
5625            --csi_counters_vl CN
5626 	  WHERE
5627 	   INT.COUNTER_ID = CTR.COUNTER_ID
5628 	   --AND CTR.NAME = CN.NAME --bug# 5918525
5629            --AND CTR.NAME = CN.counter_template_name
5630            AND CTR.NAME = p_counter_name
5631 	   AND INT.MR_EFFECTIVITY_ID = P_MR_EFFECTIVITY_ID
5632 	   --AND CN.COUNTER_ID = P_COUNTER_ID
5633 	   AND INT.START_DATE > P_START_DATE
5634 	  ORDER BY
5635 	   INT.START_DATE ASC
5636           )
5637      WHERE ROWNUM < 2;
5638 
5639 
5640   l_counter_remain          NUMBER;
5641   l_counter_due_date        DATE; -- due date calculated using start-value of interval.
5642   l_current_ctr_tbl         counter_values_tbl_type;
5643   l_next_interval_ctr_rec   ahl_next_interval_ctr_csr%ROWTYPE;
5644   l_next_interval_date_rec  ahl_next_interval_date_csr%ROWTYPE;
5645   l_return_val              BOOLEAN;
5646   l_due_counter_tbl         counter_values_tbl_type;
5647   l_ctr_based               BOOLEAN; -- indicates if due date is based on start-value of interval.
5648   l_date_based              BOOLEAN; -- indicates if due date is based on start-date of interval.
5649 
5650   l_date_due_date           DATE;
5651   l_due_at_counter          NUMBER;
5652 
5653   l_mr_interval_found       BOOLEAN := FALSE; -- set to true if a future interval is found.
5654 
5655   -- Added to fix bug#4224867.
5656   l_date_based_counter_remain  NUMBER;
5657   l_ctr_based_counter_remain   NUMBER;
5658 
5659   -- Added to fix bug# 6358940.
5660   l_next_due_date_rec          next_due_date_rec_type;
5661   l_ctr_due_at_counter_value   NUMBER;
5662 
5663 BEGIN
5664 
5665    IF G_DEBUG = 'Y' THEN
5666         AHL_DEBUG_PUB.Debug('Start Get_DueDate_from_NxtInterval');
5667         AHL_DEBUG_PUB.Debug('Input Counter ID:' || p_current_ctr_rec.counter_id);
5668         AHL_DEBUG_PUB.Debug('Input Counter Name:' || p_current_ctr_rec.counter_name);
5669         AHL_DEBUG_PUB.Debug('Input Counter start value:' || p_start_int_match_at_ctr);
5670    END IF;
5671 
5672    -- Initialize.
5673    x_return_val := TRUE;
5674    l_ctr_based  := FALSE; -- indicates if due date is based on start-value of interval.
5675    l_date_based := FALSE; -- indicates if due date is based on start-date of interval.
5676 
5677    -- initialize.
5678    x_next_due_date_rec := l_next_due_date_rec;
5679 
5680    -- Find interval greater than the counter value.
5681    OPEN ahl_next_interval_ctr_csr(p_mr_effectivity_id,
5682                                   --p_current_ctr_rec.counter_id,
5683                                   p_current_ctr_rec.counter_name,
5684                                   p_start_int_match_at_ctr);
5685    FETCH ahl_next_interval_ctr_csr INTO l_next_interval_ctr_rec;
5686    IF (ahl_next_interval_ctr_csr%FOUND) THEN
5687      l_mr_interval_found := TRUE;
5688 
5689      l_counter_remain := l_next_interval_ctr_rec.start_value - p_current_ctr_rec.counter_value;
5690      l_ctr_due_at_counter_value := l_next_interval_ctr_rec.start_value;
5691 
5692      -- Added to fix bug# 6358940
5693      -- here start value will not be a null value.
5694      IF (l_next_interval_ctr_rec.earliest_due_value IS NOT NULL
5695        AND p_repetivity_flag = 'N') THEN
5696         IF (p_mr_accomplish_exists = TRUE AND p_dependent_mr_flag = FALSE) THEN
5697           -- MR accomplishment exists.
5698           IF (p_last_accomplish_ctr_val >= l_next_interval_ctr_rec.earliest_due_value) THEN
5699              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
5700                                  - p_current_ctr_rec.counter_value;
5701              l_ctr_due_at_counter_value := p_last_accomplish_ctr_val
5702                                            + l_next_interval_ctr_rec.interval_value;
5703 
5704           END IF;
5705         END IF;
5706      ELSIF (l_next_interval_ctr_rec.earliest_due_value IS NULL AND p_repetivity_flag = 'N' AND
5707             p_mr_accomplish_exists = TRUE AND p_dependent_mr_flag = FALSE) THEN
5708              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
5709                                  - p_current_ctr_rec.counter_value;
5710              l_ctr_due_at_counter_value := p_last_accomplish_ctr_val
5711                                            + l_next_interval_ctr_rec.interval_value;
5712 
5713      END IF;
5714 
5715      -- Added to fix bug# 6858788(for repetity).
5716      IF (p_repetivity_flag = 'Y' AND p_last_due_mr_interval_id = l_next_interval_ctr_rec.mr_interval_id) THEN
5717             -- same interval threshold as previous due date calculation. Use
5718             -- interval value rather than start value.
5719              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
5720                                  - p_current_ctr_rec.counter_value;
5721              l_ctr_due_at_counter_value := p_last_accomplish_ctr_val
5722                                            + l_next_interval_ctr_rec.interval_value;
5723      -- case where last and current triggered intervals do not match. Ex: where group MR triggers.
5724      ELSIF (p_repetivity_flag = 'Y' AND l_next_interval_ctr_rec.earliest_due_value IS NOT NULL) THEN
5725          IF (p_last_accomplish_ctr_val >= l_next_interval_ctr_rec.earliest_due_value) THEN
5726             l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
5727                                 - p_current_ctr_rec.counter_value;
5728             l_ctr_due_at_counter_value := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value;
5729          END IF;
5730      ELSIF (p_repetivity_flag = 'Y' AND l_next_interval_ctr_rec.earliest_due_value IS NULL) THEN
5731           l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value
5732                               - p_current_ctr_rec.counter_value;
5733           l_ctr_due_at_counter_value := p_last_accomplish_ctr_val + l_next_interval_ctr_rec.interval_value;
5734 
5735      END IF;
5736 
5737      IF G_DEBUG = 'Y' THEN
5738        AHL_DEBUG_PUB.Debug('Found future interval with start value:' || l_next_interval_ctr_rec.start_value);
5739        AHL_DEBUG_PUB.Debug('Last due interval ID:' || p_last_due_mr_interval_id);
5740        AHL_DEBUG_PUB.Debug('Current interval ID:' || l_next_interval_ctr_rec.mr_interval_id);
5741        AHL_DEBUG_PUB.Debug('p_last_accomplish_ctr_val:' || p_last_accomplish_ctr_val);
5742        AHL_DEBUG_PUB.Debug('p_current_ctr_rec.counter_value:' || p_current_ctr_rec.counter_value);
5743        AHL_DEBUG_PUB.Debug('l_next_interval_date_rec.interval_value:' || l_next_interval_ctr_rec.interval_value);
5744        AHL_DEBUG_PUB.Debug('counter remain:' || l_counter_remain);
5745      END IF;
5746 
5747      -- l_counter_remain can be negative. Fix bug# 6739599.
5748      IF (l_counter_remain > 0) THEN
5749         -- calculate due date based on forecast.
5750         get_date_from_uf(l_counter_remain,
5751                          p_current_ctr_rec.uom_code,
5752                          p_counter_rules_tbl,
5753                          p_current_ctr_at_date,
5754                          l_counter_due_date);
5755      ELSIF (l_counter_remain = 0) THEN
5756         l_counter_due_date := trunc(sysdate);
5757      ELSIF (l_counter_remain < 0) THEN
5758         -- Due date = counter reading date.
5759         get_ctr_date_for_reading (p_csi_item_instance_id => p_applicable_mrs_rec.csi_item_instance_id,
5760                                   p_counter_id           => p_current_ctr_rec.counter_id,
5761                                   p_counter_value        => l_ctr_due_at_counter_value,
5762                                   x_ctr_record_date      => l_counter_due_date,
5763                                   x_return_val           => l_return_val);
5764         IF NOT(l_return_val) THEN
5765           l_counter_due_date := trunc(sysdate);
5766         END IF;
5767 
5768      END IF;
5769 
5770      --dbms_output.put_line ('due date by forecast' || l_due_date );
5771 
5772      /* commented to fix bug# 6907562.
5773      -- Check the due date value.
5774      IF (l_counter_due_date IS NULL) THEN
5775         CLOSE ahl_next_interval_ctr_csr;
5776         x_return_val := FALSE;
5777         RETURN;
5778      END IF;
5779      */
5780 
5781      -- fix bug# 4224867.
5782      l_ctr_based_counter_remain := l_counter_remain;
5783 
5784    END IF; -- ahl_next_ctr_interval_csr found.
5785 
5786    -- Now check for existence of interval, based on date range.
5787    OPEN ahl_next_interval_date_csr(p_mr_effectivity_id,
5788                                    --p_current_ctr_rec.counter_id,
5789                                    p_current_ctr_rec.counter_name,
5790                                    p_current_ctr_at_date);
5791    FETCH ahl_next_interval_date_csr INTO l_next_interval_date_rec;
5792    IF (ahl_next_interval_date_csr%FOUND) THEN
5793      l_mr_interval_found := TRUE;
5794 
5795      -- Added to fix bug# 6358940
5796      -- here start date will not be a null value.
5797      IF (l_next_interval_date_rec.earliest_due_value IS NOT NULL AND p_repetivity_flag = 'N') AND
5798         (p_mr_accomplish_exists = TRUE AND p_dependent_mr_flag = FALSE) AND -- MR accomplishment exists.
5799         (p_last_accomplish_ctr_val >= l_next_interval_date_rec.earliest_due_value) THEN
5800              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
5801                                  - p_current_ctr_rec.counter_value;
5802              l_due_at_counter := p_last_accomplish_ctr_val
5803                                  + l_next_interval_date_rec.interval_value;
5804 
5805      ELSIF (l_next_interval_date_rec.earliest_due_value IS NULL AND p_repetivity_flag = 'N' AND
5806             p_mr_accomplish_exists = TRUE AND p_dependent_mr_flag = FALSE) THEN
5807              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
5808                                  - p_current_ctr_rec.counter_value;
5809              l_due_at_counter := p_last_accomplish_ctr_val
5810                                  + l_next_interval_date_rec.interval_value;
5811 
5812      -- added to fix bug# 6858788(consider repetivity = Y).
5813      ELSIF (p_repetivity_flag = 'Y' AND p_last_due_mr_interval_id = l_next_interval_date_rec.mr_interval_id) THEN
5814             -- same interval threshold as previous due date calculation. Use
5815             -- interval value rather than start value.
5816              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
5817                                  - p_current_ctr_rec.counter_value;
5818              l_due_at_counter := p_last_accomplish_ctr_val
5819                                  + l_next_interval_date_rec.interval_value;
5820      -- added to fix bug# 6858788(consider repetivity = Y) where last and current interval triggered
5821      -- are not the same..
5822      ELSIF (l_next_interval_date_rec.earliest_due_value IS NOT NULL AND p_repetivity_flag = 'Y') AND
5823            (p_last_accomplish_ctr_val >= l_next_interval_date_rec.earliest_due_value) THEN
5824              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
5825                                  - p_current_ctr_rec.counter_value;
5826              l_due_at_counter := p_last_accomplish_ctr_val
5827                                  + l_next_interval_date_rec.interval_value;
5828      ELSIF (l_next_interval_date_rec.earliest_due_value IS NULL AND p_repetivity_flag = 'Y') THEN
5829              l_counter_remain := p_last_accomplish_ctr_val + l_next_interval_date_rec.interval_value
5830                                  - p_current_ctr_rec.counter_value;
5831              l_due_at_counter := p_last_accomplish_ctr_val
5832                                  + l_next_interval_date_rec.interval_value;
5833 
5834      ELSE
5835         --IF (ahl_next_interval_ctr_csr%FOUND) THEN
5836         -- Find the counter value as of l_next_interval_date_rec.start_date.
5837         l_current_ctr_tbl(1) := p_current_ctr_rec;
5838         Get_Due_At_Counter_Values (p_last_due_date => p_current_ctr_at_date,
5839                                    p_last_due_counter_val_tbl => l_current_ctr_tbl,
5840                                    p_due_date => l_next_interval_date_rec.start_date,
5841                                    p_counter_rules_tbl => p_counter_rules_tbl,
5842                                    x_due_at_counter_val_tbl => l_due_counter_tbl,
5843                                    x_return_value  => l_return_val);
5844         IF NOT(l_return_val) THEN
5845           CLOSE ahl_next_interval_date_csr;
5846           CLOSE ahl_next_interval_ctr_csr;
5847           -- set return values.
5848           x_return_val := FALSE;
5849           x_next_due_date_rec.due_date := l_counter_due_date;
5850           x_next_due_date_rec.tolerance_after := l_next_interval_ctr_rec.tolerance_after;
5851           x_next_due_date_rec.tolerance_before := l_next_interval_ctr_rec.tolerance_before;
5852           x_next_due_date_rec.mr_interval_id := l_next_interval_ctr_rec.mr_interval_id;
5853           x_next_due_date_rec.due_at_counter_value := null;
5854           x_next_due_date_rec.counter_remain := null;
5855 
5856           x_mr_interval_found := l_mr_interval_found;
5857 
5858           RETURN;
5859         END IF;
5860 
5861         -- Add interval to the counter value and get the due date for this.
5862         -- 11/01/07: due date should be l_next_interval_date_rec.start_date.
5863         l_counter_remain := l_due_counter_tbl(1).counter_value
5864                             -- + l_next_interval_date_rec.interval_value
5865                             - p_current_ctr_rec.counter_value;
5866 
5867         l_due_at_counter := l_due_counter_tbl(1).counter_value;
5868                             --+ l_next_interval_date_rec.interval_value;
5869 
5870      END IF;
5871 
5872      IF G_DEBUG = 'Y' THEN
5873        AHL_DEBUG_PUB.Debug('Found future interval with start date:' || to_char(l_next_interval_date_rec.start_date,'DD-MON-YYYY'));
5874        AHL_DEBUG_PUB.Debug('counter remain:' || l_counter_remain);
5875        AHL_DEBUG_PUB.Debug('l_ctr_due_at_counter_value:' || l_ctr_due_at_counter_value);
5876        AHL_DEBUG_PUB.Debug('p_last_accomplish_ctr_val:' || p_last_accomplish_ctr_val);
5877        AHL_DEBUG_PUB.Debug('earliest_due_value:' || l_next_interval_date_rec.earliest_due_value);
5878      END IF;
5879 
5880      -- calculate due date based on forecast.
5881      get_date_from_uf(l_counter_remain,
5882                       p_current_ctr_rec.uom_code,
5883                       p_counter_rules_tbl,
5884                       p_current_ctr_at_date,
5885                       l_date_due_date);
5886 
5887      --dbms_output.put_line ('due date by forecast' || l_date_due_date );
5888 
5889      /* commented to fix bug# 6907562.
5890      -- Check the due date value.
5891      IF (l_date_due_date IS NULL) THEN
5892         CLOSE ahl_next_interval_ctr_csr;
5893         x_return_val := FALSE;
5894         RETURN;
5895      END IF;
5896      */
5897 
5898      -- fix bug# 4224867.
5899      l_date_based_counter_remain := l_counter_remain;
5900 
5901      IF (ahl_next_interval_ctr_csr%FOUND) THEN
5902        -- Pick one of l_date_due_date OR l_counter_due_date
5903        -- as the due_date based on whichever_first_code.
5904        -- Added null due date checks to fix bug# 6907562.
5905        IF (l_counter_due_date IS NULL OR l_date_due_date IS NULL) THEN
5906           IF (validate_for_duedate_reset(l_date_due_date,
5907                                      l_date_based_counter_remain,
5908                                      l_counter_due_date,
5909                                      p_current_ctr_rec.counter_id,
5910                                      l_ctr_based_counter_remain) = 'Y') THEN
5911              l_date_based := TRUE;
5912           ELSE
5913              l_ctr_based  := TRUE;
5914           END IF;
5915        ELSE
5916 
5917           IF (p_applicable_mrs_rec.whichever_first_code = 'FIRST') THEN
5918             IF (l_counter_due_date <= l_date_due_date) THEN
5919                l_ctr_based := TRUE;
5920             ELSE
5921                l_date_based := TRUE;
5922             END IF;
5923           ELSE --whichever_first_code = 'LAST'
5924             IF (l_counter_due_date < l_date_due_date) THEN
5925               l_date_based := TRUE;
5926             ELSE
5927               l_ctr_based := TRUE;
5928             END IF;
5929           END IF; -- whichever first code.
5930        END IF; -- l_counter_due_date IS NULL
5931      ELSE
5932        -- Here due_date = start_date counter + interval.
5933        l_date_based := TRUE;
5934      END IF; -- ahl_next_interval_ctr_csr.
5935    ELSIF (ahl_next_interval_ctr_csr%FOUND) THEN
5936      l_ctr_based := TRUE;
5937    END IF; -- ahl_next_interval_date_csr.
5938 
5939    CLOSE ahl_next_interval_ctr_csr;
5940    CLOSE ahl_next_interval_date_csr;
5941 
5942    -- set output parameters.
5943    IF (l_ctr_based) THEN
5944      x_next_due_date_rec.due_date := l_counter_due_date;
5945      x_next_due_date_rec.tolerance_after := l_next_interval_ctr_rec.tolerance_after;
5946      x_next_due_date_rec.tolerance_before := l_next_interval_ctr_rec.tolerance_before;
5947      x_next_due_date_rec.mr_interval_id := l_next_interval_ctr_rec.mr_interval_id;
5948      --x_next_due_date_rec.due_at_counter_value := l_next_interval_ctr_rec.start_value;
5949      x_next_due_date_rec.due_at_counter_value := l_ctr_due_at_counter_value;
5950      x_next_due_date_rec.counter_remain := l_ctr_based_counter_remain;
5951 
5952      /* commenting this out as this causes next repetity to be over interval
5953       * value (fix for bug# 6858788)
5954      -- Fix for bug# 6739599. l_counter_due_date can be a past date.
5955      IF (l_counter_due_date > trunc(sysdate)) THEN
5956        -- Check if the counter value on the due date is less than the due counter value.
5957        -- If less, add a day to the due date. This would ensure that the MR is performed not before
5958        -- the due counter value.
5959        l_current_ctr_tbl(1) := p_current_ctr_rec;
5960        Get_Due_At_Counter_Values (p_last_due_date => p_current_ctr_at_date,
5961                                   p_last_due_counter_val_tbl => l_current_ctr_tbl,
5962                                   p_due_date => l_counter_due_date,
5963                                   p_counter_rules_tbl => p_counter_rules_tbl,
5964                                   x_due_at_counter_val_tbl => l_due_counter_tbl,
5965                                   x_return_value  => l_return_val);
5966 
5967        IF (l_due_counter_tbl(1).counter_value < l_next_interval_ctr_rec.start_value) THEN
5968           l_counter_due_date := l_counter_due_date + 1;
5969           Get_Due_At_Counter_Values (p_last_due_date => p_current_ctr_at_date,
5970                                      p_last_due_counter_val_tbl => l_current_ctr_tbl,
5971                                      p_due_date => l_counter_due_date,
5972                                      p_counter_rules_tbl => p_counter_rules_tbl,
5973                                      x_due_at_counter_val_tbl => l_due_counter_tbl,
5974                                      x_return_value  => l_return_val);
5975           IF NOT(l_return_val) THEN  -- forecast not available.
5976             x_return_val := FALSE;
5977             RETURN;
5978           END IF;
5979 
5980           --x_next_due_date_rec.due_at_counter_value := l_due_counter_tbl(1).counter_value;
5981           x_next_due_date_rec.due_date := l_counter_due_date;
5982        END IF;
5983      END IF; -- l_counter_due_date > trunc(sysdate)
5984      */
5985    ELSIF (l_date_based) THEN
5986 
5987      x_next_due_date_rec.due_date := l_date_due_date;
5988      x_next_due_date_rec.tolerance_after := l_next_interval_date_rec.tolerance_after;
5989      x_next_due_date_rec.tolerance_before := l_next_interval_date_rec.tolerance_before;
5990      x_next_due_date_rec.mr_interval_id := l_next_interval_date_rec.mr_interval_id;
5991      x_next_due_date_rec.due_at_counter_value := l_due_at_counter;
5992      x_next_due_date_rec.counter_remain := l_date_based_counter_remain;
5993    END IF;
5994 
5995    x_mr_interval_found := l_mr_interval_found;
5996 
5997    IF G_DEBUG = 'Y' THEN
5998         AHL_DEBUG_PUB.Debug('End Get_DueDate_from_NxtInterval');
5999    END IF;
6000 
6001 END Get_DueDate_from_NxtInterval;
6002 
6003 -----------------------------------------------------------------------------
6004 -- Apply the counter ratio factor to convert a given counter value at a
6005 -- component level to the root instance. This is needed as forecast is only
6006 -- defined at root instance.
6007 
6008 FUNCTION Apply_Counter_Ratio ( p_counter_remain IN NUMBER,
6009                                p_counter_uom_code IN VARCHAR2,
6010                                p_counter_rules_tbl IN counter_rules_tbl_type)
6011 RETURN NUMBER IS
6012 
6013   l_counter_remain NUMBER := p_counter_remain;
6014 
6015 BEGIN
6016 
6017   IF G_DEBUG = 'Y' THEN
6018      AHL_DEBUG_PUB.Debug('Start Apply Counter Ratio');
6019   END IF;
6020 
6021   -- Loop through p_counter_rules_tbl.
6022   IF (p_counter_rules_tbl.COUNT > 0) THEN
6023     FOR i IN p_counter_rules_tbl.FIRST..p_counter_rules_tbl.LAST LOOP
6024       IF (p_counter_rules_tbl(i).uom_code = p_counter_uom_code) THEN
6025          l_counter_remain := p_counter_remain / p_counter_rules_tbl(i).ratio;
6026       END IF;
6027     END LOOP;
6028   END IF;
6029 
6030   IF G_DEBUG = 'Y' THEN
6031      AHL_DEBUG_PUB.Debug('End Apply Counter Ratio');
6032   END IF;
6033 
6034   RETURN l_counter_remain;
6035 
6036 END Apply_Counter_Ratio;
6037 
6038 -------------------------------------------------------------------------------
6039 -- Apply the counter ratio factor to convert a given counter value at a root
6040 -- instance level to the component. This is needed as forecast is only defined
6041 -- at root instance.
6042 
6043 FUNCTION Apply_ReverseCounter_Ratio ( p_counter_remain IN NUMBER,
6044                                       p_counter_uom_code IN VARCHAR2,
6045                                       p_counter_rules_tbl IN counter_rules_tbl_type)
6046 RETURN NUMBER IS
6047 
6048   l_counter_remain NUMBER := p_counter_remain;
6049 
6050 BEGIN
6051 
6052   IF G_DEBUG = 'Y' THEN
6053      AHL_DEBUG_PUB.Debug('Start Apply Reverse Counter Ratio');
6054   END IF;
6055 
6056 
6057   -- Loop through p_counter_rules_tbl.
6058   IF (p_counter_rules_tbl.COUNT > 0) THEN
6059     FOR i IN p_counter_rules_tbl.FIRST..p_counter_rules_tbl.LAST LOOP
6060       IF (p_counter_rules_tbl(i).uom_code = p_counter_uom_code) THEN
6061          l_counter_remain := p_counter_remain * p_counter_rules_tbl(i).ratio;
6062       END IF;
6063     END LOOP;
6064   END IF;
6065 
6066   IF G_DEBUG = 'Y' THEN
6067      AHL_DEBUG_PUB.Debug('End Apply Reverse Counter Ratio');
6068   END IF;
6069 
6070   RETURN l_counter_remain;
6071 
6072 END Apply_ReverseCounter_Ratio;
6073 
6074 ------------------------------------------------------------------------------
6075 -- To process the decendents in case the mr is a group MR.
6076 
6077 PROCEDURE Process_GroupMR (p_applicable_mrs_rec  IN applicable_mrs_rec_type,
6078                            p_new_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE,
6079                            p_unit_effectivity_tbl IN unit_effectivity_tbl_type,
6080                            p_old_UE_forecast_sequence IN NUMBER := -1)
6081 
6082 IS
6083 
6084   -- Read applicable group table for validation.
6085   -- In this table mr_header_id/csi_item_instance_id are parents
6086   -- and related_mr_header_id/related_csi_item_instance_id are children.
6087   CURSOR ahl_applicable_grp_csr( p_item_instance_id IN NUMBER,
6088                                  p_mr_header_id IN NUMBER,
6089                                  p_level IN NUMBER) IS
6090 
6091     SELECT mr_header_id, csi_item_instance_id,
6092            related_mr_header_id,
6093            related_csi_item_instance_id
6094     FROM ahl_applicable_mr_relns
6095     WHERE level = p_level
6096     START WITH mr_header_id = p_mr_header_id AND
6097                csi_item_instance_id = p_item_instance_id AND
6098                orig_mr_header_id = p_mr_header_id AND
6099                orig_csi_item_instance_id = p_item_instance_id AND
6100                relationship_code = 'PARENT'
6101     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
6102                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
6103                orig_mr_header_id = p_mr_header_id AND
6104                orig_csi_item_instance_id = p_item_instance_id AND
6105                relationship_code = 'PARENT'
6106     ORDER BY   level, mr_header_id, csi_item_instance_id;
6107 
6108   -- Read applicable group table for updates.
6109   CURSOR ahl_applicable1_grp_csr( p_item_instance_id IN NUMBER,
6110                                   p_mr_header_id IN NUMBER) IS
6111 
6112     SELECT mr_header_id, csi_item_instance_id, related_mr_header_id,
6113            related_csi_item_instance_id
6114     FROM ahl_applicable_mr_relns
6115     START WITH mr_header_id = p_mr_header_id AND
6116                csi_item_instance_id = p_item_instance_id AND
6117                orig_mr_header_id = p_mr_header_id AND
6118                orig_csi_item_instance_id = p_item_instance_id AND
6119                relationship_code = 'PARENT'
6120     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
6121                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
6122                orig_mr_header_id = p_mr_header_id AND
6123                orig_csi_item_instance_id = p_item_instance_id AND
6124                relationship_code = 'PARENT'
6125     ORDER BY   level, mr_header_id, csi_item_instance_id;
6126 
6127   -- for reading unit effectivity table.
6128   CURSOR ahl_ue_relns_csr ( p_unit_effectivity_id IN NUMBER, p_level IN NUMBER ) IS
6129     SELECT ue_id, related_ue_id
6130     FROM ahl_ue_relationships relns
6131     WHERE level = p_level
6132     START WITH ue_id = p_unit_effectivity_id AND
6133                relationship_code = 'PARENT'
6134     CONNECT BY PRIOR related_ue_id = ue_id AND
6135                originator_ue_id = p_unit_effectivity_id AND
6136                relationship_code = 'PARENT'
6137     ORDER BY   level;
6138 
6139   -- get related unit effectivities details.
6140   CURSOR ahl_ue_csr ( p_ue_id IN NUMBER,
6141                       p_related_ue_id IN NUMBER ) IS
6142     SELECT ue1.mr_header_id, ue1.csi_item_instance_id,
6143            ue2.mr_header_id related_mr_header_id,
6144            ue2.csi_item_instance_id related_csi_item_instance_id
6145     --FROM ahl_unit_effectivities_app_v ue1, ahl_unit_effectivities_app_v ue2
6146     FROM ahl_unit_effectivities_b ue1, ahl_unit_effectivities_b ue2
6147     WHERE ue1.unit_effectivity_id = p_ue_id AND
6148           ue2.unit_effectivity_id = p_related_ue_id;
6149 
6150   -- To check if mr has a preceding mr.
6151   CURSOR ahl_appl_mr_csr (p_item_instance_id IN NUMBER,
6152                           p_mr_header_id IN NUMBER) IS
6153    SELECT 'x'
6154    FROM ahl_applicable_mrs
6155    WHERE csi_item_instance_id = p_item_instance_id AND
6156          mr_header_id = p_mr_header_id AND
6157          implement_status_code <> 'OPTIONAL_DO_NOT_IMPLEMENT' AND
6158          preceding_mr_header_id IS NOT NULL;
6159 
6160   l_new_unit_effectivity_rec  ahl_temp_unit_effectivities%ROWTYPE;
6161   l_initialize_ue_rec         ahl_temp_unit_effectivities%ROWTYPE;
6162 
6163   l_junk  VARCHAR2(1);
6164   l_visit_end_date DATE;
6165   l_unit_effectivity_id  NUMBER;
6166   l_ue_id                NUMBER;
6167   l_related_ue_id        NUMBER;
6168 
6169   TYPE ue_details_rec_type IS RECORD (
6170      mr_header_id NUMBER,
6171      csi_item_instance_id NUMBER,
6172      related_mr_header_id NUMBER,
6173      related_csi_item_instance_id NUMBER,
6174      match_flag  VARCHAR2(1));
6175 
6176   l_ue_details_rec       ue_details_rec_type;
6177 
6178   TYPE l_ue_details_tbl_type IS TABLE OF ue_details_rec_type INDEX BY BINARY_INTEGER;
6179 
6180   l_ue_details_tbl       l_ue_details_tbl_type;
6181   l_grp_details_tbl      l_ue_details_tbl_type;
6182 
6183   l_grp_match  BOOLEAN;
6184   l_level NUMBER;
6185   l_reln_found BOOLEAN;
6186   l_appl_grp_found BOOLEAN;
6187 
6188   i NUMBER;
6189 
6190   l_visit_status    VARCHAR2(30);
6191 
6192  BEGIN
6193 
6194   IF G_DEBUG = 'Y' THEN
6195      AHL_DEBUG_PUB.Debug('Start Process Group MR');
6196   END IF;
6197 
6198   l_grp_match := FALSE; /* set default to be "no group" available to match against in ahl_unit_effectitivities. */
6199 
6200   IF (p_old_UE_forecast_sequence <> -1) THEN
6201   -- match the group tree under unit_effectivity_id in unit_effectivity_tbl(l_old_UE_forecast_sequence)
6202   -- with the one in ahl_applicable_mr_relns.
6203 
6204     l_level := 0;  /* tree level */
6205     l_unit_effectivity_id := p_unit_effectivity_tbl(p_old_UE_forecast_sequence).unit_effectivity_id;
6206 
6207     l_grp_match := TRUE;
6208     l_reln_found := TRUE; /* ue_relns record found */
6209     l_appl_grp_found := TRUE; /* applicable grp mrs found */
6210 
6211     -- Check if workorder already created.
6212     l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status (l_unit_effectivity_id);
6213 
6214     -- when UE is on shop floor or UE status is INIT-DUE, skip group MR comparison.
6215     -- This will be done later in flush_from_temp_table proc.
6216     IF (p_unit_effectivity_tbl(p_old_UE_forecast_sequence).status_code) = 'INIT-DUE'
6217        OR (nvl(l_visit_status,'x') IN ('RELEASED','CLOSED')) THEN
6218        null; -- for init-due status skip group MR comparison. This will be done later in flush_from_temp_table proc.
6219        -- We need the UE id inserted as the First Due info needs to be copied to new UE
6220     ELSE
6221 
6222       WHILE ( ((l_reln_found) OR (l_appl_grp_found)) AND (l_grp_match = TRUE)) LOOP
6223 
6224          l_level := l_level + 1;
6225          --dbms_output.put_line('level:' || l_level);
6226          i := 1;
6227          FOR l_ue_relns_rec IN ahl_ue_relns_csr(l_unit_effectivity_id, l_level) LOOP
6228              OPEN ahl_ue_csr(l_ue_relns_rec.ue_id, l_ue_relns_rec.related_ue_id);
6229              FETCH ahl_ue_csr INTO l_ue_details_tbl(i).mr_header_id,
6230                                    l_ue_details_tbl(i).csi_item_instance_id,
6231                                    l_ue_details_tbl(i).related_mr_header_id,
6232                                    l_ue_details_tbl(i).related_csi_item_instance_id;
6233              IF (ahl_ue_csr%NOTFOUND) THEN
6234                  FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_RELN_NOTFOUND');
6235                  FND_MESSAGE.Set_Token('UE_ID',l_ue_relns_rec.ue_id);
6236                  FND_MESSAGE.Set_Token('RELATED_UE_ID', l_ue_relns_rec.related_ue_id);
6237                  FND_MSG_PUB.ADD;
6238                  CLOSE ahl_ue_csr;
6239                  RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
6240              END IF;
6241              --dbms_output.put_line ('found ue relns');
6242 
6243              l_ue_details_tbl(i).match_flag := 'N';
6244              i := i + 1;
6245              CLOSE ahl_ue_csr;
6246          END LOOP;
6247 
6248          IF (l_ue_details_tbl.COUNT > 0 ) THEN
6249             l_reln_found := TRUE;
6250          ELSE
6251             l_reln_found := FALSE;
6252          END IF;
6253          --dbms_output.put_line('count ue tbl' || l_ue_details_tbl.COUNT);
6254 
6255          -- from applicable_mrs_group.
6256          i := 1;
6257          FOR l_appl_grp_rec IN ahl_applicable_grp_csr(p_applicable_mrs_rec.csi_item_instance_id,
6258                                                       p_applicable_mrs_rec.mr_header_id,
6259                                                       l_level)
6260          LOOP
6261              l_grp_details_tbl(i).mr_header_id := l_appl_grp_rec.mr_header_id;
6262              l_grp_details_tbl(i).csi_item_instance_id := l_appl_grp_rec.csi_item_instance_id;
6263              l_grp_details_tbl(i).related_mr_header_id := l_appl_grp_rec.related_mr_header_id;
6264              l_grp_details_tbl(i).related_csi_item_instance_id := l_appl_grp_rec.related_csi_item_instance_id;
6265              l_grp_details_tbl(i).match_flag := 'N';
6266              i := i + 1;
6267          END LOOP;
6268 
6269          IF (l_grp_details_tbl.COUNT > 0 ) THEN
6270             l_appl_grp_found := TRUE;
6271          ELSE
6272             l_appl_grp_found := FALSE;
6273          END IF;
6274          --dbms_output.put_line('count grp tbl' || l_grp_details_tbl.COUNT);
6275 
6276          -- Now compare l_grp_details_tbl with l_ue_details_tbl.
6277          IF (l_grp_details_tbl.COUNT > 0 ) THEN
6278            FOR i IN l_grp_details_tbl.FIRST..l_grp_details_tbl.LAST LOOP
6279              -- match if entry present in l_ue_details_tbl.
6280 
6281              IF (l_ue_details_tbl.COUNT > 0 ) THEN
6282                FOR j IN l_ue_details_tbl.FIRST..l_ue_details_tbl.LAST LOOP
6283                  IF (l_ue_details_tbl(j).mr_header_id = l_grp_details_tbl(i).mr_header_id AND
6284                     l_ue_details_tbl(j).csi_item_instance_id = l_grp_details_tbl(i).csi_item_instance_id AND
6285                     l_ue_details_tbl(j).related_csi_item_instance_id = l_grp_details_tbl(i).related_csi_item_instance_id AND
6286                     l_ue_details_tbl(j).related_mr_header_id = l_grp_details_tbl(i).related_mr_header_id AND
6287                     l_ue_details_tbl(j).match_flag = 'N' AND
6288                     l_grp_details_tbl(i).match_flag = 'N') THEN
6289                     --l_ue_details_tbl.DELETE(j);
6290                     --l_grp_details_tbl.DELETE(i);
6291                     l_ue_details_tbl(j).match_flag := 'Y';
6292                     l_grp_details_tbl(i).match_flag := 'Y';
6293                      EXIT;
6294                  END IF;
6295                END LOOP; /* ue_details */
6296              END IF; /* count - ue_details */
6297            END LOOP; /* grp_details */
6298          END IF; /* count - grp_details */
6299 
6300          -- delete records from table where match flag is Y.
6301          IF (l_ue_details_tbl.COUNT > 0 ) THEN
6302            FOR j IN l_ue_details_tbl.FIRST..l_ue_details_tbl.LAST LOOP
6303              IF (l_ue_details_tbl(j).match_flag = 'Y') THEN
6304                 l_ue_details_tbl.DELETE(j);
6305              END IF;
6306            END LOOP;
6307          END IF;
6308 
6309          IF (l_grp_details_tbl.COUNT > 0 ) THEN
6310            FOR i IN l_grp_details_tbl.FIRST..l_grp_details_tbl.LAST LOOP
6311              IF (l_grp_details_tbl(i).match_flag = 'Y') THEN
6312                l_grp_details_tbl.DELETE(i);
6313              END IF;
6314            END LOOP;
6315          END IF;
6316 
6317          IF (l_ue_details_tbl.COUNT <= 0) AND (l_grp_details_tbl.COUNT <= 0) THEN
6318              l_grp_match := TRUE;
6319 
6320          ELSE
6321              l_grp_match := FALSE;
6322 
6323          END IF;
6324 
6325       END LOOP; /* while - level */
6326     END IF; -- status_code
6327 
6328   END IF; -- p_old_UE_forecast_sequence
6329 
6330   -- if trees match, then
6331   -- update the temp table record for orig MR with visit_end_date and unit_effectivity ID.
6332   IF (p_old_UE_forecast_sequence IS NOT NULL AND l_grp_match = TRUE) THEN
6333 
6334     -- get visit end date from unit_effectivity_tbl for l_old_UE_Forecast_sequence.
6335     l_visit_end_date := p_unit_effectivity_tbl(p_old_UE_forecast_sequence).visit_end_date;
6336     l_new_unit_effectivity_rec.unit_effectivity_id :=
6337                           p_unit_effectivity_tbl(p_old_UE_forecast_sequence).unit_effectivity_id;
6338 
6339   ELSE
6340     l_visit_end_date := null;
6341   END IF;
6342 
6343   -- construct temporary unit effectivity for group top node.
6344 
6345     l_new_unit_effectivity_rec.due_date := p_new_unit_effectivity_rec.due_date;
6346     l_new_unit_effectivity_rec.mr_interval_id := p_new_unit_effectivity_rec.mr_interval_id;
6347     l_new_unit_effectivity_rec.mr_effectivity_id := p_new_unit_effectivity_rec.mr_effectivity_id;
6348     l_new_unit_effectivity_rec.due_counter_value := p_new_unit_effectivity_rec.due_counter_value;
6349     l_new_unit_effectivity_rec.csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
6350     l_new_unit_effectivity_rec.mr_header_id := p_applicable_mrs_rec.mr_header_id;
6351     l_new_unit_effectivity_rec.repetitive_mr_flag := p_new_unit_effectivity_rec.repetitive_mr_flag;
6352     l_new_unit_effectivity_rec.visit_end_date := l_visit_end_date;
6353     l_new_unit_effectivity_rec.forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
6354     -- to indicate group.
6355     l_new_unit_effectivity_rec.orig_csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
6356     l_new_unit_effectivity_rec.orig_mr_header_id := p_applicable_mrs_rec.mr_header_id;
6357     l_new_unit_effectivity_rec.orig_forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
6358     -- Added for ER# 2636001.
6359     l_new_unit_effectivity_rec.earliest_due_date := p_new_unit_effectivity_rec.earliest_due_date;
6360     l_new_unit_effectivity_rec.latest_due_date := p_new_unit_effectivity_rec.latest_due_date;
6361     l_new_unit_effectivity_rec.counter_id := p_new_unit_effectivity_rec.counter_id;
6362 
6363     l_new_unit_effectivity_rec.tolerance_flag := p_new_unit_effectivity_rec.tolerance_flag;
6364     l_new_unit_effectivity_rec.tolerance_before := p_new_unit_effectivity_rec.tolerance_before;
6365     l_new_unit_effectivity_rec.tolerance_after := p_new_unit_effectivity_rec.tolerance_after;
6366 
6367 
6368   -- write into temp table.
6369     Create_temp_unit_effectivity(l_new_unit_effectivity_rec);
6370 
6371   -- Read group MR tree and apply details from p_next_due_rec_type.
6372   FOR l_mr_grp_rec IN ahl_applicable1_grp_csr(p_applicable_mrs_rec.csi_item_instance_id,
6373                                               p_applicable_mrs_rec.mr_header_id)
6374   LOOP
6375 
6376    l_new_unit_effectivity_rec := l_initialize_ue_rec;
6377 
6378     -- Build temp_unit_effectivity record and write into temporary table.
6379     -- fix bug#6530920: UOM remain issue for child MRs.
6380     l_new_unit_effectivity_rec.due_date := p_new_unit_effectivity_rec.due_date;
6381     l_new_unit_effectivity_rec.mr_interval_id := p_new_unit_effectivity_rec.mr_interval_id;
6382     l_new_unit_effectivity_rec.mr_effectivity_id := p_new_unit_effectivity_rec.mr_effectivity_id;
6383     l_new_unit_effectivity_rec.due_counter_value := p_new_unit_effectivity_rec.due_counter_value;
6384     l_new_unit_effectivity_rec.csi_item_instance_id := l_mr_grp_rec.related_csi_item_instance_id;
6385     l_new_unit_effectivity_rec.parent_csi_item_instance_id := l_mr_grp_rec.csi_item_instance_id;
6386     l_new_unit_effectivity_rec.mr_header_id := l_mr_grp_rec.related_mr_header_id;
6387     l_new_unit_effectivity_rec.parent_mr_header_id := l_mr_grp_rec.mr_header_id;
6388     l_new_unit_effectivity_rec.orig_csi_item_instance_id := p_applicable_mrs_rec.csi_item_instance_id;
6389     l_new_unit_effectivity_rec.orig_mr_header_id := p_applicable_mrs_rec.mr_header_id;
6390     l_new_unit_effectivity_rec.orig_forecast_sequence := p_new_unit_effectivity_rec.forecast_sequence;
6391     l_new_unit_effectivity_rec.repetitive_mr_flag := p_new_unit_effectivity_rec.repetitive_mr_flag;
6392     l_new_unit_effectivity_rec.visit_end_date := l_visit_end_date;
6393     l_new_unit_effectivity_rec.earliest_due_date := p_new_unit_effectivity_rec.earliest_due_date;
6394     l_new_unit_effectivity_rec.latest_due_date := p_new_unit_effectivity_rec.latest_due_date;
6395     l_new_unit_effectivity_rec.counter_id := p_new_unit_effectivity_rec.counter_id;
6396 
6397     l_new_unit_effectivity_rec.tolerance_flag := p_new_unit_effectivity_rec.tolerance_flag;
6398     l_new_unit_effectivity_rec.tolerance_before := p_new_unit_effectivity_rec.tolerance_before;
6399     l_new_unit_effectivity_rec.tolerance_after := p_new_unit_effectivity_rec.tolerance_after;
6400 
6401     l_new_unit_effectivity_rec.unit_effectivity_id := null;
6402 
6403     -- check if this mr has a preceding mr.
6404     OPEN ahl_appl_mr_csr (l_mr_grp_rec.related_csi_item_instance_id,
6405                           l_mr_grp_rec.related_mr_header_id);
6406     FETCH ahl_appl_mr_csr INTO l_junk;
6407     IF (ahl_appl_mr_csr%FOUND) THEN
6408        l_new_unit_effectivity_rec.preceding_check_flag:= 'Y';
6409     ELSE
6410        l_new_unit_effectivity_rec.preceding_check_flag:= 'N';
6411     END IF;
6412     CLOSE ahl_appl_mr_csr;
6413 
6414     -- write into temp table.
6415     Create_temp_unit_effectivity(l_new_unit_effectivity_rec);
6416 
6417   END LOOP;
6418 
6419   IF G_DEBUG = 'Y' THEN
6420      AHL_DEBUG_PUB.Debug('End Process GroupMR');
6421   END IF;
6422 
6423 END Process_GroupMR;
6424 
6425 -------------------------------------------------------------------------------------
6426 -- To process the dependent MRs based on the value of preceding MR.
6427 
6428 PROCEDURE Process_PrecedingMR (p_applicable_mrs_rec IN applicable_mrs_rec_type,
6429                                p_counter_rules_tbl  IN counter_rules_tbl_type,
6430                                p_current_usage_tbl  IN counter_values_tbl_type)
6431 IS
6432 
6433   -- Declare cursor to get all MRs that have preceding MR as that in applicable_mrs_rec.
6434   /* modified for performance
6435   CURSOR ahl_preceding_mr_csr (p_mr_header_id IN NUMBER,
6436                                p_item_instance_id IN NUMBER) IS
6437     SELECT mr.mr_header_id,
6438            apmr.csi_item_instance_id,
6439            apmr.Implement_status_code,
6440            apmr.copy_accomplishment_code,
6441            apmr.show_repetitive_code,
6442            --apmr.preceding_mr_header_id, -- fix for bug# 5922149
6443            curr_mr.mr_header_id preceding_mr_header_id,
6444            apmr.descendent_count,
6445            mr.whichever_first_code,
6446            apmr.repetitive_flag
6447     FROM ahl_mr_headers_app_v mr, ahl_mr_headers_b curr_mr, ahl_applicable_mrs apmr
6448     --fix for bug number 5922149
6449     --WHERE mr.preceding_mr_header_id = curr_mr.mr_header_id AND
6450     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
6451           curr_mr.mr_header_id = p_mr_header_id AND
6452           apmr.mr_header_id = mr.mr_header_id AND
6453           -- Fix for bug# 6711228.
6454           -- validation moved to before this procedure call.
6455           -- curr_mr.implement_status_code = 'MANDATORY' AND
6456           trunc(sysdate) >= trunc(nvl(mr.effective_from, sysdate)) AND
6457           trunc(sysdate) <= trunc(nvl(mr.effective_to, sysdate+1)) AND
6458           apmr.csi_item_instance_id = p_item_instance_id;
6459   */
6460 
6461   CURSOR ahl_preceding_mr_csr (p_curr_mr_title    IN VARCHAR2,
6462                                p_item_instance_id IN NUMBER) IS
6463     SELECT mr.mr_header_id,
6464            mr.version_number,
6465            apmr.csi_item_instance_id,
6466            apmr.Implement_status_code,
6467            apmr.copy_accomplishment_code,
6468            apmr.show_repetitive_code,
6469            --apmr.preceding_mr_header_id,
6470            apmr.descendent_count,
6471            mr.whichever_first_code,
6472            apmr.repetitive_flag,
6473            mr.title,
6474            mr.effective_from,
6475            mr.effective_to
6476     FROM ahl_mr_headers_app_v mr, ahl_applicable_mrs apmr
6477     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
6478           apmr.mr_header_id = mr.mr_header_id AND
6479           trunc(sysdate) >= trunc(nvl(mr.effective_from, sysdate)) AND
6480           trunc(sysdate) <= trunc(nvl(mr.effective_to, sysdate+1)) AND
6481           apmr.csi_item_instance_id = p_item_instance_id;
6482 
6483    l_dependent_mr_rec applicable_mrs_rec_type;
6484 
6485    k NUMBER := 0;
6486 
6487 
6488 BEGIN
6489 
6490   IF G_DEBUG = 'Y' THEN
6491      AHL_DEBUG_PUB.Debug('Start Process PrecedingMR');
6492   END IF;
6493 
6494   -- Process mrs which are dependent on current mr and are applicable to the same item instance.
6495   --FOR l_appl_rec IN ahl_preceding_mr_csr(p_applicable_mrs_rec.mr_header_id,
6496   --                                       p_applicable_mrs_rec.csi_item_instance_id) LOOP
6497   FOR l_appl_rec IN ahl_preceding_mr_csr(p_applicable_mrs_rec.title,
6498                                          p_applicable_mrs_rec.csi_item_instance_id) LOOP
6499 
6500      -- Build applicable_mrs_rec.
6501      l_dependent_mr_rec.csi_item_instance_id := l_appl_rec.csi_item_instance_id;
6502      l_dependent_mr_rec.MR_header_id := l_appl_rec.MR_header_id;
6503      l_dependent_mr_rec.Implement_status_code := l_appl_rec.Implement_status_code;
6504      l_dependent_mr_rec.copy_accomplishment_code := l_appl_rec.copy_accomplishment_code;
6505      l_dependent_mr_rec.show_repetitive_code := l_appl_rec.show_repetitive_code;
6506      --l_dependent_mr_rec.preceding_mr_header_id := l_appl_rec.preceding_mr_header_id;
6507      l_dependent_mr_rec.preceding_mr_header_id := p_applicable_mrs_rec.mr_header_id;
6508      l_dependent_mr_rec.descendent_count := l_appl_rec.descendent_count;
6509      l_dependent_mr_rec.whichever_first_code := l_appl_rec.whichever_first_code;
6510      l_dependent_mr_rec.repetitive_flag := l_appl_rec.repetitive_flag;
6511      l_dependent_mr_rec.title := l_appl_rec.title;
6512      l_dependent_mr_rec.version_number := l_appl_rec.version_number;
6513      l_dependent_mr_rec.effective_to := l_appl_rec.effective_to;
6514      l_dependent_mr_rec.effective_from := l_appl_rec.effective_from;
6515 
6516      Build_Effectivity (p_applicable_mrs_rec => l_dependent_mr_rec,
6517                         p_current_usage_tbl  => p_current_usage_tbl,
6518                         p_counter_rules_tbl  => p_counter_rules_tbl);
6519 
6520   END LOOP;
6521 
6522   IF G_DEBUG = 'Y' THEN
6523      AHL_DEBUG_PUB.Debug('End Process PrecedingMR');
6524   END IF;
6525 
6526 
6527 END Process_PrecedingMR;
6528 
6529 --------------------------------------------------------------------------------
6530 -- To update the preceding_check_flag in the temporary unit effectivities table.
6531 
6532 PROCEDURE Update_check_flag (p_applicable_mrs_rec IN applicable_mrs_rec_type,
6533                              p_dependent_mr_flag IN BOOLEAN,
6534                              p_next_due_date_rec IN next_due_date_rec_type)
6535 IS
6536 
6537   l_preceding_check_flag VARCHAR2(1);
6538 
6539 BEGIN
6540 
6541   IF G_DEBUG = 'Y' THEN
6542      AHL_DEBUG_PUB.Debug('Start Update Check Flag');
6543   END IF;
6544 
6545   IF (p_dependent_mr_flag) THEN
6546    /* i.e accomplishment is based on preceding MR */
6547     IF (p_next_due_date_rec.due_date IS NULL) THEN
6548        null; /* leave all preceding_check_flag = 'Y' */
6549     ELSE
6550        UPDATE ahl_temp_unit_effectivities
6551        SET preceding_check_flag = 'N'
6552        WHERE csi_item_instance_id = p_applicable_mrs_rec.csi_item_instance_id
6553              AND mr_header_id = p_applicable_mrs_rec.mr_header_id
6554              AND due_date >= p_next_due_date_rec.due_date;
6555     END IF;
6556   ELSE
6557    /* this MR has its accomplishments; update all records irrespective of due date */
6558     UPDATE ahl_temp_unit_effectivities
6559     SET preceding_check_flag = 'N'
6560     WHERE csi_item_instance_id = p_applicable_mrs_rec.csi_item_instance_id
6561           AND mr_header_id = p_applicable_mrs_rec.mr_header_id;
6562 
6563   END IF;
6564 
6565   IF G_DEBUG = 'Y' THEN
6566      AHL_DEBUG_PUB.Debug('End Update Check Flag');
6567   END IF;
6568 
6569 END Update_check_flag;
6570 
6571 
6572 -----------------------------------------------------------
6573 -- To write a record into ahl_temp_unit_effectivities.
6574 
6575 PROCEDURE Create_temp_unit_effectivity (X_unit_effectivity_rec IN ahl_temp_unit_effectivities%ROWTYPE)
6576 
6577 IS
6578 
6579 BEGIN
6580   IF G_DEBUG = 'Y' THEN
6581      AHL_DEBUG_PUB.Debug('Start Create Temporary Unit Effect');
6582   END IF;
6583 
6584   -- insert into temporary table.
6585   insert into ahl_temp_unit_effectivities (
6586     csi_item_instance_id,
6587     MR_header_id,
6588     due_date,
6589     mr_interval_id,
6590     mr_effectivity_id,
6591     due_counter_value,
6592     parent_csi_item_instance_id,
6593     parent_mr_header_id,
6594     orig_csi_item_instance_id,
6595     orig_mr_header_id,
6596     orig_forecast_sequence,
6597     preceding_csi_item_instance_id,
6598     preceding_mr_header_id,
6599     preceding_forecast_seq,
6600     forecast_sequence,
6601     tolerance_before,
6602     tolerance_after,
6603     preceding_check_flag,
6604     unit_effectivity_id,
6605     repetitive_mr_flag,
6606     tolerance_flag,
6607     message_code,
6608     service_line_id,
6609     program_mr_header_id,
6610     earliest_due_date,
6611     latest_due_date,
6612     counter_id)
6613   values (
6614     X_unit_effectivity_rec.csi_item_instance_id,
6615     X_unit_effectivity_rec.MR_header_id,
6616     X_unit_effectivity_rec.due_date,
6617     X_unit_effectivity_rec.mr_interval_id,
6618     X_unit_effectivity_rec.mr_effectivity_id,
6619     X_unit_effectivity_rec.due_counter_value,
6620     X_unit_effectivity_rec.parent_csi_item_instance_id,
6621     X_unit_effectivity_rec.parent_mr_header_id,
6622     X_unit_effectivity_rec.orig_csi_item_instance_id,
6623     X_unit_effectivity_rec.orig_mr_header_id,
6624     X_unit_effectivity_rec.orig_forecast_sequence,
6625     X_unit_effectivity_rec.preceding_csi_item_instance_id,
6626     X_unit_effectivity_rec.preceding_mr_header_id,
6627     X_unit_effectivity_rec.preceding_forecast_seq,
6628     X_unit_effectivity_rec.forecast_sequence,
6629     X_unit_effectivity_rec.tolerance_before,
6630     X_unit_effectivity_rec.tolerance_after,
6631     X_unit_effectivity_rec.preceding_check_flag,
6632     X_unit_effectivity_rec.unit_effectivity_id,
6633     X_unit_effectivity_rec.repetitive_mr_flag,
6634     X_unit_effectivity_rec.tolerance_flag,
6635     X_unit_effectivity_rec.message_code,
6636     X_unit_effectivity_rec.service_line_id,
6637     X_unit_effectivity_rec.program_mr_header_id,
6638     X_unit_effectivity_rec.earliest_due_date,
6639     X_unit_effectivity_rec.latest_due_date,
6640     X_unit_effectivity_rec.counter_id
6641 
6642   );
6643 
6644   IF G_DEBUG = 'Y' THEN
6645      AHL_DEBUG_PUB.Debug('End Create Temp Unit Effect.');
6646   END IF;
6647 
6648 END Create_temp_unit_effectivity;
6649 
6650 
6651 ---------------------------------------------------------------------------
6652 -- To log error messages into a log file if called from concurrent process.
6653 
6654 PROCEDURE log_error_messages IS
6655 
6656 l_msg_count      NUMBER;
6657 l_msg_index_out  NUMBER;
6658 l_msg_data       VARCHAR2(2000);
6659 
6660 BEGIN
6661 
6662 IF G_DEBUG = 'Y' THEN
6663      AHL_DEBUG_PUB.Debug('Start log error messages');
6664 END IF;
6665 
6666  -- Standard call to get message count.
6667 l_msg_count := FND_MSG_PUB.Count_Msg;
6668 
6669 FOR i IN 1..l_msg_count LOOP
6670   FND_MSG_PUB.get (
6671       p_msg_index      => i,
6672       p_encoded        => FND_API.G_FALSE,
6673       p_data           => l_msg_data,
6674       p_msg_index_out  => l_msg_index_out );
6675 
6676   fnd_file.put_line(FND_FILE.LOG, 'Err message-'||l_msg_index_out||':' || l_msg_data);
6677   IF G_DEBUG = 'Y' THEN
6678      AHL_DEBUG_PUB.Debug('Err message-'||l_msg_index_out||':' || substr(l_msg_data,1,240));
6679   END IF;
6680 
6681 END LOOP;
6682 
6683 IF G_DEBUG = 'Y' THEN
6684      AHL_DEBUG_PUB.Debug('End log error messages');
6685 END IF;
6686 
6687 
6688 END log_error_messages;
6689 
6690 -----------------------------------------------------------------------
6691 --  Function    : Calls FMP and populates the AHL_APPLICABLE_MRS table
6692 --                for preventive maintenance installation.
6693 --  Pre-reqs    :
6694 --  Parameters  :
6695 --
6696 --  PopulatePM_Appl_MRs Parameters:
6697 --       p_csi_ii_id       IN  csi item instance id  Required
6698 --
6699 --
6700 --  End of Comments.
6701 
6702 PROCEDURE PopulatePM_Appl_MRs (
6703     p_csi_ii_id           IN            NUMBER,
6704     x_return_status       OUT  NOCOPY   VARCHAR2,
6705     x_msg_count           OUT  NOCOPY   NUMBER,
6706     x_msg_data            OUT  NOCOPY   VARCHAR2,
6707     x_UnSch_programs_tbl  OUT  NOCOPY   PMprogram_tbl_type)
6708 
6709 IS
6710  l_api_version            CONSTANT NUMBER := 1.0;
6711  l_appl_activities_tbl    AHL_FMP_PVT.applicable_activities_tbl_type;
6712  l_appl_programs_tbl      AHL_FMP_PVT.applicable_programs_tbl_type;
6713  l_pm_install_flag        VARCHAR2(1);
6714 
6715  l_duplicate_pgm_flag  BOOLEAN;
6716  l_pgm_index           NUMBER;
6717  l_UnSch_programs_tbl  PMprogram_tbl_type;
6718 
6719  l_activity_sch_exists_flag BOOLEAN;
6720 
6721 BEGIN
6722 
6723   IF G_DEBUG = 'Y' THEN
6724     AHL_DEBUG_PUB.debug('Start of PopulatePM_Appl_MRs');
6725   END IF;
6726 
6727   -- call api to fetch all applicable mrs for PM installation.
6728   AHL_FMP_PVT.get_pm_applicable_mrs(
6729                        p_api_version            => l_api_version,
6730                        p_init_msg_list          => FND_API.G_FALSE,
6731                        p_commit                 => FND_API.G_FALSE,
6732                        p_validation_level       => FND_API.G_VALID_LEVEL_FULL,
6733                        x_return_status          => x_return_status,
6734                        x_msg_count              => x_msg_count,
6735                        x_msg_data               => x_msg_data,
6736            	       p_item_instance_id       => p_csi_ii_id,
6737    		       x_applicable_activities_tbl     => l_appl_activities_tbl,
6738                        x_applicable_programs_tbl      => l_appl_programs_tbl);
6739 
6740 
6741   -- Raise errors if exceptions occur
6742   IF (x_return_status = FND_API.G_RET_STS_ERROR) THEN
6743     RAISE FND_API.G_EXC_ERROR;
6744   ELSIF (x_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
6745     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
6746   END IF;
6747 
6748   -- initialize.
6749   l_pgm_index := 0;
6750 
6751   -- Read programs table.
6752   IF (l_appl_programs_tbl.COUNT > 0) THEN
6753 
6754      FOR i IN l_appl_programs_tbl.FIRST..l_appl_programs_tbl.LAST LOOP
6755 
6756          l_activity_sch_exists_flag := TRUE;
6757 
6758          -- find the corressponding activities in l_appl_activities_tbl for the program.
6759          IF (l_appl_activities_tbl.COUNT > 0) THEN
6760             FOR j IN l_appl_activities_tbl.FIRST..l_appl_activities_tbl.LAST LOOP
6761                IF (l_appl_activities_tbl(j).service_line_id = l_appl_programs_tbl(i).service_line_id)
6762                THEN
6763 
6764                     INSERT INTO AHL_APPLICABLE_MRS (
6765                         	CSI_ITEM_INSTANCE_ID,
6766                   	        MR_HEADER_ID,
6767                         	MR_EFFECTIVITY_ID,
6768                     	        REPETITIVE_FLAG   ,
6769                           	SHOW_REPETITIVE_CODE,
6770                       	        IMPLEMENT_STATUS_CODE,
6771                                 WHICHEVER_FIRST_CODE,
6772                                 SERVICE_LINE_ID,
6773                                 PROGRAM_MR_HEADER_ID,
6774                                 CONTRACT_START_DATE,
6775                                 CONTRACT_END_DATE,
6776                                 COVERAGE_IMP_LEVEL,
6777                                 PM_SCHEDULE_EXISTS)
6778                     VALUES (    l_appl_activities_tbl(j).ITEM_INSTANCE_ID,
6779                                 l_appl_activities_tbl(j).MR_HEADER_ID,
6780                                 l_appl_activities_tbl(j).MR_EFFECTIVITY_ID,
6781                                 l_appl_activities_tbl(j).REPETITIVE_FLAG,
6782                                 l_appl_activities_tbl(j).SHOW_REPETITIVE_CODE,
6783                                 l_appl_activities_tbl(j).IMPLEMENT_STATUS_CODE,
6784                                 l_appl_activities_tbl(j).WHICHEVER_FIRST_CODE,
6785                                 l_appl_activities_tbl(j).SERVICE_LINE_ID,
6786                                 l_appl_activities_tbl(j).PROGRAM_MR_HEADER_ID,
6787                                 l_appl_programs_tbl(i).SERVICE_START_DATE,
6788                                 l_appl_programs_tbl(i).SERVICE_END_DATE,
6789                                 l_appl_programs_tbl(i).COVERAGE_TYPE_IMP_LEVEL,
6790                                 nvl(l_appl_activities_tbl(j).ACT_SCHEDULE_EXISTS,'N')
6791                            );
6792                     -- Set activity_sch_exists_flag if any of the activities does
6793                     -- not have a schedule.
6794                     IF (nvl(l_appl_activities_tbl(j).act_schedule_exists,'N') = 'N') THEN
6795                       l_activity_sch_exists_flag := FALSE;
6796                     END IF;
6797                END IF;
6798 
6799                IF G_DEBUG = 'Y' THEN
6800                  AHL_DEBUG_PUB.debug('Successfully inserted for Act ID:' || l_appl_activities_tbl(j).MR_HEADER_ID);
6801                END IF;
6802 
6803             END LOOP; -- next activities record.
6804          END IF; -- activity COUNT.
6805 
6806          -- If this program does not have a schedule, add this program to table l_UnSch_programs_tbl
6807          -- if it is unique.
6808          IF (NOT(l_activity_sch_exists_flag)  AND
6809              l_appl_programs_tbl(i).mr_effectivity_id IS NOT NULL) THEN
6810 
6811             l_duplicate_pgm_flag := FALSE;
6812             -- Check if this program already exists in the table.
6813             IF (l_UnSch_programs_tbl.COUNT > 0) THEN
6814                FOR j IN l_UnSch_programs_tbl.FIRST..l_UnSch_programs_tbl.LAST LOOP
6815                   IF (l_UnSch_programs_tbl(j).program_mr_header_id = l_appl_programs_tbl(i).PM_program_id) THEN
6816                       l_duplicate_pgm_flag := TRUE;
6817                       EXIT;
6818                   END IF;
6819                END LOOP; -- chk next program.
6820             END IF; -- count > 0.
6821 
6822             -- if not duplicate add to program table.
6823             IF NOT(l_duplicate_pgm_flag) THEN
6824                 l_pgm_index := l_pgm_index + 1;
6825                 l_UnSch_programs_tbl(l_pgm_index).program_mr_header_id := l_appl_programs_tbl(i).PM_program_id;
6826                 l_UnSch_programs_tbl(l_pgm_index).mr_effectivity_id := l_appl_programs_tbl(i).mr_effectivity_id;
6827                 IF G_DEBUG = 'Y' THEN
6828                    AHL_DEBUG_PUB.debug('Successfully added Program to l_UnSch_programs_tbl:index:value:' || i || ':' ||
6829                                        l_UnSch_programs_tbl(l_pgm_index).program_mr_header_id);
6830                 END IF;
6831 
6832             END IF;
6833 
6834          END IF;
6835       END LOOP; -- next program record.
6836     END IF; -- count > 0.
6837 
6838   -- set output parameter.
6839   x_unsch_programs_tbl := l_UnSch_programs_tbl;
6840 
6841   IF G_DEBUG = 'Y' THEN
6842     AHL_DEBUG_PUB.debug('End of PopulatePM_Appl_MRs');
6843   END IF;
6844 
6845 END PopulatePM_Appl_MRs;
6846 
6847 ----------------------------------------------------------------------------------
6848 -- Process Unit for PM(preventive maintenance) installation.
6849 PROCEDURE Process_PM_Unit(p_csi_item_instance_id IN NUMBER,
6850                           p_UnSch_programs_tbl   IN PMprogram_tbl_type) IS
6851 
6852   l_current_usage_tbl    counter_values_tbl_type;
6853   /* contains current counter usage */
6854 
6855 BEGIN
6856 
6857   IF G_DEBUG = 'Y' THEN
6858      AHL_DEBUG_PUB.Debug('Start of Process_PM_Unit procedure');
6859   END IF;
6860 
6861   -- Get current usage of all the counters defined for the item instance.
6862   get_Current_Usage (p_csi_item_instance_id,
6863                      l_current_usage_tbl);
6864 
6865   -- Calculate program end date for all MR's where program is not scheduled.
6866   Calc_program_end_dates (p_UnSch_programs_tbl,
6867                           l_current_usage_tbl);
6868 
6869   -- Process records with program dates scheduled.
6870   Process_PMSch_Activities;
6871 
6872   -- Process records with no program dates.
6873   Process_PMUnSch_Activities(l_current_usage_tbl);
6874 
6875   -- Assign existing unit_effectivity ID's that have not been accomplished
6876   -- to the newly created ones in the temporary table.
6877   Assign_Unit_effectivity_IDs;
6878 
6879   IF G_DEBUG = 'Y' THEN
6880      AHL_DEBUG_PUB.Debug('End of Process_PM_Unit procedure');
6881   END IF;
6882 
6883 END Process_PM_Unit;
6884 
6885 
6886 --------------------------------------------------------------------------------
6887 
6888 -- To calculate the program end dates for all contracts with no due date schedule.
6889 PROCEDURE Calc_Program_End_Dates(p_UnSch_programs_tbl   IN PMprogram_tbl_type,
6890                                  p_current_usage_tbl    IN counter_values_tbl_type) IS
6891 
6892   -- get all programs which have no schedules.
6893   CURSOR ahl_cont_not_scheduled_csr IS
6894     SELECT DISTINCT appl.program_mr_header_id, mr.whichever_first_code
6895     FROM ahl_applicable_mrs appl, ahl_mr_headers_b mr
6896     -- replaced ahl_mr_headers_app_v with ahl_mr_headers_b as ahl_applicable_mrs has
6897     -- the filter of application_usg_code.
6898     WHERE appl.program_mr_header_id = mr.mr_header_id
6899        AND pm_schedule_exists = 'N';
6900 
6901   -- get details of program effectivity.
6902   CURSOR ahl_program_eff_csr (p_mr_effectivity_id IN NUMBER) IS
6903     SELECT mr_effectivity_id, program_duration, program_duration_uom_code,
6904            threshold_date
6905     FROM ahl_mr_effectivities
6906     where mr_effectivity_id = p_mr_effectivity_id;
6907 
6908   -- get all intervals for an effectivity.
6909   CURSOR ahl_mr_interval_csr (p_mr_effectivity_id IN NUMBER) IS
6910     SELECT start_value, stop_value, counter_id, counter_name, mr_interval_id
6911     FROM ahl_mr_intervals_v
6912     WHERE mr_effectivity_id = p_mr_effectivity_id;
6913 
6914   l_effectivity_rec   ahl_program_eff_csr%ROWTYPE;
6915 
6916   l_counter_rules_tbl counter_rules_tbl_type;
6917 
6918   l_program_due_date      DATE;
6919   l_program_calender_days NUMBER;
6920   l_UnSch_program_tbl     PMprogram_tbl_type;
6921   l_upd_SQLstmt_str       VARCHAR2(2000);
6922 
6923   l_program_expire_flag   BOOLEAN;
6924   /* indicates if a program has expired. */
6925 
6926   l_current_ctr_value NUMBER;
6927   l_counter_remain    NUMBER;
6928   l_ctr_found         BOOLEAN;
6929   l_current_ctr_uom   VARCHAR2(3);
6930   l_due_days          NUMBER;
6931   l_due_date          DATE;
6932   l_tbl_index         NUMBER;
6933   l_program_expired_flag  BOOLEAN;
6934 
6935 BEGIN
6936 
6937   IF G_DEBUG = 'Y' THEN
6938       AHL_DEBUG_PUB.Debug('Start of CALC_PROGRAM_END_DATES procedure');
6939   END IF;
6940 
6941   FOR program_rec IN ahl_cont_not_scheduled_csr LOOP
6942     -- Initialize variables.
6943     l_program_due_date := NULL;
6944     l_counter_remain := 0;
6945     l_program_calender_days := 0;
6946     l_UnSch_program_tbl.DELETE;
6947     l_tbl_index := 0;
6948 
6949     IF G_DEBUG = 'Y' THEN
6950       AHL_DEBUG_PUB.Debug('Calculating program end date for:' || program_rec.program_mr_header_id);
6951     END IF;
6952 
6953     -- build temporary table containing the effectivities associated to the program.
6954     IF (p_UnSch_programs_tbl.COUNT > 0) THEN
6955        FOR i IN p_UnSch_programs_tbl.FIRST..p_UnSch_programs_tbl.LAST LOOP
6956           IF (p_UnSch_programs_tbl(i).program_mr_header_id = program_rec.program_mr_header_id) THEN
6957              l_tbl_index := l_tbl_index + 1;
6958              l_UnSch_program_tbl(l_tbl_index) := p_UnSch_programs_tbl(i);
6959              --dbms_output.put_line('program id:' || l_UnSch_program_tbl(l_tbl_index).program_mr_header_id);
6960           END IF;
6961        END LOOP;
6962     END IF;
6963 
6964     -- read effectivity attributes for the program.
6965     IF (l_UnSch_program_tbl.COUNT > 0) THEN
6966        FOR i IN l_UnSch_program_tbl.FIRST..l_UnSch_program_tbl.LAST LOOP
6967 
6968          IF G_DEBUG = 'Y' THEN
6969             AHL_DEBUG_PUB.Debug('Processing for program effectivity-id:' || l_UnSch_program_tbl(l_tbl_index).mr_effectivity_id);
6970          END IF;
6971 
6972          OPEN ahl_program_eff_csr (l_UnSch_program_tbl(i).mr_effectivity_id);
6973          FETCH ahl_program_eff_csr INTO l_effectivity_rec;
6974          IF (ahl_program_eff_csr%FOUND) THEN
6975             -- read intervals for the effectivity.
6976             FOR interval_rec IN ahl_mr_interval_csr(l_effectivity_rec.mr_effectivity_id) LOOP
6977 
6978               IF G_DEBUG = 'Y' THEN
6979                  AHL_DEBUG_PUB.Debug('Processing for interval:' || interval_rec.mr_interval_id);
6980               END IF;
6981 
6982               -- Set current usage counter value.
6983               l_current_ctr_value := 0;
6984               l_ctr_found := FALSE;
6985               l_current_ctr_uom := NULL;
6986               -- Get the interval counter's  value from l_current_usage_tbl.
6987               FOR i IN p_current_usage_tbl.FIRST..p_current_usage_tbl.LAST LOOP
6988                 IF (p_current_usage_tbl(i).counter_name = interval_rec.counter_name) THEN
6989                    l_current_ctr_value := p_current_usage_tbl(i).counter_value;
6990                    l_current_ctr_uom := p_current_usage_tbl(i).uom_code;
6991                    l_ctr_found := TRUE;
6992                    EXIT;
6993                 END IF;
6994               END LOOP;
6995 
6996               IF (l_ctr_found) THEN
6997 
6998                  -- Check that the current counter value less than the program stop value.
6999                  l_counter_remain := interval_rec.stop_value - l_current_ctr_value;
7000 
7001                  /* indicates if a program has expired. */
7002                  l_program_expire_flag := FALSE;
7003 
7004                  -- Using forecast find the number of days to reach stop_value.
7005                  IF (l_counter_remain > 0) THEN
7006                      -- get date from forecast.
7007                      get_date_from_uf(l_counter_remain,
7008                                       l_current_ctr_uom,
7009                                       l_counter_rules_tbl, -- empty table.
7010                                       sysdate,
7011                                       l_due_date);
7012 
7013                      -- Compare dates.
7014                      IF (l_program_due_date IS NULL) THEN
7015                        l_program_due_date := l_due_date;
7016                      ELSE
7017                        IF (l_due_date IS NOT NULL) THEN
7018                           IF (program_rec.whichever_first_code = 'FIRST') THEN
7019                              IF (trunc(l_program_due_date) > trunc(l_due_date)) THEN
7020                                  l_program_due_date := l_due_date;
7021                              END IF;
7022                           ELSE /* whichever_first_code = 'LAST' */
7023                              IF (trunc(l_program_due_date) < trunc(l_due_date)) THEN
7024                                  l_program_due_date := l_due_date;
7025                              END IF;
7026                           END IF;
7027                        END IF; -- due date null.
7028                      END IF;
7029 
7030                  ELSE
7031                        l_program_expire_flag := TRUE;
7032                        -- if program expired for mr with whichever_code = FIRST, stop calculation.
7033                        IF (program_rec.whichever_first_code = 'FIRST') THEN
7034                           -- program expired for this instance.
7035                           l_due_date := NULL;
7036                           l_program_due_date := NULL;
7037                           EXIT; -- exit intervals loop.
7038                        END IF;
7039                  END IF;
7040 
7041               END IF; /* end l_ctr_found */
7042 
7043             END LOOP; /* next interval_rec */
7044 
7045             -- calculate due date using effectivity attributes.
7046             IF (program_rec.whichever_first_code = 'FIRST') AND (l_program_expired_flag) THEN
7047                 -- program expired for this instance.
7048                 null; -- do nothing.
7049             ELSIF (nvl(l_effectivity_rec.program_duration,0)) <> 0 AND
7050                l_effectivity_rec.program_duration_uom_code IS NOT NULL
7051             THEN
7052 
7053               --dbms_output.put_line('effectivity duration:' ||l_effectivity_rec.program_duration );
7054               --dbms_output.put_line('effectivity duration:' ||l_effectivity_rec.program_duration_uom_code );
7055 
7056               IF (l_effectivity_rec.program_duration_uom_code = 'YR') THEN
7057                  l_due_days := trunc(ADD_MONTHS(trunc(SYSDATE), 12 * l_effectivity_rec.program_duration)) - trunc(SYSDATE);
7058               ELSIF (l_effectivity_rec.program_duration_uom_code = 'MTH') THEN
7059                  l_due_days := trunc(ADD_MONTHS(trunc(SYSDATE), l_effectivity_rec.program_duration)) - trunc(SYSDATE);
7060               ELSIF (l_effectivity_rec.program_duration_uom_code = 'WK') THEN
7061                  l_due_days := 7 * l_effectivity_rec.program_duration;
7062               ELSIF (l_effectivity_rec.program_duration_uom_code = 'DAY') THEN
7063                  l_due_days := l_effectivity_rec.program_duration;
7064               END IF;
7065 
7066               --dbms_output.put_line('due days are:' || l_due_days );
7067 
7068               -- Compare the due days.
7069               IF (l_program_calender_days = 0) THEN
7070                   l_program_calender_days := l_due_days;
7071               ELSIF (program_rec.whichever_first_code = 'FIRST') THEN
7072                 IF (l_program_calender_days > l_due_days) THEN
7073                   l_program_calender_days := l_due_days;
7074                 END IF;
7075               ELSE /* whichever_first_code = 'LAST' */
7076                 IF (l_program_calender_days < l_due_days) THEN
7077                   l_program_calender_days := l_due_days;
7078                 END IF;
7079               END IF;
7080 
7081             END IF; /* effectivity_rec.program_duration */
7082 
7083          END IF; /* effectivity_rec found */
7084          CLOSE ahl_program_eff_csr;
7085 
7086          -- chk for program expired.
7087          IF (program_rec.whichever_first_code = 'FIRST') AND (l_program_expired_flag) THEN
7088              -- program expired for this instance.
7089              l_program_due_date := NULL;
7090              EXIT; -- exit program table loop.
7091          END IF;
7092 
7093       END LOOP; /* program table */
7094     END IF; /* count */
7095 
7096     IF G_DEBUG = 'Y' THEN
7097        AHL_DEBUG_PUB.Debug('Program end date:' || l_program_due_date );
7098        AHL_DEBUG_PUB.Debug('Program calender days:' || l_program_calender_days );
7099     END IF;
7100 
7101     -- Update record in ahl_applicable_mrs with the calculated program end date.
7102     IF (l_program_expired_flag) THEN
7103        -- For this case, set program end date = sysdate -1.
7104        l_upd_SQLstmt_str := 'UPDATE ahl_applicable_mrs' ||
7105                             ' SET program_end_date = :1' ||
7106                             ' WHERE program_mr_header_id = :2'||
7107                             ' AND PM_schedule_exists = :3';
7108 
7109        IF G_DEBUG = 'Y' THEN
7110           AHL_DEBUG_PUB.Debug('Expire SQL string:' || l_upd_SQLstmt_str);
7111        END IF;
7112 
7113        EXECUTE IMMEDIATE l_upd_SQLstmt_str USING SYSDATE - 1,
7114                                                  program_rec.program_mr_header_id,
7115                                                  'N';
7116     ELSE
7117 
7118        -- dbms_output.put_line('Not expired');
7119        -- set program end date = least of (program_calculated_date, contract_start + calender_days, contract_end_date)
7120        --UPDATE ahl_applicable_mrs
7121        --SET program_end_date = LEAST (nvl(l_program_due_date,contract_end_date),
7122        --                              decode(l_program_calender_days,0, contract_end_date, contract_start_date + l_program_calender_days),
7123        --                              contract_end_date)
7124        --WHERE program_mr_header_id = program_rec.program_mr_header_id
7125        --   AND PM_schedule_exists = 'N';
7126 
7127        -- for whichever_last, pick greatest of l_program_calender_days+ contract start date
7128        -- and l_program_due_date.
7129 
7130        IF (program_rec.whichever_first_code = 'FIRST') THEN
7131 
7132           l_upd_SQLstmt_str := 'UPDATE ahl_applicable_mrs' ||
7133                                ' SET program_end_date = LEAST (nvl(:1,contract_end_date),' ||
7134                                                             ' decode(:2,0, contract_end_date, contract_start_date + :3),' ||
7135                                                           ' contract_end_date)' ||
7136                             ' WHERE program_mr_header_id = :4' ||
7137                             '     AND PM_schedule_exists = :5';
7138        ELSE
7139 
7140           l_upd_SQLstmt_str := 'UPDATE ahl_applicable_mrs' ||
7141                                ' SET program_end_date = LEAST ( GREATEST (nvl(:1,contract_end_date),' ||
7142                                                             ' decode(:2,0, contract_end_date, contract_start_date + :3)),' ||
7143                                                           ' contract_end_date)' ||
7144                             ' WHERE program_mr_header_id = :4' ||
7145                             '     AND PM_schedule_exists = :5';
7146        END IF;
7147 
7148 
7149        IF G_DEBUG = 'Y' THEN
7150           AHL_DEBUG_PUB.Debug('SQL string:' || l_upd_SQLstmt_str);
7151        END IF;
7152 
7153        EXECUTE IMMEDIATE l_upd_SQLstmt_str USING l_program_due_date,
7154                                                  l_program_calender_days,
7155                                                  l_program_calender_days,
7156                                                  program_rec.program_mr_header_id,
7157                                                  'N';
7158     END IF;
7159 
7160   END LOOP; /* next program rec */
7161 
7162   IF G_DEBUG = 'Y' THEN
7163      AHL_DEBUG_PUB.Debug('End of CALC_PROGRAM_END_DATES procedure');
7164   END IF;
7165 
7166 END Calc_Program_End_Dates;
7167 
7168 --------------------------------------------------
7169 -- Process records with contract dates scheduled.
7170 PROCEDURE Process_PMSch_Activities  IS
7171 
7172   -- get distinct activities for which due dates have been scheduled for the service.
7173   CURSOR ahl_sch_activity_csr IS
7174     SELECT DISTINCT mr_header_id, csi_item_instance_id, service_line_id,
7175                     program_mr_header_id, contract_end_date, program_end_date,
7176                     show_repetitive_code,
7177                     repetitive_flag
7178     FROM ahl_applicable_mrs
7179     WHERE pm_schedule_exists = 'Y';
7180 
7181   -- Fix for FP bug# 6327241. We should be able to process multiple contracts.
7182   /*
7183   -- get program which have service dates scheduled in the order of importance
7184   -- and contract_start_date. Process only the first one.
7185   CURSOR ahl_cont_scheduled_csr(p_mr_header_id IN NUMBER) IS
7186     SELECT mr_header_id, service_line_id, mr_effectivity_id,
7187            program_mr_header_id, contract_end_date, program_end_date
7188     FROM ahl_applicable_mrs
7189     WHERE mr_header_id = p_mr_header_id
7190          AND pm_schedule_exists = 'Y'
7191     ORDER BY coverage_imp_level , contract_start_date;
7192   */
7193   -- Temporary fix for bug# 3022915.
7194   -- Get due date associated to the accomplishment date.
7195   /*
7196   -- fix for FP bug# 5223862.
7197   CURSOR ahl_due_date_csr(p_accomplishment_date IN DATE,
7198                           p_mr_header_id         IN NUMBER,
7199                           p_csi_item_instance_id IN NUMBER) IS
7200     SELECT due_date
7201     FROM ahl_unit_effectivities_b
7202     WHERE mr_header_id = p_mr_header_id
7203       AND csi_item_instance_id = p_csi_item_instance_id
7204       AND trunc(accomplished_date) = trunc(p_accomplishment_date)
7205       AND status_code IN ('ACCOMPLISHED','INIT-ACCOMPLISHED','TERMINATED')
7206     ORDER BY due_date desc;
7207   */
7208 
7209   -- Added filter by service_line_id to avoid issues caused by oks bug - 4574548
7210   -- wherein SRs associated to higher due dates are accomplished before lesser
7211   -- due date and the contract may have expired/terminated.
7212   CURSOR ahl_due_date_csr(--p_accomplishment_date  IN DATE,
7213                           p_mr_header_id         IN NUMBER,
7214                           p_csi_item_instance_id IN NUMBER,
7215                           p_service_line_id      IN NUMBER) IS
7216     SELECT due_date, accomplished_date
7217     FROM ahl_unit_effectivities_b
7218     WHERE mr_header_id = p_mr_header_id
7219       AND csi_item_instance_id = p_csi_item_instance_id
7220       AND service_line_id = p_service_line_id
7221       --AND trunc(accomplished_date) = trunc(p_accomplishment_date)
7222       AND status_code IN ('ACCOMPLISHED','INIT-ACCOMPLISHED','TERMINATED')
7223     ORDER BY accomplished_date desc, due_date desc;
7224 
7225   --l_cont_scheduled_rec ahl_cont_scheduled_csr%ROWTYPE;
7226   /* record structure holding the service line and program details. */
7227 
7228   l_due_date        DATE;
7229   l_first_array_index  NUMBER;
7230   l_forecast_sequence  NUMBER := 0;
7231 
7232   -- parameters needed to call OKS API.
7233   l_pm_schedule_tbl OKS_PM_ENTITLEMENTS_PUB.pm_sch_tbl_type;
7234   l_inp_sch_rec     OKS_PM_ENTITLEMENTS_PUB.inp_sch_rec;
7235   l_return_status   VARCHAR2(1);
7236   l_msg_count       NUMBER;
7237   l_msg_data        VARCHAR2(2000);
7238 
7239 
7240   l_del_SQLstmt_str VARCHAR2(2000);
7241 
7242   l_temp_unit_effectivity_rec  ahl_temp_unit_effectivities%ROWTYPE;
7243   /* record structure to hold the activity and due date details */
7244 
7245   -- Added to fix bug# 3546136.
7246   l_temp_ue_initrec           ahl_temp_unit_effectivities%ROWTYPE;
7247 
7248   -- parameters needed to call get_accomplishment_details.
7249   l_last_accomplishment_date  DATE;
7250   l_last_acc_counter_val_tbl  counter_values_tbl_type;
7251   l_current_usage_tbl         counter_values_tbl_type;
7252   l_counter_rules_tbl         counter_rules_tbl_type;
7253   l_dependent_mr_flag         BOOLEAN;
7254   l_get_preceding_next_due    BOOLEAN;
7255   l_applicable_mrs_rec        applicable_mrs_rec_type;
7256   l_one_time_mr_flag          BOOLEAN;
7257   l_last_due_date             DATE;
7258 
7259   -- Added for bug# 6711228
7260   l_no_forecast_flag          BOOLEAN;
7261   l_mr_accomplish_exists      BOOLEAN;
7262 
7263 BEGIN
7264 
7265   IF G_DEBUG = 'Y' THEN
7266      AHL_DEBUG_PUB.Debug('Start of PROCESS_PMSCH_ACTIVITIES procedure');
7267   END IF;
7268 
7269   FOR sch_activity_rec IN ahl_sch_activity_csr LOOP
7270 
7271     IF G_DEBUG = 'Y' THEN
7272         AHL_DEBUG_PUB.Debug('Processing for:' || sch_activity_rec.mr_header_id);
7273         AHL_DEBUG_PUB.Debug('Processing for Item Instance:' || sch_activity_rec.csi_item_instance_id);
7274         AHL_DEBUG_PUB.Debug('Processing for Repetitive flag:' || sch_activity_rec.repetitive_flag);
7275         AHL_DEBUG_PUB.Debug('Processing for SHow Repetitive code:' || sch_activity_rec.show_repetitive_code);
7276     END IF;
7277 
7278     -- initialize forecast sequence for the activity.
7279     l_forecast_sequence := 0;
7280 
7281     -- Fix for FP bug# 6327241. We should be able to process multiple contracts.
7282     /*
7283     OPEN ahl_cont_scheduled_csr(sch_activity_rec.mr_header_id);
7284     FETCH ahl_cont_scheduled_csr INTO l_cont_scheduled_rec;
7285     IF (ahl_cont_scheduled_csr%NOTFOUND) THEN
7286        FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_PMPROGRAM_NOTFOUND');
7287        FND_MESSAGE.Set_Token('PMPROGRAM',sch_activity_rec.mr_header_id);
7288        FND_MSG_PUB.ADD;
7289        CLOSE ahl_cont_scheduled_csr;
7290        RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7291     END IF;
7292 
7293     -- check for existence of accomplishments.
7294 
7295     -- initialize.
7296     l_one_time_mr_flag := FALSE;
7297 
7298     -- build applicable_mrs_rec.
7299     l_applicable_mrs_rec.mr_header_id := sch_activity_rec.mr_header_id;
7300     l_applicable_mrs_rec.csi_item_instance_id := sch_activity_rec.csi_item_instance_id;
7301     l_applicable_mrs_rec.repetitive_flag := sch_activity_rec.repetitive_flag;
7302 
7303     -- Check if accomplishment details exist.
7304     Get_accomplishment_details(p_applicable_mrs_rec => l_applicable_mrs_rec,
7305                                p_current_usage_tbl  => l_current_usage_tbl,
7306                                p_counter_rules_tbl  => l_counter_rules_tbl,
7307                                x_accomplishment_date => l_last_accomplishment_date,
7308                                x_last_acc_counter_val_tbl => l_last_acc_counter_val_tbl,
7309                                x_one_time_mr_flag         => l_one_time_mr_flag,
7310                                x_dependent_mr_flag => l_dependent_mr_flag,
7311                                x_get_preceding_next_due => l_get_preceding_next_due,
7312                                x_mr_accomplish_exists  => l_mr_accomplish_exists,
7313                                x_no_forecast_flag => l_no_forecast_flag );
7314 
7315     -- No need to check l_no_forecast_flag as this does not apply to PM flow.
7316     -- call OKS API to get due dates and process them in case one_time_mr_flag = false.
7317     IF NOT(l_one_time_mr_flag) THEN
7318     */
7319     -- get due date associated to the accomplishment date.
7320     OPEN ahl_due_date_csr (--l_last_accomplishment_date,
7321                            sch_activity_rec.mr_header_id,
7322                            sch_activity_rec.csi_item_instance_id,
7323                            sch_activity_rec.service_line_id);
7324     FETCH ahl_due_date_csr INTO l_last_due_date, l_last_accomplishment_date;
7325     IF (ahl_due_date_csr%FOUND) THEN
7326         IF (l_last_accomplishment_date IS NOT NULL) THEN
7327           IF G_DEBUG = 'Y' THEN
7328              AHL_DEBUG_PUB.debug('l_last_accomplishment_date:' || l_last_accomplishment_date);
7329           END IF;
7330 
7331           /* Fix for FP bug# 6327241
7332           -- get due date associated to the accomplishment date.
7333           OPEN ahl_due_date_csr (l_last_accomplishment_date,
7334                                  sch_activity_rec.mr_header_id,
7335                                  sch_activity_rec.csi_item_instance_id,
7336                                  l_cont_scheduled_rec.service_line_id);
7337           FETCH ahl_due_date_csr INTO l_last_due_date;
7338           CLOSE ahl_due_date_csr;
7339           */
7340 
7341           IF (l_last_due_date IS NOT NULL) THEN
7342             IF G_DEBUG = 'Y' THEN
7343                AHL_DEBUG_PUB.Debug('l_last_due_date is not null:' || l_last_due_date);
7344             END IF;
7345 
7346             l_last_accomplishment_date := l_last_due_date + 1;
7347           END IF;
7348         ELSE
7349           l_last_accomplishment_date := NULL;
7350         END IF;
7351     ELSE
7352      l_last_accomplishment_date := NULL;
7353     END IF;
7354     CLOSE ahl_due_date_csr;
7355 
7356         l_inp_sch_rec.service_line_id     := sch_activity_rec.service_line_id;
7357         l_inp_sch_rec.program_id          := sch_activity_rec.program_mr_header_id;
7358         l_inp_sch_rec.activity_id         := sch_activity_rec.mr_header_id;
7359         l_inp_sch_rec.schedule_start_date := l_last_accomplishment_date;
7360         l_inp_sch_rec.schedule_end_date   := G_last_day_of_window; /* uptill rolling window */
7361 
7362         -- Call contracts API to get due dates.
7363          OKS_PM_ENTITLEMENTS_PUB.Get_PM_Schedule (
7364                                p_api_version   => 1.0,
7365                                p_init_msg_list => OKC_API.G_FALSE,
7366                                p_sch_rec       => l_inp_sch_rec,
7367                                x_return_status => l_return_status,
7368                                x_msg_count     => l_msg_count,
7369                                x_msg_data      => l_msg_data,
7370                                x_pm_schedule   => l_pm_schedule_tbl);
7371 
7372         IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
7373           RAISE FND_API.G_EXC_ERROR;
7374         ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
7375           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
7376         END IF;
7377 
7378         IF G_DEBUG = 'Y' THEN
7379            AHL_DEBUG_PUB.debug('Service Line ID: ' || l_inp_sch_rec.service_line_id);
7380            AHL_DEBUG_PUB.debug('Program ID: ' || l_inp_sch_rec.program_id);
7381            AHL_DEBUG_PUB.debug('Activity ID: ' || l_inp_sch_rec.activity_id);
7382            AHL_DEBUG_PUB.debug('Start Date: ' || to_char(l_inp_sch_rec.schedule_start_date, 'DD-MON-YYYY HH24:MI:SS'));
7383            AHL_DEBUG_PUB.debug('End Date: ' || to_char(l_inp_sch_rec.schedule_end_date, 'DD-MON-YYYY HH24:MI:SS'));
7384            AHL_DEBUG_PUB.debug('Count of l_pm_schedule_tbl is: ' || l_pm_schedule_tbl.count);
7385 
7386            IF (l_pm_schedule_tbl.count > 0 ) THEN
7387                  for i in l_pm_schedule_tbl.first..l_pm_schedule_tbl.last loop
7388                     AHL_DEBUG_PUB.debug('Serv Line for ' || i ||':' || l_pm_schedule_tbl(i).service_line_id);
7389                     AHL_DEBUG_PUB.debug('Sch ON for ' || i ||':' || l_pm_schedule_tbl(i).schedule_on);
7390                     AHL_DEBUG_PUB.debug('Sch Start for ' || i ||':' || l_pm_schedule_tbl(i).schedule_from);
7391                     AHL_DEBUG_PUB.debug('Sch End for ' || i ||':' || l_pm_schedule_tbl(i).schedule_to);
7392                  end loop;
7393            END IF;
7394         END IF;
7395 
7396         -- Write due dates into ahl temporary table.
7397         IF (l_pm_schedule_tbl.COUNT > 0) THEN
7398           l_first_array_index := l_pm_schedule_tbl.FIRST;
7399           /* date associated to this index will be set as 'next due' occurrence */
7400 
7401           FOR i IN l_pm_schedule_tbl.FIRST..l_pm_schedule_tbl.LAST LOOP
7402 
7403             -- initialize.
7404             l_due_date := NULL;
7405             l_temp_unit_effectivity_rec := l_temp_ue_initrec;
7406 
7407             IF (l_pm_schedule_tbl(i).schedule_on IS NOT NULL) AND
7408              (l_pm_schedule_tbl(i).schedule_on <> FND_API.G_MISS_DATE) THEN
7409                  l_due_date := l_pm_schedule_tbl(i).schedule_on;
7410             ELSIF (l_pm_schedule_tbl(i).schedule_to IS NOT NULL) AND
7411              (l_pm_schedule_tbl(i).schedule_to <> FND_API.G_MISS_DATE) THEN
7412                  l_due_date := l_pm_schedule_tbl(i).schedule_to;
7413             END IF;
7414 
7415             -- write into temporary table if due date is not null.
7416             IF (l_due_date IS NOT NULL) THEN
7417 
7418               -- Build temporary table record.
7419               l_temp_unit_effectivity_rec.due_date := l_due_date;
7420               l_temp_unit_effectivity_rec.csi_item_instance_id := sch_activity_rec.csi_item_instance_id;
7421               l_temp_unit_effectivity_rec.mr_header_id := sch_activity_rec.mr_header_id;
7422               l_temp_unit_effectivity_rec.program_mr_header_id := sch_activity_rec.program_mr_header_id;
7423               l_temp_unit_effectivity_rec.service_line_id := sch_activity_rec.service_line_id;
7424               -- Added for ER# 2636001.
7425               IF (l_pm_schedule_tbl(i).schedule_from IS NOT NULL AND
7426                   l_pm_schedule_tbl(i).schedule_from <> FND_API.G_MISS_DATE) THEN
7427                  l_temp_unit_effectivity_rec.earliest_due_date := l_pm_schedule_tbl(i).schedule_from;
7428               END IF;
7429               IF (l_pm_schedule_tbl(i).schedule_to IS NOT NULL AND
7430                   l_pm_schedule_tbl(i).schedule_to <> FND_API.G_MISS_DATE) THEN
7431                  l_temp_unit_effectivity_rec.latest_due_date := l_pm_schedule_tbl(i).schedule_to;
7432               END IF;
7433 
7434               -- increment forecast sequence.
7435               l_forecast_sequence := l_forecast_sequence + 1;
7436               l_temp_unit_effectivity_rec.forecast_sequence := l_forecast_sequence;
7437 
7438               -- set repetitive mr flag.
7439               IF (i = l_first_array_index) THEN
7440                  l_temp_unit_effectivity_rec.repetitive_mr_flag := 'N';
7441               ELSE
7442                  l_temp_unit_effectivity_rec.repetitive_mr_flag := 'Y';
7443               END IF;
7444 
7445               -- create record in temporary table.
7446               Create_Temp_Unit_Effectivity (l_temp_unit_effectivity_rec);
7447 
7448             END IF;
7449 
7450             -- Check show_repetitive_code value.
7451             -- If it is = 'NEXT' then exit loop as repetities need not be shown in UMP.
7452             IF (sch_activity_rec.show_repetitive_code = 'NEXT') THEN
7453                EXIT;
7454             END IF;
7455 
7456           END LOOP; /* next record from pm_schedule */
7457 
7458         END IF; /* count */
7459     --END IF; /* one time mr flag */
7460 
7461     -- Delete duplicate programs/contracts for this mr_header_id if they exist.
7462     l_del_SQLstmt_str := 'DELETE FROM ahl_applicable_mrs' ||
7463                          ' WHERE mr_header_id = :1 AND pm_schedule_exists = ''N'' '||
7464                          ' AND service_line_id <> :2';
7465 
7466     IF G_DEBUG = 'Y' THEN
7467        AHL_DEBUG_PUB.Debug('SQL string:' || l_del_SQLstmt_str);
7468     END IF;
7469 
7470     EXECUTE IMMEDIATE l_del_SQLstmt_str USING  sch_activity_rec.mr_header_id,
7471                                                sch_activity_rec.service_line_id;
7472 
7473     --CLOSE ahl_cont_scheduled_csr;
7474   END LOOP; /* for ahl_sch_program_csr */
7475 
7476   IF G_DEBUG = 'Y' THEN
7477      AHL_DEBUG_PUB.debug('End of PROCESS_PMSCH_ACTIVITIES procedure');
7478   END IF;
7479 
7480 END Process_PMSch_Activities;
7481 ----------------------------------------------------------
7482 
7483 PROCEDURE Process_PMUnSch_Activities(p_current_usage_tbl IN counter_values_tbl_type)
7484 IS
7485 
7486   -- get all programs which have no contract dates scheduled.
7487   CURSOR ahl_UnSch_activity_csr IS
7488     SELECT DISTINCT appl.mr_header_id,
7489                     appl.csi_item_instance_id,
7490                     appl.whichever_first_code,
7491                     appl.repetitive_flag,
7492                     appl.show_repetitive_code,
7493                       mr.effective_to,
7494                       mr.effective_from
7495     FROM ahl_applicable_mrs appl, ahl_mr_headers_b mr
7496     WHERE appl.mr_header_id = mr.mr_header_id AND
7497           appl.pm_schedule_exists = 'N';
7498 
7499   l_last_day_of_window   DATE;
7500   l_next_due_flag        BOOLEAN;
7501   l_last_due_date        DATE;
7502   l_due_date             DATE;
7503   l_forecast_sequence    NUMBER;
7504   l_return_value         BOOLEAN;
7505   l_contract_found_flag  BOOLEAN;
7506   l_contract_override_due_date DATE;
7507   l_cont_override_earliest_due DATE;
7508   l_cont_override_latest_due   DATE;
7509 
7510   -- parameter for calculate_due_date procedure.
7511   l_next_due_date_rec         next_due_date_rec_type;
7512 
7513   l_program_mr_header_id NUMBER;
7514   l_service_line_id      NUMBER;
7515   l_contract_start_date  DATE;
7516 
7517   -- parameters to call get_accomplishment_details procedure.
7518   l_counter_rules_tbl         counter_rules_tbl_type;
7519   l_last_accomplishment_date  DATE;
7520   l_last_acc_counter_val_tbl  counter_values_tbl_type;
7521   l_dependent_mr_flag         BOOLEAN;
7522   l_get_preceding_next_due    BOOLEAN;
7523   l_one_time_mr_flag          BOOLEAN;
7524   l_last_due_counter_val_tbl  counter_values_tbl_type;
7525   l_due_at_counter_val_tbl    counter_values_tbl_type;
7526 
7527   l_applicable_mrs_rec        applicable_mrs_rec_type;
7528 
7529   l_temp_unit_effectivity_rec ahl_temp_unit_effectivities%ROWTYPE;
7530   l_temp_ue_initrec           ahl_temp_unit_effectivities%ROWTYPE;
7531 
7532   -- Added for bug# 6711228
7533   l_no_forecast_flag          BOOLEAN;
7534   l_mr_accomplish_exists      BOOLEAN;
7535 
7536   -- Added to fix bug# 6858788.
7537   l_last_due_mr_interval_id   NUMBER;
7538 
7539 BEGIN
7540 
7541   IF G_DEBUG = 'Y' THEN
7542      AHL_DEBUG_PUB.Debug('Start of process_pmunsch_activities procedure');
7543   END IF;
7544 
7545   FOR appl_mrs_rec IN ahl_UnSch_activity_csr LOOP
7546 
7547     -- initialize.
7548     l_forecast_sequence := 0;
7549 
7550     -- build applicable_mrs_rec.
7551     l_applicable_mrs_rec.mr_header_id := appl_mrs_rec.mr_header_id;
7552     l_applicable_mrs_rec.csi_item_instance_id := appl_mrs_rec.csi_item_instance_id;
7553     l_applicable_mrs_rec.whichever_first_code := appl_mrs_rec.whichever_first_code;
7554     l_applicable_mrs_rec.repetitive_flag := appl_mrs_rec.repetitive_flag;
7555     l_applicable_mrs_rec.show_repetitive_code := appl_mrs_rec.show_repetitive_code;
7556     l_applicable_mrs_rec.effective_to := appl_mrs_rec.effective_to;
7557     l_applicable_mrs_rec.effective_from := appl_mrs_rec.effective_from;
7558 
7559     IF G_DEBUG = 'Y' THEN
7560         AHL_DEBUG_PUB.Debug('Processing for:' || appl_mrs_rec.mr_header_id);
7561     END IF;
7562 
7563     -- Set last accomplishment details.
7564     Get_accomplishment_details(p_applicable_mrs_rec => l_applicable_mrs_rec,
7565                                p_current_usage_tbl  => p_current_usage_tbl,
7566                                p_counter_rules_tbl  => l_counter_rules_tbl, -- empty table. n/a for PM installation.
7567                                x_accomplishment_date => l_last_accomplishment_date,
7568                                x_last_acc_counter_val_tbl => l_last_acc_counter_val_tbl,
7569                                x_one_time_mr_flag         => l_one_time_mr_flag,
7570                                x_dependent_mr_flag => l_dependent_mr_flag,
7571                                x_get_preceding_next_due => l_get_preceding_next_due,
7572                                x_mr_accomplish_exists  => l_mr_accomplish_exists,
7573                                x_no_forecast_flag => l_no_forecast_flag );
7574 
7575     IF G_DEBUG = 'Y' THEN
7576        AHL_DEBUG_PUB.Debug('Start of process_pmunsch_activities procedure');
7577     END IF;
7578 
7579     -- No need to check l_no_forecast_flag as this does not apply to PM flow.
7580     -- Check for one time MR case and process otherwise only.
7581     IF NOT(l_one_time_mr_flag) THEN
7582        --dbms_output.put_line('Not one time MR');
7583 
7584        -- Calculate next due date.
7585        -- Added parameter p_dependent_mr_flag to fix bug# 6711228. Issue does
7586        -- not impact PM calculation.
7587        Calculate_Due_Date (p_repetivity_flag => 'N',
7588                            p_applicable_mrs_rec => l_applicable_mrs_rec,
7589                            p_current_usage_tbl => p_current_usage_tbl,
7590                            p_counter_rules_tbl => l_counter_rules_tbl,   -- empty table. n/a for PM installation.
7591                            p_last_due_date => l_last_accomplishment_date,
7592                            p_last_due_counter_val_tbl => l_last_acc_counter_val_tbl,
7593                            p_dependent_mr_flag => l_dependent_mr_flag,
7594                            p_mr_accomplish_exists  => l_mr_accomplish_exists,
7595                            x_next_due_date_rec => l_next_due_date_rec);
7596       IF G_DEBUG = 'Y' THEN
7597         AHL_DEBUG_PUB.Debug('Aft calculate_due_date nextdue');
7598         AHL_DEBUG_PUB.Debug('due date is ' || l_next_due_date_rec.DUE_DATE);
7599       END IF;
7600 
7601       l_next_due_flag := TRUE;
7602       /* next due mr calculation. */
7603 
7604       -- set last due_date values to current values.
7605       l_last_due_date := sysdate;
7606       l_last_due_counter_val_tbl := p_current_usage_tbl;
7607 
7608       -- process next due and repetivity.
7609       LOOP
7610 
7611         -- initialize program and service line for the calculated due date.
7612         l_program_mr_header_id := NULL;
7613         l_service_line_id      := NULL;
7614         l_contract_found_flag  := FALSE;
7615         l_contract_override_due_date := NULL;
7616 
7617         -- Set due_date from l_next_due_date_rec.
7618         l_due_date := l_next_due_date_rec.DUE_DATE;
7619 
7620         IF (l_next_due_flag = TRUE) OR
7621               -- In the case of next-due, if l_due_date is null, get the earliest
7622               -- contract date and program available for the activity; else if
7623               -- l_due_date is not null, get the appropriate contract.
7624            (l_next_due_flag = FALSE AND l_due_date IS NOT NULL AND
7625             trunc(l_due_date) <= trunc(g_last_day_of_window))
7626               -- In the case of repetity and l_due_date is not null.
7627         THEN
7628 
7629            -- get program and service_line_id for the due date calculated.
7630            get_PMprogram(p_csi_item_instance_id   => appl_mrs_rec.csi_item_instance_id,
7631                          p_mr_header_id           => appl_mrs_rec.mr_header_id,
7632                          p_last_due_date          => l_last_due_date,
7633                          p_due_date               => l_due_date,
7634                          p_earliest_due           => l_next_due_date_rec.earliest_due_date,
7635                          p_latest_due             => l_next_due_date_rec.latest_due_date,
7636                          x_program_mr_header_id   => l_program_mr_header_id,
7637                          x_service_line_id        => l_service_line_id,
7638                          x_contract_override_due_date  => l_contract_override_due_date,
7639                          x_cont_override_earliest_due  => l_cont_override_earliest_due,
7640                          x_cont_override_latest_due    => l_cont_override_latest_due,
7641                          x_contract_found_flag         => l_contract_found_flag);
7642 
7643            -- write into temporary table if contract found.
7644            IF (l_contract_found_flag) THEN
7645 
7646                  IF G_DEBUG = 'Y' THEN
7647                     AHL_DEBUG_PUB.debug('contract found for due date:' ||l_due_date);
7648                     AHL_DEBUG_PUB.debug('contract found with override date:' || l_contract_override_due_date);
7649                     AHL_DEBUG_PUB.debug('contract found with override earliest:' || l_cont_override_earliest_due);
7650                     AHL_DEBUG_PUB.debug('contract found with override latest:' || l_cont_override_latest_due);
7651                  END IF;
7652 
7653                  IF (l_contract_override_due_date IS NOT NULL) THEN
7654 
7655                     l_next_due_date_rec.due_date := l_contract_override_due_date;
7656                     l_due_date := l_contract_override_due_date;
7657 
7658                     -- set due counter value and related data to null; as we do not know
7659                     -- the triggered counter value as on l_contract_override_due_date.
7660                     l_next_due_date_rec.due_at_counter_value := null;
7661                     l_next_due_date_rec.mr_effectivity_id    := null;
7662                     l_next_due_date_rec.mr_interval_id       := null;
7663                     l_next_due_date_rec.tolerance_flag       := null;
7664                     l_next_due_date_rec.tolerance_before      := null;
7665                     l_next_due_date_rec.tolerance_after      := null;
7666                     l_next_due_date_rec.message_code         := null;
7667                     l_next_due_date_rec.counter_id         := null;
7668 
7669                  END IF;
7670 
7671                  -- Added for ER# 2636001.
7672                  IF (l_cont_override_earliest_due IS NOT NULL) THEN
7673                     l_next_due_date_rec.earliest_due_date := l_cont_override_earliest_due;
7674                  END IF;
7675                  IF (l_cont_override_latest_due IS NOT NULL) THEN
7676                     l_next_due_date_rec.latest_due_date := l_cont_override_latest_due;
7677                  END IF;
7678 
7679                  -- Build temporary table record.
7680                  l_temp_unit_effectivity_rec := l_temp_ue_initrec; -- initialize.
7681 
7682                  l_temp_unit_effectivity_rec.due_date := l_due_date;
7683                  l_temp_unit_effectivity_rec.csi_item_instance_id := appl_mrs_rec.csi_item_instance_id;
7684                  l_temp_unit_effectivity_rec.mr_header_id := appl_mrs_rec.mr_header_id;
7685                  l_temp_unit_effectivity_rec.program_mr_header_id := l_program_mr_header_id;
7686                  l_temp_unit_effectivity_rec.service_line_id := l_service_line_id;
7687                  l_temp_unit_effectivity_rec.mr_effectivity_id := l_next_due_date_rec.mr_effectivity_id;
7688                  l_temp_unit_effectivity_rec.mr_interval_id := l_next_due_date_rec.mr_interval_id;
7689                  l_temp_unit_effectivity_rec.due_counter_value := l_next_due_date_rec.due_at_counter_value;
7690                  l_temp_unit_effectivity_rec.tolerance_flag := l_next_due_date_rec.tolerance_flag;
7691                  l_temp_unit_effectivity_rec.tolerance_before := l_next_due_date_rec.tolerance_before;
7692                  l_temp_unit_effectivity_rec.tolerance_after := l_next_due_date_rec.tolerance_after;
7693                  l_temp_unit_effectivity_rec.message_code := l_next_due_date_rec.message_code;
7694                  l_temp_unit_effectivity_rec.preceding_check_flag:= 'N';
7695                  --Added for ER# 2636001.
7696                  l_temp_unit_effectivity_rec.earliest_due_date := l_next_due_date_rec.earliest_due_date;
7697                  l_temp_unit_effectivity_rec.latest_due_date := l_next_due_date_rec.latest_due_date;
7698                  -- Added to fix bug#
7699                  l_temp_unit_effectivity_rec.counter_id := l_next_due_date_rec.counter_id;
7700 
7701                  -- increment forecast sequence.
7702                  l_forecast_sequence := l_forecast_sequence + 1;
7703                  l_temp_unit_effectivity_rec.forecast_sequence := l_forecast_sequence;
7704 
7705                  -- set repetivity based on next_due_flag.
7706                  IF (l_next_due_flag) THEN
7707                     l_temp_unit_effectivity_rec.repetitive_mr_flag := 'N';
7708                  ELSE
7709                     l_temp_unit_effectivity_rec.repetitive_mr_flag := 'Y';
7710                  END IF;
7711 
7712                  -- create record in temporary table.
7713                  Create_Temp_Unit_Effectivity (l_temp_unit_effectivity_rec);
7714 
7715                  -- Set next due flag to FALSE after writing record into temporary unit_effectivity.
7716                  IF (l_next_due_flag) THEN
7717                      l_next_due_flag := FALSE;
7718                  END IF;
7719 
7720                  -- Added to fix bug# 6858788
7721                  l_last_due_mr_interval_id := l_next_due_date_rec.mr_interval_id;
7722 
7723            END IF; -- l_contract_found_flag.
7724 
7725         END IF; --l_next_due_flag
7726 
7727         -- exit to process next activity.
7728         EXIT WHEN (l_next_due_flag = FALSE AND l_next_due_date_rec.DUE_DATE IS NULL) OR  -- calculate_due_date returns null.
7729                   (l_next_due_flag = FALSE AND trunc(l_next_due_date_rec.DUE_DATE) > trunc(g_last_day_of_window)) OR
7730                   (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
7731                   (l_next_due_flag = FALSE AND appl_mrs_rec.show_repetitive_code = 'NEXT') OR
7732                   (l_contract_found_flag = FALSE);  -- contract not available.
7733 
7734         -- If due date is a past date, then set it to sysdate.
7735         -- This will happen only when calculating next-due date.
7736         IF (trunc(l_due_date) < trunc(sysdate)) THEN
7737           l_due_date := sysdate;
7738         END IF;
7739 
7740         IF G_DEBUG = 'Y' THEN
7741            AHL_DEBUG_PUB.Debug('Processing for repetivity');
7742            AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
7743            AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
7744            IF (l_last_due_counter_val_tbl.COUNT > 0) THEN
7745               FOR i in l_last_due_counter_val_tbl.FIRST..l_last_due_counter_val_tbl.LAST LOOP
7746                 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);
7747               END LOOP;
7748            END IF;
7749         END IF;
7750 
7751 
7752         -- get all counter values as on l_due_date.
7753         Get_Due_at_Counter_Values (p_last_due_date => l_last_due_date,
7754                                    p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
7755                                    p_due_date => l_due_date,
7756                                    p_counter_rules_tbl => l_counter_rules_tbl,
7757                                    x_due_at_counter_val_tbl => l_due_at_counter_val_tbl,
7758                                    x_return_value => l_return_value);
7759 
7760         IF NOT(l_return_value) THEN  -- no forecast case.
7761            --dbms_output.put_line('l_return_value is false');
7762            EXIT;
7763         END IF;
7764 
7765         -- set current values to previous values.
7766         l_last_due_date := l_due_date;
7767         l_last_due_counter_val_tbl := l_due_at_counter_val_tbl;
7768 
7769         IF G_DEBUG = 'Y' THEN
7770            AHL_DEBUG_PUB.Debug('AFter get_due_at_counter_values');
7771            AHL_DEBUG_PUB.Debug('l_last_due_date: '|| l_last_due_date);
7772            AHL_DEBUG_PUB.Debug('l_due_date: '|| l_due_date);
7773            IF (l_due_at_counter_val_tbl.COUNT) > 0 THEN
7774                FOR i in l_due_at_counter_val_tbl.FIRST..l_due_at_counter_val_tbl.LAST LOOP
7775                    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);
7776                end loop;
7777            END IF;
7778        END IF;
7779 
7780         -- Calculate next due date.
7781         Calculate_Due_Date (p_repetivity_flag => 'Y',
7782                             p_applicable_mrs_rec => l_applicable_mrs_rec,
7783                             p_current_usage_tbl => p_current_usage_tbl,
7784                             p_counter_rules_tbl => l_counter_rules_tbl,
7785                             p_last_due_date => l_last_due_date,
7786                             p_last_due_counter_val_tbl => l_last_due_counter_val_tbl,
7787                             p_mr_accomplish_exists  => l_mr_accomplish_exists,
7788                             p_last_due_mr_interval_id => l_last_due_mr_interval_id,
7789                             x_next_due_date_rec => l_next_due_date_rec);
7790 
7791         IF G_DEBUG = 'Y' THEN
7792            AHL_DEBUG_PUB.Debug('aft calculate_due_date - repetivity');
7793            AHL_DEBUG_PUB.Debug('due date is ' || l_next_due_date_rec.DUE_DATE);
7794         END IF;
7795 
7796         -- Check if calculated date is same as last due date. If they are the same then, add one day.
7797         IF (l_next_due_date_rec.due_date IS NOT NULL) THEN
7798            IF (trunc(l_last_due_date) = trunc(l_next_due_date_rec.due_date)) THEN
7799                l_next_due_date_rec.due_date := l_next_due_date_rec.due_date + 1;
7800                l_next_due_date_rec.EARLIEST_DUE_DATE := NULL;
7801                l_next_due_date_rec.latest_due_date := NULL;
7802 
7803                IF G_DEBUG = 'Y' THEN
7804                  AHL_DEBUG_PUB.Debug('Adding one day to l_next_due_date_rec.due_date:' || l_next_due_date_rec.due_date);
7805                END IF;
7806 
7807                --IF G_DEBUG = 'Y' THEN
7808                --   AHL_DEBUG_PUB.Debug('Exiting build effectivity as last due = due date');
7809                --END IF;
7810                --EXIT;
7811            END IF;
7812         END IF;
7813 
7814       END LOOP; /* process repetivity. */
7815 
7816     END IF; /* one time mr */
7817 
7818   END LOOP; /* ahl_UnSch_contracts_csr */
7819 
7820   IF G_DEBUG = 'Y' THEN
7821      AHL_DEBUG_PUB.debug('End of process_pmunsch_activities procedure');
7822   END IF;
7823 
7824 END Process_PMUnSch_Activities;
7825 
7826 ---------------------------------------------
7827 -- Procedure to find the service_line_id and program for a calculated due_date.
7828 -- The calculated due_date may be overridden by the contract/program dates.
7829 -- Also the earliest due and latest due date will get adjusted if they are not
7830 -- within the contract and program start/end dates.
7831 
7832 PROCEDURE Get_PMprogram(p_csi_item_instance_id       IN  NUMBER,
7833                         p_mr_header_id               IN  NUMBER,
7834                         p_last_due_date              IN  DATE,
7835                         p_due_date                   IN  DATE,
7836                         p_earliest_due               IN  DATE,
7837                         p_latest_due                 IN  DATE,
7838                         x_program_mr_header_id       OUT NOCOPY NUMBER,
7839                         x_service_line_id            OUT NOCOPY NUMBER,
7840                         x_contract_override_due_date OUT NOCOPY DATE,
7841                         x_cont_override_earliest_due OUT NOCOPY DATE,
7842                         x_cont_override_latest_due   OUT NOCOPY DATE,
7843                         x_contract_found_flag        OUT NOCOPY BOOLEAN)
7844 IS
7845 
7846   -- get contract/program for a given due date.
7847   CURSOR ahl_contract_exists_csr(p_mr_header_id  IN NUMBER,
7848                                  p_due_date      IN DATE) IS
7849     SELECT program_mr_header_id,
7850            service_line_id, contract_start_date, contract_end_date, program_end_date
7851     FROM ahl_applicable_mrs
7852     WHERE mr_header_id = p_mr_header_id
7853       AND pm_schedule_exists = 'N'
7854       AND trunc(program_end_date) >= trunc(p_due_date) -- eliminate expired programs.
7855       AND trunc(p_due_date) >= trunc(contract_start_date)
7856       AND trunc(p_due_date) <= LEAST(trunc(contract_end_date), nvl(trunc(program_end_date),trunc(contract_end_date)))
7857     ORDER BY contract_start_date;
7858 
7859   -- get the next contract (if available).
7860   CURSOR ahl_next_contract_csr (p_mr_header_id IN NUMBER,
7861                                 p_due_date     IN DATE) IS
7862     SELECT program_mr_header_id,
7863            service_line_id,
7864            contract_start_date, contract_end_date, program_end_date
7865     FROM ahl_applicable_mrs
7866     WHERE pm_schedule_exists = 'N'
7867       AND trunc(program_end_date) >= trunc(p_due_date) -- eliminate expired programs.
7868       AND mr_header_id = p_mr_header_id
7869       AND trunc(p_due_date) <= trunc(contract_start_date)
7870     ORDER BY contract_start_date;
7871 
7872 
7873   l_program_mr_header_id  NUMBER;
7874   /* program header id for the due date. */
7875 
7876   l_service_line_id    NUMBER;
7877   /* service line id for the due date. */
7878 
7879   l_due_date           DATE := p_due_date;
7880 
7881   l_contract_start_date DATE;
7882   l_program_end_date    DATE;
7883   l_contract_end_date   DATE;
7884 
7885   l_contract_override_due_date  DATE := NULL;
7886   -- this is set only if there exists no contract for the
7887   -- input due date but there is a contract that starts at
7888   -- a later date.
7889 
7890 
7891 BEGIN
7892 
7893   IF G_DEBUG = 'Y' THEN
7894      AHL_DEBUG_PUB.debug('Start of Get_PMprogram procedure for MR:Due Date is: ' ||
7895             p_mr_header_id || ':' || p_due_date);
7896   END IF;
7897 
7898   -- Initialize.
7899   x_program_mr_header_id := NULL;
7900   x_service_line_id := NULL;
7901   x_contract_override_due_date := NULL;
7902   x_contract_found_flag := FALSE;
7903   x_cont_override_earliest_due := NULL;
7904   x_cont_override_latest_due := NULL;
7905 
7906   -- if p_due_date is null, set it = sysdate; so that it picks ups the earliest contract.
7907   IF (l_due_date IS NULL) THEN
7908       l_due_date := sysdate;
7909   END IF;
7910 
7911   -- Check if calculated due date belongs to any contracts.
7912   OPEN ahl_contract_exists_csr (p_mr_header_id,
7913                                 l_due_date);
7914   FETCH ahl_contract_exists_csr INTO l_program_mr_header_id,
7915                                      l_service_line_id,
7916                                      l_contract_start_date,
7917                                      l_contract_end_date,
7918                                      l_program_end_date;
7919   IF (ahl_contract_exists_csr%FOUND) THEN
7920      x_program_mr_header_id := l_program_mr_header_id;
7921      x_service_line_id := l_service_line_id;
7922      x_contract_override_due_date := NULL;
7923      x_contract_found_flag := TRUE;
7924 
7925      -- In the case due_date is null, return sysdate as due date.
7926      IF (p_due_date IS NULL) THEN
7927         x_contract_override_due_date := l_due_date;
7928      END IF;
7929      -- Added for ER# 2636001.
7930      IF (trunc(p_earliest_due) < trunc(l_contract_start_date)) THEN
7931        x_cont_override_earliest_due := l_contract_start_date;
7932      END IF;
7933      -- if program end date not available, then replace with contract end date.
7934      IF (trunc(p_latest_due) > LEAST(trunc(l_contract_end_date),
7935                                      trunc(nvl(l_program_end_date, l_contract_end_date))))
7936      THEN
7937          x_cont_override_latest_due  := LEAST(trunc(l_contract_end_date),
7938                                               trunc(nvl(l_program_end_date,l_contract_end_date)));
7939      END IF;
7940 
7941   ELSE
7942     -- Look for next contract if exists.
7943     OPEN ahl_next_contract_csr (p_mr_header_id, l_due_date);
7944     FETCH ahl_next_contract_csr INTO l_program_mr_header_id,
7945                                      l_service_line_id,
7946                                      l_contract_start_date,
7947                                      l_contract_end_date,
7948                                      l_program_end_date;
7949       IF (ahl_next_contract_csr%FOUND) THEN
7950          x_program_mr_header_id := l_program_mr_header_id;
7951          x_service_line_id := l_service_line_id;
7952          x_contract_override_due_date := l_contract_start_date;
7953          x_contract_found_flag := TRUE;
7954 
7955          -- Added for ER# 2636001.
7956          IF (trunc(p_earliest_due) < trunc(l_contract_start_date)) THEN
7957            x_cont_override_earliest_due := l_contract_start_date;
7958          END IF;
7959          -- if program end date not available, then replace with contract end date.
7960          IF (trunc(p_latest_due) > LEAST(trunc(l_contract_end_date),
7961                                          trunc(nvl(l_program_end_date, l_contract_end_date))))
7962          THEN
7963              x_cont_override_latest_due  := LEAST(trunc(l_contract_end_date),
7964                                                   trunc(nvl(l_program_end_date,l_contract_end_date)));
7965          END IF;
7966 
7967       END IF;
7968 
7969     CLOSE ahl_next_contract_csr;
7970   END IF;
7971   CLOSE ahl_contract_exists_csr;
7972 
7973   IF G_DEBUG = 'Y' THEN
7974     IF NOT(x_contract_found_flag) THEN
7975       AHL_DEBUG_PUB.debug('Contract Not Found');
7976     END IF;
7977     AHL_DEBUG_PUB.debug('End of Get_PMprogram procedure');
7978   END IF;
7979 
7980 END Get_PMprogram;
7981 
7982 -------------------------------------------------------------
7983 -- After creation of all maintenance requirements for the instance in the temporary table,
7984 -- assign unit effectivity IDs from existing un-accomplished maintenance requirements
7985 -- belonging to the same instance from ahl_unit_effectivities_b.
7986 PROCEDURE Assign_Unit_Effectivity_IDs IS
7987 
7988   -- Added service_line_id to fix FP bug# 5481605.
7989   -- read temporary table sequentially.
7990   CURSOR ahl_mr_header_csr IS
7991     SELECT DISTINCT mr_header_id, csi_item_instance_id, service_line_id
7992     FROM ahl_temp_unit_effectivities;
7993 
7994   -- retrieve current unit effectivity records.
7995   CURSOR ahl_unit_effectivity_csr (p_csi_item_instance_id IN NUMBER,
7996                                    p_mr_header_id IN NUMBER,
7997                                    p_service_line_id IN NUMBER,
7998                                    p_appl_usg_code   IN VARCHAR2) IS
7999     SELECT ue.unit_effectivity_id
8000     FROM   ahl_unit_effectivities_b UE
8001     WHERE  mr_header_id = p_mr_header_id
8002        AND csi_item_instance_id = p_csi_item_instance_id
8003        AND application_usg_code = p_appl_usg_code
8004        AND service_line_id = p_service_line_id
8005        AND (UE.Status_code IS NULL OR status_code IN ('INIT-DUE','DEFERRED'))
8006     --ORDER BY forecast_sequence ASC;
8007     ORDER BY unit_effectivity_id ASC;  -- fix FP bug# 5481605.
8008 
8009   CURSOR ahl_temp_effectivity_csr(p_csi_item_instance_id IN NUMBER,
8010                                   p_mr_header_id IN NUMBER,
8011                                   p_service_line_id IN NUMBER) IS
8012     SELECT unit_effectivity_id
8013     FROM ahl_temp_unit_effectivities
8014     WHERE mr_header_id = p_mr_header_id
8015        AND csi_item_instance_id = p_csi_item_instance_id
8016        AND service_line_id = p_service_line_id
8017     FOR UPDATE OF unit_effectivity_id
8018     ORDER BY forecast_sequence ASC;
8019 
8020   l_unit_effectivity_id  NUMBER;
8021 
8022   l_ue_id_tbl      nbr_tbl_type;
8023   l_appl_usg_code  ahl_unit_effectivities_b.application_usg_code%TYPE;
8024 
8025 BEGIN
8026 
8027    IF G_DEBUG = 'Y' THEN
8028       AHL_DEBUG_PUB.debug('Start of assign_unit_effectivity_ids procedure');
8029    END IF;
8030 
8031    -- Application usage code.
8032    l_appl_usg_code := FND_PROFILE.VALUE('AHL_APPLN_USAGE');
8033 
8034    -- For each mr_header_id assign the unit effectivity IDs.
8035    -- note: All mr's are for one item instance only.
8036 
8037    FOR mr_header_rec IN ahl_mr_header_csr LOOP
8038      --dbms_output.put_line('Processing for:' ||  mr_header_rec.mr_header_id);
8039 
8040      -- Added service_line_id to fix FP bug# 5481605.
8041      -- open temporary table cursor.
8042      OPEN ahl_temp_effectivity_csr(mr_header_rec.csi_item_instance_id,
8043                                    mr_header_rec.mr_header_id,
8044                                    mr_header_rec.service_line_id);
8045 
8046      -- loop through all unit_effectivity records.
8047      /*FOR unit_effectivity_rec IN ahl_unit_effectivity_csr(mr_header_rec.csi_item_instance_id,
8048                                                           mr_header_rec.mr_header_id,
8049                                                           mr_header_rec.service_line_id)
8050      */
8051      OPEN ahl_unit_effectivity_csr(mr_header_rec.csi_item_instance_id,
8052                                    mr_header_rec.mr_header_id,
8053                                    mr_header_rec.service_line_id,
8054                                    l_appl_usg_code);
8055 
8056      LOOP
8057        FETCH ahl_unit_effectivity_csr BULK COLLECT INTO l_ue_id_tbl LIMIT 1000;
8058        EXIT WHEN (l_ue_id_tbl.count = 0);
8059 
8060        IF (l_ue_id_tbl.count > 0) THEN
8061          FOR i IN l_ue_id_tbl.FIRST..l_ue_id_tbl.LAST LOOP
8062 
8063            -- Fetch record from temporary table.
8064            FETCH  ahl_temp_effectivity_csr INTO l_unit_effectivity_id;
8065            IF (ahl_temp_effectivity_csr%NOTFOUND) THEN
8066               -- exit ahl_unit_effectivity_csr loop as no more records to assign.
8067               EXIT;
8068            ELSE
8069 
8070               --dbms_output.put_line('found ue.unit_effectivity_id:' || unit_effectivity_rec.unit_effectivity_id);
8071 
8072               --l_unit_effectivity_id := unit_effectivity_rec.unit_effectivity_id;
8073               l_unit_effectivity_id := l_ue_id_tbl(i);
8074 
8075               -- update record.
8076 
8077               UPDATE ahl_temp_unit_effectivities
8078               SET unit_effectivity_id = l_unit_effectivity_id
8079               WHERE CURRENT OF ahl_temp_effectivity_csr;
8080            END IF; -- ahl_temp_effectivity_csr%NOTFOUND
8081          END LOOP; -- l_ue_id_tbl.FIRST
8082        END IF; -- l_ue_id_tbl.count > 0
8083 
8084        IF (ahl_temp_effectivity_csr%NOTFOUND) THEN
8085          EXIT; -- exit ahl_unit_effectivity_csr LOOP
8086        END IF;
8087 
8088        l_ue_id_tbl.DELETE;
8089 
8090      END LOOP; -- ahl_unit_effectivity_csr
8091      CLOSE ahl_temp_effectivity_csr;
8092      CLOSE ahl_unit_effectivity_csr;
8093 
8094    END LOOP; -- ahl_mr_header_csr.
8095 
8096    IF G_DEBUG = 'Y' THEN
8097       AHL_DEBUG_PUB.debug('End of assign_unit_effectivity_ids procedure');
8098    END IF;
8099 
8100 END Assign_Unit_Effectivity_IDs;
8101 
8102 -------------------------------------------------------------
8103 -- Procedure to calculate due date based on deferral details.
8104 PROCEDURE Get_Deferred_Due_Date (p_unit_effectivity_id IN NUMBER,
8105                                  p_deferral_threshold_tbl IN  counter_values_tbl_type,
8106                                  x_due_date               OUT NOCOPY DATE,
8107                                  x_return_status          OUT NOCOPY VARCHAR2,
8108                                  x_msg_data               OUT NOCOPY VARCHAR2,
8109                                  x_msg_count              OUT NOCOPY NUMBER)
8110 IS
8111 
8112   -- Get Unit Effectivity details.
8113   CURSOR ahl_unit_effectivity_csr (p_unit_effectivity_id IN NUMBER) IS
8114     SELECT csi_item_instance_id, mr_header_id
8115     FROM ahl_unit_effectivities_app_v
8116     WHERE unit_effectivity_id = p_unit_effectivity_id;
8117 
8118   -- Get MR details.
8119   CURSOR ahl_mr_headers_csr (p_mr_header_id IN NUMBER) IS
8120     SELECT whichever_first_code
8121     FROM ahl_mr_headers_app_v
8122     WHERE mr_header_id = p_mr_header_id;
8123 
8124   -- get the configuration structure.(G_config_node_tbl).
8125   CURSOR csi_reln_csr ( p_csi_item_instance_id IN NUMBER) IS
8126     SELECT position_reference
8127     FROM csi_ii_relationships
8128     WHERE subject_id = p_csi_item_instance_id
8129                AND relationship_type_code = 'COMPONENT-OF'
8130                AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
8131                AND trunc(sysdate) < trunc(nvl(active_end_date, sysdate+1));
8132 
8133   -- get the counter usage
8134   CURSOR cs_ctr_counter_csr (p_csi_item_instance_id  IN NUMBER,
8135                              p_counter_id            IN NUMBER) IS
8136   /*
8137   SELECT nvl(net_reading, 0)
8138   FROM csi_cp_counters_v
8139   WHERE customer_product_id = p_csi_item_instance_id
8140     AND counter_id = p_counter_id;
8141   */
8142 
8143   SELECT nvl(cv.net_reading,0) net_reading
8144      FROM csi_counter_values_v cv
8145      WHERE cv.counter_id = p_counter_id
8146        AND cv.counter_id IN (select counter_id
8147                              from   csi_counter_associations cca
8148                              where  source_object_code = 'CP'
8149                              AND    source_object_id = p_csi_item_instance_id
8150                              AND    cca.counter_id = cv.counter_id)
8151        AND rownum < 2;
8152 
8153   i                       NUMBER;
8154   l_csi_item_instance_id  NUMBER;
8155   l_root_csi_instance_id  NUMBER;
8156   l_mr_header_id          NUMBER;
8157   l_uc_header_id          NUMBER;
8158   l_calc_due_date         DATE;
8159   l_due_date              DATE;
8160   l_whichever_first_code  ahl_mr_headers_app_v.whichever_first_code%TYPE;
8161   l_inv_master_organization_id number;
8162   l_inventory_item_id     number;
8163   l_position_reference    VARCHAR2(30);
8164   l_counter_rules_tbl     counter_rules_tbl_type;
8165   l_current_usage_tbl     counter_values_tbl_type;
8166   l_counter_value         number;
8167   l_counter_remain        number;
8168 
8169   -- Global variables.
8170   G_master_config_id      NUMBER;
8171 
8172 BEGIN
8173 
8174   -- Set return status.
8175   x_return_status := FND_API.G_RET_STS_SUCCESS;
8176 
8177   -- Enable Debug.
8178   IF G_DEBUG = 'Y' THEN
8179     AHL_DEBUG_PUB.enable_debug;
8180   END IF;
8181 
8182   -- Add debug mesg.
8183   IF G_DEBUG = 'Y' THEN
8184     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Get_Deferred_Due_Date');
8185     AHL_DEBUG_PUB.debug('Dump of input parameters:');
8186     AHL_DEBUG_PUB.debug('Unit Effectivity ID:' || p_unit_effectivity_id);
8187     AHL_DEBUG_PUB.debug('Count on p_deferral_threshold_tbl:' || p_deferral_threshold_tbl.COUNT);
8188   END IF;
8189 
8190   -- Validate input parameters.
8191   IF (p_unit_effectivity_id IS NULL OR p_unit_effectivity_id = FND_API.G_MISS_NUM) THEN
8192      FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_UE_NULL');
8193      FND_MSG_PUB.ADD;
8194      RAISE FND_API.G_EXC_ERROR;
8195   ELSE
8196      OPEN ahl_unit_effectivity_csr (p_unit_effectivity_id);
8197      FETCH ahl_unit_effectivity_csr INTO l_csi_item_instance_id, l_mr_header_id;
8198      IF (ahl_unit_effectivity_csr%NOTFOUND) THEN
8199         FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_UE_INVALID');
8200         FND_MESSAGE.Set_Token('UE_ID', p_unit_effectivity_id);
8201         FND_MSG_PUB.ADD;
8202         RAISE FND_API.G_EXC_ERROR;
8203      END IF;
8204   END IF;
8205 
8206   IF (l_mr_header_id IS NOT NULL) THEN
8207      -- get MR details from ahl_mr_headers.
8208      OPEN ahl_mr_headers_csr(l_mr_header_id);
8209      FETCH ahl_mr_headers_csr INTO l_whichever_first_code;
8210      IF (ahl_mr_headers_csr%NOTFOUND) THEN
8211        FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_MR_INVALID');
8212        FND_MESSAGE.Set_Token('UE_ID', p_unit_effectivity_id);
8213        FND_MSG_PUB.ADD;
8214        RAISE FND_API.G_EXC_ERROR;
8215      END IF;
8216      CLOSE ahl_mr_headers_csr;
8217   ELSE
8218      -- SR case.
8219      l_whichever_first_code := 'FIRST';
8220   END IF;
8221 
8222   IF G_DEBUG = 'Y' THEN
8223     AHL_DEBUG_PUB.debug('Step 1');
8224     AHL_DEBUG_PUB.debug('MR Header ID:' || l_mr_header_id);
8225     AHL_DEBUG_PUB.debug('CSI Item Instance ID:' || l_csi_item_instance_id);
8226   END IF;
8227 
8228   -- Get Unit and Master Config IDs if available.
8229   -- Find the root item instance.
8230   l_root_csi_instance_id := Get_RootInstanceID(l_csi_item_instance_id);
8231 
8232   -- Get master and unit configuration for the root item instance.
8233   Get_Unit_Master_ConfigIDs (l_root_csi_instance_id,
8234                              l_uc_header_id, G_master_config_id);
8235 
8236   IF G_DEBUG = 'Y' THEN
8237     AHL_DEBUG_PUB.debug('Step 2');
8238   END IF;
8239 
8240   -- Check for errors.
8241   IF FND_MSG_PUB.Count_msg > 0 THEN
8242      RAISE FND_API.G_EXC_ERROR;
8243   END IF;
8244 
8245   IF G_DEBUG = 'Y' THEN
8246     AHL_DEBUG_PUB.debug('Step 3');
8247   END IF;
8248 
8249   -- Get utilization forecast for the unit/part.
8250   Get_Utilization_Forecast (l_root_csi_instance_id,
8251                             l_uc_header_id,
8252                             l_inventory_item_id,
8253                             l_inv_master_organization_id,
8254                             G_forecast_details_tbl);
8255 
8256   IF G_DEBUG = 'Y' THEN
8257     AHL_DEBUG_PUB.debug('Step 4');
8258     AHL_DEBUG_PUB.debug('Count on util forecast tbl:' || G_forecast_details_tbl.count);
8259   END IF;
8260 
8261   -- Get the position installed in.
8262   OPEN csi_reln_csr(l_csi_item_instance_id);
8263   FETCH csi_reln_csr INTO l_position_reference;
8264   IF (csi_reln_csr%NOTFOUND) THEN
8265      l_position_reference := G_master_config_id;
8266   END IF;
8267   CLOSE csi_reln_csr;
8268 
8269   IF G_DEBUG = 'Y' THEN
8270     AHL_DEBUG_PUB.debug('Step 5');
8271   END IF;
8272 
8273   -- Build counter rules ratio if node is not root node.
8274   IF (G_master_config_id IS NOT NULL AND l_position_reference IS NOT NULL) THEN
8275       build_Counter_Ratio(l_position_reference,
8276                           l_csi_item_instance_id,
8277                           G_master_config_id,
8278                           l_counter_rules_tbl);
8279   END IF;
8280 
8281   IF G_DEBUG = 'Y' THEN
8282     AHL_DEBUG_PUB.debug('Step 6');
8283   END IF;
8284 
8285   -- Calculate counter_remain and call get_date_from_uf.
8286   IF (p_deferral_threshold_tbl.COUNT > 0) THEN
8287      FOR i IN p_deferral_threshold_tbl.FIRST..p_deferral_threshold_tbl.LAST LOOP
8288        -- get the usage based on deferral effective on.
8289        OPEN cs_ctr_counter_csr(l_csi_item_instance_id, p_deferral_threshold_tbl(i).counter_id);
8290        FETCH cs_ctr_counter_csr INTO l_counter_value;
8291        IF (cs_ctr_counter_csr%NOTFOUND) THEN
8292           IF G_DEBUG = 'Y' THEN
8293             AHL_DEBUG_PUB.debug('Step 7');
8294           END IF;
8295           l_counter_value := 0;
8296        END IF;
8297 
8298        CLOSE cs_ctr_counter_csr;
8299 
8300        IF G_DEBUG = 'Y' THEN
8301          AHL_DEBUG_PUB.debug('l_counter_value:' || l_counter_value);
8302        END IF;
8303 
8304        -- Get due date for counter remain.
8305        l_counter_remain := p_deferral_threshold_tbl(i).counter_value - l_counter_value;
8306 
8307        IF G_DEBUG = 'Y' THEN
8308          AHL_DEBUG_PUB.debug('l_counter_remain:' || l_counter_remain);
8309        END IF;
8310 
8311        -- get date from forecast.
8312        get_date_from_uf(l_counter_remain,
8313                         p_deferral_threshold_tbl(i).uom_code,
8314                         l_counter_rules_tbl,
8315                         sysdate,
8316                         l_due_date);
8317 
8318        IF (l_due_date IS NULL) THEN
8319            l_calc_due_date := NULL;
8320            EXIT;
8321        ELSIF (l_calc_due_date IS NULL) THEN
8322            l_calc_due_date := l_due_date;
8323        ELSIF (l_whichever_first_code = 'FIRST') THEN
8324            IF (trunc(l_due_date) < trunc(l_calc_due_date)) THEN
8325              l_calc_due_date := l_due_date;
8326            END IF;
8327        ELSIF (l_whichever_first_code = 'LAST') THEN
8328            IF (trunc(l_due_date) > trunc(l_calc_due_date)) THEN
8329              l_calc_due_date := l_due_date;
8330            END IF;
8331        END IF;
8332 
8333      END LOOP;
8334   END IF;
8335   x_due_date := l_calc_due_date;
8336 
8337   -- Standard call to get message count and if count is 1, get message info
8338   FND_MSG_PUB.Count_And_Get
8339     ( p_count => x_msg_count,
8340       p_data  => x_msg_data,
8341       p_encoded => fnd_api.g_false
8342     );
8343 
8344 --
8345 EXCEPTION
8346  WHEN FND_API.G_EXC_ERROR THEN
8347    x_return_status := FND_API.G_RET_STS_ERROR;
8348    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
8349                               p_data  => x_msg_data,
8350                               p_encoded => fnd_api.g_false);
8351 
8352    -- Disable debug
8353    AHL_DEBUG_PUB.disable_debug;
8354 
8355  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
8356    x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
8357    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
8358                               p_data  => x_msg_data,
8359                               p_encoded => fnd_api.g_false);
8360 
8361    -- Disable debug
8362    AHL_DEBUG_PUB.disable_debug;
8363 
8364  WHEN OTHERS THEN
8365 
8366     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
8367     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
8368        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
8369                                p_procedure_name => 'Get_Deferred_Due_Date',
8370                                p_error_text     => SUBSTR(SQLERRM,1,240));
8371     END IF;
8372     FND_MSG_PUB.count_and_get( p_count => x_msg_count,
8373                                p_data  => x_msg_data,
8374                                p_encoded => fnd_api.g_false);
8375 
8376 
8377     -- Disable debug
8378     AHL_DEBUG_PUB.disable_debug;
8379 
8380 END Get_Deferred_Due_Date;
8381 ------------------------------------------------------------------
8382 
8383 -- Get the latest recorded counter reading for a given date.
8384 PROCEDURE get_ctr_reading_for_date (p_csi_item_instance_id IN NUMBER,
8385                                     p_counter_id           IN NUMBER,
8386                                     p_reading_date         IN DATE,
8387                                     x_net_reading        OUT NOCOPY NUMBER) IS
8388 
8389   -- get the latest reading recorded for a counter on any given date.
8390   CURSOR cs_ctr_reading_csr(p_csi_item_instance_id IN NUMBER,
8391                             p_counter_id           IN NUMBER,
8392                             p_reading_date IN DATE) IS
8393     /*SELECT net_reading
8394     FROM cs_ctr_counter_values_v cv, cs_counter_groups cg
8395     WHERE cv.counter_group_id = cg.counter_group_id
8396       AND cg.source_object_code = 'CP'
8397       AND cg.source_object_id = p_csi_item_instance_id
8398       AND cv.counter_id = p_counter_id
8399       AND trunc(VALUE_TIMESTAMP) <= trunc(p_reading_date)
8400     ORDER BY cv.value_timestamp desc; */
8401 
8402 	--priyan
8403 	--Query being changed due to performance related fixes
8404 	--Refer Bug # 4918744
8405 
8406         /* Commented out to fix bug# 6445866. In R12, IB is not instantiating
8407          * counter groups in CS_CSI_COUNTER_GROUPS.
8408 	SELECT --DISTINCT
8409 		CCR.NET_READING
8410 	FROM
8411 		CSI_COUNTERS_VL CC,
8412 		--CS_COUNTER_GROUPS CCA,
8413 		--priyan
8414 		--changes for Bug #5207990.
8415 		CS_CSI_COUNTER_GROUPS CCA,
8416 		CSI_COUNTER_READINGS CCR
8417 	WHERE
8418 		CC.DEFAULTED_GROUP_ID (+)  = CCA.COUNTER_GROUP_ID
8419 		AND CCA.SOURCE_OBJECT_CODE = 'CP'
8420 		AND CCR.COUNTER_ID		   = CC.COUNTER_ID
8421 		AND CCA.SOURCE_OBJECT_ID   = P_CSI_ITEM_INSTANCE_ID
8422 		AND CC.COUNTER_ID          = P_COUNTER_ID
8423 		AND TRUNC(CCR.VALUE_TIMESTAMP) <= TRUNC(P_READING_DATE)
8424 	ORDER BY
8425 		CCR.VALUE_TIMESTAMP DESC;
8426 
8427         */
8428 
8429         SELECT * FROM (
8430     	               SELECT CCR.NET_READING
8431   	               FROM
8432 		               CSI_COUNTER_READINGS CCR
8433 	               WHERE
8434 		               CCR.COUNTER_ID          = P_COUNTER_ID
8435                                AND nvl(CCR.disabled_flag,'N') = 'N'
8436 		               AND TRUNC(CCR.VALUE_TIMESTAMP) <= TRUNC(P_READING_DATE)
8437 	               ORDER BY
8438 		               CCR.VALUE_TIMESTAMP DESC
8439                       )
8440         WHERE rownum < 2;
8441 
8442 
8443   l_net_reading  NUMBER;
8444 
8445 BEGIN
8446 
8447     IF G_DEBUG = 'Y' THEN
8448       AHL_DEBUG_PUB.debug('Start of get_ctr_reading_for_date');
8449     END IF;
8450 
8451     OPEN cs_ctr_reading_csr(p_csi_item_instance_id,
8452                             p_counter_id,
8453                             p_reading_date);
8454     FETCH cs_ctr_reading_csr INTO l_net_reading;
8455     IF (cs_ctr_reading_csr%NOTFOUND) THEN
8456        l_net_reading := 0;
8457     END IF;
8458     CLOSE cs_ctr_reading_csr;
8459 
8460     x_net_reading := l_net_reading;
8461 
8462     IF G_DEBUG = 'Y' THEN
8463       AHL_DEBUG_PUB.debug('End of get_ctr_reading_for_date');
8464     END IF;
8465 
8466 END get_ctr_reading_for_date;
8467 -----------------------------------------------------------------------
8468 
8469 -- Get the earliest date on which a given reading was recorded.
8470 PROCEDURE get_ctr_date_for_reading (p_csi_item_instance_id IN NUMBER,
8471                                     p_counter_id           IN NUMBER,
8472                                     p_counter_value        IN NUMBER,
8473                                     x_ctr_record_date    OUT NOCOPY DATE,
8474                                     x_return_val         OUT NOCOPY BOOLEAN) IS
8475 
8476 
8477   -- get the earliest reading for which the given counter value exceeds.
8478   CURSOR cs_ctr_reading_csr(p_csi_item_instance_id IN NUMBER,
8479                             p_counter_id           IN NUMBER,
8480                             p_counter_value        IN NUMBER) IS
8481     /*
8482 	SELECT value_timestamp
8483     FROM cs_ctr_counter_values_v cv, cs_counter_groups cg
8484     WHERE cv.counter_group_id = cg.counter_group_id
8485       AND cg.source_object_code = 'CP'
8486       AND cg.source_object_id = p_csi_item_instance_id
8487       AND cv.counter_id = p_counter_id
8488       AND nvl(cv.net_reading,0) >= p_counter_value
8489     ORDER BY value_timestamp asc;
8490 	*/
8491 
8492 	--priyan
8493 	--Query being changed due to performance related fixes
8494 	--Refer Bug # 4918744
8495 
8496        /* Commented out to fix bug# 6445866. In R12, IB is not instantiating
8497         * counter groups in CS_CSI_COUNTER_GROUPS.
8498 
8499 	SELECT --DISTINCT
8500 		CCR.VALUE_TIMESTAMP
8501 	FROM
8502 		CSI_COUNTERS_VL CC,
8503 		--CS_COUNTER_GROUPS CCA,
8504 		--priyan
8505 		--Refer Bug # 5207990 for changes.
8506 		CS_CSI_COUNTER_GROUPS CCA,
8507 		CSI_COUNTER_READINGS CCR
8508 	WHERE
8509 		CC.DEFAULTED_GROUP_ID (+)       = CCA.COUNTER_GROUP_ID
8510 		 AND CCA.SOURCE_OBJECT_CODE		= 'CP'
8511 		 AND CCR.COUNTER_ID				= CC.COUNTER_ID
8512 		 AND CCA.SOURCE_OBJECT_ID		= P_CSI_ITEM_INSTANCE_ID
8513 		 AND CC.COUNTER_ID				= P_COUNTER_ID
8514 		 AND NVL(CCR.NET_READING,0)	>= P_COUNTER_VALUE
8515 	ORDER BY
8516 		CCR.VALUE_TIMESTAMP ASC;
8517         */
8518 
8519         SELECT * FROM (
8520                        SELECT CCR.VALUE_TIMESTAMP
8521                        FROM CSI_COUNTER_READINGS CCR
8522                        WHERE CCR.COUNTER_ID = P_COUNTER_ID
8523                          AND nvl(disabled_flag,'N') = 'N'
8524                          AND NVL(CCR.NET_READING,0) >= P_COUNTER_VALUE
8525                        ORDER BY CCR.VALUE_TIMESTAMP ASC
8526                       )
8527          WHERE rownum < 2;
8528 
8529   l_ctr_record_date    DATE;
8530   l_return_val         BOOLEAN := TRUE;
8531 
8532 BEGIN
8533 
8534 
8535   IF G_DEBUG = 'Y' THEN
8536     AHL_DEBUG_PUB.debug('Start of get_ctr_date_for_reading');
8537   END IF;
8538 
8539   OPEN cs_ctr_reading_csr (p_csi_item_instance_id,
8540                            p_counter_id,
8541                            p_counter_value);
8542   FETCH cs_ctr_reading_csr INTO l_ctr_record_date;
8543   IF (cs_ctr_reading_csr%NOTFOUND) THEN
8544      l_return_val := FALSE;
8545      l_ctr_record_date := NULL;
8546   END IF;
8547   CLOSE cs_ctr_reading_csr;
8548 
8549   x_ctr_record_date := l_ctr_record_date;
8550   x_return_val := l_return_val;
8551 
8552   IF G_DEBUG = 'Y' THEN
8553     AHL_DEBUG_PUB.debug('End of get_ctr_date_for_reading');
8554   END IF;
8555 
8556 END get_ctr_date_for_reading;
8557 
8558 -------------------------------------------------------------------------------
8559 -- Calculate due date for all deferred unit effectivities.
8560 PROCEDURE Process_Deferred_UE (p_csi_item_instance_id IN NUMBER,
8561                                p_current_usage_tbl  IN counter_values_tbl_type,
8562                                p_counter_rules_tbl  IN counter_rules_tbl_type)
8563 IS
8564 
8565   -- get all deferred unit effectivity records for the instance and MR.
8566   CURSOR ahl_deferred_ue_csr (p_csi_item_instance_id IN NUMBER) IS
8567 
8568     SELECT
8569         UE.UNIT_EFFECTIVITY_ID,
8570         UE.OBJECT_TYPE,
8571         UE.CSI_ITEM_INSTANCE_ID,
8572         UE.MR_HEADER_ID,
8573         UE.STATUS_CODE,
8574         UE.DEFER_FROM_UE_ID,
8575         nvl(MR.whichever_first_code, 'FIRST') whichever_first_code,
8576         UDF.unit_deferral_type, UE.CS_INCIDENT_ID, UDF.DEFERRAL_EFFECTIVE_ON,
8577         UDF.AFFECT_DUE_CALC_FLAG, UDF.SET_DUE_DATE, UDF.unit_deferral_id
8578     FROM ahl_unit_effectivities_app_v UE, ahl_unit_deferrals_b UDF, ahl_mr_headers_b MR
8579     WHERE UE.defer_from_ue_id = UDF.unit_effectivity_id
8580       AND UE.mr_header_id = MR.mr_header_id(+)
8581       AND csi_item_instance_id = p_csi_item_instance_id
8582       AND status_code IS NULL
8583       --AND defer_from_ue_id IS NOT NULL -- not required as joining table ahl_unit_deferrals_b
8584       AND UDF.unit_deferral_type IN ('DEFERRAL', 'MEL','CDL')
8585       AND NOT EXISTS (SELECT 'x'
8586                       FROM ahl_ue_relationships
8587                       WHERE related_ue_id = UE.unit_effectivity_id
8588                         AND relationship_code = 'PARENT')
8589       AND UDF.approval_status_code = 'DEFERRED'
8590     ORDER BY DEFERRAL_EFFECTIVE_ON ASC;
8591 
8592   /* Commented as we retrieve this info in ahl_deferred_ue_csr
8593   -- Get deferral detail from ahl_unit_deferrals.
8594   CURSOR ahl_unit_deferral_csr (p_deferred_from_ue_id IN NUMBER) IS
8595     SELECT AFFECT_DUE_CALC_FLAG, SET_DUE_DATE, unit_deferral_id, deferral_effective_on
8596     FROM ahl_unit_deferrals_b
8597     WHERE unit_effectivity_id = p_deferred_from_ue_id
8598       AND unit_deferral_type = 'DEFERRAL';
8599   */
8600 
8601   -- Get threshold details.
8602   CURSOR ahl_unit_threshold_csr (p_unit_deferral_id IN NUMBER) IS
8603     SELECT counter_id, counter_value, ctr_value_type_code
8604     FROM ahl_unit_thresholds
8605     WHERE unit_deferral_id = p_unit_deferral_id;
8606 
8607   -- Read applicable relns table for group MR details.
8608   CURSOR ahl_applicable_grp_csr( p_item_instance_id IN NUMBER,
8609                                  p_mr_header_id IN NUMBER) IS
8610 
8611     SELECT related_mr_header_id,
8612            related_csi_item_instance_id,
8613            csi_item_instance_id parent_csi_item_instance_id,
8614            mr_header_id parent_mr_header_id
8615     FROM ahl_applicable_mr_relns
8616     START WITH mr_header_id = p_mr_header_id AND
8617                csi_item_instance_id = p_item_instance_id AND
8618                orig_mr_header_id = p_mr_header_id AND
8619                orig_csi_item_instance_id = p_item_instance_id AND
8620                relationship_code = 'PARENT'
8621     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
8622                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
8623                orig_mr_header_id = p_mr_header_id AND
8624                orig_csi_item_instance_id = p_item_instance_id AND
8625                relationship_code = 'PARENT'
8626     ORDER BY   level;
8627 
8628    -- check repair category for time limit.
8629    cursor get_repair_category_csr(p_cs_incident_id IN NUMBER)
8630     is
8631        select nvl(repair_time,0), cs.expected_resolution_date
8632        from ahl_repair_categories rc, cs_incidents_all_b cs
8633        where rc.sr_urgency_id(+) = cs.incident_urgency_id
8634          and  cs.incident_id = p_cs_incident_id;
8635 
8636    -- Read immediate children of the SR.
8637    CURSOR ahl_ue_reln_csr (p_ue_id  IN NUMBER) IS
8638      SELECT ue.unit_effectivity_id, ue.status_code,
8639             UE.CSI_ITEM_INSTANCE_ID, UE.MR_HEADER_ID
8640      FROM ahl_ue_relationships uer, ahl_unit_effectivities_app_v ue
8641      WHERE ue.unit_effectivity_id = uer.related_ue_id
8642        AND uer.ue_id = p_ue_id;
8643 
8644 --
8645   l_due_at_counter_value   NUMBER;
8646   --l_affect_due_date_calc   VARCHAR2(1);
8647   l_set_due_date           DATE;
8648   l_unit_deferral_id       NUMBER;
8649   l_deferral_effective_on  DATE;
8650   l_net_reading            NUMBER;
8651   l_due_date               DATE;
8652   l_counter_read_date      DATE;
8653 
8654   l_counter_remain         NUMBER;
8655   l_current_ctr_value      NUMBER;
8656   k                        NUMBER;
8657   l_return_val             BOOLEAN;
8658 
8659   l_calc_due_date          DATE;
8660   l_calc_counter_id        NUMBER;
8661   l_calc_tolerance_flag    ahl_unit_effectivities_app_v.tolerance_flag%TYPE;
8662   l_calc_message_code      ahl_unit_effectivities_app_v.message_code%TYPE;
8663   l_calc_due_counter_value NUMBER;
8664 
8665   l_visit_start_date       DATE;
8666   l_visit_end_date         DATE;
8667   l_visit_assign_code      fnd_lookups.lookup_code%TYPE;
8668 
8669   l_grp_match              VARCHAR2(1);
8670   l_grp_match1             VARCHAR2(1);
8671 
8672   l_unit_deferral_type     VARCHAR2(30);
8673   l_repair_time            NUMBER;
8674   l_expected_resolutn_date DATE;
8675 
8676   l_visit_status           ahl_visits_b.status_code%TYPE;
8677 
8678 BEGIN
8679 
8680   IF G_DEBUG = 'Y' THEN
8681     AHL_DEBUG_PUB.debug('Start of process_Deferred_ue');
8682   END IF;
8683 
8684   -- get all open deferred unit effectivities.
8685   FOR unit_effectivity_rec IN ahl_deferred_ue_csr(p_csi_item_instance_id) LOOP
8686 
8687     IF G_DEBUG = 'Y' THEN
8688       AHL_DEBUG_PUB.debug('Processing ..ID:' || unit_effectivity_rec.unit_effectivity_id);
8689       AHL_DEBUG_PUB.debug('Processing ..unit_deferral_type:' || unit_effectivity_rec.unit_deferral_type);
8690     END IF;
8691 
8692     -- Initialize.
8693     l_calc_due_date := null;
8694     --l_calc_counter_id,
8695     l_calc_due_counter_value := null;
8696     l_calc_tolerance_flag := null;
8697     l_calc_message_code := null;
8698 
8699 IF (unit_effectivity_rec.unit_deferral_type = 'DEFERRAL') THEN
8700 
8701         -- get deferral details.
8702         l_set_due_date         := unit_effectivity_rec.set_due_date;
8703         l_unit_deferral_id     := unit_effectivity_rec.unit_deferral_id;
8704         l_deferral_effective_on := unit_effectivity_rec.deferral_effective_on;
8705 
8706         /*
8707         OPEN ahl_unit_deferral_csr(unit_effectivity_rec.defer_from_ue_id);
8708         FETCH ahl_unit_deferral_csr INTO l_affect_due_date_calc, l_set_due_date, l_unit_deferral_id,
8709                                          l_deferral_effective_on;
8710         IF (ahl_unit_deferral_csr%NOTFOUND) THEN
8711            CLOSE  ahl_unit_deferral_csr;
8712            FND_MESSAGE.Set_Name('AHL','AHL_UMP_DEF_NOTFOUND');
8713            FND_MESSAGE.Set_Token('UE_ID',unit_effectivity_rec.defer_from_ue_id);
8714            FND_MSG_PUB.ADD;
8715            RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
8716         END IF;
8717 
8718         CLOSE  ahl_unit_deferral_csr;
8719         */
8720         -- process threshold details for this deferral.
8721         FOR threshold_rec IN ahl_unit_threshold_csr(l_unit_deferral_id) LOOP
8722           l_due_at_counter_value := threshold_rec.counter_value;
8723           l_counter_remain := 0;
8724           l_current_ctr_value := 0;
8725           k := 0;
8726           -- search for the current counter value in p_current_usage_tbl.
8727           IF (p_current_usage_tbl.COUNT > 0) THEN
8728              FOR i IN p_current_usage_tbl.FIRST..p_current_usage_tbl.LAST LOOP
8729                IF (p_current_usage_tbl(i).counter_id = threshold_rec.counter_id) THEN
8730                   l_current_ctr_value := p_current_usage_tbl(i).counter_value;
8731                   k := i;
8732                   EXIT;
8733                END IF;
8734              END LOOP;
8735 
8736              IF G_DEBUG = 'Y' THEN
8737                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);
8738 
8739              END IF;
8740 
8741              -- Calculate counter remain.
8742              IF (threshold_rec.ctr_value_type_code = 'DEFER_BY') THEN
8743                 -- get counter usage as on deferral_effective_on date.
8744                 get_ctr_reading_for_datetime (p_csi_item_instance_id => p_csi_item_instance_id,
8745                                               p_counter_id           => p_current_usage_tbl(k).counter_id,
8746                                               p_reading_date         => l_deferral_effective_on,
8747                                               x_net_reading          => l_net_reading);
8748 
8749                 -- add net reading to the threshold value.
8750                 l_due_at_counter_value := l_net_reading + l_due_at_counter_value;
8751              END IF; -- defer by.
8752 
8753              l_counter_remain := l_due_at_counter_value - l_current_ctr_value;
8754 
8755              --dbms_output.put_line ('After reading:ctr remain' || l_counter_remain);
8756 
8757              -- calculate due date from forecast.
8758              IF (l_counter_remain > 0) THEN
8759                 --dbms_output.put_line ('counter remain greater than zero');
8760                 -- get date from forecast.
8761                 get_date_from_uf(l_counter_remain,
8762                                  p_current_usage_tbl(k).uom_code,
8763                                  p_counter_rules_tbl,
8764                                  null, /* start date = sysdate */
8765                                  l_due_date);
8766              ELSIF (l_counter_remain < 0) THEN
8767                  --dbms_output.put_line ('counter remain less than zero');
8768                  -- Due date = counter reading date.
8769                  get_ctr_date_for_reading (p_csi_item_instance_id => p_csi_item_instance_id,
8770                                            p_counter_id           => p_current_usage_tbl(k).counter_id,
8771                                            p_counter_value        => l_due_at_counter_value,
8772                                            x_ctr_record_date      => l_counter_read_date,
8773                                            x_return_val           => l_return_val);
8774 
8775                  IF NOT(l_return_val) THEN
8776                     l_due_date := sysdate;
8777                  ELSE
8778                     l_due_date := l_counter_read_date;
8779                  END IF;
8780 
8781              ELSIF (l_counter_remain = 0) THEN  /* due_date = sysdate */
8782                  --dbms_output.put_line ('counter remain is zero');
8783                  l_due_date := sysdate;
8784              END IF; -- counter remain.
8785 
8786              -- For MR type, based on whichever first code, set calculated due date.
8787              -- For SR type, whichever first code = 'FIRST'.
8788              IF (l_due_date IS NULL) THEN
8789                 l_calc_due_date := NULL;
8790                 l_calc_counter_id := p_current_usage_tbl(k).counter_id;
8791                 l_calc_due_counter_value := l_due_at_counter_value;
8792                 EXIT;
8793              ELSIF (l_calc_due_date IS NULL) THEN
8794                 l_calc_due_date := l_due_date;
8795                 l_calc_counter_id := p_current_usage_tbl(k).counter_id;
8796                 l_calc_due_counter_value := l_due_at_counter_value;
8797              ELSE
8798                 IF (unit_effectivity_rec.whichever_first_code = 'FIRST') THEN
8799                   IF (trunc(l_due_date) < trunc(l_calc_due_date)) THEN
8800                     l_calc_due_date := l_due_date;
8801                     l_calc_counter_id := p_current_usage_tbl(k).counter_id;
8802                     l_calc_due_counter_value := l_due_at_counter_value;
8803                   END IF;
8804                 ELSE  -- whichever_first_code = 'LAST'
8805                   IF (trunc(l_due_date) > trunc(l_calc_due_date)) THEN
8806                     l_calc_due_date := l_due_date;
8807                     l_calc_counter_id := p_current_usage_tbl(k).counter_id;
8808                     l_calc_due_counter_value := l_due_at_counter_value;
8809                   END IF;
8810                 END IF;
8811              END IF;
8812 
8813         --dbms_output.put_line ('Bl_calc_due_date:' || l_calc_due_date);
8814         --dbms_output.put_line ('Bset_due_date:' || l_set_due_date);
8815         --dbms_output.put_line ('Bdue_ctr_val:' || l_calc_due_counter_value);
8816         --dbms_output.put_line ('BcounterID:' || l_calc_counter_id);
8817 
8818           END IF; -- current_usage_tbl.
8819         END LOOP; -- threshold rec.
8820 
8821         IF G_DEBUG = 'Y' THEN
8822           AHL_DEBUG_PUB.debug('l_calc_due_date:' || l_calc_due_date);
8823           AHL_DEBUG_PUB.debug('set_due_date:' || l_set_due_date);
8824           AHL_DEBUG_PUB.debug('due_ctr_val:' || l_calc_due_counter_value);
8825           AHL_DEBUG_PUB.debug('counterID:' || l_calc_counter_id);
8826         END IF;
8827 
8828         -- Check calculated due date against set_due_date.
8829         IF (l_calc_due_date IS NOT NULL AND l_set_due_date IS NOT NULL) THEN
8830           IF (unit_effectivity_rec.whichever_first_code = 'FIRST') THEN
8831             IF (trunc(l_set_due_date) < trunc(l_calc_due_date)) THEN
8832                l_calc_due_date := l_set_due_date;
8833                l_calc_counter_id := null;
8834                l_calc_due_counter_value := null;
8835             END IF;
8836           ELSE  -- whichever_first_code = 'LAST'
8837             IF (trunc(l_set_due_date) > trunc(l_calc_due_date)) THEN
8838                l_calc_due_date := l_set_due_date;
8839                l_calc_counter_id := null;
8840                l_calc_due_counter_value := null;
8841             END IF;
8842           END IF;
8843         ELSIF (l_set_due_date IS NOT NULL) THEN
8844           l_calc_due_date := l_set_due_date;
8845           l_calc_counter_id := null;
8846           l_calc_due_counter_value := null;
8847         END IF;
8848 
8849     END IF;  -- unit_effectivity_rec.unit_deferral_type = 'DEFERRAL
8850 
8851 
8852     -- Added for R12: MEL/CDL due date.
8853     IF (unit_effectivity_rec.unit_deferral_type = 'MEL'
8854         OR unit_effectivity_rec.unit_deferral_type = 'CDL') THEN
8855 
8856         -- fix bug# 5217126. This variable is inserted into the temp table.
8857         l_deferral_effective_on := unit_effectivity_rec.deferral_effective_on;
8858 
8859         IF G_DEBUG = 'Y' THEN
8860           AHL_DEBUG_PUB.debug('Calculating due date for MEL/CDL');
8861           AHL_DEBUG_PUB.debug('Deferral Eff on:' || unit_effectivity_rec.DEFERRAL_EFFECTIVE_ON);
8862           AHL_DEBUG_PUB.debug('Processing ..object type:' || unit_effectivity_rec.object_type);
8863         END IF;
8864 
8865         -- validate repair category.
8866         -- Added expected_resolution_date to fix bug# 5217126.
8867         OPEN get_repair_category_csr(unit_effectivity_rec.cs_incident_id);
8868         FETCH get_repair_category_csr INTO l_repair_time, l_expected_resolutn_date;
8869         IF (get_repair_category_csr%NOTFOUND) THEN
8870           --l_calc_due_date := NULL;
8871           FND_MESSAGE.Set_Name('AHL','AHL_PUE_INCIDENT_ID_MISSING');
8872           FND_MESSAGE.Set_Token('CS_INC_ID',unit_effectivity_rec.cs_incident_id);
8873           FND_MSG_PUB.ADD;
8874           RAISE FND_API.G_EXC_ERROR;
8875         ELSE
8876 
8877           IF l_repair_time <> 0 AND
8878               unit_effectivity_rec.DEFERRAL_EFFECTIVE_ON IS NOT NULL
8879           THEN
8880             l_calc_due_date := unit_effectivity_rec.DEFERRAL_EFFECTIVE_ON +
8881                                trunc(l_repair_time/24);
8882           ELSE
8883             -- fix for bug# 5217126.
8884             l_calc_due_date := l_expected_resolutn_date;
8885           END IF;
8886 
8887         END IF; -- get_repair_category_csr%NOTFOUND
8888         CLOSE get_repair_category_csr;
8889 
8890         IF G_DEBUG = 'Y' THEN
8891           AHL_DEBUG_PUB.debug('MEL/CDL:Calculated due date is:' || l_calc_due_date);
8892           AHL_DEBUG_PUB.debug('MEL/CDL:DEFERRAL_EFFECTIVE_ON:' || l_deferral_effective_on);
8893         END IF;
8894 
8895     END IF; -- unit_effectivity_rec.unit_deferral_type = 'MEL'
8896 
8897     -- Call visit work package to get visit end date if unit effectivity has been assigned to a visit.
8898     AHL_UMP_UTIL_PKG.get_visit_details (unit_effectivity_rec.unit_effectivity_id,
8899                                         l_visit_start_date,
8900                                         l_visit_end_date,
8901                                         l_visit_assign_code);
8902 
8903     /*
8904     IF (l_visit_end_date IS NOT NULL AND l_calc_due_date IS NOT NULL) THEN
8905       IF G_DEBUG = 'Y' THEN
8906          AHL_DEBUG_PUB.Debug('Visit assigned:End Date:' || l_visit_end_date);
8907       END IF;
8908 
8909       IF (trunc(l_visit_end_date) < trunc(l_calc_due_date)) THEN
8910            l_calc_tolerance_flag := 'Y';
8911            l_calc_message_code := 'TOLERANCE-BEFORE';
8912       END IF;
8913     END IF;
8914     */
8915 
8916     IF (l_visit_start_date IS NOT NULL AND l_calc_due_date IS NOT NULL) THEN
8917       IF G_DEBUG = 'Y' THEN
8918          AHL_DEBUG_PUB.Debug('Visit assigned: Start Date:' || l_visit_start_date);
8919       END IF;
8920       IF (trunc(l_visit_start_date) > trunc(l_calc_due_date)) THEN
8921            l_calc_tolerance_flag := 'Y';
8922            l_calc_message_code := 'TOLERANCE-EXCEEDED';
8923       END IF;
8924     END IF;
8925 
8926     IF ( l_calc_due_date IS NOT NULL) THEN
8927       IF (trunc(l_calc_due_date) < trunc(sysdate)) THEN
8928          l_calc_tolerance_flag := 'Y';
8929          l_calc_message_code := 'TOLERANCE-EXCEEDED';
8930       END IF;
8931     END IF;
8932 
8933     --dbms_output.put_line ('Al_calc_due_date:' || l_calc_due_date);
8934     --dbms_output.put_line ('Aset_due_date:' || l_set_due_date);
8935     --dbms_output.put_line ('Adue_ctr_val:' || l_calc_due_counter_value);
8936 
8937 
8938     -- Check if workorder already created.
8939     l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status(unit_effectivity_rec.unit_effectivity_id);
8940 
8941     IF (nvl(l_visit_status,'X') IN ('RELEASED','CLOSED')) THEN
8942        -- if UE is on shop floor then keep UE structure as is.
8943        l_grp_match := 'Y';
8944     ELSE
8945        IF (unit_effectivity_rec.object_type = 'MR') THEN
8946 
8947            Match_Group_MR (p_orig_csi_item_instance_id  => unit_effectivity_rec.csi_item_instance_id,
8948                            p_orig_mr_header_id          => unit_effectivity_rec.mr_header_id,
8949                            p_unit_effectivity_id        => unit_effectivity_rec.unit_effectivity_id,
8950                            x_group_match_flag           => l_grp_match);
8951 
8952        ELSE
8953            l_grp_match := 'Y';
8954            -- For SR case, for each child group MR associated match the group MR.
8955            FOR ahl_ue_reln_rec IN ahl_ue_reln_csr(unit_effectivity_rec.unit_effectivity_id) LOOP
8956               IF (ahl_ue_reln_rec.status_code = 'MR-TERMINATE') THEN
8957                     -- skip mr-terminated records.
8958                    l_grp_match1 := 'Y';
8959               ELSE
8960 
8961                    Match_Group_MR (p_orig_csi_item_instance_id  => ahl_ue_reln_rec.csi_item_instance_id,
8962                                    p_orig_mr_header_id          => ahl_ue_reln_rec.mr_header_id,
8963                                    p_unit_effectivity_id        => ahl_ue_reln_rec.unit_effectivity_id,
8964                                    x_group_match_flag           => l_grp_match1);
8965 
8966                   IF (l_grp_match1 = 'N') THEN
8967                       l_grp_match := 'N';
8968                   END IF;
8969 
8970               END IF;
8971 
8972            END LOOP;
8973 
8974        END IF; -- unit_effectivity_rec.object_type
8975     END IF; -- l_visit_status
8976 
8977 
8978     IF G_DEBUG = 'Y' THEN
8979       AHL_DEBUG_PUB.Debug('Group Match flag:l_visit_status:' || l_grp_match || ':' || l_visit_status);
8980     END IF;
8981 
8982     -- insert into deferral temp table.
8983     insert into ahl_temp_unit_SR_deferrals (
8984         unit_effectivity_id,
8985         object_type,
8986         csi_item_instance_id,
8987         mr_header_id,
8988         due_date,
8989         counter_id,
8990         due_counter_value,
8991         tolerance_flag,
8992         message_code,
8993         parent_csi_item_instance_id,
8994         parent_mr_header_id,
8995         orig_csi_item_instance_id,
8996         orig_mr_header_id,
8997         orig_unit_effectivity_id,
8998         visit_end_date,
8999         deferral_effective_on,
9000         affect_due_calc_flag,
9001         group_match_flag)
9002     VALUES (
9003         unit_effectivity_rec.unit_effectivity_id,
9004         unit_effectivity_rec.object_type,
9005         unit_effectivity_rec.csi_item_instance_id,
9006         unit_effectivity_rec.mr_header_id,
9007         l_calc_due_date,
9008         l_calc_counter_id,
9009         l_calc_due_counter_value,
9010         l_calc_tolerance_flag,
9011         l_calc_message_code,
9012         null,
9013         null,
9014         null,
9015         null,
9016         null,
9017         l_visit_end_date,
9018         l_deferral_effective_on,
9019         --l_affect_due_date_calc,
9020         unit_effectivity_rec.AFFECT_DUE_CALC_FLAG,
9021         l_grp_match);
9022 
9023     -- Insert all child MRs for group MR.
9024     FOR ahl_applicable_grp_rec IN ahl_applicable_grp_csr(unit_effectivity_rec.csi_item_instance_id,
9025                                                          unit_effectivity_rec.mr_header_id)
9026     LOOP
9027            -- insert into deferral temp table.
9028            insert into ahl_temp_unit_SR_deferrals (
9029                unit_effectivity_id,
9030                object_type,
9031                csi_item_instance_id,
9032                mr_header_id,
9033                due_date,
9034                due_counter_value,
9035                tolerance_flag,
9036                message_code,
9037                parent_csi_item_instance_id,
9038                parent_mr_header_id,
9039                orig_csi_item_instance_id,
9040                orig_mr_header_id,
9041                orig_unit_effectivity_id,
9042                visit_end_date,
9043                deferral_effective_on,
9044                affect_due_calc_flag,
9045                group_match_flag)
9046            VALUES (
9047                null,
9048                'MR',
9049                ahl_applicable_grp_rec.related_csi_item_instance_id,
9050                ahl_applicable_grp_rec.related_mr_header_id,
9051                l_calc_due_date,
9052                l_calc_due_counter_value,
9053                l_calc_tolerance_flag,
9054                l_calc_message_code,
9055                ahl_applicable_grp_rec.parent_csi_item_instance_id,
9056                ahl_applicable_grp_rec.parent_mr_header_id,
9057                unit_effectivity_rec.csi_item_instance_id,
9058                unit_effectivity_rec.mr_header_id,
9059                unit_effectivity_rec.unit_effectivity_id,
9060                l_visit_end_date,
9061                l_deferral_effective_on,
9062                --l_affect_due_date_calc,
9063                unit_effectivity_rec.AFFECT_DUE_CALC_FLAG,
9064                l_grp_match);
9065 
9066     END LOOP;
9067     --fix for bug#5217126
9068     --CLOSE ahl_unit_deferral_csr;
9069 
9070   END LOOP; -- unit effectivity rec.
9071 
9072   IF G_DEBUG = 'Y' THEN
9073     AHL_DEBUG_PUB.debug('End of process_Deferred_ue');
9074   END IF;
9075 
9076 END Process_Deferred_UE;
9077 -----------------------------------------------
9078 
9079 -- Explode SR's having MRs for calculating MR due dates.
9080 PROCEDURE Process_SR_UE (p_csi_item_instance_id IN NUMBER)  IS
9081 
9082   CURSOR ahl_ue_sr_csr (p_csi_item_instance_id IN NUMBER) IS
9083     SELECT
9084         UE.UNIT_EFFECTIVITY_ID,
9085         UE.OBJECT_TYPE,
9086         UE.CSI_ITEM_INSTANCE_ID,
9087         UE.MR_HEADER_ID,
9088         UE.STATUS_CODE,
9089         UE.DUE_DATE,
9090         UE.DUE_COUNTER_VALUE
9091     FROM ahl_unit_effectivities_app_v UE
9092     WHERE UE.OBJECT_TYPE = 'SR'
9093       AND defer_from_ue_id IS NULL
9094       AND csi_item_instance_id = p_csi_item_instance_id
9095       AND status_code IS NULL;
9096 
9097 
9098   -- Read applicable relns table for group MR details.
9099   CURSOR ahl_applicable_grp_csr( p_item_instance_id IN NUMBER,
9100                                  p_mr_header_id IN NUMBER) IS
9101 
9102     SELECT related_mr_header_id,
9103            related_csi_item_instance_id,
9104            csi_item_instance_id parent_csi_item_instance_id,
9105            mr_header_id parent_mr_header_id
9106     FROM ahl_applicable_mr_relns
9107     START WITH mr_header_id = p_mr_header_id AND
9108                csi_item_instance_id = p_item_instance_id AND
9109                orig_mr_header_id = p_mr_header_id AND
9110                orig_csi_item_instance_id = p_item_instance_id AND
9111                relationship_code = 'PARENT'
9112     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
9113                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
9114                orig_mr_header_id = p_mr_header_id AND
9115                orig_csi_item_instance_id = p_item_instance_id AND
9116                relationship_code = 'PARENT'
9117     ORDER BY   level;
9118 
9119 
9120   -- Read immediate children of the SR.
9121   CURSOR ahl_ue_reln_csr (p_ue_id  IN NUMBER) IS
9122     SELECT ue.unit_effectivity_id, ue.status_code,
9123            UE.CSI_ITEM_INSTANCE_ID, UE.MR_HEADER_ID
9124     FROM ahl_ue_relationships uer, ahl_unit_effectivities_app_v ue
9125     WHERE ue.unit_effectivity_id = uer.related_ue_id
9126       AND uer.ue_id = p_ue_id;
9127 
9128 
9129   l_calc_tolerance_flag    ahl_unit_effectivities_app_v.tolerance_flag%TYPE;
9130   l_calc_message_code      ahl_unit_effectivities_app_v.message_code%TYPE;
9131 
9132   l_visit_start_date       DATE;
9133   l_visit_end_date         DATE;
9134   l_visit_assign_code      fnd_lookups.lookup_code%TYPE;
9135 
9136   l_grp_match              VARCHAR2(1);
9137   l_grp_match1             VARCHAR2(1);
9138 
9139   l_visit_status           ahl_visits_b.status_code%TYPE;
9140 
9141 BEGIN
9142 
9143   IF G_DEBUG = 'Y' THEN
9144     AHL_DEBUG_PUB.debug('Start of Process_SR_UE');
9145   END IF;
9146 
9147   -- Get all UE's with object-type = SR.
9148   FOR ahl_ue_sr_rec IN ahl_ue_sr_csr(p_csi_item_instance_id) LOOP
9149 
9150     -- Call visit work package to get visit end date if unit effectivity has been assigned to a visit.
9151     AHL_UMP_UTIL_PKG.get_visit_details (ahl_ue_sr_rec.unit_effectivity_id,
9152                                         l_visit_start_date,
9153                                         l_visit_end_date,
9154                                         l_visit_assign_code);
9155 
9156     IF (l_visit_end_date IS NOT NULL AND ahl_ue_sr_rec.due_date IS NOT NULL) THEN
9157       IF G_DEBUG = 'Y' THEN
9158          AHL_DEBUG_PUB.Debug('Visit assigned:End Date:' || l_visit_end_date);
9159       END IF;
9160 
9161       IF (trunc(l_visit_end_date) < trunc(ahl_ue_sr_rec.due_date )) THEN
9162            l_calc_tolerance_flag := 'Y';
9163            l_calc_message_code := 'TOLERANCE-BEFORE';
9164       END IF;
9165     END IF;
9166 
9167     IF (l_visit_start_date IS NOT NULL AND ahl_ue_sr_rec.due_date IS NOT NULL) THEN
9168       IF G_DEBUG = 'Y' THEN
9169          AHL_DEBUG_PUB.Debug('Visit assigned:Start Date:' || l_visit_start_date);
9170       END IF;
9171 
9172       IF (trunc(l_visit_start_date) > trunc(ahl_ue_sr_rec.due_date )) THEN
9173            l_calc_tolerance_flag := 'Y';
9174            l_calc_message_code := 'TOLERANCE-EXCEEDED';
9175       END IF;
9176     END IF;
9177 
9178     -- Check if workorder already created.
9179     l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status(ahl_ue_sr_rec.unit_effectivity_id);
9180 
9181     IF (nvl(l_visit_status,'X') IN ('RELEASED','CLOSED')) THEN
9182        -- if UE is on shop floor then keep UE structure as is.
9183        l_grp_match := 'Y';
9184     ELSE
9185       -- initialize.
9186       l_grp_match := 'Y';
9187 
9188       -- For each group MR associated match the group MR.
9189       FOR ahl_ue_reln_rec IN ahl_ue_reln_csr(ahl_ue_sr_rec.unit_effectivity_id) LOOP
9190         IF (ahl_ue_reln_rec.status_code = 'MR-TERMINATE') THEN
9191            -- skip mr-terminated records.
9192            l_grp_match1 := 'Y';
9193         ELSE
9194 
9195            Match_Group_MR (p_orig_csi_item_instance_id  => ahl_ue_reln_rec.csi_item_instance_id,
9196                            p_orig_mr_header_id          => ahl_ue_reln_rec.mr_header_id,
9197                            p_unit_effectivity_id        => ahl_ue_reln_rec.unit_effectivity_id,
9198                            x_group_match_flag           => l_grp_match1);
9199 
9200           IF (l_grp_match1 = 'N') THEN
9201             l_grp_match := 'N';
9202           END IF;
9203         END IF;
9204 
9205       END LOOP;
9206     END IF; --l_visit_status
9207 
9208     -- Write SR UE into temporary table.
9209     insert into ahl_temp_unit_SR_deferrals (
9210         unit_effectivity_id,
9211         object_type,
9212         csi_item_instance_id,
9213         mr_header_id,
9214         due_date,
9215         due_counter_value,
9216         tolerance_flag,
9217         message_code,
9218         parent_csi_item_instance_id,
9219         parent_mr_header_id,
9220         orig_mr_header_id,
9221         orig_csi_item_instance_id,
9222         orig_unit_effectivity_id,
9223         visit_end_date,
9224         deferral_effective_on,
9225         affect_due_calc_flag,
9226         group_match_flag)
9227      VALUES (
9228         ahl_ue_sr_rec.unit_effectivity_id,
9229         ahl_ue_sr_rec.object_type,
9230         ahl_ue_sr_rec.csi_item_instance_id,
9231         null,
9232         ahl_ue_sr_rec.due_date,
9233         ahl_ue_sr_rec.due_counter_value,
9234         l_calc_tolerance_flag,
9235         l_calc_message_code,
9236         null,
9237         null,
9238         null,
9239         null,
9240         null,
9241         l_visit_end_date,
9242         null,
9243         'Y',
9244         l_grp_match);
9245 
9246 
9247       -- Write child MRs into temporary table.
9248 
9249       FOR ahl_applicable_grp_rec IN ahl_applicable_grp_csr(ahl_ue_sr_rec.csi_item_instance_id,
9250                                                            ahl_ue_sr_rec.mr_header_id)
9251       LOOP
9252            -- insert into deferral temp table.
9253            insert into ahl_temp_unit_SR_deferrals (
9254                unit_effectivity_id,
9255                object_type,
9256                csi_item_instance_id,
9257                mr_header_id,
9258                due_date,
9259                due_counter_value,
9260                tolerance_flag,
9261                message_code,
9262                parent_csi_item_instance_id,
9263                parent_mr_header_id,
9264                orig_csi_item_instance_id,
9265                orig_mr_header_id,
9266                orig_unit_effectivity_id,
9267                visit_end_date,
9268                deferral_effective_on,
9269                affect_due_calc_flag,
9270                group_match_flag)
9271            VALUES (
9272                null,
9273                null,
9274                ahl_applicable_grp_rec.related_csi_item_instance_id,
9275                ahl_applicable_grp_rec.related_mr_header_id,
9276                ahl_ue_sr_rec.due_date,
9277                ahl_ue_sr_rec.due_counter_value,
9278                l_calc_tolerance_flag,
9279                l_calc_message_code,
9280                ahl_applicable_grp_rec.parent_csi_item_instance_id,
9281                ahl_applicable_grp_rec.parent_mr_header_id,
9282                ahl_ue_sr_rec.csi_item_instance_id,
9283                ahl_ue_sr_rec.mr_header_id,
9284                ahl_ue_sr_rec.unit_effectivity_id,
9285                l_visit_end_date,
9286                null,
9287                'Y',
9288                l_grp_match);
9289 
9290       END LOOP;
9291 
9292   END LOOP;
9293 
9294   IF G_DEBUG = 'Y' THEN
9295     AHL_DEBUG_PUB.debug('End of Process_SR_UE');
9296   END IF;
9297 
9298 END Process_SR_UE;
9299 
9300 -----------------------------------------------
9301 
9302 -- Match if current UE group MR matches the applicable group MR.
9303 PROCEDURE Match_Group_MR (p_orig_csi_item_instance_id  IN NUMBER,
9304                           p_orig_mr_header_id          IN NUMBER,
9305                           p_unit_effectivity_id        IN NUMBER,
9306                           x_group_match_flag       OUT NOCOPY VARCHAR2)
9307 IS
9308 
9309   -- Get all child UE's for a given unit effectivity.
9310   CURSOR ahl_ue_relns_csr (p_unit_effectivity_id  IN NUMBER) IS
9311     SELECT related_ue_id, ue_id, level
9312     FROM  ahl_ue_relationships
9313     START WITH ue_id = p_unit_effectivity_id
9314            AND relationship_code = 'PARENT'
9315     CONNECT BY PRIOR related_ue_id = ue_id
9316            AND relationship_code = 'PARENT'
9317     ORDER BY level;
9318 
9319   -- get unit effectivities details.
9320   CURSOR ahl_ue_csr ( p_ue_id IN NUMBER,
9321                       p_related_ue_id IN NUMBER ) IS
9322     SELECT ue1.mr_header_id, ue1.csi_item_instance_id,
9323            ue2.mr_header_id related_mr_header_id,
9324            ue2.csi_item_instance_id related_csi_item_instance_id
9325     FROM ahl_unit_effectivities_b ue1, ahl_unit_effectivities_b ue2
9326     WHERE ue1.unit_effectivity_id = p_ue_id AND
9327           ue2.unit_effectivity_id = p_related_ue_id;
9328 
9329   -- Read applicable relns table for group MR details.
9330   CURSOR ahl_applicable_grp_csr( p_item_instance_id IN NUMBER,
9331                                  p_mr_header_id IN NUMBER) IS
9332 
9333     SELECT mr_header_id, csi_item_instance_id,
9334            related_mr_header_id,
9335            related_csi_item_instance_id, level
9336     FROM ahl_applicable_mr_relns
9337     START WITH mr_header_id = p_mr_header_id AND
9338                csi_item_instance_id = p_item_instance_id AND
9339                orig_mr_header_id = p_mr_header_id AND
9340                orig_csi_item_instance_id = p_item_instance_id AND
9341                relationship_code = 'PARENT'
9342     CONNECT BY PRIOR related_mr_header_id = mr_header_id AND
9343                PRIOR related_csi_item_instance_id = csi_item_instance_id AND
9344                orig_mr_header_id = p_mr_header_id AND
9345                orig_csi_item_instance_id = p_item_instance_id AND
9346                relationship_code = 'PARENT'
9347     ORDER BY   level;
9348 
9349 
9350   TYPE ue_details_rec_type IS RECORD (
9351      mr_header_id NUMBER,
9352      csi_item_instance_id NUMBER,
9353      related_mr_header_id NUMBER,
9354      related_csi_item_instance_id NUMBER,
9355      level                NUMBER,
9356      unit_effectivity_id  NUMBER,
9357      match_flag           VARCHAR2(1));
9358 
9359   l_ue_details_rec       ue_details_rec_type;
9360 
9361   TYPE l_ue_details_tbl_type IS TABLE OF ue_details_rec_type INDEX BY BINARY_INTEGER;
9362 
9363   l_ue_details_tbl       l_ue_details_tbl_type;
9364   l_grp_details_tbl      l_ue_details_tbl_type;
9365   i                      NUMBER;
9366 
9367 BEGIN
9368 
9369     IF G_DEBUG = 'Y' THEN
9370       AHL_DEBUG_PUB.debug('Start of Match_Group_MR');
9371     END IF;
9372 
9373     -- Match the ue relations tree with the group applicablilty tree.
9374     i := 1;
9375     FOR ahl_ue_relns_rec in ahl_ue_relns_csr(p_unit_effectivity_id) LOOP
9376        OPEN ahl_ue_csr(ahl_ue_relns_rec.ue_id, ahl_ue_relns_rec.related_ue_id);
9377        FETCH ahl_ue_csr INTO l_ue_details_tbl(i).mr_header_id,
9378                              l_ue_details_tbl(i).csi_item_instance_id,
9379                              l_ue_details_tbl(i).related_mr_header_id,
9380                              l_ue_details_tbl(i).related_csi_item_instance_id;
9381        IF (ahl_ue_csr%NOTFOUND) THEN
9382            FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_RELN_NOTFOUND');
9383            FND_MESSAGE.Set_Token('UE_ID',ahl_ue_relns_rec.ue_id);
9384            FND_MESSAGE.Set_Token('RELATED_UE_ID', ahl_ue_relns_rec.related_ue_id);
9385            FND_MSG_PUB.ADD;
9386            RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
9387        END IF;
9388 
9389        l_ue_details_tbl(i).level := ahl_ue_relns_rec.level;
9390        l_ue_details_tbl(i).unit_effectivity_id := ahl_ue_relns_rec.related_ue_id;
9391        l_ue_details_tbl(i).match_flag := 'N';
9392 
9393        --dbms_output.put_line ('found ue relns');
9394        i := i + 1;
9395        CLOSE ahl_ue_csr;
9396     END LOOP;
9397 
9398     i := 1;
9399     -- from applicable_mrs_relations.
9400     FOR l_appl_grp_rec IN ahl_applicable_grp_csr(p_orig_csi_item_instance_id,
9401                                                  p_orig_mr_header_id)
9402 
9403     LOOP
9404       l_grp_details_tbl(i).mr_header_id := l_appl_grp_rec.mr_header_id;
9405       l_grp_details_tbl(i).csi_item_instance_id := l_appl_grp_rec.csi_item_instance_id;
9406       l_grp_details_tbl(i).related_mr_header_id := l_appl_grp_rec.related_mr_header_id;
9407       l_grp_details_tbl(i).related_csi_item_instance_id := l_appl_grp_rec.related_csi_item_instance_id;
9408       l_grp_details_tbl(i).level := l_appl_grp_rec.level;
9409       l_grp_details_tbl(i).match_flag := 'N';
9410       i := i + 1;
9411     END LOOP;
9412 
9413     -- Now compare l_grp_details_tbl with l_ue_details_tbl.
9414     IF (l_grp_details_tbl.COUNT > 0) THEN
9415        FOR i IN l_grp_details_tbl.FIRST..l_grp_details_tbl.LAST LOOP
9416          -- match if entry present in l_ue_details_tbl.
9417          IF (l_ue_details_tbl.COUNT > 0 ) THEN
9418             FOR j IN l_ue_details_tbl.FIRST..l_ue_details_tbl.LAST LOOP
9419               IF (l_ue_details_tbl(j).mr_header_id = l_grp_details_tbl(i).mr_header_id AND
9420                  l_ue_details_tbl(j).csi_item_instance_id = l_grp_details_tbl(i).csi_item_instance_id AND
9421                  l_ue_details_tbl(j).related_csi_item_instance_id = l_grp_details_tbl(i).related_csi_item_instance_id AND
9422                  l_ue_details_tbl(j).related_mr_header_id = l_grp_details_tbl(i).related_mr_header_id AND
9423                  l_ue_details_tbl(j).level = l_grp_details_tbl(i).level AND
9424                  l_ue_details_tbl(j).match_flag = 'N' AND
9425                  l_grp_details_tbl(i).match_flag = 'N') THEN
9426                      --l_ue_details_tbl.DELETE(j);
9427                      --l_grp_details_tbl.DELETE(i);
9428                      l_ue_details_tbl(j).match_flag := 'Y';
9429                      l_grp_details_tbl(i).match_flag := 'Y';
9430                      EXIT;
9431               END IF;
9432             END LOOP; /* ue_details */
9433          END IF; /* count - ue_details */
9434        END LOOP; /* grp_details */
9435     END IF; /* count - grp_details */
9436 
9437     -- delete records from table where match flag is Y.
9438     IF (l_ue_details_tbl.COUNT > 0 ) THEN
9439       FOR j IN l_ue_details_tbl.FIRST..l_ue_details_tbl.LAST LOOP
9440         IF (l_ue_details_tbl(j).match_flag = 'Y') THEN
9441            l_ue_details_tbl.DELETE(j);
9442         END IF;
9443       END LOOP;
9444     END IF;
9445 
9446     IF (l_grp_details_tbl.COUNT > 0 ) THEN
9447       FOR i IN l_grp_details_tbl.FIRST..l_grp_details_tbl.LAST LOOP
9448          IF (l_grp_details_tbl(i).match_flag = 'Y') THEN
9449            l_grp_details_tbl.DELETE(i);
9450          END IF;
9451       END LOOP;
9452     END IF;
9453 
9454     IF (l_ue_details_tbl.COUNT = 0) AND (l_grp_details_tbl.COUNT = 0) THEN
9455       x_group_match_flag := 'Y';
9456 
9457     ELSE
9458       x_group_match_flag := 'N';
9459 
9460     END IF;
9461 
9462     IF G_DEBUG = 'Y' THEN
9463       AHL_DEBUG_PUB.debug('End of Match_Group_MR');
9464     END IF;
9465 
9466 END Match_Group_MR;
9467 
9468 -----------------------------------------------
9469 
9470 PROCEDURE Process_Unplanned_UE(p_csi_item_instance_id IN NUMBER) IS
9471   -- Read Unplanned MRs.(only top nodes)
9472   CURSOR ahl_unplanned_ue_csr(p_csi_item_instance_id IN NUMBER) IS
9473     SELECT ue.mr_header_id,
9474            ue.csi_item_instance_id,
9475            ue.unit_effectivity_id,
9476            ue.status_code
9477     FROM ahl_unit_effectivities_app_v ue
9478     /*
9479     WHERE NOT EXISTS ( SELECT 'x'
9480                        --FROM ahl_ue_relationships uer, ahl_unit_effectivities_app_v ue1
9481                        FROM ahl_ue_relationships uer, ahl_unit_effectivities_b ue1
9482                        WHERE uer.related_ue_id = ue.unit_effectivity_id AND
9483                              uer.originator_ue_id = ue1.unit_effectivity_id AND
9484                              ue1.object_type <> 'SR' )
9485     */
9486     -- pick up only top nodes.
9487     WHERE NOT EXISTS (SELECT 'x'
9488                       FROM ahl_ue_relationships uer
9489                       WHERE uer.related_ue_id = ue.unit_effectivity_id
9490                         AND relationship_code = 'PARENT')
9491         AND ue.csi_item_instance_id = p_csi_item_instance_id
9492         AND nvl(ue.manually_planned_flag,'N') = 'Y'
9493         AND ue.object_type = 'MR'
9494         AND ue.defer_from_ue_id IS NULL
9495         AND (ue.status_code IS NULL OR ue.status_code = 'EXCEPTION');
9496 
9497   CURSOR ahl_applicable_mr_csr (p_csi_item_instance_id IN NUMBER,
9498                                 p_mr_header_id         IN NUMBER) IS
9499     SELECT 'x'
9500     FROM ahl_applicable_mrs
9501     WHERE mr_header_id = p_mr_header_id AND
9502           csi_item_instance_id = p_csi_item_instance_id;
9503 
9504 
9505   -- Cursor to get all details of a unit effectivity record.
9506   CURSOR ahl_unit_effectivity_csr ( p_unit_effectivity_id IN NUMBER) IS
9507      SELECT
9508         UNIT_EFFECTIVITY_ID ,
9509         CSI_ITEM_INSTANCE_ID,
9510         MR_INTERVAL_ID,
9511         MR_EFFECTIVITY_ID ,
9512         MR_HEADER_ID,
9513         STATUS_CODE ,
9514         DUE_DATE   ,
9515         DUE_COUNTER_VALUE ,
9516         FORECAST_SEQUENCE ,
9517         REPETITIVE_MR_FLAG ,
9518         TOLERANCE_FLAG ,
9519         REMARKS ,
9520         MESSAGE_CODE ,
9521         PRECEDING_UE_ID ,
9522         DATE_RUN ,
9523         SET_DUE_DATE ,
9524         ACCOMPLISHED_DATE ,
9525         CANCEL_REASON_CODE,
9526         EARLIEST_DUE_DATE,
9527         LATEST_DUE_DATE,
9528         SERVICE_LINE_ID,
9529         PROGRAM_MR_HEADER_ID,
9530         defer_from_ue_id,
9531         cs_incident_id,
9532         qa_collection_id,
9533         orig_deferral_ue_id,
9534         application_usg_code,
9535         object_type,
9536         counter_id,
9537         manually_planned_flag,
9538         LOG_SERIES_CODE,
9539         LOG_SERIES_NUMBER, FLIGHT_NUMBER, MEL_CDL_TYPE_CODE,
9540         POSITION_PATH_ID,
9541         ATA_CODE, UNIT_CONFIG_HEADER_ID,
9542         ATTRIBUTE_CATEGORY ,
9543         ATTRIBUTE1,
9544         ATTRIBUTE2 ,
9545         ATTRIBUTE3 ,
9546         ATTRIBUTE4 ,
9547         ATTRIBUTE5 ,
9548         ATTRIBUTE6 ,
9549         ATTRIBUTE7 ,
9550         ATTRIBUTE8 ,
9551         ATTRIBUTE9 ,
9552         ATTRIBUTE10,
9553         ATTRIBUTE11 ,
9554         ATTRIBUTE12 ,
9555         ATTRIBUTE13 ,
9556         ATTRIBUTE14 ,
9557         ATTRIBUTE15 ,
9558         OBJECT_VERSION_NUMBER
9559      FROM ahl_unit_effectivities_vl
9560      WHERE unit_effectivity_id = p_unit_effectivity_id
9561      FOR UPDATE OF message_code NOWAIT;
9562 
9563   -- Read group from ahl_ue_relationships.
9564   CURSOR decendent_csr (p_unit_effectivity_id IN NUMBER) IS
9565     SELECT related_ue_id
9566     FROM ahl_ue_relationships
9567     WHERE relationship_code = 'PARENT' AND
9568           originator_ue_id = p_unit_effectivity_id;
9569 
9570   l_exception_flag  BOOLEAN;
9571   l_grp_match_flag  VARCHAR2(1);
9572   l_message_code    ahl_unit_effectivities_b.message_code%TYPE;
9573   l_status_code     ahl_unit_effectivities_b.status_code%TYPE;
9574   l_junk            VARCHAR2(1);
9575 
9576   l_ue_rec          ahl_unit_effectivity_csr%ROWTYPE;
9577 
9578   l_visit_status    VARCHAR2(30);
9579 
9580 BEGIN
9581 
9582   IF G_DEBUG = 'Y' THEN
9583     AHL_DEBUG_PUB.debug('Start of Process_Unplanned_UE');
9584   END IF;
9585 
9586   -- Loop through all Unplanned MRs.
9587   FOR ahl_unplanned_ue_rec IN ahl_unplanned_ue_csr(p_csi_item_instance_id) LOOP
9588     -- initialize.
9589     l_exception_flag := FALSE;
9590 
9591     -- Check if workorder already created.
9592     l_visit_status := AHL_UMP_UTIL_PKG.get_Visit_Status (ahl_unplanned_ue_rec.unit_effectivity_id);
9593 
9594     -- only if visit is in planning status we must mark an exception.
9595     -- if visit is already on the floor, we do nothing.
9596     IF (nvl(l_visit_status,'X') NOT IN ('RELEASED','CLOSED')) THEN
9597 
9598       -- Check if top node applicable.
9599       OPEN ahl_applicable_mr_csr(ahl_unplanned_ue_rec.csi_item_instance_id,
9600                                  ahl_unplanned_ue_rec.mr_header_id);
9601       FETCH ahl_applicable_mr_csr INTO l_junk;
9602       IF (ahl_applicable_mr_csr%FOUND) THEN
9603         --Match the group.
9604         Match_Group_MR (p_orig_csi_item_instance_id  => ahl_unplanned_ue_rec.csi_item_instance_id,
9605                         p_orig_mr_header_id          => ahl_unplanned_ue_rec.mr_header_id,
9606                         p_unit_effectivity_id        => ahl_unplanned_ue_rec.unit_effectivity_id,
9607                         x_group_match_flag           => l_grp_match_flag);
9608 
9609         IF (l_grp_match_flag = 'N') THEN
9610           l_exception_flag := TRUE;
9611         END IF;
9612       ELSE
9613         l_exception_flag := TRUE;
9614       END IF; -- ahl_applicable_mr_csr found chk.
9615       CLOSE ahl_applicable_mr_csr;
9616 
9617       IF G_DEBUG = 'Y' THEN
9618         AHL_DEBUG_PUB.debug('Group Match Flag for UE:' || ahl_unplanned_ue_rec.unit_effectivity_id || 'is:' ||
9619              l_grp_match_flag);
9620       END IF;
9621 
9622       -- If exception, then update the UE status to exception.
9623       -- If no longer an exception, then update the UE status to NULL.
9624       IF ((ahl_unplanned_ue_rec.status_code IS NULL) AND (l_exception_flag = TRUE)) OR
9625          ((ahl_unplanned_ue_rec.status_code = 'EXCEPTION') AND (l_exception_flag = FALSE)) THEN
9626 
9627          OPEN ahl_unit_effectivity_csr(ahl_unplanned_ue_rec.unit_effectivity_id);
9628          FETCH ahl_unit_effectivity_csr INTO l_ue_rec;
9629          IF (ahl_unit_effectivity_csr%NOTFOUND) THEN
9630            FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_UE_NOTFOUND');
9631            FND_MESSAGE.Set_Token('UE_ID',l_ue_rec.unit_effectivity_id);
9632            FND_MSG_PUB.ADD;
9633            -- dbms_output.put_line('unit effectivity not found for ue id' ||l_ue_rec.unit_effectivity_id );
9634            ClOSE ahl_unit_effectivity_csr;
9635            RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
9636          ELSE
9637            -- set UE attributes.
9638            IF (ahl_unplanned_ue_rec.status_code IS NULL) AND (l_exception_flag = TRUE) THEN
9639               IF G_DEBUG = 'Y' THEN
9640                 AHL_DEBUG_PUB.Debug('Updating Unplanned UE..' || l_ue_rec.unit_effectivity_id || ' to an exception');
9641               END IF;
9642               -- update unit effectivity.
9643               l_message_code := 'VISIT-ASSIGN';
9644               l_status_code := 'EXCEPTION';
9645            ELSE
9646               IF G_DEBUG = 'Y' THEN
9647                 AHL_DEBUG_PUB.Debug('Updating Unplanned UE..' || l_ue_rec.unit_effectivity_id || ' from an exception');
9648               END IF;
9649                -- update unit effectivity.
9650               l_message_code := NULL;
9651               l_status_code := NULL;
9652            END IF;
9653            ClOSE ahl_unit_effectivity_csr;
9654 
9655            -- Update unit effectivity.
9656            AHL_UNIT_EFFECTIVITIES_PKG.Update_Row(
9657                   X_UNIT_EFFECTIVITY_ID   => l_ue_rec.unit_effectivity_id,
9658                   X_CSI_ITEM_INSTANCE_ID  => l_ue_rec.csi_item_instance_id,
9659                   X_MR_INTERVAL_ID        => l_ue_rec.mr_interval_id,
9660                   X_MR_EFFECTIVITY_ID     => l_ue_rec.mr_effectivity_id,
9661                   X_MR_HEADER_ID          => l_ue_rec.mr_header_id,
9662                   X_STATUS_CODE           => l_status_code,
9663                   X_DUE_DATE              => l_ue_rec.due_date,
9664                   X_DUE_COUNTER_VALUE     => l_ue_rec.due_counter_value,
9665                   X_FORECAST_SEQUENCE     => l_ue_rec.forecast_sequence,
9666                   X_REPETITIVE_MR_FLAG    => l_ue_rec.repetitive_mr_flag,
9667                   X_TOLERANCE_FLAG        => l_ue_rec.tolerance_flag,
9668                   X_REMARKS               => l_ue_rec.remarks,
9669                   X_MESSAGE_CODE          => l_message_code,
9670                   X_PRECEDING_UE_ID       => l_ue_rec.preceding_ue_id,
9671                   X_DATE_RUN              => sysdate,
9672                   X_SET_DUE_DATE          => l_ue_rec.set_due_date,
9673                   X_ACCOMPLISHED_DATE     => l_ue_rec.accomplished_date,
9674                   X_SERVICE_LINE_ID       => l_ue_rec.service_line_id,
9675                   X_PROGRAM_MR_HEADER_ID  => l_ue_rec.program_mr_header_id,
9676                   X_CANCEL_REASON_CODE    => l_ue_rec.cancel_reason_code,
9677                   X_EARLIEST_DUE_DATE     => l_ue_rec.earliest_due_date,
9678                   X_LATEST_DUE_DATE       => l_ue_rec.latest_due_date,
9679                   X_defer_from_ue_id      => l_ue_rec.defer_from_ue_id,
9680                   X_cs_incident_id        => l_ue_rec.cs_incident_id,
9681                   X_qa_collection_id      => l_ue_rec.qa_collection_id,
9682                   X_orig_deferral_ue_id   => l_ue_rec.orig_deferral_ue_id,
9683                   X_application_usg_code  => l_ue_rec.application_usg_code,
9684                   X_object_type           => l_ue_rec.object_type,
9685                   X_counter_id          => l_ue_rec.counter_id,
9686                   X_MANUALLY_PLANNED_FLAG => l_ue_rec.MANUALLY_PLANNED_FLAG,
9687                   X_LOG_SERIES_CODE       => l_ue_rec.log_series_code,
9688                   X_LOG_SERIES_NUMBER     => l_ue_rec.log_series_number,
9689                   X_FLIGHT_NUMBER         => l_ue_rec.flight_number,
9690                   X_MEL_CDL_TYPE_CODE     => l_ue_rec.mel_cdl_type_code,
9691                   X_POSITION_PATH_ID      => l_ue_rec.position_path_id,
9692                   X_ATA_CODE              => l_ue_rec.ATA_CODE,
9693                   X_UNIT_CONFIG_HEADER_ID  => l_ue_rec.unit_config_header_id,
9694                   X_ATTRIBUTE_CATEGORY    => l_ue_rec.attribute_category,
9695                   X_ATTRIBUTE1            => l_ue_rec.attribute1,
9696                   X_ATTRIBUTE2            => l_ue_rec.attribute2,
9697                   X_ATTRIBUTE3            => l_ue_rec.attribute3,
9698                   X_ATTRIBUTE4            => l_ue_rec.attribute4,
9699                   X_ATTRIBUTE5            => l_ue_rec.attribute5,
9700                   X_ATTRIBUTE6            => l_ue_rec.attribute6,
9701                   X_ATTRIBUTE7            => l_ue_rec.attribute7,
9702                   X_ATTRIBUTE8            => l_ue_rec.attribute8,
9703                   X_ATTRIBUTE9            => l_ue_rec.attribute9,
9704                   X_ATTRIBUTE10           => l_ue_rec.attribute10,
9705                   X_ATTRIBUTE11           => l_ue_rec.attribute11,
9706                   X_ATTRIBUTE12           => l_ue_rec.attribute12,
9707                   X_ATTRIBUTE13           => l_ue_rec.attribute13,
9708                   X_ATTRIBUTE14           => l_ue_rec.attribute14,
9709                   X_ATTRIBUTE15           => l_ue_rec.attribute15,
9710                   X_OBJECT_VERSION_NUMBER => l_ue_rec.object_version_number + 1,
9711                   X_LAST_UPDATE_DATE => sysdate,
9712                   X_LAST_UPDATED_BY => fnd_global.user_id,
9713                   X_LAST_UPDATE_LOGIN  => fnd_global.login_id);
9714 
9715            -- Now update all the child MRs status too.
9716            FOR ue_reln_rec IN decendent_csr(ahl_unplanned_ue_rec.unit_effectivity_id) LOOP
9717 
9718              OPEN ahl_unit_effectivity_csr (ue_reln_rec.related_ue_id);
9719              FETCH ahl_unit_effectivity_csr INTO l_ue_rec;
9720              IF (ahl_unit_effectivity_csr%FOUND) THEN
9721                AHL_UNIT_EFFECTIVITIES_PKG.Update_Row(
9722                   X_UNIT_EFFECTIVITY_ID   => l_ue_rec.unit_effectivity_id,
9723                   X_CSI_ITEM_INSTANCE_ID  => l_ue_rec.csi_item_instance_id,
9724                   X_MR_INTERVAL_ID        => l_ue_rec.mr_interval_id,
9725                   X_MR_EFFECTIVITY_ID     => l_ue_rec.mr_effectivity_id,
9726                   X_MR_HEADER_ID          => l_ue_rec.mr_header_id,
9727                   X_STATUS_CODE           => l_status_code,
9728                   X_DUE_DATE              => l_ue_rec.due_date,
9729                   X_DUE_COUNTER_VALUE     => l_ue_rec.due_counter_value,
9730                   X_FORECAST_SEQUENCE     => l_ue_rec.forecast_sequence,
9731                   X_REPETITIVE_MR_FLAG    => l_ue_rec.repetitive_mr_flag,
9732                   X_TOLERANCE_FLAG        => l_ue_rec.tolerance_flag,
9733                   X_REMARKS               => l_ue_rec.remarks,
9734                   X_MESSAGE_CODE          => l_message_code,
9735                   X_PRECEDING_UE_ID       => l_ue_rec.preceding_ue_id,
9736                   X_DATE_RUN              => sysdate,
9737                   X_SET_DUE_DATE          => l_ue_rec.set_due_date,
9738                   X_ACCOMPLISHED_DATE     => l_ue_rec.accomplished_date,
9739                   X_SERVICE_LINE_ID       => l_ue_rec.service_line_id,
9740                   X_PROGRAM_MR_HEADER_ID  => l_ue_rec.program_mr_header_id,
9741                   X_CANCEL_REASON_CODE    => l_ue_rec.cancel_reason_code,
9742                   X_EARLIEST_DUE_DATE     => l_ue_rec.earliest_due_date,
9743                   X_LATEST_DUE_DATE       => l_ue_rec.latest_due_date,
9744                   X_defer_from_ue_id      => l_ue_rec.defer_from_ue_id,
9745                   X_cs_incident_id        => l_ue_rec.cs_incident_id,
9746                   X_qa_collection_id      => l_ue_rec.qa_collection_id,
9747                   X_orig_deferral_ue_id   => l_ue_rec.orig_deferral_ue_id,
9748                   X_application_usg_code  => l_ue_rec.application_usg_code,
9749                   X_object_type           => l_ue_rec.object_type,
9750                   X_counter_id          => l_ue_rec.counter_id,
9751                   X_MANUALLY_PLANNED_FLAG => l_ue_rec.MANUALLY_PLANNED_FLAG,
9752                   X_LOG_SERIES_CODE       => l_ue_rec.log_series_code,
9753                   X_LOG_SERIES_NUMBER     => l_ue_rec.log_series_number,
9754                   X_FLIGHT_NUMBER         => l_ue_rec.flight_number,
9755                   X_MEL_CDL_TYPE_CODE     => l_ue_rec.mel_cdl_type_code,
9756                   X_POSITION_PATH_ID      => l_ue_rec.position_path_id,
9757                   X_ATA_CODE              => l_ue_rec.ATA_CODE,
9758                   X_UNIT_CONFIG_HEADER_ID  => l_ue_rec.unit_config_header_id,
9759                   X_ATTRIBUTE_CATEGORY    => l_ue_rec.attribute_category,
9760                   X_ATTRIBUTE1            => l_ue_rec.attribute1,
9761                   X_ATTRIBUTE2            => l_ue_rec.attribute2,
9762                   X_ATTRIBUTE3            => l_ue_rec.attribute3,
9763                   X_ATTRIBUTE4            => l_ue_rec.attribute4,
9764                   X_ATTRIBUTE5            => l_ue_rec.attribute5,
9765                   X_ATTRIBUTE6            => l_ue_rec.attribute6,
9766                   X_ATTRIBUTE7            => l_ue_rec.attribute7,
9767                   X_ATTRIBUTE8            => l_ue_rec.attribute8,
9768                   X_ATTRIBUTE9            => l_ue_rec.attribute9,
9769                   X_ATTRIBUTE10           => l_ue_rec.attribute10,
9770                   X_ATTRIBUTE11           => l_ue_rec.attribute11,
9771                   X_ATTRIBUTE12           => l_ue_rec.attribute12,
9772                   X_ATTRIBUTE13           => l_ue_rec.attribute13,
9773                   X_ATTRIBUTE14           => l_ue_rec.attribute14,
9774                   X_ATTRIBUTE15           => l_ue_rec.attribute15,
9775                   X_OBJECT_VERSION_NUMBER => l_ue_rec.object_version_number + 1,
9776                   X_LAST_UPDATE_DATE => sysdate,
9777                   X_LAST_UPDATED_BY => fnd_global.user_id,
9778                   X_LAST_UPDATE_LOGIN  => fnd_global.login_id);
9779              ELSE
9780                FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_UE_NOTFOUND');
9781                FND_MESSAGE.Set_Token('UE_ID',l_ue_rec.unit_effectivity_id);
9782                FND_MSG_PUB.ADD;
9783                -- dbms_output.put_line('descendent mr not found for ue id');
9784                ClOSE ahl_unit_effectivity_csr;
9785                RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
9786              END IF;
9787              ClOSE ahl_unit_effectivity_csr;
9788            END LOOP; -- decendent_csr
9789 
9790           END IF; -- ahl_unit_effectivity_csr%NOTFOUND chk.
9791       END IF;  -- unplanned status code check.
9792     END IF; -- l_visit_status
9793 
9794   END LOOP; -- next unplanned MR.
9795 
9796   IF (G_DEBUG = 'Y') THEN
9797     AHL_DEBUG_PUB.debug('End of Process_Unplanned_UE');
9798   END IF;
9799 
9800 END Process_Unplanned_UE;
9801 
9802 
9803 -----------------------------------------------
9804 
9805 -- Procedure to calculate counter values at a given forecasted date for Reliability Fwk use.
9806 PROCEDURE Get_Forecasted_Counter_Values(
9807               x_return_status          OUT NOCOPY VARCHAR2,
9808               x_msg_data               OUT NOCOPY VARCHAR2,
9809               x_msg_count              OUT NOCOPY NUMBER,
9810               p_init_msg_list          IN         VARCHAR2 := FND_API.G_FALSE,
9811               p_csi_item_instance_id   IN         NUMBER,   -- Instance Id
9812               p_forecasted_date        IN         DATE,
9813               x_counter_values_tbl    OUT NOCOPY counter_values_tbl_type) -- Forecasted Counter Vals.
9814 IS
9815 
9816   l_csi_item_instance_id        NUMBER;
9817   l_uc_header_id                NUMBER;
9818   l_inventory_item_id           NUMBER;
9819   l_inv_master_organization_id  NUMBER;
9820   i                             NUMBER;
9821 
9822   l_current_usage_tbl    counter_values_tbl_type;
9823   /* contains current counter usage */
9824 
9825   l_counter_rules_tbl    counter_rules_tbl_type;
9826   /* contains current counter rules for the position */
9827 
9828   l_due_at_counter_val_tbl  counter_values_tbl_type;
9829   /* local variable to hold due at p_forecasted_date ctr values. */
9830 
9831   l_return_value                BOOLEAN;
9832 
9833 BEGIN
9834 
9835   IF G_DEBUG = 'Y' THEN
9836         AHL_DEBUG_PUB.Debug('Start API Get_Forecasted_Counter_Values');
9837   END IF;
9838 
9839   -- Initialize message list if p_init_msg_list is set to TRUE
9840   IF FND_API.To_Boolean(p_init_msg_list) THEN
9841     FND_MSG_PUB.Initialize;
9842   END IF;
9843 
9844   -- Initialize Procedure return status to success
9845   x_return_status := FND_API.G_RET_STS_SUCCESS;
9846 
9847   -- Enable Debug.
9848   IF G_DEBUG = 'Y' THEN
9849     AHL_DEBUG_PUB.enable_debug;
9850   END IF;
9851 
9852   -- Add debug mesg.
9853   IF G_DEBUG = 'Y' THEN
9854     AHL_DEBUG_PUB.debug('Begin private API:' ||  G_PKG_NAME || '.' || 'Get_Forcasted_Counter_Values');
9855 
9856     -- Dump input parameters.
9857     AHL_DEBUG_PUB.debug(' Csi Item instance ID:' || p_csi_item_instance_id);
9858     AHL_DEBUG_PUB.debug(' Forecasted Date:' || p_forecasted_date);
9859 
9860   END IF;
9861 
9862   -- validate item instance.
9863   Validate_item_instance(p_csi_item_instance_id, l_inventory_item_id,
9864                          l_inv_master_organization_id);
9865 
9866   IF FND_MSG_PUB.Count_msg > 0 THEN
9867      RAISE FND_API.G_EXC_ERROR;
9868   END IF;
9869 
9870   -- set instance variable.
9871   l_csi_item_instance_id := p_csi_item_instance_id;
9872 
9873 
9874   -- Set configuration variables based on installation type.
9875   -- If item instance is not top node, find the root item instance.
9876   l_csi_item_instance_id := Get_RootInstanceID(l_csi_item_instance_id);
9877 
9878   -- Get master and unit configuration IDs if they exist for this item instance.
9879   Get_Unit_Master_ConfigIDs (l_csi_item_instance_id,
9880                              l_uc_header_id, G_master_config_id);
9881 
9882   -- Check for errors.
9883   IF FND_MSG_PUB.Count_msg > 0 THEN
9884      RAISE FND_API.G_EXC_ERROR;
9885   END IF;
9886 
9887   -- Build the Configuration tree structure.(G_config_node_tbl).
9888   Build_Config_Tree(l_csi_item_instance_id, G_master_config_id, G_CONFIG_NODE_TBL);
9889 
9890   -- Add debug mesg.
9891   IF G_DEBUG = 'Y' THEN
9892     AHL_DEBUG_PUB.debug(' Count on Config Node Tbl:' || G_config_node_tbl.COUNT);
9893     AHL_DEBUG_PUB.debug(' Root Node:' || l_csi_item_instance_id );
9894     AHL_DEBUG_PUB.debug(' Unit Config ID:' || l_uc_header_id);
9895     AHL_DEBUG_PUB.debug(' Master Config ID:' || G_master_config_id);
9896   END IF;
9897 
9898   -- Read applicable utilization forecast for the configuration.
9899   Get_Utilization_Forecast (l_csi_item_instance_id,
9900                             l_uc_header_id,
9901                             l_inventory_item_id,
9902                             l_inv_master_organization_id,
9903                             G_forecast_details_tbl);
9904 
9905   -- Build counter rules ratio if node is not root node.
9906   IF (G_master_config_id IS NOT NULL AND p_csi_item_instance_id <> l_csi_item_instance_id) THEN
9907     IF (G_config_node_tbl.count > 0) THEN
9908        FOR j IN G_config_node_tbl.FIRST..G_config_node_tbl.LAST LOOP
9909          IF (G_config_node_tbl(j).csi_item_instance_id = p_csi_item_instance_id) THEN
9910             i := j;
9911          END IF;
9912        END LOOP;
9913     END IF; -- G_config_node_tbl.count.
9914     build_Counter_Ratio(G_config_node_tbl(i).position_reference,
9915                         G_config_node_tbl(i).csi_item_instance_id,
9916                         G_master_config_id,
9917                         l_counter_rules_tbl);
9918   END IF; -- G_master_config_id IS NOT NULL.
9919 
9920   -- Get current usage for all the counters defined for the item instance.
9921   get_Current_Usage (p_csi_item_instance_id,
9922                      l_current_usage_tbl);
9923 
9924 
9925   -- get all counter values as on p_forecasted_date.
9926   Get_Due_at_Counter_Values (p_last_due_date => sysdate,
9927                              p_last_due_counter_val_tbl => l_current_usage_tbl,
9928                              p_due_date => p_forecasted_date,
9929                              p_counter_rules_tbl => l_counter_rules_tbl,
9930                              x_due_at_counter_val_tbl => l_due_at_counter_val_tbl,
9931                              x_return_value => l_return_value);
9932 
9933   IF G_DEBUG = 'Y' THEN
9934      AHL_DEBUG_PUB.Debug('AFter get_due_at_counter_values');
9935      AHL_DEBUG_PUB.Debug('l_last_due_date: '|| sysdate);
9936      AHL_DEBUG_PUB.Debug('l_due_date: '|| p_forecasted_date);
9937      IF (l_due_at_counter_val_tbl.COUNT) > 0 THEN
9938           for i in l_due_at_counter_val_tbl.FIRST..l_due_at_counter_val_tbl.LAST LOOP
9939             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);
9940           end loop;
9941      END IF; -- count.
9942   END IF; -- Debug = Y
9943 
9944   IF NOT(l_return_value) THEN
9945      RAISE FND_API.G_EXC_ERROR;  /* no forecast available */
9946   ELSE
9947      x_counter_values_tbl := l_due_at_counter_val_tbl;
9948   END IF;
9949 
9950   -- Standard call to get message count and if count is 1, get message info
9951   FND_MSG_PUB.Count_And_Get
9952     ( p_count => x_msg_count,
9953       p_data  => x_msg_data,
9954       p_encoded => fnd_api.g_false
9955     );
9956 
9957   IF G_DEBUG = 'Y' THEN
9958         AHL_DEBUG_PUB.Debug('End API Get_Forecasted_Counter_Values');
9959   END IF;
9960 
9961 --
9962 EXCEPTION
9963  WHEN FND_API.G_EXC_ERROR THEN
9964    x_return_status := FND_API.G_RET_STS_ERROR;
9965    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
9966                               p_data  => x_msg_data,
9967                               p_encoded => fnd_api.g_false);
9968 
9969    -- Disable debug
9970    AHL_DEBUG_PUB.disable_debug;
9971 
9972  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
9973    x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
9974    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
9975                               p_data  => x_msg_data,
9976                               p_encoded => fnd_api.g_false);
9977 
9978    -- Disable debug
9979    AHL_DEBUG_PUB.disable_debug;
9980 
9981  WHEN OTHERS THEN
9982     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
9983     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
9984        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
9985                                p_procedure_name => 'Get_Forecasted_Counter_Values',
9986                                p_error_text     => SUBSTR(SQLERRM,1,240));
9987     END IF;
9988     FND_MSG_PUB.count_and_get( p_count => x_msg_count,
9989                                p_data  => x_msg_data,
9990                                p_encoded => fnd_api.g_false);
9991 
9992     -- Disable debug
9993     AHL_DEBUG_PUB.disable_debug;
9994 
9995 END Get_Forecasted_Counter_Values;
9996 ----------------------------------------------
9997 -- Added in R12 to fix bug# 4224867.
9998 -- find usage forecast for a given date.
9999 PROCEDURE get_usage_for_date(p_due_date          IN DATE,
10000                              p_counter_uom_code  IN VARCHAR2,
10001                              p_counter_rules_tbl IN Counter_rules_tbl_type,
10002                              x_usage_per_day     OUT NOCOPY NUMBER)
10003 IS
10004   l_next_index  NUMBER;
10005 
10006 BEGIN
10007 
10008   x_usage_per_day := 0;
10009 
10010   -- Read g_forecast_details_tbl to get forecast values.
10011   l_next_index := G_forecast_details_tbl.FIRST;
10012 
10013   IF (l_next_index IS NOT NULL) THEN
10014     FOR i IN G_forecast_details_tbl.FIRST..G_forecast_details_tbl.LAST LOOP
10015       IF (G_forecast_details_tbl(i).uom_code = p_counter_uom_code) AND
10016          (trunc(G_forecast_details_tbl(i).start_date) <= trunc(p_due_date) AND
10017           trunc(p_due_date) <= trunc(nvl(G_forecast_details_tbl(i).end_date,p_due_date)))
10018       THEN
10019          x_usage_per_day := G_forecast_details_tbl(i).usage_per_day;
10020          EXIT;
10021       END IF;
10022     END LOOP;
10023   END IF;
10024 
10025   --dbms_output.put_line ('counter remain input to forecast' || l_counter_remain );
10026   --dbms_output.put_line ('counter uom' ||p_counter_uom_code);
10027 
10028   x_usage_per_day := Apply_ReverseCounter_Ratio ( x_usage_per_day,
10029                                                   p_counter_uom_code,
10030                                                   p_counter_rules_tbl);
10031 
10032 
10033 END get_usage_for_date;
10034 ----------------------------------------------
10035 -- Added to fix bug# 6875650.
10036 -- Get the latest recorded counter reading for a given datetime.
10037 PROCEDURE get_ctr_reading_for_datetime (p_csi_item_instance_id IN NUMBER,
10038                                         p_counter_id           IN NUMBER,
10039                                         p_reading_date         IN DATE,
10040                                         x_net_reading        OUT NOCOPY NUMBER) IS
10041 
10042   -- get the latest reading recorded for a counter on any given date.
10043   CURSOR cs_ctr_reading_csr(p_csi_item_instance_id IN NUMBER,
10044                             p_counter_id           IN NUMBER,
10045                             p_reading_date IN DATE) IS
10046         SELECT * FROM (
10047 	               SELECT CCR.NET_READING
10048 	               FROM
10049 		            CSI_COUNTER_READINGS CCR
10050 	               WHERE
10051 		            CCR.COUNTER_ID          = P_COUNTER_ID
10052                          AND nvl(disabled_flag,'N') = 'N'
10053 		         AND CCR.VALUE_TIMESTAMP   <= P_READING_DATE
10054       	               ORDER BY CCR.VALUE_TIMESTAMP DESC
10055                       )
10056         WHERE ROWNUM < 2;
10057 
10058   l_net_reading  NUMBER;
10059 
10060 BEGIN
10061 
10062     IF G_DEBUG = 'Y' THEN
10063       AHL_DEBUG_PUB.debug('Start of get_ctr_reading_for_datetime');
10064     END IF;
10065 
10066     OPEN cs_ctr_reading_csr(p_csi_item_instance_id,
10067                             p_counter_id,
10068                             p_reading_date);
10069     FETCH cs_ctr_reading_csr INTO l_net_reading;
10070     IF (cs_ctr_reading_csr%NOTFOUND) THEN
10071        l_net_reading := 0;
10072     END IF;
10073     CLOSE cs_ctr_reading_csr;
10074 
10075     x_net_reading := l_net_reading;
10076 
10077     IF G_DEBUG = 'Y' THEN
10078       AHL_DEBUG_PUB.debug('End of get_ctr_reading_for_datetime');
10079     END IF;
10080 
10081 END get_ctr_reading_for_datetime;
10082 
10083 ----------------------------------------------
10084 -- added to fix bug# 6907562.
10085 -- function that compares previous due date and uom remain with current values
10086 -- and return Y is the current due date replaces the prev one.
10087 FUNCTION validate_for_duedate_reset(p_due_date        IN DATE,
10088                                     p_uom_remain      IN NUMBER,
10089                                     p_prev_due_date   IN DATE,
10090                                     p_prev_counter_id IN NUMBER,
10091                                     p_prev_uom_remain IN NUMBER)
10092 RETURN VARCHAR2 IS
10093   l_return_status  VARCHAR2(1);
10094 
10095 BEGIN
10096   IF G_DEBUG = 'Y' THEN
10097     AHL_DEBUG_PUB.debug('Start of validate_for_duedate_reset');
10098   END IF;
10099 
10100   l_return_status := 'N';
10101   IF (p_due_date IS NULL) THEN
10102     -- check if p_prev_counter_id is null or not. If null then this is first due date calculation.
10103     IF (p_prev_counter_id IS NULL) THEN
10104       l_return_status := 'Y';
10105     ELSE
10106       -- check prior date; it could either be null or not null.
10107       IF (p_prev_due_date IS NULL) THEN
10108         -- trigger ctr based on uom remain.
10109         IF (p_uom_remain < p_prev_uom_remain) THEN
10110            l_return_status := 'Y';
10111         END IF;
10112       ELSE -- p_prev_due_date is not null.
10113         -- check UOM remaining.
10114         IF (p_prev_uom_remain <= 0 AND p_uom_remain > 0) OR
10115            (p_prev_uom_remain < p_uom_remain AND p_uom_remain < 0) THEN
10116             null; -- do nothing
10117         ELSE
10118            l_return_status := 'Y';
10119         END IF; -- p_prev_uom_remain < 0
10120       END IF; -- p_prev_due_date
10121     END IF; -- p_prev_counter_id
10122   ELSE -- p_due_date is not null.
10123     IF (p_prev_due_date IS NULL) THEN
10124       IF (p_prev_counter_id IS NULL) THEN
10125         -- this is first time due due calculation.
10126         l_return_status := 'Y';
10127       ELSE
10128         -- prior due date is a null due date.
10129         -- swap based on uom remain.
10130         IF (p_uom_remain < p_prev_uom_remain AND p_prev_uom_remain < 0) OR
10131            (p_uom_remain <= 0 AND p_prev_uom_remain > 0) THEN
10132            l_return_status := 'Y';
10133         END IF;
10134       END IF; -- p_prev_counter_id
10135     END IF; -- p_prev_due_date
10136   END IF; -- p_due_date
10137 
10138   IF G_DEBUG = 'Y' THEN
10139     AHL_DEBUG_PUB.debug('End of validate_for_duedate_reset');
10140   END IF;
10141 
10142   RETURN l_return_status;
10143 
10144 END validate_for_duedate_reset;
10145 
10146 -----------------------------------------------
10147 -- Added procedure to replace call to ahl_fmp_pvt.get_mr_affected_items for Prev. Maint
10148 -- Called when processing based on MR invoked through concurrent program.
10149 -- Perf fix for bug# 5093064.
10150 PROCEDURE Process_PM_MR_Affected_Items(
10151     p_commit                 IN            VARCHAR2 := FND_API.G_FALSE,
10152     x_msg_count              OUT NOCOPY    NUMBER,
10153     x_msg_data               OUT NOCOPY    VARCHAR2,
10154     x_return_status          OUT NOCOPY    VARCHAR2,
10155     p_mr_header_id           IN            NUMBER,
10156     p_old_mr_header_id       IN            NUMBER    := NULL,
10157     p_concurrent_flag        IN            VARCHAR2  := 'N',
10158     p_num_of_workers         IN            NUMBER    := 10)
10159 
10160 IS
10161 
10162   l_msg_count             NUMBER;
10163   l_return_status         VARCHAR2(1);
10164   l_msg_data              VARCHAR2(30);
10165   i                       NUMBER;
10166   l_debug                 VARCHAR2(1) := AHL_DEBUG_PUB.is_log_enabled;
10167   l_master_org_id         NUMBER;
10168   l_mr_header_id          NUMBER;
10169 
10170   l_csi_min_id            NUMBER;
10171   l_csi_max_id            NUMBER;
10172   l_csi_eff_min_id        NUMBER;
10173   l_csi_eff_max_id        NUMBER;
10174   l_num_workers           NUMBER;
10175   l_end_csi_id            NUMBER;
10176   l_start_csi_id          NUMBER;
10177   l_step                  NUMBER;
10178   l_req_id                NUMBER;
10179   l_count                 NUMBER;
10180   l_total_count           NUMBER := 0;
10181 
10182   l_csi_inst_tbl         nbr_tbl_type;
10183 
10184   --check whether the given mr exists
10185   CURSOR check_mr_exists(c_mr_header_id number)
10186   IS
10187     SELECT mr_header_id
10188       FROM ahl_mr_headers_app_v
10189      WHERE mr_header_id = c_mr_header_id;
10190 
10191   --get all the MR effectivity definitions for a given MR
10192   CURSOR get_mr_effect(c_mr_header_id NUMBER)
10193   IS
10194    SELECT mr_header_id, mr_effectivity_id, inventory_item_id
10195    FROM ahl_mr_effectivities_app_v
10196    WHERE mr_header_id = c_mr_header_id;
10197 
10198   -- get master org id.
10199   CURSOR get_master_org_id_csr (c_inventory_item_id IN NUMBER)
10200   IS
10201     SELECT itm.organization_id
10202     FROM mtl_system_items_b itm, mtl_parameters mtl
10203     WHERE itm.inventory_item_id = c_inventory_item_id
10204       AND   itm.organization_id = mtl.organization_id
10205       AND   mtl.master_organization_id = mtl.organization_id;
10206 
10207   -- Get min/max instance ID for a given INV ID.
10208   CURSOR get_minmax_inst_csr(c_inventory_item_id IN NUMBER,
10209                              c_inventory_org_id  IN NUMBER)
10210   IS
10211     SELECT min(instance_id), max(instance_id), count(instance_id)
10212     FROM csi_item_instances
10213     WHERE inventory_item_id = c_inventory_item_id
10214     AND   inv_master_organization_id = c_inventory_org_id
10215     AND SYSDATE between trunc(nvl(active_start_date,sysdate)) and
10216         trunc(nvl(active_end_date,sysdate+1))
10217     GROUP BY inventory_item_id, inv_master_organization_id;
10218 
10219   -- get instances when mr_header_id is provided.
10220   CURSOR get_inst( p_mr_header_id      IN NUMBER,
10221                    c_start_inst_id     IN NUMBER,
10222                    c_end_inst_id       IN NUMBER)
10223   IS
10224   SELECT cii.instance_id
10225     FROM csi_item_instances cii, ahl_mr_effectivities mre, mtl_system_items_b msi
10226     WHERE cii.inventory_item_id = msi.inventory_item_id
10227     AND cii.inv_master_organization_id = msi.organization_id
10228     AND cii.inventory_item_id = mre.inventory_item_id
10229     AND mre.mr_header_id = p_mr_header_id
10230     AND SYSDATE between trunc(nvl(cii.active_start_date,sysdate)) and
10231         trunc(nvl(cii.active_end_date,sysdate+1))
10232     AND cii.instance_id >= c_start_inst_id
10233     AND cii.instance_id <= c_end_inst_id;
10234 
10235 BEGIN
10236 
10237   IF l_debug = 'Y' THEN
10238     AHL_DEBUG_PUB.enable_debug;
10239     AHL_DEBUG_PUB.debug('Begin private API: AHL_UMP_PROCESSUNIT_PVT.PROCESS_PM_MR_AFFECTED_ITEMS');
10240   END IF;
10241 
10242   -- Check whether the mr_header_id exists --
10243   OPEN check_mr_exists(p_mr_header_id);
10244   FETCH check_mr_exists INTO l_mr_header_id;
10245   IF check_mr_exists%NOTFOUND THEN
10246     CLOSE check_mr_exists;
10247     FND_MESSAGE.SET_NAME('AHL','AHL_FMP_INVALID_MR');
10248     FND_MSG_PUB.ADD;
10249     RAISE FND_API.G_EXC_ERROR;
10250   END IF;
10251   CLOSE check_mr_exists;
10252 
10253   IF l_debug = 'Y' THEN
10254     AHL_DEBUG_PUB.debug(' Phase 1');
10255   END IF;
10256 
10257   -- validate # of workers.
10258   l_num_workers := p_num_of_workers;
10259 
10260   IF (p_num_of_workers > 30) THEN
10261      l_num_workers := 30;
10262   END IF;
10263 
10264   IF l_debug = 'Y' THEN
10265     AHL_DEBUG_PUB.debug(' Phase 2:l_num_workers:' || l_num_workers);
10266   END IF;
10267 
10268   FOR l_mr_effect IN get_mr_effect(p_mr_header_id)
10269   LOOP
10270     IF (l_mr_effect.inventory_item_id IS NOT NULL) THEN
10271 
10272         IF l_debug = 'Y' THEN
10273            AHL_DEBUG_PUB.debug(' Phase 3:Inv Item ID:' || l_mr_effect.inventory_item_id);
10274         END IF;
10275 
10276         --DBMS_OUTPUT.put_line('API1: Come here in case 1B and l_index is: '||l_index);
10277 
10278         AHL_FMP_COMMON_PVT.validate_item(x_return_status => l_return_status,
10279                                          x_msg_data => l_msg_data,
10280                                          p_item_number => NULL,
10281                                          p_x_inventory_item_id => l_mr_effect.inventory_item_id);
10282         IF (l_return_status = 'S') THEN
10283 
10284            IF l_debug = 'Y' THEN
10285               AHL_DEBUG_PUB.debug('Phase 4: Inv Item ID is Valid');
10286            END IF;
10287            -- get master organization id.
10288            OPEN get_master_org_id_csr(l_mr_effect.inventory_item_id);
10289            FETCH get_master_org_id_csr INTO l_master_org_id;
10290            IF (get_master_org_id_csr%NOTFOUND) THEN
10291               FND_MESSAGE.Set_Name('AHL','AHL_UMP_PUE_MASORG_NOTFOUND');
10292               FND_MESSAGE.Set_Token('INV_ID',l_mr_effect.inventory_item_id);
10293               FND_MSG_PUB.ADD;
10294               --DBMS_OUTPUT.put_line('Master org not found for inventory item:' || l_mr_effect.inventory_item_id);
10295               ClOSE get_master_org_id_csr;
10296               RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
10297            END IF;
10298            CLOSE get_master_org_id_csr;
10299 
10300            OPEN get_minmax_inst_csr(l_mr_effect.inventory_item_id,l_master_org_id);
10301            FETCH get_minmax_inst_csr INTO l_csi_eff_min_id, l_csi_eff_max_id, l_count;
10302            IF (get_minmax_inst_csr%FOUND) THEN
10303               IF ((l_csi_min_id IS NULL) OR (l_csi_eff_min_id < l_csi_min_id)) THEN
10304                   l_csi_min_id := l_csi_eff_min_id;
10305               END IF;
10306 
10307               IF ((l_csi_max_id IS NULL) OR (l_csi_max_id < l_csi_eff_max_id)) THEN
10308                  l_csi_max_id := l_csi_eff_max_id;
10309               END IF;
10310               l_total_count := l_count + l_total_count;
10311 
10312            END IF;
10313            CLOSE get_minmax_inst_csr;
10314 
10315            IF l_debug = 'Y' THEN
10316               AHL_DEBUG_PUB.debug(' Phase 5:csi_min:csi_max:count:' || l_csi_min_id || ':' || l_csi_max_id || ':' ||
10317                                     l_total_count);
10318            END IF;
10319 
10320         END IF; -- l_return_status = 'S'
10321       END IF; -- l_mr_effect.inventory_item_id IS NOT NULL
10322     END LOOP; -- l_mr_effect
10323 
10324     IF (p_concurrent_flag = 'Y') THEN
10325        -- launch workers after assigning instance range.
10326        IF (l_num_workers < 15) THEN
10327           Instance_Split_BTree(p_csi_max_id  => l_csi_max_id,
10328                                p_csi_min_id  => l_csi_min_id,
10329                                p_num_workers => p_num_of_workers,
10330                                p_mr_header_id => p_mr_header_id,
10331                                p_total_inst_count  => l_total_count);
10332        ELSE
10333           Instance_Split_Sequential(p_csi_max_id  => l_csi_max_id,
10334                                     p_csi_min_id  => l_csi_min_id,
10335                                     p_num_workers => p_num_of_workers,
10336                                     p_mr_header_id => p_mr_header_id);
10337 
10338        END IF;
10339     ELSE
10340        -- process all instances.
10341        OPEN get_inst(p_mr_header_id, l_csi_min_id, l_csi_max_id);
10342        LOOP
10343 
10344          FETCH get_inst BULK COLLECT INTO l_csi_inst_tbl LIMIT 1000;
10345          IF (l_csi_inst_tbl.count > 0) THEN
10346            -- call process unit for all instances.
10347 
10348            FOR i IN l_csi_inst_tbl.FIRST..l_csi_inst_tbl.LAST  LOOP
10349              -- Call Process Unit for the item instance.
10350              Process_Unit (
10351                          p_commit               => FND_API.G_TRUE,
10352                          p_init_msg_list        => FND_API.G_TRUE,
10353                          x_msg_count            => x_msg_count,
10354                          x_msg_data             => x_msg_data,
10355                          x_return_status        => x_return_status,
10356                          p_csi_item_instance_id => l_csi_inst_tbl(i),
10357                          p_concurrent_flag      => 'N');
10358 
10359              IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
10360                EXIT;
10361              END IF;
10362 
10363            END LOOP; -- l_csi_inst_tbl.FIRST
10364          END IF; -- l_csi_inst_tbl.count
10365          IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
10366            EXIT;
10367          END IF;
10368 
10369          EXIT WHEN get_inst%NOTFOUND;
10370        END LOOP; -- get_inst.
10371        CLOSE get_inst;
10372     END IF; -- p_concurrent_flag
10373 
10374 END Process_PM_MR_Affected_Items;
10375 
10376 ----------------------------------------------
10377 -- Split instance range into blocks based on instance IDs.
10378 PROCEDURE Instance_Split_Sequential(p_csi_max_id  in NUMBER,
10379                                     p_csi_min_id  IN NUMBER,
10380                                     p_num_workers IN NUMBER,
10381                                     p_mr_header_id IN NUMBER)
10382 IS
10383 
10384   l_debug                 VARCHAR2(1) := AHL_DEBUG_PUB.is_log_enabled;
10385 
10386   l_csi_min_id            NUMBER;
10387   l_csi_max_id            NUMBER;
10388   l_csi_eff_min_id        NUMBER;
10389   l_csi_eff_max_id        NUMBER;
10390   l_num_workers           NUMBER;
10391   l_end_csi_id            NUMBER;
10392   l_start_csi_id          NUMBER;
10393   l_step                  NUMBER;
10394   l_req_id                NUMBER;
10395 
10396 BEGIN
10397 
10398     l_num_workers := p_num_workers;
10399     l_csi_min_id := p_csi_min_id;
10400     l_csi_max_id := p_csi_max_id;
10401 
10402     -- split the instances based on # of workers and launch seperate concurrent
10403     -- programs to process a group of instances.
10404     IF (l_csi_max_id IS NOT NULL) AND (l_csi_min_id IS NOT NULL) THEN
10405        l_step := round((l_csi_max_id - l_csi_min_id) / l_num_workers);
10406 
10407        IF (l_step < 1) THEN
10408           l_step := l_csi_max_id - l_csi_min_id;
10409           l_num_workers := 1;
10410        END IF;
10411 
10412        l_start_csi_id := l_csi_min_id;
10413 
10414        IF l_debug = 'Y' THEN
10415           AHL_DEBUG_PUB.debug('l_step:' || l_step  || 'start csi: end csi' || l_start_csi_id || ':' || l_end_csi_id);
10416        END IF;
10417 
10418        -- loop through
10419        WHILE (l_start_csi_id < l_csi_max_id) LOOP
10420          l_end_csi_id := l_start_csi_id + l_step;
10421          IF (l_end_csi_id > l_csi_max_id) THEN
10422             l_end_csi_id := l_csi_max_id;
10423          END IF;
10424 
10425          IF l_debug = 'Y' THEN
10426           AHL_DEBUG_PUB.debug('Loop start csi: end csi' || l_start_csi_id || ':' || l_end_csi_id);
10427          END IF;
10428 
10429          -- launch BUE worker request.
10430          l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, p_mr_header_id, l_start_csi_id, l_end_csi_id);
10431 
10432          IF (l_req_id = 0 OR l_req_id IS NULL) THEN
10433             IF l_debug = 'Y' THEN
10434               AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
10435             END IF;
10436             fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
10437             fnd_file.new_line(FND_FILE.LOG,1);
10438             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
10439 
10440          ELSE
10441               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);
10442 
10443             IF l_debug = 'Y' THEN
10444               AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id || ' launched to process instances between:' || l_start_csi_id || ' and ' || l_end_csi_id);
10445             END IF;
10446          END IF;
10447 
10448          l_start_csi_id := l_end_csi_id + 1;
10449 
10450        END LOOP;
10451     END IF;
10452 
10453 END Instance_Split_Sequential;
10454 
10455 ----------------------------------------------
10456 -- Split instances based on instance count.
10457 PROCEDURE Instance_Split_BTree(p_csi_max_id  in NUMBER,
10458                                p_csi_min_id  IN NUMBER,
10459                                p_num_workers IN NUMBER,
10460                                p_mr_header_id IN NUMBER,
10461                                p_total_inst_count  IN NUMBER)
10462 IS
10463 
10464   l_debug                 VARCHAR2(1) := AHL_DEBUG_PUB.is_log_enabled;
10465   l_step number;
10466   l_start_csi_id number;
10467   l_launched_workers number;
10468   l_mid_point_inst_id number;
10469   l_count number;
10470   l_req_id number;
10471   l_end_csi_id number;
10472   l_begin_count_csi_id number;
10473 
10474   l_tol_after number;
10475   l_tol_bef   number;
10476 
10477   l_num_workers number;
10478 
10479   cursor csi_inst_count_csr (p_start_inst_id in number,
10480                              p_end_inst_id   in number,
10481                              p_mr_header_id  in number) IS
10482     SELECT count(instance_id)
10483     FROM csi_item_instances csi, ahl_mr_effectivities me
10484     WHERE csi.instance_id >= p_start_inst_id and csi.instance_id <= p_end_inst_id
10485     AND csi.inventory_item_id = me.inventory_item_id
10486     AND me.mr_header_id = p_mr_header_id
10487     AND SYSDATE between trunc(nvl(active_start_date,sysdate)) and
10488         trunc(nvl(active_end_date,sysdate+1));
10489 
10490 BEGIN
10491     IF l_debug = 'Y' THEN
10492        AHL_DEBUG_PUB.debug('Start of procedure: Instance_Split_BTree');
10493        AHL_DEBUG_PUB.debug('p_mr_header_id:' || p_mr_header_id);
10494        AHL_DEBUG_PUB.debug('p_num_workers:' || p_num_workers);
10495        AHL_DEBUG_PUB.debug('p_csi_max_id:' || p_csi_max_id);
10496        AHL_DEBUG_PUB.debug('p_csi_min_id:' || p_csi_min_id);
10497        AHL_DEBUG_PUB.debug('p_total_inst_count:' || p_total_inst_count);
10498     END IF;
10499 
10500     l_num_workers := p_num_workers;
10501 
10502     IF (p_total_inst_count > 0 ) THEN
10503        IF (l_num_workers = 1) THEN
10504          -- launch BUE worker request.
10505          l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, p_mr_header_id,
10506                                                 p_csi_min_id, p_csi_max_id);
10507 
10508          IF (l_req_id = 0 OR l_req_id IS NULL) THEN
10509             IF l_debug = 'Y' THEN
10510               AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
10511             END IF;
10512             fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
10513             fnd_file.new_line(FND_FILE.LOG,1);
10514             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
10515 
10516          ELSE
10517               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);
10518 
10519             IF l_debug = 'Y' THEN
10520               AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id || ' launched to process instances between:' || p_csi_min_id || ' and ' || p_csi_min_id);
10521             END IF;
10522          END IF;
10523 
10524        ELSE
10525          -- find optimal and tolerant count of instances and hence the start and
10526          -- end instance ID for each worker.
10527          l_step := round(p_total_inst_count/l_num_workers);
10528          IF (l_step = 0) THEN
10529            l_num_workers := p_total_inst_count;
10530            l_step := 1;
10531          END IF;
10532          l_tol_bef := l_step - trunc((0.1 * l_step));
10533          l_tol_after := l_step + trunc((0.1 * l_step));
10534 
10535          IF l_debug = 'Y' THEN
10536             AHL_DEBUG_PUB.debug('l_step:' || l_step);
10537             AHL_DEBUG_PUB.debug('l_tol_bef:' || l_tol_bef);
10538             AHL_DEBUG_PUB.debug('l_tol_after:' || l_tol_after);
10539          END IF;
10540 
10541          --dbms_output.put_line('l_Step:' || l_step);
10542          --dbms_output.put_line('l_tol_minus:' || l_tol_bef);
10543          --dbms_output.put_line('l_tol_plus:' || l_tol_after);
10544 
10545          -- use binary search logic to find the start and end points for every worker.
10546          l_begin_count_csi_id := p_csi_min_id;
10547          l_start_csi_id := p_csi_min_id;
10548          l_end_csi_id := p_csi_max_id;
10549 
10550          l_launched_workers := 0;
10551 
10552          --l_mid_point_inst_id := trunc((p_csi_min_id + p_csi_max_id) / 2);
10553          l_mid_point_inst_id := p_csi_max_id; -- start with full interval.
10554 
10555          WHILE (l_launched_workers < l_num_workers) loop
10556 
10557              WHILE (true) LOOP
10558 
10559                IF l_debug = 'Y' THEN
10560                   AHL_DEBUG_PUB.debug('Start loop:l_begin_count_csi_id:' || l_begin_count_csi_id);
10561                   AHL_DEBUG_PUB.debug('l_start_csi_id:' || l_start_csi_id);
10562                   AHL_DEBUG_PUB.debug('l_mid_point_inst_id:' || l_mid_point_inst_id);
10563                   --dbms_output.put_line('l_start_csi_id:' || l_start_csi_id);
10564                   --dbms_output.put_line('l_mid_point_inst_id:' || l_mid_point_inst_id);
10565                END IF;
10566 
10567                OPEN csi_inst_count_csr(l_begin_count_csi_id, l_mid_point_inst_id, p_mr_header_id);
10568                FETCH csi_inst_count_csr INTO l_count;
10569                CLOSE csi_inst_count_csr;
10570 
10571                IF l_debug = 'Y' THEN
10572                   AHL_DEBUG_PUB.debug('l_count:' || l_count);
10573                END IF;
10574                -- dbms_output.put_line('l_count:' || l_count);
10575 
10576                IF (l_count >= l_tol_bef AND l_count <= l_tol_after) THEN
10577 
10578                   l_launched_workers := l_launched_workers + 1;
10579 
10580                   -- launch BUE worker request.
10581                   l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, p_mr_header_id,
10582                                                          l_begin_count_csi_id, l_mid_point_inst_id);
10583 
10584                   --dbms_output.put_line('new l_launched_workers:' || l_launched_workers);
10585                   --dbms_output.put_line('newB l_begin_count_csi_id:' || l_begin_count_csi_id);
10586                   --dbms_output.put_line('newB l_mid_point_inst_id:' || l_mid_point_inst_id);
10587 
10588                   IF (l_req_id = 0 OR l_req_id IS NULL) THEN
10589                      IF l_debug = 'Y' THEN
10590                        AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
10591                      END IF;
10592                      fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
10593                      fnd_file.new_line(FND_FILE.LOG,1);
10594                      RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
10595 
10596                   ELSE
10597                      fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id ||
10598                      ' launched to process instances between:' || l_begin_count_csi_id || ' and ' ||
10599                       l_mid_point_inst_id);
10600 
10601                      IF l_debug = 'Y' THEN
10602                        AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id ||
10603                        ' launched to process instances between:' || l_begin_count_csi_id || ' and ' ||
10604                        l_mid_point_inst_id);
10605                      END IF;
10606                   END IF;
10607                   IF (l_launched_workers = l_num_workers - 1) THEN
10608                      -- launch last worker.
10609                      l_begin_count_csi_id := l_mid_point_inst_id + 1;
10610                      l_mid_point_inst_id := p_csi_max_id;
10611                      l_launched_workers := l_launched_workers + 1;
10612                      l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, p_mr_header_id,
10613                                                             l_begin_count_csi_id, l_mid_point_inst_id);
10614                      IF (l_req_id = 0 OR l_req_id IS NULL) THEN
10615                         IF l_debug = 'Y' THEN
10616                           AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
10617                         END IF;
10618                         fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
10619                         fnd_file.new_line(FND_FILE.LOG,1);
10620                         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
10621 
10622                      ELSE
10623                         fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id ||
10624                         ' launched to process instances between:' || l_begin_count_csi_id || ' and ' ||
10625                          l_mid_point_inst_id);
10626 
10627                         IF l_debug = 'Y' THEN
10628                           AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id ||
10629                           ' launched to process instances between:' || l_begin_count_csi_id || ' and ' ||
10630                           l_mid_point_inst_id);
10631                         END IF;
10632                      END IF; -- l_req_id = 0 OR ..
10633                   END IF;
10634                   EXIT;
10635                ELSIF (l_count < l_step) THEN
10636                   l_start_csi_id := l_mid_point_inst_id;
10637                   l_mid_point_inst_id := trunc((l_mid_point_inst_id + l_end_csi_id) /2);
10638                   --dbms_output.put_line('new l_mid_point_inst_id:<' || l_mid_point_inst_id);
10639                ELSIF (l_count > l_step) THEN
10640                   l_end_csi_id := l_mid_point_inst_id;
10641                   l_mid_point_inst_id := trunc((l_mid_point_inst_id + l_start_csi_id)/2);
10642                   --dbms_output.put_line('new l_mid_point_inst_id:>' || l_mid_point_inst_id);
10643 
10644                END IF; -- l_count >= l_tol_bef..
10645              END LOOP; -- WHILE (true)
10646              -- initialize begin, start and end points for next worker.
10647              l_begin_count_csi_id := l_mid_point_inst_id+1;
10648              l_start_csi_id := l_mid_point_inst_id+1;
10649              l_end_csi_id := p_csi_max_id;
10650              l_mid_point_inst_id := trunc((l_start_csi_id + l_end_csi_id) / 2);
10651          END LOOP;
10652 
10653      END IF;
10654   END IF;
10655 
10656   IF l_debug = 'Y' THEN
10657      AHL_DEBUG_PUB.debug('End of procedure: Instance_Split_BTree');
10658   END IF;
10659 
10660 END Instance_Split_BTree;
10661 
10662 ----------------------------------------------
10663 -- PM Build unit Effectivities worker concurrent program.
10664 PROCEDURE Process_Unit_Range (
10665                      errbuf                 OUT NOCOPY  VARCHAR2,
10666                      retcode                OUT NOCOPY  NUMBER,
10667                      p_mr_header_id         IN NUMBER,
10668                      p_start_instance_id    IN NUMBER,
10669                      p_end_instance_id      IN NUMBER)
10670 IS
10671 
10672   -- get instances when mr_header_id is provided.
10673   CURSOR get_inst( p_mr_header_id      IN NUMBER,
10674                    c_start_inst_id     IN NUMBER,
10675                    c_end_inst_id       IN NUMBER)
10676   IS
10677   SELECT cii.instance_id
10678     FROM csi_item_instances cii, ahl_mr_effectivities mre, mtl_system_items_b msi
10679     -- repalced mtl_system_items_kfv with mtl_system items_b.
10680     WHERE cii.inventory_item_id = msi.inventory_item_id
10681     AND cii.inv_master_organization_id = msi.organization_id
10682     AND cii.inventory_item_id = mre.inventory_item_id
10683     AND mre.mr_header_id = p_mr_header_id
10684     AND SYSDATE between trunc(nvl(cii.active_start_date,sysdate)) and
10685         trunc(nvl(cii.active_end_date,sysdate+1))
10686     AND cii.instance_id >= c_start_inst_id
10687     AND cii.instance_id <= c_end_inst_id;
10688 
10689   -- get instances when no mr_header_id.
10690   CURSOR get_all_inst( c_start_inst_id IN NUMBER,
10691                        c_end_inst_id   IN NUMBER)
10692   IS
10693   SELECT cii.instance_id
10694    FROM  csi_item_instances cii, ahl_mr_effectivities mre, mtl_system_items_b msi,
10695          (select mr_header_id
10696           from ahl_mr_headers_app_v
10697           where type_code = 'PROGRAM') mr
10698    WHERE cii.inventory_item_id = msi.inventory_item_id
10699      AND cii.inv_master_organization_id = msi.organization_id
10700      AND cii.inventory_item_id = mre.inventory_item_id
10701      AND mre.mr_header_id = mr.mr_header_id
10702      AND SYSDATE between trunc(nvl(cii.active_start_date,sysdate)) and
10703          trunc(nvl(cii.active_end_date,sysdate+1))
10704      AND cii.instance_id >= c_start_inst_id
10705      AND cii.instance_id <= c_end_inst_id;
10706 
10707   l_msg_count  NUMBER;
10708   l_msg_data   VARCHAR2(3000);
10709   l_return_status VARCHAR2(1);
10710 
10711   -- added for performance fix 6511501.
10712   TYPE nbr_tbl_type IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
10713   l_csi_inst_tbl  nbr_tbl_type;
10714 
10715 BEGIN
10716 
10717     IF G_DEBUG = 'Y' THEN
10718       fnd_file.put_line(FND_FILE.LOG,'MR Header ID = '||p_mr_header_id);
10719       fnd_file.put_line(FND_FILE.LOG,'CSI Start Instance = '||p_start_instance_id);
10720       fnd_file.put_line(FND_FILE.LOG,'CSI End Instance = '||p_end_instance_id);
10721       fnd_file.put_line(FND_FILE.LOG,'Start Time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
10722       fnd_file.new_line(FND_FILE.LOG,1);
10723     END IF;
10724 
10725     -- initialize return status.
10726     retcode := 0;
10727     IF (p_mr_header_id IS NOT NULL) THEN
10728       OPEN get_inst(p_mr_header_id, p_start_instance_id, p_end_instance_id);
10729     ELSE
10730       OPEN get_all_inst(p_start_instance_id, p_end_instance_id);
10731     END IF;
10732 
10733 
10734     LOOP
10735       IF (p_mr_header_id IS NOT NULL) THEN
10736         FETCH get_inst BULK COLLECT INTO l_csi_inst_tbl LIMIT 1000;
10737       ELSE
10738         FETCH get_all_inst BULK COLLECT INTO l_csi_inst_tbl LIMIT 1000;
10739       END IF;
10740 
10741       IF (l_csi_inst_tbl.count > 0) THEN
10742         -- call process unit for all instances.
10743         --FOR inst_rec IN get_inst(p_mr_header_id, p_start_instance_id, p_end_instance_id) LOOP
10744         FOR i IN l_csi_inst_tbl.FIRST..l_csi_inst_tbl.LAST  LOOP
10745            -- Call Process Unit for the item instance.
10746            Process_Unit (
10747                          p_commit               => FND_API.G_TRUE,
10748                          p_init_msg_list        => FND_API.G_TRUE,
10749                          x_msg_count            => l_msg_count,
10750                          x_msg_data             => l_msg_data,
10751                          x_return_status        => l_return_status,
10752                          p_csi_item_instance_id => l_csi_inst_tbl(i),
10753                                                    --inst_rec.instance_id,
10754                          p_concurrent_flag      => 'Y');
10755 
10756            l_msg_count := FND_MSG_PUB.Count_Msg;
10757            IF (l_return_status <> FND_API.G_RET_STS_SUCCESS)
10758            THEN
10759                retcode := 2;  -- error based only on return status
10760            ELSIF (l_msg_count > 0 AND l_return_status = FND_API.G_RET_STS_SUCCESS)
10761            THEN
10762                retcode := 1;  -- warning based on return status + msg count
10763            END IF;
10764 
10765         END LOOP; -- l_csi_inst_tbl.FIRST
10766       END IF; -- l_csi_inst_tbl.count
10767 
10768       IF (p_mr_header_id IS NOT NULL) THEN
10769         EXIT WHEN get_inst%NOTFOUND;
10770       ELSE
10771         EXIT WHEN get_all_inst%NOTFOUND;
10772       END IF;
10773 
10774     END LOOP; -- get_inst.
10775     IF (p_mr_header_id IS NOT NULL) THEN
10776       CLOSE get_inst;
10777     ELSE
10778       CLOSE get_all_inst;
10779     END IF;
10780 
10781     IF G_DEBUG = 'Y' THEN
10782       fnd_file.new_line(FND_FILE.LOG,1);
10783       fnd_file.put_line(FND_FILE.LOG,'End Time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
10784     END IF;
10785 
10786 --
10787 EXCEPTION
10788  WHEN OTHERS THEN
10789    retcode := 2;
10790    errbuf := 'Process_Unit_Range:PM:OTHERS:' || substrb(sqlerrm,1,60);
10791 
10792 END Process_Unit_Range;
10793 
10794 ----------------------------------------------
10795 -- Added for performance bug# 6893404.
10796 PROCEDURE Split_Process_All_Instances(p_concurrent_flag  IN  VARCHAR2,
10797                                       p_commit_flag      IN  VARCHAR2,
10798                                       p_num_of_workers   IN  NUMBER,
10799                                       p_mr_header_id     IN  NUMBER,
10800                                       p_mtl_category_id  IN  NUMBER,
10801                                       p_process_option   IN  VARCHAR2,
10802                                       x_msg_count        OUT NOCOPY  NUMBER,
10803                                       x_msg_data         OUT NOCOPY  NUMBER,
10804                                       x_return_status    OUT NOCOPY  VARCHAR2)
10805 IS
10806 
10807   l_req_id        number;
10808   l_conc_req_id   number;
10809   l_instance_id   number;
10810 
10811   l_num_of_workers number;
10812 
10813   dml_errors EXCEPTION;
10814   PRAGMA EXCEPTION_INIT(dml_errors, -24381);
10815 
10816 BEGIN
10817 
10818   IF G_debug = 'Y' THEN
10819      AHL_DEBUG_PUB.debug('Start Split_Process_All_Instances:p_concurrent_flag:' || p_concurrent_flag);
10820      AHL_DEBUG_PUB.debug('Input MR Header ID:' || p_mr_header_id);
10821      AHL_DEBUG_PUB.debug('Input p_num_of_workers:' || p_num_of_workers);
10822   END IF;
10823 
10824   -- initialize return status.
10825   x_return_status := FND_API.G_RET_STS_SUCCESS;
10826 
10827   IF (p_concurrent_flag = 'Y') THEN
10828     l_conc_req_id := fnd_global.conc_request_id;
10829   ELSE
10830     l_conc_req_id := fnd_global.session_id;
10831   END IF;
10832 
10833   -- validate p_num_of_workers.
10834   l_num_of_workers := trunc(p_num_of_workers);
10835 
10836   IF (l_num_of_workers IS NULL OR l_num_of_workers <= 0) THEN
10837     l_num_of_workers := 1;
10838   ELSIF l_num_of_workers > 30 THEN
10839     l_num_of_workers := 30;
10840   END IF;
10841 
10842   Populate_BUE_Worker(p_conc_request_id => l_conc_req_id,
10843                       p_concurrent_flag => p_concurrent_flag,
10844                       p_mtl_category_id => p_mtl_category_id,
10845                       p_process_option  => p_process_option,
10846                       errbuf            => x_msg_data,
10847                       x_return_status   => x_return_status);
10848 
10849   IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
10850     RETURN;
10851   END IF;
10852 
10853   -- launch worker programs.
10854   IF (p_concurrent_flag = 'Y') THEN
10855       -- submit worker programs to process units.
10856       FOR i IN 1..l_num_of_workers LOOP
10857          l_req_id := fnd_request.submit_request('AHL','AHLWUEFF',NULL,NULL,FALSE, l_conc_req_id);
10858          IF (l_req_id = 0 OR l_req_id IS NULL) THEN
10859             IF G_debug = 'Y' THEN
10860                AHL_DEBUG_PUB.debug('Tried to submit concurrent request but failed');
10861             END IF;
10862             fnd_file.put_line(FND_FILE.LOG, 'Failed submit concurrent request');
10863             fnd_file.new_line(FND_FILE.LOG,1);
10864             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
10865 
10866          ELSE
10867             fnd_file.put_line(FND_FILE.LOG, 'Concurrent request ID:' || l_req_id );
10868             IF G_debug = 'Y' THEN
10869                AHL_DEBUG_PUB.debug('Concurrent request ID:' || l_req_id );
10870             END IF;
10871          END IF; -- l_req_id = 0 OR ..
10872 
10873       END LOOP;
10874 
10875       -- call cleanup BUE for previously failed deletes.
10876      Cleanup_BUE_Worker(p_parent_conc_request_id => l_conc_req_id,
10877                         p_child_conc_request_id  => NULL);
10878   ELSE
10879 
10880      LOOP
10881         -- initialize return status.
10882         x_return_status := FND_API.G_RET_STS_SUCCESS;
10883 
10884         Get_Next_BUE_Row(p_parent_conc_pgm_id  => l_conc_req_id,
10885                          p_conc_child_req_id   => l_conc_req_id,
10886                          x_return_status       => x_return_status,
10887                          errbuf                => x_msg_data,
10888                          x_item_instance_id    => l_instance_id);
10889 
10890         IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
10891            EXIT;
10892         END IF;
10893 
10894         EXIT WHEN (l_instance_id IS NULL);
10895 
10896         IF G_DEBUG = 'Y' THEN
10897            AHL_DEBUG_PUB.debug('Now processing..:' || l_instance_id);
10898         END IF;
10899 
10900         -- Call Process Unit for the item instance.
10901         Process_Unit (
10902                 p_commit               => p_commit_flag,
10903                 p_init_msg_list        => FND_API.G_TRUE,
10904                 x_msg_count            => x_msg_count,
10905                 x_msg_data             => x_msg_data,
10906                 x_return_status        => x_return_status,
10907                 p_csi_item_instance_id => l_instance_id,
10908                 p_concurrent_flag      => p_concurrent_flag);
10909 
10910         IF ( x_return_status <> FND_API.G_RET_STS_SUCCESS) AND (p_commit_flag = FND_API.G_FALSE) THEN
10911           EXIT;
10912         END IF;
10913 
10914      END LOOP;
10915 
10916      -- cleanup worker table after processing.
10917      Cleanup_BUE_Worker(p_parent_conc_request_id => l_conc_req_id,
10918                         p_child_conc_request_id  => l_conc_req_id);
10919 
10920   END IF;
10921 
10922   IF G_debug = 'Y' THEN
10923      AHL_DEBUG_PUB.debug('End Split_Process_All_Instances:Return Status:' || x_return_status);
10924   END IF;
10925 
10926 END Split_Process_All_Instances;
10927 
10928 ----------------------------------------------
10929 -- BUE Worker program for AHL processing.
10930 -- Called from BUE concurrent pgm when all units option is chosen..
10931 -- or when BUE is run for an MR or MR revision.
10932 PROCEDURE Process_Unit_Range (errbuf                 OUT NOCOPY  VARCHAR2,
10933                               retcode                OUT NOCOPY  NUMBER,
10934                               p_parent_conc_pgm_id   IN NUMBER)
10935 IS
10936   l_instance_id     NUMBER;
10937   l_conc_child_req_id NUMBER;
10938 
10939   l_msg_count  NUMBER;
10940   l_msg_data   VARCHAR2(3000);
10941   l_return_status VARCHAR2(1);
10942 
10943 BEGIN
10944 
10945   fnd_file.put_line(FND_FILE.LOG,'Start time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
10946 
10947   G_DEBUG_LINE_NUM := 1;
10948 
10949   -- initialize return status.
10950   retcode := 0;
10951 
10952   l_conc_child_req_id := fnd_global.conc_request_id;
10953 
10954   IF G_debug = 'Y' THEN
10955      AHL_DEBUG_PUB.debug('Start Process_Unit_Range for concurrent pgm ID:' || l_conc_child_req_id);
10956      AHL_DEBUG_PUB.debug('Parent concurrent pgm ID:' || p_parent_conc_pgm_id);
10957   END IF;
10958 
10959   -- AHL processing.
10960   LOOP
10961     -- initialize return status.
10962     l_return_status := FND_API.G_RET_STS_SUCCESS;
10963 
10964     G_DEBUG_LINE_NUM := 10;
10965 
10966     -- get next unit to process.
10967     Get_Next_BUE_Row(p_parent_conc_pgm_id  => p_parent_conc_pgm_id,
10968                      p_conc_child_req_id   => l_conc_child_req_id,
10969                      x_return_status       => l_return_status,
10970                      errbuf                => errbuf,
10971                      x_item_instance_id    => l_instance_id);
10972 
10973     IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
10974        EXIT;
10975     END IF;
10976 
10977     EXIT WHEN (l_instance_id IS NULL);
10978 
10979     fnd_file.new_line(FND_FILE.LOG,1);
10980     fnd_file.put_line(FND_FILE.LOG,'Now processing..:' || l_instance_id);
10981     fnd_file.put_line(FND_FILE.LOG,'Start time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
10982 
10983     G_DEBUG_LINE_NUM := 20;
10984 
10985     -- Call Process Unit for the item instance.
10986     Process_Unit (
10987            p_commit               => FND_API.G_TRUE,
10988            p_init_msg_list        => FND_API.G_TRUE,
10989            x_msg_count            => l_msg_count,
10990            x_msg_data             => l_msg_data,
10991            x_return_status        => l_return_status,
10992            p_csi_item_instance_id => l_instance_id,
10993            p_concurrent_flag      => 'Y');
10994 
10995     fnd_file.put_line(FND_FILE.LOG,'End time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
10996 
10997     l_msg_count := FND_MSG_PUB.Count_Msg;
10998     IF (retcode <> 2 AND l_return_status <> FND_API.G_RET_STS_SUCCESS)
10999     THEN
11000        retcode := 2;  -- error based only on return status
11001     ELSIF (retcode = 0 AND l_msg_count > 0 AND l_return_status = FND_API.G_RET_STS_SUCCESS)
11002     THEN
11003        retcode := 1;  -- warning based on return status + msg count
11004     END IF;
11005 
11006   END LOOP;
11007 
11008   G_DEBUG_LINE_NUM := 30;
11009 
11010   -- cleanup worker table after processing.
11011   Cleanup_BUE_Worker(p_parent_conc_request_id => p_parent_conc_pgm_id,
11012                      p_child_conc_request_id  => l_conc_child_req_id);
11013 
11014 
11015   IF G_debug = 'Y' THEN
11016      AHL_DEBUG_PUB.debug('Concurrent pgm retcode:' || retcode);
11017      AHL_DEBUG_PUB.debug('Concurrent pgm l_return_status:' || l_return_status);
11018      AHL_DEBUG_PUB.debug('End Process_Unit_Range for concurrent pgm ID:' || l_conc_child_req_id);
11019   END IF;
11020 
11021 --
11022 EXCEPTION
11023  WHEN FND_API.G_EXC_ERROR THEN
11024    retcode := 2;
11025    errbuf := 'Process_Unit_Range:EXC:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
11026 
11027  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
11028    retcode := 2;
11029    errbuf := 'Process_Unit_Range:UNEXP:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
11030 
11031  WHEN OTHERS THEN
11032    IF (SQLCODE = -54) THEN
11033      retcode := 1;
11034      errbuf := 'Process_Unit_Range:54:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
11035    ELSIF (SQLCODE = -6519) THEN
11036      retcode := 1;
11037      errbuf := 'Process_Unit_Range:6519:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
11038    ELSE
11039      retcode := 2;
11040      errbuf := 'Process_Unit_Range:OTH:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
11041    END IF;
11042 
11043 END Process_Unit_Range;
11044 ------------------------
11045 -- BUE Worker program for AHL processing.
11046 -- This procedure is called after a MR is revised.
11047 PROCEDURE Process_Unit_Range (errbuf                 OUT NOCOPY  VARCHAR2,
11048                               retcode                OUT NOCOPY  NUMBER,
11049                               p_old_mr_header_id     IN          NUMBER,
11050                               p_new_mr_header_id     IN          NUMBER)
11051 
11052 IS
11053 
11054   l_return_status      varchar2(1);
11055   l_msg_count          number;
11056   l_msg_data           varchar2(2000);
11057 
11058 BEGIN
11059 
11060     fnd_file.put_line(FND_FILE.LOG,'Start time:' || to_char(sysdate, 'Month DD, YYYY HH24:MI:SS'));
11061 
11062     IF G_debug = 'Y' THEN
11063        AHL_DEBUG_PUB.debug('Start Process_Unit_Range for MR: Old ID:New ID:' || p_old_mr_header_id || ':' || p_new_mr_header_id);
11064     END IF;
11065 
11066     -- initialize return status.
11067     retcode := 0;
11068 
11069     -- After commit call UMP BUE api to build UEs.
11070     AHL_UMP_PROCESSUNIT_PVT.Process_MRAffected_Units (
11071            p_commit          => FND_API.G_TRUE,
11072            x_msg_count       => l_msg_count,
11073            x_msg_data        => l_msg_data,
11074            x_return_status   => l_return_status, -- ignore status returned by this api.
11075            p_old_mr_header_id  => p_old_mr_header_id,
11076            p_mr_header_id      => p_new_mr_header_id,
11077            p_concurrent_flag   => 'Y',
11078            p_num_of_workers    => 5);
11079 
11080     l_msg_count := FND_MSG_PUB.Count_Msg;
11081     IF (l_return_status <> FND_API.G_RET_STS_SUCCESS)
11082     THEN
11083        retcode := 2;  -- error based only on return status
11084        log_error_messages;
11085     ELSIF (l_msg_count > 0 AND l_return_status = FND_API.G_RET_STS_SUCCESS)
11086     THEN
11087        retcode := 1;  -- warning based on return status + msg count
11088        log_error_messages;
11089     END IF;
11090 
11091     IF G_debug = 'Y' THEN
11092        AHL_DEBUG_PUB.debug('End Process_Unit_Range for MR: retcode:' || retcode);
11093     END IF;
11094 
11095 --
11096 EXCEPTION
11097  WHEN FND_API.G_EXC_ERROR THEN
11098    retcode := 2;
11099    errbuf := 'Process_Unit_Range:MR:EXC:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
11100 
11101  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
11102    retcode := 2;
11103    errbuf := 'Process_Unit_Range:MR:UNEXP:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,60);
11104 
11105  WHEN OTHERS THEN
11106    IF (SQLCODE = -54) THEN
11107      retcode := 1;
11108      errbuf := 'Process_Unit_Range:54:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,70);
11109    ELSIF (SQLCODE = -6519) THEN
11110      retcode := 1;
11111      errbuf := 'Process_Unit_Range:6519:' || G_DEBUG_LINE_NUM || ':' || substrb(sqlerrm,1,70);
11112    ELSE
11113      retcode := 2;
11114      errbuf := 'Process_Unit_Range:MR:OTH:' || substrb(sqlerrm,1,60);
11115    END IF;
11116 
11117 END Process_Unit_Range;
11118 
11119 ------------------------
11120 -- Added for performance bug# 6893404.
11121 PROCEDURE Populate_BUE_Worker(p_conc_request_id IN  NUMBER,
11122                               p_concurrent_flag IN  VARCHAR2,
11123                               p_mtl_category_id IN  NUMBER,
11124                               p_process_option  IN  VARCHAR2,
11125                               errbuf            OUT NOCOPY VARCHAR2,
11126                               x_return_status   OUT NOCOPY VARCHAR2)
11127 IS
11128   PRAGMA AUTONOMOUS_TRANSACTION;
11129 
11130   l_instance_id_tbl   nbr_tbl_type;
11131   l_unit_name_tbl     vchar_tbl_type;
11132 
11133   -- get all valid uc headers
11134   CURSOR ahl_unit_config_header_csr IS
11135     SELECT csi_item_instance_id
11136     FROM  ahl_unit_config_headers
11137     WHERE trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11138       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11139       AND unit_config_status_code <> 'DRAFT'
11140       AND parent_uc_header_id IS NULL;
11141 
11142   -- get all valid uc headers that match item category.
11143   CURSOR ahl_unit_itemcat_csr(p_mtl_category_id IN NUMBER) IS
11144     SELECT csi_item_instance_id
11145     FROM  ahl_unit_config_headers uc
11146     WHERE trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11147       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11148       AND unit_config_status_code <> 'DRAFT'
11149       AND parent_uc_header_id IS NULL
11150       AND exists (select 'x'
11151                   from mtl_category_set_valid_cats cs, mtl_item_categories itc,
11152                        csi_item_instances cii2
11153                   where cs.category_set_id = fnd_profile.value('AHL_BUE_ITEM_CATEGORY_SET')
11154                     AND cs.category_set_id = itc.category_set_id
11155                     AND cs.category_id = itc.category_id
11156                     AND itc.category_id = p_mtl_category_id
11157                     AND cii2.instance_id = uc.csi_item_instance_id
11158                     AND itc.organization_id = cii2.inv_master_organization_id
11159                     AND itc.inventory_item_id = cii2.inventory_item_id
11160                   ); -- get units matching item category.
11161 
11162 
11163   -- get item instances matching inventory item id.
11164   -- when no item category and process option = 'Units or Components' or all
11165   CURSOR get_uc_item_inst_csr(p_opt_uc IN NUMBER) IS
11166     SELECT instance_id from
11167      (SELECT DISTINCT nvl(root_instance_id, instance_id) instance_id from
11168        (
11169         SELECT cii.instance_id,
11170               (select object_id from csi_ii_relationships parent
11171                where not exists (select 'x' from csi_ii_relationships
11172                                  where subject_id = parent.object_id and
11173                                  relationship_type_code = 'COMPONENT-OF' and
11174                                  trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) and
11175                                  trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
11176                start with parent.subject_id = cii.instance_id and
11177                parent.relationship_type_code = 'COMPONENT-OF' and
11178                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11179                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11180                connect by prior parent.object_id = parent.subject_id and
11181                parent.relationship_type_code = 'COMPONENT-OF' and
11182                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11183                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11184                ) Root_instance_id
11185 
11186         FROM csi_item_instances cii, ahl_mr_effectivities mre
11187         WHERE mre.inventory_item_id = nvl(null, mre.inventory_item_id)
11188           AND mre.mr_header_id = nvl(null,mre.mr_header_id)
11189           -- added nvl conditions above as this seems to force use of index on
11190           -- ahl_mr_headers_b and also brings query cost down.
11191           AND mre.relationship_id is null
11192           AND mre.inventory_item_id = cii.inventory_item_id
11193           AND exists (SELECT 'x' from ahl_mr_headers_app_v MR
11194                        WHERE MR.mr_header_id = mre.mr_header_id
11195                          AND MR.program_type_code NOT IN ('MO_PROC')
11196                          AND MR.version_number in (SELECT max(MRM.version_number)
11197                                                    FROM ahl_mr_headers_app_v MRM
11198                                                    WHERE mrm.title = mr.title
11199                                                      AND SYSDATE between trunc(MR.effective_from)
11200                                                      AND trunc(nvl(MR.effective_to,SYSDATE+1))
11201                                                      AND mr_status_code='COMPLETE'
11202                                                   )
11203                      )
11204           AND trunc(nvl(cii.active_start_date, sysdate)) <= trunc(sysdate)
11205           AND trunc(sysdate) < trunc(nvl(cii.active_end_date, sysdate+1))
11206        )
11207      ) valid_inst
11208     WHERE /*(p_opt_uc = 1 AND exists (select 'x' from ahl_unit_config_headers
11209                                     where csi_item_instance_id = valid_inst.instance_id
11210                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11211                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11212                                       AND unit_config_status_code <> 'DRAFT'
11213                                       AND parent_uc_header_id IS NULL
11214                                    ) -- get UCs only.
11215           )
11216           OR */  -- this cursor is not used when p_opt_uc = 1
11217           -- get components.
11218           (p_opt_uc = 2 AND not exists (select 'x' from ahl_unit_config_headers
11219                                         where csi_item_instance_id = valid_inst.instance_id
11220                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11221                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11222                                           -- instance is a UC if in status draft.
11223                                           --AND unit_config_status_code <> 'DRAFT'
11224                                           --AND parent_uc_header_id IS NULL
11225                                        )
11226           )
11227           OR
11228           -- get all but ignore UCs as they have alredy been selected.
11229           (p_opt_uc = 0 AND not exists (select 'x' from ahl_unit_config_headers
11230                                         where csi_item_instance_id = valid_inst.instance_id
11231                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11232                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11233                                           -- instance is a UC if in status draft.
11234                                           --AND unit_config_status_code <> 'DRAFT'
11235                                           --AND parent_uc_header_id IS NULL
11236                                        )
11237           );
11238 
11239   -- get item instances matching inventory item id, item cat and is a UC.
11240   -- when item category selected with process option of ALL, Units or Components.
11241   CURSOR get_uc_itemcat_inst_csr (p_mtl_category_id IN NUMBER,
11242                                   p_opt_uc          IN NUMBER) IS
11243     SELECT instance_id from
11244      (SELECT DISTINCT nvl(root_instance_id, instance_id) instance_id from
11245        (
11246         SELECT cii.instance_id,
11247               (select object_id from csi_ii_relationships parent
11248                where not exists (select 'x' from csi_ii_relationships
11249                                  where subject_id = parent.object_id and
11250                                  relationship_type_code = 'COMPONENT-OF' and
11251                                  trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) and
11252                                  trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
11253                start with parent.subject_id = cii.instance_id and
11254                parent.relationship_type_code = 'COMPONENT-OF' and
11255                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11256                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11257                connect by prior parent.object_id = parent.subject_id and
11258                parent.relationship_type_code = 'COMPONENT-OF' and
11259                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11260                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11261                ) Root_instance_id
11262 
11263         FROM csi_item_instances cii,
11264              (select distinct me.inventory_item_id
11265               from ahl_mr_headers_app_v mr, ahl_mr_effectivities me
11266               where mr.mr_header_id = me.mr_header_id AND
11267                     mr.mr_status_code = 'COMPLETE' AND
11268                     MR.program_type_code NOT IN ('MO_PROC') AND -- added in R12
11269                     trunc(effective_from) <= trunc(sysdate) AND
11270                     trunc(nvl(effective_to,sysdate)) >= trunc(sysdate)
11271                     and me.inventory_item_id is not null
11272              ) mre
11273         WHERE trunc(nvl(cii.active_start_date, sysdate)) <= trunc(sysdate) AND
11274               trunc(sysdate) < trunc(nvl(cii.active_end_date, sysdate+1))
11275           AND mre.inventory_item_id = cii.inventory_item_id
11276        )
11277      ) valid_inst
11278     WHERE exists (select 'x'
11279                   from mtl_category_set_valid_cats cs, mtl_item_categories itc,
11280                        csi_item_instances cii2
11281                   where cs.category_set_id = fnd_profile.value('AHL_BUE_ITEM_CATEGORY_SET')
11282                     AND cs.category_set_id = itc.category_set_id
11283                     AND cs.category_id = itc.category_id
11284                     AND itc.category_id = p_mtl_category_id
11285                     AND cii2.instance_id = valid_inst.instance_id
11286                     AND itc.organization_id = cii2.inv_master_organization_id
11287                     AND itc.inventory_item_id = cii2.inventory_item_id
11288                   ) -- get root nodes matching item category.
11289 
11290       AND ((p_opt_uc = 1 AND exists (select 'x' from ahl_unit_config_headers
11291                                     where csi_item_instance_id = valid_inst.instance_id
11292                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11293                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11294                                       AND unit_config_status_code <> 'DRAFT'
11295                                       AND parent_uc_header_id IS NULL
11296                                    ) -- get UCs only.
11297           )
11298           OR
11299           -- get components.
11300           (p_opt_uc = 2 AND not exists (select 'x' from ahl_unit_config_headers
11301                                         where csi_item_instance_id = valid_inst.instance_id
11302                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11303                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11304                                           -- instance is a UC if in status draft.
11305                                           --AND unit_config_status_code <> 'DRAFT'
11306                                           --AND parent_uc_header_id IS NULL
11307                                        )
11308           )
11309           OR
11310           -- when process option is ALL.
11311           -- get components in this case too as UC's have already been selected.
11312           (p_opt_uc = 0 AND not exists (select 'x' from ahl_unit_config_headers
11313                                         where csi_item_instance_id = valid_inst.instance_id
11314                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11315                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11316                                           -- instance is a UC if in status draft.
11317                                           --AND unit_config_status_code <> 'DRAFT'
11318                                           --AND parent_uc_header_id IS NULL
11319                                        )
11320           )
11321           );
11322 
11323   l_buffer_limit  number := 5000;
11324   l_opt_uc        number;
11325 
11326   dml_errors EXCEPTION;
11327   PRAGMA EXCEPTION_INIT(dml_errors, -24381);
11328 
11329 BEGIN
11330 
11331   IF G_debug = 'Y' THEN
11332      AHL_DEBUG_PUB.debug('Start Populate_BUE_Worker for pgm ID:' || p_conc_request_id);
11333      AHL_DEBUG_PUB.debug('Concurrent flag:' || p_concurrent_flag);
11334   END IF;
11335 
11336   -- initialize return status.
11337   x_return_status := FND_API.G_RET_STS_SUCCESS;
11338 
11339   IF (p_process_option = 'AHL_BUE_ALL_COMPONENTS') THEN
11340      l_opt_uc := 2;
11341   ELSIF (p_process_option = 'AHL_BUE_ALL_UNITS') THEN
11342      l_opt_uc := 1;
11343   ELSE
11344      l_opt_uc := 0; -- when opt is null or AHL_BUE_ALL
11345   END IF;
11346 
11347   -- get all unit configurations.
11348   IF (l_opt_uc IN (0,1)) THEN
11349 
11350       IF (p_mtl_category_id IS NULL) THEN
11351         OPEN ahl_unit_config_header_csr;
11352       ELSE
11353         OPEN ahl_unit_itemcat_csr(p_mtl_category_id);
11354       END IF;
11355 
11356       LOOP
11357         IF (p_mtl_category_id IS NULL) THEN
11358           FETCH ahl_unit_config_header_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
11359         ELSE
11360           FETCH ahl_unit_itemcat_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
11361         END IF;
11362 
11363         EXIT WHEN (l_instance_id_tbl.count = 0);
11364 
11365         -- insert into BUE table.
11366         FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST
11367           INSERT INTO AHL_BUE_WORKER_DATA
11368           (parent_conc_request_id,
11369            csi_item_instance_id,
11370            child_conc_request_id,
11371            last_update_date,
11372            last_updated_by,
11373            creation_date,
11374            created_by,
11375            last_update_login,
11376            object_version_number) VALUES
11377            (p_conc_request_id,
11378             l_instance_id_tbl(instance_indx),
11379             null,
11380             sysdate,
11381             fnd_global.user_id,
11382             sysdate,
11383             fnd_global.user_id,
11384             fnd_global.conc_login_id,
11385             1);
11386 
11387         l_instance_id_tbl.DELETE;
11388 
11389       END LOOP;
11390 
11391       IF (p_mtl_category_id IS NULL) THEN
11392          CLOSE ahl_unit_config_header_csr;
11393       ELSE
11394          CLOSE ahl_unit_itemcat_csr;
11395       END IF;
11396 
11397   END IF; -- (l_opt_uc IN (0,1))
11398 
11399   IF (l_opt_uc <> 1) THEN -- skip when only processing units.
11400     -- now process instances based on inventory_item_id.
11401     IF (p_mtl_category_id IS NULL) THEN
11402         OPEN get_uc_item_inst_csr(l_opt_uc);
11403     ELSE
11404         OPEN get_uc_itemcat_inst_csr(p_mtl_category_id, l_opt_uc);
11405     END IF;
11406 
11407     LOOP
11408       IF (p_mtl_category_id IS NULL) THEN
11409           FETCH get_uc_item_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
11410       ELSE
11411           FETCH get_uc_itemcat_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
11412       END IF;
11413 
11414       EXIT WHEN (l_instance_id_tbl.count = 0);
11415 
11416       BEGIN
11417         -- insert into BUE table.
11418         FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST SAVE EXCEPTIONS
11419           INSERT INTO AHL_BUE_WORKER_DATA
11420           (parent_conc_request_id,
11421            csi_item_instance_id,
11422            child_conc_request_id,
11423            last_update_date,
11424            last_updated_by,
11425            creation_date,
11426            created_by,
11427            last_update_login,
11428            object_version_number) VALUES
11429            (p_conc_request_id,
11430             l_instance_id_tbl(instance_indx),
11431             null,
11432             sysdate,
11433             fnd_global.user_id,
11434             sysdate,
11435             fnd_global.user_id,
11436             fnd_global.conc_login_id,
11437             1);
11438 
11439         EXCEPTION
11440           WHEN DML_ERRORS THEN
11441             IF (get_uc_item_inst_csr%ISOPEN) THEN
11442               CLOSE get_uc_item_inst_csr;
11443             END IF;
11444             IF (get_uc_itemcat_inst_csr%ISOPEN) THEN
11445               CLOSE get_uc_itemcat_inst_csr;
11446             END IF;
11447 
11448             x_return_status := 'E';
11449 
11450             IF (p_concurrent_flag = 'Y') THEN
11451               fnd_file.put_line(fnd_file.log, 'Following error(s) occured while inserting into table ahl_bue_worker_data');
11452               FOR j IN 1..sql%bulk_exceptions.count
11453               LOOP
11454                 fnd_file.put_line(fnd_file.log, sql%bulk_exceptions(j).error_index || ', ' ||
11455                 sqlerrm(-sql%bulk_exceptions(j).error_code) );
11456               END LOOP;
11457             END IF;
11458 
11459             FND_MESSAGE.set_name('AHL', 'AHL_UMP_BUE_WORKER_ERR');
11460             FND_MSG_PUB.add;
11461             errbuf := FND_MSG_PUB.Get;
11462 
11463             RETURN;
11464       END;
11465 
11466       l_instance_id_tbl.DELETE;
11467 
11468     END LOOP;
11469 
11470     IF (p_mtl_category_id IS NULL) THEN
11471        CLOSE get_uc_item_inst_csr;
11472     ELSE
11473        CLOSE get_uc_itemcat_inst_csr;
11474     END IF;
11475   END IF; -- l_opt_uc
11476 
11477   -- delete duplicate rows.
11478   DELETE FROM ahl_bue_worker_data
11479   WHERE parent_conc_request_id = p_conc_request_id
11480     AND rowid not in (SELECT MIN(rowid)
11481                       FROM ahl_bue_worker_data
11482                       WHERE parent_conc_request_id = p_conc_request_id
11483                       GROUP BY csi_item_instance_id, parent_conc_request_id) ;
11484 
11485   -- save changes.
11486   COMMIT WORK;
11487 
11488   IF G_debug = 'Y' THEN
11489      AHL_DEBUG_PUB.debug('Concurrent pgm x_return_status:' || x_return_status);
11490      AHL_DEBUG_PUB.debug('End Populate_BUE_Worker for pgm ID:' || p_conc_request_id);
11491   END IF;
11492 
11493 END Populate_BUE_Worker;
11494 
11495 -- Added for performance bug# 6893404.
11496 PROCEDURE Get_Next_BUE_Row(p_parent_conc_pgm_id    IN  NUMBER,
11497                            p_conc_child_req_id     IN  NUMBER,
11498                            x_return_status         OUT NOCOPY VARCHAR2,
11499                            errbuf                  OUT NOCOPY VARCHAR2,
11500                            x_item_instance_id      OUT NOCOPY NUMBER)
11501 IS
11502 
11503   PRAGMA AUTONOMOUS_TRANSACTION;
11504 
11505   CURSOR ahl_bue_worker_csr (p_parent_conc_pgm_id IN NUMBER)
11506   IS
11507     SELECT rowid, csi_item_instance_id, object_version_number
11508     FROM ahl_bue_worker_data
11509     WHERE parent_conc_request_id = p_parent_conc_pgm_id
11510       AND child_conc_request_id IS NULL;
11511     --FOR UPDATE OF child_conc_request_id;
11512 
11513  CURSOR bue_lock_row (p_rowid IN urowid, p_parent_conc_pgm_id IN NUMBER )
11514   IS
11515     SELECT rowid, csi_item_instance_id
11516     FROM ahl_bue_worker_data
11517     WHERE parent_conc_request_id = p_parent_conc_pgm_id
11518       AND child_conc_request_id IS NULL
11519       AND ROWID = p_rowid
11520     FOR UPDATE OF child_conc_request_id NOWAIT;
11521 
11522   l_instance_id  NUMBER;
11523 
11524   record_locked   EXCEPTION;
11525   pragma exception_init (record_locked, -54);
11526 
11527   l_status        NUMBER;
11528   l_rowid         UROWID;
11529   l_object_version_number  NUMBER;
11530 
11531 BEGIN
11532   IF G_debug = 'Y' THEN
11533      AHL_DEBUG_PUB.debug('Start Get_Next_BUE_Row: Parent Conc Request ID:' || p_parent_conc_pgm_id);
11534      AHL_DEBUG_PUB.debug('Child Conc Request ID:' || p_conc_child_req_id);
11535   END IF;
11536 
11537   --DBMS_LOCK.SLEEP(60);
11538 
11539   -- get next unprocessed row.
11540   OPEN ahl_bue_worker_csr(p_parent_conc_pgm_id);
11541   LOOP
11542      l_status := 0;
11543      BEGIN
11544         FETCH ahl_bue_worker_csr INTO l_rowid, l_instance_id, l_object_version_number;
11545         IF (ahl_bue_worker_csr%FOUND) THEN
11546             -- lock row
11547             OPEN bue_lock_row(l_rowid, p_parent_conc_pgm_id);
11548             FETCH bue_lock_row into l_rowid, l_instance_id;
11549             IF (bue_lock_row%FOUND) THEN
11550               -- update only if ovn remains the same.
11551               UPDATE ahl_bue_worker_data
11552               set child_conc_request_id = p_conc_child_req_id,
11553               last_update_date = sysdate,
11554               object_version_number = object_version_number + 1,
11555               last_update_login = fnd_global.login_id,
11556               last_updated_by = fnd_global.user_id
11557               WHERE ROWID = l_rowid
11558                 AND object_version_number = l_object_version_number;
11559                 --WHERE CURRENT OF ahl_bue_worker_csr;
11560 
11561               COMMIT WORK;
11562             ELSE
11563               l_status := 100;
11564               ROLLBACK;
11565             END IF;
11566             CLOSE bue_lock_row;
11567 
11568         ELSE
11569             l_instance_id := NULL;
11570             ROLLBACK;
11571         END IF;
11572       EXCEPTION
11573         WHEN record_locked THEN
11574           -- select next row.
11575           l_status := -54;
11576           ROLLBACK;
11577           IF (bue_lock_row%ISOPEN) THEN
11578              CLOSE bue_lock_row;
11579           END IF;
11580 
11581         WHEN NO_DATA_FOUND THEN
11582           -- select next row.
11583           l_status := 100;
11584           ROLLBACK;
11585           IF (bue_lock_row%ISOPEN) THEN
11586              CLOSE bue_lock_row;
11587           END IF;
11588 
11589         WHEN OTHERS THEN
11590           ROLLBACK;
11591           l_status := SQLCODE;
11592           errbuf := 'Get_Next_BUE_Row:' || substrb(sqlerrm,1,60);
11593           l_instance_id := NULL;
11594           x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
11595           IF (bue_lock_row%ISOPEN) THEN
11596              CLOSE bue_lock_row;
11597           END IF;
11598      END;
11599 
11600      IF (l_status = 0) THEN
11601         -- success or end of rows.
11602         EXIT;
11603      ELSIF (l_status <> -54 AND l_status <> 100) THEN
11604         EXIT;
11605      END IF;
11606 
11607   END LOOP; -- select next row.
11608 
11609   CLOSE ahl_bue_worker_csr;
11610   x_item_instance_id := l_instance_id;
11611 
11612   IF G_debug = 'Y' THEN
11613      AHL_DEBUG_PUB.debug('End Get_Next_BUE_Row: x_item_instance_id:' || x_item_instance_id);
11614   END IF;
11615 
11616 EXCEPTION
11617   WHEN OTHERS THEN
11618     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
11619     errbuf := 'AHL_UMP_ProcessUnit_Pvt.Process.Get_Next_BUE_Row:' || SUBSTR(SQLERRM,1,240);
11620     x_item_instance_id := NULL;
11621 
11622 END Get_Next_BUE_Row;
11623 
11624 ------------------------------------------------------------------
11625 -- Added for performance bug# 6893404.
11626 -- procedure deletes the worker data after processing is complete.
11627 PROCEDURE Cleanup_BUE_Worker(p_parent_conc_request_id IN  NUMBER,
11628                              p_child_conc_request_id  IN  NUMBER)
11629 IS
11630    PRAGMA AUTONOMOUS_TRANSACTION;
11631 
11632    CURSOR get_undeleted_parents(p_conc_request_id IN NUMBER) IS
11633      SELECT DISTINCT parent_conc_request_id
11634      FROM ahl_bue_worker_data
11635      WHERE parent_conc_request_id <> p_conc_request_id;
11636 
11637    CURSOR get_undeleted_child(p_conc_request_id IN NUMBER) IS
11638      SELECT DISTINCT child_conc_request_id
11639      FROM ahl_bue_worker_data
11640      WHERE parent_conc_request_id = p_conc_request_id;
11641 
11642    CURSOR lock_child_rows(p_parent_conc_id IN NUMBER,
11643                           p_child_conc_id  IN NUMBER) IS
11644      SELECT rowid
11645      FROM ahl_bue_worker_data
11646      WHERE parent_conc_request_id = p_parent_conc_id
11647        AND child_conc_request_id = p_child_conc_id
11648        FOR UPDATE OF object_version_number NOWAIT;
11649 
11650    CURSOR fnd_concur_csr(p_conc_req_id IN NUMBER) IS
11651     SELECT 'x'
11652     FROM fnd_concurrent_requests
11653     WHERE REQUEST_ID = p_conc_req_id;
11654 
11655    record_locked   EXCEPTION;
11656    pragma exception_init (record_locked, -54);
11657 
11658    l_req_status boolean;
11659    l_rphase     varchar2(80);
11660    l_rstatus    varchar2(80);
11661    l_dphase     varchar2(30);
11662    lc_dphase    varchar2(30);
11663    l_dstatus    varchar2(30);
11664    l_message    varchar2(240);
11665 
11666    l_buffer_limit number := 100;
11667 
11668    TYPE urowid_tbl_type IS TABLE OF urowid INDEX BY BINARY_INTEGER;
11669 
11670    l_rowid_tbl  urowid_tbl_type;
11671    l_junk       VARCHAR2(1);
11672 
11673 BEGIN
11674 
11675   IF G_debug = 'Y' THEN
11676      AHL_DEBUG_PUB.debug('Start Cleanup_BUE_Worker: Parent Conc Request ID:' || p_parent_conc_request_id);
11677      AHL_DEBUG_PUB.debug('Child Conc Request ID:' || p_child_conc_request_id);
11678   END IF;
11679 
11680   IF (p_parent_conc_request_id IS NULL) THEN
11681     RETURN; -- do nothing
11682   END IF;
11683 
11684   IF (p_child_conc_request_id IS NOT NULL) THEN
11685     G_DEBUG_LINE_NUM := 300;
11686     -- cleanup rows processed by this worker.
11687     DELETE from ahl_bue_worker_data
11688     WHERE parent_conc_request_id = p_parent_conc_request_id
11689       AND child_conc_request_id = p_child_conc_request_id ;
11690     COMMIT WORK;
11691   END IF;
11692 
11693   IF (p_child_conc_request_id IS NULL) OR
11694      (p_child_conc_request_id IS NOT NULL AND p_child_conc_request_id = p_parent_conc_request_id) THEN
11695     -- this routine is executed by parent conc request. Modified due to ORA-00054 errors reported
11696     -- when workers are deleting the rows.
11697 
11698     G_DEBUG_LINE_NUM := 310;
11699     -- cleanup any orphaned rows left from other parent requests.
11700     FOR undeleted_parent IN get_undeleted_parents(p_parent_conc_request_id) LOOP
11701        /* not needed - check only child conc request status
11702        -- check parent status.
11703        l_req_status := FND_CONCURRENT.GET_REQUEST_STATUS(request_id => undeleted_parent.parent_conc_request_id,
11704                                                          --appl_shortname => 'AHL',
11705                                                          --program   => 'AHLUEFF',
11706                                                          phase      => l_rphase,
11707                                                          status     => l_rstatus,
11708                                                          dev_phase  => l_dphase,
11709                                                          dev_status => l_dstatus,
11710                                                          message    => l_message);
11711        IF (l_req_status = TRUE) AND (l_dphase = 'COMPLETE' OR l_dphase IS NULL) THEN
11712        */
11713 
11714        FOR undeleted_child IN get_undeleted_child(undeleted_parent.parent_conc_request_id) LOOP
11715            l_req_status := FND_CONCURRENT.GET_REQUEST_STATUS(request_id => undeleted_child.child_conc_request_id,
11716                                                              --appl_shortname => 'AHL',
11717                                                              --program   => 'AHLWUEFF',
11718                                                              phase      => l_rphase,
11719                                                              status     => l_rstatus,
11720                                                              dev_phase  => lc_dphase,
11721                                                              dev_status => l_dstatus,
11722                                                              message    => l_message);
11723            IF NOT(l_req_status) THEN
11724               -- check if request exists in fnd_concurrent_requests table
11725               OPEN fnd_concur_csr(undeleted_child.child_conc_request_id);
11726               FETCH fnd_concur_csr INTO l_junk;
11727               IF (fnd_concur_csr%NOTFOUND) THEN
11728                 l_req_status := TRUE;
11729                 lc_dphase := NULL;
11730               END IF;
11731               CLOSE fnd_concur_csr;
11732            END IF;
11733 
11734            IF (l_req_status = TRUE) AND (lc_dphase = 'COMPLETE' OR lc_dphase IS NULL) THEN
11735               -- lock and delete rows for undeleted_child.child_conc_request_id.
11736               OPEN lock_child_rows(undeleted_parent.parent_conc_request_id,
11737                                    undeleted_child.child_conc_request_id);
11738               G_DEBUG_LINE_NUM := 320;
11739               LOOP
11740                   G_DEBUG_LINE_NUM := 330;
11741                   FETCH lock_child_rows BULK COLLECT INTO l_rowid_tbl LIMIT l_buffer_limit;
11742                   --EXIT WHEN (l_rowid_tbl.count = 0);
11743                   IF (l_rowid_tbl.count = 0) THEN
11744                     ROLLBACK;
11745                     EXIT;
11746                   END IF;
11747 
11748                   G_DEBUG_LINE_NUM := 340;
11749 
11750                   BEGIN
11751                     SAVEPOINT lock_child_rows_upd_s;
11752                     FORALL j IN l_rowid_tbl.FIRST..l_rowid_tbl.LAST
11753                        -- delete for parent concurrent.
11754                        DELETE FROM ahl_bue_worker_data
11755                        WHERE rowid = l_rowid_tbl(j);
11756 
11757                     COMMIT;
11758                     --
11759                     EXCEPTION
11760                         WHEN OTHERS THEN
11761                           rollback to lock_child_rows_upd_s;
11762                           EXIT; -- abort delete for child.
11763                           -- dbms_output.put_line('Record Locked');
11764                   END;
11765 
11766                   l_rowid_tbl.delete;
11767 
11768               END LOOP;
11769               CLOSE lock_child_rows;
11770 
11771            END IF; -- l_req_status and lc_dphase
11772        END LOOP; -- undeleted_child IN
11773 
11774      --END IF; -- (l_dphase = 'COMPLETE')
11775     END LOOP; -- undeleted_parent IN
11776   END IF; -- p_child_conc_request_id IS NULL
11777 
11778   IF G_debug = 'Y' THEN
11779      AHL_DEBUG_PUB.debug('End Cleanup_BUE_Worker');
11780   END IF;
11781 
11782 EXCEPTION
11783   WHEN record_locked THEN
11784     IF (lock_child_rows%ISOPEN) THEN
11785       CLOSE lock_child_rows;
11786     END IF;
11787     ROLLBACK;
11788     -- dbms_output.put_line('Record Locked');
11789 
11790 END Cleanup_BUE_Worker;
11791 
11792 -- Added for performance bug# 6893404.
11793 PROCEDURE Populate_BUE_Worker_for_MR(p_conc_request_id IN  NUMBER,
11794                                      p_mr_header_id    IN  NUMBER,
11795                                      p_concurrent_flag IN  VARCHAR2,
11796                                      p_mtl_category_id IN  NUMBER,
11797                                      p_process_option  IN  VARCHAR2,
11798                                      x_return_status   OUT NOCOPY VARCHAR2)
11799 IS
11800   PRAGMA AUTONOMOUS_TRANSACTION;
11801 
11802   -- get item instances that are either components
11803   -- or a UC when no item category and process option = Units or Components or all.
11804   CURSOR get_inst_csr (p_mr_header_id IN NUMBER,
11805                        p_opt_uc       IN NUMBER) IS
11806     SELECT instance_id from
11807      (SELECT DISTINCT nvl(root_instance_id, instance_id) instance_id from
11808        (
11809         SELECT cii.instance_id,
11810               (select object_id from csi_ii_relationships parent
11811                where not exists (select 'x' from csi_ii_relationships
11812                                  where subject_id = parent.object_id and
11813                                  relationship_type_code = 'COMPONENT-OF' and
11814                                  trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) and
11815                                  trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
11816                start with parent.subject_id = cii.instance_id and
11817                parent.relationship_type_code = 'COMPONENT-OF' and
11818                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11819                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11820                connect by prior parent.object_id = parent.subject_id and
11821                parent.relationship_type_code = 'COMPONENT-OF' and
11822                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11823                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11824                ) Root_instance_id
11825 
11826         FROM csi_item_instances cii, ahl_mr_instances_temp mr
11827         WHERE trunc(nvl(cii.active_start_date, sysdate)) <= trunc(sysdate) AND
11828               trunc(sysdate) < trunc(nvl(cii.active_end_date, sysdate+1))
11829           AND mr.item_instance_id  = cii.instance_id
11830        )
11831      ) valid_inst
11832     WHERE (p_opt_uc = 1 AND exists (select 'x' from ahl_unit_config_headers
11833                                     where csi_item_instance_id = valid_inst.instance_id
11834                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11835                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11836                                       AND unit_config_status_code <> 'DRAFT'
11837                                       AND parent_uc_header_id IS NULL
11838                                    ) -- get UCs only.
11839           )
11840           OR
11841           -- get components.
11842           (p_opt_uc = 2 AND not exists (select 'x' from ahl_unit_config_headers
11843                                         where csi_item_instance_id = valid_inst.instance_id
11844                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11845                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11846                                           -- instance is a UC if in status draft.
11847                                           --AND unit_config_status_code <> 'DRAFT'
11848                                           --AND parent_uc_header_id IS NULL
11849                                        )
11850           )
11851           OR
11852           -- get all but do not select draft UCs as Process Unit will raise error.
11853           (p_opt_uc = 0 AND not exists (select 'x' from ahl_unit_config_headers
11854                                         where csi_item_instance_id = valid_inst.instance_id
11855                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11856                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11857                                           AND unit_config_status_code = 'DRAFT'
11858                                        )
11859           );
11860 
11861 
11862   -- get item instances when item category selected with process option of ALL, Units or Components.
11863   CURSOR get_itemcat_inst_csr (p_mr_header_id IN NUMBER,
11864                                p_mtl_category_id IN NUMBER,
11865                                p_opt_uc          IN NUMBER) IS
11866     SELECT instance_id from
11867      (SELECT DISTINCT nvl(root_instance_id, instance_id) instance_id from
11868        (
11869         SELECT cii.instance_id,
11870               (select object_id from csi_ii_relationships parent
11871                where not exists (select 'x' from csi_ii_relationships
11872                                  where subject_id = parent.object_id and
11873                                  relationship_type_code = 'COMPONENT-OF' and
11874                                  trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate) and
11875                                  trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
11876                start with parent.subject_id = cii.instance_id and
11877                parent.relationship_type_code = 'COMPONENT-OF' and
11878                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11879                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11880                connect by prior parent.object_id = parent.subject_id and
11881                parent.relationship_type_code = 'COMPONENT-OF' and
11882                trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11883                trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11884                ) Root_instance_id
11885 
11886         FROM csi_item_instances cii,ahl_mr_instances_temp mr
11887         WHERE trunc(nvl(cii.active_start_date, sysdate)) <= trunc(sysdate) AND
11888               trunc(sysdate) < trunc(nvl(cii.active_end_date, sysdate+1))
11889           AND mr.item_instance_id  = cii.instance_id
11890        )
11891      ) valid_inst
11892     WHERE exists (select 'x'
11893                   from mtl_category_set_valid_cats cs, mtl_item_categories itc,
11894                        csi_item_instances cii2
11895                   where cs.category_set_id = fnd_profile.value('AHL_BUE_ITEM_CATEGORY_SET')
11896                     AND cs.category_set_id = itc.category_set_id
11897                     AND cs.category_id = itc.category_id
11898                     AND itc.category_id = p_mtl_category_id
11899                     AND cii2.instance_id = valid_inst.instance_id
11900                     AND itc.organization_id = cii2.inv_master_organization_id
11901                     AND itc.inventory_item_id = cii2.inventory_item_id
11902                   ) -- get root nodes matching item category.
11903       -- either UC or components.
11904       AND ((p_opt_uc = 1 AND exists (select 'x' from ahl_unit_config_headers
11905                                     where csi_item_instance_id = valid_inst.instance_id
11906                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11907                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11908                                       AND unit_config_status_code <> 'DRAFT'
11909                                       AND parent_uc_header_id IS NULL
11910                                    ) -- get UCs only.
11911           )
11912           OR
11913           -- get components.
11914           (p_opt_uc = 2 AND not exists (select 'x' from ahl_unit_config_headers
11915                                         where csi_item_instance_id = valid_inst.instance_id
11916                                       AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11917                                       AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11918                                           -- instance is a UC if in status draft.
11919                                           --AND unit_config_status_code <> 'DRAFT'
11920                                           --AND parent_uc_header_id IS NULL
11921                                        )
11922           )
11923           OR
11924           -- when process option is ALL. Ignore Draft UC's
11925           (p_opt_uc = 0 AND not exists (select 'x' from ahl_unit_config_headers
11926                                         where csi_item_instance_id = valid_inst.instance_id
11927                                           AND trunc(nvl(active_start_date,sysdate)) <= trunc(sysdate)
11928                                           AND trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1))
11929                                           AND unit_config_status_code = 'DRAFT'
11930                                        )
11931           )
11932           );
11933 
11934 
11935   -- get UEs for the MR that are not existing in BUE worker table.
11936   CURSOR get_extra_ue_na(p_mr_header_id IN NUMBER,
11937                          p_conc_request_id IN NUMBER)  IS
11938     SELECT csi_item_instance_id
11939     FROM (
11940           SELECT DISTINCT nvl(Root_instance_id, csi_item_instance_id) csi_item_instance_id
11941           FROM (
11942                 SELECT DISTINCT UE.csi_item_instance_id,
11943                                 (select object_id from csi_ii_relationships parent
11944                                  where not exists (select 'x' from csi_ii_relationships
11945                                                    where subject_id = parent.object_id and
11946                                                    trunc(sysdate) < trunc(nvl(active_end_date,sysdate+1)))
11947                                  start with parent.subject_id = UE.CSI_ITEM_INSTANCE_ID and
11948                                  parent.relationship_type_code = 'COMPONENT-OF' and
11949                                  trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11950                                  trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11951                                  connect by prior parent.object_id = parent.subject_id and
11952                                  parent.relationship_type_code = 'COMPONENT-OF' and
11953                                  trunc(nvl(parent.active_start_date, sysdate)) <= trunc(sysdate) and
11954                                  trunc(sysdate) < trunc(nvl(parent.active_end_date, sysdate+1))
11955                                 ) Root_instance_id
11956 
11957                 FROM  ahl_unit_effectivities_app_v UE
11958                 WHERE UE.mr_header_id = p_mr_header_id
11959                   AND (UE.status_code IS NULL OR UE.status_code IN ('INIT-DUE','EXCEPTION'))
11960                   AND  NOT EXISTS (Select 1
11961                                    FROM ahl_mr_instances_temp
11962                                    WHERE item_instance_id = ue.csi_item_instance_id)
11963                                   )
11964          ) valid_inst
11965     WHERE NOT EXISTS (Select 1
11966                       FROM AHL_BUE_WORKER_DATA
11967                       WHERE csi_item_instance_id = valid_inst.csi_item_instance_id
11968                         AND parent_conc_request_id = p_conc_request_id) ;
11969 
11970   l_relationship_tbl  nbr_tbl_type;
11971   l_instance_id_tbl   nbr_tbl_type;
11972 
11973   l_opt           number;
11974   l_opt_uc        number;
11975 
11976   l_buffer_limit  number := 1000;
11977 
11978   l_api_version   number := 1.0;
11979   l_msg_count     number;
11980   l_msg_data      varchar2(4000);
11981 
11982   dml_errors EXCEPTION;
11983   PRAGMA EXCEPTION_INIT(dml_errors, -24381);
11984 
11985   l_mr_item_instances_tbl  AHL_FMP_PVT.MR_ITEM_INSTANCE_TBL_TYPE;
11986 
11987 BEGIN
11988 
11989   IF G_debug = 'Y' THEN
11990      AHL_DEBUG_PUB.debug('Start Populate_BUE_Worker_for_MR: Input MR Header ID:' || p_mr_header_id);
11991      AHL_DEBUG_PUB.debug('Input Concurrent Flag:' || p_conc_request_id);
11992      AHL_DEBUG_PUB.debug('Input Conc Request ID:' || p_concurrent_flag);
11993   END IF;
11994 
11995   -- initialize return status.
11996   x_return_status := FND_API.G_RET_STS_SUCCESS;
11997 
11998   -- get instances applicable to the MR.
11999   -- this API will insert the applicable MRs into temp table ahl_mr_instances_temp
12000   AHL_FMP_PVT.GET_MR_AFFECTED_ITEMS (
12001          p_api_version => 1.0,
12002          p_init_msg_list => FND_API.G_TRUE,
12003          x_return_status => x_return_status,
12004          x_msg_count     => l_msg_count,
12005          x_msg_data      => l_msg_data,
12006          p_mr_header_id  => p_mr_header_id,
12007          p_top_node_flag => 'N',
12008          p_unique_inst_flag => 'Y',
12009          x_mr_item_inst_tbl => l_mr_item_instances_tbl );
12010 
12011   IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
12012     ROLLBACK;
12013     RETURN;
12014   END IF;
12015 
12016 
12017   IF (p_process_option = 'AHL_BUE_ALL_COMPONENTS') THEN
12018      l_opt_uc := 2;
12019   ELSIF (p_process_option = 'AHL_BUE_ALL_UNITS') THEN
12020      l_opt_uc := 1;
12021   ELSE
12022      l_opt_uc := 0;  -- when null or input is AHL_BUE_ALL
12023   END IF;
12024 
12025   -- process effectivity
12026   IF (p_mtl_category_id IS NULL) THEN
12027       OPEN get_inst_csr(p_mr_header_id, l_opt_uc);
12028   ELSE
12029       OPEN get_itemcat_inst_csr(p_mr_header_id, p_mtl_category_id, l_opt_uc);
12030   END IF;
12031 
12032   LOOP
12033       IF (p_mtl_category_id IS NULL) THEN
12034           FETCH get_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
12035       ELSE
12036           FETCH get_itemcat_inst_csr BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
12037       END IF;
12038 
12039       EXIT WHEN (l_instance_id_tbl.count = 0);
12040 
12041       BEGIN
12042         -- insert into BUE table.
12043         FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST SAVE EXCEPTIONS
12044           INSERT INTO AHL_BUE_WORKER_DATA
12045           (parent_conc_request_id,
12046            csi_item_instance_id,
12047            child_conc_request_id,
12048            last_update_date,
12049            last_updated_by,
12050            creation_date,
12051            created_by,
12052            last_update_login,
12053            object_version_number) VALUES
12054            (p_conc_request_id,
12055             l_instance_id_tbl(instance_indx),
12056             null,
12057             sysdate,
12058             fnd_global.user_id,
12059             sysdate,
12060             fnd_global.user_id,
12061             fnd_global.conc_login_id,
12062             1);
12063 
12064         EXCEPTION
12065           WHEN DML_ERRORS THEN
12066             IF (get_inst_csr%ISOPEN) THEN
12067               CLOSE get_inst_csr;
12068             END IF;
12069             IF (get_itemcat_inst_csr%ISOPEN) THEN
12070               CLOSE get_itemcat_inst_csr;
12071             END IF;
12072 
12073             x_return_status := 'E';
12074 
12075             IF (p_concurrent_flag = 'Y') THEN
12076               fnd_file.put_line(fnd_file.log, 'Following error(s) occured while inserting into table ahl_bue_worker_data');
12077               FOR j IN 1..sql%bulk_exceptions.count
12078               LOOP
12079                 fnd_file.put_line(fnd_file.log, sql%bulk_exceptions(j).error_index || ', ' ||
12080                 sqlerrm(-sql%bulk_exceptions(j).error_code) );
12081               END LOOP;
12082             END IF;
12083 
12084             FND_MESSAGE.set_name('AHL', 'AHL_UMP_BUE_WORKER_ERR');
12085             FND_MSG_PUB.add;
12086 
12087             RETURN;
12088         END;
12089 
12090         l_instance_id_tbl.DELETE;
12091 
12092   END LOOP;
12093 
12094   IF (p_mtl_category_id IS NULL) THEN
12095      CLOSE get_inst_csr;
12096   ELSE
12097      CLOSE get_itemcat_inst_csr;
12098   END IF;
12099 
12100   l_instance_id_tbl.DELETE;
12101 
12102   -- process extra UE instances
12103   OPEN get_extra_ue_na(p_mr_header_id, p_conc_request_id);
12104   LOOP
12105     FETCH get_extra_ue_na BULK COLLECT INTO l_instance_id_tbl LIMIT l_buffer_limit;
12106     EXIT WHEN (l_instance_id_tbl.COUNT = 0);
12107     BEGIN
12108       -- insert into BUE table.
12109       FORALL instance_indx IN l_instance_id_tbl.FIRST..l_instance_id_tbl.LAST SAVE EXCEPTIONS
12110         INSERT INTO AHL_BUE_WORKER_DATA
12111           (parent_conc_request_id,
12112            csi_item_instance_id,
12113            child_conc_request_id,
12114            last_update_date,
12115            last_updated_by,
12116            creation_date,
12117            created_by,
12118            last_update_login,
12119            object_version_number) VALUES
12120            (p_conc_request_id,
12121             l_instance_id_tbl(instance_indx),
12122             null,
12123             sysdate,
12124             fnd_global.user_id,
12125             sysdate,
12126             fnd_global.user_id,
12127             fnd_global.conc_login_id,
12128             1);
12129 
12130     EXCEPTION
12131       WHEN DML_ERRORS THEN
12132 
12133         IF (get_extra_ue_na%ISOPEN) THEN
12134           CLOSE get_extra_ue_na;
12135         END IF;
12136         x_return_status := 'E';
12137 
12138         IF (p_concurrent_flag = 'Y') THEN
12139           fnd_file.put_line(fnd_file.log, 'Following error(s) occured while inserting into table ahl_bue_worker_data');
12140           FOR j IN 1..sql%bulk_exceptions.count
12141           LOOP
12142             fnd_file.put_line(fnd_file.log, sql%bulk_exceptions(j).error_index || ', ' ||
12143             sqlerrm(-sql%bulk_exceptions(j).error_code) );
12144           END LOOP;
12145         END IF;
12146 
12147         FND_MESSAGE.set_name('AHL', 'AHL_UMP_BUE_WORKER_ERR');
12148         FND_MSG_PUB.add;
12149 
12150         RETURN;
12151       END;
12152 
12153       l_instance_id_tbl.DELETE;
12154 
12155   END LOOP;
12156   CLOSE get_extra_ue_na;
12157 
12158   -- delete duplicate rows.
12159   DELETE FROM ahl_bue_worker_data
12160   WHERE parent_conc_request_id = p_conc_request_id
12161     AND rowid not in (SELECT MIN(rowid)
12162                       FROM ahl_bue_worker_data
12163                       WHERE parent_conc_request_id = p_conc_request_id
12164                       GROUP BY csi_item_instance_id, parent_conc_request_id) ;
12165 
12166 
12167   -- save changes.
12168   COMMIT WORK;
12169 
12170   IF G_debug = 'Y' THEN
12171     AHL_DEBUG_PUB.debug('End Populate_BUE_Worker_for_MR: x_return_status:' || x_return_status);
12172   END IF;
12173 
12174 END Populate_BUE_Worker_for_MR;
12175 
12176 -- Added for performance bug# 6893404.
12177 FUNCTION get_latest_ctr_reading(p_counter_id IN NUMBER) RETURN NUMBER
12178 IS
12179 
12180   -- get net reading.
12181   CURSOR get_ctr_reading_csr (p_counter_id IN NUMBER) IS
12182      SELECT * FROM
12183         (SELECT net_reading
12184          FROM csi_counter_readings
12185          WHERE counter_id = p_counter_id
12186            AND nvl(disabled_flag,'N') = 'N'
12187          ORDER BY value_timestamp desc)
12188      WHERE rownum < 2;
12189 
12190   l_net_reading NUMBER;
12191 
12192 BEGIN
12193 
12194   OPEN get_ctr_reading_csr(p_counter_id);
12195   FETCH get_ctr_reading_csr INTO l_net_reading;
12196   IF (get_ctr_reading_csr%NOTFOUND) THEN
12197      l_net_reading := 0;
12198   END IF;
12199   CLOSE get_ctr_reading_csr;
12200 
12201   RETURN l_net_reading;
12202 
12203 END get_latest_ctr_reading;
12204 ----
12205 
12206 -- procedure checks if forecast exists for all of instance's UOM and adds
12207 -- zero forecast row if missing forecast.
12208 PROCEDURE validate_uf_for_ctr(p_current_usage_tbl       IN counter_values_tbl_type,
12209                               p_x_forecast_details_tbl  IN OUT NOCOPY forecast_details_tbl_type)
12210 IS
12211   l_last_index  NUMBER;
12212   l_uom_found_flag BOOLEAN;
12213 
12214 BEGIN
12215 
12216   IF G_DEBUG = 'Y' THEN
12217      AHL_DEBUG_PUB.debug ('Start validate_uf_for_ctr');
12218   END IF;
12219 
12220   l_last_index := p_x_forecast_details_tbl.LAST + 1;
12221 
12222   IF (p_current_usage_tbl.COUNT > 0) THEN
12223     FOR j IN p_current_usage_tbl.FIRST..p_current_usage_tbl.LAST LOOP
12224        l_uom_found_flag := FALSE;
12225        IF (p_x_forecast_details_tbl.COUNT > 0) THEN
12226          FOR i IN p_x_forecast_details_tbl.FIRST..p_x_forecast_details_tbl.LAST LOOP
12227            IF (p_x_forecast_details_tbl(i).uom_code = p_current_usage_tbl(j).uom_code) THEN
12228              l_uom_found_flag := TRUE;
12229              EXIT;
12230            END IF;
12231          END LOOP;  -- i
12232 
12233          IF (l_uom_found_flag = FALSE) THEN
12234             p_x_forecast_details_tbl(l_last_index).uom_code := p_current_usage_tbl(j).uom_code;
12235             p_x_forecast_details_tbl(l_last_index).start_date := trunc(sysdate);
12236             p_x_forecast_details_tbl(l_last_index).end_date := NULL;
12237             p_x_forecast_details_tbl(l_last_index).usage_per_day := 0;
12238 
12239             l_last_index := l_last_index + 1;
12240          END IF;
12241        END IF;
12242 
12243     END LOOP; -- j
12244   END IF; -- p_current_usage_tbl.COUNT
12245 
12246   IF G_DEBUG = 'Y' THEN
12247      AHL_DEBUG_PUB.debug ('Count on forecast_details' || p_x_forecast_details_tbl.COUNT);
12248 
12249      IF (p_x_forecast_details_tbl.COUNT > 0) THEN
12250        FOR i IN p_x_forecast_details_tbl.FIRST..p_x_forecast_details_tbl.LAST LOOP
12251              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Uom_Code' || p_x_forecast_details_tbl(i).uom_code);
12252              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Start Date' || p_x_forecast_details_tbl(i).start_date);
12253              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') End Date' || p_x_forecast_details_tbl(i).end_date);
12254              AHL_DEBUG_PUB.debug('Forecast Record ('|| i || ') Usage' || p_x_forecast_details_tbl(i).usage_per_day);
12255        END LOOP;
12256      END IF;
12257      AHL_DEBUG_PUB.debug ('End validate_uf_for_ctr');
12258   END IF;
12259 
12260 END validate_uf_for_ctr;
12261 
12262 
12263 
12264 END AHL_UMP_ProcessUnit_PVT;