Need Query to find onhand quantity based on lot and serial

Hi,
I have four tables mtl_system_items_b,mtl_onhand_quantities_detail,mtl_lot_numbers,mtl_serial_numbers. Based on tables i want onhand quantity in both lot and serial number wise.


mtl_onhand_quantities_detail

ORGANIZATION_ID 4 int
INVENTORY_ITEM_ID -5 bigint
SUBINVENTORY_CODE 12 varchar
LOCATOR_ID -5 bigint
PRIMARY_TRANSACTION_QUANTITY 3 decimal
LOT_NUMBER 12 varchar
TRANSACTION_UOM_CODE 12 varchar
TRANSACTION_QUANTITY 3 decimal

mtl_system_items_b
ORGANIZATION_ID 4 int
INVENTORY_ITEM_ID -5 bigint
SEGMENT1 12 varchar
DESCRIPTION -9 nvarchar
INVENTORY_ITEM_STATUS_CODE 12 varchar
PRIMARY_UOM_CODE 12 varchar
LOT_CONTROL_CODE 4 int
SERIAL_NUMBER_CONTROL_CODE 4 int

mtl_serial_numbers
INVENTORY_ITEM_ID -5 bigint
SERIAL_NUMBER 12 varchar
CURRENT_STATUS 4 int
LOT_NUMBER 12 varchar
CURRENT_ORGANIZATION_ID 4 int
CURRENT_SUBINVENTORY_CODE 12 varchar
CURRENT_LOCATOR_ID -5 bigint

mtl_lot_numbers
ORGANIZATION_ID 4 int
INVENTORY_ITEM_ID -5 bigint
LOT_NUMBER -9 nvarchar
EXPIRATION_DATE 11 datetime
STATUS_ID 4 int

By applying below logic on Tables

  1. mtl_system_items_b
    segment1 --> Item name
    inventory_item_id --> Item Number
    primary_uom_code --> UOM
  2. mtl_onhand_quantities_detail
    primary_transaction_quantity --> On hand Qty
  3. mtl_lot_numbers
    lot_number
  4. mtl_serial_numbers
    serial_number

Logic:

  1. Pure Lot Control Items
    lot_control_code <> 1
  2. Pure Serial Control Items
    serial_number_control_code <> 1
    lot_number = NULL
    current_status = 3
  3. Both Lot and Serial Control Items
    serial_number_control_code <> 1
    lot_number <> NULL
    current_status = 3
  4. No Control Items
    lot_control_code = 1
    serial_number_control_code=1

Output Required columns as below

ORGANIZATION_ID
SUBINVENTORY_CODE
LOCATOR_ID
ITEM_NAME
ITEM_NUMBER
ONHAND_QTY
LOT_NUMBER
SERIAL_NUMBER
UOM
LOT_QTY/SERIAL_QTY

Script for generating table

Not sure about your logic and how the tables should be joined, but this might start you off:

use stock;

declare @logic int=4; /* 1=Pure Lot Control Items
                         2=Pure Serial Control Items
                         3=Both Lot and Serial Control Items
                         4=No Control Items
                      */

select i.organization_id
      ,o.subinventory_code
      ,o.locator_id
      ,i.segment1 as [Item name]
      ,i.inventory_item_id as [Item number]
      ,sum(o.primary_transaction_quantity) as [On hand qty]
      ,o.lot_number /* or l.lot_number */
      ,s.serial_number
      ,i.primary_uom_code as [UOM]
	  ,case
	      when isnull(count(s.serial_number) over(partition by i.organization_id
                                                              ,o.subinventory_code
                                                              ,o.locator_id
                                                              ,i.segment1
                                                              ,i.inventory_item_id
                                                              ,o.lot_number /* or l.lot_number */
                                                              ,i.primary_uom_code
                                                 )
                     ,0
					 )
              =0
          then null
          else sum(o.primary_transaction_quantity)
              /count(s.serial_number) over(partition by i.organization_id
                                                       ,o.subinventory_code
                                                       ,o.locator_id
                                                       ,i.segment1
                                                       ,i.inventory_item_id
                                                       ,o.lot_number /* or l.lot_number */
                                                       ,i.primary_uom_code
                                          )
       end as [lot/serial]
  from dbo.mtl_system_items_b as i
       inner join dbo.mtl_onhand_quantities_detail as o
               on o.organization_id=i.organization_id
              and o.inventory_item_id=i.inventory_item_id
       left outer join dbo.mtl_serial_numbers as s
                    on s.current_organization_id=o.organization_id
                   and s.inventory_item_id=o.inventory_item_id
                   and s.current_locator_id=o.locator_id
                   and s.current_subinventory_code=o.subinventory_code
                   and @logic in (2,3)
 where (@logic=1 and i.lot_control_code<>'1')
    or (@logic=2 and i.serial_number_control_code<>1 and o.lot_number is null and s.current_status=3)
	or (@logic=3 and i.serial_number_control_code<>1 and o.lot_number is not null and s.current_status=3)
	or (@logic=4 and i.lot_control_code='1' and i.serial_number_control_code=1)
 group by i.organization_id
         ,o.subinventory_code
         ,o.locator_id
         ,i.segment1
         ,i.inventory_item_id
         ,o.lot_number /* or l.lot_number */
         ,s.serial_number
         ,i.primary_uom_code
;

mtl_system_items_b is master table with INVENTORY_ITEM_STATUS_CODE active means item is active in stock
mtl_onhand_quantities_detail contains On hand Qty details
mtl_lot_numbers contains lot details
mtl_serial_numbers contains serial details

the logic is
1 lot have 1000 serial(single) items

if Pure Lot Control Items i.e item available only in lot
lot_control_code <> 1

if Pure Serial Control Items i.e item available only in serial
serial_number_control_code <> 1
lot_number = NULL
current_status = 3

if Both Lot and Serial i.e item available in both lot and serial
serial_number_control_code <> 1
lot_number <> NULL
current_status = 3

if item is not in lot and serial
lot_control_code = 1
serial_number_control_code=1

so serial qty is always 1
if item is in serial,serial qty is always 1
if item is in lot, lot qty should be calculated

Yeah, I'm still not understanding the logic so I'm folding on this one

did you understand how to get lot and serial items based on conditions from tables?
Which part you didn't understand?

Did the query I supplied join correct?
Are you looking for a single query or 4?
From the data you supplied, what should be the output?

Single query is need. Item validity check based on INVENTORY_ITEM_STATUS_CODE = active means item is valid in stock Output should have lot items, serial items , items in both lot and serial , items not in both lot and serial in stock . Lot qty - count of number of lots in that item Serial qty- will be always 1.

Hi,
I got query for the task.
--pure lot

select a.ORGANIZATION_ID,a.SUBINVENTORY_CODE,LOCATOR_ID,SEGMENT1 ITEM_NAME,
a.INVENTORY_ITEM_ID ITEM_NUMBER, (select sum(PRIMARY_TRANSACTION_QUANTITY) from mtl_onhand_quantities_detail
where INVENTORY_ITEM_ID=a.INVENTORY_ITEM_ID
and ORGANIZATION_ID=a.ORGANIZATION_ID) ONHAND_QTY,LOT_NUMBER,'' as SERIAL_NUMBER,b.PRIMARY_UOM_CODE UOM,
PRIMARY_TRANSACTION_QUANTITY LOT_QTYSERIAL_QTY
from mtl_onhand_quantities_detail a,mtl_system_items_b b
where 1 = 1
AND a.ORGANIZATION_ID=b.ORGANIZATION_ID and
a.INVENTORY_ITEM_ID=b.INVENTORY_ITEM_ID
and b.LOT_CONTROL_CODE<>1 and a.ORGANIZATION_ID=141
and a.INVENTORY_ITEM_ID not in(select INVENTORY_ITEM_ID from mtl_serial_numbers c where SERIAL_NUMBER is not null
and CURRENT_ORGANIZATION_ID=141)

union
---pureserial
select distinct
a.ORGANIZATION_ID,a.SUBINVENTORY_CODE,a.LOCATOR_ID,b.SEGMENT1 ITEM_NAME,
b.INVENTORY_ITEM_ID ITEM_NUMBER,(select sum(primary_transaction_quantity)
from mtl_onhand_quantities_detail
where 1 = 1
AND organization_id=b.organization_id
and inventory_item_id=b.inventory_item_id
) ONHAND_QTY,
a.LOT_NUMBER,
sn.SERIAL_NUMBER,
b.PRIMARY_UOM_CODE UOM,
1 as LOT_QTYSERIAL_QTY
from mtl_onhand_quantities_detail a,mtl_system_items_b b,mtl_serial_numbers sn
where a.ORGANIZATION_ID=b.ORGANIZATION_ID
and a.INVENTORY_ITEM_ID =b.INVENTORY_ITEM_ID
and b.ORGANIZATION_ID=sn.CURRENT_ORGANIZATION_ID
and b.INVENTORY_ITEM_ID =sn.INVENTORY_ITEM_ID
and b.INVENTORY_ITEM_ID=sn.INVENTORY_ITEM_ID
and b.ORGANIZATION_ID=sn.CURRENT_ORGANIZATION_ID
and b.SERIAL_NUMBER_CONTROL_CODE<>1
and isnull (a.locator_id, 0) = isnull (sn.current_locator_id, 0)
and b.ORGANIZATION_ID=141
and sn.LOT_NUMBER is null
and b.INVENTORY_ITEM_ID not in(select INVENTORY_ITEM_ID from mtl_lot_numbers where ORGANIZATION_ID=141)
and sn.CURRENT_STATUS=3
and a.subinventory_code=sn.current_subinventory_code
union
---bothlot&serial
select a.ORGANIZATION_ID,b.SUBINVENTORY_CODE,b.LOCATOR_ID ,a.segment1 ITEM_NAME,
a.inventory_item_id ITEM_NUMBER ,
(select sum(primary_transaction_quantity)
from mtl_onhand_quantities_detail
where 1 = 1
AND organization_id=b.organization_id
and inventory_item_id=b.inventory_item_id
) ONHAND_QTY,b.LOT_NUMBER, sn. serial_number , a.primary_uom_code UOM, 1 LOT_QTYSERIAL_QTY
--b.primary_transaction_quantity
from
mtl_system_items_b a ,mtl_onhand_quantities_detail b,mtl_serial_numbers sn where a.INVENTORY_ITEM_ID=b.INVENTORY_ITEM_ID
and a.INVENTORY_ITEM_ID=sn.INVENTORY_ITEM_ID and b.ORGANIZATION_ID=141 and
a.ORGANIZATION_ID=b.ORGANIZATION_ID and a.ORGANIZATION_ID=sn.CURRENT_ORGANIZATION_ID and
a.serial_number_control_code <> 1
and
b.lot_number is not NULL and sn.current_status = 3 and
b.LOT_NUMBER=sn.LOT_NUMBER and
isnull (b.locator_id, 0) = isnull (sn.current_locator_id, 0) and
b.subinventory_code=sn.current_subinventory_code
union
--notin both
select a.ORGANIZATION_ID,a.SUBINVENTORY_CODE,LOCATOR_ID,SEGMENT1 ITEM_NAME,
a.INVENTORY_ITEM_ID ITEM_NUMBER, (select sum(PRIMARY_TRANSACTION_QUANTITY) from mtl_onhand_quantities_detail
where a.INVENTORY_ITEM_ID=b.INVENTORY_ITEM_ID
and a.ORGANIZATION_ID=b.ORGANIZATION_ID) ONHAND_QTY, '' as LOT_NUMBER,'' as SERIAL_NUMBER,b.PRIMARY_UOM_CODE UOM,
PRIMARY_TRANSACTION_QUANTITY LOT_QTYSERIAL_QTY
from mtl_onhand_quantities_detail a,mtl_system_items_b b
where 1 = 1
AND a.ORGANIZATION_ID=b.ORGANIZATION_ID and
a.INVENTORY_ITEM_ID=b.INVENTORY_ITEM_ID and a.ORGANIZATION_ID=141
and b.LOT_CONTROL_CODE=1
and b.SERIAL_NUMBER_CONTROL_CODE=1

Thanks.