1 PACKAGE BODY gme_complete_batch_pvt AS
2 /* $Header: GMEVCMBB.pls 120.31.12020000.2 2012/07/26 15:29:35 gmurator ship $ */
3
4 G_DEBUG VARCHAR2(5) := FND_PROFILE.VALUE('AFLOG_LEVEL');
5
6 g_pkg_name VARCHAR2(30) := 'GME_COMPLETE_BATCH_PVT';
7
8
9 PROCEDURE complete_batch
10 (p_batch_header_rec IN gme_batch_header%ROWTYPE
11 ,x_exception_material_tbl IN OUT NOCOPY gme_common_pvt.exceptions_tab
12 ,x_batch_header_rec OUT NOCOPY gme_batch_header%ROWTYPE
13 ,x_return_status OUT NOCOPY VARCHAR2) IS
14
15
16
17
18 CURSOR Cur_associated_step(v_matl_dtl_id NUMBER) IS
19 SELECT step_status
20 FROM gme_batch_steps s, gme_batch_step_items item
21 WHERE s.batchstep_id = item.batchstep_id
22 AND item.material_detail_id = v_matl_dtl_id;
23
24 CURSOR Cur_get_step_to_complete(v_batch_id NUMBER) IS
25 SELECT *
26 FROM gme_batch_steps
27 WHERE batch_id = v_batch_id
28 AND step_status NOT IN (gme_common_pvt.g_step_completed, gme_common_pvt.g_step_closed);
29
30 CURSOR Cur_get_phantom_batch(v_batch_id NUMBER) IS
31 SELECT hdr.*
32 FROM gme_material_details dtl, gme_batch_header hdr
33 WHERE dtl.batch_id = v_batch_id
34 AND dtl.line_type = gme_common_pvt.g_line_type_ing
35 AND dtl.phantom_id IS NOT NULL
36 AND hdr.batch_id = dtl.phantom_id
37 AND hdr.batch_status NOT IN (gme_common_pvt.g_batch_completed, gme_common_pvt.g_batch_closed);
38
39 CURSOR cur_lock_batch_ingredients (v_batch_id NUMBER) IS
40 SELECT *
41 FROM gme_material_details
42 WHERE batch_id = v_batch_id
43 AND (line_type = gme_common_pvt.g_line_type_ing OR
44 (line_type = gme_common_pvt.g_line_type_prod AND phantom_line_id IS NOT NULL))
45 FOR UPDATE OF actual_qty NOWAIT;
46
47 CURSOR Cur_lock_batch_products(v_batch_id NUMBER) IS
48 SELECT *
49 FROM gme_material_details
50 WHERE batch_id = v_batch_id
51 AND line_type IN (gme_common_pvt.g_line_type_prod,gme_common_pvt.g_line_type_byprod)
52 AND phantom_line_id IS NULL -- no phantom products
53 FOR UPDATE OF actual_qty NOWAIT;
54
55 l_api_name CONSTANT VARCHAR2 (30) := 'COMPLETE_BATCH';
56 l_table_name CONSTANT VARCHAR2 (30) := 'gme_material_details';
57
58 l_step_status NUMBER;
59 l_matl_dtl_tab_ing gme_common_pvt.material_details_tab;
60 l_matl_dtl_tab gme_common_pvt.material_details_tab;
61 l_btch_hdr gme_batch_header%ROWTYPE;
62 l_btch_hdr_tab gme_common_pvt.batch_headers_tab;
63 l_matl_dtl gme_material_details%ROWTYPE;
64 l_matl_dtl_rec gme_material_details%ROWTYPE;
65 l_step_tab gme_common_pvt.steps_tab;
66 l_batch_step_rec gme_batch_steps%ROWTYPE;
67 l_yield_type NUMBER;
68 l_phantom_batch gme_batch_header%ROWTYPE;
69 l_phantom_batch_rec gme_batch_header%ROWTYPE;
70 l_item_rec mtl_system_items_b%ROWTYPE;
71 l_return_status VARCHAR2(1);
72 l_yield BOOLEAN;
73 l_exception_qty NUMBER;
74
75
76 locked_by_other_user EXCEPTION;
77 batch_lines_locked EXCEPTION;
78 --Bug#5296812
79 error_get_item EXCEPTION;
80 error_update_batch EXCEPTION;
81 error_process_material EXCEPTION;
82 error_complete_batch EXCEPTION;
83 error_complete_step_rec EXCEPTION;
84 error_release_batch EXCEPTION;
85
86 PRAGMA exception_init (locked_by_other_user, -54);
87
88 BEGIN
89 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
90 gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
91 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' Completing batch_id='||p_batch_header_rec.batch_id);
92 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' actual_cmplt_date='||to_char(p_batch_header_rec.actual_cmplt_date, 'YYYY-MON-DD HH24:MI:SS'));
93 END IF;
94
95 /* Set the return status to success initially */
96 x_return_status := FND_API.G_RET_STS_SUCCESS;
97
98 -- set output structure
99 x_batch_header_rec := p_batch_header_rec;
100
101 -- if the batch is pending, call release batch
102 IF p_batch_header_rec.batch_status = gme_common_pvt.g_batch_pending THEN
103 -- call release batch
104 gme_release_batch_pvt.release_batch
105 (p_batch_header_rec => p_batch_header_rec
106 ,x_batch_header_rec => x_batch_header_rec
107 ,x_return_status => l_return_status
108 ,x_exception_material_tbl => x_exception_material_tbl);
109 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
110 x_return_status := l_return_status;
111 RAISE error_release_batch;
112 END IF;
113
114 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
115 x_return_status := gme_common_pvt.g_exceptions_err;
116 END IF;
117 END IF;
118
119 -- set batch status
120 x_batch_header_rec.batch_status := gme_common_pvt.g_batch_completed;
121
122 -- no need to set the actual completion date because it is expected to have been in p_batch_header_rec
123
124 -- Update the batch header
125 IF NOT gme_batch_header_dbl.update_row (p_batch_header => x_batch_header_rec) THEN
126 RAISE error_update_batch;
127 END IF;
128
129 -- Update WHO columns for output structure
130 x_batch_header_rec.last_updated_by := gme_common_pvt.g_user_ident;
131 x_batch_header_rec.last_update_date := gme_common_pvt.g_timestamp;
132 x_batch_header_rec.last_update_login := gme_common_pvt.g_login_id;
133
134 -- Lock all the ingredents and phantom product lines associated with the batch
135 OPEN cur_lock_batch_ingredients (x_batch_header_rec.batch_id);
136 FETCH cur_lock_batch_ingredients BULK COLLECT INTO l_matl_dtl_tab_ing;
137 IF SQLCODE = -54 THEN
138 CLOSE cur_lock_batch_ingredients;
139 RAISE batch_lines_locked;
140 END IF;
141 CLOSE cur_lock_batch_ingredients;
142
143 OPEN Cur_lock_batch_products (x_batch_header_rec.batch_id);
144 FETCH Cur_lock_batch_products BULK COLLECT INTO l_matl_dtl_tab;
145 IF SQLCODE = -54 THEN
146 CLOSE Cur_lock_batch_products;
147 RAISE batch_lines_locked;
148 END IF;
149 CLOSE Cur_lock_batch_products;
150
151 -- Process the products...
152 -- 1) yield auto yield products
153 -- 2) set wip plan qty
154
155 FOR i IN 1..l_matl_dtl_tab.COUNT LOOP
156 l_matl_dtl_rec := l_matl_dtl_tab(i);
157
158 l_yield_type := l_matl_dtl_rec.release_type;
159 IF l_yield_type = gme_common_pvt.g_mtl_autobystep_release THEN
160 OPEN Cur_associated_step(l_matl_dtl_rec.material_detail_id);
161 FETCH Cur_associated_step INTO l_step_status;
162 IF Cur_associated_step%NOTFOUND THEN
163 l_yield_type := gme_common_pvt.g_mtl_auto_release;
164 END IF;
165 CLOSE Cur_associated_step;
166 END IF;
167
168 IF l_matl_dtl_rec.line_type IN (gme_common_pvt.g_line_type_prod, gme_common_pvt.g_line_type_byprod) THEN
169 IF l_yield_type <> gme_common_pvt.g_mtl_autobystep_release THEN
170 IF l_yield_type = gme_common_pvt.g_mtl_auto_release THEN
171 l_yield := TRUE;
172 ELSE
173 l_yield := FALSE;
174 END IF;
175
176 process_material
177 (p_material_detail_rec => l_matl_dtl_rec
178 ,p_yield => l_yield
179 ,p_trans_date => x_batch_header_rec.actual_cmplt_date
180 ,p_update_inv_ind => x_batch_header_rec.update_inventory_ind
181 ,x_exception_material_tbl => x_exception_material_tbl
182 ,x_return_status => l_return_status);
183
184 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
185 x_return_status := l_return_status;
186 RAISE error_process_material;
187 END IF;
188
189 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
190 x_return_status := gme_common_pvt.g_exceptions_err;
191 END IF;
192 -- Pawan Kumar added this for bug 5109095
193 ELSE -- of l_yield_type <> gme_common_pvt.g_mtl_autobystep_release THEN
194 -- This will insert exception all completed step products and byprodcuts.
195 --Bug#5296812 Added the call to the item record.Added the condition to check the inv update ind,and transaction ind.Start
196 gme_material_detail_pvt.get_item_rec
197 (p_org_id => l_matl_dtl_rec.organization_id
198 ,p_item_id => l_matl_dtl_rec.inventory_item_id
199 ,x_item_rec => l_item_rec
200 ,x_return_status => l_return_status);
201 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
202 x_return_status := l_return_status;
203 RAISE error_get_item;
204 END IF;
205 IF p_batch_header_rec.update_inventory_ind = 'Y' AND l_item_rec.mtl_transactions_enabled_flag = 'Y' THEN
206 --Bug#5296812 End.
207 IF l_step_status = gme_common_pvt.g_step_completed THEN
208
209 l_exception_qty := l_matl_dtl_rec.wip_plan_qty - l_matl_dtl_rec.actual_qty;
210
211 IF l_exception_qty < 0 THEN
212 l_exception_qty := 0;
213 END IF;
214
215 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
216 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' calling create_batch_exception for material_detail_id='||l_matl_dtl_rec.material_detail_id);
217 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' actual_qty='||l_matl_dtl_rec.actual_qty);
218 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' wip_plan_qty='||l_matl_dtl_rec.wip_plan_qty);
219 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception qty='||l_exception_qty);
220 END IF;
221
222 gme_release_batch_pvt.create_batch_exception
223 (p_material_dtl_rec => l_matl_dtl_rec
224 ,p_pending_move_order_ind => NULL -- don't know...allow to calculate
225 ,p_pending_rsrv_ind => NULL -- don't know...allow to calculate
226 ,p_transacted_qty => 0 -- only auto rel products are transacted.. this is for ing
227 ,p_exception_qty => l_exception_qty
228 ,p_force_unconsumed => fnd_api.g_false
229 ,x_exception_material_tbl => x_exception_material_tbl
230 ,x_return_status => l_return_status);
231
232 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
233 x_return_status := l_return_status;
234 RAISE error_complete_batch;
235 END IF;
236
237 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
238 x_return_status := gme_common_pvt.g_exceptions_err;
239 END IF;
240
241 END IF;-- IF l_step_status = gme_common_pvt.g_step_completed THEN
242 END IF;--IF p_batch_header_rec.update_inventory_ind = 'Y'.....
243 -- Pawan Kumar added above for bug 5109095
244 END IF; -- IF l_yield_type <> gme_common_pvt.g_mtl_autobystep_release THEN
245 END IF; -- IF l_matl_dtl_rec.line_type IN (gme_common_pvt.g_line_type_prod, gme_common_pvt.g_line_type_byprod)
246 END LOOP;
247
248 -- Complete any steps that are not complete or closed
249 OPEN Cur_get_step_to_complete(p_batch_header_rec.batch_id);
250 FETCH Cur_get_step_to_complete BULK COLLECT INTO l_step_tab;
251 CLOSE Cur_get_step_to_complete;
252
253 FOR i in 1..l_step_tab.COUNT LOOP
254 -- Bug 7475553 - removing unconditional overwriting of step dates as it should consider
255 -- if the step is already released. The dates will now be set in complete step code.
256 -- l_step_tab(i).actual_start_date := p_batch_header_rec.actual_start_date;
257 -- l_step_tab(i).actual_cmplt_date := p_batch_header_rec.actual_cmplt_date;
258 -- Also, pass in x_batch_header_rec instead of p_batch_header_rec so that step
259 -- code logic works properly as it needs the proper batch_status value.
260 gme_complete_batch_step_pvt.complete_step_recursive
261 (p_batch_step_rec => l_step_tab(i)
262 ,p_batch_header_rec => x_batch_header_rec
263 ,x_batch_step_rec => l_batch_step_rec
264 ,x_exception_material_tbl => x_exception_material_tbl
265 ,x_return_status => l_return_status);
266
267 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
268 x_return_status := l_return_status;
269 RAISE error_complete_step_rec;
270 END IF;
271
272 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
273 x_return_status := gme_common_pvt.g_exceptions_err;
274 END IF;
275 END LOOP;
276
277 -- Complete any phantom batches that are not complete or closed
278 OPEN Cur_get_phantom_batch(p_batch_header_rec.batch_id);
279 FETCH Cur_get_phantom_batch BULK COLLECT INTO l_btch_hdr_tab;
280 CLOSE Cur_get_phantom_batch;
281
282 -- Complete any phantom batches...
283 FOR i IN 1..l_btch_hdr_tab.COUNT LOOP
284 l_btch_hdr_tab(i).actual_cmplt_date := x_batch_header_rec.actual_cmplt_date;
285
286 complete_batch
287 (p_batch_header_rec => l_btch_hdr_tab(i)
288 ,x_exception_material_tbl => x_exception_material_tbl
289 ,x_batch_header_rec => l_btch_hdr
290 ,x_return_status => l_return_status);
291
292 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
293 x_return_status := l_return_status;
294 RAISE error_complete_batch;
295 END IF;
296
297 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
298 x_return_status := gme_common_pvt.g_exceptions_err;
299 END IF;
300
301 END LOOP; -- FOR i IN 1..l_btch_hdr_tab.COUNT LOOP
302
303 -- examine all non-phantom ingredients to determine if there's an exception
304 -- phantom products are reported at the time of yield, so don't double report with phantom ingredient
305 -- all other products are reported in either process material (non auto yield) or yield_material (auto yield)
306 FOR i IN 1..l_matl_dtl_tab_ing.COUNT LOOP
307 l_matl_dtl_rec := l_matl_dtl_tab_ing(i);
308 IF l_matl_dtl_rec.line_type = gme_common_pvt.g_line_type_ing THEN
309 -- don't check for unconsumed first because even if it's fully consumed,
310 -- but has reservation or MO, want to report it
311 --Bug#5296812 Added the call to the item record.Added the condition to check the inv update ind,and transaction ind.Start.
312 gme_material_detail_pvt.get_item_rec
313 (p_org_id => l_matl_dtl_rec.organization_id
314 ,p_item_id => l_matl_dtl_rec.inventory_item_id
315 ,x_item_rec => l_item_rec
316 ,x_return_status => l_return_status);
317 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
318 x_return_status := l_return_status;
319 RAISE error_get_item;
320 END IF;
321 IF p_batch_header_rec.update_inventory_ind = 'Y' AND
322 l_item_rec.mtl_transactions_enabled_flag = 'Y' THEN
323 --Bug#5296812 End.
324 l_exception_qty := l_matl_dtl_rec.wip_plan_qty - l_matl_dtl_rec.actual_qty;
325
326 IF l_exception_qty < 0 THEN
327 l_exception_qty := 0;
328 END IF;
329
330 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
331 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' calling create_batch_exception for material_detail_id='||l_matl_dtl_rec.material_detail_id);
332 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' actual_qty='||l_matl_dtl_rec.actual_qty);
333 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' wip_plan_qty='||l_matl_dtl_rec.wip_plan_qty);
334 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception qty='||l_exception_qty);
335 END IF;
336
337 gme_release_batch_pvt.create_batch_exception
338 (p_material_dtl_rec => l_matl_dtl_rec
339 ,p_pending_move_order_ind => NULL -- don't know...allow to calculate
340 ,p_pending_rsrv_ind => NULL -- don't know...allow to calculate
341 ,p_transacted_qty => 0 -- only auto rel products are transacted.. this is for ing
342 ,p_exception_qty => l_exception_qty
343 ,p_force_unconsumed => fnd_api.g_false
344 ,x_exception_material_tbl => x_exception_material_tbl
345 ,x_return_status => l_return_status);
346
347 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
348 x_return_status := l_return_status;
349 RAISE error_complete_batch;
350 END IF;
351
352 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
353 x_return_status := gme_common_pvt.g_exceptions_err;
354 END IF;
355 END IF; --IF p_batch_header_rec.update_inventory_ind = 'Y'...
356 END IF;
357 END LOOP;
358
359 -- Bug 12571877 - Pass in correct batch record.
360 IF NOT gme_common_pvt.create_history
361 -- (p_batch_header_rec => p_batch_header_rec
362 (p_batch_header_rec => x_batch_header_rec
363 ,p_original_status => gme_common_pvt.g_batch_wip
364 ,p_event_id => NVL(gme_common_pvt.g_transaction_header_id,-9999)) THEN
365 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
366 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' create history returned error');
367 END IF;
368 END IF;
369
370 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
371 gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
372 END IF;
373
374 EXCEPTION
375 WHEN error_update_batch THEN
376 gme_common_pvt.log_message ('GME_UNEXPECTED_ERROR', 'ERROR', SQLERRM);
377 x_return_status := FND_API.g_ret_sts_unexp_error;
378 --Bug#5296812 Handling the raised exception error_get_item.
379 WHEN error_process_material OR error_complete_batch OR
380 error_complete_step_rec OR error_release_batch OR error_get_item THEN
381 NULL;
382 WHEN locked_by_other_user or batch_lines_locked THEN
383 gme_common_pvt.log_message (
384 'GME_RECORD_LOCKED',
385 'TABLE_NAME',
386 l_table_name
387 );
388 x_return_status := FND_API.G_RET_STS_ERROR;
389 WHEN OTHERS THEN
390 fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
391 IF (NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT) THEN
392 gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
393 END IF;
394 x_return_status := FND_API.g_ret_sts_unexp_error;
395 END complete_batch;
396
397
398 PROCEDURE process_material
399 (p_material_detail_rec IN gme_material_details%ROWTYPE
400 ,p_yield IN BOOLEAN
401 ,p_trans_date IN DATE
402 ,p_update_inv_ind IN VARCHAR2
403 ,x_exception_material_tbl IN OUT NOCOPY gme_common_pvt.exceptions_tab
404 ,x_return_status OUT NOCOPY VARCHAR2) IS
405
406
407 l_api_name CONSTANT VARCHAR2 (30) := 'process_material';
408
409 l_matl_dtl_rec gme_material_details%ROWTYPE;
410 l_in_phantom_batch_rec gme_batch_header%ROWTYPE;
411 l_phantom_batch_rec gme_batch_header%ROWTYPE;
412 l_return_status VARCHAR2(1);
413 l_item_rec mtl_system_items_b%ROWTYPE;
414 l_actual_qty NUMBER;
415 l_start_actual_qty NUMBER;
416 l_exception_qty NUMBER;
417
418 error_fetch_batch EXCEPTION;
419 error_complete_batch EXCEPTION;
420 error_yield_material EXCEPTION;
421 error_update_row EXCEPTION;
422 error_get_item EXCEPTION;
423 error_batch_exception EXCEPTION;
424
425
426
427 BEGIN
428
429 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
430 gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
431 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' Processing material material_detail_id='||p_material_detail_rec.material_detail_id);
432 END IF;
433
434 /* Set the return status to success initially */
435 x_return_status := FND_API.G_RET_STS_SUCCESS;
436
437 -- Process the material
438 -- 1) complete product
439 -- 2) complete phantom batch for phantom ingredient
440
441 l_matl_dtl_rec := p_material_detail_rec;
442
443 -- if it's a phantom ingredient, then complete the phantom batch
444 -- which will cause the phantom product to be yielded (the passed in ingredient will be consumed in trxm mgr
445
446 -- complete phantom batch
447 IF l_matl_dtl_rec.line_type = gme_common_pvt.g_line_type_ing AND l_matl_dtl_rec.phantom_id IS NOT NULL THEN -- phantom ingredient -> complete the phantom batch
448 l_phantom_batch_rec.batch_id := l_matl_dtl_rec.phantom_id;
449 IF NOT gme_batch_header_dbl.fetch_row(l_phantom_batch_rec, l_phantom_batch_rec) THEN
450 RAISE error_fetch_batch;
451 END IF;
452
453 IF l_phantom_batch_rec.batch_status IN (gme_common_pvt.g_batch_pending, gme_common_pvt.g_batch_wip) THEN
454 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
455 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' processing phantom ingredient material_detail_id='||l_matl_dtl_rec.material_detail_id);
456 END IF;
457 -- pass in the phantom line id so that release batch will know to yield that product
458 l_in_phantom_batch_rec := l_phantom_batch_rec;
459
460 l_in_phantom_batch_rec.actual_start_date := NVL(l_in_phantom_batch_rec.actual_start_date, p_trans_date);
461 l_in_phantom_batch_rec.actual_cmplt_date := p_trans_date;
462
463 complete_batch
464 (p_batch_header_rec => l_in_phantom_batch_rec
465 ,x_exception_material_tbl => x_exception_material_tbl
466 ,x_batch_header_rec => l_phantom_batch_rec
467 ,x_return_status => l_return_status);
468
469 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
470 x_return_status := l_return_status;
471 RAISE error_complete_batch;
472 END IF;
473
474 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
475 x_return_status := gme_common_pvt.g_exceptions_err;
476 END IF;
477 END IF; -- IF l_phantom_batch_rec.batch_status IN (gme_common_pvt.g_batch_pending, gme_common_pvt.g_batch_wip)
478 ELSIF l_matl_dtl_rec.line_type IN (gme_common_pvt.g_line_type_prod, gme_common_pvt.g_line_type_byprod) AND p_yield THEN
479 gme_material_detail_pvt.get_item_rec
480 (p_org_id => l_matl_dtl_rec.organization_id
481 ,p_item_id => l_matl_dtl_rec.inventory_item_id
482 ,x_item_rec => l_item_rec
483 ,x_return_status => l_return_status);
484
485 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
486 x_return_status := l_return_status;
487 RAISE error_get_item;
488 END IF;
489
490 IF p_update_inv_ind = 'Y' AND
491 l_item_rec.mtl_transactions_enabled_flag = 'Y' THEN
492 l_start_actual_qty := l_matl_dtl_rec.actual_qty;
493 yield_material(p_material_dtl_rec => l_matl_dtl_rec
494 ,p_yield_qty => NULL -- take the entire wip plan qty
495 ,p_trans_date => p_trans_date
496 ,p_item_rec => l_item_rec
497 ,p_force_unconsumed => fnd_api.g_false
498 ,x_exception_material_tbl => x_exception_material_tbl
499 ,x_actual_qty => l_actual_qty
500 ,x_return_status => l_return_status);
501
502 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
503 x_return_status := l_return_status;
504 RAISE error_yield_material;
505 END IF;
506
507 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
508 x_return_status := gme_common_pvt.g_exceptions_err;
509 END IF;
510
511 l_matl_dtl_rec.actual_qty := l_actual_qty;
512
513 -- if actual qty is met, we still need to see if there are pending product lots...
514 -- this is not required in yield material... it's a requirement of complete batch
515 IF l_matl_dtl_rec.actual_qty >= l_matl_dtl_rec.wip_plan_qty THEN
516 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
517 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' calling create_batch_exception after yield_material not for unyielded but for possibility of pplots for material_detail_id='||l_matl_dtl_rec.material_detail_id);
518 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' actual_qty='||l_matl_dtl_rec.actual_qty);
519 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' wip_plan_qty='||l_matl_dtl_rec.wip_plan_qty);
520 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception qty='||(l_matl_dtl_rec.actual_qty - l_matl_dtl_rec.wip_plan_qty));
521 END IF;
522
523 gme_release_batch_pvt.create_batch_exception
524 (p_material_dtl_rec => l_matl_dtl_rec
525 ,p_pending_move_order_ind => FALSE -- product doesn't have MO
526 ,p_pending_rsrv_ind => NULL -- let proc figure out; for product, looks at pplot
527 ,p_transacted_qty => l_actual_qty - l_start_actual_qty
528 ,p_exception_qty => 0
529 ,p_force_unconsumed => fnd_api.g_false
530 ,x_exception_material_tbl => x_exception_material_tbl
531 ,x_return_status => l_return_status);
532
533 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
534 x_return_status := l_return_status;
535 RAISE error_yield_material;
536 END IF;
537
538 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
539 x_return_status := gme_common_pvt.g_exceptions_err;
540 END IF;
541 END IF;
542
543 ELSE
544 l_matl_dtl_rec.actual_qty := l_matl_dtl_rec.plan_qty;
545 END IF;
546 ELSE -- check for exception... this should be for all products that are not auto release
547 --Bug#5296812 Added the call to the item record.Added the condition to check the inv update ind,and transaction ind.
548 gme_material_detail_pvt.get_item_rec
549 (p_org_id => l_matl_dtl_rec.organization_id
550 ,p_item_id => l_matl_dtl_rec.inventory_item_id
551 ,x_item_rec => l_item_rec
552 ,x_return_status => l_return_status);
553 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
554 x_return_status := l_return_status;
555 RAISE error_get_item;
556 END IF;
557 IF p_update_inv_ind = 'Y' AND l_item_rec.mtl_transactions_enabled_flag = 'Y' THEN
558 --Bug#5296812 End.
559 l_exception_qty := l_matl_dtl_rec.wip_plan_qty - l_matl_dtl_rec.actual_qty;
560
561 IF l_exception_qty < 0 THEN
562 l_exception_qty := 0;
563 END IF;
564
565 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
566 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' calling create_batch_exception for material_detail_id='||l_matl_dtl_rec.material_detail_id);
567 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' actual_qty='||l_matl_dtl_rec.actual_qty);
568 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' wip_plan_qty='||l_matl_dtl_rec.wip_plan_qty);
569 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception qty='||l_exception_qty);
570 END IF;
571
572 gme_release_batch_pvt.create_batch_exception
573 (p_material_dtl_rec => l_matl_dtl_rec
574 ,p_pending_move_order_ind => FALSE -- product doesn't have MO
575 ,p_pending_rsrv_ind => NULL -- let proc figure out; for product, looks at pplot
576 ,p_transacted_qty => 0 -- products other than auto yield don't get transacted in complete
577 ,p_exception_qty => l_exception_qty
578 ,p_force_unconsumed => fnd_api.g_false
579 ,x_exception_material_tbl => x_exception_material_tbl
580 ,x_return_status => l_return_status);
581
582 IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
583 x_return_status := l_return_status;
584 RAISE error_batch_exception;
585 END IF;
586
587 IF l_return_status = gme_common_pvt.g_exceptions_err THEN
588 x_return_status := gme_common_pvt.g_exceptions_err;
589 END IF;
590 END IF;--IF p_update_inv_ind = 'Y' AND...
591 END IF; -- IF l_matl_dtl_rec.phantom_id IS NOT NULL...
592
593 -- set WIP plan qty
594 -- Commented the below line for Bug 8483455
595 --l_matl_dtl_rec.wip_plan_qty := l_matl_dtl_rec.plan_qty;
596
597 IF NOT gme_material_details_dbl.update_row (l_matl_dtl_rec) THEN
598 RAISE error_update_row;
599 END IF;
600
601 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
602 gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
603 END IF;
604
605 EXCEPTION
606 WHEN error_fetch_batch OR error_update_row THEN
607 gme_common_pvt.log_message ('GME_UNEXPECTED_ERROR', 'ERROR', SQLERRM);
608 x_return_status := FND_API.g_ret_sts_unexp_error;
609 WHEN error_complete_batch OR error_yield_material OR error_get_item OR error_batch_exception THEN
610 NULL;
611 WHEN OTHERS THEN
612 fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
613 IF g_debug <= gme_debug.g_log_procedure THEN
614 gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
615 END IF;
616 x_return_status := FND_API.g_ret_sts_unexp_error;
617 END process_material;
618
619
620 -- Note: p_yield_qty is the target actual qty; for incr, it's also the target, not the incr
621 PROCEDURE yield_material(p_material_dtl_rec IN gme_material_details%ROWTYPE
622 ,p_yield_qty IN NUMBER
623 ,p_trans_date IN DATE
624 ,p_item_rec IN mtl_system_items_b%ROWTYPE
625 ,p_force_unconsumed IN VARCHAR2
626 ,x_exception_material_tbl IN OUT NOCOPY gme_common_pvt.exceptions_tab
627 ,x_actual_qty OUT NOCOPY NUMBER
628 ,x_return_status OUT NOCOPY VARCHAR2) IS
629
630 l_api_name CONSTANT VARCHAR2 (30) := 'YIELD_MATERIAL';
631
632 l_pending_product_lot_tab gme_common_pvt.pending_lots_tab;
633 l_pp_lot_rec gme_pending_product_lots%ROWTYPE;
634 i NUMBER;
635
636 l_yield_qty NUMBER;
637 l_trans_date DATE;
638 l_subinv VARCHAR2(10);
639 l_locator_id NUMBER;
640 l_revision VARCHAR2(3);
641 l_eff_locator_control NUMBER;
642 l_start_actual_qty NUMBER;
643 l_return_status VARCHAR2(1);
644
645 CURSOR cur_get_item_revision(v_item_id NUMBER, v_org_id NUMBER) IS
646 SELECT revision
647 FROM mtl_item_revisions_b
648 WHERE inventory_item_id = v_item_id
649 AND organization_id = v_org_id
650 AND effectivity_date <= gme_common_pvt.g_timestamp
651 ORDER BY effectivity_date desc;
652
653 error_build_trxn EXCEPTION;
654 error_get_exception EXCEPTION;
655 error_nothing_to_yield EXCEPTION;
656 error_get_pplot EXCEPTION;
657 no_yield_required EXCEPTION;
658
659 BEGIN
660
661 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
662 gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
663 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' material_detail_id='||p_material_dtl_rec.material_detail_id);
664 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_yield_qty='||p_yield_qty);
665 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_trans_date='||to_char(p_trans_date,
666 'YYYY-MON-DD HH24:MI:SS'));
667 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' line_no='||p_material_dtl_rec.line_no);
668 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' line_type='||p_material_dtl_rec.line_type);
669 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_force_unconsumed='||p_force_unconsumed);
670 END IF;
671
672 /* Set the return status to success initially */
673 x_return_status := FND_API.G_RET_STS_SUCCESS;
674
675 x_actual_qty := p_material_dtl_rec.actual_qty;
676
677 -- following global is set only for migration purposes, where transactions need not be created,
678 -- this will only be set for complete step; complete batch is not called from migrate; however
679 -- if this is needed for complete batch, logic will work there also
680 IF gme_release_batch_pvt.g_bypass_txn_creation = 1 THEN
681 RAISE no_yield_required;
682 END IF;
683 /*Pawan Kumar 08-25-2006 bug 5486066 added nvl for wip_plan_qty
684 during direct completion, the wip plan qty is also null
685 So this was not getting caught in l_yield_qty <= x_actual_qty and this was
686 sending transaction quantity as null to transactions where it was failing*/
687
688 l_yield_qty := NVL(p_yield_qty, nvl(p_material_dtl_rec.wip_plan_qty,p_material_dtl_rec.plan_qty));
689 l_trans_date := NVL(p_trans_date, gme_common_pvt.g_timestamp);
690
691 l_start_actual_qty := x_actual_qty;
692
693 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
694 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' l_yield_qty='||l_yield_qty);
695 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' l_trans_date='||to_char(l_trans_date, 'YYYY-MON-DD HH24:MI:SS'));
696 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
697 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' l_start_actual_qty='||l_start_actual_qty);
698 END IF;
699
700 IF l_yield_qty <= x_actual_qty THEN
701 -- this returns as success for now; there's nothing additional to yield
702 RAISE error_nothing_to_yield;
703 END IF;
704
705 IF p_material_dtl_rec.subinventory IS NULL THEN
706 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
707 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' subinv on material is NULL; cant yield anything; get exceptions');
708 END IF;
709 RAISE error_get_exception;
710 END IF;
711
712 IF p_material_dtl_rec.locator_id IS NULL THEN
713 -- check if it's locator control, we need a locator...
714 /* Bug 5441643 Added NVL condition for location control code*/
715 l_eff_locator_control :=
716 gme_common_pvt.eff_locator_control
717 (p_organization_id => p_material_dtl_rec.organization_id
718 ,p_org_control => gme_common_pvt.g_org_locator_control
719 ,p_subinventory => p_material_dtl_rec.subinventory
720 ,p_item_control => NVL(p_item_rec.location_control_code,1)
721 ,p_item_loc_restrict => p_item_rec.restrict_locators_code
722 ,p_action => gme_common_pvt.g_prod_comp_txn_action);
723 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
724 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' l_eff_locator_control='||l_eff_locator_control);
725 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' organization_id='||p_material_dtl_rec.organization_id);
726 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' g_org_locator_control='||gme_common_pvt.g_org_locator_control);
727 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' subinventory='||p_material_dtl_rec.subinventory);
728 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' inventory_item_id='||p_item_rec.inventory_item_id);
729 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' location_control_code='||p_item_rec.location_control_code);
730 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' restrict_locators_code='||p_item_rec.restrict_locators_code);
731 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_action='||gme_common_pvt.g_prod_comp_txn_action);
732 END IF;
733 IF l_eff_locator_control <> 1 THEN
734 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
735 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' locator on material is NULL and material is eff locator control; cant yield anything; get exceptions');
736 END IF;
737 RAISE error_get_exception;
738 END IF;
739 END IF;
740
741 l_subinv := p_material_dtl_rec.subinventory;
742 l_locator_id := p_material_dtl_rec.locator_id;
743
744 IF p_item_rec.revision_qty_control_code = 2 THEN -- under revision control
745 IF p_material_dtl_rec.revision IS NOT NULL THEN
746 l_revision := p_material_dtl_rec.revision;
747 ELSE
748 OPEN cur_get_item_revision(p_material_dtl_rec.inventory_item_id,
749 p_material_dtl_rec.organization_id);
750 FETCH cur_get_item_revision INTO l_revision;
751 CLOSE cur_get_item_revision;
752 END IF;
753 END IF; -- IF p_revision_qty_control_code = 2
754
755 IF p_item_rec.lot_control_code = 1 THEN -- not lot control
756 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
757 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' item not lot control');
758 END IF;
759
760 build_and_create_transaction
761 (p_mtl_dtl_rec => p_material_dtl_rec
762 ,p_pp_lot_rec => NULL
763 ,p_subinv => l_subinv
764 ,p_locator_id => l_locator_id
765 ,p_trans_date => l_trans_date
766 ,p_yield_qty => l_yield_qty
767 ,p_revision => l_revision
768 ,p_sec_uom_code => p_item_rec.secondary_uom_code
769 ,x_actual_qty => x_actual_qty
770 ,x_return_status => l_return_status);
771
772 IF l_return_status NOT IN (gme_common_pvt.g_not_transactable, FND_API.G_RET_STS_SUCCESS) THEN
773 x_return_status := l_return_status;
774 RAISE error_build_trxn;
775 END IF;
776 ELSE -- lot control... go to pending product lots
777 gme_pending_product_lots_pvt.get_pending_lot
778 (p_material_detail_id => p_material_dtl_rec.material_detail_id
779 ,x_return_status => l_return_status
780 ,x_pending_product_lot_tbl => l_pending_product_lot_tab);
781 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
782 x_return_status := l_return_status;
783 RAISE error_get_pplot;
784 END IF;
785
786 i := 1;
787
788 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
789 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' l_yield_qty='||l_yield_qty);
790 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
791 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' count from pplot='||l_pending_product_lot_tab.COUNT);
792 END IF;
793
794 WHILE l_yield_qty > x_actual_qty AND i <= l_pending_product_lot_tab.COUNT LOOP
795
796 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
797 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' pending lot loop i='||i);
798 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' pending lot loop x_actual_qty='||x_actual_qty);
799 END IF;
800
801 l_pp_lot_rec := l_pending_product_lot_tab(i);
802
803 build_and_create_transaction
804 (p_mtl_dtl_rec => p_material_dtl_rec
805 ,p_pp_lot_rec => l_pp_lot_rec
806 ,p_subinv => l_subinv
807 ,p_locator_id => l_locator_id
808 ,p_trans_date => l_trans_date
809 ,p_yield_qty => l_yield_qty
810 ,p_revision => l_revision
811 ,p_sec_uom_code => p_item_rec.secondary_uom_code
812 ,x_actual_qty => x_actual_qty
813 ,x_return_status => l_return_status);
814 IF l_return_status NOT IN (gme_common_pvt.g_not_transactable, FND_API.G_RET_STS_SUCCESS) THEN
815 x_return_status := l_return_status;
816 RAISE error_build_trxn;
817 END IF;
818
819 i := i + 1; -- move on to the next lot
820 END LOOP;
821 END IF; -- IF p_item_rec.lot_control_code = 1 THEN
822
823 IF x_actual_qty < l_yield_qty THEN
824 RAISE error_get_exception;
825 END IF;
826
827 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
828 gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
829 END IF;
830
831
832 EXCEPTION
833 WHEN error_build_trxn OR error_get_pplot OR no_yield_required THEN
834 NULL;
835 WHEN error_nothing_to_yield THEN
836 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
837 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exiting without yield because actual_qty= '||x_actual_qty||' and target yield qty = '||l_yield_qty);
838 END IF;
839
840 WHEN error_get_exception THEN
841 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
842 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception block for get exceptions:');
843 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
844 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' l_start_actual_qty='||l_start_actual_qty);
845 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' l_yield_qty='||l_yield_qty);
846 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception qty='||(l_yield_qty - x_actual_qty));
847 END IF;
848
849 gme_release_batch_pvt.create_batch_exception
850 (p_material_dtl_rec => p_material_dtl_rec
851 ,p_pending_move_order_ind => FALSE
852 ,p_pending_rsrv_ind => NULL -- let proc figure out; for product, looks at pplot
853 ,p_transacted_qty => x_actual_qty - l_start_actual_qty
854 ,p_exception_qty => l_yield_qty - x_actual_qty
855 ,p_force_unconsumed => p_force_unconsumed
856 ,x_exception_material_tbl => x_exception_material_tbl
857 ,x_return_status => x_return_status);
858
859 WHEN OTHERS THEN
860 fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
861 IF (NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT) THEN
862 gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
863 END IF;
864 x_return_status := FND_API.g_ret_sts_unexp_error;
865 END yield_material;
866
867 PROCEDURE build_and_create_transaction
868 (p_mtl_dtl_rec IN gme_material_details%ROWTYPE
869 ,p_pp_lot_rec IN gme_pending_product_lots%ROWTYPE
870 ,p_subinv IN VARCHAR2
871 ,p_locator_id IN NUMBER
872 ,p_trans_date IN DATE
873 ,p_yield_qty IN NUMBER
874 ,p_revision IN VARCHAR2 DEFAULT NULL
875 ,p_sec_uom_code IN VARCHAR2 DEFAULT NULL
876 ,x_actual_qty IN OUT NOCOPY NUMBER
877 ,x_return_status OUT NOCOPY VARCHAR2) IS
878
879 l_api_name CONSTANT VARCHAR2 (30) := 'build_and_create_transaction';
880
881 l_transaction_rec mtl_transactions_interface%ROWTYPE;
882 l_lot_tbl gme_common_pvt.mtl_trans_lots_inter_tbl;
883 l_trxn_qty NUMBER;
884 l_dtl_qty NUMBER;
885 l_sec_qty NUMBER;
886
887 -- Bug 11725091 - Added following variable and cursor.
888 l_prim_qty NUMBER;
889 l_prim_uom VARCHAR2(3);
890 l_from_um VARCHAR2(3);
891 l_to_um VARCHAR2(3);
892 l_item_no mtl_system_items_kfv.concatenated_segments%TYPE;
893
894 um_convert_error EXCEPTION;
895
896 CURSOR item_no_cursor(v_inventory_item_id NUMBER,
897 v_org_id NUMBER) IS
898 SELECT concatenated_segments, primary_uom_code
899 FROM mtl_system_items_kfv
900 WHERE inventory_item_id = v_inventory_item_id
901 AND organization_id = v_org_id;
902
903 error_build_mmti EXCEPTION;
904 error_create_trxn EXCEPTION;
905 error_relieve_pp_lot EXCEPTION;
906
907 BEGIN
908 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
909 gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
910 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' material_detail_id='||p_mtl_dtl_rec.material_detail_id);
911 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_subinv='||p_subinv);
912 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_locator_id='||p_locator_id);
913 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_yield_qty='||p_yield_qty);
914 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_revision='||p_revision);
915 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_sec_uom_code='||p_sec_uom_code);
916 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
917 END IF;
918
919 /* Set the return status to success initially */
920 x_return_status := FND_API.G_RET_STS_SUCCESS;
921
922 constr_mmti(p_mtl_dtl_rec => p_mtl_dtl_rec
923 ,p_yield_qty => p_yield_qty
924 ,p_subinv => p_subinv
925 ,p_revision => p_revision
926 ,p_locator_id => p_locator_id
927 ,p_pp_lot_rec => p_pp_lot_rec
928 ,x_mmti_rec => l_transaction_rec
929 ,x_mmli_tbl => l_lot_tbl
930 ,x_sec_qty => l_sec_qty
931 ,x_dtl_qty => l_dtl_qty
932 ,x_return_status => x_return_status);
933
934 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
935 RAISE error_build_mmti;
936 END IF;
937
938 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
939 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' after constr_mmti l_dtl_qty := '||l_dtl_qty);
940 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' after constr_mmti l_sec_qty := '||l_sec_qty);
941 END IF;
942
943 -- Bug 11725091 - Let's fetch this data right up front even though it may not be used.
944 OPEN item_no_cursor(p_mtl_dtl_rec.inventory_item_id, p_mtl_dtl_rec.organization_id);
945 FETCH item_no_cursor INTO l_item_no, l_prim_uom;
946 CLOSE item_no_cursor;
947
948 -- Bug 7262112 - Added '=' to condition. No need to recompute secondary values if yielding the full amount.
949 IF l_dtl_qty <= p_yield_qty - x_actual_qty THEN
950 l_trxn_qty := l_dtl_qty;
951 ELSE
952 l_trxn_qty := p_yield_qty - x_actual_qty;
953 /* Bug 5256543 l_sec_qty was set to null that was incorrect it has to be recalculated from new l_trxn_qty */
954 IF (p_sec_uom_code IS NOT NULL) THEN
955 l_sec_qty := INV_CONVERT.inv_um_convert
956 (item_id => p_mtl_dtl_rec.inventory_item_id
957 ,lot_number => p_pp_lot_rec.lot_number
958 ,organization_id => p_mtl_dtl_rec.organization_id
959 ,PRECISION => gme_common_pvt.g_precision
960 ,from_quantity => l_trxn_qty
961 ,from_unit => p_mtl_dtl_rec.dtl_um
962 ,to_unit => p_sec_uom_code
963 ,from_name => NULL
964 ,to_name => NULL);
965
966 IF l_sec_qty = -99999 THEN
967 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
968 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' inv_convert.inv_um_convert returned error');
969 END IF;
970 l_from_um := p_mtl_dtl_rec.dtl_um;
971 l_to_um := p_sec_uom_code;
972 RAISE um_convert_error;
973 END IF;
974 END IF;
975 END IF;
976
977 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
978 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' calculated l_trxn_qty := '||l_trxn_qty);
979 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' calculated l_sec_qty := '||l_sec_qty);
980 END IF;
981
982 IF p_mtl_dtl_rec.line_type = gme_common_pvt.g_line_type_prod THEN
983 l_transaction_rec.transaction_type_id := gme_common_pvt.g_prod_completion;
984 ELSE
985 l_transaction_rec.transaction_type_id := gme_common_pvt.g_byprod_completion;
986 END IF;
987
988 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
989 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' l_transaction_rec.transaction_type_id := '||l_transaction_rec.transaction_type_id);
990 END IF;
991
992 l_transaction_rec.transaction_date := p_trans_date;
993 l_transaction_rec.transaction_quantity := l_trxn_qty;
994 l_transaction_rec.secondary_uom_code := p_sec_uom_code;
995
996 IF l_sec_qty IS NOT NULL THEN
997 l_transaction_rec.secondary_transaction_quantity := l_sec_qty;
998 END IF;
999
1000 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
1001 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' transaction_date='||to_char(l_transaction_rec.transaction_date
1002 ,'YYYY-MON-DD HH24:MI:SS'));
1003 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' transaction_qty='||l_transaction_rec.transaction_quantity);
1004 END IF;
1005
1006 l_transaction_rec.transaction_uom := p_mtl_dtl_rec.dtl_um;
1007
1008 -- Bug 11725091 - Let's initialize primary qty also.
1009 l_prim_qty := l_trxn_qty;
1010 IF (p_mtl_dtl_rec.dtl_um <> l_prim_uom) THEN
1011 l_prim_qty := INV_CONVERT.inv_um_convert
1012 (item_id => p_mtl_dtl_rec.inventory_item_id
1013 ,lot_number => p_pp_lot_rec.lot_number
1014 ,organization_id => p_mtl_dtl_rec.organization_id
1015 ,PRECISION => gme_common_pvt.g_precision
1016 ,from_quantity => l_trxn_qty
1017 ,from_unit => p_mtl_dtl_rec.dtl_um
1018 ,to_unit => l_prim_uom
1019 ,from_name => NULL
1020 ,to_name => NULL);
1021
1022 IF l_prim_qty = -99999 THEN
1023 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
1024 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' inv_convert.inv_um_convert returned error');
1025 END IF;
1026 l_from_um := p_mtl_dtl_rec.dtl_um;
1027 l_to_um := l_prim_uom;
1028 RAISE um_convert_error;
1029 END IF;
1030 END IF;
1031
1032 -- l_prim_qty will always have a value at this point.
1033 l_transaction_rec.primary_quantity := l_prim_qty;
1034 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
1035 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' primary_qty is known:'||l_transaction_rec.primary_quantity);
1036 END IF;
1037
1038 IF l_lot_tbl.count > 0 THEN
1039 IF l_lot_tbl(1).lot_number IS NOT NULL THEN
1040 l_lot_tbl(1).transaction_quantity := l_transaction_rec.transaction_quantity;
1041 l_lot_tbl(1).primary_quantity := l_prim_qty;
1042 IF l_sec_qty IS NOT NULL THEN
1043 l_lot_tbl(1).secondary_transaction_quantity := l_sec_qty;
1044 END IF;
1045 END IF;
1046 END IF;
1047
1048 gme_transactions_pvt.create_material_txn
1049 (p_mmti_rec => l_transaction_rec
1050 ,p_mmli_tbl => l_lot_tbl
1051 ,x_return_status => x_return_status);
1052
1053 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1054 IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
1055 gme_debug.put_line (g_pkg_name||'.'||l_api_name||' gme_transactions_pvt.create_transaction returned error');
1056 END IF;
1057 RAISE error_create_trxn;
1058 END IF;
1059
1060 x_actual_qty := x_actual_qty + l_trxn_qty;
1061
1062 -- If pending product lot, then decrease qty, entry remains if the qty goes to zero
1063 IF p_pp_lot_rec.pending_product_lot_id IS NOT NULL THEN
1064 gme_pending_product_lots_pvt.relieve_pending_lot
1065 (p_pending_lot_id => p_pp_lot_rec.pending_product_lot_id
1066 ,p_quantity => l_trxn_qty
1067 ,p_secondary_quantity => l_sec_qty
1068 ,x_return_status => x_return_status);
1069
1070 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1071 RAISE error_relieve_pp_lot;
1072 END IF;
1073 END IF;
1074
1075 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
1076 gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
1077 gme_debug.put_line(g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
1078 END IF;
1079
1080 EXCEPTION
1081 WHEN um_convert_error THEN
1082
1083 fnd_message.set_name ('GMI', 'IC_API_UOM_CONVERSION_ERROR');
1084 fnd_message.set_token ('ITEM_NO', l_item_no);
1085 fnd_message.set_token ('FROM_UOM',l_from_um);
1086 fnd_message.set_token ('TO_UOM', l_to_um);
1087 fnd_msg_pub.ADD;
1088 x_return_status := FND_API.g_ret_sts_error;
1089 WHEN error_create_trxn OR error_relieve_pp_lot OR error_build_mmti THEN
1090 NULL;
1091 WHEN OTHERS THEN
1092 fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
1093 IF (NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT) THEN
1094 gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
1095 END IF;
1096 x_return_status := FND_API.g_ret_sts_unexp_error;
1097 END build_and_create_transaction;
1098
1099 PROCEDURE constr_mmti
1100 (p_mtl_dtl_rec IN gme_material_details%ROWTYPE
1101 ,p_yield_qty IN NUMBER
1102 ,p_subinv IN VARCHAR2
1103 ,p_locator_id IN NUMBER
1104 ,p_revision IN VARCHAR2
1105 ,p_pp_lot_rec IN gme_pending_product_lots%ROWTYPE
1106 ,x_mmti_rec OUT NOCOPY mtl_transactions_interface%ROWTYPE
1107 ,x_mmli_tbl OUT NOCOPY gme_common_pvt.mtl_trans_lots_inter_tbl
1108 ,x_sec_qty OUT NOCOPY NUMBER
1109 ,x_dtl_qty OUT NOCOPY NUMBER
1110 ,x_return_status OUT NOCOPY VARCHAR2) IS
1111
1112 l_api_name CONSTANT VARCHAR2 (30) := 'CONSTR_MMTI';
1113 BEGIN
1114
1115 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
1116 gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
1117 END IF;
1118
1119 /* Initially let us assign the return status to success */
1120 x_return_status := FND_API.g_ret_sts_success;
1121
1122 -- consturct mtl_transactions_interface
1123 x_mmti_rec.transaction_source_id := p_mtl_dtl_rec.batch_id; -- batch_id
1124 x_mmti_rec.trx_source_line_id := p_mtl_dtl_rec.material_detail_id; -- material_detail_id
1125 x_mmti_rec.inventory_item_id := p_mtl_dtl_rec.inventory_item_id;
1126 x_mmti_rec.organization_id := p_mtl_dtl_rec.organization_id;
1127 x_mmti_rec.subinventory_code := p_subinv;
1128 x_mmti_rec.locator_id := p_locator_id;
1129 x_mmti_rec.revision := p_revision;
1130 x_mmti_rec.transaction_sequence_id := p_pp_lot_rec.pending_product_lot_id;
1131 x_dtl_qty := p_yield_qty;
1132 -- construct mtl_transaction_lots_interface
1133 IF p_pp_lot_rec.lot_number IS NOT NULL THEN
1134 x_mmli_tbl(1).lot_number := p_pp_lot_rec.lot_number;
1135 x_mmli_tbl(1).reason_id := p_pp_lot_rec.reason_id;
1136 /* Bug 5256543 Assign revision only if not null otherwise it will come from mtl dtl line */
1137 IF (p_pp_lot_rec.revision IS NOT NULL) THEN
1138 x_mmti_rec.revision := p_pp_lot_rec.revision;
1139 END IF;
1140 x_mmti_rec.reason_id := p_pp_lot_rec.reason_id;
1141 x_dtl_qty := p_pp_lot_rec.quantity;
1142 x_sec_qty := p_pp_lot_rec.secondary_quantity;
1143 END IF;
1144
1145 IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
1146 gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
1147 END IF;
1148
1149 EXCEPTION
1150 WHEN OTHERS THEN
1151 fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
1152 IF (NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT) THEN
1153 gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
1154 END IF;
1155 x_return_status := FND_API.g_ret_sts_unexp_error;
1156 END constr_mmti;
1157
1158 PROCEDURE validate_batch_for_complete (p_batch_header_rec IN gme_batch_header%ROWTYPE
1159 ,x_batch_header_rec OUT NOCOPY gme_batch_header%ROWTYPE
1160 ,x_return_status OUT NOCOPY VARCHAR2) IS
1161
1162 l_api_name CONSTANT VARCHAR2 (30) := 'validate_batch_for_complete';
1163
1164 CURSOR Cur_gme_batch_steps (v_batch_id NUMBER) IS
1165 SELECT count(1)
1166 FROM gme_batch_steps
1167 WHERE step_status NOT IN (gme_common_pvt.g_step_completed, gme_common_pvt.g_step_closed)
1168 AND batch_id = v_batch_id
1169 AND rownum = 1;
1170
1171 l_is_step NUMBER;
1172 l_batch_header_rec gme_batch_header%ROWTYPE;
1173 CURSOR cur_validity_rule(v_recipe_validity_rule_id NUMBER)
1174 IS
1175 SELECT *
1176 FROM gmd_recipe_validity_rules
1177 WHERE recipe_validity_rule_id = v_recipe_validity_rule_id;
1178
1179 CURSOR cur_validity_status_type(v_validity_rule_status VARCHAR2)
1180 IS
1181 SELECT status_type
1182 FROM gmd_status
1183 WHERE status_code=v_validity_rule_status;
1184
1185 l_validity_rule gmd_recipe_validity_rules%ROWTYPE;
1186 l_status_type GMD_STATUS.status_type%TYPE;
1187 error_vr_not_found EXCEPTION;
1188 error_validity_status EXCEPTION;
1189 error_batch_type EXCEPTION;
1190 error_batch_status EXCEPTION;
1191 error_phantom EXCEPTION;
1192 error_steps_not_complete EXCEPTION;
1193 error_cmplt_date EXCEPTION;
1194 error_future_date EXCEPTION;
1195 error_vr_dates EXCEPTION;
1196 BEGIN
1197 IF NVL (g_debug, gme_debug.g_log_procedure + 1) <=
1198 gme_debug.g_log_procedure THEN
1199 gme_debug.put_line ('Entering api ' || g_pkg_name || '.'
1200 || l_api_name);
1201 END IF;
1202
1203 x_return_status := FND_API.g_ret_sts_success;
1204
1205 -- set output structure
1206 x_batch_header_rec := p_batch_header_rec;
1207
1208 -- set actual complete date if it's not passed
1209 IF p_batch_header_rec.actual_cmplt_date IS NULL THEN
1210 x_batch_header_rec.actual_cmplt_date := SYSDATE;
1211 END IF;
1212
1213 IF p_batch_header_rec.batch_type = gme_common_pvt.g_doc_type_fpo THEN
1214 RAISE error_batch_type;
1215 END IF;
1216
1217 IF p_batch_header_rec.batch_status NOT IN
1218 (gme_common_pvt.g_batch_pending, gme_common_pvt.g_batch_wip) THEN
1219 RAISE error_batch_status;
1220 END IF;
1221
1222 IF p_batch_header_rec.parentline_id IS NOT NULL THEN
1223 RAISE error_phantom;
1224 END IF;
1225
1226 -- Bug 11855868 - Check steps only when enforce step dependency is on.
1227 IF p_batch_header_rec.enforce_step_dependency = 1 THEN
1228 OPEN Cur_gme_batch_steps (p_batch_header_rec.batch_id);
1229 FETCH Cur_gme_batch_steps INTO l_is_step;
1230 CLOSE Cur_gme_batch_steps;
1231
1232 -- Bug 11855868 - Changed condition to compare against zero.
1233 -- IF l_is_step > 1 THEN
1234 IF l_is_step > 0 THEN
1235 RAISE error_steps_not_complete;
1236 END IF;
1237 END IF;/*enforce_step_dependency = 1*/
1238
1239 --Sunith ch.5404329 check validity rule if it's not NULL; it would be NULL in case of LCF
1240 IF p_batch_header_rec.recipe_validity_rule_id IS NOT NULL THEN
1241 -- Bug 13004429 - This check should only be done for a pending batch.
1242 IF p_batch_header_rec.batch_status = 1 THEN
1243 OPEN cur_validity_rule(p_batch_header_rec.recipe_validity_rule_id);
1244 FETCH cur_validity_rule INTO l_validity_rule;
1245 CLOSE cur_validity_rule;
1246
1247 IF l_validity_rule.recipe_validity_rule_id IS NULL THEN -- not found
1248 RAISE error_vr_not_found;
1249 ELSE
1250 -- following prevents user from releasing a pending batch
1251 -- if validity rule is ON_HOLD or OBSOLETE.
1252 OPEN cur_validity_status_type(l_validity_rule.validity_rule_status);
1253 FETCH cur_validity_status_type INTO l_status_type;
1254 CLOSE cur_validity_status_type;
1255
1256 IF l_status_type IN ('1000' ,'800') THEN
1257 RAISE error_validity_status;
1258 END IF;
1259 END IF; -- IF l_validity_rule.recipe_validity_rule_id IS NULL
1260
1261 /* IF l_validity_rule.start_date > x_batch_header_rec.actual_start_date OR
1262 (l_validity_rule.end_date IS NOT NULL AND
1263 l_validity_rule.end_date < x_batch_header_rec.actual_start_date) THEN
1264 RAISE error_vr_dates;
1265 END IF;*/
1266 -- sunitha ch. Bug 5336007 aded call to check_validity_rule_dates and passed p_validate_plan_dates_ind = 1
1267 -- to validate planned start date against validate rule dates
1268 IF NOT gme_common_pvt.check_validity_rule_dates (
1269 p_validity_rule_id => p_batch_header_rec.recipe_validity_rule_id
1270 ,p_start_date => p_batch_header_rec.actual_start_date
1271 ,p_cmplt_date => p_batch_header_rec.actual_cmplt_date
1272 ,p_batch_header_rec => p_batch_header_rec
1273 ,p_validate_plan_dates_ind => 1) THEN
1274 x_return_status := fnd_api.g_ret_sts_error;
1275 RAISE error_vr_dates;
1276 END IF;
1277 -- End Bug 5336007
1278 END IF; -- p_batch_header_rec.batch_status = 1
1279 END IF; -- IF p_batch_header_rec.recipe_validity_rule_id IS NOT NULL
1280
1281 -- validate completion date with actual start date and current date
1282 IF x_batch_header_rec.actual_cmplt_date < x_batch_header_rec.actual_start_date THEN
1283 RAISE error_cmplt_date;
1284 ELSIF x_batch_header_rec.actual_cmplt_date > SYSDATE THEN
1285 RAISE error_future_date;
1286 END IF;
1287
1288 IF NVL (g_debug, gme_debug.g_log_procedure + 1) <=
1289 gme_debug.g_log_procedure THEN
1290 gme_debug.put_line ('Exiting api ' || g_pkg_name || '.' || l_api_name);
1291 END IF;
1292
1293 EXCEPTION
1294 WHEN error_phantom THEN
1295 gme_common_pvt.log_message ('PM_INVALID_PHANTOM_ACTION');
1296 x_return_status := FND_API.G_RET_STS_ERROR;
1297 WHEN error_batch_type OR error_batch_status THEN
1298 gme_common_pvt.log_message('GME_API_INVALID_BATCH_COMPL');
1299 x_return_status := fnd_api.g_ret_sts_error;
1300 WHEN error_steps_not_complete THEN
1301 gme_common_pvt.log_message('GME_STEPS_NOT_COMPLETE');
1302 x_return_status := fnd_api.g_ret_sts_error;
1303 WHEN error_cmplt_date THEN
1304 gme_common_pvt.log_message('GME_INVALID_DATE_RANGE'
1305 ,'DATE1','Completion date'
1306 ,'DATE2','Start date');
1307 x_return_status := fnd_api.g_ret_sts_error;
1308 WHEN error_future_date THEN
1309 fnd_message.set_name ('GMA', 'SY_NOFUTUREDATE');
1310 fnd_msg_pub.ADD;
1311 x_return_status := fnd_api.g_ret_sts_error;
1312 WHEN error_vr_dates THEN
1313 x_return_status := FND_API.G_RET_STS_ERROR;
1314 WHEN OTHERS THEN
1315 fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
1316
1317 IF g_debug <= gme_debug.g_log_procedure THEN
1318 gme_debug.put_line ( 'Unexpected error: '
1319 || g_pkg_name
1320 || '.'
1321 || l_api_name
1322 || ': '
1323 || SQLERRM);
1324 END IF;
1325
1326 x_return_status := fnd_api.g_ret_sts_unexp_error;
1327 END validate_batch_for_complete;
1328
1329 END gme_complete_batch_pvt;