1 Package Body GMD_COMMON_VAL AS
2 /* $Header: GMDPCOMB.pls 120.15.12010000.2 2008/11/06 18:49:15 rnalla 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;
384 x_return_status := FND_API.G_RET_STS_SUCCESS;
381 IF FND_API.to_Boolean(p_init_msg_list) THEN
382 FND_MSG_PUB.initialize;
383 END IF;
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 /* | | */
490 /* | | */
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 | */
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;
574
571 l_validity_scale_factor NUMBER;
572 l_item_id NUMBER(10);
573 l_validity_um VARCHAR2(4);
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;
695 /* IF routing qty is provided as opposed to the
692 IF (l_debug = 'Y') THEN
693 gmd_debug.put_line(' Routing UOM : '||l_routing_uom);
694 END IF;
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);
770 /* If for some reason the yield_uom in formula table is not defined OR
767 END IF;
768 END IF;
769
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,
869 p_scale_factor => l_validity_scale_factor,
866 x_return_status => l_toq_return_status,
867 x_msg_count => x_msg_count,
868 x_msg_data => x_msg_data,
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 /* */
974 /* ====================================================================== */
971 /* Procedure returns the total product and ingredient qty */
972 /* The uom is that of FM_YIELD_TYPE UOM */
973 /* */
975 PROCEDURE Calculate_Total_Qty
976 ( formula_id IN GMD_RECIPES.Formula_id%TYPE ,
977 x_product_qty OUT NOCOPY NUMBER ,
978 x_ingredient_qty OUT NOCOPY NUMBER ,
979 x_uom IN OUT NOCOPY VARCHAR2 ,
980 x_return_status OUT NOCOPY VARCHAR2 ,
981 x_msg_count OUT NOCOPY NUMBER ,
982 x_msg_data OUT NOCOPY VARCHAR2 ,
983 p_scale_factor IN NUMBER ,
984 p_primaries IN VARCHAR2
985 ) IS
986
987 l_temp_qty NUMBER := 0;
988 l_um_type mtl_units_of_measure.uom_class%TYPE;
989 /*Bug 5667857 - Change the column from unit_of_measure to uom_code */
990 CURSOR get_sy_std_um(pUm_type mtl_units_of_measure.uom_class%TYPE) IS
991 SELECT uom_code
992 FROM mtl_units_of_measure
993 WHERE uom_class = pUm_type
994 AND base_uom_flag = 'Y';
995
996 CURSOR prod_um_cur(vFormula_id NUMBER) IS
997 SELECT detail_uom
998 FROM fm_matl_dtl
999 WHERE line_no = 1
1000 AND line_type = 1
1001 AND formula_id = vFormula_id;
1002
1003 /* Bug 1683702 - Thomas Daniel */
1004 l_count NUMBER(5) DEFAULT 0;
1005 l_scale_tab GMD_COMMON_SCALE.scale_tab;
1006 l_material_tab GMD_COMMON_SCALE.scale_tab;
1007
1008 -- NPD Conv. Use inventory_iem_id and detail_uom instead of item_id and item_um
1009 CURSOR Get_formula_lines (vFormula_id NUMBER) IS
1010 SELECT line_no, line_type, inventory_item_id, qty, detail_uom, scale_type,
1011 contribute_yield_ind, scale_multiple, scale_rounding_variance,
1012 rounding_direction
1013 FROM fm_matl_dtl
1014 WHERE formula_id = vFormula_id
1015 ORDER BY line_type;
1016
1017 -- NPD Conv.
1018 l_orgn_id NUMBER;
1019 l_return_status VARCHAR2(10);
1020
1021 CURSOR get_formula_owner_orgn_id(vformula_id NUMBER) IS
1022 SELECT owner_organization_id
1023 FROM fm_form_mst_b
1024 WHERE formula_id = vformula_id;
1025
1026 BEGIN
1027
1028 /* Initialize the input and output qtys */
1029 x_product_qty := 0;
1030 x_ingredient_qty := 0;
1031 x_return_status := 'S';
1032
1033 -- NPD Conv. Get formula owner orgn. id
1034 OPEN get_formula_owner_orgn_id(formula_id);
1035 FETCH get_formula_owner_orgn_id INTO l_orgn_id;
1036 CLOSE get_formula_owner_orgn_id;
1037
1038 /* if the x_uom value is not paased as input parameter */
1039 /* then we use the GMD:Yield type std um as the formula uom */
1040 IF (x_uom IS NULL) THEN
1041 -- l_um_type := fnd_profile.value('FM_YIELD_TYPE');
1042
1043 -- NPD Conv. Use the new detch proc. to get FM_YIELD_TYPE
1044 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1045 P_parm_name => 'FM_YIELD_TYPE' ,
1046 P_parm_value => l_um_type ,
1047 X_return_status => l_return_status );
1048
1049 IF (l_um_type IS NOT NULL) then
1050 OPEN get_sy_std_um(l_um_type);
1051 FETCH get_sy_std_um INTO x_uom;
1052 IF get_sy_std_um%NOTFOUND then
1053 x_uom := NULL;
1054 End if;
1055 CLOSE get_sy_std_um;
1056 END IF;
1057 END IF;
1058
1059 /* If the GMD:Yield type is not defined use th emain product UOM */
1060 IF (x_uom IS NULL) THEN /* get the main prod um */
1061 /* Determine the main product UOM */
1062 OPEN prod_um_cur(formula_id);
1063 FETCH prod_um_cur INTO x_uom;
1064 IF prod_um_cur%NOTFOUND then
1065 x_uom := NULL;
1066 End if;
1067 CLOSE prod_um_cur;
1068 END IF;
1069
1070 /* If the x_uom is yet NULL then its an error */
1071 IF (x_uom IS NULL) Then
1072 FND_MESSAGE.SET_NAME('GMD', 'FM_SCALE_BAD_YIELD_TYPE');
1073 FND_MSG_PUB.Add;
1074 x_return_status := 'E';
1075 END IF;
1076
1077 /* Bug 1683702 - Thomas Daniel */
1078 FOR l_rec IN Get_formula_lines (formula_id) LOOP
1079 l_count := l_count + 1;
1080 l_scale_tab(l_count).line_no := l_rec.line_no;
1081 l_scale_tab(l_count).line_type := l_rec.line_type;
1082 l_scale_tab(l_count).inventory_item_id := l_rec.inventory_item_id; -- NPD Conv.
1083 l_scale_tab(l_count).qty := l_rec.qty;
1084 l_scale_tab(l_count).detail_uom := l_rec.detail_uom; -- NPD Conv.
1085 l_scale_tab(l_count).scale_type := l_rec.scale_type;
1086 l_scale_tab(l_count).contribute_yield_ind := l_rec.contribute_yield_ind;
1087 l_scale_tab(l_count).scale_multiple := l_rec.scale_multiple;
1088 l_scale_tab(l_count).scale_rounding_variance := l_rec.scale_rounding_variance;
1089 l_scale_tab(l_count).rounding_direction := l_rec.rounding_direction;
1090 END LOOP; /* FOR l_rec IN Get_formula_lines (l_formula_id) */
1091
1092 IF NVL(p_scale_factor, 1) = 1 THEN
1093 l_material_tab := l_scale_tab;
1094 ELSE
1098 ,p_scale_factor => p_scale_factor
1095 -- NPD Conv. Pass orgn_id to the scale proc.
1096 GMD_COMMON_SCALE.scale (p_scale_tab => l_scale_tab
1097 ,p_orgn_id => l_orgn_id
1099 ,p_primaries => p_primaries
1100 ,x_scale_tab => l_material_tab
1101 ,x_return_status => x_return_status);
1102 IF x_return_status <> FND_API.g_ret_sts_success THEN
1103 RAISE FND_API.g_exc_error;
1104 END IF;
1105 END IF; /* IF NVL(p_scale_factor, 1) = 1 */
1106
1107 /* Calculate the ingredient total quantities */
1108 FOR i IN 1..l_material_tab.COUNT LOOP
1109 IF l_material_tab(i).line_type = -1 AND
1110 /*Bug 2880618 - Thomas Daniel */
1111 /*Need to compute only for ingredients contributing to yield */
1112 l_material_tab(i).contribute_yield_ind = 'Y' THEN
1113 -- NPD Conv.
1114 l_temp_qty := INV_CONVERT.inv_um_convert( item_id => l_material_tab(i).inventory_item_id
1115 ,precision => 5
1116 ,from_quantity => l_material_tab(i).qty
1117 ,from_unit => l_material_tab(i).detail_uom
1118 ,to_unit => x_uom
1119 ,from_name => NULL
1120 ,to_name => NULL);
1121 IF l_temp_qty < 0 THEN
1122 x_ingredient_qty := NULL;
1123 x_return_status := 'Q';
1124 FND_MESSAGE.SET_NAME('GMD', 'GMD_CANNOT_CALC_TOQ');
1125 FND_MSG_PUB.Add;
1126 Exit;
1127 ELSE
1128 X_ingredient_qty := X_ingredient_qty + l_temp_qty;
1129 END IF;
1130 END IF;
1131 END LOOP;
1132
1133 /* Now let us calculate the product total quantities */
1134 FOR i IN 1..l_material_tab.COUNT LOOP
1135 IF l_material_tab(i).line_type IN (1,2) THEN
1136 -- NPD Conv.
1137 l_temp_qty := INV_CONVERT.inv_um_convert( item_id => l_material_tab(i).inventory_item_id
1138 ,precision => 5
1139 ,from_quantity => l_material_tab(i).qty
1140 ,from_unit => l_material_tab(i).detail_uom
1141 ,to_unit => x_uom
1142 ,from_name => NULL
1143 ,to_name => NULL);
1144 IF l_temp_qty < 0 THEN
1145 x_product_qty := NULL;
1146 x_return_status := 'Q';
1147 FND_MESSAGE.SET_NAME('GMD', 'GMD_CANNOT_CALC_TOQ');
1148 FND_MSG_PUB.Add;
1149 Exit;
1150 ELSE
1151 x_product_qty := x_product_qty + l_temp_qty;
1152 END IF;
1153 END IF;
1154 END LOOP;
1155
1156 FND_MSG_PUB.COUNT_AND_GET (P_count => x_msg_count,
1157 P_data => x_msg_data);
1158
1159 EXCEPTION
1160 WHEN FND_API.g_exc_error THEN
1161 x_return_status := 'Q';
1162 WHEN Others THEN
1163 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1164 FND_MESSAGE.SET_NAME('GMD', 'GMD_UNEXPECTED_ERROR');
1165 FND_MESSAGE.SET_TOKEN('ERROR', sqlerrm);
1166 FND_MSG_PUB.ADD;
1167 FND_MSG_PUB.COUNT_AND_GET (P_count => x_msg_count,
1168 P_data => x_msg_data);
1169
1170 END Calculate_Total_Qty;
1171
1172 /* ==================================================================== */
1173 /* Function */
1174 /* Get_Routing_Scale_Factor */
1175 /* */
1176 /* Description - */
1177 /* Routing qtys are scaled to a value proportional to the Recipe */
1178 /* Total Output Qty. This scale factor is the routing scale factor. */
1179 /* Return value : x_Routing_Scale_Factor NUMBER */
1180 /* */
1181 /* */
1182 /* */
1183 /* ==================================================================== */
1184 FUNCTION Get_Routing_Scale_Factor(vRecipe_id IN NUMBER,
1185 x_return_status OUT NOCOPY VARCHAR2,
1186 vFormula_Id IN NUMBER,
1187 vRouting_Id IN NUMBER)
1188 RETURN NUMBER IS
1189
1190 l_recipe_qty NUMBER ;
1191 x_Routing_Scale_factor NUMBER := 1 ;
1192
1193 CURSOR Cur_get_recipe IS
1194 SELECT formula_id, routing_id, calculate_step_quantity
1195 FROM gmd_recipes_b
1196 WHERE recipe_id = vRecipe_Id;
1197
1198 Cursor get_routrecipe_qty(pFormula_Id NUMBER, pRouting_Id NUMBER) IS
1199 Select rout.routing_qty rout_qty,
1200 form.total_output_qty recipe_qty,
1201 rout.routing_uom rout_uom,
1202 form.formula_id formula_id,
1203 form.yield_uom yield_typ_uom
1204 from fm_form_mst_b form,
1205 gmd_routings_b rout
1209 l_formula_id NUMBER;
1206 where form.formula_id = pformula_id and
1207 rout.routing_id = prouting_id ;
1208
1210 l_routing_id NUMBER;
1211 l_calculate_step_qty NUMBER(5);
1212 l_product_qty NUMBER;
1213 l_ingredient_qty NUMBER;
1214 l_uom mtl_units_of_measure.unit_of_measure%TYPE;
1215 l_return_status VARCHAR2(1);
1216 l_msg_count NUMBER;
1217 l_msg_data VARCHAR2(2000);
1218 BEGIN
1219 X_return_status := FND_API.g_ret_sts_success;
1220 IF vRecipe_Id IS NOT NULL THEN
1221 OPEN Cur_get_recipe;
1222 FETCH Cur_get_recipe INTO l_formula_id, l_routing_id, l_calculate_step_qty;
1223 CLOSE Cur_get_recipe;
1224 ELSE
1225 l_formula_id := vFormula_Id;
1226 l_routing_id := vRouting_Id;
1227 l_calculate_step_qty := 0;
1228 END IF;
1229 FOR rout_rec IN get_routrecipe_qty(l_formula_Id, l_routing_Id) LOOP
1230 IF(l_calculate_step_qty <> 1) THEN
1231 IF (rout_rec.rout_uom <> rout_rec.yield_typ_uom) THEN
1232 l_recipe_qty := INV_CONVERT.inv_um_convert(item_id => 0
1233 ,precision => 5
1234 ,from_quantity => rout_rec.recipe_qty
1235 ,from_unit => rout_rec.yield_typ_uom
1236 ,to_unit => rout_rec.rout_uom
1237 ,from_name => NULL
1238 ,to_name => NULL);
1239 /*This implies that the recipe qty uom and the routing qty uom are
1240 not of the same uom class */
1241 /*so lets recalculate the recipe qty based on the routing uom */
1242 IF l_recipe_qty < 0 THEN
1243 l_uom := rout_rec.rout_uom;
1244 Calculate_Total_Qty (Formula_Id => rout_rec.formula_id
1245 ,x_product_qty => l_product_qty
1246 ,x_ingredient_qty => l_ingredient_qty
1247 ,x_uom => l_uom
1248 ,x_return_status => l_return_status
1249 ,x_msg_count => l_msg_count
1250 ,x_msg_data => l_msg_data);
1251
1252 /*Bug 2722961 - Thomas Daniel */
1253 /*Changed the checking from return_status to l_product_qty */
1254 /*as the calculate_total_qty routine was passing back the */
1255 /*return status as 'Q' if the ingredient conversions were */
1256 /*not setup, though the product conversions have been setup */
1257 IF l_product_qty > 0 THEN
1258 l_recipe_qty := l_product_qty;
1259 ELSE
1260 FND_MSG_PUB.INITIALIZE;
1261 FND_MESSAGE.SET_NAME ('GMD', 'GMD_ERR_CALC_ROUT_FACT');
1262 FND_MSG_PUB.add;
1263 x_return_status := 'W';
1264 RETURN 1;
1265 END IF;
1266 END IF;
1267 ELSE
1268 l_recipe_qty := rout_rec.recipe_qty;
1269 END IF;
1270 x_Routing_scale_factor := l_recipe_qty / rout_rec.rout_qty;
1271 ELSE
1272 /* ASQC flag is ON it implies that the recipe step qty have the rout qty
1273 factor is already incorporated */
1274 x_Routing_scale_factor := 1;
1275 END IF;
1276 END LOOP;
1277
1278 return x_Routing_Scale_factor;
1279
1280 END Get_Routing_Scale_Factor;
1281
1282
1283 /* =============================================================== */
1284 /* Procedure: */
1285 /* Calculate_Charges */
1286 /* */
1287 /* DESCRIPTION: */
1288 /* */
1289 /* Return E if no status code exists */
1290 /* Return S if status code is found */
1291 /* */
1292 /* Procedure returns the all Charges for a routing step */
1293 /* History : */
1294 /* Shyam 03/29/2002 Bug # 2284643: Added logic to scale the */
1295 /* routing step qty if the total routing step */
1296 /* is not equal to the Recipe qty */
1297 /* Shyam 04/20/2002 Create a new organization based capacity */
1298 /* cursor : Bug # 2272885 */
1299 /* =============================================================== */
1300
1301 PROCEDURE Calculate_Charges
1302 ( Batch_id IN NUMBER ,
1303 Recipe_id IN NUMBER ,
1304 Routing_id IN NUMBER ,
1305 VR_qty IN NUMBER ,
1306 Tolerance IN NUMBER ,
1307 Orgn_id IN NUMBER ,
1308 x_charge_tbl OUT NOCOPY charge_tbl ,
1309 x_return_status OUT NOCOPY VARCHAR2
1310 ) IS
1311
1312 /* Defining all variables */
1313 l_row NUMBER := 0 ;
1314 l_rout_scale_factor NUMBER := 1 ;
1318 /* get capacities for resources that belong any orgn (generic) */
1315 l_step_tbl GMD_AUTO_STEP_CALC.step_rec_tbl;
1316 l_return_status VARCHAR2(1);
1317
1319 CURSOR Step_qty_Cur(vRouting_id NUMBER) IS
1320 SELECT dtl.routingStep_id ,
1321 dtl.step_qty qty ,
1322 opr.process_qty_uom step_um
1323 FROM fm_rout_dtl dtl ,
1324 gmd_operations_b opr
1325 WHERE dtl.oprn_id = opr.oprn_id AND
1326 dtl.routing_id = vRouting_id
1327 ORDER BY dtl.routingStep_id;
1328
1329 CURSOR Get_Recipe_Step_Details(vRecipe_id NUMBER, vRoutingStep_id NUMBER) IS
1330 SELECT step_qty, mass_qty, mass_std_uom, volume_qty, volume_std_uom
1331 FROM gmd_recipe_routing_steps
1332 WHERE recipe_id = vRecipe_id AND
1333 routingstep_id = vRoutingStep_id;
1334
1335 BEGIN
1336 IF (l_debug = 'Y') THEN
1337 gmd_debug.log_initialize('CalcCharges');
1338 END IF;
1339 /* Initialize variables */
1340 /* Get the Routing Scale Factor */
1341 IF (l_debug = 'Y') THEN
1342 gmd_debug.put_line('In calc_charges proc initializing the variables ');
1343 END IF;
1344 x_return_status := FND_API.g_ret_sts_success;
1345
1346 /* Get the Routing Scale Factor */
1347 IF (l_debug = 'Y') THEN
1348 gmd_debug.put_line('In calc_charges proc - before calling routing scale fact '
1349 ||Recipe_id);
1350 END IF;
1351 l_rout_scale_factor := Get_Routing_Scale_Factor(vRecipe_Id => Recipe_id,
1352 x_return_status => l_return_status);
1353
1354
1355 IF (l_debug = 'Y') THEN
1356 gmd_debug.put_line('In calc_charges proc - after calling routing scale fact '
1357 ||l_rout_scale_factor||' '||l_return_status);
1358 END IF;
1359
1360 /* Step1: Get all step details based on the routing_id */
1361 FOR Step_qty_rec IN Step_qty_cur(Routing_id) LOOP
1362
1363 /* Get the routing step value */
1364 l_row := l_row + 1;
1365 l_step_tbl(l_row).step_id := Step_qty_rec.routingstep_id;
1366 l_step_tbl(l_row).step_qty := Step_qty_rec.qty * NVL(l_rout_scale_factor, 1);
1367 l_step_tbl(l_row).step_qty_uom := Step_qty_rec.step_um;
1368
1369 IF (l_debug = 'Y') THEN
1370 gmd_debug.put_line('In CalcCharges Proc - the step qty and its uom is '
1371 ||l_step_tbl(l_row).step_qty||' '||l_step_tbl(l_row).step_qty_uom);
1372 END IF;
1373
1374 /* At Recipe_Routing_Step_level, we store the step qty in three uom */
1375 /* 1) Step qty in its operating uom */
1376 /* 2) As, mass qty in mass reference uom */
1377 /* 3) As, volume qty in volume reference uom */
1378
1379 /* Check if the step qty has been overridden at recipe level */
1380 /* Table gmd_recipe_routing_steps stores step qtys that are overridden */
1381
1382 /* This cursor should return only one row */
1383 FOR Get_Recipe_Step_rec IN
1384 Get_Recipe_Step_Details(Recipe_id, Step_qty_rec.routingStep_id) LOOP
1385
1386 /* Get the recipe routing step qty */
1387 /* Use the overridden step qty */
1388 l_step_tbl(l_row).step_qty := Get_Recipe_Step_rec.step_qty;
1389 l_step_tbl(l_row).step_mass_qty := Get_Recipe_Step_rec.mass_qty;
1390 l_step_tbl(l_row).step_mass_uom := Get_Recipe_Step_rec.mass_std_uom;
1391 l_step_tbl(l_row).step_vol_qty := Get_Recipe_Step_rec.volume_qty;
1392 l_step_tbl(l_row).step_vol_uom := Get_Recipe_Step_rec.volume_std_uom;
1393
1394 IF (l_debug = 'Y') THEN
1395 gmd_debug.put_line('In CalcCharges Proc - the override step qty and its uom is '
1396 ||l_step_tbl(l_row).step_qty||' '||l_step_tbl(l_row).step_qty_uom);
1397 END IF;
1398
1399 END LOOP; /* End loop when routing step details exists at recipe level */
1400
1401 END LOOP;
1402
1403 /* We have the step quantities now lets calculate the charges */
1404 IF l_step_tbl.COUNT > 0 THEN
1405 GMD_COMMON_VAL.calculate_step_charges (p_recipe_id => Recipe_id
1406 ,p_tolerance => tolerance
1407 ,p_orgn_id => Orgn_id
1408 ,p_step_tbl => l_step_tbl
1409 ,x_charge_tbl => x_charge_tbl
1410 ,x_return_status => x_return_status);
1411 IF (l_debug = 'Y') THEN
1412 gmd_debug.put_line('In CalcCharges Proc - after calling Calc_step_chr '
1413 ||x_return_status);
1414 END IF;
1415 END IF; /* If their are rows in the step table */
1416
1417 END Calculate_Charges;
1418
1419
1420 /* =============================================================== */
1421 /* Procedure: */
1422 /* Calculate_Step_Charges */
1423 /* */
1424 /* DESCRIPTION: */
1425 /* */
1426 /* Return E if no status code exists */
1427 /* Return S if status code is found */
1431 /* Thomas 07/23/2002 Bug # 1683702: Added this new procedure */
1428 /* */
1429 /* Procedure returns the all Charges for a routing step */
1430 /* History : */
1432 /* To calculate the charges off the step */
1433 /* quantities passed in */
1434 /* RajaSekhar 02/04/2003 BUG#2365583 Added code to represent */
1435 /* whether the number of charges is defaulted */
1436 /* or calculated properly. */
1437 /* Kalyani 02/06/2006 Bug#5258672 Store max capacity in res UOM */
1438 /* =============================================================== */
1439
1440 PROCEDURE Calculate_Step_Charges
1441 ( P_recipe_id IN NUMBER ,
1442 P_tolerance IN NUMBER ,
1443 P_orgn_id IN NUMBER ,
1444 P_step_tbl IN GMD_AUTO_STEP_CALC.step_rec_tbl,
1445 x_charge_tbl OUT NOCOPY charge_tbl ,
1446 x_return_status OUT NOCOPY VARCHAR2
1447 ) IS
1448
1449 /* Defining all variables */
1450 l_charge INTEGER := 1 ;
1451 l_rough_charge NUMBER ;
1452 l_step_qty_uom VARCHAR2(4) ;
1453 l_max_capacity NUMBER ;
1454 l_max_capacity_old NUMBER ;
1455 l_capacity_uom VARCHAR2(4) ;
1456 l_row NUMBER := 1 ;
1457 m_counter NUMBER := 1 ;
1458 l_step_qty NUMBER ;
1459 l_def_charge VARCHAR2(1) ; --BUG#2365583 RajaSekhar
1460
1461 CURSOR Capacity_cur(vRecipe_id NUMBER, vRoutingstep_id NUMBER,
1462 vOrgn_id NUMBER) IS
1463 /*Bug 3679608 - Thomas Daniel */
1464 /*Modified the select statement to consider the generic resource only */
1465 /*if there are no plant specific overrides */
1466 SELECT MIN( NVL(orgnres.max_capacity, crres.max_capacity) ) max_cap,
1467 crres.capacity_um capacity_um
1468 FROM (SELECT resources, max_capacity, capacity_um, capacity_constraint
1469 FROM cr_rsrc_mst_b m
1470 WHERE capacity_constraint = 1
1471 AND NOT EXISTS (SELECT 1
1472 FROM cr_rsrc_dtl d
1473 WHERE d.organization_id = vOrgn_id
1474 AND d.resources = m.resources)
1475 UNION
1476 SELECT resources, max_capacity, capacity_um, capacity_constraint
1477 FROM cr_rsrc_dtl
1478 WHERE organization_id = vOrgn_id
1479 AND capacity_constraint = 1 ) crres ,
1480 (SELECT max_capacity, resources, routingstep_id
1481 FROM gmd_recipe_orgn_resources
1482 WHERE recipe_id = vRecipe_id
1483 AND organization_id = vOrgn_id) orgnres ,
1484 (SELECT oprn_id, routingStep_id
1485 FROM fm_rout_dtl
1486 WHERE routingstep_id = vRoutingstep_id ) dtl ,
1487 gmd_operation_resources res ,
1488 gmd_operation_activities act ,
1489 gmd_operations_b opr
1490 WHERE crres.resources = res.resources AND
1491 dtl.oprn_id = opr.oprn_id AND
1492 opr.oprn_id = act.oprn_id AND
1493 act.oprn_line_id = res.oprn_line_id AND
1494 (orgnres.routingstep_id IS NULL OR
1495 dtl.routingstep_id = orgnres.routingstep_id ) AND
1496 res.resources = orgnres.resources(+)
1497 GROUP BY crres.capacity_um;
1498
1499 BEGIN
1500 IF (l_debug = 'Y') THEN
1501 gmd_debug.put_line('In CalcCharges Step Proc - ');
1502 END IF;
1503 /* Initialize variables */
1504 x_return_status := FND_API.g_ret_sts_success;
1505 FOR i IN 1..P_step_tbl.COUNT LOOP
1506 /*Bug 3669132 - Thomas Daniel */
1507 /*Initialize default charge variable to identify if the code has entered the following for loop */
1508 l_def_charge := NULL;
1509 /* Let us fetch the min of the max capacities for all the resources belonging */
1510 /* to the current routing step and recipe */
1511 /* Step1: Get all resources details based on the routingStep_id */
1512 FOR Capacity_rec IN Capacity_cur(P_recipe_id,
1513 P_step_tbl(i).step_id,
1514 P_orgn_id) LOOP
1515 l_charge := 1;
1516
1517 /* Get the routing step value */
1518 l_step_qty := P_step_tbl(i).step_qty;
1519 l_step_qty_uom := P_step_tbl(i).step_qty_uom;
1520
1521 l_capacity_uom := Capacity_rec.capacity_um;
1522
1523 /* The min of max_capacity needs to derived for a step */
1524 /* Please remember if the max capacity is -ve */
1525 /* it probably means that the capcity conversion to step qty um was not set */
1526 l_max_capacity := INV_CONVERT.inv_um_convert(item_id => 0
1527 ,precision => 5
1531 ,from_name => NULL
1528 ,from_quantity => nvl(Capacity_rec.max_cap,0)
1529 ,from_unit => Capacity_rec.capacity_um
1530 ,to_unit => l_step_qty_uom
1532 ,to_name => NULL);
1533
1534 IF (l_debug = 'Y') THEN
1535 gmd_debug.put_line('In CalcCharges Step Proc - 1. the max cap and its uom '
1536 ||l_max_capacity||' ' ||l_capacity_uom);
1537 END IF;
1538
1539 IF (l_max_capacity < 0) THEN
1540 /* Set a message in our stack : the capacity conv has not occurred */
1541 x_return_status := 'E';
1542 FND_MESSAGE.SET_NAME('GMD', 'GMD_CANNOT_CONV_CAPACITY_UOM');
1543 FND_MSG_PUB.Add;
1544 END IF; /* when max cap is < 0 */
1545
1546 /* Get the step qty : */
1547 /* If the max capacity is yet -ve its becoz none of the capcity uom where */
1548 /* convertible to the process_um or step operation um */
1549
1550 /* Test if the capacity UOM can be converted into the Mass Qty UOM */
1551 /* It might be possible that the capacity uom is not convertible to the
1552 /* process_um but convertible to the mass_ref_um */
1553 IF (l_max_capacity < 0) THEN
1554 l_step_qty := P_step_tbl(i).step_mass_qty;
1555 l_step_qty_uom := P_step_tbl(i).step_mass_uom;
1556 l_max_capacity := INV_CONVERT.inv_um_convert(item_id => 0
1557 ,precision => 5
1558 ,from_quantity => Capacity_rec.max_cap
1559 ,from_unit => l_capacity_uom
1560 ,to_unit => l_step_qty_uom
1561 ,from_name => NULL
1562 ,to_name => NULL);
1563 IF (l_debug = 'Y') THEN
1564 gmd_debug.put_line('In CalcCharges Step Proc - 2. the max cap and its uom '
1565 ||l_max_capacity||' ' ||l_capacity_uom);
1566 END IF;
1567 END IF; /* when max cap is < 0 */
1568
1569 /* Test if the capacity UOM can be converted into the Volume Qty UOM */
1570 /* It might be possible that the capacity uom is not convertible to the
1571 /* process_um and mass_um but convertible to the volume_ref_um */
1572 IF (l_max_capacity < 0) THEN
1573 l_step_qty := P_step_tbl(i).step_vol_qty;
1574 l_step_qty_uom := P_step_tbl(i).step_vol_uom;
1575 l_max_capacity := INV_CONVERT.inv_um_convert(item_id => 0
1576 ,precision => 5
1577 ,from_quantity => Capacity_rec.max_cap
1578 ,from_unit => l_capacity_uom
1579 ,to_unit => l_step_qty_uom
1580 ,from_name => NULL
1581 ,to_name => NULL);
1582
1583 IF (l_debug = 'Y') THEN
1584 gmd_debug.put_line('In CalcCharges Step Proc - 3. the max cap and its uom '
1585 ||l_max_capacity||' ' ||l_capacity_uom);
1586 END IF;
1587 END IF; /* when max cap is < 0 */
1588
1589 IF (l_debug = 'Y') THEN
1590 gmd_debug.put_line('In CalcCharges Step Proc - 4. the max cap and step_qty '
1591 ||l_max_capacity||' ' ||l_step_qty);
1592 END IF;
1593 /* Calculations after step qty and UOM is found */
1594 IF ((l_step_qty > 0) AND (l_max_capacity > 0)) THEN
1595 /* If the remainder after dividing the step quantity by the
1596 l_max_capacity is greater than tolerance then we round up the
1597 value to the next interger else we truncate to an integer smaller than
1598 the ratio value
1599 */
1600 /* E.g if the step_qty is 110 and the l_max_capacity = 100
1601 the l_rough_charge is 1.1 and the remainder is 10. If the tolerance was
1602 15 (i.e > 10) then the charge would = 1.0 . However, if the tolerance is
1603 5 (i.e < 10) the charge would be = 2.0
1604 */
1605 l_rough_charge := l_step_qty /l_max_capacity;
1606
1607 IF ( MOD(l_step_qty, l_max_capacity) > p_tolerance ) THEN
1608 l_charge := CEIL(l_rough_charge);
1609 ELSE
1610 l_charge := TRUNC(l_rough_charge);
1611 END IF; /* when ratio is greater than tolerance */
1612 l_def_charge :='N'; --BUG#2365583 RajaSekhar
1613 ELSE
1614 l_charge := 1;
1615 l_def_charge :='Y'; --BUG#2365583 RajaSekhar
1616 END IF; /* End condition when step qty > 0 */
1617
1618 /* Resource usage is below capacity. Bug 2183650 */
1619 IF (l_charge <= 0 OR l_charge IS NULL) THEN
1620 l_charge := 1;
1621 END IF; /* when charge is 0 */
1622
1623 /* If Resource capacity is -ve - probably due to non UOM conv set it to NUll */
1624 IF (l_max_capacity < 0) THEN
1625 l_max_capacity := NULL;
1626 END IF;
1627
1628 /* Associate with charges and routing step details with out table */
1632 /* Eliminate duplicate routingStepid rows */
1629 /* For each RoutingStep_id check for the max charge value */
1630 /* This condition occurs when each set has more than one resource with diff cap UOM */
1631
1633 /* For each RoutingStep_id check for the max charge value and remove the
1634 one with lower charge */
1635 /* This condition occurs when each set has more than one resource with diff cap UOM */
1636
1637 IF (m_counter = 1) THEN
1638 x_charge_tbl(l_row).def_charge := l_def_charge; --BUG#2365583 RajaSekhar
1639 x_charge_tbl(l_row).charge := l_charge;
1640 x_charge_tbl(l_row).routingstep_id := P_step_tbl(i).step_id ;
1641 x_charge_tbl(l_row).max_capacity := l_max_capacity;
1642 --x_charge_tbl(l_row).capacity_uom := l_capacity_uom;
1643 /* bug # 2385711 - The uom to be returned is the step qty uom
1644 and not the capacity uom */
1645 x_charge_tbl(l_row).capacity_uom := P_step_tbl(i).step_qty_uom;
1646 m_counter := m_counter + 1;
1647 -- Bug#5258672 Store the capacity value in resource UOM
1648 x_charge_tbl(l_row).Max_Capacity_In_Res_UOM := Capacity_rec.max_cap;
1649 END IF;
1650
1651 IF (x_charge_tbl(l_row).routingstep_id = P_step_tbl(i).Step_id) THEN
1652 IF (x_charge_tbl(l_row).charge < l_charge) THEN
1653 x_charge_tbl(l_row).def_charge := l_def_charge; --BUG#2365583 RajaSekhar
1654 x_charge_tbl(l_row).charge := l_charge;
1655 x_charge_tbl(l_row).routingstep_id := P_step_tbl(i).step_id ;
1656 x_charge_tbl(l_row).max_capacity := l_max_capacity;
1657 --x_charge_tbl(l_row).capacity_uom := l_capacity_uom;
1658 /* bug # 2385711 - The uom to be returned is the step qty uom
1659 and not the capacity uom */
1660 x_charge_tbl(l_row).capacity_uom := P_step_tbl(i).step_qty_uom;
1661 -- Bug#5258672 Store the capacity value in resource UOM
1662 x_charge_tbl(l_row).Max_Capacity_In_Res_UOM := Capacity_rec.max_cap;
1663 END IF; /* when row in previous row is different from current values */
1664 ELSE
1665 l_row := l_row + 1;
1666 x_charge_tbl(l_row).def_charge := l_def_charge; --BUG#2365583 RajaSekhar
1667 x_charge_tbl(l_row).charge := l_charge;
1668 x_charge_tbl(l_row).routingstep_id := P_step_tbl(i).Step_id;
1669 x_charge_tbl(l_row).max_capacity := l_max_capacity;
1670 -- x_charge_tbl(l_row).capacity_uom := l_capacity_uom;
1671 /* bug # 2385711 - The uom to be returned is the step qty uom
1672 and not the capacity uom */
1673 x_charge_tbl(l_row).capacity_uom := P_step_tbl(i).step_qty_uom;
1674 -- Bug#5258672 Store the capacity value in resource UOM
1675 x_charge_tbl(l_row).Max_Capacity_In_Res_UOM := Capacity_rec.max_cap;
1676 END IF; /* When routingStep id are same */
1677
1678 END LOOP; /* End loop for main generic cursor */
1679 /*Bug 3669132 - Thomas Daniel */
1680 /*Added the following code to set the charge as 1 if no capacity constraint */
1681 /*resources are found for this routing step */
1682 IF l_def_charge IS NULL THEN
1683 /*Bug3679608 - Thomas Daniel*/
1684 /*Moved the row incremented up */
1685 IF m_counter <> 1 THEN
1686 l_row := l_row + 1;
1687 ELSE
1688 m_counter := m_counter + 1;
1689 END IF;
1690 x_charge_tbl(l_row).def_charge := 'Y';
1691 x_charge_tbl(l_row).charge := 1;
1692 x_charge_tbl(l_row).routingstep_id := P_step_tbl(i).Step_id;
1693 x_charge_tbl(l_row).max_capacity := NULL;
1694 x_charge_tbl(l_row).capacity_uom := P_step_tbl(i).step_qty_uom;
1695 END IF;
1696 END LOOP; /* FOR i IN 1..Step_tbl.COUNT */
1697
1698 END Calculate_Step_Charges;
1699
1700
1701
1702 FUNCTION UPDATE_ALLOWED(Entity VARCHAR2
1703 ,Entity_id NUMBER
1704 ,Update_Column_Name VARCHAR2 Default Null)
1705 RETURN BOOLEAN IS
1706 l_meaning GMD_STATUS.Meaning%TYPE ;
1707 l_desc GMD_STATUS.Description%TYPE ;
1708 l_return_status VARCHAR2(1);
1709 l_bool BOOLEAN := TRUE;
1710 l_status_code GMD_STATUS.Status_Code%TYPE;
1711 l_delete_mark NUMBER := 0;
1712
1713 l_resp_id NUMBER(15) DEFAULT FND_PROFILE.VALUE('RESP_ID');
1714 l_owner_orgn_id GMD_RECIPES_B.owner_organization_id%TYPE;
1715 l_dummy NUMBER := 0;
1716
1717 Cursor Check_recipe_orgn_access(vresp_id NUMBER, vOwner_orgn_id NUMBER) IS
1718 SELECT 1
1719 FROM org_access_view
1720 WHERE responsibility_id = vresp_id
1721 AND organization_id = vOwner_orgn_id;
1722
1723 BEGIN
1724 IF (l_debug = 'Y') THEN
1725 gmd_debug.put_line('In GMD_COMMON_VAL.UPDATE_ALLOWED - '
1726 ||' Entity = '||Entity||' and Entity id = '
1727 ||Entity_id);
1728 END IF;
1729 IF (Entity = 'FORMULA') THEN
1730 SELECT delete_mark, formula_status
1731 INTO l_delete_mark, l_status_code
1732 FROM fm_form_mst
1733 WHERE formula_id = Entity_id;
1734 ELSIF (Entity = 'RECIPE') THEN
1735
1739 WHERE recipe_id = Entity_id;
1736 SELECT delete_mark, recipe_status, owner_organization_id
1737 INTO l_delete_mark, l_status_code, l_owner_orgn_id
1738 FROM gmd_recipes_b
1740
1741 /* Check if user has access to this Recipe orgn */
1742 OPEN Check_recipe_orgn_access(l_resp_id, l_Owner_orgn_id);
1743 FETCH Check_recipe_orgn_access INTO l_dummy;
1744 IF Check_recipe_orgn_access%NOTFOUND THEN
1745 CLOSE Check_recipe_orgn_access;
1746 Return FALSE;
1747 END IF;
1748 CLOSE Check_recipe_orgn_access;
1749
1750 ELSIF (Entity = 'ROUTING') THEN
1751
1752 SELECT delete_mark, routing_status
1753 INTO l_delete_mark, l_status_code
1754 FROM fm_rout_hdr
1755 WHERE routing_id = Entity_id;
1756 ELSIF (Entity = 'OPERATION') THEN
1757 SELECT delete_mark, operation_status
1758 INTO l_delete_mark, l_status_code
1759 FROM gmd_operations
1760 WHERE oprn_id = Entity_id;
1761 ELSIF (Entity = 'VALIDITY') THEN
1762 SELECT delete_mark, validity_rule_status
1763 INTO l_delete_mark, l_status_code
1764 FROM gmd_recipe_validity_rules
1765 WHERE recipe_validity_rule_id = Entity_id;
1766 END IF;
1767
1768 Get_Status
1769 ( Status_code => l_status_code ,
1770 Meaning => l_meaning ,
1771 Description => l_desc ,
1772 x_return_status => l_return_status
1773 );
1774
1775 -- Added this condition to allow update of end dates for
1776 -- frozen Operations, Routings and Validity Rules
1777 IF ((l_status_code between 900 and 999)
1778 AND (Upper(Update_Column_Name) like '%END_DATE%')) THEN
1779 Return TRUE;
1780 ELSIF ((l_status_code between 200 and 299) OR (l_status_code >= 800) OR
1781 (l_status_code between 500 and 599) OR (l_delete_mark = 1)) THEN
1782 Return FALSE;
1783 ELSE
1784 Return TRUE;
1785 END IF;
1786
1787 return false;
1788 EXCEPTION
1789 WHEN NO_DATA_FOUND THEN
1790 RETURN TRUE;
1791 END UPDATE_ALLOWED;
1792
1793
1794 FUNCTION VERSION_CONTROL_STATE(Entity VARCHAR2, Entity_id NUMBER) RETURN VARCHAR2 IS
1795
1796 l_state VARCHAR2(32) := 'N';
1797 l_status VARCHAR2(30);
1798 l_version_enabled VARCHAR2(1) := 'N';
1799
1800 TYPE Status_ref_cur IS REF CURSOR;
1801 Status_cur Status_ref_cur;
1802
1803 CURSOR get_formula_owner_orgn_id(vformula_id NUMBER) IS
1804 SELECT owner_organization_id
1805 FROM fm_form_mst_b
1806 WHERE formula_id = vformula_id;
1807 CURSOR get_recipe_owner_orgn_id(vrecipe_id NUMBER) IS
1808 SELECT owner_organization_id
1809 FROM gmd_recipes_b
1810 WHERE recipe_id = vrecipe_id;
1811 CURSOR get_routing_owner_orgn_id(vrouting_id NUMBER) IS
1812 SELECT owner_organization_id
1813 FROM gmd_routings_b
1814 WHERE routing_id = vrouting_id;
1815 CURSOR get_operation_owner_orgn_id(voprn_id NUMBER) IS
1816 SELECT owner_organization_id
1817 FROM gmd_operations_b
1818 WHERE oprn_id = voprn_id;
1819
1820 CURSOR get_substitution_owner_orgn_id(vsub_id NUMBER) IS
1821 SELECT owner_organization_id
1822 FROM GMD_ITEM_SUBSTITUTION_HDR_B
1823 WHERE SUBSTITUTION_ID = vsub_id;
1824 l_orgn_id NUMBER;
1825 l_return_status VARCHAR2(10);
1826 BEGIN
1827
1828 -- Check for status that allow the version control
1829 -- e.g normally version control is set beyond
1830 -- status = 'Approved for gen use'
1831
1832 IF (Upper(Entity) = 'FORMULA') THEN
1833 OPEN get_formula_owner_orgn_id(entity_id);
1834 FETCH get_formula_owner_orgn_id INTO l_orgn_id;
1835 CLOSE get_formula_owner_orgn_id;
1836 OPEN Status_cur FOR
1837 Select f.formula_status, s.version_enabled
1838 From fm_form_mst f, gmd_status s
1839 Where f.formula_id = Entity_id
1840 And f.formula_status = s.status_code;
1841 FETCH Status_cur INTO l_status, l_version_enabled;
1842 ClOSE Status_cur;
1843
1844 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1845 P_parm_name => 'GMD_FORMULA_VERSION_CONTROL',
1846 P_parm_value => l_state ,
1847 X_return_status => l_return_status );
1848
1849 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1850 l_state := 'Y';
1851 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1852 l_state := 'O';
1853 ELSE
1854 l_state := 'N';
1855 END IF;
1856
1857 ELSIF (Upper(Entity) = 'RECIPE') THEN
1858 OPEN get_recipe_owner_orgn_id(entity_id);
1859 FETCH get_recipe_owner_orgn_id INTO l_orgn_id;
1860 CLOSE get_recipe_owner_orgn_id;
1861 OPEN Status_cur FOR
1862 Select r.recipe_status, s.version_enabled
1863 From gmd_recipes r, gmd_status s
1864 Where r.recipe_id = Entity_id
1865 And r.recipe_status = s.status_code;
1866 FETCH Status_cur INTO l_status, l_version_enabled;
1867 ClOSE Status_cur;
1868
1869 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1873
1870 P_parm_name => 'GMD_RECIPE_VERSION_CONTROL' ,
1871 P_parm_value => l_state ,
1872 X_return_status => l_return_status );
1874 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1875 l_state := 'Y';
1876 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1877 l_state := 'O';
1878 ELSE
1879 l_state := 'N';
1880 END IF;
1881
1882 ELSIF (Upper(Entity) = 'ROUTING') THEN
1883 OPEN get_routing_owner_orgn_id(entity_id);
1884 FETCH get_routing_owner_orgn_id INTO l_orgn_id;
1885 CLOSE get_routing_owner_orgn_id;
1886 OPEN Status_cur FOR
1887 Select r.routing_status, s.version_enabled
1888 From fm_rout_hdr r, gmd_status s
1889 Where r.routing_id = Entity_id
1890 And r.routing_status = s.status_code;
1891 FETCH Status_cur INTO l_status, l_version_enabled;
1892 ClOSE Status_cur;
1893
1894 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1895 P_parm_name => 'GMD_ROUTING_VERSION_CONTROL' ,
1896 P_parm_value => l_state ,
1897 X_return_status => l_return_status );
1898
1899 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1900 l_state := 'Y';
1901 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1902 l_state := 'O';
1903 ELSE
1904 l_state := 'N';
1905 END IF;
1906
1907 ELSIF (Upper(Entity) = 'OPERATION') THEN
1908 OPEN get_operation_owner_orgn_id(entity_id);
1909 FETCH get_operation_owner_orgn_id INTO l_orgn_id;
1910 CLOSE get_operation_owner_orgn_id;
1911 OPEN Status_cur FOR
1912 Select r.operation_status, s.version_enabled
1913 From gmd_operations r, gmd_status s
1914 Where r.oprn_id = Entity_id
1915 And r.operation_status = s.status_code;
1916 FETCH Status_cur INTO l_status, l_version_enabled;
1917 ClOSE Status_cur;
1918
1919 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1920 P_parm_name => 'GMD_OPERATION_VERSION_CONTROL' ,
1921 P_parm_value => l_state ,
1922 X_return_status => l_return_status );
1923
1924 /*SELECT TRIM(FND_PROFILE.VALUE('GMD_OPERATION_VERSION_CONTROL'))
1925 INTO l_state
1926 FROM sys.dual;*/
1927
1928 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1929 l_state := 'Y';
1930 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1931 l_state := 'O';
1932 ELSE
1933 l_state := 'N';
1934 END IF;
1935 ELSIF (Upper(Entity) = 'SUBSTITUTION') THEN -- Bug number 4479101
1936 OPEN get_substitution_owner_orgn_id(entity_id);
1937 FETCH get_substitution_owner_orgn_id INTO l_orgn_id;
1938 CLOSE get_substitution_owner_orgn_id;
1939
1940 OPEN Status_cur FOR
1941 Select r.substitution_status, s.version_enabled
1942 From gmd_item_substitution_hdr_b r, gmd_status s
1943 Where r.substitution_id = Entity_id
1944 And r.substitution_status = s.status_code;
1945 FETCH Status_cur INTO l_status, l_version_enabled;
1946 ClOSE Status_cur;
1947
1948 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => l_orgn_id ,
1949 P_parm_name => 'GMD_SUBS_VERSION_CONTROL' ,
1950 P_parm_value => l_state ,
1951 X_return_status => l_return_status );
1952
1953 IF ((l_state = 'Y') AND (l_version_enabled = 'Y')) THEN
1954 l_state := 'Y';
1955 ELSIF ((l_state = 'O') AND (l_version_enabled = 'Y')) THEN
1956 l_state := 'O';
1957 ELSE
1958 l_state := 'N';
1959 END IF;
1960
1961 ELSE
1962 l_state := 'N';
1963 END IF;
1964
1965 return l_state;
1966
1967 END VERSION_CONTROL_STATE;
1968
1969
1970 /*****************************************************************************
1971 * PROCEDURE
1972 * set_conc_program_Status
1973 *
1974 * DESCRIPTION
1975 * Sets the concurrent manager completion status
1976 *
1977 * INPUT PARAMETERS
1978 * p_errstat - Completion status, must be one of 'NORMAL', 'WARNING', or
1979 * 'ERROR'
1980 * p_errmsg - Completion message to be passed back
1981 *
1982 * HISTORY
1983 * 05-31-2001 Shyam Sitaraman Created
1984 *
1985 ******************************************************************************/
1986
1987 PROCEDURE set_conc_program_Status (
1988 p_errstat IN VARCHAR2,
1989 p_errmsg IN VARCHAR2
1990 )
1991 IS
1992 l_retval BOOLEAN;
1993 BEGIN
1994
1995 l_retval := fnd_concurrent.set_completion_status(p_errstat,p_errmsg);
1996
1997 END set_conc_program_Status;
1998
1999
2000 /* **********************************************************************
2001 * PROCEDURE
2002 * Run_status_update
2003 *
2004 * Parameter Input
2005 * pCalendar_code - Calendar code set in cm_cldr_dtl
2006 * pPeriod_code - Period code set in cm_cldr_dtl
2007 * pCost_mthd_code - Cost_mthd_code from cm_cldr_hdr
2008 *
2012 * p_retcode Return code to the Concurrent Manager
2009 * Parameters Output
2010 *
2011 * p_errbuf Completion message to the Concurrent Manager
2013 *
2014 *
2015 * Description
2016 *
2017 * Procedure is used by costing to update the GMD tables with frozen status.
2018 * This procedure is registered as a concurrent program
2019 * Whenever costing updates the period status in cm_cldr_dtl table
2020 * from 0 to 1 , the trigger fires and submits a request for a
2021 * concurrent job.
2022 *
2023 * History
2024 * 05/31/2001 Shyam Created
2025 * 11/14/2001 Shyam Added fm context after the cost update.
2026 * 12-FEB-2002 Shyam BUG # 2222882: Changes to Procedure GMD_RUN_STATUS_UPDATE.
2027 * The FORALL condition for BULK update was changed to
2028 * conventional FOR LOOP statement and makes update for each row.
2029 *
2030 * 12-FEB-2002 Shyam Created an NVL ststement for routing_id that is returned after
2031 * the recipe table is updated. Recipe can have null routing_ids and
2032 * returning a NULL routing_id into variable l_routing_id can cause issues.
2033 * 01-MAR-2002 Shyam Added validation for Run_status_Updtae to check if the cost method is 'Standard'
2034 * and period status is 1.
2035 * 01/16/2003 Shyam UPdate made on status that are not obsoleted or on-hold
2036 *
2037 * *********************************************************************** */
2038
2039 PROCEDURE Run_status_update( p_errbuf OUT NOCOPY VARCHAR2,
2040 p_retcode OUT NOCOPY VARCHAR2,
2041 pCalendar_code IN cm_cmpt_dtl.calendar_code%TYPE,
2042 pPeriod_code IN cm_cmpt_dtl.period_code%TYPE,
2043 pCost_mthd_code IN cm_cmpt_dtl.cost_mthd_code%TYPE) IS
2044
2045 x_return_status VARCHAR2(1) := 'S';
2046 l_Recipe_Id NUMBER;
2047 l_formula_Id NUMBER;
2048 l_routing_Id NUMBER;
2049 l_oprn_Id NUMBER;
2050 l_period_cnt NUMBER;
2051 l_cost_type NUMBER;
2052
2053
2054 TYPE VRtbl IS TABLE OF GMD_RECIPE_VALIDITY_RULES.Recipe_Validity_Rule_Id%TYPE;
2055 VRList VRtbl;
2056
2057 CURSOR FROZEN_EFF_CUR IS
2058 SELECT distinct(fmeff_id) fmeff_id from cm_cmpt_dtl
2059 WHERE Calendar_code = pCalendar_code AND
2060 Period_code = pPeriod_code AND
2061 Cost_mthd_code = pCost_mthd_code AND
2062 ROLLOVER_IND = 1;
2063
2064 CURSOR Get_Period_Status IS
2065 SELECT count(*) FROM cm_cldr_dtl
2066 WHERE Calendar_code = pCalendar_code AND
2067 Period_code = pPeriod_code AND
2068 period_status = 1;
2069
2070 CURSOR Get_Cost_type IS
2071 SELECT cost_type from cm_mthd_mst
2072 WHERE cost_mthd_code = pCost_mthd_code;
2073
2074 CURSOR Get_Recipe_id(vValidity_Rule_id NUMBER) IS
2075 SELECT recipe_id from gmd_recipe_validity_rules
2076 WHERE recipe_validity_rule_id = vValidity_Rule_id;
2077
2078 CURSOR Get_FmRout_id(vRecipe_id NUMBER) IS
2079 SELECT formula_id, routing_id From gmd_recipes_b
2080 WHERE recipe_id = vRecipe_id;
2081
2082 Standard_costing_exception EXCEPTION;
2083 Period_status_exception EXCEPTION;
2084
2085 BEGIN
2086 SAVEPOINT update_status;
2087
2088 OPEN Get_Period_Status;
2089 FETCH Get_Period_Status INTO l_period_cnt;
2090 IF ((Get_Period_Status%NOTFOUND) OR (l_period_cnt = 0)) THEN
2091 CLOSE Get_Period_Status;
2092 Raise Period_Status_exception;
2093 END IF;
2094 CLOSE Get_Period_Status;
2095
2096 OPEN Get_Cost_type;
2097 FETCH Get_Cost_type INTO l_cost_type;
2098 IF ((Get_Cost_type%NOTFOUND) OR (l_cost_type = 1)) THEN
2099 CLOSE Get_Cost_type;
2100 Raise Standard_costing_exception;
2101 END IF;
2102 CLOSE Get_Cost_Type;
2103
2104 OPEN FROZEN_EFF_CUR;
2105 FETCH FROZEN_EFF_CUR BULK COLLECT INTO VRList;
2106 CLOSE FROZEN_EFF_CUR;
2107
2108 IF (VRList.count > 0) THEN
2109
2110 FOR i IN 1 .. VRList.count LOOP
2111
2112 /* Update the VR - status field */
2113 Update gmd_recipe_validity_rules
2114 SET validity_rule_status = '900'
2115 WHERE recipe_validity_rule_id = VRList(i)
2116 AND to_number(validity_rule_status) < 800;
2117
2118 OPEN Get_Recipe_id(VRList(i));
2119 FETCH Get_Recipe_id INTO l_Recipe_id;
2120 CLOSE Get_Recipe_id;
2121
2122 /* Update the Recipe - status field */
2123 UPDATE gmd_recipes_b
2124 SET recipe_status = '900'
2125 WHERE recipe_id = l_Recipe_Id
2126 AND to_number(recipe_status) < 800;
2127
2128 OPEN Get_FmRout_id(l_recipe_id);
2129 FETCH Get_FmRout_id INTO l_formula_id, l_routing_id;
2130 CLOSE Get_FmRout_id;
2131
2135 WHERE formula_id = l_formula_id
2132 /* Update the formula and routing status */
2133 UPDATE fm_form_mst_b
2134 SET formula_status = '900'
2136 AND to_number(formula_status) < 800;
2137
2138 UPDATE gmd_routings_b
2139 SET routing_status = '900'
2140 WHERE routing_id = l_routing_id
2141 AND to_number(routing_status) < 800;
2142
2143 /* Update oprns status */
2144 IF (l_routing_id IS NOT NULL) THEN
2145 UPDATE gmd_operations_b
2146 SET operation_status = '900'
2147 WHERE oprn_id IN (SELECT oprn_id
2148 FROM fm_rout_dtl d
2149 WHERE routing_id = l_routing_id)
2150 AND to_number(operation_status) < 800;
2151 END IF;
2152 END LOOP;
2153
2154 ELSE /* when VRList count is <= 0 */
2155 p_retcode := 0;
2156 p_errbuf := NULL;
2157 set_conc_program_Status('NORMAL', 'Did not update the status on GMD tables');
2158
2159 END IF;
2160
2161 /* If o.k until here */
2162 p_retcode := 0;
2163 p_errbuf := NULL;
2164 set_conc_program_Status('NORMAL', NULL);
2165
2166 /* sets the context for formula security */
2167 gmd_p_fs_context.set_additional_attr;
2168
2169 EXCEPTION
2170 WHEN Standard_costing_exception THEN
2171 p_retcode := 3;
2172 p_errbuf := NULL;
2173 set_conc_program_Status('ERROR','Invalid cost method only standard cost methods are allowed ' );
2174 ROLLBACK to update_status;
2175 WHEN Period_status_exception THEN
2176 p_retcode := 3;
2177 p_errbuf := NULL;
2178 set_conc_program_Status('ERROR','Invalid period status only frozen periods are allowed' );
2179 ROLLBACK to update_status;
2180 WHEN OTHERS THEN
2181 p_retcode := 3;
2182 p_errbuf := NULL;
2183 set_conc_program_Status('ERROR',sqlerrm);
2184 ROLLBACK to update_status;
2185
2186 END Run_Status_Update;
2187 /* **********************************************************************
2188 * PROCEDURE
2189 * check_formula_item_access
2190 *
2191 * Parameter Input
2192 * pFormula_id Formula Id
2193 * pInventory_Item_ID Inventory Item Id
2194 * Parameters Output
2195 * X_return_status Return Status
2196 * S when the org access are true
2197 * E when known error
2198 * U when unknown error
2199 *
2200 *
2201 * Description
2202 *
2203 * Procedure is used to identify the organization's item access used
2204 * for the recipe, override organizations and validaity rules.
2205 *
2206 * History
2207 * 05-Dec-2005 KSHUKLA Created
2208 * 30-May-2006 Kalyani Changed the order of variables in cursor fetch.
2209 * 12-Jun-2006 Kalyani Added new parameter pRevision and code to check the orgn access
2210 * for the item revision.
2211 * 21-Apr-2008 RLNAGARA Bug 6982623 Added validation for formula orgn item access.
2212 * *********************************************************************** */
2213 PROCEDURE CHECK_FORMULA_ITEM_ACCESS(pFormula_id IN NUMBER,
2214 pInventory_Item_ID IN NUMBER,
2215 x_return_status OUT NOCOPY VARCHAR2,
2216 pRevision IN VARCHAR2) IS
2217
2221 SELECT fm.formula_no, fm.formula_vers, organization_code
2218 --RLNAGARA start Bug 6982623 Added validation for formula item access
2219
2220 CURSOR Cur_formula_own (p_formula_id NUMBER, p_inventory_item_id NUMBER) IS
2222 FROM fm_form_mst fm, mtl_parameters o
2223 WHERE formula_id =p_formula_id
2224 AND fm.owner_organization_id = o.organization_id
2225 AND formula_status < 1000
2226 AND NOT EXISTS (SELECT 1
2227 FROM mtl_system_items m
2228 WHERE inventory_item_id = p_inventory_item_id
2229 AND recipe_enabled_flag = 'Y'
2230 AND m.organization_id = fm.owner_organization_id);
2231
2232 CURSOR Cur_formula_own_revision (p_formula_id NUMBER, p_inventory_item_id NUMBER,p_revision VARCHAR2) IS
2233 SELECT fm.formula_no, fm.formula_vers, organization_code
2234 FROM fm_form_mst fm, mtl_parameters o
2235 WHERE formula_id =p_formula_id
2236 AND fm.owner_organization_id = o.organization_id
2237 AND formula_status < 1000
2238 AND NOT EXISTS (SELECT 1
2239 FROM mtl_system_items m, mtl_item_revisions mir
2240 WHERE m.inventory_item_id = p_inventory_item_id
2241 AND mir.revision = p_revision
2242 AND m.inventory_item_id = mir.inventory_item_id
2243 AND m.recipe_enabled_flag = 'Y'
2244 AND m.organization_id = fm.owner_organization_id
2245 AND mir.organization_id = m.organization_id);
2246
2247 --RLNAGARA end Bug 6982623
2248
2249 -- Lists the organization id for the recipe which are not owned
2250 -- By the owner organization id of formula
2251 CURSOR Cur_recipe_own (p_formula_id NUMBER, p_inventory_item_id NUMBER) IS
2252 SELECT recipe_no, recipe_version, organization_code
2253 FROM gmd_recipes_b r, mtl_parameters o
2254 WHERE formula_id = p_formula_id
2255 AND r.owner_organization_id = o.organization_id
2256 AND recipe_status < 1000
2257 AND NOT EXISTS (SELECT 1
2258 FROM mtl_system_items m
2259 WHERE inventory_item_id = p_inventory_item_id
2260 AND recipe_enabled_flag = 'Y'
2261 AND m.organization_id = r.owner_organization_id);
2262 -- Bug 5237351 added
2263 CURSOR Cur_recipe_own_revision (p_formula_id NUMBER, p_inventory_item_id NUMBER,p_revision VARCHAR2) IS
2264 SELECT recipe_no, recipe_version, organization_code
2265 FROM gmd_recipes_b r, mtl_parameters o
2266 WHERE formula_id = p_formula_id
2267 AND r.owner_organization_id = o.organization_id
2268 AND recipe_status < 1000
2269 AND NOT EXISTS (SELECT 1
2270 FROM mtl_system_items m, mtl_item_revisions mir
2271 WHERE m.inventory_item_id = p_inventory_item_id
2272 AND mir.revision = p_revision
2273 AND m.inventory_item_id = mir.inventory_item_id
2274 AND m.recipe_enabled_flag = 'Y'
2275 AND m.organization_id = r.owner_organization_id
2276 AND mir.organization_id = m.organization_id
2277 );
2278
2279 -- Cursors to get the recipe over rides for a recipe id
2280 CURSOR Cur_recipe_override(p_formula_id number, p_inventory_item_id number) IS
2281 select r.recipe_no, r.recipe_version, o.organization_code
2282 from gmd_recipe_process_loss rpl, gmd_recipes_b r, mtl_parameters o
2283 where r.recipe_id = rpl.recipe_id
2284 AND r.formula_id = p_formula_id
2285 AND r.owner_organization_id <> rpl.organization_id
2286 AND rpl.organization_id = o.organization_id
2287 AND r.recipe_status < 1000
2288 AND NOT EXISTS (SELECT 1
2289 FROM mtl_system_items m
2290 WHERE inventory_item_id = p_inventory_item_id
2291 AND recipe_enabled_flag = 'Y'
2292 AND m.organization_id = rpl.organization_id);
2293
2294 -- Bug 5237351 added
2295 CURSOR Cur_recipe_override_revision(p_formula_id number, p_inventory_item_id number,p_revision VARCHAR2) IS
2296 select r.recipe_no, r.recipe_version, o.organization_code
2297 from gmd_recipe_process_loss rpl, gmd_recipes_b r, mtl_parameters o
2298 where r.recipe_id = rpl.recipe_id
2299 AND r.formula_id = p_formula_id
2300 AND r.owner_organization_id <> rpl.organization_id
2301 AND rpl.organization_id = o.organization_id
2302 AND r.recipe_status < 1000
2303 AND NOT EXISTS (SELECT 1
2304 FROM mtl_system_items m, mtl_item_revisions mir
2305 WHERE m.inventory_item_id = p_inventory_item_id
2306 AND mir.revision = p_revision
2307 AND m.inventory_item_id = mir.inventory_item_id
2308 AND m.recipe_enabled_flag = 'Y'
2309 AND m.organization_id = rpl.organization_id
2310 AND mir.organization_id = m.organization_id);
2311
2312 -- Cursor to get the validity rules for the recipes
2313 CURSOR Cur_recipe_validity(p_formula_id number,p_inventory_item_id number) IS
2314 select o.organization_code,r.recipe_no, r.recipe_version
2315 from gmd_recipe_validity_rules rvr, gmd_recipes_b r, mtl_parameters o
2316 where r.recipe_id = rvr.recipe_id
2317 and r.formula_id = p_formula_id
2318 and o.organization_id = rvr.organization_id
2319 AND rvr.organization_id <> r.owner_organization_id
2320 AND r.recipe_status < 1000
2321 AND rvr.validity_rule_status < 1000
2322 AND NOT EXISTS (SELECT 1
2323 FROM mtl_system_items m
2324 WHERE inventory_item_id = p_inventory_item_id
2325 AND recipe_enabled_flag = 'Y'
2329 select o.organization_code,r.recipe_no, r.recipe_version
2326 AND m.organization_id = rvr.organization_id);
2327 -- Bug 5237351 added
2328 CURSOR Cur_recipe_validity_revision(p_formula_id number,p_inventory_item_id number,p_revision VARCHAR2) IS
2330 from gmd_recipe_validity_rules rvr, gmd_recipes_b r, mtl_parameters o
2331 where r.recipe_id = rvr.recipe_id
2332 and r.formula_id = p_formula_id
2333 and o.organization_id = rvr.organization_id
2334 AND r.recipe_status < 1000
2335 AND rvr.validity_rule_status < 1000
2336 AND NOT EXISTS (SELECT 1
2337 FROM mtl_system_items m, mtl_item_revisions mir
2338 WHERE m.inventory_item_id = p_inventory_item_id
2339 AND mir.revision = p_revision
2340 AND m.inventory_item_id = mir.inventory_item_id
2341 AND m.recipe_enabled_flag = 'Y'
2342 AND m.organization_id = rvr.organization_id
2343 AND mir.organization_id = m.organization_id
2344 );
2345 -- Bug 5237351 added
2346 CURSOR Cur_item_rev_ctl(v_item_id NUMBER) IS
2347 select revision_qty_control_code
2348 from mtl_system_items_b
2349 where inventory_item_id = v_item_id;
2350
2351 l_rev_ctl number; -- Bug 5237351 added
2352 l_org_id number;
2353 l_organization_code varchar2(3);
2354 l_formula_no varchar2(32);
2355 l_formula_vers number; --RLNAGARA B6982623
2356 l_recipe_no varchar2(32);
2357 l_recipe_version number;
2358 X_global_return_status varchar2(1) := FND_API.g_ret_sts_success;
2359
2360 VALIDATION_FAIL EXCEPTION;
2361 NO_FORMULA EXCEPTION;
2362
2363 BEGIN
2364 --
2365 -- Find the formula no for the formula id
2366 --
2367 -- Check for the organization access to the formula
2368 IF pFormula_id IS NULL THEN
2369 RAISE NO_FORMULA;
2370
2371 END IF;
2372 -- Bug 5237351 added
2373 OPEN Cur_item_rev_ctl(pInventory_item_id);
2374 FETCH Cur_item_rev_ctl INTO l_rev_ctl;
2375 CLOSE Cur_item_rev_ctl;
2376
2377 --RLNAGARA start Bug 6982623 Added validation for formula item access
2378
2379 OPEN Cur_formula_own (pFormula_id, pInventory_item_id);
2380 FETCH Cur_formula_own INTO l_formula_no, l_formula_vers, l_organization_code;
2381 IF Cur_formula_own%FOUND THEN
2382 CLOSE Cur_formula_own;
2383 FND_MESSAGE.set_name('GMD','GMD_FORM_OWNORG_NO_ACCESS');
2384 FND_MESSAGE.set_token('FORMULA_NO',l_formula_no);
2385 FND_MESSAGE.set_token('FORMULA_VERSION',l_formula_vers);
2386 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2387 fnd_msg_pub.ADD;
2388 X_return_status := FND_API.g_ret_sts_error;
2389 RAISE VALIDATION_FAIL;
2390 END IF;
2391 CLOSE Cur_formula_own;
2392
2393 IF l_rev_ctl = 2 and pRevision IS NOT NULL THEN
2394 OPEN Cur_formula_own_revision (pFormula_id, pInventory_item_id,pRevision);
2395 FETCH Cur_formula_own_revision INTO l_formula_no, l_formula_vers, l_organization_code;
2396 IF Cur_formula_own_revision%FOUND THEN
2397 CLOSE Cur_formula_own_revision;
2398 FND_MESSAGE.set_name('GMD','GMD_FORM_REV_OWNORG_NO_ACCESS');
2399 FND_MESSAGE.set_token('FORMULA_NO',l_formula_no);
2400 FND_MESSAGE.set_token('FORMULA_VERSION',l_formula_vers);
2401 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2402 fnd_msg_pub.ADD;
2403 X_return_status := FND_API.g_ret_sts_error;
2404 RAISE VALIDATION_FAIL;
2405 END IF;
2406 CLOSE Cur_formula_own_revision;
2407 END IF;
2408
2409 --RLNAGARA end Bug 6982623
2410
2411 OPEN Cur_recipe_own (pFormula_id, pInventory_item_id);
2412 FETCH Cur_recipe_own INTO l_recipe_no, l_recipe_version, l_organization_code;
2413 IF Cur_recipe_own%FOUND THEN
2414 CLOSE Cur_recipe_own;
2415 FND_MESSAGE.set_name('GMD','GMD_OWNER_ORG_NOT_ACCESSIBLE');
2416 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2417 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2418 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2419 fnd_msg_pub.ADD;
2420 X_return_status := FND_API.g_ret_sts_error;
2421 RAISE VALIDATION_FAIL;
2422 END IF;
2423 CLOSE Cur_recipe_own;
2424 -- Bug 5237351 added
2425 IF l_rev_ctl = 2 and pRevision IS NOT NULL THEN
2426 OPEN Cur_recipe_own_revision (pFormula_id, pInventory_item_id,pRevision);
2427 FETCH Cur_recipe_own_revision INTO l_recipe_no, l_recipe_version, l_organization_code;
2428 IF Cur_recipe_own_revision%FOUND THEN
2429 CLOSE Cur_recipe_own_revision;
2430 FND_MESSAGE.set_name('GMD','GMD_REV_OWNORG_NOT_ACCESSIBLE');
2431 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2432 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2433 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2434 fnd_msg_pub.ADD;
2435 X_return_status := FND_API.g_ret_sts_error;
2436 RAISE VALIDATION_FAIL;
2437 END IF;
2438 CLOSE Cur_recipe_own_revision;
2439 END IF;
2440 -- Check the organization access for the override organizations
2441 OPEN Cur_recipe_override (pFormula_id, pInventory_item_id);
2442 -- Bug 5237126 MK Changed the order of variables.
2443 FETCH Cur_recipe_override INTO l_recipe_no, l_recipe_version, l_organization_code;
2444 IF Cur_recipe_override%FOUND THEN
2445 CLOSE Cur_recipe_override;
2446 FND_MESSAGE.set_name('GMD','GMD_OVERRIDE_ORG_NOT_ACCESSIBL');
2450 fnd_msg_pub.ADD;
2447 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2448 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2449 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2451 X_return_status := FND_API.g_ret_sts_error;
2452 RAISE VALIDATION_FAIL;
2453 END IF;
2454 CLOSE Cur_recipe_override;
2455 -- Bug 5237351 added
2456 IF l_rev_ctl = 2 and pRevision IS NOT NULL THEN
2457 OPEN Cur_recipe_override_revision (pFormula_id, pInventory_item_id, pRevision);
2458 FETCH Cur_recipe_override_revision INTO l_recipe_no, l_recipe_version, l_organization_code;
2459 IF Cur_recipe_override_revision%FOUND THEN
2460 CLOSE Cur_recipe_override_revision;
2461 FND_MESSAGE.set_name('GMD','GMD_REV_OVERORG_NOT_ACCESSIBL');
2462 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2463 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2464 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2465 fnd_msg_pub.ADD;
2466 X_return_status := FND_API.g_ret_sts_error;
2467 RAISE VALIDATION_FAIL;
2468 END IF;
2469 CLOSE Cur_recipe_override_revision;
2470 END IF;
2471 OPEN Cur_recipe_validity (pFormula_id, pInventory_item_id);
2472 FETCH Cur_recipe_validity INTO l_organization_code, l_recipe_no, l_recipe_version;
2473 IF Cur_recipe_validity%FOUND THEN
2474 CLOSE Cur_recipe_validity;
2475 FND_MESSAGE.set_name('GMD','GMD_VALIDITY_OWNER_ORG_NOT_ACC');
2476 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2477 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2478 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2479 fnd_msg_pub.ADD;
2480 X_return_status := FND_API.g_ret_sts_error;
2481 RAISE VALIDATION_FAIL;
2482 END IF;
2483 CLOSE Cur_recipe_validity;
2484 -- Bug 5237351 added
2485 IF l_rev_ctl = 2 and pRevision IS NOT NULL THEN
2486 OPEN Cur_recipe_validity_revision (pFormula_id, pInventory_item_id, pRevision);
2487 FETCH Cur_recipe_validity_revision INTO l_organization_code, l_recipe_no, l_recipe_version;
2488 IF Cur_recipe_validity_revision%FOUND THEN
2489 CLOSE Cur_recipe_validity_revision;
2490 FND_MESSAGE.set_name('GMD','GMD_REV_VALIDITY_ORG_NOT_ACC');
2491 FND_MESSAGE.set_token('RECIPE_NO',l_recipe_no);
2492 FND_MESSAGE.set_token('RECIPE_VERSION',l_recipe_version);
2493 FND_MESSAGE.SET_TOKEN('ORGANIZATION_CODE',l_organization_code);
2494 fnd_msg_pub.ADD;
2495 X_return_status := FND_API.g_ret_sts_error;
2496 RAISE VALIDATION_FAIL;
2497 END IF;
2498 CLOSE Cur_recipe_validity_revision;
2499 END IF;
2500
2501 -- Final Return Status of the API
2502 x_return_status := FND_API.G_RET_STS_SUCCESS;
2503 EXCEPTION
2504 WHEN VALIDATION_FAIL THEN
2505 x_return_status := FND_API.G_RET_STS_ERROR;
2506 WHEN NO_FORMULA THEN
2507 x_return_status := FND_API.G_RET_STS_SUCCESS;
2508
2509 WHEN OTHERS THEN
2510 X_return_status := FND_API.g_ret_sts_unexp_error;
2511
2512 END check_formula_item_access;
2513
2514 -- Kapil ME Auto-Prod :Bug# 5716318
2515 /* Api start of comments
2516 +============================================================================
2517 | PROCEDURE NAME
2518 | CALCULATE_TOTAL_PRODUCT_QTY
2519 |
2520 | DESCRIPTION
2521 | Procedure to calculate Product Qty autmatically.
2522 |
2523 | INPUT PARAMETERS
2524 | pFormula_id NUMBER
2525 |
2526 | OUTPUT PARAMETERS
2527 | x_msg_data VARCHAR2
2528 | x_return_status VARCHAR2
2529 | x_msg_count NUMBER
2530 |
2531 | HISTORY
2532 | 05-FEB-2007 Kapil M Bug# 5716318 Created.
2533 |
2534 +=============================================================================
2535 Api end of comments
2536 */
2537 PROCEDURE Calculate_Total_Product_Qty ( p_formula_id IN gmd_recipes.formula_id%TYPE,
2538 x_return_status OUT NOCOPY VARCHAR2,
2539 x_msg_count OUT NOCOPY NUMBER,
2540 x_msg_data OUT NOCOPY VARCHAR2) IS
2541
2542 -- Definition of variables
2543 l_auto_calc VARCHAR2(1) := 'N';
2544 l_count NUMBER (5) DEFAULT 0;
2545 l_material_tab gmd_common_scale.scale_tab;
2546 l_uom fm_matl_dtl.item_um%TYPE;
2547 l_conv_uom VARCHAR2(30);
2548 l_temp_qty NUMBER := 0;
2549
2550 l_ingredient_qty NUMBER := 0;
2551 l_by_product_qty NUMBER := 0;
2552 l_qty_touse NUMBER := 0;
2553 l_prod_cnt NUMBER := 0;
2554 l_prod_ratio NUMBER := 1;
2555 l_one_prodqty NUMBER;
2556 l_prod_fix_cnt NUMBER := 0;
2557 l_prod_fix_qty NUMBER := 0;
2558 l_prod_prop_cnt NUMBER := 0;
2559 l_prod_prop_qty NUMBER := 0;
2560 lhdrqty NUMBER := 0;
2561 l_different_uom VARCHAR2 (1) := 'N';
2562 l_return_status VARCHAR2(1);
2563 p_orgn_id NUMBER;
2564 l_yield_type VARCHAR2(30);
2565 l_uom_class VARCHAR2(10);
2569
2566 l_common_uom_class VARCHAR2(10);
2567
2568 CANNOT_CONVERT EXCEPTION;
2570 TYPE temp_prod_qty_rec IS RECORD (
2571 inventory_item_id NUMBER,
2572 orig_qty NUMBER,
2573 orig_uom VARCHAR2 (4),
2574 cov_qty NUMBER,
2575 cov_uom VARCHAR2 (4),
2576 line_no NUMBER,
2577 prod_percent NUMBER
2578 );
2579 TYPE temp_prod_tbl IS TABLE OF temp_prod_qty_rec
2580 INDEX BY BINARY_INTEGER;
2581
2582 temp_prod_tbl1 temp_prod_tbl;
2583 -- Cursor Definitions
2584
2585 CURSOR Cur_get_formula_org IS
2586 SELECT OWNER_ORGANIZATION_ID
2587 FROM FM_FORM_MST
2588 WHERE formula_id = p_formula_id;
2589
2590 CURSOR get_formula_lines (vformula_id NUMBER) IS
2591 SELECT line_no, line_type, inventory_item_id, qty, DETAIL_UOM, scale_type,
2592 contribute_yield_ind, scale_multiple, scale_rounding_variance,
2593 rounding_direction , prod_percent
2594 FROM fm_matl_dtl
2595 WHERE formula_id = p_formula_id
2596 AND contribute_yield_ind = 'Y' /* Added in Bug No.6314028 */
2597 ORDER BY line_type;
2598
2599 CURSOR get_unit_of_measure(v_yield_type VARCHAR2) IS
2600 SELECT unit_of_measure
2601 FROM mtl_units_of_measure
2602 WHERE uom_class = v_yield_type
2603 AND base_uom_flag = 'Y';
2604
2605 BEGIN
2606
2607 x_return_status := FND_API.G_RET_STS_SUCCESS;
2608 FND_MSG_PUB.initialize;
2609
2610 -- Check ORganization Parameters
2611 OPEN Cur_get_formula_org;
2612 FETCH Cur_get_formula_org INTO p_orgn_id;
2613 CLOSE Cur_get_formula_org;
2614 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => p_orgn_id ,
2615 P_parm_name => 'GMD_AUTO_PROD_CALC' ,
2616 P_parm_value => l_auto_calc ,
2617 X_return_status => x_return_status );
2618
2619 IF l_auto_calc = 'Y' THEN -- Perform Auto Calculation
2620
2621 -- Get the Yield type UOM - NPD Convergence
2622 GMD_API_GRP.FETCH_PARM_VALUES ( P_orgn_id => p_orgn_id ,
2623 P_parm_name => 'FM_YIELD_TYPE' ,
2624 P_parm_value => l_yield_type ,
2625 X_return_status => x_return_status );
2626 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
2627 RETURN;
2628 END IF;
2629
2630 /* Populate a local pl/sql table that will be iterated for further processings. */
2631 FOR l_rec IN get_formula_lines (p_formula_id)
2632 LOOP
2633 l_count := l_count + 1;
2634
2635 IF NVL (l_uom, l_rec.detail_uom) <> l_rec.detail_uom
2636 THEN
2637 l_different_uom := 'Y';
2638 END IF;
2639 l_material_tab (l_count).line_no := l_rec.line_no;
2640 l_material_tab (l_count).line_type := l_rec.line_type;
2641 l_material_tab (l_count).inventory_item_id := l_rec.inventory_item_id;
2642 l_material_tab (l_count).qty := l_rec.qty;
2643 l_material_tab (l_count).detail_uom := l_rec.detail_uom;
2644 l_material_tab (l_count).scale_type := l_rec.scale_type;
2645 l_material_tab (l_count).contribute_yield_ind :=
2646 l_rec.contribute_yield_ind;
2647 l_material_tab (l_count).scale_multiple := l_rec.prod_percent;
2648
2649 l_material_tab (l_count).scale_rounding_variance :=
2650 l_rec.scale_rounding_variance;
2651 l_material_tab (l_count).rounding_direction :=
2652 l_rec.rounding_direction;
2653 l_uom := l_rec.detail_uom;
2654 END LOOP;
2655
2656 /* UOM COnversions - Get the common UOM for conversions */
2657
2658 FOR i IN 1 .. l_material_tab.COUNT
2659 LOOP
2660 IF l_material_tab(i).detail_uom IS NOT NULL THEN
2661 /* Get the common UOM class of the detail lines UOM */
2662 SELECT uom_class
2663 INTO l_uom_class
2664 FROM mtl_units_of_measure
2665 where uom_code = l_material_tab (i).detail_uom;
2666
2667 /* If different UOM - get the yield type UOM for conversions. */
2668 IF NVL(l_common_uom_class,l_uom_class) <> l_uom_class THEN
2669 OPEN get_unit_of_measure(l_yield_type);
2670 FETCH get_unit_of_measure INTO l_conv_uom;
2671 CLOSE get_unit_of_measure;
2672 END IF;
2673 l_common_uom_class := l_uom_class;
2674 END IF;
2675 END LOOP;
2676 /* If all the UOMs belong to the same class, Get the base UOM for conversion. */
2677 IF l_conv_uom IS NULL THEN
2678 OPEN get_unit_of_measure(l_common_uom_class);
2679 FETCH get_unit_of_measure INTO l_conv_uom;
2680 CLOSE get_unit_of_measure;
2681
2682 END IF;
2683
2684 -- Calculate the totla material line quantities
2685 FOR i IN 1 .. l_material_tab.COUNT
2686 LOOP
2687 IF l_different_uom = 'Y'
2688 THEN
2689 l_temp_qty := INV_CONVERT.inv_um_convert(item_id => l_material_tab (i).inventory_item_id
2690 ,precision => 5
2691 ,from_quantity => l_material_tab (i).qty
2692 ,from_unit => l_material_tab (i).detail_uom
2696
2693 ,to_unit => l_conv_uom
2694 ,from_name => NULL
2695 ,to_name => NULL);
2697 IF l_temp_qty < 0
2698 THEN
2699 fnd_message.set_name ('GMD', 'GMD_UOM_CONV_ERROR');
2700 fnd_message.set_token('UOM',l_conv_uom);
2701 fnd_msg_pub.ADD;
2702 RAISE CANNOT_CONVERT;
2703 END IF;
2704 ELSE
2705 l_temp_qty := l_material_tab (i).qty;
2706 END IF;
2707
2708 -- If it is ingredient then see if this is contributing to yield or not
2709 IF l_material_tab (i).line_type = -1
2710 AND l_material_tab (i).contribute_yield_ind = 'Y'
2711 THEN
2712 l_ingredient_qty := NVL (l_ingredient_qty, 0) + l_temp_qty;
2713 ELSIF l_material_tab (i).line_type = 2
2714 THEN -- By product
2715 l_by_product_qty := l_by_product_qty + l_temp_qty;
2716 ELSIF l_material_tab (i).line_type = 1
2717 THEN -- Products
2718 l_prod_cnt := l_prod_cnt + 1;
2719
2720 /* See if the product is of scale type fixed, if yes, then do not update and also use to subtract from the total
2721 ingredient qty to be distributed. */
2722 IF l_material_tab (i).scale_type = 0
2723 THEN
2724 l_prod_fix_cnt := l_prod_fix_cnt + 1;
2725 l_prod_fix_qty := l_prod_fix_qty + l_temp_qty;
2726 ELSE
2727 l_prod_prop_cnt := l_prod_prop_cnt + 1;
2728 l_prod_prop_qty := l_prod_prop_qty + l_temp_qty;
2729 temp_prod_tbl1 (l_prod_prop_cnt).inventory_item_id :=
2730 l_material_tab (i).inventory_item_id;
2731 temp_prod_tbl1 (l_prod_prop_cnt).cov_qty := l_temp_qty;
2732 -- Conv UOM
2733 temp_prod_tbl1 (l_prod_prop_cnt).cov_uom := l_conv_uom;
2734 temp_prod_tbl1 (l_prod_prop_cnt).orig_qty :=
2735 l_material_tab (i).qty;
2736 temp_prod_tbl1 (l_prod_prop_cnt).orig_uom :=
2737 l_material_tab (i).detail_uom;
2738 temp_prod_tbl1 (l_prod_prop_cnt).line_no :=
2739 l_material_tab (i).line_no;
2740 temp_prod_tbl1 (l_prod_prop_cnt).prod_percent :=
2741 l_material_tab (i).scale_multiple;
2742
2743 END IF;
2744 END IF;
2745 END LOOP;
2746
2747 /* Get the Quantity to be distributed among Products.
2748 Qty = Sum(INGR) - SUM(BY-PRODS) - SUM(PROD-FIXED) */
2749 l_qty_touse :=
2750 l_ingredient_qty - NVL (l_by_product_qty, 0)
2751 - NVL (l_prod_fix_qty, 0);
2752
2753 /* Now Calculate the Product Qty based on ratio */
2754 FOR i IN 1 .. temp_prod_tbl1.COUNT
2755 LOOP
2756 IF l_prod_prop_qty > 0 THEN
2757 /* Check whether Percentages have been enterd for all Proportional Products. */
2758 IF temp_prod_tbl1 (i).prod_percent IS NULL THEN
2759 fnd_message.set_name ('GMD', 'GMD_ENTER_PERCENTAGE_YES');
2760 fnd_msg_pub.ADD;
2761 RAISE CANNOT_CONVERT;
2762 END IF;
2763 l_prod_ratio := temp_prod_tbl1 (i).prod_percent / 100;
2764 ELSE
2765 l_prod_ratio := 1;
2766 END IF;
2767
2768 -- Calculate the specific prod qty
2769 IF l_qty_touse > 0
2770 THEN
2771 l_one_prodqty := l_qty_touse * l_prod_ratio;
2772 ELSE
2773 l_one_prodqty := temp_prod_tbl1 (i).cov_qty;
2774 END IF;
2775
2776 -- Also keep updating the formula level product qty.
2777 lhdrqty := lhdrqty + l_one_prodqty;
2778 -- Changed
2779 IF l_different_uom = 'Y'
2780 THEN
2781 l_temp_qty := INV_CONVERT.inv_um_convert(item_id => l_material_tab (i).inventory_item_id
2782 ,precision => 5
2783 ,from_quantity => l_one_prodqty
2784 ,from_unit => l_conv_uom
2785 ,to_unit => temp_prod_tbl1 (i).orig_uom
2786 ,from_name => NULL
2787 ,to_name => NULL);
2788
2789 IF l_temp_qty < 0
2790 THEN
2791 x_return_status := 'Q';
2792 fnd_message.set_name ('GMD', 'GMD_UOM_CONV_ERROR');
2793 fnd_message.set_token('UOM',l_conv_uom);
2794 fnd_msg_pub.ADD;
2795 EXIT;
2796 END IF;
2797 ELSE
2798 l_temp_qty := l_one_prodqty;
2799 END IF;
2800
2801 UPDATE fm_matl_dtl
2802 SET qty = ROUND (l_temp_qty, 5),
2803 DETAIL_UOM = temp_prod_tbl1 (i).orig_uom
2804 WHERE formula_id = p_formula_id
2805 AND line_type = 1
2806 AND inventory_item_id = temp_prod_tbl1 (i).inventory_item_id
2807 AND line_no = temp_prod_tbl1 (i).line_no;
2808 END LOOP;
2809
2810 /* Finally update the formula level product qty as prod qty + by product qty. */
2811 lhdrqty := lhdrqty + l_prod_fix_qty + NVL (l_by_product_qty, 0);
2812
2813 -- Update formula Header also
2814 UPDATE fm_form_mst_b
2815 SET total_output_qty = lhdrqty
2816 WHERE formula_id = p_formula_id;
2817 /* Get the message count from the Message stack */
2818 END IF;
2819 fnd_msg_pub.count_and_get (p_count => x_msg_count,
2820 p_data => x_msg_data);
2821 EXCEPTION
2822 WHEN CANNOT_CONVERT THEN
2823 x_return_status := fnd_api.g_ret_sts_unexp_error;
2824 fnd_msg_pub.count_and_get (p_count => x_msg_count,
2825 p_data => x_msg_data);
2826 END Calculate_Total_Product_Qty ;
2827
2828
2829 END; /* Package Body GMD_COMMON_VAL */