DBA Data[Home] [Help]

PACKAGE BODY: APPS.GME_COMPLETE_BATCH_PVT

Source


1 PACKAGE BODY gme_complete_batch_pvt AS
2 /* $Header: GMEVCMBB.pls 120.22.12010000.2 2008/08/04 18:30:16 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       l_step_tab(i).actual_start_date := p_batch_header_rec.actual_start_date;
255       l_step_tab(i).actual_cmplt_date := p_batch_header_rec.actual_cmplt_date;
256       gme_complete_batch_step_pvt.complete_step_recursive
257         (p_batch_step_rec           => l_step_tab(i)
258         ,p_batch_header_rec         => p_batch_header_rec
259         ,x_batch_step_rec           => l_batch_step_rec
260         ,x_exception_material_tbl   => x_exception_material_tbl
261         ,x_return_status            => l_return_status);
262 
263       IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
264         x_return_status := l_return_status;
265         RAISE error_complete_step_rec;
266       END IF;
267 
268       IF l_return_status = gme_common_pvt.g_exceptions_err THEN
269         x_return_status := gme_common_pvt.g_exceptions_err;
270       END IF;
271     END LOOP;
272 
273     -- Complete any phantom batches that are not complete or closed
274     OPEN Cur_get_phantom_batch(p_batch_header_rec.batch_id);
275     FETCH Cur_get_phantom_batch BULK COLLECT INTO l_btch_hdr_tab;
276     CLOSE Cur_get_phantom_batch;
277 
278     -- Complete any phantom batches...
279     FOR i IN 1..l_btch_hdr_tab.COUNT LOOP
280       l_btch_hdr_tab(i).actual_cmplt_date := x_batch_header_rec.actual_cmplt_date;
281 
282       complete_batch
283               (p_batch_header_rec           => l_btch_hdr_tab(i)
284               ,x_exception_material_tbl     => x_exception_material_tbl
285               ,x_batch_header_rec           => l_btch_hdr
286               ,x_return_status              => l_return_status);
287 
288       IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
289         x_return_status := l_return_status;
290         RAISE error_complete_batch;
291       END IF;
292 
293       IF l_return_status = gme_common_pvt.g_exceptions_err THEN
294         x_return_status := gme_common_pvt.g_exceptions_err;
295       END IF;
296 
297     END LOOP;  -- FOR i IN 1..l_btch_hdr_tab.COUNT LOOP
298 
299     -- examine all non-phantom ingredients to determine if there's an exception
300     -- phantom products are reported at the time of yield, so don't double report with phantom ingredient
301     -- all other products are reported in either process material (non auto yield) or yield_material (auto yield)
302     FOR i IN 1..l_matl_dtl_tab_ing.COUNT LOOP
303       l_matl_dtl_rec := l_matl_dtl_tab_ing(i);
304       IF l_matl_dtl_rec.line_type = gme_common_pvt.g_line_type_ing THEN
305         -- don't check for unconsumed first because even if it's fully consumed,
306         -- but has reservation or MO, want to report it
307         --Bug#5296812  Added the call to the item record.Added the condition to check the inv update ind,and transaction ind.Start.
308          gme_material_detail_pvt.get_item_rec
309                         (p_org_id                => l_matl_dtl_rec.organization_id
310                         ,p_item_id               => l_matl_dtl_rec.inventory_item_id
311                         ,x_item_rec              => l_item_rec
312                         ,x_return_status         => l_return_status);
313           IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
314              x_return_status := l_return_status;
315              RAISE error_get_item;
316           END IF;
317        IF p_batch_header_rec.update_inventory_ind = 'Y' AND
318          l_item_rec.mtl_transactions_enabled_flag = 'Y' THEN
319        --Bug#5296812 End.
320         l_exception_qty := l_matl_dtl_rec.wip_plan_qty - l_matl_dtl_rec.actual_qty;
321 
322         IF l_exception_qty < 0 THEN
323           l_exception_qty := 0;
324         END IF;
325 
326         IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
327           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);
328           gme_debug.put_line (g_pkg_name||'.'||l_api_name||' actual_qty='||l_matl_dtl_rec.actual_qty);
329           gme_debug.put_line (g_pkg_name||'.'||l_api_name||' wip_plan_qty='||l_matl_dtl_rec.wip_plan_qty);
330           gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception qty='||l_exception_qty);
331         END IF;
332 
333         gme_release_batch_pvt.create_batch_exception
334               (p_material_dtl_rec         => l_matl_dtl_rec
335               ,p_pending_move_order_ind   => NULL  -- don't know...allow to calculate
336               ,p_pending_rsrv_ind         => NULL  -- don't know...allow to calculate
337               ,p_transacted_qty           => 0     -- only auto rel products are transacted.. this is for ing
338               ,p_exception_qty            => l_exception_qty
339               ,p_force_unconsumed         => fnd_api.g_false
340               ,x_exception_material_tbl   => x_exception_material_tbl
341               ,x_return_status            => l_return_status);
342 
343         IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
344           x_return_status := l_return_status;
345           RAISE error_complete_batch;
346         END IF;
347 
348         IF l_return_status = gme_common_pvt.g_exceptions_err THEN
349           x_return_status := gme_common_pvt.g_exceptions_err;
350         END IF;
351        END IF; --IF p_batch_header_rec.update_inventory_ind = 'Y'...
352       END IF;
353     END LOOP;
354 
355     IF NOT gme_common_pvt.create_history
356                         (p_batch_header_rec      => p_batch_header_rec
357                         ,p_original_status       => gme_common_pvt.g_batch_wip
358                         ,p_event_id              => NVL(gme_common_pvt.g_transaction_header_id,-9999)) THEN
359       IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
360         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' create history returned error');
361       END IF;
362     END IF;
363 
364     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
365       gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
366     END IF;
367 
368   EXCEPTION
369   WHEN  error_update_batch THEN
370     gme_common_pvt.log_message ('GME_UNEXPECTED_ERROR', 'ERROR', SQLERRM);
371     x_return_status := FND_API.g_ret_sts_unexp_error;
372     --Bug#5296812 Handling the raised exception error_get_item.
373   WHEN  error_process_material OR error_complete_batch OR
374         error_complete_step_rec OR error_release_batch OR error_get_item THEN
375     NULL;
376   WHEN locked_by_other_user or batch_lines_locked THEN
377             gme_common_pvt.log_message (
378             'GME_RECORD_LOCKED',
379             'TABLE_NAME',
380             l_table_name
381           );
382          x_return_status := FND_API.G_RET_STS_ERROR;
383   WHEN OTHERS THEN
384     fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
385     IF (NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT) THEN
386       gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
387     END IF;
388     x_return_status := FND_API.g_ret_sts_unexp_error;
389   END complete_batch;
390 
391 
392   PROCEDURE process_material
393               (p_material_detail_rec        IN         gme_material_details%ROWTYPE
394               ,p_yield                      IN         BOOLEAN
395               ,p_trans_date                 IN         DATE
396               ,p_update_inv_ind             IN         VARCHAR2
397               ,x_exception_material_tbl     IN  OUT NOCOPY  gme_common_pvt.exceptions_tab
398               ,x_return_status              OUT NOCOPY      VARCHAR2) IS
399 
400 
401     l_api_name               CONSTANT   VARCHAR2 (30)                := 'process_material';
402 
403     l_matl_dtl_rec                gme_material_details%ROWTYPE;
404     l_in_phantom_batch_rec        gme_batch_header%ROWTYPE;
405     l_phantom_batch_rec           gme_batch_header%ROWTYPE;
406     l_return_status               VARCHAR2(1);
407     l_item_rec                    mtl_system_items_b%ROWTYPE;
408     l_actual_qty                  NUMBER;
409     l_start_actual_qty            NUMBER;
410     l_exception_qty               NUMBER;
411 
412     error_fetch_batch             EXCEPTION;
413     error_complete_batch          EXCEPTION;
414     error_yield_material          EXCEPTION;
415     error_update_row              EXCEPTION;
416     error_get_item                EXCEPTION;
417     error_batch_exception         EXCEPTION;
418 
419 
420 
421   BEGIN
422 
423     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
424       gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
425       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' Processing material material_detail_id='||p_material_detail_rec.material_detail_id);
426     END IF;
427 
428     /* Set the return status to success initially */
429     x_return_status       := FND_API.G_RET_STS_SUCCESS;
430 
431     -- Process the material
432     -- 1) complete product
433     -- 2) complete phantom batch for phantom ingredient
434 
435     l_matl_dtl_rec := p_material_detail_rec;
436 
437     -- if it's a phantom ingredient, then complete the phantom batch
438     -- which will cause the phantom product to be yielded (the passed in ingredient will be consumed in trxm mgr
439 
440     -- complete phantom batch
441     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
442       l_phantom_batch_rec.batch_id := l_matl_dtl_rec.phantom_id;
443       IF NOT gme_batch_header_dbl.fetch_row(l_phantom_batch_rec, l_phantom_batch_rec) THEN
444         RAISE error_fetch_batch;
445       END IF;
446 
447       IF l_phantom_batch_rec.batch_status IN (gme_common_pvt.g_batch_pending, gme_common_pvt.g_batch_wip) THEN
448         IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
449           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' processing phantom ingredient material_detail_id='||l_matl_dtl_rec.material_detail_id);
450         END IF;
451         -- pass in the phantom line id so that release batch will know to yield that product
452         l_in_phantom_batch_rec := l_phantom_batch_rec;
453 
454         l_in_phantom_batch_rec.actual_start_date := NVL(l_in_phantom_batch_rec.actual_start_date, p_trans_date);
455         l_in_phantom_batch_rec.actual_cmplt_date := p_trans_date;
456 
457         complete_batch
458               (p_batch_header_rec           => l_in_phantom_batch_rec
459               ,x_exception_material_tbl     => x_exception_material_tbl
460               ,x_batch_header_rec           => l_phantom_batch_rec
461               ,x_return_status              => l_return_status);
462 
463         IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
464           x_return_status := l_return_status;
465           RAISE error_complete_batch;
466         END IF;
467 
468         IF l_return_status = gme_common_pvt.g_exceptions_err THEN
469           x_return_status := gme_common_pvt.g_exceptions_err;
470         END IF;
471       END IF;  -- IF l_phantom_batch_rec.batch_status IN (gme_common_pvt.g_batch_pending, gme_common_pvt.g_batch_wip)
472     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
473       gme_material_detail_pvt.get_item_rec
474                         (p_org_id                => l_matl_dtl_rec.organization_id
475                         ,p_item_id               => l_matl_dtl_rec.inventory_item_id
476                         ,x_item_rec              => l_item_rec
477                         ,x_return_status         => l_return_status);
478 
479       IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
480         x_return_status := l_return_status;
481         RAISE error_get_item;
482       END IF;
483 
484       IF p_update_inv_ind = 'Y' AND
485          l_item_rec.mtl_transactions_enabled_flag = 'Y' THEN
486         l_start_actual_qty := l_matl_dtl_rec.actual_qty;
487         yield_material(p_material_dtl_rec    => l_matl_dtl_rec
488                       ,p_yield_qty           => NULL  -- take the entire wip plan qty
489                       ,p_trans_date          => p_trans_date
490                       ,p_item_rec            => l_item_rec
491                       ,p_force_unconsumed    => fnd_api.g_false
492                       ,x_exception_material_tbl      => x_exception_material_tbl
493                       ,x_actual_qty          => l_actual_qty
494                       ,x_return_status       => l_return_status);
495 
496         IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
497           x_return_status := l_return_status;
498           RAISE error_yield_material;
499         END IF;
500 
501         IF l_return_status = gme_common_pvt.g_exceptions_err THEN
502           x_return_status := gme_common_pvt.g_exceptions_err;
503         END IF;
504 
505         l_matl_dtl_rec.actual_qty := l_actual_qty;
506 
507         -- if actual qty is met, we still need to see if there are pending product lots...
508         -- this is not required in yield material... it's a requirement of complete batch
509         IF l_matl_dtl_rec.actual_qty >= l_matl_dtl_rec.wip_plan_qty THEN
510           IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
511             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);
512             gme_debug.put_line (g_pkg_name||'.'||l_api_name||' actual_qty='||l_matl_dtl_rec.actual_qty);
513             gme_debug.put_line (g_pkg_name||'.'||l_api_name||' wip_plan_qty='||l_matl_dtl_rec.wip_plan_qty);
514             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));
515           END IF;
516 
517           gme_release_batch_pvt.create_batch_exception
518               (p_material_dtl_rec         => l_matl_dtl_rec
519               ,p_pending_move_order_ind   => FALSE  -- product doesn't have MO
520               ,p_pending_rsrv_ind         => NULL   -- let proc figure out; for product, looks at pplot
521               ,p_transacted_qty           => l_actual_qty - l_start_actual_qty
522               ,p_exception_qty            => 0
523               ,p_force_unconsumed         => fnd_api.g_false
524               ,x_exception_material_tbl   => x_exception_material_tbl
525               ,x_return_status            => l_return_status);
526 
527           IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
528             x_return_status := l_return_status;
529             RAISE error_yield_material;
530           END IF;
531 
532           IF l_return_status = gme_common_pvt.g_exceptions_err THEN
533             x_return_status := gme_common_pvt.g_exceptions_err;
534           END IF;
535         END IF;
536 
537       ELSE
538         l_matl_dtl_rec.actual_qty := l_matl_dtl_rec.plan_qty;
539       END IF;
540     ELSE  -- check for exception... this should be for all products that are not auto release
541     --Bug#5296812 Added the call to the item record.Added the condition to check the inv update ind,and transaction ind.
542         gme_material_detail_pvt.get_item_rec
543                         (p_org_id                => l_matl_dtl_rec.organization_id
544                         ,p_item_id               => l_matl_dtl_rec.inventory_item_id
545                         ,x_item_rec              => l_item_rec
546                         ,x_return_status         => l_return_status);
547         IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
548            x_return_status := l_return_status;
549            RAISE error_get_item;
550         END IF;
551        IF p_update_inv_ind = 'Y' AND l_item_rec.mtl_transactions_enabled_flag = 'Y' THEN
552        --Bug#5296812 End.
553         l_exception_qty := l_matl_dtl_rec.wip_plan_qty - l_matl_dtl_rec.actual_qty;
554 
555         IF l_exception_qty < 0 THEN
556           l_exception_qty := 0;
557         END IF;
558 
559         IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
560           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);
561           gme_debug.put_line (g_pkg_name||'.'||l_api_name||' actual_qty='||l_matl_dtl_rec.actual_qty);
562           gme_debug.put_line (g_pkg_name||'.'||l_api_name||' wip_plan_qty='||l_matl_dtl_rec.wip_plan_qty);
563           gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception qty='||l_exception_qty);
564         END IF;
565 
566         gme_release_batch_pvt.create_batch_exception
567               (p_material_dtl_rec         => l_matl_dtl_rec
568               ,p_pending_move_order_ind   => FALSE  -- product doesn't have MO
569               ,p_pending_rsrv_ind         => NULL   -- let proc figure out; for product, looks at pplot
570               ,p_transacted_qty           => 0                -- products other than auto yield don't get transacted in complete
571               ,p_exception_qty            => l_exception_qty
572               ,p_force_unconsumed         => fnd_api.g_false
573               ,x_exception_material_tbl   => x_exception_material_tbl
574               ,x_return_status            => l_return_status);
575 
576         IF l_return_status NOT IN (FND_API.G_RET_STS_SUCCESS, gme_common_pvt.g_exceptions_err) THEN
577           x_return_status := l_return_status;
578           RAISE error_batch_exception;
579         END IF;
580 
581         IF l_return_status = gme_common_pvt.g_exceptions_err THEN
582           x_return_status := gme_common_pvt.g_exceptions_err;
583         END IF;
584       END IF;--IF p_update_inv_ind = 'Y' AND...
585     END IF;  -- IF l_matl_dtl_rec.phantom_id IS NOT NULL...
586 
587     -- set WIP plan qty
588     l_matl_dtl_rec.wip_plan_qty := l_matl_dtl_rec.plan_qty;
589 
590     IF NOT gme_material_details_dbl.update_row (l_matl_dtl_rec) THEN
591       RAISE error_update_row;
592     END IF;
593 
594     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
595       gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
596     END IF;
597 
598   EXCEPTION
599   WHEN error_fetch_batch OR error_update_row THEN
600     gme_common_pvt.log_message ('GME_UNEXPECTED_ERROR', 'ERROR', SQLERRM);
601     x_return_status := FND_API.g_ret_sts_unexp_error;
602   WHEN error_complete_batch OR error_yield_material OR error_get_item OR error_batch_exception THEN
603     NULL;
604   WHEN OTHERS THEN
605     fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
606     IF g_debug <= gme_debug.g_log_procedure THEN
607       gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
608     END IF;
609     x_return_status := FND_API.g_ret_sts_unexp_error;
610   END process_material;
611 
612 
613   -- Note: p_yield_qty is the target actual qty; for incr, it's also the target, not the incr
614   PROCEDURE yield_material(p_material_dtl_rec  IN gme_material_details%ROWTYPE
615                             ,p_yield_qty       IN NUMBER
616                             ,p_trans_date      IN DATE
617                             ,p_item_rec        IN mtl_system_items_b%ROWTYPE
618                             ,p_force_unconsumed IN VARCHAR2
619                             ,x_exception_material_tbl    IN OUT NOCOPY gme_common_pvt.exceptions_tab
620                             ,x_actual_qty      OUT NOCOPY NUMBER
621                             ,x_return_status   OUT NOCOPY VARCHAR2) IS
622 
623     l_api_name         CONSTANT   VARCHAR2 (30)                := 'YIELD_MATERIAL';
624 
625     l_pending_product_lot_tab     gme_common_pvt.pending_lots_tab;
626     l_pp_lot_rec                  gme_pending_product_lots%ROWTYPE;
627     i                             NUMBER;
628 
629     l_yield_qty                   NUMBER;
630     l_trans_date                  DATE;
631     l_subinv                      VARCHAR2(10);
632     l_locator_id                  NUMBER;
633     l_revision                    VARCHAR2(3);
634     l_eff_locator_control         NUMBER;
635     l_start_actual_qty            NUMBER;
636     l_return_status               VARCHAR2(1);
637 
638     CURSOR cur_get_item_revision(v_item_id NUMBER, v_org_id NUMBER) IS
639     SELECT revision
640       FROM mtl_item_revisions_b
641      WHERE inventory_item_id = v_item_id
642        AND organization_id = v_org_id
643        AND effectivity_date <= gme_common_pvt.g_timestamp
644      ORDER BY effectivity_date desc;
645 
646     error_build_trxn              EXCEPTION;
647     error_get_exception           EXCEPTION;
648     error_nothing_to_yield        EXCEPTION;
649     error_get_pplot               EXCEPTION;
650     no_yield_required             EXCEPTION;
651 
652   BEGIN
653 
654     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
655       gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
656       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' material_detail_id='||p_material_dtl_rec.material_detail_id);
657       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_yield_qty='||p_yield_qty);
658       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_trans_date='||to_char(p_trans_date,
659                                                                                 'YYYY-MON-DD HH24:MI:SS'));
660       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' line_no='||p_material_dtl_rec.line_no);
661       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' line_type='||p_material_dtl_rec.line_type);
662       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_force_unconsumed='||p_force_unconsumed);
663     END IF;
664 
665     /* Set the return status to success initially */
666     x_return_status       := FND_API.G_RET_STS_SUCCESS;
667 
668     x_actual_qty := p_material_dtl_rec.actual_qty;
669 
670     -- following global is set only for migration purposes, where transactions need not be created,
671     -- this will only be set for complete step; complete batch is not called from migrate; however
672     -- if this is needed for complete batch, logic will work there also
673     IF gme_release_batch_pvt.g_bypass_txn_creation = 1 THEN
674       RAISE no_yield_required;
675     END IF;
676     /*Pawan Kumar 08-25-2006 bug 5486066 added nvl for wip_plan_qty
677       during direct completion, the wip plan qty is also null
678       So this was not getting caught in l_yield_qty <= x_actual_qty and this was
679       sending transaction quantity as null to transactions where it was failing*/
680 
681     l_yield_qty := NVL(p_yield_qty, nvl(p_material_dtl_rec.wip_plan_qty,p_material_dtl_rec.plan_qty));
682     l_trans_date := NVL(p_trans_date, gme_common_pvt.g_timestamp);
683 
684     l_start_actual_qty := x_actual_qty;
685 
686     IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
687       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' l_yield_qty='||l_yield_qty);
688       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' l_trans_date='||to_char(l_trans_date, 'YYYY-MON-DD HH24:MI:SS'));
689       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
690       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' l_start_actual_qty='||l_start_actual_qty);
691     END IF;
692 
693     IF l_yield_qty <= x_actual_qty THEN
694       -- this returns as success for now; there's nothing additional to yield
695       RAISE error_nothing_to_yield;
696     END IF;
697 
698     IF p_material_dtl_rec.subinventory IS NULL THEN
699       IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
700         gme_debug.put_line(g_pkg_name||'.'||l_api_name||' subinv on material is NULL; cant yield anything; get exceptions');
701       END IF;
702       RAISE error_get_exception;
703     END IF;
704 
705     IF p_material_dtl_rec.locator_id IS NULL THEN
706       -- check if it's locator control, we need a locator...
707       /* Bug 5441643 Added NVL condition for location control code*/
708       l_eff_locator_control :=
709                gme_common_pvt.eff_locator_control
710                      (p_organization_id        => p_material_dtl_rec.organization_id
711                      ,p_org_control            => gme_common_pvt.g_org_locator_control
712                      ,p_subinventory           => p_material_dtl_rec.subinventory
713                      ,p_item_control           => NVL(p_item_rec.location_control_code,1)
714                      ,p_item_loc_restrict      => p_item_rec.restrict_locators_code
715                      ,p_action                 => gme_common_pvt.g_prod_comp_txn_action);
716       IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
717           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' l_eff_locator_control='||l_eff_locator_control);
718           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' organization_id='||p_material_dtl_rec.organization_id);
719           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' g_org_locator_control='||gme_common_pvt.g_org_locator_control);
720           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' subinventory='||p_material_dtl_rec.subinventory);
721           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' inventory_item_id='||p_item_rec.inventory_item_id);
722           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' location_control_code='||p_item_rec.location_control_code);
723           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' restrict_locators_code='||p_item_rec.restrict_locators_code);
724           gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_action='||gme_common_pvt.g_prod_comp_txn_action);
725       END IF;
726       IF l_eff_locator_control <> 1 THEN
727         IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
728           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');
729         END IF;
730         RAISE error_get_exception;
731       END IF;
732     END IF;
733 
734     l_subinv := p_material_dtl_rec.subinventory;
735     l_locator_id := p_material_dtl_rec.locator_id;
736 
737     IF p_item_rec.revision_qty_control_code = 2 THEN -- under revision control
738       IF p_material_dtl_rec.revision IS NOT NULL THEN
739         l_revision := p_material_dtl_rec.revision;
740       ELSE
741         OPEN cur_get_item_revision(p_material_dtl_rec.inventory_item_id,
742                                    p_material_dtl_rec.organization_id);
743         FETCH cur_get_item_revision INTO l_revision;
744         CLOSE cur_get_item_revision;
745       END IF;
746     END IF;  -- IF p_revision_qty_control_code = 2
747 
748     IF p_item_rec.lot_control_code = 1 THEN -- not lot control
749       IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
750         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' item not lot control');
751       END IF;
752 
753       build_and_create_transaction
754               (p_mtl_dtl_rec           => p_material_dtl_rec
755               ,p_pp_lot_rec            => NULL
756               ,p_subinv                => l_subinv
757               ,p_locator_id            => l_locator_id
758               ,p_trans_date            => l_trans_date
759               ,p_yield_qty             => l_yield_qty
760               ,p_revision              => l_revision
761               ,p_sec_uom_code          => p_item_rec.secondary_uom_code
762               ,x_actual_qty            => x_actual_qty
763               ,x_return_status         => l_return_status);
764 
765       IF l_return_status NOT IN (gme_common_pvt.g_not_transactable, FND_API.G_RET_STS_SUCCESS) THEN
766         x_return_status := l_return_status;
767         RAISE error_build_trxn;
768       END IF;
769     ELSE  -- lot control... go to pending product lots
770       gme_pending_product_lots_pvt.get_pending_lot
771               (p_material_detail_id           => p_material_dtl_rec.material_detail_id
772               ,x_return_status                => l_return_status
773               ,x_pending_product_lot_tbl      => l_pending_product_lot_tab);
774       IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
775         x_return_status := l_return_status;
776         RAISE error_get_pplot;
777       END IF;
778 
779       i := 1;
780 
781       IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
782         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' l_yield_qty='||l_yield_qty);
783         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
784         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' count from pplot='||l_pending_product_lot_tab.COUNT);
785       END IF;
786 
787       WHILE l_yield_qty > x_actual_qty AND i <= l_pending_product_lot_tab.COUNT LOOP
788 
789         IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
790           gme_debug.put_line (g_pkg_name||'.'||l_api_name||' pending lot loop i='||i);
791           gme_debug.put_line (g_pkg_name||'.'||l_api_name||' pending lot loop x_actual_qty='||x_actual_qty);
792         END IF;
793 
794         l_pp_lot_rec := l_pending_product_lot_tab(i);
795 
796         build_and_create_transaction
797               (p_mtl_dtl_rec           => p_material_dtl_rec
798               ,p_pp_lot_rec            => l_pp_lot_rec
799               ,p_subinv                => l_subinv
800               ,p_locator_id            => l_locator_id
801               ,p_trans_date            => l_trans_date
802               ,p_yield_qty             => l_yield_qty
803               ,p_revision              => l_revision
804               ,p_sec_uom_code          => p_item_rec.secondary_uom_code
805               ,x_actual_qty            => x_actual_qty
806               ,x_return_status         => l_return_status);
807         IF l_return_status NOT IN (gme_common_pvt.g_not_transactable, FND_API.G_RET_STS_SUCCESS) THEN
808           x_return_status := l_return_status;
809           RAISE error_build_trxn;
810         END IF;
811 
812         i := i + 1; -- move on to the next lot
813       END LOOP;
814     END IF;  -- IF p_item_rec.lot_control_code = 1 THEN
815 
816     IF x_actual_qty < l_yield_qty THEN
817       RAISE error_get_exception;
818     END IF;
819 
820     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
821       gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
822     END IF;
823 
824 
825   EXCEPTION
826   WHEN error_build_trxn OR error_get_pplot OR no_yield_required THEN
827     NULL;
828   WHEN error_nothing_to_yield THEN
829     IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
830       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);
831     END IF;
832 
833     WHEN error_get_exception THEN
834       IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
835         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception block for get exceptions:');
836         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
837         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' l_start_actual_qty='||l_start_actual_qty);
838         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' l_yield_qty='||l_yield_qty);
839         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' exception qty='||(l_yield_qty - x_actual_qty));
840       END IF;
841 
842       gme_release_batch_pvt.create_batch_exception
843               (p_material_dtl_rec         => p_material_dtl_rec
844               ,p_pending_move_order_ind   => FALSE
845               ,p_pending_rsrv_ind         => NULL   -- let proc figure out; for product, looks at pplot
846               ,p_transacted_qty           => x_actual_qty - l_start_actual_qty
847               ,p_exception_qty            => l_yield_qty - x_actual_qty
848               ,p_force_unconsumed         => p_force_unconsumed
849               ,x_exception_material_tbl   => x_exception_material_tbl
850               ,x_return_status            => x_return_status);
851 
852   WHEN OTHERS THEN
853     fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
854     IF (NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT) THEN
855       gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
856     END IF;
857     x_return_status := FND_API.g_ret_sts_unexp_error;
858   END yield_material;
859 
860   PROCEDURE build_and_create_transaction
861               (p_mtl_dtl_rec           IN gme_material_details%ROWTYPE
862               ,p_pp_lot_rec            IN gme_pending_product_lots%ROWTYPE
863               ,p_subinv                IN VARCHAR2
864               ,p_locator_id            IN NUMBER
865               ,p_trans_date            IN DATE
866               ,p_yield_qty             IN NUMBER
867               ,p_revision              IN VARCHAR2 DEFAULT NULL
868               ,p_sec_uom_code          IN VARCHAR2 DEFAULT NULL
869               ,x_actual_qty            IN OUT NOCOPY NUMBER
870               ,x_return_status         OUT NOCOPY VARCHAR2) IS
871 
872     l_api_name               CONSTANT   VARCHAR2 (30)                := 'build_and_create_transaction';
873 
874     l_transaction_rec        mtl_transactions_interface%ROWTYPE;
875     l_lot_tbl                gme_common_pvt.mtl_trans_lots_inter_tbl;
876     l_trxn_qty               NUMBER;
877     l_dtl_qty                NUMBER;
878     l_sec_qty                NUMBER;
879 
880     error_build_mmti         EXCEPTION;
881     error_create_trxn        EXCEPTION;
882     error_relieve_pp_lot     EXCEPTION;
883 
884   BEGIN
885     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
886       gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
887       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' material_detail_id='||p_mtl_dtl_rec.material_detail_id);
888       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_subinv='||p_subinv);
889       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_locator_id='||p_locator_id);
890       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_yield_qty='||p_yield_qty);
891       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_revision='||p_revision);
892       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' p_sec_uom_code='||p_sec_uom_code);
893       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
894     END IF;
895 
896     /* Set the return status to success initially */
897     x_return_status       := FND_API.G_RET_STS_SUCCESS;
898 
899     constr_mmti(p_mtl_dtl_rec               => p_mtl_dtl_rec
900                ,p_yield_qty                 => p_yield_qty
901                ,p_subinv                    => p_subinv
902                ,p_revision                  => p_revision
903                ,p_locator_id                => p_locator_id
904                ,p_pp_lot_rec                => p_pp_lot_rec
905                ,x_mmti_rec                  => l_transaction_rec
906                ,x_mmli_tbl                  => l_lot_tbl
907                ,x_sec_qty                   => l_sec_qty
908                ,x_dtl_qty                   => l_dtl_qty
909                ,x_return_status             => x_return_status);
910 
911     IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
912       RAISE error_build_mmti;
913     END IF;
914 
915     IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
916       gme_debug.put_line (g_pkg_name||'.'||l_api_name||' after constr_mmti l_dtl_qty := '||l_dtl_qty);
917       gme_debug.put_line (g_pkg_name||'.'||l_api_name||' after constr_mmti l_sec_qty := '||l_sec_qty);
918     END IF;
919 
920     -- Bug 7262112 - Added '=' to condition. No need to recompute secondary values if yielding the full amount.
921     IF l_dtl_qty <= p_yield_qty - x_actual_qty THEN
922       l_trxn_qty := l_dtl_qty;
923     ELSE
924       l_trxn_qty := p_yield_qty - x_actual_qty;
925       /* Bug 5256543 l_sec_qty was set to null that was incorrect it has to be recalculated from new l_trxn_qty */
926       IF (p_sec_uom_code IS NOT NULL) THEN
927         l_sec_qty := INV_CONVERT.inv_um_convert
928                               (item_id            => p_mtl_dtl_rec.inventory_item_id
929                               ,lot_number         => p_pp_lot_rec.lot_number
930                               ,organization_id    => p_mtl_dtl_rec.organization_id
931                               ,PRECISION          => gme_common_pvt.g_precision
932                               ,from_quantity      => l_trxn_qty
933                               ,from_unit          => p_mtl_dtl_rec.dtl_um
934                               ,to_unit            => p_sec_uom_code
935                               ,from_name          => NULL
936                               ,to_name            => NULL);
937       END IF;
938     END IF;
939 
940     IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
941       gme_debug.put_line (g_pkg_name||'.'||l_api_name||' calculated l_trxn_qty := '||l_trxn_qty);
942       gme_debug.put_line (g_pkg_name||'.'||l_api_name||' calculated l_sec_qty := '||l_sec_qty);
943     END IF;
944 
945     IF p_mtl_dtl_rec.line_type = gme_common_pvt.g_line_type_prod THEN
946       l_transaction_rec.transaction_type_id := gme_common_pvt.g_prod_completion;
947     ELSE
948       l_transaction_rec.transaction_type_id := gme_common_pvt.g_byprod_completion;
949     END IF;
950 
951     IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
952       gme_debug.put_line (g_pkg_name||'.'||l_api_name||' l_transaction_rec.transaction_type_id := '||l_transaction_rec.transaction_type_id);
953     END IF;
954 
955     l_transaction_rec.transaction_date := p_trans_date;
956     l_transaction_rec.transaction_quantity := l_trxn_qty;
957     l_transaction_rec.secondary_uom_code := p_sec_uom_code;
958 
959     IF l_sec_qty IS NOT NULL THEN
960       l_transaction_rec.secondary_transaction_quantity := l_sec_qty;
961     END IF;
962 
963     IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
964       gme_debug.put_line (g_pkg_name||'.'||l_api_name||' transaction_date='||to_char(l_transaction_rec.transaction_date
965                                                                          ,'YYYY-MON-DD HH24:MI:SS'));
966       gme_debug.put_line (g_pkg_name||'.'||l_api_name||' transaction_qty='||l_transaction_rec.transaction_quantity);
967     END IF;
968 
969     l_transaction_rec.transaction_uom := p_mtl_dtl_rec.dtl_um;
970 
971     IF l_lot_tbl.count > 0 THEN
972       IF l_lot_tbl(1).lot_number IS NOT NULL THEN
973         l_lot_tbl(1).transaction_quantity := l_transaction_rec.transaction_quantity;
974         IF l_sec_qty IS NOT NULL THEN
975           l_lot_tbl(1).secondary_transaction_quantity := l_sec_qty;
976         END IF;
977       END IF;
978     END IF;
979 
980     gme_transactions_pvt.create_material_txn
981                         (p_mmti_rec             => l_transaction_rec
982                         ,p_mmli_tbl             => l_lot_tbl
983                         ,x_return_status        => x_return_status);
984 
985     IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
986       IF ( NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT ) THEN
987         gme_debug.put_line (g_pkg_name||'.'||l_api_name||' gme_transactions_pvt.create_transaction returned error');
988       END IF;
989       RAISE error_create_trxn;
990     END IF;
991 
992     x_actual_qty := x_actual_qty + l_trxn_qty;
993 
994     -- If pending product lot, then decrease qty, entry remains if the qty goes to zero
995     IF p_pp_lot_rec.pending_product_lot_id IS NOT NULL THEN
996       gme_pending_product_lots_pvt.relieve_pending_lot
997         (p_pending_lot_id           => p_pp_lot_rec.pending_product_lot_id
998         ,p_quantity                 => l_trxn_qty
999         ,p_secondary_quantity       => l_sec_qty
1000         ,x_return_status            => x_return_status);
1001 
1002       IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1003         RAISE error_relieve_pp_lot;
1004       END IF;
1005     END IF;
1006 
1007     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
1008       gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
1009       gme_debug.put_line(g_pkg_name||'.'||l_api_name||' x_actual_qty='||x_actual_qty);
1010     END IF;
1011 
1012   EXCEPTION
1013   WHEN error_create_trxn OR error_relieve_pp_lot OR error_build_mmti THEN
1014     NULL;
1015   WHEN OTHERS THEN
1016     fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
1017     IF (NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT) THEN
1018       gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
1019     END IF;
1020     x_return_status := FND_API.g_ret_sts_unexp_error;
1021   END build_and_create_transaction;
1022 
1023   PROCEDURE constr_mmti
1024     (p_mtl_dtl_rec              IN   gme_material_details%ROWTYPE
1025     ,p_yield_qty                IN   NUMBER
1026     ,p_subinv                   IN   VARCHAR2
1027     ,p_locator_id               IN   NUMBER
1028     ,p_revision                 IN   VARCHAR2
1029     ,p_pp_lot_rec               IN   gme_pending_product_lots%ROWTYPE
1030     ,x_mmti_rec                 OUT  NOCOPY mtl_transactions_interface%ROWTYPE
1031     ,x_mmli_tbl                 OUT  NOCOPY gme_common_pvt.mtl_trans_lots_inter_tbl
1032     ,x_sec_qty                  OUT  NOCOPY NUMBER
1033     ,x_dtl_qty                  OUT  NOCOPY NUMBER
1034     ,x_return_status            OUT  NOCOPY VARCHAR2) IS
1035 
1036     l_api_name     CONSTANT VARCHAR2 (30)      := 'CONSTR_MMTI';
1037   BEGIN
1038 
1039     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
1040       gme_debug.put_line('Entering api '||g_pkg_name||'.'||l_api_name);
1041     END IF;
1042 
1043     /* Initially let us assign the return status to success */
1044     x_return_status := FND_API.g_ret_sts_success;
1045 
1046     -- consturct mtl_transactions_interface
1047     x_mmti_rec.transaction_source_id        := p_mtl_dtl_rec.batch_id;  -- batch_id
1048     x_mmti_rec.trx_source_line_id           := p_mtl_dtl_rec.material_detail_id;  -- material_detail_id
1049     x_mmti_rec.inventory_item_id            := p_mtl_dtl_rec.inventory_item_id;
1050     x_mmti_rec.organization_id              := p_mtl_dtl_rec.organization_id;
1051     x_mmti_rec.subinventory_code            := p_subinv;
1052     x_mmti_rec.locator_id                   := p_locator_id;
1053     x_mmti_rec.revision                     := p_revision;
1054     x_mmti_rec.transaction_sequence_id      := p_pp_lot_rec.pending_product_lot_id;
1055     x_dtl_qty                               := p_yield_qty;
1056     -- construct mtl_transaction_lots_interface
1057     IF p_pp_lot_rec.lot_number IS NOT NULL THEN
1058       x_mmli_tbl(1).lot_number := p_pp_lot_rec.lot_number;
1059       x_mmli_tbl(1).reason_id  := p_pp_lot_rec.reason_id;
1060       /* Bug 5256543 Assign revision only if not null otherwise it will come from mtl dtl line */
1061       IF (p_pp_lot_rec.revision IS NOT NULL) THEN
1062         x_mmti_rec.revision := p_pp_lot_rec.revision;
1063       END IF;
1064       x_mmti_rec.reason_id := p_pp_lot_rec.reason_id;
1065       x_dtl_qty            := p_pp_lot_rec.quantity;
1066       x_sec_qty            := p_pp_lot_rec.secondary_quantity;
1067     END IF;
1068 
1069     IF nvl(g_debug, gme_debug.g_log_procedure + 1) <= gme_debug.g_log_procedure THEN
1070       gme_debug.put_line('Exiting api '||g_pkg_name||'.'||l_api_name);
1071     END IF;
1072 
1073   EXCEPTION
1074   WHEN OTHERS THEN
1075     fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
1076     IF (NVL(G_DEBUG,-1) = GME_DEBUG.G_LOG_STATEMENT) THEN
1077       gme_debug.put_line ('Unexpected error: '||g_pkg_name||'.'||l_api_name||': '||SQLERRM);
1078     END IF;
1079     x_return_status := FND_API.g_ret_sts_unexp_error;
1080   END constr_mmti;
1081 
1082   PROCEDURE validate_batch_for_complete (p_batch_header_rec     IN gme_batch_header%ROWTYPE
1083                                         ,x_batch_header_rec     OUT NOCOPY gme_batch_header%ROWTYPE
1084                                         ,x_return_status        OUT NOCOPY VARCHAR2) IS
1085 
1086       l_api_name   CONSTANT VARCHAR2 (30)           := 'validate_batch_for_complete';
1087 
1088       CURSOR Cur_gme_batch_steps (v_batch_id NUMBER) IS
1089       SELECT count(1)
1090       FROM   gme_batch_steps
1091       WHERE  step_status NOT IN (gme_common_pvt.g_step_completed, gme_common_pvt.g_step_closed)
1092       AND    batch_id = v_batch_id
1093       AND    rownum = 1;
1094 
1095       l_is_step                   NUMBER;
1096       l_batch_header_rec          gme_batch_header%ROWTYPE;
1097       CURSOR cur_validity_rule(v_recipe_validity_rule_id NUMBER)
1098       IS
1099          SELECT *
1100           FROM gmd_recipe_validity_rules
1101           WHERE recipe_validity_rule_id = v_recipe_validity_rule_id;
1102 
1103       CURSOR cur_validity_status_type(v_validity_rule_status VARCHAR2)
1104       IS
1105          SELECT status_type
1106           FROM gmd_status
1107           WHERE status_code=v_validity_rule_status;
1108 
1109       l_validity_rule             gmd_recipe_validity_rules%ROWTYPE;
1110       l_status_type               GMD_STATUS.status_type%TYPE;
1111       error_vr_not_found          EXCEPTION;
1112       error_validity_status       EXCEPTION;
1113       error_batch_type            EXCEPTION;
1114       error_batch_status          EXCEPTION;
1115       error_phantom               EXCEPTION;
1116       error_steps_not_complete    EXCEPTION;
1117       error_cmplt_date            EXCEPTION;
1118       error_future_date           EXCEPTION;
1119       error_vr_dates              EXCEPTION;
1120    BEGIN
1121       IF NVL (g_debug, gme_debug.g_log_procedure + 1) <=
1122                                                     gme_debug.g_log_procedure THEN
1123          gme_debug.put_line ('Entering api ' || g_pkg_name || '.'
1124                              || l_api_name);
1125       END IF;
1126 
1127       x_return_status := FND_API.g_ret_sts_success;
1128 
1129       -- set output structure
1130       x_batch_header_rec := p_batch_header_rec;
1131 
1132       -- set actual complete date if it's not passed
1133       IF p_batch_header_rec.actual_cmplt_date IS NULL THEN
1134          x_batch_header_rec.actual_cmplt_date := SYSDATE;
1135       END IF;
1136 
1137       IF p_batch_header_rec.batch_type = gme_common_pvt.g_doc_type_fpo THEN
1138         RAISE error_batch_type;
1139       END IF;
1140 
1141       IF p_batch_header_rec.batch_status NOT IN
1142                          (gme_common_pvt.g_batch_pending, gme_common_pvt.g_batch_wip) THEN
1143         RAISE error_batch_status;
1144       END IF;
1145 
1146       IF p_batch_header_rec.parentline_id IS NOT NULL THEN
1147         RAISE error_phantom;
1148       END IF;
1149 
1150       OPEN Cur_gme_batch_steps (p_batch_header_rec.batch_id);
1151       FETCH Cur_gme_batch_steps INTO l_is_step;
1152       CLOSE Cur_gme_batch_steps;
1153 
1154       IF l_is_step > 1 THEN
1155         RAISE error_steps_not_complete;
1156       END IF;
1157       --Sunith ch.5404329 check validity rule if it's not NULL; it would be NULL in case of LCF
1158       IF p_batch_header_rec.recipe_validity_rule_id IS NOT NULL THEN
1159         OPEN cur_validity_rule(p_batch_header_rec.recipe_validity_rule_id);
1160         FETCH cur_validity_rule INTO l_validity_rule;
1161         CLOSE cur_validity_rule;
1162 
1163         IF l_validity_rule.recipe_validity_rule_id IS NULL THEN  -- not found
1164            RAISE error_vr_not_found;
1165         ELSE
1166            -- following prevents user from releasing a pending batch
1167            -- if validity rule is ON_HOLD or OBSOLETE.
1168            OPEN cur_validity_status_type(l_validity_rule.validity_rule_status);
1169            FETCH cur_validity_status_type INTO l_status_type;
1170            CLOSE cur_validity_status_type;
1171 
1172            IF l_status_type IN ('1000' ,'800') THEN
1173              RAISE error_validity_status;
1174            END IF;
1175         END IF;  -- IF l_validity_rule.recipe_validity_rule_id IS NULL
1176 
1177       /*  IF l_validity_rule.start_date > x_batch_header_rec.actual_start_date OR
1178            (l_validity_rule.end_date IS NOT NULL AND
1179             l_validity_rule.end_date < x_batch_header_rec.actual_start_date) THEN
1180           RAISE error_vr_dates;
1181         END IF;*/
1182 --sunitha ch. Bug 5336007 aded call to check_validity_rule_dates and passed p_validate_plan_dates_ind=1
1183 --to validate planned start date against validate rule dates
1184         IF NOT gme_common_pvt.check_validity_rule_dates (
1185                                      p_validity_rule_id           =>  p_batch_header_rec.recipe_validity_rule_id
1186                                      ,p_start_date                =>  p_batch_header_rec.actual_start_date
1187                                      ,p_cmplt_date                =>  p_batch_header_rec.actual_cmplt_date
1188                                      ,p_batch_header_rec          =>  p_batch_header_rec
1189                                      ,p_validate_plan_dates_ind   => 1) THEN
1190           x_return_status := fnd_api.g_ret_sts_error;
1191           RAISE error_vr_dates;
1192 	END IF;
1193 -- End Bug 5336007
1194       END IF;  -- IF p_batch_header_rec.recipe_validity_rule_id IS NOT NULL
1195 
1196       -- validate completion date with actual start date and current date
1197       IF x_batch_header_rec.actual_cmplt_date < x_batch_header_rec.actual_start_date THEN
1198          RAISE error_cmplt_date;
1199       ELSIF x_batch_header_rec.actual_cmplt_date > SYSDATE THEN
1200          RAISE error_future_date;
1201       END IF;
1202 
1203       IF NVL (g_debug, gme_debug.g_log_procedure + 1) <=
1204                                                      gme_debug.g_log_procedure THEN
1205          gme_debug.put_line ('Exiting api ' || g_pkg_name || '.' || l_api_name);
1206       END IF;
1207 
1208    EXCEPTION
1209       WHEN error_phantom THEN
1210         gme_common_pvt.log_message ('PM_INVALID_PHANTOM_ACTION');
1211         x_return_status := FND_API.G_RET_STS_ERROR;
1212       WHEN error_batch_type OR error_batch_status THEN
1213         gme_common_pvt.log_message('GME_API_INVALID_BATCH_COMPL');
1214         x_return_status := fnd_api.g_ret_sts_error;
1215       WHEN error_steps_not_complete THEN
1216         gme_common_pvt.log_message('GME_STEPS_NOT_COMPLETE');
1217         x_return_status := fnd_api.g_ret_sts_error;
1218       WHEN error_cmplt_date THEN
1219         gme_common_pvt.log_message('GME_INVALID_DATE_RANGE'
1220                                   ,'DATE1','Completion date'
1221                                   ,'DATE2','Start date');
1222         x_return_status := fnd_api.g_ret_sts_error;
1223       WHEN error_future_date THEN
1224         fnd_message.set_name ('GMA', 'SY_NOFUTUREDATE');
1225         fnd_msg_pub.ADD;
1226         x_return_status := fnd_api.g_ret_sts_error;
1227       WHEN error_vr_dates THEN
1228         x_return_status := FND_API.G_RET_STS_ERROR;
1229       WHEN OTHERS THEN
1230         fnd_msg_pub.add_exc_msg (g_pkg_name, l_api_name);
1231 
1232         IF g_debug <= gme_debug.g_log_procedure THEN
1233             gme_debug.put_line (   'Unexpected error: '
1234                                 || g_pkg_name
1235                                 || '.'
1236                                 || l_api_name
1237                                 || ': '
1238                                 || SQLERRM);
1239         END IF;
1240 
1241         x_return_status := fnd_api.g_ret_sts_unexp_error;
1242    END validate_batch_for_complete;
1243 
1244 END gme_complete_batch_pvt;