I have 9,791 items with QTY in service >0 that I want to "adjust" out of stock.
All these items have been financially accounted for, written off over the years, the IV account manually cleared by journal each month. However the items have been left in stock (why we do this is for another day).
My challenge is to remove the items from stock so that I can then delete all the inventory master records for items as they are all historical items that have been discontinued for over 10 years and I'm sick of seeing them in reports and enquiries.
To do this
- I need to firstly create a stock transfer document for all the items and qtys, including bins and serial numbers
- I need create a stock adjustment for the same items bin qtys and serial numbers to adjust the items out of stock
- I need to post a reversing journal to undo the effect on the already adjusted accounts
I really don’t like the idea of trying to write a GP macro to do this, it will take forever to run and is complicated by having to select serial numbers and bin numbers for each item.
I could go for programming solution using eConnect, but looking at it, I don’t think the business rules are that difficult and the problem is quite constrained so just building the transactions in SQL will do me. I feel confident I won’t screw anything up here.
I will show you the scripts I’ve used but be aware that I know this system well, you may have other modules installed that would affect things, or have GP set up in different ways that will cause issues. So TEST! TEST! TEST! first, I can take to responsibility for what happens on your system with this script!
To generate a transfer, create an empty inventory transfer with no lines, take a note of the document number and set it as the variable in the script. Save the GP document and come out of it.
Run the first half of the SQL script to create transfers for ALL the items in inventory that have a type of “In Service”. Obviously this could be narrowed down to your own needs with some more where clauses.
Note that I have made some safe assumptions for the dataset I’m working with, some of the field values are tied down rather than looked up. For example, you would need to check the account indexes for your inventory accounts before running the script, but it provides a starting point.
Once the SQL has generated the transfer, post it. Once posted run the second half of the SQL script, this will use the posted transfer to generate the inventory adjustment.
Now post the inventory adjustment.
Note: When I tried this it took over 19 hours on the test environment, after switching off the Intrastat Module it only took a few mins, see more on this at the bottom of this post.
Finally in our case we needed some reversing journals to put the accounts back to where they should have been, but that was only as we were not using the system correctly in the first place!
The SQL…
DECLARE @IVDOCNMBR CHAR(17)
-- Create a new Inventory Transfer Document, Save it then enter its number here
-- this will be the document that will be loaded with items
SELECT @IVDOCNMBR = '00017213'
-- Load all items that have an "in service" value to a stock transfer to change to "on hand"
INSERT INTO IV10001
SELECT @IVDOCNMBR
,3
,IV00101.ITEMNMBR
,(
ROW_NUMBER() OVER (
ORDERBY IV00101.ITEMNMBR
) - 1
) * 16384 + 16384
,IV40201.BASEUOFM
,IV40202.QTYBSUOM
,IV00102.QTYINSVC
,CURRCOST
,STNDCOST * IV00102.QTYINSVC
,IV00102.LOCNCODE
,IV00102.LOCNCODE
,4
,1
,2011
,523
,0x00000000
,DECPLCUR
,IV00101.DECPLQTY
,0
,''
FROM IV00101
JOIN IV00102 ON IV00101.ITEMNMBR = IV00102.ITEMNMBR
AND IV00102.RCRDTYPE = 2
JOIN IV40201 ON IV40201.UOMSCHDL = IV00101.UOMSCHDL
JOIN IV40202 ON IV40202.UOMSCHDL = IV40201.UOMSCHDL
AND IV40202.UOFM = IV40201.BASEUOFM
WHERE QTYINSVC > 0
INSERT INTO IV10003
SELECT IVDOCNBR
,IVDOCTYP
,LNSEQNBR
,(
ROW_NUMBER() OVER (
ORDERBY IV10001.ITEMNMBR
) - 1
) * 16384 + 16384
,IV10001.ITEMNMBR
,TRXLOCTN
,IV00112.BIN
,IV00112.BIN
,TRFQTYTY
,IV00112.QUANTITY
,0
FROM IV10001
JOIN IV00112 ON IV10001.ITEMNMBR = IV00112.ITEMNMBR
AND IV10001.TRXLOCTN = IV00112.LOCNCODE
AND IV10001.TRFQTYTY = IV00112.QTYTYPE
WHERE IVDOCNBR = @IVDOCNMBR
AND IV00112.QUANTITY - IV00112.ATYALLOC > 0
INSERT INTO IV10002
SELECT IVDOCNBR
,IVDOCTYP
,IV10001.ITEMNMBR
,IV00200.SERLNMBR
,1
,IV10001.LNSEQNBR
,(
ROW_NUMBER() OVER (
ORDERBY IV10001.ITEMNMBR
) - 1
) * 16384 + 16384
,IV00200.DATERECD
,IV00200.DTSEQNUM
,0
,0
,IV00200.BIN
,IV00200.BIN
,'1900-01-01'
,'1900-01-01'
FROM IV10001
JOIN IV00200 ON IV10001.ITEMNMBR = IV00200.ITEMNMBR
AND IV10001.TRXLOCTN = IV00200.LOCNCODE
AND IV10001.TRFQTYTY = IV00200.QTYTYPE
WHERE IVDOCNBR = @IVDOCNMBR
AND IV00200.SERLNSLD = 0
UPDATE IV00200
SET SERLNSLD = 1
FROM IV10001
JOIN IV10002 ON IV10001.IVDOCNBR = IV10002.IVDOCNBR
AND IV10001.IVDOCTYP = IV10002.IVDOCTYP
AND IV10001.LNSEQNBR = IV10002.LNSEQNBR
JOIN IV00200 ON IV10002.ITEMNMBR = IV00200.ITEMNMBR
AND IV10001.TRXLOCTN = IV00200.LOCNCODE
AND IV10002.DATERECD = IV00200.DATERECD
AND IV10002.DTSEQNUM = IV00200.DTSEQNUM
AND IV10002.SERLTNUM = IV00200.SERLNMBR
AND IV10001.TRFQTYTY = IV00200.QTYTYPE
WHERE IV10002.IVDOCNBR = @IVDOCNMBR
-----------------------------------------------------------------------------------
-- Post the generated document, once sucessfully posted run the next part that follows
---- prepare the inventory adjustment by creating a new inventory adjustment and saving it (empty)
-- enter the previous document number for the stock transfer, and the empty adjustment number - an inventory adjustment
-- will be created from the transfer to adjust all that stock out.
DECLARE @IVDOCNMBR CHAR(17)
SELECT @IVDOCNMBR = '00017213'-- posted (in history) inventory transfer
DECLARE @IVDOCNMBR2 CHAR(17)
SELECT @IVDOCNMBR2 = '00054595'-- empty inventory adjustment
INSERT INTO IV10001
SELECT @IVDOCNMBR2
,1
,IV30300.ITEMNMBR
,(
ROW_NUMBER() OVER (
ORDERBY IV30300.ITEMNMBR
) - 1
) * 16384 + 16384
,IV30300.UOFM
,IV30300.QTYBSUOM
,- 1 * TRXQTY
,UNITCOST
,0
,IV30300.TRNSTLOC
,''
,0
,0
,525
,2008
,0x00000000
,DECPLCUR
,IV30300.DECPLQTY
,0
,''
FROM IV30300
WHERE IV30300.DOCNUMBR = @IVDOCNMBR
AND IV30300.DOCTYPE = 3
INSERT INTO IV10003
SELECT @IVDOCNMBR2
,1
,IV30300.LNSEQNBR
,IV30302.SEQNUMBR
,IV30302.ITEMNMBR
,IV30302.LOCNCODE
,TOBIN
,''
,IV30302.QTYTYPE
,IV30302.QTYSLCTD
,0
FROM IV30302
JOIN IV30300 ON IV30302.DOCNUMBR = IV30300.DOCNUMBR
AND IV30302.DOCTYPE = IV30300.DOCTYPE
AND IV30302.LNSEQNBR = IV30300.LNSEQNBR
WHERE IV30300.DOCNUMBR = @IVDOCNMBR
INSERT INTO IV10002
SELECT @IVDOCNMBR2
,1
,IV30400.ITEMNMBR
,[SERLTNUM]
,1
,LNSEQNBR
,SLTSQNUM
,DATERECD
,DTSEQNUM
,0
,0
,TOBIN
,''
,'1900-01-01'
,'1900-01-01'
FROM [IV30400]
JOIN IV00200 ON IV30400.ITEMNMBR = IV00200.ITEMNMBR
AND IV30400.SERLTNUM = IV00200.SERLNMBR
AND IV00200.SERLNSLD = 0
WHERE DOCNUMBR = @IVDOCNMBR
UPDATE IV00200
SET SERLNSLD = 1
FROM IV10001
JOIN IV10002 ON IV10001.IVDOCNBR = IV10002.IVDOCNBR
AND IV10001.IVDOCTYP = IV10002.IVDOCTYP
AND IV10001.LNSEQNBR = IV10002.LNSEQNBR
JOIN IV00200 ON IV10002.ITEMNMBR = IV00200.ITEMNMBR
AND IV10001.TRXLOCTN = IV00200.LOCNCODE
AND IV10002.DATERECD = IV00200.DATERECD
AND IV10002.DTSEQNUM = IV00200.DTSEQNUM
AND IV10002.SERLTNUM = IV00200.SERLNMBR
AND IV00200.QTYTYPE = 1
WHERE IV10002.IVDOCNBR = @IVDOCNMBR
ROLLBACKTRANSACTION
UPDATE IV00102
SET ATYALLOC = ATYALLOC + ABS(TRXQTY)
--SELECT *
FROM IV10001
JOIN IV00102 ON IV10001.ITEMNMBR = IV00102.ITEMNMBR
AND IV10001.TRXLOCTN = IV00102.LOCNCODE
AND TRFQTYTY = 0
WHERE IV10001.IVDOCNBR = @IVDOCNMBR2
AND IV10001.IVDOCTYP = 1
UPDATE IV00102
SET ATYALLOC = ATYALLOC + ABS(TRXQTY)
--SELECT *
FROM IV10001
JOIN IV00102 ON IV10001.ITEMNMBR = IV00102.ITEMNMBR
AND RCRDTYPE = 1
AND TRFQTYTY = 0
WHERE IV10001.IVDOCNBR = @IVDOCNMBR2
AND IV10001.IVDOCTYP = 1