Home SuiteQL: Inventory Detail
Post
Cancel

SuiteQL: Inventory Detail

Inventory Detail in SuiteQL

In the previous post we discussed the tables Transaction and TransactionLine. Please make sure to read that post before reading this one.

In this post we will discuss the Inventoryassignment table and how we can use it to get the inventory detail.

The inventory assignment table

Suppose we wanted the lot and/or bin information for a transactionline. Obviously we can’t store this in the TransactionLine table as we can have multiple inventory lines for the same transaction line. This is where the Inventoryassignment table comes in.

Here is the join (building on the Transaction table):

1
2
3
4
FROM transaction
INNER JOIN transactionline on transactionline.transaction = transaction.id
INNER JOIN inventoryassignment on inventoryassignment.transactionline = transactionline.id
and inventoryassignment.transaction = transactionline.transaction

As we can see the primary key of the table is a composite key, containing inventoryassignment.transactionline a reference to the transactionline and inventoryassignment.transaction a refrence to the transaction.

Let us look at some the important fields available to us in the \T Inventoryassignment table:

Column NameDescriptionType
quantityThe quantity of the inventoryassignment line (in base units)Decimal
inventorynumberThe Lot Number (note it is a reference to the lot number not a string)Integer (Internal ID)
binnumberThe bin record or null if not using binsInteger (Internal ID)
inventorystatusThe internal id of the inventory statusInteger (Internal ID)

So suppose we wanted to get the inventory detail of a sales order that has the following lines:

ItemQuantity
Item 110
Item 220

and has the following inventory detail for item 1:

LotBinQuantity
Lot 1Bin 15
Lot 2Bin 25

and the following inventory detail for item 2:

LotBinQuantity
Lot 3Bin 115
Lot 4Bin 25

We can write a query as follows:

1
2
3
4
5
6
7
8
9
10
11
SELECT
  BUILTIN.DF(TransactionLine.item) as Item,
  BUILTIN.DF(Inventoryassignment.inventorynumber) as lot,
  BUILTIN.DF(Inventoryassignment.binnumber) as Bin,
  Inventoryassignment.quantity
FROM Transaction
INNER JOIN TransactionLine on TransactionLine.transaction = Transaction.id
INNER JOIN Inventoryassignment on Inventoryassignment.transactionline = TransactionLine.id
AND Inventoryassignment.transaction = TransactionLine.transaction
  WHERE Transaction.type = 'SalesOrd'
  AND Transaction.id = 1234

This will return the following result:

ItemLotBinQuantity
Item 1Lot 1Bin 15
Item 1Lot 2Bin 25
Item 2Lot 3Bin 115
Item 2Lot 4Bin 25

Getting inventory as of date

NetSuite - unlike other ERP systems - doesn’t have an single inventory journal table. The three tables above -Inventoryassignment, TransactionLine and Transaction - are the three tables that make up the inventory journal.

For each transaction we can generate a row as follows:

1
2
3
4
5
6
7
8
9
10
11
SELECT
Transaction.trandate,
TransactionLine.item,
TransactionLine.location,
Inventoryassignment.inventorynumber,
Inventoryassignment.binnumber,
Inventoryassignment.quantity
FROM transaction
INNER JOIN TransactionLine ON transactionline.transaction = transaction.id
INNER JOIN Inventoryassignment ON inventoryassignment.transactionline = transactionline.id
and Inventoryassignment.transaction = transactionline.transaction

Using this information NetSuite can deduce the inventory snapshot of a given item as of a given date.

We need to include a check for the field TransactionLine.isinventoryaffecting, this will filter out transactions like work orders that don’t affect inventory such as Work Orders. We also will include a check for the field Transaction.posting to check for transactions that are not in a state to affect inventory such as Item Fullfilments in picked status.

Suppose the date that we want to look at is 01/01/2023 and the internal id of the item is 1234:

The following query uses CTEs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
WITH Inventoryjournal as (
    SELECT
    Transaction.trandate,
    BUILTIN.DF(TransactionLine.item) AS item,
    BUILTIN.DF(TransactionLine.location) AS location,
    BUILTIN.(Inventoryassignment.inventorynumber) AS lotnumber,
    BUILTIN.DF(Inventoryassignment.binnumber) AS Bin,
    Inventoryassignment.quantity
    FROM Transaction
    INNER JOIN TransactionLine ON TransactionLine.transaction = transaction.id
    INNER JOIN Inventoryassignment ON Inventoryassignment.transactionline = transactionline.id
    and Inventoryassignment.transaction = transactionline.transaction
    WHERE Transaction.trandate <= TO_DATE('01/01/2023', 'MM/DD/YYYY') AND item = 1234
    AND TransactionLine.isinventoryaffecting = 'T'
    AND Transaction.posting = 'T'
)
SELECT
Inventoryjournal.item,
Inventoryjournal.location,
Inventoryjournal.inventorynumber,
Inventoryjournal.binnumber,
SUM(Quantity)
FROM Inventoryjournal
GROUP BY
Inventoryjournal.item,
Inventoryjournal.location,
Inventoryjournal.lotnumber,
Inventoryjournal.bin

This will give you a breakdown of what was in inventory as of 01/01/2023 for item 1234.

This query can be very slow, it is reccomended to test it before running it on all your items

Sample Query | Sales By Location per month per Item (with inventory detail)

This query is the same as the previous post, but with the addition of the inventory detail.

First let’s get the transaction lines we’ll need with the inventory detail:

1
2
3
4
5
6
7
8
SELECT
transaction.tranid,
transaction.trandate,
TO_CHAR(transaction.trandate, 'Month YYYY') AS month,
BUILTIN.DF(transactionline.item) as item,
inventoryassignment.quantity
BUILTIN.DF(inventoryassignment.inventorynumber) as lotnumber,
where transaction.type = 'SalesOrd'

Now we pull it into a CTE and do the grouping:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  WITH salestransactions AS (
  SELECT
  transaction.tranid,
  transaction.trandate,
  TO_CHAR(transaction.trandate, 'Month YYYY') AS month,
  BUILTIN.DF(transactionline.item) as item,
  inventoryassignment.quantity
  BUILTIN.DF(inventoryassignment.inventorynumber) as inventorynumber,
  Where transaction.type = 'SalesOrd'
)
SELECT
salestransactions.month,
salestransactions.item,
salestransactions.inventorynumber,
SUM(salestransactions.quantity)
GROUP BY
salestransactions.month,
salestransactions.item,
salestransactions.inventorynumber

Stay tuned for the next post where we will discuss joining the table TransactionAccountingLIne to get the GL impact of transactions.

This post is licensed under CC BY 4.0 by the author.

SuiteQL: Transactions

SuiteQL: GL Impact