1 Package Body GMD_COMMON_VAL AS
2 /* $Header: GMDPCOMB.pls 120.22.12020000.2 2012/07/17 10:31:23 mtou ship $ */
3
4
5 --Bug 3222090, NSRIVAST 20-FEB-2004, BEGIN
6 --Forward declaration.
7 FUNCTION set_debug_flag RETURN VARCHAR2;
8 l_debug VARCHAR2(1) := set_debug_flag;
9
10 FUNCTION set_debug_flag RETURN VARCHAR2 IS
11 l_debug VARCHAR2(1):= 'N';
12 BEGIN
13 IF( FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL ) THEN
14 l_debug := 'Y';
15 END IF;
16 RETURN l_debug;
17 END set_debug_flag;
18 --Bug 3222090, NSRIVAST 20-FEB-2004, END
19
20 /* ********************************************************************* */
21 /* Purpose: Validation functions and procedures used by more than one */
22 /* part of GMD (Routings, Ops, Formula, QC, Recipes, Lab) */
23 /* */
24 /* Some code common to more than one module can be found in GMA_VALID_GRP*/
25 /* (ex: validate_um, validate_orgn_code, validate_type) */
26 /* */
27 /* check_from_date */
28 /* check_date */
29 /* check_date_range */
30 /* get_customer_id */
31 /* customer_exists */
32 /* check_project_id */
33 /* check_user_id */
34 /* action_code */
35 /* */
36 /* */
37 /* MODIFICATION HISTORY */
38 /* Person Date Comments */
39 /* --------- ------ ------------------------------------------ */
40 /* 14Nov2000 Created */
41 /* ********************************************************************* */
42 FUNCTION check_from_date(pfrom_date IN DATE,
43 pcalledby_form IN VARCHAR2) RETURN NUMBER
44 IS
45 BEGIN
46 return 1;
47 END check_from_date;
48
49 FUNCTION check_date(pdate IN DATE,
50 pcalledby_form IN VARCHAR2) RETURN NUMBER
51 IS
52 BEGIN
53 return 1;
54 END check_date;
55
56 FUNCTION check_date_range(pfrom_date IN DATE,
57 pto_date IN DATE,
58 pcalledby_form IN VARCHAR2) RETURN NUMBER
59 IS
60 BEGIN
61 return 1;
62
63 END;
64
65 /* ======================================================================= */
66 /* PROCEDURE: */
67 /* get_customer_id */
68 /* */
69 /* DESCRIPTION: */
70 /* This PL/SQL function is responsible for */
71 /* retrieving a customer's surrogate key unique number */
72 /* based on the passed in customer number. */
73 /* */
74 /* CUST_ID is returned in the xvalue parameter */
75 /* and xreturn_code is 0 (zero) upon success. Failure */
76 /* returns xvalue as NULL and xreturn_code contains the */
77 /* error code. */
78 /* */
79 /* SYNOPSIS: */
80 /* iret := GMDFMVAL_PUB.get_customer_id(pcustomer_no, */
81 /* xvalue, */
82 /* xreturn_code); */
83 /* */
84 /* RETURNS: */
85 /* 0 Success */
86 /* -92205 Customer ID not found. */
87 /* < 0 RDBMS error */
88 /* ======================================================================== */
89
90 PROCEDURE get_customer_id(pcustomer_no IN VARCHAR2,
91 xcust_id OUT NOCOPY NUMBER,
92 xsite_id OUT NOCOPY NUMBER,
93 xorg_id OUT NOCOPY NUMBER,
94 xreturn_code OUT NOCOPY NUMBER) IS
95
96 /* Local variables. */
97 l_cust_id hz_cust_accounts.cust_account_id%TYPE := 0;
98 l_site_id hz_cust_site_uses_all.site_use_id%TYPE := 0;
99 l_org_id hz_cust_site_uses_all.org_id%TYPE := 0;
100
101
102 /* Cursor Definitions. */
103 /* =================== */
104 CURSOR get_id IS
105 SELECT cust_acct.cust_account_id, site.site_use_id, site.org_id
106 FROM hz_parties party,
107 hz_cust_accounts cust_acct,
108 hz_cust_acct_sites_all acct_site,
109 hz_cust_site_uses_all site,
110 hz_party_sites party_site,
111 hz_locations loc
112 WHERE acct_site.cust_account_id=cust_acct.cust_account_id
113 and cust_acct.party_id=party.party_id
114 and site.site_use_code='SHIP_TO'
115 and site.cust_acct_site_id=acct_site.cust_acct_site_id
116 and acct_site.status='A'
117 and site.cust_acct_site_id=acct_site.cust_acct_site_id
118 and acct_site.party_site_id=party_site.party_site_id
119 and party_site.location_id=loc.location_id
120 and party.party_number = UPPER(pcustomer_no);
121
122
123 /* ================================================ */
124 BEGIN
125 OPEN get_id;
126 FETCH get_id INTO l_cust_id,l_site_id,l_org_id;
127 IF (get_id%NOTFOUND) THEN
128 xcust_id := NULL;
129 xsite_id := NULL;
130 xorg_id := NULL;
131 xreturn_code := FMVAL_CUSTID_ERR;
132 CLOSE get_id;
133 RETURN;
134 END IF;
135
136 xcust_id := l_cust_id;
137 xsite_id := l_site_id;
138 xorg_id := l_org_id;
139 xreturn_code := 0;
140 CLOSE get_id;
141 RETURN;
142
143 EXCEPTION
144 WHEN OTHERS THEN
145
146 RETURN;
147 END get_customer_id;
148
149
150 /* **************************************************************************
151 * NAME
152 * customer_exists
153 * DESCRIPTION
154 * This procedure will check if given id or name exist in OP_CUST_MST.
155 * If name provided, id will be returned.
156 * Currently used by recipes and QC
157 * PARAMETERS standard + customer_id, customer_no
158 * RETURN VALUES standard + customer_id
159 *
160 * LrJackson 27Dec2000 Copied from recipe_exists
161 * Raju Added new cursors to check siteid and orgid exists for that customer.
162 **************************************************************************** */
163
164 PROCEDURE customer_exists
165 ( p_api_version IN NUMBER,
166 p_init_msg_list IN VARCHAR2 := FND_API.G_FALSE,
167 p_commit IN VARCHAR2 := FND_API.G_FALSE,
168 p_validation_level IN NUMBER := FND_API.G_VALID_LEVEL_NONE,
169 p_customer_id IN NUMBER,
170 p_site_id IN NUMBER,
171 p_org_id IN NUMBER,
172 p_customer_no IN VARCHAR2,
173 x_return_status OUT NOCOPY VARCHAR2,
174 x_msg_count OUT NOCOPY NUMBER,
175 x_msg_data OUT NOCOPY VARCHAR2,
176 x_return_code OUT NOCOPY NUMBER,
177 x_customer_id OUT NOCOPY NUMBER) IS
178
179 CURSOR get_record IS
180 SELECT cust_acct.cust_account_id
181 FROM hz_parties party,
182 hz_cust_accounts cust_acct,
183 hz_cust_acct_sites_all acct_site,
184 hz_cust_site_uses_all site,
185 hz_party_sites party_site,
186 hz_locations loc
187 where acct_site.cust_account_id=cust_acct.cust_account_id
188 and cust_acct.party_id=party.party_id
189 and site.site_use_code='SHIP_TO'
190 and site.cust_acct_site_id=acct_site.cust_acct_site_id
191 and acct_site.status='A'
192 and site.cust_acct_site_id=acct_site.cust_acct_site_id
193 and acct_site.party_site_id=party_site.party_site_id
194 and party_site.location_id=loc.location_id
195 and (cust_acct.cust_account_id = p_customer_id OR party.party_number = UPPER(p_customer_no));
196
197 CURSOR get_site IS
198 SELECT site.site_use_id
199 FROM hz_parties party,
200 hz_cust_accounts cust_acct,
201 hz_cust_acct_sites_all acct_site,
202 hz_cust_site_uses_all site,
203 hz_party_sites party_site,
204 hz_locations loc
205 where acct_site.cust_account_id=cust_acct.cust_account_id
206 and cust_acct.party_id=party.party_id
207 and site.site_use_code='SHIP_TO'
208 and site.cust_acct_site_id=acct_site.cust_acct_site_id
209 and acct_site.status='A'
210 and site.cust_acct_site_id=acct_site.cust_acct_site_id
211 and acct_site.party_site_id=party_site.party_site_id
212 and party_site.location_id=loc.location_id
213 and site.site_use_id = p_site_id
214 and (cust_acct.cust_account_id = p_customer_id OR party.party_number = UPPER(p_customer_no));
215
216 CURSOR get_orgid IS
217 SELECT site.org_id
218 FROM hz_parties party,
219 hz_cust_accounts cust_acct,
220 hz_cust_acct_sites_all acct_site,
221 hz_cust_site_uses_all site,
222 hz_party_sites party_site,
223 hz_locations loc
224 where acct_site.cust_account_id=cust_acct.cust_account_id
225 and cust_acct.party_id=party.party_id
226 and site.site_use_code='SHIP_TO'
227 and site.cust_acct_site_id=acct_site.cust_acct_site_id
228 and acct_site.status='A'
229 and site.cust_acct_site_id=acct_site.cust_acct_site_id
230 and acct_site.party_site_id=party_site.party_site_id
231 and party_site.location_id=loc.location_id
232 and site.org_id = p_org_id
233 and (cust_acct.cust_account_id = p_customer_id OR party.party_number = UPPER(p_customer_no));
234
235 /*** Variables ***/
236 l_api_name CONSTANT VARCHAR2(30) := 'CUSTOMER_EXISTS';
237 l_api_version CONSTANT NUMBER := 1.0;
238 l_site_id NUMBER;
239 l_org_id NUMBER;
240
241 BEGIN
242 /* no SAVEPOINT needed because there is no insert/update/delete */
243 IF NOT FND_API.Compatible_API_Call (l_api_version, p_api_version,
244 l_api_name, G_PKG_NAME) THEN
245 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
246 END IF;
247 IF FND_API.to_Boolean(p_init_msg_list) THEN
248 FND_MSG_PUB.initialize;
249 END IF;
250 x_return_status := FND_API.G_RET_STS_SUCCESS;
251
252 IF (p_customer_id IS NOT NULL OR p_customer_no IS NOT NULL) THEN
253 OPEN get_record;
254 FETCH get_record into x_customer_id;
255 IF get_record%NOTFOUND THEN
256 RAISE fnd_api.g_exc_error;
257 END IF;
258 CLOSE get_record;
259 END IF;
260
261 IF (p_site_id IS NOT NULL) THEN
262 OPEN get_site;
263 FETCH get_site into l_site_id;
264 IF get_site%NOTFOUND THEN
265 RAISE fnd_api.g_exc_error;
266 END IF;
267 CLOSE get_site;
268 END IF;
269
270 IF (p_org_id IS NOT NULL) THEN
271 OPEN get_orgid;
272 FETCH get_orgid into l_org_id;
273 IF get_orgid%NOTFOUND THEN
274 RAISE fnd_api.g_exc_error;
275 END IF;
276 CLOSE get_orgid;
277 END IF;
278
279 /* no standard check of p_commit because no insert/update/delete */
280
281 /* standard call to get msge cnt, and if cnt is 1, get mesg info */
282 FND_MSG_PUB.Count_And_Get(p_count=>x_msg_count, p_data=>x_msg_data);
283
284 EXCEPTION
285 WHEN FND_API.G_EXC_ERROR THEN
286 X_return_code := SQLCODE;
287 x_return_status := FND_API.G_RET_STS_ERROR;
288 FND_MSG_PUB.Count_And_Get(p_count=>x_msg_count, p_data=>x_msg_data);
289
290 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
291 X_return_code := SQLCODE;
292
293 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
294 FND_MSG_PUB.Count_And_Get(p_count=>x_msg_count, p_data=>x_msg_data);
295
296 WHEN OTHERS THEN
297 X_return_code := SQLCODE;
298 x_return_status := FND_API.G_RET_STS_ERROR;
299 FND_MSG_PUB.Count_And_Get(p_count=>x_msg_count, p_data=>x_msg_data);
300
301 END customer_exists;
302
303
304 /* ===================================================== */
305 /* PROCEDURE: check_user_id */
306 /* */
307 /* Send a user_id, get a return code of 0 if user exists,*/
308 /* anything else is an error */
309 /* */
310 /* LeAta Jackson 22Dec2000 Created */
311 /* ===================================================== */
312 PROCEDURE check_user_id (p_api_version IN NUMBER,
313 p_init_msg_list IN VARCHAR2,
314 p_commit IN VARCHAR2,
315 p_validation_level IN NUMBER,
316 p_user_id IN NUMBER,
317 x_return_status OUT NOCOPY VARCHAR2,
318 x_msg_count OUT NOCOPY NUMBER,
319 x_msg_data OUT NOCOPY VARCHAR2,
320 x_return_code OUT NOCOPY NUMBER)
321
322 IS
323 CURSOR get_user IS
324 SELECT user_id
325 FROM fnd_user
326 WHERE user_id = p_user_id;
327
328 l_user_id fnd_user.user_id%TYPE;
329
330 BEGIN
331 OPEN get_user;
332 FETCH get_user INTO l_user_id;
333
334 IF get_user%NOTFOUND THEN
335 x_return_code := -1;
336 x_return_status := 'E';
337 ELSE
338 x_return_code := 0;
339
340 x_return_status := 'S';
341 END IF;
342
343 CLOSE get_user;
344
345 END check_user_id;
346
347
348 /* **************************************************************************
349 * NAME
350 * action_code
351 * DESCRIPTION
352 * This procedure will check that given action code is valid. I, U, D
353 * PARAMETERS - standard +
354 * p_action_code
355 * RETURN VALUES - standard
356 * MODIFICATION HISTORY
357 * Person Date Comments
358 *
359 **************************************************************************** */
360 PROCEDURE action_code
361 ( p_api_version IN NUMBER,
362 p_init_msg_list IN VARCHAR2 := FND_API.G_FALSE,
363 p_commit IN VARCHAR2 := FND_API.G_FALSE,
364 p_validation_level IN NUMBER := FND_API.G_VALID_LEVEL_NONE,
365 p_action_code IN VARCHAR2,
366 x_return_status OUT NOCOPY VARCHAR2,
367 x_msg_count OUT NOCOPY NUMBER,
368 x_msg_data OUT NOCOPY VARCHAR2,
369 x_return_code OUT NOCOPY NUMBER)
370 IS
371 /*** Variables ***/
372 l_api_name CONSTANT VARCHAR2(30) := 'ACTION_CODE';
373 l_api_version CONSTANT NUMBER := 1.0;
374
375 BEGIN
376 /* no SAVEPOINT needed because there is no insert/update/delete */
377 IF NOT FND_API.Compatible_API_Call (l_api_version, p_api_version,
378 l_api_name, G_PKG_NAME) THEN
379 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
380 END IF;
381 IF FND_API.to_Boolean(p_init_msg_list) THEN
382 FND_MSG_PUB.initialize;
383 END IF;
384 x_return_status := FND_API.G_RET_STS_SUCCESS;
385
386
387 IF p_action_code is null or p_action_code not in ('I', 'U', 'D') THEN
388 RAISE fnd_api.g_exc_error;
389 END IF;
390
391 /* no standard check of p_commit because no insert/update/delete */
392
393 /* standard call to get msge cnt, and if cnt is 1, get mesg info */
394 FND_MSG_PUB.Count_And_Get(p_count=>x_msg_count, p_data=>x_msg_data);
395
396 EXCEPTION
397 WHEN FND_API.G_EXC_ERROR THEN
398 X_return_code := SQLCODE;
399 x_return_status := FND_API.G_RET_STS_ERROR;
400 FND_MSG_PUB.Count_And_Get(p_count=>x_msg_count, p_data=>x_msg_data);
401
402 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
403 X_return_code := SQLCODE;
404 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
405 FND_MSG_PUB.Count_And_Get(p_count=>x_msg_count, p_data=>x_msg_data);
406
407 WHEN OTHERS THEN
408 X_return_code := SQLCODE;
409 x_return_status := FND_API.G_RET_STS_ERROR;
410
411 FND_MSG_PUB.Count_And_Get(p_count=>x_msg_count, p_data=>x_msg_data);
412
413 END action_code;
414
415 /* ========================================================= */
416 /* Procedure: */
417 /* Get_Status */
418 /* */
419 /* DESCRIPTION: */
420 /* This PL/SQL procedure fetch the status details - */
421 /* it gets the status meaning and description given the */
422 /* status code */
423 /* Return E if no status code exists */
424 /* Return S if status code is found */
425 /* ========================================================= */
426 PROCEDURE Get_Status
427 (
428 Status_code IN GMD_STATUS.Status_code%TYPE ,
429 Meaning OUT NOCOPY GMD_STATUS.Meaning%TYPE ,
430 Description OUT NOCOPY GMD_STATUS.Description%TYPE ,
431 x_return_status OUT NOCOPY VARCHAR2
432 ) IS
433 CURSOR Status_Cur(vStatus_code VARCHAR2) IS
434 SELECT Distinct status_code, Meaning, Description
435 FROM GMD_STATUS
436 Where status_code = vStatus_code;
437
438 l_status_code GMD_STATUS.Status_code%TYPE;
439 l_meaning GMD_STATUS.meaning%TYPE;
440 l_description GMD_STATUS.description%TYPE;
441
442 BEGIN
443
444 OPEN Status_cur(Status_code);
445 FETCH Status_cur INTO l_status_code, l_meaning, l_description;
446 IF (Status_cur%NOTFOUND) THEN
447 x_return_status := 'E';
448 FND_MESSAGE.SET_NAME('GMD', 'GMD_INVALID_STATUS_CODE');
449 FND_MSG_PUB.Add;
450 Else
451 x_return_status := 'S';
452 Meaning := l_meaning;
453 Description := l_description;
454 End If;
455 CLOSE Status_cur;
456
457 END Get_Status;
458
459 /* ************************************************************************ */
460 /* Procedure: */
461 /* Calculate_Process_loss */
462 /* */
463 /* DESCRIPTION: */
464 /* This PL/SQL procedure calculates the process loss value */
465 /* Parameters input */
466 /* Name Type */
467 /* 1) process_loss Record_type */
468 /* This record type comprises of the following fields */
469 /* qty Its the routing or recipe or batch quantity for which the*/
470 /* theo process will be calculated. */
471 /* User could pass a null value and expect the qty value to */
472 /* calculated. e.g recipe quantity can be derived. */
473 /* Recipe_id Null value could be passed, e.g for deriving the theo and*/
474 /* planned process at routing level (used from routing form)*/
475 /* need not have recipe information. */
476 /* If user decides to pass the recipe_id then the formula_id*/
477 /* routing_id information is redundant */
478 /* formula_id Can be null value. However need a value if the user does*/
479 /* not pass the recipe_id. */
480 /* Routing_id Cannot be null. Both theo or planned loss are not */
481 /* calculated when routing_id is not passed. */
482 /* */
483 /* Matrix for all conditions */
484 /* ----------------------------------------------------------------------| */
485 /* | Entity Required Comments | */
486 /* | | */
487 /* | qty No If not null, this value is used for all | */
488 /* | calculations. | */
489 /* | Yes If the calculation of losses is for a BATCH | */
490 /* | | */
491 /* | Recipe_id No If null, formula is required | */
492 /* | Yes If the calculation of losses is for a BATCH | */
493 /* | | */
494 /* | Formula_id No If null, recipe_id is required | */
495 /* | | */
496 /* | Routing_id Yes Passed or derived using Recipe_id | */
497 /* | | */
498 /* |---------------------------------------------------------------------| */
499 /* */
500 /* 2) Entity_type Takes 3 values: Routing, Recipe and Batch. */
501 /* */
502 /* OUT parameters */
503 /* x_recipe_theo_loss :Returns the Recipe theoretical Process loss */
504 /* x_process_loss :Returns the planned process loss for Routing, */
505 /* Recipe or Batch */
506 /* x_return_status */
507 /* Returns E if any error occues during the calculation */
508 /* e.g No routing class is associated with the routing */
509 /* Returns S if process loss is calculated and status is success */
510 /* Returns U if unexpected error occurs */
511 /* */
512 /* Step1 - Based on the routing_id get the routing_class from fm_rout_hdr */
513 /* Step2 - Based on routing_class get the UOM from fm_rout_cls table */
514 /* Step3 - Check if recipe uom can be converted to this UOM and convert */
515 /* total product qty to this UOM */
516 /* Step4 - Get the process loss from gmd_process_loss table. */
517 /* Step5 - apply a prorated values in routing */
518 /* Step 6 - apply prorated values in recipe for batch */
519 /* ======================================================================== */
520 /* HISTORY */
521 /* L.R.Jackson 05Jul2001 Bug 1857225. Initialize message list. */
522 /* Set return status = E when no routing is found */
523 /* Form will show messages as notes in */
524 /* the status bar if return status = E. */
525 /* Shyam 07/12/2001 The Total Output Qty value can be 0. */
526 /* Changed the condition (l_recipe_qty > 0) to */
527 /* (l_recipe_qty >= 0) prior to deriving the */
528 /* process loss (in line#662 ) for l_recipe_qty */
529 /* Shyam 04DEC2001 BUG # 2119151: With OPM Family Pack H changes. */
530 /* This was done to prevent ZERO divide error that */
531 /* have occurred if the theoretical process loss */
532 /* (l_routing_theo_loss) was 0. */
533 /* Uday Phadtare 13-MAR-2008 Bug 6871738. Select ROUTING_CLASS_UOM */
534 /* instead of UOM in Cursor Rout_cls_cur. */
535 /* ************************************************************************ */
536
537 PROCEDURE Calculate_Process_loss
538 ( process_loss IN process_loss_rec ,
539 Entity_type IN VARCHAR2 ,
540 x_recipe_theo_loss OUT NOCOPY GMD_PROCESS_LOSS.process_loss%TYPE ,
541 x_process_loss OUT NOCOPY GMD_PROCESS_LOSS.process_loss%TYPE ,
542 x_return_status OUT NOCOPY VARCHAR2 ,
543 x_msg_count OUT NOCOPY NUMBER ,
544 x_msg_data OUT NOCOPY VARCHAR2
545 ) IS
546
547 l_process_loss NUMBER;
548 l_recipe_qty NUMBER;
549 l_ing_qty NUMBER;
550 l_uom VARCHAR2(4);
551 l_item_um VARCHAR2(3);
552 l_routing_class fm_rout_hdr.routing_class%TYPE;
553 l_routing_uom fm_rout_cls.UOM%TYPE;
554 l_routing_qty fm_rout_hdr.routing_qty%TYPE;
555 l_routing_planned_loss NUMBER;
556 l_routing_theo_loss NUMBER;
557 l_routing_prorate_factor NUMBER := 1;
558 l_recipe_prorate_factor NUMBER := 1;
559 l_qty NUMBER;
560 l_recipe_id NUMBER;
561 l_formula_id NUMBER;
562 l_routing_id NUMBER;
563 l_recipe_pp_loss NUMBER;
564 l_toq_return_status VARCHAR2(5) := 'S';
565 /* Bug 1683702 - Thomas Daniel */
566 l_validity_rule_id NUMBER;
567 l_validity_qty NUMBER;
568 l_recipe_theo_loss NUMBER;
569 l_validity_orgn NUMBER;
570 l_orgn_process_loss NUMBER;
571 l_validity_scale_factor NUMBER;
572 l_item_id NUMBER(10);
573 l_validity_um VARCHAR2(4);
574
575 CURSOR Get_recipe_cur(vRecipe_id NUMBER) IS
576 Select formula_id, routing_id, planned_process_loss
577 From gmd_recipes
578 Where recipe_id = vRecipe_id;
579
580 Cursor Rout_hdr_cur(vRouting_id NUMBER) IS
581 Select Routing_class, Routing_qty, Process_loss, routing_uom
582 From gmd_routings_b
583 Where routing_id = vRouting_id
584 and delete_mark = 0;
585
586 --Bug 6871738. Select ROUTING_CLASS_UOM instead of UOM.
587 Cursor Rout_cls_cur(vRouting_class fm_rout_hdr.routing_class%TYPE) IS
588 Select ROUTING_CLASS_UOM
589 From fm_rout_cls
590 Where routing_class = vRouting_class
591 and delete_mark = 0;
592
593 CURSOR process_loss_cur(vRouting_class VARCHAR2, qty NUMBER) IS
594 SELECT process_loss
595 FROM gmd_process_loss
596 WHERE routing_class = vRouting_class AND
597 (max_quantity >= qty OR
598 max_quantity IS NULL)
599 ORDER BY max_quantity;
600
601 CURSOR get_total_qty_cur(vFormula_id NUMBER) IS
602 SELECT total_output_qty, yield_uom
603 FROM fm_form_mst_b
604 WHERE formula_id = vFormula_id;
605
606 -- NPD Conv.
607 CURSOR Get_validity_cur (vValidity_Rule_Id NUMBER) IS
608 SELECT r.recipe_id, formula_id, routing_id, v.std_qty, v.organization_id, v.inventory_item_id, v.detail_uom
609 FROM gmd_recipes_b r, gmd_recipe_validity_rules v
610 WHERE r.recipe_id = v.recipe_id
611 AND v.recipe_validity_rule_id = vValidity_Rule_Id;
612
613 CURSOR Get_recipe_orgn_loss (vRecipe_id NUMBER, vOrgn_code_id VARCHAR2) IS
614 SELECT process_loss
615 FROM gmd_recipe_process_loss
616 WHERE recipe_id = vRecipe_id
617 AND organization_id = vOrgn_code_id;
618
619 BEGIN
620 IF (l_debug = 'Y') THEN
621 gmd_debug.log_initialize('CalcProcessLoss');
622 END IF;
623 /* Initialize the return status and the message list*/
624 x_return_status := 'S';
625 FND_MSG_PUB.initialize;
626
627 /* get the values from the record that is input */
628 l_qty := process_loss.qty;
629 l_recipe_id := process_loss.recipe_id;
630 l_formula_id := process_loss.formula_id;
631 l_routing_id := process_loss.routing_id;
632
633 /* Bug 1683702 - Thomas Daniel */
634 l_validity_rule_id := process_loss.validity_rule_id;
635
636 /* Condition when recipe_id is not passed */
637 IF ((NVL(l_recipe_id,0) > 0) AND (l_validity_rule_id IS NULL AND
638 l_formula_id IS NULL)) THEN
639 IF (l_debug = 'Y') THEN
640 gmd_debug.put_line(' Fetching the details using recipe id :'||l_recipe_id);
641 END IF;
642 /* Get the formula and routing information based on the recipe*/
643 OPEN Get_recipe_cur(l_Recipe_id);
644 FETCH Get_recipe_cur
645 INTO l_formula_id, l_routing_id, l_recipe_pp_loss;
646 CLOSE Get_recipe_cur;
647 l_item_id := process_loss.inventory_item_id;
648 ELSIF ((NVL(l_validity_rule_id, 0) > 0) AND (l_formula_id IS NULL)) THEN
649 IF (l_debug = 'Y') THEN
650 gmd_debug.put_line(' Fetching the details using validity rule id :' ||l_validity_rule_id);
651 END IF;
652 /* Get the formula and routing information based on the validity rule*/
653 OPEN Get_validity_cur(l_validity_rule_id);
654 FETCH Get_validity_cur
655 INTO l_recipe_id, l_formula_id, l_routing_id, l_validity_qty,
656 l_validity_orgn, l_item_id, l_validity_um;
657 CLOSE Get_validity_cur;
658 END IF;
659
660 IF process_loss.organization_id IS NOT NULL THEN
661 l_validity_orgn := process_loss.organization_id;
662 END IF;
663
664 /* If routing id is null then theo loss cannot be calculated. */
665 IF (l_routing_id IS NOT NULL) THEN
666 /* Check if routing class exists */
667 /* If no routing class exists then there is no theo process loss */
668 OPEN Rout_hdr_cur(l_Routing_id);
669 FETCH Rout_hdr_cur
670 INTO l_routing_class, l_routing_qty, l_routing_planned_loss, l_item_um;
671 IF (Rout_hdr_cur%NOTFOUND) THEN
672 l_routing_class := NULL;
673 /* TPL cannot be calculated */
674 x_return_status := 'E';
675 FND_MESSAGE.SET_NAME('GMD', 'GMD_TPL_WO_ROUT_CLS');
676 FND_MSG_PUB.Add;
677 END IF;
678 CLOSE Rout_hdr_cur;
679 IF (l_debug = 'Y') THEN
680 gmd_debug.put_line(' Rout Class:'||l_routing_class ||'Rout Qty:'||l_routing_qty ||' Planned Loss:'||l_routing_planned_loss);
681 END IF;
682 /* If Routing_class is not null then get its uom from fm_rout_cls table */
683 OPEN Rout_cls_cur(l_routing_class);
684 FETCH Rout_cls_cur INTO l_routing_uom;
685 IF (Rout_cls_cur%NOTFOUND) THEN
686 l_routing_uom := NULL;
687 x_return_status := 'E';
688 FND_MESSAGE.SET_NAME('GMD', 'GMD_TPL_WO_ROUT_UOM');
689 FND_MSG_PUB.Add;
690 END IF;
691 CLOSE Rout_cls_cur;
692 IF (l_debug = 'Y') THEN
693 gmd_debug.put_line(' Routing UOM : '||l_routing_uom);
694 END IF;
695 /* IF routing qty is provided as opposed to the
696 routing_qty stored in the database */
697 IF ((UPPER(Entity_type) = 'ROUTING') AND l_qty > 0) THEN
698 l_routing_qty := l_qty;
699 END IF;
700
701 /* Convert the routing qty from its uom to the routing class UOM */
702 /* Routing UOM needs to be convertible to the routing class UOM */
703 l_routing_qty := INV_CONVERT.inv_um_convert(item_id => 0
704 ,precision => 5
705 ,from_quantity => l_routing_qty
706 ,from_unit => l_item_um
707 ,to_unit => l_routing_uom
708 ,from_name => NULL
709 ,to_name => NULL);
710
711 IF (NVL(l_routing_qty,0) < 0) THEN
712 x_return_status := 'E';
713 FND_MESSAGE.SET_NAME('GMD', 'GMD_TPL_WO_ROUT_UOM');
714 FND_MSG_PUB.Add;
715 END IF;
716
717 OPEN process_loss_cur(l_routing_class,l_routing_qty);
718 FETCH process_loss_cur INTO l_routing_theo_loss;
719 IF (process_loss_cur%NOTFOUND) THEN
720 /* Theo process loss has not been defined. */
721 l_routing_theo_loss := NULL;
722 x_return_status := 'E';
723 FND_MESSAGE.SET_NAME('GMD', 'GMD_TPL_NOT_DEFINED');
724 FND_MSG_PUB.Add;
725 END IF;
726 CLOSE process_loss_cur;
727 IF (l_debug = 'Y') THEN
728 gmd_debug.put_line(' Routing Theoretical Loss:'||l_routing_theo_loss);
729 END IF;
730
731 /* Calculation for recipe theoretical and planned process losses */
732 IF (Upper(Entity_type) <> 'ROUTING') THEN
733 IF ((l_routing_theo_loss IS NOT NULL) AND (l_routing_theo_loss <> 0)) THEN
734 l_routing_prorate_factor := (l_routing_planned_loss/l_routing_theo_loss);
735 ELSE
736 /* under condition when l_routing_theo_loss is 0 or NULL
737 set the proration to 1 */
738 l_routing_prorate_factor := 1;
739 END IF;
740 IF (l_debug = 'Y') THEN
741 gmd_debug.put_line(' Routing pro rate factor :'||l_routing_prorate_factor);
742 END IF;
743 /* Get the total product qty and convert it to routing UOM */
744 /* Are we sure about the total product qty UOM??? */
745 /* Is it the main product UOM ? Or Is it the formula UOM */
746 /* Or is it the formula yield type? */
747 IF ((UPPER(Entity_type) = 'RECIPE') AND l_qty > 0) THEN
748 l_recipe_qty := l_qty;
749 END IF;
750
751 /* Check if the GMD:Yield type UOM can be convertible to the
752 routing class UOM */
753 IF (NVL(l_recipe_qty,0) = 0) THEN
754 OPEN get_total_qty_cur(l_formula_id);
755 FETCH get_total_qty_cur INTO l_recipe_qty, l_uom;
756 CLOSE get_total_qty_cur;
757 IF (l_recipe_qty IS NULL) THEN
758 l_recipe_qty := -20;
759 ELSE
760 l_recipe_qty := INV_CONVERT.inv_um_convert(item_id => 0
761 ,precision => 5
762 ,from_quantity => l_recipe_qty
763 ,from_unit => l_uom
764 ,to_unit => l_routing_uom
765 ,from_name => NULL
766 ,to_name => NULL);
767 END IF;
768 END IF;
769
770 /* If for some reason the yield_uom in formula table is not defined OR
771 the yield UOM is not convertible to routing class uom the
772 l_recipe_qty is -ve value. In such case, check if the each product
773 in this formula can be directly converted into the routing class UOM */
774 IF (l_recipe_qty < 0) THEN
775 Calculate_total_qty(l_formula_id, l_recipe_qty, l_ing_qty, l_routing_uom,
776 l_toq_return_status, x_msg_count, x_msg_data);
777 /* l_recipe_qty is NULL if the products uoms cannot be converted
778 to the routing class UOM */
779 END IF;
780
781 /* Get the theoretical/planned process loss for this recipe qty
782 from gmd_process_loss table Cannot calculate recipe theo/planned
783 loss if the recipe_qty is NULL or < 0 */
784 If (l_recipe_qty >= 0) THEN
785 open process_loss_cur(l_routing_class,l_recipe_qty);
786 fetch process_loss_cur INTO l_recipe_theo_loss;
787 IF (process_loss_cur%NOTFOUND) THEN
788 x_return_status := 'E';
789 FND_MESSAGE.SET_NAME('GMD', 'GMD_TPL_NOT_DEFINED');
790 FND_MSG_PUB.Add;
791 l_recipe_theo_loss := NULL;
792 l_recipe_pp_loss := NULL;
793 ELSE
794 /* After applying the routing loss proration */
795 IF l_recipe_pp_loss IS NULL THEN
796 l_recipe_pp_loss := l_recipe_theo_loss*l_routing_prorate_factor;
797 END IF;
798 END IF;
799 close process_loss_cur;
800 END IF; /* recipe qty is < 0 */
801 IF (l_debug = 'Y') THEN
802 gmd_debug.put_line(' Recipe Theoretical Loss1:'||l_recipe_theo_loss);
803 END IF;
804 /* Bug 1683702 - Thomas Daniel */
805 /* Calculation for validity theoretical and planned process losses* */
806 IF (Upper(Entity_type) <> 'RECIPE') THEN
807 /* We have to calculate the prorate factor which should be applied
808 on the theoretical loss calculated for the validity rule to
809 evaluate the planned process loss of the validity */
810 IF (NVL(l_recipe_theo_loss, 0) > 0) THEN
811 /* The planned process loss which should be used will also depend
812 on any process loss entered at the validity rule orgn level */
813 IF l_validity_orgn IS NOT NULL THEN
814 IF (l_debug = 'Y') THEN
815 gmd_debug.put_line(' Checking process loss for orgn:'||l_validity_orgn);
816 END IF;
817 OPEN Get_recipe_orgn_loss (l_recipe_id, l_validity_orgn);
818 FETCH Get_recipe_orgn_loss INTO l_orgn_process_loss;
819 CLOSE Get_recipe_orgn_loss;
820 IF l_orgn_process_loss IS NOT NULL THEN
821 l_recipe_pp_loss := l_orgn_process_loss;
822 END IF;
823 END IF; /* IF l_validity_orgn IS NOT NULL */
824 IF l_recipe_pp_loss IS NOT NULL THEN
825 l_recipe_prorate_factor := (l_recipe_pp_loss/l_recipe_theo_loss);
826 ELSE
827 l_recipe_prorate_factor := l_routing_prorate_factor;
828 END IF;
829 ELSE
830 /* under condition when l_recipe_theo_loss is 0 or NULL
831 set the proration to 1 */
832 l_recipe_prorate_factor := l_routing_prorate_factor;
833 END IF;
834 IF (l_debug = 'Y') THEN
835 gmd_debug.put_line(' Recipe prorate factor:'||l_recipe_prorate_factor);
836 END IF;
837 /* Lets check if we have to use the qty passed in or use the qty
838 in the database */
839 IF ((UPPER(Entity_type) = 'VALIDITY') AND l_qty > 0) THEN
840 l_validity_qty := l_qty;
841 END IF;
842
843 /* Lets check if we have to use the uom passed in or use the std um
844 in the database */
845 IF ((UPPER(Entity_type) = 'VALIDITY') AND process_loss.UOM IS NOT NULL) THEN
846 l_validity_um := process_loss.UOM;
847 END IF;
848
849 /* Lets get the scale factor between the validity std qty and
850 the formula product qty */
851 gmd_validity_rules.get_validity_scale_factor
852 ( p_recipe_id => l_recipe_id
853 ,p_item_id => l_item_id
854 ,p_std_qty => l_validity_qty
855 ,p_std_um => l_validity_um
856 ,x_scale_factor => l_validity_scale_factor
857 ,x_return_status => x_return_status);
858 IF (l_debug = 'Y') THEN
859 gmd_debug.put_line(' Scale factor :'||l_validity_scale_factor);
860 END IF;
861 /* Get the total product qty and convert it to routing UOM */
862 Calculate_total_qty(formula_id => l_formula_id,
863 x_product_qty => l_validity_qty,
864 x_ingredient_qty => l_ing_qty,
865 x_uom => l_routing_uom,
866 x_return_status => l_toq_return_status,
867 x_msg_count => x_msg_count,
868 x_msg_data => x_msg_data,
869 p_scale_factor => l_validity_scale_factor,
870 p_primaries => 'OUTPUTS');
871 IF (l_debug = 'Y') THEN
872 gmd_debug.put_line(' total qty:'||l_validity_qty
873 ||' rout class:'||l_routing_class
874 ||' recipe prorate:'||l_recipe_prorate_factor);
875 END IF;
876 /* Get the theoretical/planned process loss for this recipe qty */
877 /* from gmd_process_loss table Cannot calculate recipe theo/planned
878 loss if the recipe_qty is NULL or < 0 */
879 If (l_validity_qty >= 0) THEN
880 open process_loss_cur(l_routing_class,l_validity_qty);
881 fetch process_loss_cur INTO x_recipe_theo_loss;
882 IF (process_loss_cur%NOTFOUND) THEN
883 x_return_status := 'E';
884 FND_MESSAGE.SET_NAME('GMD', 'GMD_TPL_NOT_DEFINED');
885 FND_MSG_PUB.Add;
886 x_recipe_theo_loss := NULL;
887 x_process_loss := NULL;
888 ELSE
889 /* After applying the routing loss proration */
890 x_process_loss := x_recipe_theo_loss * l_recipe_prorate_factor;
891 END IF;
892 CLOSE process_loss_cur;
893 ELSE
894 /* May be recipe qty caould not calculated */
895 x_process_loss := NULL;
896 END IF; /* validity qty is < 0 */
897 IF (l_debug = 'Y') THEN
898 gmd_debug.put_line(' Theoretical:'||x_recipe_theo_loss||' Planned:'||x_process_loss);
899 END IF;
900 ELSE
901 /* entity type is recipe */
902 x_recipe_theo_loss := l_recipe_theo_loss;
903 x_process_loss := l_recipe_pp_loss;
904 END IF; /* Condition ends for validity losses calculation */
905 END IF; /* Condition ends for recipe losses calculation */
906
907
908 /* *** CALCULATION FOR BATCH PLANNED PROCESS LOSSES *************** */
909 /* If batch has called this routine then we also need to */
910 /* apply the recipe prorate factor */
911 /* In case of batch we expect the qty value to be provide */
912
913 IF (Entity_type NOT IN ('ROUTING','RECIPE','VALIDITY')) THEN
914 IF ((l_qty > 0) AND (x_process_loss IS NOT NULL)) THEN
915 If ((x_process_loss IS NOT NULL) OR (x_process_loss <> 0)) THEN
916 l_recipe_prorate_factor := (l_recipe_pp_loss/x_process_loss);
917 Else
918 l_recipe_prorate_factor := 1;
919 END IF;
920
921 OPEN process_loss_cur(l_routing_class,l_qty);
922 FETCH process_loss_cur INTO x_process_loss;
923 IF (process_loss_cur%NOTFOUND) THEN
924 /* Theo process loss has not been defined. */
925 x_process_loss := NULL;
926 ELSE
927 /* After applying the recipe loss proration */
928 x_process_loss := x_process_loss*l_recipe_prorate_factor;
929 END IF;
930 CLOSE process_loss_cur;
931 END IF; /* if qty was < 0 planned pp loss for batch is not calculated */
932 END IF; /* Condition ends for batch process loss calculation */
933
934 END IF; /* if routing id was null */
935
936 /* Finally we need to ensure that the recipe and batch planned losses
937 values are always returned */
938 IF ((x_process_loss IS NULL) AND
939 (upper(Entity_type) = 'VALIDITY' OR upper(Entity_type) = 'BATCH')) THEN
940 x_process_loss := l_recipe_pp_loss;
941 ELSIF ((x_process_loss IS NULL) AND (Upper(Entity_type) = 'ROUTING')) THEN
942 x_process_loss := l_routing_theo_loss;
943 END IF;
944
945 /* return the message count and data */
946 FND_MSG_PUB.COUNT_AND_GET (P_count => x_msg_count,
947 P_data => x_msg_data);
948
949 EXCEPTION
950 WHEN FND_API.g_exc_error THEN
951 NULL;
952 When Others then
953 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
954 FND_MESSAGE.SET_NAME('GMD', 'GMD_UNEXPECTED_ERROR');
955 FND_MESSAGE.SET_TOKEN('ERROR', sqlerrm);
956 FND_MSG_PUB.ADD;
957 FND_MSG_PUB.COUNT_AND_GET (P_count => x_msg_count,
958 P_data => x_msg_data);
959 END Calculate_Process_loss;
960
961
962 /* ====================================================================== */
963 /* Procedure: */
964 /* Calculate_Total_Qty */
965 /* */
966 /* DESCRIPTION: */
967 /* This PL/SQL procedure calculates the process loss value */
968 /* Return E if no status code exists */
969 /* Return S if status code is found */
970 /* */
971 /* Procedure returns the total product and ingredient qty */
972 /* The uom is that of FM_YIELD_TYPE UOM */
973 /* */
974 /* bug13909243 is fixed by passing the precision value as 9. */
975 /* ====================================================================== */
976 PROCEDURE Calculate_Total_Qty
977 ( formula_id IN GMD_RECIPES.Formula_id%TYPE ,
978 x_product_qty OUT NOCOPY NUMBER ,
979 x_ingredient_qty OUT NOCOPY NUMBER ,
980 x_uom IN OUT NOCOPY VARCHAR2 ,
981 x_return_status OUT NOCOPY VARCHAR2 ,
982 x_msg_count OUT NOCOPY NUMBER ,
983 x_msg_data OUT NOCOPY VARCHAR2 ,
984 p_scale_factor IN NUMBER ,
985 p_primaries IN VARCHAR2
986 ) IS
987
988 l_temp_qty NUMBER := 0;
989 l_um_type mtl_units_of_measure.uom_class%TYPE;
990 /*Bug 5667857 - Change the column from unit_of_measure to uom_code */
991 CURSOR get_sy_std_um(pUm_type mtl_units_of_measure.uom_class%TYPE) IS
992 SELECT uom_code
993 FROM mtl_units_of_measure
994 WHERE uom_class = pUm_type
995 AND base_uom_flag = 'Y';
996
997 CURSOR prod_um_cur(vFormula_id NUMBER) IS
998 SELECT detail_uom
999 FROM fm_matl_dtl
1000 WHERE line_no = 1
1001 AND line_type = 1
1002 AND formula_id = vFormula_id;
1003
1004 /* Bug 1683702 - Thomas Daniel */
1005 l_count NUMBER(5) DEFAULT 0;
1006 l_scale_tab GMD_COMMON_SCALE.scale_tab;
1007 l_material_tab GMD_COMMON_SCALE.scale_tab;
1008
1009 -- NPD Conv. Use inventory_iem_id and detail_uom instead of item_id and item_um
1010 CURSOR Get_formula_lines (vFormula_id NUMBER) IS
1011 SELECT line_no, line_type, inventory_item_id, qty, detail_uom, scale_type,
1012 contribute_yield_ind, scale_multiple, scale_rounding_variance,
1013 rounding_direction
1014 FROM fm_matl_dtl
1015 WHERE formula_id = vFormula_id
1016 ORDER BY line_type;
1017
1018 -- NPD Conv.
1019 l_orgn_id NUMBER;
1020 l_return_status VARCHAR2(10);
1021
1022 CURSOR get_formula_owner_orgn_id(vformula_id NUMBER) IS
1023 SELECT owner_organization_id
1024 FROM fm_form_mst_b
1025 WHERE formula_id = vformula_id;
1026
1027 BEGIN
1028
1029 /* Initialize the input and output qtys */
1030 x_product_qty := 0;
1031 x_ingredient_qty := 0;
1032 x_return_status := 'S';
1033
1034 -- NPD Conv. Get formula owner orgn. id
1035 OPEN get_formula_owner_orgn_id(formula_id);
1036 FETCH get_formula_owner_orgn_id INTO l_orgn_id;
1037 CLOSE get_formula_owner_orgn_id;
1038
1039 /* if the x_uom value is not paased as input parameter */
1040 /* then we use the GMD:Yield type std um as the formula uom */
1041 IF (x_uom IS NULL) THEN
1042 -- l_um_type := fnd_profile.value('FM_YIELD_TYPE');
1043
1044 -- NPD Conv. Use the new detch proc. to get FM_YIELD_TYPE
1045 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1046 P_parm_name => 'FM_YIELD_TYPE' ,
1047 P_parm_value => l_um_type ,
1048 X_return_status => l_return_status );
1049
1050 IF (l_um_type IS NOT NULL) then
1051 OPEN get_sy_std_um(l_um_type);
1052 FETCH get_sy_std_um INTO x_uom;
1053 IF get_sy_std_um%NOTFOUND then
1054 x_uom := NULL;
1055 End if;
1056 CLOSE get_sy_std_um;
1057 END IF;
1058 END IF;
1059
1060 /* If the GMD:Yield type is not defined use th emain product UOM */
1061 IF (x_uom IS NULL) THEN /* get the main prod um */
1062 /* Determine the main product UOM */
1063 OPEN prod_um_cur(formula_id);
1064 FETCH prod_um_cur INTO x_uom;
1065 IF prod_um_cur%NOTFOUND then
1066 x_uom := NULL;
1067 End if;
1068 CLOSE prod_um_cur;
1069 END IF;
1070
1071 /* If the x_uom is yet NULL then its an error */
1072 IF (x_uom IS NULL) Then
1073 FND_MESSAGE.SET_NAME('GMD', 'FM_SCALE_BAD_YIELD_TYPE');
1074 FND_MSG_PUB.Add;
1075 x_return_status := 'E';
1076 END IF;
1077
1078 /* Bug 1683702 - Thomas Daniel */
1079 FOR l_rec IN Get_formula_lines (formula_id) LOOP
1080 l_count := l_count + 1;
1081 l_scale_tab(l_count).line_no := l_rec.line_no;
1082 l_scale_tab(l_count).line_type := l_rec.line_type;
1083 l_scale_tab(l_count).inventory_item_id := l_rec.inventory_item_id; -- NPD Conv.
1084 l_scale_tab(l_count).qty := l_rec.qty;
1085 l_scale_tab(l_count).detail_uom := l_rec.detail_uom; -- NPD Conv.
1086 l_scale_tab(l_count).scale_type := l_rec.scale_type;
1087 l_scale_tab(l_count).contribute_yield_ind := l_rec.contribute_yield_ind;
1088 l_scale_tab(l_count).scale_multiple := l_rec.scale_multiple;
1089 l_scale_tab(l_count).scale_rounding_variance := l_rec.scale_rounding_variance;
1090 l_scale_tab(l_count).rounding_direction := l_rec.rounding_direction;
1091 END LOOP; /* FOR l_rec IN Get_formula_lines (l_formula_id) */
1092
1093 IF NVL(p_scale_factor, 1) = 1 THEN
1094 l_material_tab := l_scale_tab;
1095 ELSE
1096 -- NPD Conv. Pass orgn_id to the scale proc.
1097 GMD_COMMON_SCALE.scale (p_scale_tab => l_scale_tab
1098 ,p_orgn_id => l_orgn_id
1099 ,p_scale_factor => p_scale_factor
1100 ,p_primaries => p_primaries
1101 ,x_scale_tab => l_material_tab
1102 ,x_return_status => x_return_status);
1103 IF x_return_status <> FND_API.g_ret_sts_success THEN
1104 RAISE FND_API.g_exc_error;
1105 END IF;
1106 END IF; /* IF NVL(p_scale_factor, 1) = 1 */
1107
1108 /* Calculate the ingredient total quantities */
1109 FOR i IN 1..l_material_tab.COUNT LOOP
1110 IF l_material_tab(i).line_type = -1 AND
1111 /*Bug 2880618 - Thomas Daniel */
1112 /*Need to compute only for ingredients contributing to yield */
1113 l_material_tab(i).contribute_yield_ind = 'Y' THEN
1114 -- NPD Conv.
1115 l_temp_qty := INV_CONVERT.inv_um_convert( item_id => l_material_tab(i).inventory_item_id
1116 ,precision => 9
1117 ,from_quantity => l_material_tab(i).qty
1118 ,from_unit => l_material_tab(i).detail_uom
1119 ,to_unit => x_uom
1120 ,from_name => NULL
1121 ,to_name => NULL);
1122 IF l_temp_qty < 0 THEN
1123 x_ingredient_qty := NULL;
1124 x_return_status := 'Q';
1125 FND_MESSAGE.SET_NAME('GMD', 'GMD_CANNOT_CALC_TOQ');
1126 FND_MSG_PUB.Add;
1127 Exit;
1128 ELSE
1129 X_ingredient_qty := X_ingredient_qty + l_temp_qty;
1130 END IF;
1131 END IF;
1132 END LOOP;
1133
1134 /* Now let us calculate the product total quantities */
1135 FOR i IN 1..l_material_tab.COUNT LOOP
1136 IF l_material_tab(i).line_type IN (1,2) THEN
1137 -- NPD Conv.
1138 l_temp_qty := INV_CONVERT.inv_um_convert( item_id => l_material_tab(i).inventory_item_id
1139 ,precision => 9
1140 ,from_quantity => l_material_tab(i).qty
1141 ,from_unit => l_material_tab(i).detail_uom
1142 ,to_unit => x_uom
1143 ,from_name => NULL
1144 ,to_name => NULL);
1145 IF l_temp_qty < 0 THEN
1146 x_product_qty := NULL;
1147 x_return_status := 'Q';
1148 FND_MESSAGE.SET_NAME('GMD', 'GMD_CANNOT_CALC_TOQ');
1149 FND_MSG_PUB.Add;
1150 Exit;
1151 ELSE
1152 x_product_qty := x_product_qty + l_temp_qty;
1153 END IF;
1154 END IF;
1155 END LOOP;
1156
1157 FND_MSG_PUB.COUNT_AND_GET (P_count => x_msg_count,
1158 P_data => x_msg_data);
1159
1160 EXCEPTION
1161 WHEN FND_API.g_exc_error THEN
1162 x_return_status := 'Q';
1163 WHEN Others THEN
1164 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1165 FND_MESSAGE.SET_NAME('GMD', 'GMD_UNEXPECTED_ERROR');
1166 FND_MESSAGE.SET_TOKEN('ERROR', sqlerrm);
1167 FND_MSG_PUB.ADD;
1168 FND_MSG_PUB.COUNT_AND_GET (P_count => x_msg_count,
1169 P_data => x_msg_data);
1170
1171 END Calculate_Total_Qty;
1172
1173 /* ==================================================================== */
1174 /* Function */
1175 /* Get_Routing_Scale_Factor */
1176 /* */
1177 /* Description - */
1178 /* Routing qtys are scaled to a value proportional to the Recipe */
1179 /* Total Output Qty. This scale factor is the routing scale factor. */
1180 /* Return value : x_Routing_Scale_Factor NUMBER */
1181 /* */
1182 /* */
1183 /* */
1184 /* ==================================================================== */
1185 FUNCTION Get_Routing_Scale_Factor(vRecipe_id IN NUMBER,
1186 x_return_status OUT NOCOPY VARCHAR2,
1187 vFormula_Id IN NUMBER,
1188 vRouting_Id IN NUMBER)
1189 RETURN NUMBER IS
1190
1191 l_recipe_qty NUMBER ;
1192 x_Routing_Scale_factor NUMBER := 1 ;
1193
1194 CURSOR Cur_get_recipe IS
1195 SELECT formula_id, routing_id, calculate_step_quantity
1196 FROM gmd_recipes_b
1197 WHERE recipe_id = vRecipe_Id;
1198
1199 Cursor get_routrecipe_qty(pFormula_Id NUMBER, pRouting_Id NUMBER) IS
1200 Select rout.routing_qty rout_qty,
1201 form.total_output_qty recipe_qty,
1202 rout.routing_uom rout_uom,
1203 form.formula_id formula_id,
1204 form.yield_uom yield_typ_uom
1205 from fm_form_mst_b form,
1206 gmd_routings_b rout
1207 where form.formula_id = pformula_id and
1208 rout.routing_id = prouting_id ;
1209
1210 l_formula_id NUMBER;
1211 l_routing_id NUMBER;
1212 l_calculate_step_qty NUMBER(5);
1213 l_product_qty NUMBER;
1214 l_ingredient_qty NUMBER;
1215 l_uom mtl_units_of_measure.unit_of_measure%TYPE;
1216 l_return_status VARCHAR2(1);
1217 l_msg_count NUMBER;
1218 l_msg_data VARCHAR2(2000);
1219 BEGIN
1220 X_return_status := FND_API.g_ret_sts_success;
1221 IF vRecipe_Id IS NOT NULL THEN
1222 OPEN Cur_get_recipe;
1223 FETCH Cur_get_recipe INTO l_formula_id, l_routing_id, l_calculate_step_qty;
1224 CLOSE Cur_get_recipe;
1225 ELSE
1226 l_formula_id := vFormula_Id;
1227 l_routing_id := vRouting_Id;
1228 l_calculate_step_qty := 0;
1229 END IF;
1230 --Modified the following code for bug 13112823 by calling Calculate_Total_Qty first
1231 --if product qty is not > 0 then call INV_CONVERT.inv_um_convert.
1232 FOR rout_rec IN get_routrecipe_qty(l_formula_Id, l_routing_Id) LOOP
1233 IF(l_calculate_step_qty <> 1) THEN
1234 IF (rout_rec.rout_uom <> rout_rec.yield_typ_uom) THEN
1235 l_uom := rout_rec.rout_uom;
1236 Calculate_Total_Qty (Formula_Id => rout_rec.formula_id
1237 ,x_product_qty => l_product_qty
1238 ,x_ingredient_qty => l_ingredient_qty
1239 ,x_uom => l_uom
1240 ,x_return_status => l_return_status
1241 ,x_msg_count => l_msg_count
1242 ,x_msg_data => l_msg_data);
1243 IF l_product_qty > 0 THEN
1244 l_recipe_qty := l_product_qty;
1245 ELSE
1246 l_recipe_qty := INV_CONVERT.inv_um_convert(item_id => 0
1247 ,precision => 9
1248 ,from_quantity => rout_rec.recipe_qty
1249 ,from_unit => rout_rec.yield_typ_uom
1250 ,to_unit => rout_rec.rout_uom
1251 ,from_name => NULL
1252 ,to_name => NULL);
1253 IF l_recipe_qty < 0 THEN
1254 /*Bug 2722961 - Thomas Daniel */
1255 /*Changed the checking from return_status to l_product_qty */
1256 /*as the calculate_total_qty routine was passing back the */
1257 /*return status as 'Q' if the ingredient conversions were */
1258 /*not setup, though the product conversions have been setup */
1259 FND_MSG_PUB.INITIALIZE;
1260 FND_MESSAGE.SET_NAME ('GMD', 'GMD_ERR_CALC_ROUT_FACT');
1261 FND_MSG_PUB.add;
1262 x_return_status := 'W';
1263 RETURN 1;
1264 END IF;
1265 END IF;
1266 ELSE
1267 l_recipe_qty := rout_rec.recipe_qty;
1268 END IF;
1269 x_Routing_scale_factor := l_recipe_qty / rout_rec.rout_qty;
1270 ELSE
1271 /* ASQC flag is ON it implies that the recipe step qty have the rout qty
1272 factor is already incorporated */
1273 x_Routing_scale_factor := 1;
1274 END IF;
1275 END LOOP;
1276
1277 return x_Routing_Scale_factor;
1278
1279 /*commented the following code for bug 13112823
1280 IF (rout_rec.rout_uom <> rout_rec.yield_typ_uom) THEN
1281 l_recipe_qty := INV_CONVERT.inv_um_convert(item_id => 0
1282 ,precision => 5
1283 ,from_quantity => rout_rec.recipe_qty
1284 ,from_unit => rout_rec.yield_typ_uom
1285 ,to_unit => rout_rec.rout_uom
1286 ,from_name => NULL
1287 ,to_name => NULL);
1288
1289 This implies that the recipe qty uom and the routing qty uom are
1290 not of the same uom class
1291 so lets recalculate the recipe qty based on the routing uom
1292 IF l_recipe_qty < 0 THEN
1293 l_uom := rout_rec.rout_uom;
1294 Calculate_Total_Qty (Formula_Id => rout_rec.formula_id
1295 ,x_product_qty => l_product_qty
1296 ,x_ingredient_qty => l_ingredient_qty
1297 ,x_uom => l_uom
1298 ,x_return_status => l_return_status
1299 ,x_msg_count => l_msg_count
1300 ,x_msg_data => l_msg_data);
1301
1302 Bug 2722961 - Thomas Daniel
1303 Changed the checking from return_status to l_product_qty
1304 as the calculate_total_qty routine was passing back the
1305 return status as 'Q' if the ingredient conversions were
1306 not setup, though the product conversions have been setup
1307 IF l_product_qty > 0 THEN
1308 l_recipe_qty := l_product_qty;
1309 ELSE
1310 FND_MSG_PUB.INITIALIZE;
1311 FND_MESSAGE.SET_NAME ('GMD', 'GMD_ERR_CALC_ROUT_FACT');
1312 FND_MSG_PUB.add;
1313 x_return_status := 'W';
1314 RETURN 1;
1315 END IF;
1316 END IF;
1317 ELSE
1318 l_recipe_qty := rout_rec.recipe_qty;
1319 END IF;
1320 x_Routing_scale_factor := l_recipe_qty / rout_rec.rout_qty;
1321 ELSE
1322 ASQC flag is ON it implies that the recipe step qty have the rout qty
1323 factor is already incorporated
1324 x_Routing_scale_factor := 1;
1325
1326 END IF;
1327 END LOOP;
1328
1329 return x_Routing_Scale_factor;*/
1330
1331 END Get_Routing_Scale_Factor;
1332
1333
1334 /* =============================================================== */
1335 /* Procedure: */
1336 /* Calculate_Charges */
1337 /* */
1338 /* DESCRIPTION: */
1339 /* */
1340 /* Return E if no status code exists */
1341 /* Return S if status code is found */
1342 /* */
1343 /* Procedure returns the all Charges for a routing step */
1344 /* History : */
1345 /* Shyam 03/29/2002 Bug # 2284643: Added logic to scale the */
1346 /* routing step qty if the total routing step */
1347 /* is not equal to the Recipe qty */
1348 /* Shyam 04/20/2002 Create a new organization based capacity */
1349 /* cursor : Bug # 2272885 */
1350 /* =============================================================== */
1351
1352 PROCEDURE Calculate_Charges
1353 ( Batch_id IN NUMBER ,
1354 Recipe_id IN NUMBER ,
1355 Routing_id IN NUMBER ,
1356 VR_qty IN NUMBER ,
1357 Tolerance IN NUMBER ,
1358 Orgn_id IN NUMBER ,
1359 x_charge_tbl OUT NOCOPY charge_tbl ,
1360 x_return_status OUT NOCOPY VARCHAR2
1361 ) IS
1362
1363 /* Defining all variables */
1364 l_row NUMBER := 0 ;
1365 l_rout_scale_factor NUMBER := 1 ;
1366 l_step_tbl GMD_AUTO_STEP_CALC.step_rec_tbl;
1367 l_return_status VARCHAR2(1);
1368
1369 /* get capacities for resources that belong any orgn (generic) */
1370 CURSOR Step_qty_Cur(vRouting_id NUMBER) IS
1371 SELECT dtl.routingStep_id ,
1372 dtl.step_qty qty ,
1373 opr.process_qty_uom step_um
1374 FROM fm_rout_dtl dtl ,
1375 gmd_operations_b opr
1376 WHERE dtl.oprn_id = opr.oprn_id AND
1377 dtl.routing_id = vRouting_id
1378 ORDER BY dtl.routingStep_id;
1379
1380 CURSOR Get_Recipe_Step_Details(vRecipe_id NUMBER, vRoutingStep_id NUMBER) IS
1381 SELECT step_qty, mass_qty, mass_std_uom, volume_qty, volume_std_uom
1382 FROM gmd_recipe_routing_steps
1383 WHERE recipe_id = vRecipe_id AND
1384 routingstep_id = vRoutingStep_id;
1385
1386 BEGIN
1387 IF (l_debug = 'Y') THEN
1388 gmd_debug.log_initialize('CalcCharges');
1389 END IF;
1390 /* Initialize variables */
1391 /* Get the Routing Scale Factor */
1392 IF (l_debug = 'Y') THEN
1393 gmd_debug.put_line('In calc_charges proc initializing the variables ');
1394 END IF;
1395 x_return_status := FND_API.g_ret_sts_success;
1396
1397 /* Get the Routing Scale Factor */
1398 IF (l_debug = 'Y') THEN
1399 gmd_debug.put_line('In calc_charges proc - before calling routing scale fact '
1400 ||Recipe_id);
1401 END IF;
1402 l_rout_scale_factor := Get_Routing_Scale_Factor(vRecipe_Id => Recipe_id,
1403 x_return_status => l_return_status);
1404
1405
1406 IF (l_debug = 'Y') THEN
1407 gmd_debug.put_line('In calc_charges proc - after calling routing scale fact '
1408 ||l_rout_scale_factor||' '||l_return_status);
1409 END IF;
1410
1411 /* Step1: Get all step details based on the routing_id */
1412 FOR Step_qty_rec IN Step_qty_cur(Routing_id) LOOP
1413
1414 /* Get the routing step value */
1415 l_row := l_row + 1;
1416 l_step_tbl(l_row).step_id := Step_qty_rec.routingstep_id;
1417 l_step_tbl(l_row).step_qty := Step_qty_rec.qty * NVL(l_rout_scale_factor, 1);
1418 l_step_tbl(l_row).step_qty_uom := Step_qty_rec.step_um;
1419
1420 IF (l_debug = 'Y') THEN
1421 gmd_debug.put_line('In CalcCharges Proc - the step qty and its uom is '
1422 ||l_step_tbl(l_row).step_qty||' '||l_step_tbl(l_row).step_qty_uom);
1423 END IF;
1424
1425 /* At Recipe_Routing_Step_level, we store the step qty in three uom */
1426 /* 1) Step qty in its operating uom */
1427 /* 2) As, mass qty in mass reference uom */
1428 /* 3) As, volume qty in volume reference uom */
1429
1430 /* Check if the step qty has been overridden at recipe level */
1431 /* Table gmd_recipe_routing_steps stores step qtys that are overridden */
1432
1433 /* This cursor should return only one row */
1434 FOR Get_Recipe_Step_rec IN
1435 Get_Recipe_Step_Details(Recipe_id, Step_qty_rec.routingStep_id) LOOP
1436
1437 /* Get the recipe routing step qty */
1438 /* Use the overridden step qty */
1439 l_step_tbl(l_row).step_qty := Get_Recipe_Step_rec.step_qty;
1440 l_step_tbl(l_row).step_mass_qty := Get_Recipe_Step_rec.mass_qty;
1441 l_step_tbl(l_row).step_mass_uom := Get_Recipe_Step_rec.mass_std_uom;
1442 l_step_tbl(l_row).step_vol_qty := Get_Recipe_Step_rec.volume_qty;
1443 l_step_tbl(l_row).step_vol_uom := Get_Recipe_Step_rec.volume_std_uom;
1444
1445 IF (l_debug = 'Y') THEN
1446 gmd_debug.put_line('In CalcCharges Proc - the override step qty and its uom is '
1447 ||l_step_tbl(l_row).step_qty||' '||l_step_tbl(l_row).step_qty_uom);
1448 END IF;
1449
1450 END LOOP; /* End loop when routing step details exists at recipe level */
1451
1452 END LOOP;
1453
1454 /* We have the step quantities now lets calculate the charges */
1455 IF l_step_tbl.COUNT > 0 THEN
1456 GMD_COMMON_VAL.calculate_step_charges (p_recipe_id => Recipe_id
1457 ,p_tolerance => tolerance
1458 ,p_orgn_id => Orgn_id
1459 ,p_step_tbl => l_step_tbl
1460 ,x_charge_tbl => x_charge_tbl
1461 ,x_return_status => x_return_status);
1462 IF (l_debug = 'Y') THEN
1463 gmd_debug.put_line('In CalcCharges Proc - after calling Calc_step_chr '
1464 ||x_return_status);
1465 END IF;
1466 END IF; /* If their are rows in the step table */
1467
1468 END Calculate_Charges;
1469
1470
1471 /* =============================================================== */
1472 /* Procedure: */
1473 /* Calculate_Step_Charges */
1474 /* */
1475 /* DESCRIPTION: */
1476 /* */
1477 /* Return E if no status code exists */
1478 /* Return S if status code is found */
1479 /* */
1480 /* Procedure returns the all Charges for a routing step */
1481 /* History : */
1482 /* Thomas 07/23/2002 Bug # 1683702: Added this new procedure */
1483 /* To calculate the charges off the step */
1484 /* quantities passed in */
1485 /* RajaSekhar 02/04/2003 BUG#2365583 Added code to represent */
1486 /* whether the number of charges is defaulted */
1487 /* or calculated properly. */
1488 /* Kalyani 02/06/2006 Bug#5258672 Store max capacity in res UOM */
1489 /* =============================================================== */
1490
1491 PROCEDURE Calculate_Step_Charges
1492 ( P_recipe_id IN NUMBER ,
1493 P_tolerance IN NUMBER ,
1494 P_orgn_id IN NUMBER ,
1495 P_step_tbl IN GMD_AUTO_STEP_CALC.step_rec_tbl,
1496 x_charge_tbl OUT NOCOPY charge_tbl ,
1497 x_return_status OUT NOCOPY VARCHAR2
1498 ) IS
1499
1500 /* Defining all variables */
1501 l_charge INTEGER := 1 ;
1502 l_rough_charge NUMBER ;
1503 l_step_qty_uom VARCHAR2(4) ;
1504 l_max_capacity NUMBER ;
1505 l_max_capacity_old NUMBER ;
1506 l_capacity_uom VARCHAR2(4) ;
1507 l_row NUMBER := 1 ;
1508 m_counter NUMBER := 1 ;
1509 l_step_qty NUMBER ;
1510 l_def_charge VARCHAR2(1) ; --BUG#2365583 RajaSekhar
1511
1512 CURSOR Capacity_cur(vRecipe_id NUMBER, vRoutingstep_id NUMBER,
1513 vOrgn_id NUMBER) IS
1514 /*Bug 3679608 - Thomas Daniel */
1515 /*Modified the select statement to consider the generic resource only */
1516 /*if there are no plant specific overrides */
1517 SELECT MIN( NVL(orgnres.max_capacity, crres.max_capacity) ) max_cap,
1518 crres.capacity_um capacity_um
1519 FROM (SELECT resources, max_capacity, capacity_um, capacity_constraint
1520 FROM cr_rsrc_mst_b m
1521 WHERE capacity_constraint = 1
1522 AND NOT EXISTS (SELECT 1
1523 FROM cr_rsrc_dtl d
1524 WHERE d.organization_id = vOrgn_id
1525 AND d.resources = m.resources)
1526 UNION
1527 SELECT resources, max_capacity, capacity_um, capacity_constraint
1528 FROM cr_rsrc_dtl
1529 WHERE organization_id = vOrgn_id
1530 AND capacity_constraint = 1 ) crres ,
1531 (SELECT max_capacity, resources, routingstep_id
1532 FROM gmd_recipe_orgn_resources
1533 WHERE recipe_id = vRecipe_id
1534 AND organization_id = vOrgn_id) orgnres ,
1535 (SELECT oprn_id, routingStep_id
1536 FROM fm_rout_dtl
1537 WHERE routingstep_id = vRoutingstep_id ) dtl ,
1538 gmd_operation_resources res ,
1539 gmd_operation_activities act ,
1540 gmd_operations_b opr
1541 WHERE crres.resources = res.resources AND
1542 dtl.oprn_id = opr.oprn_id AND
1543 opr.oprn_id = act.oprn_id AND
1544 act.oprn_line_id = res.oprn_line_id AND
1545 (orgnres.routingstep_id IS NULL OR
1546 dtl.routingstep_id = orgnres.routingstep_id ) AND
1547 res.resources = orgnres.resources(+)
1548 GROUP BY crres.capacity_um;
1549
1550 BEGIN
1551 IF (l_debug = 'Y') THEN
1552 gmd_debug.put_line('In CalcCharges Step Proc - ');
1553 END IF;
1554 /* Initialize variables */
1555 x_return_status := FND_API.g_ret_sts_success;
1556 FOR i IN 1..P_step_tbl.COUNT LOOP
1557 /*Bug 3669132 - Thomas Daniel */
1558 /*Initialize default charge variable to identify if the code has entered the following for loop */
1559 l_def_charge := NULL;
1560 /* Let us fetch the min of the max capacities for all the resources belonging */
1561 /* to the current routing step and recipe */
1562 /* Step1: Get all resources details based on the routingStep_id */
1563 FOR Capacity_rec IN Capacity_cur(P_recipe_id,
1564 P_step_tbl(i).step_id,
1565 P_orgn_id) LOOP
1566 l_charge := 1;
1567
1568 /* Get the routing step value */
1569 l_step_qty := P_step_tbl(i).step_qty;
1570 l_step_qty_uom := P_step_tbl(i).step_qty_uom;
1571
1572 l_capacity_uom := Capacity_rec.capacity_um;
1573
1574 /* The min of max_capacity needs to derived for a step */
1575 /* Please remember if the max capacity is -ve */
1576 /* it probably means that the capcity conversion to step qty um was not set */
1577 l_max_capacity := INV_CONVERT.inv_um_convert(item_id => 0
1578 ,precision => 5
1579 ,from_quantity => nvl(Capacity_rec.max_cap,0)
1580 ,from_unit => Capacity_rec.capacity_um
1581 ,to_unit => l_step_qty_uom
1582 ,from_name => NULL
1583 ,to_name => NULL);
1584
1585 IF (l_debug = 'Y') THEN
1586 gmd_debug.put_line('In CalcCharges Step Proc - 1. the max cap and its uom '
1587 ||l_max_capacity||' ' ||l_capacity_uom);
1588 END IF;
1589
1590 IF (l_max_capacity < 0) THEN
1591 /* Set a message in our stack : the capacity conv has not occurred */
1592 x_return_status := 'E';
1593 FND_MESSAGE.SET_NAME('GMD', 'GMD_CANNOT_CONV_CAPACITY_UOM');
1594 FND_MSG_PUB.Add;
1595 END IF; /* when max cap is < 0 */
1596
1597 /* Get the step qty : */
1598 /* If the max capacity is yet -ve its becoz none of the capcity uom where */
1599 /* convertible to the process_um or step operation um */
1600
1601 /* Test if the capacity UOM can be converted into the Mass Qty UOM */
1602 /* It might be possible that the capacity uom is not convertible to the
1603 /* process_um but convertible to the mass_ref_um */
1604 IF (l_max_capacity < 0) THEN
1605 l_step_qty := P_step_tbl(i).step_mass_qty;
1606 l_step_qty_uom := P_step_tbl(i).step_mass_uom;
1607 l_max_capacity := INV_CONVERT.inv_um_convert(item_id => 0
1608 ,precision => 5
1609 ,from_quantity => Capacity_rec.max_cap
1610 ,from_unit => l_capacity_uom
1611 ,to_unit => l_step_qty_uom
1612 ,from_name => NULL
1613 ,to_name => NULL);
1614 IF (l_debug = 'Y') THEN
1615 gmd_debug.put_line('In CalcCharges Step Proc - 2. the max cap and its uom '
1616 ||l_max_capacity||' ' ||l_capacity_uom);
1617 END IF;
1618 END IF; /* when max cap is < 0 */
1619
1620 /* Test if the capacity UOM can be converted into the Volume Qty UOM */
1621 /* It might be possible that the capacity uom is not convertible to the
1622 /* process_um and mass_um but convertible to the volume_ref_um */
1623 IF (l_max_capacity < 0) THEN
1624 l_step_qty := P_step_tbl(i).step_vol_qty;
1625 l_step_qty_uom := P_step_tbl(i).step_vol_uom;
1626 l_max_capacity := INV_CONVERT.inv_um_convert(item_id => 0
1627 ,precision => 5
1628 ,from_quantity => Capacity_rec.max_cap
1629 ,from_unit => l_capacity_uom
1630 ,to_unit => l_step_qty_uom
1631 ,from_name => NULL
1632 ,to_name => NULL);
1633
1634 IF (l_debug = 'Y') THEN
1635 gmd_debug.put_line('In CalcCharges Step Proc - 3. the max cap and its uom '
1636 ||l_max_capacity||' ' ||l_capacity_uom);
1637 END IF;
1638 END IF; /* when max cap is < 0 */
1639
1640 IF (l_debug = 'Y') THEN
1641 gmd_debug.put_line('In CalcCharges Step Proc - 4. the max cap and step_qty '
1642 ||l_max_capacity||' ' ||l_step_qty);
1643 END IF;
1644 /* Calculations after step qty and UOM is found */
1645 IF ((l_step_qty > 0) AND (l_max_capacity > 0)) THEN
1646 /* If the remainder after dividing the step quantity by the
1647 l_max_capacity is greater than tolerance then we round up the
1648 value to the next interger else we truncate to an integer smaller than
1649 the ratio value
1650 */
1651 /* E.g if the step_qty is 110 and the l_max_capacity = 100
1652 the l_rough_charge is 1.1 and the remainder is 10. If the tolerance was
1653 15 (i.e > 10) then the charge would = 1.0 . However, if the tolerance is
1654 5 (i.e < 10) the charge would be = 2.0
1655 */
1656 l_rough_charge := l_step_qty /l_max_capacity;
1657
1658 IF ( MOD(l_step_qty, l_max_capacity) > p_tolerance ) THEN
1659 l_charge := CEIL(l_rough_charge);
1660 ELSE
1661 l_charge := TRUNC(l_rough_charge);
1662 END IF; /* when ratio is greater than tolerance */
1663 l_def_charge :='N'; --BUG#2365583 RajaSekhar
1664 ELSE
1665 l_charge := 1;
1666 l_def_charge :='Y'; --BUG#2365583 RajaSekhar
1667 END IF; /* End condition when step qty > 0 */
1668
1669 /* Resource usage is below capacity. Bug 2183650 */
1670 IF (l_charge <= 0 OR l_charge IS NULL) THEN
1671 l_charge := 1;
1672 END IF; /* when charge is 0 */
1673
1674 /* If Resource capacity is -ve - probably due to non UOM conv set it to NUll */
1675 IF (l_max_capacity < 0) THEN
1676 l_max_capacity := NULL;
1677 END IF;
1678
1679 /* Associate with charges and routing step details with out table */
1680 /* For each RoutingStep_id check for the max charge value */
1681 /* This condition occurs when each set has more than one resource with diff cap UOM */
1682
1683 /* Eliminate duplicate routingStepid rows */
1684 /* For each RoutingStep_id check for the max charge value and remove the
1685 one with lower charge */
1686 /* This condition occurs when each set has more than one resource with diff cap UOM */
1687
1688 IF (m_counter = 1) THEN
1689 x_charge_tbl(l_row).def_charge := l_def_charge; --BUG#2365583 RajaSekhar
1690 x_charge_tbl(l_row).charge := l_charge;
1691 x_charge_tbl(l_row).routingstep_id := P_step_tbl(i).step_id ;
1692 x_charge_tbl(l_row).max_capacity := l_max_capacity;
1693 --x_charge_tbl(l_row).capacity_uom := l_capacity_uom;
1694 /* bug # 2385711 - The uom to be returned is the step qty uom
1695 and not the capacity uom */
1696 x_charge_tbl(l_row).capacity_uom := P_step_tbl(i).step_qty_uom;
1697 m_counter := m_counter + 1;
1698 -- Bug#5258672 Store the capacity value in resource UOM
1699 x_charge_tbl(l_row).Max_Capacity_In_Res_UOM := Capacity_rec.max_cap;
1700 END IF;
1701
1702 IF (x_charge_tbl(l_row).routingstep_id = P_step_tbl(i).Step_id) THEN
1703 IF (x_charge_tbl(l_row).charge < l_charge) THEN
1704 x_charge_tbl(l_row).def_charge := l_def_charge; --BUG#2365583 RajaSekhar
1705 x_charge_tbl(l_row).charge := l_charge;
1706 x_charge_tbl(l_row).routingstep_id := P_step_tbl(i).step_id ;
1707 x_charge_tbl(l_row).max_capacity := l_max_capacity;
1708 --x_charge_tbl(l_row).capacity_uom := l_capacity_uom;
1709 /* bug # 2385711 - The uom to be returned is the step qty uom
1710 and not the capacity uom */
1711 x_charge_tbl(l_row).capacity_uom := P_step_tbl(i).step_qty_uom;
1712 -- Bug#5258672 Store the capacity value in resource UOM
1713 x_charge_tbl(l_row).Max_Capacity_In_Res_UOM := Capacity_rec.max_cap;
1714 END IF; /* when row in previous row is different from current values */
1715 ELSE
1716 l_row := l_row + 1;
1717 x_charge_tbl(l_row).def_charge := l_def_charge; --BUG#2365583 RajaSekhar
1718 x_charge_tbl(l_row).charge := l_charge;
1719 x_charge_tbl(l_row).routingstep_id := P_step_tbl(i).Step_id;
1720 x_charge_tbl(l_row).max_capacity := l_max_capacity;
1721 -- x_charge_tbl(l_row).capacity_uom := l_capacity_uom;
1722 /* bug # 2385711 - The uom to be returned is the step qty uom
1723 and not the capacity uom */
1724 x_charge_tbl(l_row).capacity_uom := P_step_tbl(i).step_qty_uom;
1725 -- Bug#5258672 Store the capacity value in resource UOM
1726 x_charge_tbl(l_row).Max_Capacity_In_Res_UOM := Capacity_rec.max_cap;
1727 END IF; /* When routingStep id are same */
1728
1729 END LOOP; /* End loop for main generic cursor */
1730 /*Bug 3669132 - Thomas Daniel */
1731 /*Added the following code to set the charge as 1 if no capacity constraint */
1732 /*resources are found for this routing step */
1733 IF l_def_charge IS NULL THEN
1734 /*Bug3679608 - Thomas Daniel*/
1735 /*Moved the row incremented up */
1736 IF m_counter <> 1 THEN
1737 l_row := l_row + 1;
1738 ELSE
1739 m_counter := m_counter + 1;
1740 END IF;
1741 x_charge_tbl(l_row).def_charge := 'Y';
1742 x_charge_tbl(l_row).charge := 1;
1743 x_charge_tbl(l_row).routingstep_id := P_step_tbl(i).Step_id;
1744 x_charge_tbl(l_row).max_capacity := NULL;
1745 x_charge_tbl(l_row).capacity_uom := P_step_tbl(i).step_qty_uom;
1746 END IF;
1747 END LOOP; /* FOR i IN 1..Step_tbl.COUNT */
1748
1749 END Calculate_Step_Charges;
1750
1751
1752
1753 FUNCTION UPDATE_ALLOWED(Entity VARCHAR2
1754 ,Entity_id NUMBER
1755 ,Update_Column_Name VARCHAR2 Default Null)
1756 RETURN BOOLEAN IS
1757 l_meaning GMD_STATUS.Meaning%TYPE ;
1758 l_desc GMD_STATUS.Description%TYPE ;
1759 l_return_status VARCHAR2(1);
1760 l_bool BOOLEAN := TRUE;
1761 l_status_code GMD_STATUS.Status_Code%TYPE;
1762 l_delete_mark NUMBER := 0;
1763
1764 l_resp_id NUMBER(15) DEFAULT FND_PROFILE.VALUE('RESP_ID');
1765 l_owner_orgn_id GMD_RECIPES_B.owner_organization_id%TYPE;
1766 l_dummy NUMBER := 0;
1767
1768 Cursor Check_recipe_orgn_access(vresp_id NUMBER, vOwner_orgn_id NUMBER) IS
1769 SELECT 1
1770 FROM org_access_view
1771 WHERE responsibility_id = vresp_id
1772 AND organization_id = vOwner_orgn_id;
1773
1774 BEGIN
1775 IF (l_debug = 'Y') THEN
1776 gmd_debug.put_line('In GMD_COMMON_VAL.UPDATE_ALLOWED - '
1777 ||' Entity = '||Entity||' and Entity id = '
1778 ||Entity_id);
1779 END IF;
1780 IF (Entity = 'FORMULA') THEN
1781 SELECT delete_mark, formula_status
1782 INTO l_delete_mark, l_status_code
1783 FROM fm_form_mst
1784 WHERE formula_id = Entity_id;
1785 ELSIF (Entity = 'RECIPE') THEN
1786
1787 SELECT delete_mark, recipe_status, owner_organization_id
1788 INTO l_delete_mark, l_status_code, l_owner_orgn_id
1789 FROM gmd_recipes_b
1790 WHERE recipe_id = Entity_id;
1791
1792 /* Check if user has access to this Recipe orgn */
1793 OPEN Check_recipe_orgn_access(l_resp_id, l_Owner_orgn_id);
1794 FETCH Check_recipe_orgn_access INTO l_dummy;
1795 IF Check_recipe_orgn_access%NOTFOUND THEN
1796 CLOSE Check_recipe_orgn_access;
1797 Return FALSE;
1798 END IF;
1799 CLOSE Check_recipe_orgn_access;
1800
1801 ELSIF (Entity = 'ROUTING') THEN
1802
1803 SELECT delete_mark, routing_status
1804 INTO l_delete_mark, l_status_code
1805 FROM fm_rout_hdr
1806 WHERE routing_id = Entity_id;
1807 ELSIF (Entity = 'OPERATION') THEN
1808 SELECT delete_mark, operation_status
1809 INTO l_delete_mark, l_status_code
1810 FROM gmd_operations
1811 WHERE oprn_id = Entity_id;
1812 ELSIF (Entity = 'VALIDITY') THEN
1813 SELECT delete_mark, validity_rule_status
1814 INTO l_delete_mark, l_status_code
1815 FROM gmd_recipe_validity_rules
1816 WHERE recipe_validity_rule_id = Entity_id;
1817 END IF;
1818
1819 Get_Status
1820 ( Status_code => l_status_code ,
1821 Meaning => l_meaning ,
1822 Description => l_desc ,
1823 x_return_status => l_return_status
1824 );
1825
1826 -- Added this condition to allow update of end dates for
1827 -- frozen Operations, Routings and Validity Rules
1828 /*--commented for Bug#6861398 start.
1829 IF ((l_status_code between 900 and 999)
1830 AND (Upper(Update_Column_Name) like '%END_DATE%')) THEN
1831 Return TRUE;
1832 ELSIF ((l_status_code between 200 and 299) OR (l_status_code >= 800) OR
1833 (l_status_code between 500 and 599) OR (l_delete_mark = 1)) THEN
1834 Return FALSE;
1835 */ --commented for Bug#6861398 end.
1836 /*Bug#6861398 Added Begin */
1837 IF ((l_status_code between 200 and 299) OR (l_status_code between 800 and 899) OR
1838 (l_status_code between 500 and 599) OR (l_delete_mark = 1)) THEN
1839 Return FALSE;
1840 /*Bug#6861398 Added End */
1841 ELSE
1842 Return TRUE;
1843 END IF;
1844
1845 return false;
1846 EXCEPTION
1847 WHEN NO_DATA_FOUND THEN
1848 RETURN TRUE;
1849 END UPDATE_ALLOWED;
1850
1851
1852 FUNCTION VERSION_CONTROL_STATE(Entity VARCHAR2, Entity_id NUMBER) RETURN VARCHAR2 IS
1853
1854 l_state VARCHAR2(32) := 'N';
1855 l_status VARCHAR2(30);
1856 l_version_enabled VARCHAR2(1) := 'N';
1857
1858 TYPE Status_ref_cur IS REF CURSOR;
1859 Status_cur Status_ref_cur;
1860
1861 CURSOR get_formula_owner_orgn_id(vformula_id NUMBER) IS
1862 SELECT owner_organization_id
1863 FROM fm_form_mst_b
1864 WHERE formula_id = vformula_id;
1865 CURSOR get_recipe_owner_orgn_id(vrecipe_id NUMBER) IS
1866 SELECT owner_organization_id
1867 FROM gmd_recipes_b
1868 WHERE recipe_id = vrecipe_id;
1869 CURSOR get_routing_owner_orgn_id(vrouting_id NUMBER) IS
1870 SELECT owner_organization_id
1871 FROM gmd_routings_b
1872 WHERE routing_id = vrouting_id;
1873 CURSOR get_operation_owner_orgn_id(voprn_id NUMBER) IS
1874 SELECT owner_organization_id
1875 FROM gmd_operations_b
1876 WHERE oprn_id = voprn_id;
1877
1878 CURSOR get_substitution_owner_orgn_id(vsub_id NUMBER) IS
1879 SELECT owner_organization_id
1880 FROM GMD_ITEM_SUBSTITUTION_HDR_B
1881 WHERE SUBSTITUTION_ID = vsub_id;
1882 l_orgn_id NUMBER;
1883 l_return_status VARCHAR2(10);
1884 BEGIN
1885
1886 -- Check for status that allow the version control
1887 -- e.g normally version control is set beyond
1888 -- status = 'Approved for gen use'
1889
1890 IF (Upper(Entity) = 'FORMULA') THEN
1891 OPEN get_formula_owner_orgn_id(entity_id);
1892 FETCH get_formula_owner_orgn_id INTO l_orgn_id;
1893 CLOSE get_formula_owner_orgn_id;
1894 OPEN Status_cur FOR
1895 Select f.formula_status, s.version_enabled
1896 From fm_form_mst f, gmd_status s
1897 Where f.formula_id = Entity_id
1898 And f.formula_status = s.status_code;
1899 FETCH Status_cur INTO l_status, l_version_enabled;
1900 ClOSE Status_cur;
1901
1902 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1903 P_parm_name => 'GMD_FORMULA_VERSION_CONTROL',
1904 P_parm_value => l_state ,
1905 X_return_status => l_return_status );
1906
1907 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1908 l_state := 'Y';
1909 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1910 l_state := 'O';
1911 ELSE
1912 l_state := 'N';
1913 END IF;
1914
1915 ELSIF (Upper(Entity) = 'RECIPE') THEN
1916 OPEN get_recipe_owner_orgn_id(entity_id);
1917 FETCH get_recipe_owner_orgn_id INTO l_orgn_id;
1918 CLOSE get_recipe_owner_orgn_id;
1919 OPEN Status_cur FOR
1920 Select r.recipe_status, s.version_enabled
1921 From gmd_recipes r, gmd_status s
1922 Where r.recipe_id = Entity_id
1923 And r.recipe_status = s.status_code;
1924 FETCH Status_cur INTO l_status, l_version_enabled;
1925 ClOSE Status_cur;
1926
1927 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1928 P_parm_name => 'GMD_RECIPE_VERSION_CONTROL' ,
1929 P_parm_value => l_state ,
1930 X_return_status => l_return_status );
1931
1932 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1933 l_state := 'Y';
1934 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1935 l_state := 'O';
1936 ELSE
1937 l_state := 'N';
1938 END IF;
1939
1940 ELSIF (Upper(Entity) = 'ROUTING') THEN
1941 OPEN get_routing_owner_orgn_id(entity_id);
1942 FETCH get_routing_owner_orgn_id INTO l_orgn_id;
1943 CLOSE get_routing_owner_orgn_id;
1944 OPEN Status_cur FOR
1945 Select r.routing_status, s.version_enabled
1946 From fm_rout_hdr r, gmd_status s
1947 Where r.routing_id = Entity_id
1948 And r.routing_status = s.status_code;
1949 FETCH Status_cur INTO l_status, l_version_enabled;
1950 ClOSE Status_cur;
1951
1952 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1953 P_parm_name => 'GMD_ROUTING_VERSION_CONTROL' ,
1954 P_parm_value => l_state ,
1955 X_return_status => l_return_status );
1956
1957 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1958 l_state := 'Y';
1959 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1960 l_state := 'O';
1961 ELSE
1962 l_state := 'N';
1963 END IF;
1964
1965 ELSIF (Upper(Entity) = 'OPERATION') THEN
1966 OPEN get_operation_owner_orgn_id(entity_id);
1967 FETCH get_operation_owner_orgn_id INTO l_orgn_id;
1968 CLOSE get_operation_owner_orgn_id;
1969 OPEN Status_cur FOR
1970 Select r.operation_status, s.version_enabled
1971 From gmd_operations r, gmd_status s
1972 Where r.oprn_id = Entity_id
1973 And r.operation_status = s.status_code;
1974 FETCH Status_cur INTO l_status, l_version_enabled;
1975 ClOSE Status_cur;
1976
1977 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1978 P_parm_name => 'GMD_OPERATION_VERSION_CONTROL' ,
1979 P_parm_value => l_state ,
1980 X_return_status => l_return_status );
1981
1982 /*SELECT TRIM(FND_PROFILE.VALUE('GMD_OPERATION_VERSION_CONTROL'))
1983 INTO l_state
1984 FROM sys.dual;*/
1985
1986 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1987 l_state := 'Y';
1988 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1989 l_state := 'O';
1990 ELSE
1991 l_state := 'N';
1992 END IF;
1993 ELSIF (Upper(Entity) = 'SUBSTITUTION') THEN -- Bug number 4479101
1994 OPEN get_substitution_owner_orgn_id(entity_id);
1995 FETCH get_substitution_owner_orgn_id INTO l_orgn_id;
1996 CLOSE get_substitution_owner_orgn_id;
1997
1998 OPEN Status_cur FOR
1999 Select r.substitution_status, s.version_enabled
2000 From gmd_item_substitution_hdr_b r, gmd_status s
2001 Where r.substitution_id = Entity_id
2002 And r.substitution_status = s.status_code;
2003 FETCH Status_cur INTO l_status, l_version_enabled;
2004 ClOSE Status_cur;
2005
2006 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
2007 P_parm_name => 'GMD_SUBS_VERSION_CONTROL' ,
2008 P_parm_value => l_state ,
2009 X_return_status => l_return_status );
2010
2011 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
2012 l_state := 'Y';
2013 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
2014 l_state := 'O';
2015 ELSE
2016 l_state := 'N';
2017 END IF;
2018
2019 ELSE
2020 l_state := 'N';
2021 END IF;
2022
2023 return l_state;
2024
2025 END VERSION_CONTROL_STATE;
2026
2027
2028 /*****************************************************************************
2029 * PROCEDURE
2030 * set_conc_program_Status
2031 *
2032 * DESCRIPTION
2033 * Sets the concurrent manager completion status
2034 *
2035 * INPUT PARAMETERS
2036 * p_errstat - Completion status, must be one of 'NORMAL', 'WARNING', or
2037 * 'ERROR'
2038 * p_errmsg - Completion message to be passed back
2039 *
2040 * HISTORY
2041 * 05-31-2001 Shyam Sitaraman Created
2042 *
2043 ******************************************************************************/
2044
2045 PROCEDURE set_conc_program_Status (
2046 p_errstat IN VARCHAR2,
2047 p_errmsg IN VARCHAR2
2048 )
2049 IS
2050 l_retval BOOLEAN;
2051 BEGIN
2052
2053 l_retval := fnd_concurrent.set_completion_status(p_errstat,p_errmsg);
2054
2055 END set_conc_program_Status;
2056
2057
2058 /* **********************************************************************
2059 * PROCEDURE
2060 * Run_status_update
2061 *
2062 * Parameter Input
2063 * pCalendar_code - Calendar code set in cm_cldr_dtl
2064 * pPeriod_code - Period code set in cm_cldr_dtl
2065 * pCost_mthd_code - Cost_mthd_code from cm_cldr_hdr
2066 *
2067 * Parameters Output
2068 *
2069 * p_errbuf Completion message to the Concurrent Manager
2070 * p_retcode Return code to the Concurrent Manager
2071 *
2072 *
2073 * Description
2074 *
2075 * Procedure is used by costing to update the GMD tables with frozen status.
2076 * This procedure is registered as a concurrent program
2077 * Whenever costing updates the period status in cm_cldr_dtl table
2078 * from 0 to 1 , the trigger fires and submits a request for a
2079 * concurrent job.
2080 *
2081 * History
2082 * 05/31/2001 Shyam Created
2083 * 11/14/2001 Shyam Added fm context after the cost update.
2084 * 12-FEB-2002 Shyam BUG # 2222882: Changes to Procedure GMD_RUN_STATUS_UPDATE.
2085 * The FORALL condition for BULK update was changed to
2086 * conventional FOR LOOP statement and makes update for each row.
2087 *
2088 * 12-FEB-2002 Shyam Created an NVL ststement for routing_id that is returned after
2089 * the recipe table is updated. Recipe can have null routing_ids and
2090 * returning a NULL routing_id into variable l_routing_id can cause issues.
2091 * 01-MAR-2002 Shyam Added validation for Run_status_Updtae to check if the cost method is 'Standard'
2092 * and period status is 1.
2093 * 01/16/2003 Shyam UPdate made on status that are not obsoleted or on-hold
2094 *
2095 * *********************************************************************** */
2096
2097 PROCEDURE Run_status_update( p_errbuf OUT NOCOPY VARCHAR2,
2098 p_retcode OUT NOCOPY VARCHAR2,
2099 pCalendar_code IN cm_cmpt_dtl.calendar_code%TYPE,
2100 pPeriod_code IN cm_cmpt_dtl.period_code%TYPE,
2101 pCost_mthd_code IN cm_cmpt_dtl.cost_mthd_code%TYPE) IS
2102
2103 x_return_status VARCHAR2(1) := 'S';
2104 l_Recipe_Id NUMBER;
2105 l_formula_Id NUMBER;
2106 l_routing_Id NUMBER;
2107 l_oprn_Id NUMBER;
2108 l_period_cnt NUMBER;
2109 l_cost_type NUMBER;
2110
2111
2112 TYPE VRtbl IS TABLE OF GMD_RECIPE_VALIDITY_RULES.Recipe_Validity_Rule_Id%TYPE;
2113 VRList VRtbl;
2114
2115 CURSOR FROZEN_EFF_CUR IS
2116 SELECT distinct(fmeff_id) fmeff_id from cm_cmpt_dtl
2117 WHERE Calendar_code = pCalendar_code AND
2118 Period_code = pPeriod_code AND
2119 Cost_mthd_code = pCost_mthd_code AND
2120 ROLLOVER_IND = 1;
2121
2122 CURSOR Get_Period_Status IS
2123 SELECT count(*) FROM cm_cldr_dtl
2124 WHERE Calendar_code = pCalendar_code AND
2125 Period_code = pPeriod_code AND
2126 period_status = 1;
2127
2128 CURSOR Get_Cost_type IS
2129 SELECT cost_type from cm_mthd_mst
2130 WHERE cost_mthd_code = pCost_mthd_code;
2131
2132 CURSOR Get_Recipe_id(vValidity_Rule_id NUMBER) IS
2133 SELECT recipe_id from gmd_recipe_validity_rules
2134 WHERE recipe_validity_rule_id = vValidity_Rule_id;
2135
2136 CURSOR Get_FmRout_id(vRecipe_id NUMBER) IS
2137 SELECT formula_id, routing_id From gmd_recipes_b
2138 WHERE recipe_id = vRecipe_id;
2139
2140 Standard_costing_exception EXCEPTION;
2141 Period_status_exception EXCEPTION;
2142
2143 BEGIN
2144 SAVEPOINT update_status;
2145
2146 OPEN Get_Period_Status;
2147 FETCH Get_Period_Status INTO l_period_cnt;
2148 IF ((Get_Period_Status%NOTFOUND) OR (l_period_cnt = 0)) THEN
2149 CLOSE Get_Period_Status;
2150 Raise Period_Status_exception;
2151 END IF;
2152 CLOSE Get_Period_Status;
2153
2154 OPEN Get_Cost_type;
2155 FETCH Get_Cost_type INTO l_cost_type;
2156 IF ((Get_Cost_type%NOTFOUND) OR (l_cost_type = 1)) THEN
2157 CLOSE Get_Cost_type;
2158 Raise Standard_costing_exception;
2159 END IF;
2160 CLOSE Get_Cost_Type;
2161
2162 OPEN FROZEN_EFF_CUR;
2163 FETCH FROZEN_EFF_CUR BULK COLLECT INTO VRList;
2164 CLOSE FROZEN_EFF_CUR;
2165
2166 IF (VRList.count > 0) THEN
2167
2168 FOR i IN 1 .. VRList.count LOOP
2169
2170 /* Update the VR - status field */
2171 Update gmd_recipe_validity_rules
2172 SET validity_rule_status = '900'
2173 WHERE recipe_validity_rule_id = VRList(i)
2174 AND to_number(validity_rule_status) < 800;
2175
2176 OPEN Get_Recipe_id(VRList(i));
2177 FETCH Get_Recipe_id INTO l_Recipe_id;
2178 CLOSE Get_Recipe_id;
2179
2180 /* Update the Recipe - status field */
2181 UPDATE gmd_recipes_b
2182 SET recipe_status = '900'
2183 WHERE recipe_id = l_Recipe_Id
2184 AND to_number(recipe_status) < 800;
2185
2186 OPEN Get_FmRout_id(l_recipe_id);
2187 FETCH Get_FmRout_id INTO l_formula_id, l_routing_id;
2188 CLOSE Get_FmRout_id;
2189
2190 /* Update the formula and routing status */
2191 UPDATE fm_form_mst_b
2192 SET formula_status = '900'
2193 WHERE formula_id = l_formula_id
2194 AND to_number(formula_status) < 800;
2195
2196 UPDATE gmd_routings_b
2197 SET routing_status = '900'
2198 WHERE routing_id = l_routing_id
2199 AND to_number(routing_status) < 800;
2200
2201 /* Update oprns status */
2202 IF (l_routing_id IS NOT NULL) THEN
2203 UPDATE gmd_operations_b
2204 SET operation_status = '900'
2205 WHERE oprn_id IN (SELECT oprn_id
2206 FROM fm_rout_dtl d
2207 WHERE routing_id = l_routing_id)
2208 AND to_number(operation_status) < 800;
2209 END IF;
2210 END LOOP;
2211
2212 ELSE /* when VRList count is <= 0 */
2213 p_retcode := 0;
2214 p_errbuf := NULL;
2215 set_conc_program_Status('NORMAL', 'Did not update the status on GMD tables');
2216
2217 END IF;
2218
2219 /* If o.k until here */
2220 p_retcode := 0;
2221 p_errbuf := NULL;
2222 set_conc_program_Status('NORMAL', NULL);
2223
2224 /* sets the context for formula security */
2225 gmd_p_fs_context.set_additional_attr;
2226
2227 EXCEPTION
2228 WHEN Standard_costing_exception THEN
2229 p_retcode := 3;
2230 p_errbuf := NULL;
2231 set_conc_program_Status('ERROR','Invalid cost method only standard cost methods are allowed ' );
2232 ROLLBACK to update_status;
2233 WHEN Period_status_exception THEN
2234 p_retcode := 3;
2235 p_errbuf := NULL;
2236 set_conc_program_Status('ERROR','Invalid period status only frozen periods are allowed' );
2237 ROLLBACK to update_status;
2238 WHEN OTHERS THEN
2239 p_retcode := 3;
2240 p_errbuf := NULL;
2241 set_conc_program_Status('ERROR',sqlerrm);
2242 ROLLBACK to update_status;
2243
2244 END Run_Status_Update;
2245 /* **********************************************************************
2246 * PROCEDURE
2247 * check_formula_item_access
2248 *
2249 * Parameter Input
2250 * pFormula_id Formula Id
2251 * pInventory_Item_ID Inventory Item Id
2252 * Parameters Output
2253 * X_return_status Return Status
2254 * S when the org access are true
2255 * E when known error
2256 * U when unknown error
2257 *
2258 *
2259 * Description
2260 *
2261 * Procedure is used to identify the organization's item access used
2262 * for the recipe, override organizations and validaity rules.
2263 *
2264 * History
2265 * 05-Dec-2005 KSHUKLA Created
2266 * 30-May-2006 Kalyani Changed the order of variables in cursor fetch.
2267 * 12-Jun-2006 Kalyani Added new parameter pRevision and code to check the orgn access
2268 * for the item revision.
2269 * 21-Apr-2008 RLNAGARA Bug 6982623 Added validation for formula orgn item access.
2270 * *********************************************************************** */
2271 PROCEDURE CHECK_FORMULA_ITEM_ACCESS(pFormula_id IN NUMBER,
2272 pInventory_Item_ID IN NUMBER,
2273 x_return_status OUT NOCOPY VARCHAR2,
2274 pRevision IN VARCHAR2) IS
2275
2276 --RLNAGARA start Bug 6982623 Added validation for formula item access
2277
2278 CURSOR Cur_formula_own (p_formula_id NUMBER, p_inventory_item_id NUMBER) IS
2279 SELECT fm.formula_no, fm.formula_vers, organization_code
2280 FROM fm_form_mst fm, mtl_parameters o
2281 WHERE formula_id =p_formula_id
2282 AND fm.owner_organization_id = o.organization_id
2283 AND formula_status < 1000
2284 AND NOT EXISTS (SELECT 1
2285 FROM mtl_system_items m
2286 WHERE inventory_item_id = p_inventory_item_id
2287 AND recipe_enabled_flag = 'Y'
2288 AND m.organization_id = fm.owner_organization_id);
2289
2290 CURSOR Cur_formula_own_revision (p_formula_id NUMBER, p_inventory_item_id NUMBER,p_revision VARCHAR2) IS
2291 SELECT fm.formula_no, fm.formula_vers, organization_code
2292 FROM fm_form_mst fm, mtl_parameters o
2293 WHERE formula_id =p_formula_id
2294 AND fm.owner_organization_id = o.organization_id
2295 AND formula_status < 1000
2296 AND NOT EXISTS (SELECT 1
2297 FROM mtl_system_items m, mtl_item_revisions mir
2298 WHERE m.inventory_item_id = p_inventory_item_id
2299 AND mir.revision = p_revision
2300 AND m.inventory_item_id = mir.inventory_item_id
2301 AND m.recipe_enabled_flag = 'Y'
2302 AND m.organization_id = fm.owner_organization_id
2303 AND mir.organization_id = m.organization_id);
2304
2305 --RLNAGARA end Bug 6982623
2306
2307 -- Lists the organization id for the recipe which are not owned
2308 -- By the owner organization id of formula
2309 CURSOR Cur_recipe_own (p_formula_id NUMBER, p_inventory_item_id NUMBER) IS
2310 SELECT recipe_no, recipe_version, organization_code
2311 FROM gmd_recipes_b r, mtl_parameters o
2312 WHERE formula_id = p_formula_id
2313 AND r.owner_organization_id = o.organization_id
2314 AND recipe_status < 1000
2315 AND NOT EXISTS (SELECT 1
2316 FROM mtl_system_items m
2317 WHERE inventory_item_id = p_inventory_item_id
2318 AND recipe_enabled_flag = 'Y'
2319 AND m.organization_id = r.owner_organization_id);
2320 -- Bug 5237351 added
2321 CURSOR Cur_recipe_own_revision (p_formula_id NUMBER, p_inventory_item_id NUMBER,p_revision VARCHAR2) IS
2322 SELECT recipe_no, recipe_version, organization_code
2323 FROM gmd_recipes_b r, mtl_parameters o
2324 WHERE formula_id = p_formula_id
2325 AND r.owner_organization_id = o.organization_id
2326 AND recipe_status < 1000
2327 AND NOT EXISTS (SELECT 1
2328 FROM mtl_system_items m, mtl_item_revisions mir
2329 WHERE m.inventory_item_id = p_inventory_item_id
2330 AND mir.revision = p_revision
2331 AND m.inventory_item_id = mir.inventory_item_id
2332 AND m.recipe_enabled_flag = 'Y'
2333 AND m.organization_id = r.owner_organization_id
2334 AND mir.organization_id = m.organization_id
2335 );
2336
2337 -- Cursors to get the recipe over rides for a recipe id
2338 CURSOR Cur_recipe_override(p_formula_id number, p_inventory_item_id number) IS
2339 select r.recipe_no, r.recipe_version, o.organization_code
2340 from gmd_recipe_process_loss rpl, gmd_recipes_b r, mtl_parameters o
2341 where r.recipe_id = rpl.recipe_id
2342 AND r.formula_id = p_formula_id
2343 AND r.owner_organization_id <> rpl.organization_id
2344 AND rpl.organization_id = o.organization_id
2345 AND r.recipe_status < 1000
2346 AND NOT EXISTS (SELECT 1
2347 FROM mtl_system_items m
2348 WHERE inventory_item_id = p_inventory_item_id
2349 AND recipe_enabled_flag = 'Y'
2350 AND m.organization_id = rpl.organization_id);
2351
2352 -- Bug 5237351 added
2353 CURSOR Cur_recipe_override_revision(p_formula_id number, p_inventory_item_id number,p_revision VARCHAR2) IS
2354 select r.recipe_no, r.recipe_version, o.organization_code
2355 from gmd_recipe_process_loss rpl, gmd_recipes_b r, mtl_parameters o
2356 where r.recipe_id = rpl.recipe_id
2357 AND r.formula_id = p_formula_id
2358 AND r.owner_organization_id <> rpl.organization_id
2359 AND rpl.organization_id = o.organization_id
2360 AND r.recipe_status < 1000
2361 AND NOT EXISTS (SELECT 1
2362 FROM mtl_system_items m, mtl_item_revisions mir
2363 WHERE m.inventory_item_id = p_inventory_item_id
2364 AND mir.revision = p_revision
2365 AND m.inventory_item_id = mir.inventory_item_id
2366 AND m.recipe_enabled_flag = 'Y'
2367 AND m.organization_id = rpl.organization_id
2368 AND mir.organization_id = m.organization_id);
2369
2370 -- Cursor to get the validity rules for the recipes
2371 CURSOR Cur_recipe_validity(p_formula_id number,p_inventory_item_id number) IS
2372 select o.organization_code,r.recipe_no, r.recipe_version
2373 from gmd_recipe_validity_rules rvr, gmd_recipes_b r, mtl_parameters o
2374 where r.recipe_id = rvr.recipe_id
2375 and r.formula_id = p_formula_id
2376 and o.organization_id = rvr.organization_id
2377 AND rvr.organization_id <> r.owner_organization_id
2378 AND r.recipe_status < 1000
2379 AND rvr.validity_rule_status < 1000
2380 AND NOT EXISTS (SELECT 1
2381 FROM mtl_system_items m
2382 WHERE inventory_item_id = p_inventory_item_id
2383 AND recipe_enabled_flag = 'Y'
2384 AND m.organization_id = rvr.organization_id);
2385 -- Bug 5237351 added
2386 CURSOR Cur_recipe_validity_revision(p_formula_id number,p_inventory_item_id number,p_revision VARCHAR2) IS
2387 select o.organization_code,r.recipe_no, r.recipe_version
2388 from gmd_recipe_validity_rules rvr, gmd_recipes_b r, mtl_parameters o
2389 where r.recipe_id = rvr.recipe_id
2390 and r.formula_id = p_formula_id
2391 and o.organization_id = rvr.organization_id
2392 AND r.recipe_status < 1000
2393 AND rvr.validity_rule_status < 1000
2394 AND NOT EXISTS (SELECT 1
2395 FROM mtl_system_items m, mtl_item_revisions mir
2396 WHERE m.inventory_item_id = p_inventory_item_id
2397 AND mir.revision = p_revision
2398 AND m.inventory_item_id = mir.inventory_item_id
2399 AND m.recipe_enabled_flag = 'Y'
2400 AND m.organization_id = rvr.organization_id
2401 AND mir.organization_id = m.organization_id
2402 );
2403 -- Bug 5237351 added
2404 CURSOR Cur_item_rev_ctl(v_item_id NUMBER) IS
2405 select revision_qty_control_code
2406 from mtl_system_items_b
2407 where inventory_item_id = v_item_id;
2408
2409 l_rev_ctl number; -- Bug 5237351 added
2410 l_org_id number;
2411 l_organization_code varchar2(3);
2412 l_formula_no varchar2(32);
2413 l_formula_vers number; --RLNAGARA B6982623
2414 l_recipe_no varchar2(32);
2415 l_recipe_version number;
2416 X_global_return_status varchar2(1) := FND_API.g_ret_sts_success;
2417
2418 VALIDATION_FAIL EXCEPTION;
2419 NO_FORMULA EXCEPTION;
2420
2421 BEGIN
2422 --
2423 -- Find the formula no for the formula id
2424 --
2425 -- Check for the organization access to the formula
2426 IF pFormula_id IS NULL THEN
2427 RAISE NO_FORMULA;
2428
2429 END IF;
2430 -- Bug 5237351 added
2431 OPEN Cur_item_rev_ctl(pInventory_item_id);
2432 FETCH Cur_item_rev_ctl INTO l_rev_ctl;
2433 CLOSE Cur_item_rev_ctl;
2434
2435 --RLNAGARA start Bug 6982623 Added validation for formula item access
2436
2437 OPEN Cur_formula_own (pFormula_id, pInventory_item_id);
2438 FETCH Cur_formula_own INTO l_formula_no, l_formula_vers, l_organization_code;
2439 IF Cur_formula_own%FOUND THEN
2440 CLOSE Cur_formula_own;
2441 FND_MESSAGE.set_name('GMD','GMD_FORM_OWNORG_NO_ACCESS');
2442 FND_MESSAGE.set_token('FORMULA_NO',l_formula_no);
2443 FND_MESSAGE.set_token('FORMULA_VERSION',l_formula_vers);
2444 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2445 fnd_msg_pub.ADD;
2446 X_return_status := FND_API.g_ret_sts_error;
2447 RAISE VALIDATION_FAIL;
2448 END IF;
2449 CLOSE Cur_formula_own;
2450
2451 IF l_rev_ctl = 2 and pRevision IS NOT NULL THEN
2452 OPEN Cur_formula_own_revision (pFormula_id, pInventory_item_id,pRevision);
2453 FETCH Cur_formula_own_revision INTO l_formula_no, l_formula_vers, l_organization_code;
2454 IF Cur_formula_own_revision%FOUND THEN
2455 CLOSE Cur_formula_own_revision;
2456 FND_MESSAGE.set_name('GMD','GMD_FORM_REV_OWNORG_NO_ACCESS');
2457 FND_MESSAGE.set_token('FORMULA_NO',l_formula_no);
2458 FND_MESSAGE.set_token('FORMULA_VERSION',l_formula_vers);
2459 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2460 fnd_msg_pub.ADD;
2461 X_return_status := FND_API.g_ret_sts_error;
2462 RAISE VALIDATION_FAIL;
2463 END IF;
2464 CLOSE Cur_formula_own_revision;
2465 END IF;
2466
2467 --RLNAGARA end Bug 6982623
2468
2469 OPEN Cur_recipe_own (pFormula_id, pInventory_item_id);
2470 FETCH Cur_recipe_own INTO l_recipe_no, l_recipe_version, l_organization_code;
2471 IF Cur_recipe_own%FOUND THEN
2472 CLOSE Cur_recipe_own;
2473 FND_MESSAGE.set_name('GMD','GMD_OWNER_ORG_NOT_ACCESSIBLE');
2474 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2475 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2476 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2477 fnd_msg_pub.ADD;
2478 X_return_status := FND_API.g_ret_sts_error;
2479 RAISE VALIDATION_FAIL;
2480 END IF;
2481 CLOSE Cur_recipe_own;
2482 -- Bug 5237351 added
2483 IF l_rev_ctl = 2 and pRevision IS NOT NULL THEN
2484 OPEN Cur_recipe_own_revision (pFormula_id, pInventory_item_id,pRevision);
2485 FETCH Cur_recipe_own_revision INTO l_recipe_no, l_recipe_version, l_organization_code;
2486 IF Cur_recipe_own_revision%FOUND THEN
2487 CLOSE Cur_recipe_own_revision;
2488 FND_MESSAGE.set_name('GMD','GMD_REV_OWNORG_NOT_ACCESSIBLE');
2489 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2490 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2491 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2492 fnd_msg_pub.ADD;
2493 X_return_status := FND_API.g_ret_sts_error;
2494 RAISE VALIDATION_FAIL;
2495 END IF;
2496 CLOSE Cur_recipe_own_revision;
2497 END IF;
2498 -- Check the organization access for the override organizations
2499 OPEN Cur_recipe_override (pFormula_id, pInventory_item_id);
2500 -- Bug 5237126 MK Changed the order of variables.
2501 FETCH Cur_recipe_override INTO l_recipe_no, l_recipe_version, l_organization_code;
2502 IF Cur_recipe_override%FOUND THEN
2503 CLOSE Cur_recipe_override;
2504 FND_MESSAGE.set_name('GMD','GMD_OVERRIDE_ORG_NOT_ACCESSIBL');
2505 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2506 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2507 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2508 fnd_msg_pub.ADD;
2509 X_return_status := FND_API.g_ret_sts_error;
2510 RAISE VALIDATION_FAIL;
2511 END IF;
2512 CLOSE Cur_recipe_override;
2513 -- Bug 5237351 added
2514 IF l_rev_ctl = 2 and pRevision IS NOT NULL THEN
2515 OPEN Cur_recipe_override_revision (pFormula_id, pInventory_item_id, pRevision);
2516 FETCH Cur_recipe_override_revision INTO l_recipe_no, l_recipe_version, l_organization_code;
2517 IF Cur_recipe_override_revision%FOUND THEN
2518 CLOSE Cur_recipe_override_revision;
2519 FND_MESSAGE.set_name('GMD','GMD_REV_OVERORG_NOT_ACCESSIBL');
2520 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2521 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2522 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2523 fnd_msg_pub.ADD;
2524 X_return_status := FND_API.g_ret_sts_error;
2525 RAISE VALIDATION_FAIL;
2526 END IF;
2527 CLOSE Cur_recipe_override_revision;
2528 END IF;
2529 OPEN Cur_recipe_validity (pFormula_id, pInventory_item_id);
2530 FETCH Cur_recipe_validity INTO l_organization_code, l_recipe_no, l_recipe_version;
2531 IF Cur_recipe_validity%FOUND THEN
2532 CLOSE Cur_recipe_validity;
2533 FND_MESSAGE.set_name('GMD','GMD_VALIDITY_OWNER_ORG_NOT_ACC');
2534 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2535 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2536 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2537 fnd_msg_pub.ADD;
2538 X_return_status := FND_API.g_ret_sts_error;
2539 RAISE VALIDATION_FAIL;
2540 END IF;
2541 CLOSE Cur_recipe_validity;
2542 -- Bug 5237351 added
2543 IF l_rev_ctl = 2 and pRevision IS NOT NULL THEN
2544 OPEN Cur_recipe_validity_revision (pFormula_id, pInventory_item_id, pRevision);
2545 FETCH Cur_recipe_validity_revision INTO l_organization_code, l_recipe_no, l_recipe_version;
2546 IF Cur_recipe_validity_revision%FOUND THEN
2547 CLOSE Cur_recipe_validity_revision;
2548 FND_MESSAGE.set_name('GMD','GMD_REV_VALIDITY_ORG_NOT_ACC');
2549 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2550 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2551 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2552 fnd_msg_pub.ADD;
2553 X_return_status := FND_API.g_ret_sts_error;
2554 RAISE VALIDATION_FAIL;
2555 END IF;
2556 CLOSE Cur_recipe_validity_revision;
2557 END IF;
2558
2559 -- Final Return Status of the API
2560 x_return_status := FND_API.G_RET_STS_SUCCESS;
2561 EXCEPTION
2562 WHEN VALIDATION_FAIL THEN
2563 x_return_status := FND_API.G_RET_STS_ERROR;
2564 WHEN NO_FORMULA THEN
2565 x_return_status := FND_API.G_RET_STS_SUCCESS;
2566
2567 WHEN OTHERS THEN
2568 X_return_status := FND_API.g_ret_sts_unexp_error;
2569
2570 END check_formula_item_access;
2571
2572 -- Kapil ME Auto-Prod :Bug# 5716318
2573 /* Api start of comments
2574 +============================================================================
2575 | PROCEDURE NAME
2576 | CALCULATE_TOTAL_PRODUCT_QTY
2577 |
2578 | DESCRIPTION
2579 | Procedure to calculate Product Qty autmatically.
2580 |
2581 | INPUT PARAMETERS
2582 | pFormula_id NUMBER
2583 |
2584 | OUTPUT PARAMETERS
2585 | x_msg_data VARCHAR2
2586 | x_return_status VARCHAR2
2587 | x_msg_count NUMBER
2588 |
2589 | HISTORY
2590 | 05-FEB-2007 Kapil M Bug# 5716318 Created.
2591 |
2592 +=============================================================================
2593 Api end of comments
2594 */
2595 PROCEDURE Calculate_Total_Product_Qty ( p_formula_id IN gmd_recipes.formula_id%TYPE,
2596 x_return_status OUT NOCOPY VARCHAR2,
2597 x_msg_count OUT NOCOPY NUMBER,
2598 x_msg_data OUT NOCOPY VARCHAR2) IS
2599
2600 -- Definition of variables
2601 l_auto_calc VARCHAR2(1) := 'N';
2602 l_count NUMBER (5) DEFAULT 0;
2603 l_material_tab gmd_common_scale.scale_tab;
2604 l_uom VARCHAR2(30);
2605 l_conv_uom VARCHAR2(30);
2606 l_temp_qty NUMBER := 0;
2607
2608 l_ingredient_qty NUMBER := 0;
2609 l_by_product_qty NUMBER := 0;
2610 l_qty_touse NUMBER := 0;
2611 l_prod_cnt NUMBER := 0;
2612 l_prod_ratio NUMBER := 1;
2613 l_one_prodqty NUMBER;
2614 l_prod_fix_cnt NUMBER := 0;
2615 l_prod_fix_qty NUMBER := 0;
2616 l_prod_prop_cnt NUMBER := 0;
2617 l_prod_prop_qty NUMBER := 0;
2618 lhdrqty NUMBER := 0;
2619 l_different_uom VARCHAR2 (1) := 'N';
2620 l_return_status VARCHAR2(1);
2621 p_orgn_id NUMBER;
2622 l_yield_type VARCHAR2(30);
2623 l_uom_class VARCHAR2(10);
2624 l_common_uom_class VARCHAR2(10);
2625
2626 CANNOT_CONVERT EXCEPTION;
2627
2628 --Bug 7243526. Changed orig_uom and cov_uom from VARCHAR2(4) to VARCHAR2(30)
2629 TYPE temp_prod_qty_rec IS RECORD (
2630 inventory_item_id NUMBER,
2631 orig_qty NUMBER,
2632 orig_uom VARCHAR2(30),
2633 cov_qty NUMBER,
2634 cov_uom VARCHAR2(30),
2635 line_no NUMBER,
2636 prod_percent NUMBER
2637 );
2638 TYPE temp_prod_tbl IS TABLE OF temp_prod_qty_rec
2639 INDEX BY BINARY_INTEGER;
2640
2641 temp_prod_tbl1 temp_prod_tbl;
2642 -- Cursor Definitions
2643
2644 CURSOR Cur_get_formula_org IS
2645 SELECT OWNER_ORGANIZATION_ID
2646 FROM FM_FORM_MST
2647 WHERE formula_id = p_formula_id;
2648
2649 CURSOR get_formula_lines (vformula_id NUMBER) IS
2650 SELECT line_no, line_type, inventory_item_id, qty, DETAIL_UOM, scale_type,
2651 contribute_yield_ind, scale_multiple, scale_rounding_variance,
2652 rounding_direction , prod_percent
2653 FROM fm_matl_dtl
2654 WHERE formula_id = p_formula_id
2655 AND contribute_yield_ind = 'Y' /* Added in Bug No.6314028 */
2656 ORDER BY line_type;
2657
2658 CURSOR get_unit_of_measure(v_yield_type VARCHAR2) IS
2659 SELECT uom_code
2660 FROM mtl_units_of_measure
2661 WHERE uom_class = v_yield_type
2662 AND base_uom_flag = 'Y';
2663
2664 BEGIN
2665
2666 x_return_status := FND_API.G_RET_STS_SUCCESS;
2667 FND_MSG_PUB.initialize;
2668
2669 -- Check ORganization Parameters
2670 OPEN Cur_get_formula_org;
2671 FETCH Cur_get_formula_org INTO p_orgn_id;
2672 CLOSE Cur_get_formula_org;
2673 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => p_orgn_id ,
2674 P_parm_name => 'GMD_AUTO_PROD_CALC' ,
2675 P_parm_value => l_auto_calc ,
2676 X_return_status => x_return_status );
2677
2678 IF l_auto_calc = 'Y' THEN -- Perform Auto Calculation
2679
2680 -- Get the Yield type UOM - NPD Convergence
2681 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => p_orgn_id ,
2682 P_parm_name => 'FM_YIELD_TYPE' ,
2683 P_parm_value => l_yield_type ,
2684 X_return_status => x_return_status );
2685 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
2686 RETURN;
2687 END IF;
2688
2689 /* Bug no.7145922 - Start */
2690 IF (l_yield_type IS NOT NULL) THEN
2691 OPEN get_unit_of_measure(l_yield_type);
2692 FETCH get_unit_of_measure INTO l_uom;
2693 IF get_unit_of_measure%NOTFOUND THEN
2694 l_uom := NULL;
2695 END IF;
2696 CLOSE get_unit_of_measure;
2697 END IF;
2698 /* Bug no.7145922 - End */
2699
2700 /* Populate a local pl/sql table that will be iterated for further processings. */
2701 FOR l_rec IN get_formula_lines (p_formula_id)
2702 LOOP
2703 l_count := l_count + 1;
2704
2705 IF NVL (l_uom, l_rec.detail_uom) <> l_rec.detail_uom
2706 THEN
2707 l_different_uom := 'Y';
2708 END IF;
2709 l_material_tab (l_count).line_no := l_rec.line_no;
2710 l_material_tab (l_count).line_type := l_rec.line_type;
2711 l_material_tab (l_count).inventory_item_id := l_rec.inventory_item_id;
2712 l_material_tab (l_count).qty := l_rec.qty;
2713 l_material_tab (l_count).detail_uom := l_rec.detail_uom;
2714 l_material_tab (l_count).scale_type := l_rec.scale_type;
2715 l_material_tab (l_count).contribute_yield_ind :=
2716 l_rec.contribute_yield_ind;
2717 l_material_tab (l_count).scale_multiple := l_rec.prod_percent;
2718
2719 l_material_tab (l_count).scale_rounding_variance :=
2720 l_rec.scale_rounding_variance;
2721 l_material_tab (l_count).rounding_direction :=
2722 l_rec.rounding_direction;
2723 -- l_uom := l_rec.detail_uom; /* Commented in Bug No.7145922 */
2724 END LOOP;
2725
2726 /* UOM COnversions - Get the common UOM for conversions */
2727
2728 -- FOR i IN 1 .. l_material_tab.COUNT
2729 -- LOOP
2730 -- IF l_material_tab(i).detail_uom IS NOT NULL THEN
2731 /* Get the common UOM class of the detail lines UOM */
2732 /* SELECT uom_class
2733 INTO l_uom_class
2734 FROM mtl_units_of_measure
2735 where uom_code = l_material_tab (i).detail_uom; */
2736
2737 /* If different UOM - get the yield type UOM for conversions. */
2738 /* IF NVL(l_common_uom_class,l_uom_class) <> l_uom_class THEN
2739 OPEN get_unit_of_measure(l_yield_type);
2740 FETCH get_unit_of_measure INTO l_conv_uom;
2741 CLOSE get_unit_of_measure;
2742 END IF;
2743 l_common_uom_class := l_uom_class;
2744 END IF;
2745 END LOOP;*/
2746 /* If all the UOMs belong to the same class, Get the base UOM for conversion. */
2747 /* IF l_conv_uom IS NULL THEN
2748 OPEN get_unit_of_measure(l_common_uom_class);
2749 FETCH get_unit_of_measure INTO l_conv_uom;
2750 CLOSE get_unit_of_measure;
2751
2752 END IF; */
2753
2754 /* Bug No.7145922 - Commented the above FOR loop and added the below line */
2755 l_conv_uom := l_uom;
2756
2757 -- Calculate the totla material line quantities
2758 FOR i IN 1 .. l_material_tab.COUNT
2759 LOOP
2760 IF l_different_uom = 'Y'
2761 THEN
2762 l_temp_qty := INV_CONVERT.inv_um_convert(item_id => l_material_tab (i).inventory_item_id
2763 ,precision => 5
2764 ,from_quantity => l_material_tab (i).qty
2765 ,from_unit => l_material_tab (i).detail_uom
2766 ,to_unit => l_conv_uom
2767 ,from_name => NULL
2768 ,to_name => NULL);
2769
2770 IF l_temp_qty < 0
2771 THEN
2772 fnd_message.set_name ('GMD', 'GMD_UOM_CONV_ERROR');
2773 fnd_message.set_token('UOM',l_conv_uom);
2774 fnd_msg_pub.ADD;
2775 RAISE CANNOT_CONVERT;
2776 END IF;
2777 ELSE
2778 l_temp_qty := l_material_tab (i).qty;
2779 END IF;
2780
2781 -- If it is ingredient then see if this is contributing to yield or not
2782 IF l_material_tab (i).line_type = -1
2783 AND l_material_tab (i).contribute_yield_ind = 'Y'
2784 THEN
2785 l_ingredient_qty := NVL (l_ingredient_qty, 0) + l_temp_qty;
2786 ELSIF l_material_tab (i).line_type = 2
2787 THEN -- By product
2788 l_by_product_qty := l_by_product_qty + l_temp_qty;
2789 ELSIF l_material_tab (i).line_type = 1
2790 THEN -- Products
2791 l_prod_cnt := l_prod_cnt + 1;
2792
2793 /* See if the product is of scale type fixed, if yes, then do not update and also use to subtract from the total
2794 ingredient qty to be distributed. */
2795 IF l_material_tab (i).scale_type = 0
2796 THEN
2797 l_prod_fix_cnt := l_prod_fix_cnt + 1;
2798 l_prod_fix_qty := l_prod_fix_qty + l_temp_qty;
2799 ELSE
2800 l_prod_prop_cnt := l_prod_prop_cnt + 1;
2801 l_prod_prop_qty := l_prod_prop_qty + l_temp_qty;
2802 temp_prod_tbl1 (l_prod_prop_cnt).inventory_item_id :=
2803 l_material_tab (i).inventory_item_id;
2804 temp_prod_tbl1 (l_prod_prop_cnt).cov_qty := l_temp_qty;
2805 -- Conv UOM
2806 temp_prod_tbl1 (l_prod_prop_cnt).cov_uom := l_conv_uom;
2807 temp_prod_tbl1 (l_prod_prop_cnt).orig_qty :=
2808 l_material_tab (i).qty;
2809 temp_prod_tbl1 (l_prod_prop_cnt).orig_uom :=
2810 l_material_tab (i).detail_uom;
2811 temp_prod_tbl1 (l_prod_prop_cnt).line_no :=
2812 l_material_tab (i).line_no;
2813 temp_prod_tbl1 (l_prod_prop_cnt).prod_percent :=
2814 l_material_tab (i).scale_multiple;
2815
2816 END IF;
2817 END IF;
2818 END LOOP;
2819
2820 /* Get the Quantity to be distributed among Products.
2821 Qty = Sum(INGR) - SUM(BY-PRODS) - SUM(PROD-FIXED) */
2822 l_qty_touse :=
2823 l_ingredient_qty - NVL (l_by_product_qty, 0)
2824 - NVL (l_prod_fix_qty, 0);
2825
2826 /* Now Calculate the Product Qty based on ratio */
2827 FOR i IN 1 .. temp_prod_tbl1.COUNT
2828 LOOP
2829 IF l_prod_prop_qty > 0 THEN
2830 /* Check whether Percentages have been enterd for all Proportional Products. */
2831 IF temp_prod_tbl1 (i).prod_percent IS NULL THEN
2832 fnd_message.set_name ('GMD', 'GMD_ENTER_PERCENTAGE_YES');
2833 fnd_msg_pub.ADD;
2834 RAISE CANNOT_CONVERT;
2835 END IF;
2836 l_prod_ratio := temp_prod_tbl1 (i).prod_percent / 100;
2837 ELSE
2838 l_prod_ratio := 1;
2839 END IF;
2840
2841 -- Calculate the specific prod qty
2842 IF l_qty_touse > 0
2843 THEN
2844 l_one_prodqty := l_qty_touse * l_prod_ratio;
2845 ELSE
2846 l_one_prodqty := temp_prod_tbl1 (i).cov_qty;
2847 END IF;
2848
2849 -- Also keep updating the formula level product qty.
2850 lhdrqty := lhdrqty + l_one_prodqty;
2851 -- Changed
2852 IF l_different_uom = 'Y'
2853 THEN
2854 /* Bug No.9399933 - Changed item_id from l_material_tab(i).inventory_item_id to temp_prod_tbl1 (i).inventory_item_id */
2855 l_temp_qty := INV_CONVERT.inv_um_convert(item_id => temp_prod_tbl1 (i).inventory_item_id
2856 ,precision => 5
2857 ,from_quantity => l_one_prodqty
2858 ,from_unit => l_conv_uom
2859 ,to_unit => temp_prod_tbl1 (i).orig_uom
2860 ,from_name => NULL
2861 ,to_name => NULL);
2862
2863 IF l_temp_qty < 0
2864 THEN
2865 x_return_status := 'Q';
2866 fnd_message.set_name ('GMD', 'GMD_UOM_CONV_ERROR');
2867 fnd_message.set_token('UOM',l_conv_uom);
2868 fnd_msg_pub.ADD;
2869 EXIT;
2870 END IF;
2871 ELSE
2872 l_temp_qty := l_one_prodqty;
2873 END IF;
2874
2875 UPDATE fm_matl_dtl
2876 SET qty = ROUND (l_temp_qty, 5),
2877 DETAIL_UOM = temp_prod_tbl1 (i).orig_uom
2878 WHERE formula_id = p_formula_id
2879 AND line_type = 1
2880 AND inventory_item_id = temp_prod_tbl1 (i).inventory_item_id
2881 AND line_no = temp_prod_tbl1 (i).line_no;
2882 END LOOP;
2883
2884 /* Finally update the formula level product qty as prod qty + by product qty. */
2885 lhdrqty := lhdrqty + l_prod_fix_qty + NVL (l_by_product_qty, 0);
2886
2887 -- Update formula Header also
2888 UPDATE fm_form_mst_b
2889 SET total_output_qty = lhdrqty
2890 WHERE formula_id = p_formula_id;
2891 /* Get the message count from the Message stack */
2892 END IF;
2893 fnd_msg_pub.count_and_get (p_count => x_msg_count,
2894 p_data => x_msg_data);
2895 EXCEPTION
2896 WHEN CANNOT_CONVERT THEN
2897 x_return_status := fnd_api.g_ret_sts_unexp_error;
2898 fnd_msg_pub.count_and_get (p_count => x_msg_count,
2899 p_data => x_msg_data);
2900 END Calculate_Total_Product_Qty ;
2901
2902 /* Bug No.7027512 - Start */
2903 /* **********************************************************************
2904 * PROCEDURE
2905 * Run_status_update
2906 *
2907 * Description
2908 *
2909 * Procedure is used by costing to update the GMD tables with frozen status.
2910 * This procedure is registered as a concurrent program
2911 *
2912 * History
2913 * 17-Jul-2008 Kishore Created
2914 *
2915 * *********************************************************************** */
2916
2917 PROCEDURE Run_status_update( p_errbuf OUT NOCOPY VARCHAR2,
2918 p_retcode OUT NOCOPY VARCHAR2,
2919 pLegal_entity_id IN number,
2920 pCalendar_code IN cm_cmpt_dtl.calendar_code%TYPE,
2921 pPeriod_code IN cm_cmpt_dtl.period_code%TYPE,
2922 pCost_type_id IN cm_cmpt_dtl.Cost_type_id%TYPE) IS
2923
2924 x_return_status VARCHAR2(1) := 'S';
2925 l_Recipe_Id NUMBER;
2926 l_formula_Id NUMBER;
2927 l_routing_Id NUMBER;
2928 l_oprn_Id NUMBER;
2929 l_period_cnt NUMBER;
2930 l_cost_type NUMBER;
2931 l_period_id NUMBER;
2932
2933
2934 TYPE VRtbl IS TABLE OF GMD_RECIPE_VALIDITY_RULES.Recipe_Validity_Rule_Id%TYPE;
2935 VRList VRtbl;
2936
2937 CURSOR Get_period_id IS
2938 SELECT period_id from gmf_period_statuses
2939 WHERE Legal_Entity_Id = pLegal_entity_id AND
2940 Calendar_code = pCalendar_code AND
2941 Period_code = pPeriod_code AND
2942 Cost_type_id = pCost_type_id ;
2943
2944 CURSOR FROZEN_EFF_CUR IS
2945 SELECT distinct(fmeff_id) fmeff_id from cm_cmpt_dtl
2946 WHERE period_id = l_period_id AND
2947 cost_type_id = pCost_type_id AND
2948 ROLLOVER_IND = 1;
2949
2950 CURSOR Get_Period_Status IS
2951 SELECT count(*) FROM gmf_period_statuses
2952 WHERE period_id = l_period_id AND
2953 period_status = 'F';
2954
2955 CURSOR Get_Cost_type IS
2956 SELECT cost_type from cm_mthd_mst
2957 WHERE cost_type_id = pCost_type_id;
2958
2959 CURSOR Get_Recipe_id(vValidity_Rule_id NUMBER) IS
2960 SELECT recipe_id from gmd_recipe_validity_rules
2961 WHERE recipe_validity_rule_id = vValidity_Rule_id;
2962
2963 CURSOR Get_FmRout_id(vRecipe_id NUMBER) IS
2964 SELECT formula_id, routing_id From gmd_recipes_b
2965 WHERE recipe_id = vRecipe_id;
2966
2967 Standard_costing_exception EXCEPTION;
2968 Period_status_exception EXCEPTION;
2969 Period_id_exception EXCEPTION;
2970
2971 BEGIN
2972 SAVEPOINT update_status;
2973
2974 OPEN Get_period_id;
2975 FETCH Get_period_id INTO l_period_id;
2976 IF (Get_period_id%NOTFOUND) THEN
2977 CLOSE Get_period_id;
2978 Raise Period_Id_exception;
2979 END IF;
2980 CLOSE Get_period_id;
2981
2982 OPEN Get_Period_Status;
2983 FETCH Get_Period_Status INTO l_period_cnt;
2984 IF ((Get_Period_Status%NOTFOUND) OR (l_period_cnt = 0)) THEN
2985 CLOSE Get_Period_Status;
2986 Raise Period_Status_exception;
2987 END IF;
2988 CLOSE Get_Period_Status;
2989
2990 OPEN Get_Cost_type;
2991 FETCH Get_Cost_type INTO l_cost_type;
2992 IF ((Get_Cost_type%NOTFOUND) OR (l_cost_type = 1)) THEN
2993 CLOSE Get_Cost_type;
2994 Raise Standard_costing_exception;
2995 END IF;
2996 CLOSE Get_Cost_Type;
2997
2998 OPEN FROZEN_EFF_CUR;
2999 FETCH FROZEN_EFF_CUR BULK COLLECT INTO VRList;
3000 CLOSE FROZEN_EFF_CUR;
3001
3002 IF (VRList.count > 0) THEN
3003
3004 FOR i IN 1 .. VRList.count LOOP
3005
3006 /* Update the VR - status field */
3007 Update gmd_recipe_validity_rules
3008 SET validity_rule_status = '900'
3009 WHERE recipe_validity_rule_id = VRList(i)
3010 AND to_number(validity_rule_status) < 800;
3011
3012 OPEN Get_Recipe_id(VRList(i));
3013 FETCH Get_Recipe_id INTO l_Recipe_id;
3014 CLOSE Get_Recipe_id;
3015
3016 /* Update the Recipe - status field */
3017 UPDATE gmd_recipes_b
3018 SET recipe_status = '900'
3019 WHERE recipe_id = l_Recipe_Id
3020 AND to_number(recipe_status) < 800;
3021
3022 OPEN Get_FmRout_id(l_recipe_id);
3023 FETCH Get_FmRout_id INTO l_formula_id, l_routing_id;
3024 CLOSE Get_FmRout_id;
3025
3026 /* Update the formula and routing status */
3027 UPDATE fm_form_mst_b
3028 SET formula_status = '900'
3029 WHERE formula_id = l_formula_id
3030 AND to_number(formula_status) < 800;
3031
3032 UPDATE gmd_routings_b
3033 SET routing_status = '900'
3034 WHERE routing_id = l_routing_id
3035 AND to_number(routing_status) < 800;
3036
3037 /* Update oprns status */
3038 IF (l_routing_id IS NOT NULL) THEN
3039 UPDATE gmd_operations_b
3040 SET operation_status = '900'
3041 WHERE oprn_id IN (SELECT oprn_id
3042 FROM fm_rout_dtl d
3043 WHERE routing_id = l_routing_id)
3044 AND to_number(operation_status) < 800;
3045 END IF;
3046 END LOOP;
3047
3048 ELSE /* when VRList count is <= 0 */
3049 p_retcode := 0;
3050 p_errbuf := NULL;
3051 set_conc_program_Status('NORMAL', 'Did not update the status on GMD tables');
3052
3053 END IF;
3054
3055 /* If o.k until here */
3056 p_retcode := 0;
3057 p_errbuf := NULL;
3058 set_conc_program_Status('NORMAL', NULL);
3059
3060 /* sets the context for formula security */
3061 gmd_p_fs_context.set_additional_attr;
3062
3063 EXCEPTION
3064 WHEN Standard_costing_exception THEN
3065 p_retcode := 3;
3066 p_errbuf := NULL;
3067 set_conc_program_Status('ERROR','Invalid cost method only standard cost methods are allowed ' );
3068 ROLLBACK to update_status;
3069 WHEN Period_status_exception THEN
3070 p_retcode := 3;
3071 p_errbuf := NULL;
3072 set_conc_program_Status('ERROR','Invalid period status only frozen periods are allowed' );
3073 ROLLBACK to update_status;
3074 WHEN Period_id_exception THEN
3075 p_retcode := 3;
3076 p_errbuf := NULL;
3077 set_conc_program_Status('ERROR','Error while fetching period_id' );
3078 ROLLBACK to update_status;
3079 WHEN OTHERS THEN
3080 p_retcode := 3;
3081 p_errbuf := NULL;
3082 set_conc_program_Status('ERROR',sqlerrm);
3083 ROLLBACK to update_status;
3084
3085 END Run_Status_Update;
3086 /* Bug No.7027512 - End */
3087
3088 END; /* Package Body GMD_COMMON_VAL */