USP_REPORT_MERCHANDISEINVENTORY
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@DEPARTMENTID | uniqueidentifier | IN | |
@DEPARTMENTQUERY | uniqueidentifier | IN | |
@INCLUDEINACTIVE | bit | IN | |
@ASOFDATE | datetime | IN | |
@CURRENTAPPUSERID | uniqueidentifier | IN |
Definition
Copy
create procedure dbo.USP_REPORT_MERCHANDISEINVENTORY
(
@DEPARTMENTID uniqueidentifier = null,
@DEPARTMENTQUERY uniqueidentifier = null,
@INCLUDEINACTIVE bit = 0,
@ASOFDATE datetime = null,
@CURRENTAPPUSERID uniqueidentifier = null
)
as
set nocount on;
if @ASOFDATE is null
set @ASOFDATE = getDate();
set @ASOFDATE = dbo.UFN_DATE_GETLATESTTIME(@ASOFDATE);
declare @USERGRANTEDMERCHANDISEPAGE bit = 0;
if dbo.UFN_APPUSER_ISSYSADMIN(@CURRENTAPPUSERID) = 1
set @USERGRANTEDMERCHANDISEPAGE = 1;
else
select
@USERGRANTEDMERCHANDISEPAGE = [dbo].[UFN_SECURITY_APPUSER_GRANTED_FORM_IN_SYSTEMROLE](@CURRENTAPPUSERID, 'b59e03d7-f2a1-47de-a1d9-adb92f56233f');
declare @INVENTORY table (
MERCHANDISEPRODUCTID uniqueidentifier,
DEPARTMENT nvarchar(100),
CATEGORY nvarchar(100),
MERCHANDISEPRODUCTINSTANCEID uniqueidentifier,
BARCODE nvarchar(24),
DESCRIPTION nvarchar(150),
VENDOR nvarchar(154),
AVERAGECOST money,
RETAILPRICE money,
QUANTITYTYPECODE tinyint, -- 0 - Historical, 1 - Future, 2 - DNE
HISTORYACTIONDATE datetime,
QUANTITY int
);
declare @DEPARTMENTS table (
ID uniqueidentifier,
NAME nvarchar(100)
);
if @DEPARTMENTID is null and @DEPARTMENTQUERY is null
insert into @DEPARTMENTS
select
ID,
NAME
from dbo.MERCHANDISEDEPARTMENT;
if @DEPARTMENTID is not null and @DEPARTMENTQUERY is null
insert into @DEPARTMENTS
select
ID,
NAME
from dbo.MERCHANDISEDEPARTMENT
where ID = @DEPARTMENTID;
if @DEPARTMENTQUERY is not null and @DEPARTMENTID is null
insert into @DEPARTMENTS
select
QUERYRESULTS.ID,
MERCHANDISEDEPARTMENT.NAME
from dbo.UFN_IDSETREADER_GETRESULTS_GUID(@DEPARTMENTQUERY) QUERYRESULTS
inner join dbo.MERCHANDISEDEPARTMENT
on QUERYRESULTS.ID = MERCHANDISEDEPARTMENT.ID;
insert into @INVENTORY
(MERCHANDISEPRODUCTID, DEPARTMENT, CATEGORY, MERCHANDISEPRODUCTINSTANCEID, BARCODE, DESCRIPTION, VENDOR, AVERAGECOST, RETAILPRICE, QUANTITY)
select
MERCHANDISEPRODUCT.ID MERCHANDISEPRODUCTID,
DEPARTMENTS.NAME DEPARTMENT,
isnull(MERCHANDISEDEPARTMENTCATEGORY.NAME, '<No Category>') CATEGORY,
MERCHANDISEPRODUCTINSTANCE.ID MERCHANDISEPRODUCTINSTANCEID,
MERCHANDISEPRODUCTINSTANCE.BARCODE,
MERCHANDISEPRODUCTINSTANCE.ITEMDETAILS DESCRIPTION,
case
when MERCHANDISEPRODUCTINSTANCE.VENDORID is not null then dbo.UFN_CONSTITUENT_BUILDNAME(MERCHANDISEPRODUCTINSTANCE.VENDORID)
else dbo.UFN_CONSTITUENT_BUILDNAME(PRODUCTVENDOR.VENDORID)
end VENDOR,
MERCHANDISEPRODUCTINSTANCE.COST AVERAGECOST,
MERCHANDISEPRODUCTINSTANCE.SALEPRICE RETAILPRICE,
MERCHANDISEPRODUCTINSTANCE.ONHANDQUANTITY QUANTITY
from dbo.MERCHANDISEPRODUCTINSTANCE
inner join dbo.MERCHANDISEPRODUCT
on MERCHANDISEPRODUCTINSTANCE.MERCHANDISEPRODUCTID = MERCHANDISEPRODUCT.ID
inner join dbo.PRODUCTVENDOR
on MERCHANDISEPRODUCTINSTANCE.MERCHANDISEPRODUCTID = PRODUCTVENDOR.PRODUCTID
inner join @DEPARTMENTS DEPARTMENTS
on MERCHANDISEPRODUCT.MERCHANDISEDEPARTMENTID = DEPARTMENTS.ID
left outer join dbo.MERCHANDISEDEPARTMENTCATEGORY
on MERCHANDISEPRODUCT.MERCHANDISEDEPARTMENTCATEGORYID = MERCHANDISEDEPARTMENTCATEGORY.ID
where MERCHANDISEPRODUCTINSTANCE.DATEADDED <= dbo.UFN_DATE_GETLATESTTIME(@ASOFDATE)
and (@INCLUDEINACTIVE = 1 or (MERCHANDISEPRODUCT.ISACTIVE = 1 and MERCHANDISEPRODUCTINSTANCE.ISACTIVE = 1));
-- get the quantity value from the most recent history item
with HISTORY_CTE as (
select
MERCHANDISEPRODUCTINSTANCEHISTORY.MERCHANDISEPRODUCTINSTANCEID,
cast(MERCHANDISEPRODUCTINSTANCEHISTORY.ACTIONDATE as datetime) ACTIONDATE,
MERCHANDISEPRODUCTINSTANCEHISTORY.ACTIONTYPECODE,
MERCHANDISEPRODUCTINSTANCEHISTORY.ONHANDQUANTITY,
case MERCHANDISEPRODUCTINSTANCEHISTORY.ACTIONTYPECODE
when 0 then MERCHANDISEPRODUCTINSTANCEHISTORY.ONHANDQUANTITY + MERCHANDISEPRODUCTINSTANCEHISTORY.QUANTITY -- Shipment
when 1 then MERCHANDISEPRODUCTINSTANCEHISTORY.ONHANDQUANTITY + MERCHANDISEPRODUCTINSTANCEHISTORY.QUANTITY -- Adjustment
when 2 then MERCHANDISEPRODUCTINSTANCEHISTORY.QUANTITY -- Physical count
end QUANTITY,
MERCHANDISEPRODUCTINSTANCEHISTORY.AVERAGECOST
from dbo.MERCHANDISEPRODUCTINSTANCEHISTORY
inner join @INVENTORY INVENTORY
on MERCHANDISEPRODUCTINSTANCEHISTORY.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
)
update @INVENTORY set
HISTORYACTIONDATE = isnull(HISTORY.ACTIONDATE, FUTURE.ACTIONDATE),
QUANTITYTYPECODE =
case
when HISTORY.ACTIONDATE is not null then 0
when FUTURE.ACTIONDATE is not null then 1
else 2
end,
QUANTITY = coalesce(HISTORY.QUANTITY, FUTURE.ONHANDQUANTITY, INVENTORY.QUANTITY),
AVERAGECOST = coalesce(SHIPMENTHISTORY.AVERAGECOST, SHIPMENTFUTURE.AVERAGECOST, INVENTORY.AVERAGECOST)
from @INVENTORY INVENTORY
outer apply (
select top 1
HISTORY_CTE.AVERAGECOST
from HISTORY_CTE
where HISTORY_CTE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and (
HISTORY_CTE.ACTIONTYPECODE = 0 -- Shipment
or (HISTORY_CTE.ACTIONTYPECODE = 2 and HISTORY_CTE.AVERAGECOST is not null) -- Initial physical count
)
and HISTORY_CTE.ACTIONDATE <= @ASOFDATE
order by HISTORY_CTE.ACTIONDATE desc
) SHIPMENTHISTORY
outer apply (
select top 1
HISTORY_CTE.AVERAGECOST
from HISTORY_CTE
where SHIPMENTHISTORY.AVERAGECOST is null
and HISTORY_CTE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and (
HISTORY_CTE.ACTIONTYPECODE = 0 -- Shipment
or (HISTORY_CTE.ACTIONTYPECODE = 2 and HISTORY_CTE.AVERAGECOST is not null) -- Initial physical count
)
and HISTORY_CTE.ACTIONDATE > @ASOFDATE
order by HISTORY_CTE.ACTIONDATE asc
) SHIPMENTFUTURE
outer apply (
select top 1
HISTORY_CTE.ACTIONDATE,
HISTORY_CTE.QUANTITY
from HISTORY_CTE
where HISTORY_CTE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and HISTORY_CTE.ACTIONDATE <= @ASOFDATE
order by HISTORY_CTE.ACTIONDATE desc
) HISTORY
outer apply (
select top 1
HISTORY_CTE.ACTIONDATE,
HISTORY_CTE.ONHANDQUANTITY
from HISTORY_CTE
where HISTORY.ACTIONDATE is null
and HISTORY_CTE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and HISTORY_CTE.ACTIONDATE > @ASOFDATE
order by HISTORY_CTE.ACTIONDATE asc
) FUTURE;
-- PERFORMANCE CONCERNS!!!
-- The following queries cast FINANCIALTRANSACTION.DATE to a datetime, which means that the index will not be used to seek.
-- This currently needs to be done instead of using CALCUATEDDATE because we need to account for the time of the HISTORYACTIONDATEs.
-- We currently can compare DATETIMEOFFSET fields because the refunds are being stored without offsets.
-- This could potentially be fixed in code and with a revision for existing refunds.
-- Update inventory items with history info Quantity As Of = Quantity - sum(Sold) + sum(Returned)
update @INVENTORY set
QUANTITY -= isnull(SALES.NUMSOLD, 0)
from @INVENTORY INVENTORY
outer apply (
select
SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID,
SUM(SALESORDERITEM.QUANTITY) NUMSOLD
from dbo.SALESORDERITEMMERCHANDISE
inner join dbo.SALESORDERITEM
on SALESORDERITEMMERCHANDISE.ID = SALESORDERITEM.ID
inner join dbo.SALESORDER
on SALESORDERITEM.SALESORDERID = SALESORDER.ID
where SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and SALESORDER.TRANSACTIONDATE between INVENTORY.HISTORYACTIONDATE and @ASOFDATE
group by SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID
) SALES
where INVENTORY.QUANTITYTYPECODE = 0;
update @INVENTORY set
QUANTITY += isnull(RETURNS.NUMRETURNED, 0)
from @INVENTORY INVENTORY
outer apply (
select
sum(
case
when CREDITITEM_EXT.SALESORDERITEMIZEDITEMID is null then -- Pre-SALESORDERITEMMERCHANDISEUNIT refunds
FINANCIALTRANSACTIONLINEITEM.QUANTITY
else
case
when SALESORDERITEMMERCHANDISEUNIT.ISRETURNED = 1 then
1
else
0
end
end
) as NUMRETURNED
from dbo.FINANCIALTRANSACTION
inner join dbo.FINANCIALTRANSACTIONLINEITEM
on FINANCIALTRANSACTION.ID = FINANCIALTRANSACTIONLINEITEM.FINANCIALTRANSACTIONID
inner join dbo.CREDITITEM_EXT
on FINANCIALTRANSACTIONLINEITEM.ID = CREDITITEM_EXT.ID
inner join dbo.SALESORDERITEMMERCHANDISE
on SALESORDERITEMMERCHANDISE.ID = CREDITITEM_EXT.SALESORDERITEMID
left join dbo.SALESORDERITEMMERCHANDISEUNIT
on SALESORDERITEMMERCHANDISEUNIT.ID = CREDITITEM_EXT.SALESORDERITEMIZEDITEMID
where SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and cast(FINANCIALTRANSACTION.DATE as datetime) between INVENTORY.HISTORYACTIONDATE and @ASOFDATE
) RETURNS
where INVENTORY.QUANTITYTYPECODE = 0;
-- Update inventory items with future info Quantity As Of = Quantity + sum(Sold) - sum(Returned)
update @INVENTORY set
QUANTITY += isnull(SALES.NUMSOLD, 0)
from @INVENTORY INVENTORY
outer apply (
select
SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID,
SUM(SALESORDERITEM.QUANTITY) NUMSOLD
from dbo.SALESORDERITEMMERCHANDISE
inner join dbo.SALESORDERITEM
on SALESORDERITEMMERCHANDISE.ID = SALESORDERITEM.ID
inner join dbo.SALESORDER
on SALESORDERITEM.SALESORDERID = SALESORDER.ID
where SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and SALESORDER.TRANSACTIONDATE between @ASOFDATE and INVENTORY.HISTORYACTIONDATE
group by SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID
) SALES
where INVENTORY.QUANTITYTYPECODE = 1;
update @INVENTORY set
QUANTITY -= isnull(RETURNS.NUMRETURNED, 0)
from @INVENTORY INVENTORY
outer apply (
select
sum(
case
when CREDITITEM_EXT.SALESORDERITEMIZEDITEMID is null then -- Pre-SALESORDERITEMMERCHANDISEUNIT refunds
FINANCIALTRANSACTIONLINEITEM.QUANTITY
else
case
when SALESORDERITEMMERCHANDISEUNIT.ISRETURNED = 1 then
1
else
0
end
end
) as NUMRETURNED
from dbo.FINANCIALTRANSACTION
inner join dbo.FINANCIALTRANSACTIONLINEITEM
on FINANCIALTRANSACTION.ID = FINANCIALTRANSACTIONLINEITEM.FINANCIALTRANSACTIONID
inner join dbo.CREDITITEM_EXT
on FINANCIALTRANSACTIONLINEITEM.ID = CREDITITEM_EXT.ID
inner join dbo.SALESORDERITEMMERCHANDISE
on SALESORDERITEMMERCHANDISE.ID = CREDITITEM_EXT.SALESORDERITEMID
left join dbo.SALESORDERITEMMERCHANDISEUNIT
on SALESORDERITEMMERCHANDISEUNIT.ID = CREDITITEM_EXT.SALESORDERITEMIZEDITEMID
where SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and cast(FINANCIALTRANSACTION.DATE as datetime) between @ASOFDATE and INVENTORY.HISTORYACTIONDATE
) RETURNS
where INVENTORY.QUANTITYTYPECODE = 1;
-- Update inventory items with no history items Quantity As Of = (Quantity Today) + sum(Sold) - sum(Returned)
declare @CURRENTDATE datetime = dbo.UFN_TIMEZONEENTRY_GETSYSTEMDEFAULTDATEFROMUTC(getutcdate());
update @INVENTORY set
QUANTITY += isnull(SALES.NUMSOLD, 0)
from @INVENTORY INVENTORY
outer apply (
select
SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID,
SUM(SALESORDERITEM.QUANTITY) NUMSOLD
from dbo.SALESORDERITEMMERCHANDISE
inner join dbo.SALESORDERITEM
on SALESORDERITEMMERCHANDISE.ID = SALESORDERITEM.ID
inner join dbo.SALESORDER
on SALESORDERITEM.SALESORDERID = SALESORDER.ID
where SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and SALESORDER.TRANSACTIONDATE between @ASOFDATE and @CURRENTDATE
group by SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID
) SALES
where INVENTORY.QUANTITYTYPECODE = 2;
update @INVENTORY set
QUANTITY -= isnull(RETURNS.NUMRETURNED, 0)
from @INVENTORY INVENTORY
outer apply (
select
sum(
case
when CREDITITEM_EXT.SALESORDERITEMIZEDITEMID is null then -- Pre-SALESORDERITEMMERCHANDISEUNIT refunds
FINANCIALTRANSACTIONLINEITEM.QUANTITY
else
case
when SALESORDERITEMMERCHANDISEUNIT.ISRETURNED = 1 then
1
else
0
end
end
) as NUMRETURNED
from dbo.FINANCIALTRANSACTION
inner join dbo.FINANCIALTRANSACTIONLINEITEM
on FINANCIALTRANSACTION.ID = FINANCIALTRANSACTIONLINEITEM.FINANCIALTRANSACTIONID
inner join dbo.CREDITITEM_EXT
on FINANCIALTRANSACTIONLINEITEM.ID = CREDITITEM_EXT.ID
inner join dbo.SALESORDERITEMMERCHANDISE
on SALESORDERITEMMERCHANDISE.ID = CREDITITEM_EXT.SALESORDERITEMID
left join dbo.SALESORDERITEMMERCHANDISEUNIT
on SALESORDERITEMMERCHANDISEUNIT.ID = CREDITITEM_EXT.SALESORDERITEMIZEDITEMID
where SALESORDERITEMMERCHANDISE.MERCHANDISEPRODUCTINSTANCEID = INVENTORY.MERCHANDISEPRODUCTINSTANCEID
and cast(FINANCIALTRANSACTION.DATE as datetime) between @ASOFDATE and @CURRENTDATE
) RETURNS
where INVENTORY.QUANTITYTYPECODE = 2;
select
'http://www.blackbaud.com/MERCHANDISEPRODUCTID?MERCHANDISEPRODUCTID=' + CONVERT(nvarchar(36), MERCHANDISEPRODUCTID) as MERCHANDISELINK,
@USERGRANTEDMERCHANDISEPAGE USERGRANTEDMERCHANDISELINK,
BARCODE,
DESCRIPTION,
DEPARTMENT,
CATEGORY,
QUANTITY,
VENDOR,
AVERAGECOST,
RETAILPRICE
from @INVENTORY
order by DESCRIPTION;
return 0;