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;