UFN_GLACCOUNT_GETACCOUNTSFROMPARAMETERS_3
Return
Return Type |
---|
table |
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@InputTable | UDT_MAPPEDVALUESFORGETACCOUNTS_2 | IN | |
@SegmentValues | UDT_GLACCOUNT_SEGMENTVALUES | IN |
Definition
Copy
CREATE function [dbo].[UFN_GLACCOUNT_GETACCOUNTSFROMPARAMETERS_3] (@InputTable UDT_MAPPEDVALUESFORGETACCOUNTS_2 readonly,
@SegmentValues UDT_GLACCOUNT_SEGMENTVALUES readonly)
returns @OutputTable table (ID uniqueidentifier, DEBITGLACCOUNTSID uniqueidentifier, DEBITGLACCOUNTNUMBER varchar(100), CREDITGLACCOUNTSID uniqueidentifier, CREDITGLACCOUNTNUMBER varchar(100), ACCOUNTNUMBERERROR tinyint)
--ACCOUNTNUMBERERROR = 0, no error; 1, AccountCode; 2, Segments; 3, Account does not exist
as
begin
declare @NumSegments int = (select count(*) from dbo.PDACCOUNTSTRUCTURE as t1 inner join @InputTable as t2 on t1.PDACCOUNTSYSTEMID = t2.PDACCOUNTSYSTEMID )
declare @AccountCodeSegmentID uniqueidentifier = (select t1.ID from dbo.PDACCOUNTSTRUCTURE as t1 inner join @InputTable as t2 on t1.PDACCOUNTSYSTEMID = t2.PDACCOUNTSYSTEMID where t1.SEGMENTTYPE = 1)
declare @AddToString int = (select count(*) from dbo.PDACCOUNTSTRUCTURE as t1 inner join @InputTable as t2 on t1.PDACCOUNTSYSTEMID = t2.PDACCOUNTSYSTEMID where t1.sequence = @NumSegments and t1.SEPARATORCODE = 6)
--declare @SegmentsWorkTable table (ID uniqueidentifier, PDAccountStructureID uniqueidentifier, PDAccountSegmentValueID uniqueidentifier NULL, TransactionType tinyint, SegType tinyint, PRIMARY KEY (ID, PDAccountStructureID, TransactionType))
declare @InputLines table (ID uniqueidentifier, TableID uniqueidentifier, MappedID uniqueidentifier, PRIMARY KEY (ID, TableID))
declare @FinalTable table (ID uniqueidentifier, GLACCOUNTID uniqueidentifier, ACCOUNTNUMBER varchar(100), TransactionType tinyint, PRIMARY KEY (ID, TransactionType, GLACCOUNTID))
declare @AccountCodeMappingTable table (ID uniqueidentifier, PDAccountStructureID uniqueidentifier, PDAccountSegmentValueID uniqueidentifier NULL, GLAccountID uniqueidentifier NULL, TransactionType tinyint, PRIMARY KEY (ID, TransactionType))
declare @AvailableAcctCodeMappings table (DEBITGLACCOUNTID uniqueidentifier, CREDITGLACCOUNTID uniqueidentifier, DEBITPDACCOUNTSEGMENTVALUEID uniqueidentifier, CREDITPDACCOUNTSEGMENTVALUEID uniqueidentifier,
PAYMENTMETHODID uniqueidentifier, APPLICATIONTYPEID uniqueidentifier, REVENUETYPEID uniqueidentifier, SUBTYPEID uniqueidentifier, PDACCOUNTCODEMAPOFFICEID uniqueidentifier, PDACCOUNTSYSTEMID uniqueidentifier)
insert into @AvailableAcctCodeMappings (DEBITGLACCOUNTID, CREDITGLACCOUNTID, DEBITPDACCOUNTSEGMENTVALUEID, CREDITPDACCOUNTSEGMENTVALUEID, PAYMENTMETHODID, APPLICATIONTYPEID, REVENUETYPEID, SUBTYPEID, PDACCOUNTCODEMAPOFFICEID, PDACCOUNTSYSTEMID)
select distinct t1.DEBITGLACCOUNTID, t1.CREDITGLACCOUNTID, t1.DEBITPDACCOUNTSEGMENTVALUEID, t1.CREDITPDACCOUNTSEGMENTVALUEID,
t2.ID as PAYMENTMETHODID, t3.ID as APPLICATIONTYPEID, t4.ID as REVENUETYPEID, t5.SUBTYPEID, t1.PDACCOUNTCODEMAPOFFICEID, t1.PDACCOUNTSYSTEMID
from PDACCOUNTCODEMAPPING t1 left join PDACCOUNTCODEMAPPAYMENTMETHODTYPE t2 on t1.PDACCOUNTCODEMAPOFFICEID = t2.PDACCOUNTCODEMAPOFFICEID and (t1.PAYMENTMETHOD & t2.NAMEID) > 0
left join PDACCOUNTCODEMAPAPPLICATIONTYPE t3 on t1.PDACCOUNTCODEMAPOFFICEID = t3.PDACCOUNTCODEMAPOFFICEID and (t1.APPLICATIONTYPE & t3.NAMEID) > 0
left join PDACCOUNTCODEMAPREVENUETYPE t4 on t1.PDACCOUNTCODEMAPOFFICEID = t4.PDACCOUNTCODEMAPOFFICEID and (t1.REVENUETYPE & t4.NAMEID) > 0
left join PDACCOUNTCODEMAPPINGSUBTYPE t5 on t1.ID = t5.PDACCOUNTCODEMAPPINGID and (t5.ADDITIONALSUBTYPE in (t2.ADDITIONALSUBTYPE, t3.ADDITIONALSUBTYPE, t4.ADDITIONALSUBTYPE)) -- Assumes ADDITIONALSUBTYPE values are unique for each type
where t1.PDACCOUNTCODEMAPOFFICEID in (select PDACCOUNTCODEMAPOFFICEID from @InputTable)
and t1.PDACCOUNTSYSTEMID in (select PDACCOUNTSYSTEMID from @InputTable)
insert into @AccountCodeMappingTable (ID, PDAccountStructureID, PDAccountSegmentValueid, GLAccountID, TransactionType)
select TV1.ID, V3.PDACCOUNTSTRUCTUREID,
case V3.TransactionType when 1 then case when COALESCE (V1.REVENUETYPEID,V1.PAYMENTMETHODID,V1.APPLICATIONTYPEID) is not null then V1.DEBITPDACCOUNTSEGMENTVALUEID else V2.DEBITPDACCOUNTSEGMENTVALUEID end when 2 then case when COALESCE (V1.REVENUETYPEID,V1.PAYMENTMETHODID,V1.APPLICATIONTYPEID) is not null then V1.CREDITPDACCOUNTSEGMENTVALUEID else V2.CREDITPDACCOUNTSEGMENTVALUEID end end,
case V3.TransactionType when 1 then case when COALESCE (V1.REVENUETYPEID,V1.PAYMENTMETHODID,V1.APPLICATIONTYPEID) is not null then V1.DEBITGLACCOUNTID else V2.DEBITGLACCOUNTID end when 2 then case when COALESCE (V1.REVENUETYPEID,V1.PAYMENTMETHODID,V1.APPLICATIONTYPEID) is not null then V1.CREDITGLACCOUNTID else V2.CREDITGLACCOUNTID end end,
V3.TransactionType
from @InputTable TV1
left join @AvailableAcctCodeMappings V1
on (V1.PaymentMethodID = TV1.PaymentMethodID or TV1.PaymentMethodID is null)
and (V1.APPLICATIONTYPEID = TV1.APPLICATIONTYPEID or TV1.APPLICATIONTYPEID is null)
and (V1.REVENUETYPEID = TV1.REVENUETYPEID or TV1.REVENUETYPEID is null or TV1.REVENUETYPEID = '00000000-0000-0000-0000-000000000000')
and (V1.SubTypeID = TV1.SubTypeID or TV1.SubTypeID is null)
and V1.PDACCOUNTCODEMAPOFFICEID = TV1.PDACCOUNTCODEMAPOFFICEID
and V1.PDACCOUNTSYSTEMID = TV1.PDACCOUNTSYSTEMID
left join @AvailableAcctCodeMappings V2
on (V2.PaymentMethodID = TV1.PaymentMethodID or TV1.PaymentMethodID is null)
and (V2.APPLICATIONTYPEID = TV1.APPLICATIONTYPEID or TV1.APPLICATIONTYPEID is null)
and (V2.REVENUETYPEID = TV1.REVENUETYPEID or TV1.REVENUETYPEID is null or TV1.REVENUETYPEID = '00000000-0000-0000-0000-000000000000')
and V2.SubTypeID = '99999999-9999-9999-9999-999999999999'
and V2.PDACCOUNTCODEMAPOFFICEID = TV1.PDACCOUNTCODEMAPOFFICEID
and V2.PDACCOUNTSYSTEMID = TV1.PDACCOUNTSYSTEMID
cross join
(select @AccountCodeSegmentID as PDACCOUNTSTRUCTUREID, 1 as TransactionType union all select @AccountCodeSegmentID, 2) V3
--Accounts where account code mapping specifies the account number
insert into @FinalTable (ID, GLACCOUNTID, ACCOUNTNUMBER, TransactionType)
select t1.ID, GLAccountID, t2.ACCOUNTNUMBER, TransactionType
from @AccountCodeMappingTable t1
inner join dbo.GLACCOUNT t2 on t1.GLACCOUNTID = t2.ID
inner join @InputTable as t3 on t2.PDACCOUNTSYSTEMID = t3.PDACCOUNTSYSTEMID
if exists (select top 1 * from @SegmentValues)
begin
declare @hashTable table(ID uniqueidentifier, TRANSACTIONTYPE tinyint, HASHVALUE uniqueidentifier);
insert into @hashTable
select
id,
TransactionType,
dbo.UFN_GLACCOUNT_MD5_HASH_SEGMENTS(
(
select
pvt.[1] SEGMENT01ID, pvt.[2] SEGMENT02ID, pvt.[3] SEGMENT03ID, pvt.[4] SEGMENT04ID, pvt.[5] SEGMENT05ID, pvt.[6] SEGMENT06ID, pvt.[7] SEGMENT07ID, pvt.[8] SEGMENT08ID, pvt.[9] SEGMENT09ID, pvt.[10] SEGMENT10ID, pvt.[11] SEGMENT11ID, pvt.[12] SEGMENT12ID, pvt.[13] SEGMENT13ID, pvt.[14] SEGMENT14ID, pvt.[15] SEGMENT15ID, pvt.[16] SEGMENT16ID, pvt.[17] SEGMENT17ID, pvt.[18] SEGMENT18ID, pvt.[19] SEGMENT19ID, pvt.[20] SEGMENT20ID, pvt.[21] SEGMENT21ID, pvt.[22] SEGMENT22ID, pvt.[23] SEGMENT23ID, pvt.[24] SEGMENT24ID, pvt.[25] SEGMENT25ID, pvt.[26] SEGMENT26ID, pvt.[27] SEGMENT27ID, pvt.[28] SEGMENT28ID, pvt.[29] SEGMENT29ID, pvt.[30] SEGMENT30ID
for XML raw('ROW'), type, elements, root('MAPPEDVALUES'), BINARY BASE64
)) ACCOUNTHASH
from(
select id, swt.TransactionType, cast(swt.PDAccountSegmentValueID as nvarchar(36)) PDAccountSegmentValueID, ROW_NUMBER() over(partition by ID, TransactionType order by swt.PDAccountSegmentValueID) segment
from @SegmentValues swt
) source
pivot
(
MAX(PDAccountSegmentValueID)
for segment in ([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], [29], [30])
) pvt
--Using a table variable instead of a CTE so I can get the index on ID and TransactionType
--Compare what I want to what is available in PDACCOUNTSEGMENT
insert into @FinalTable(ID, GLACCOUNTID, ACCOUNTNUMBER, TransactionType)
select V1.ID, V1.GLACCOUNTID, GLACCOUNT.ACCOUNTNUMBER, V1.TransactionType
from
(select SWT.ID, t1.GLACCOUNTID, SWT.TransactionType
from @SegmentValues SWT
inner join dbo.PDACCOUNTSEGMENT t1 on SWT.PDACCOUNTSTRUCTUREID = t1.PDACCOUNTSTRUCTUREID and SWT.PDACCOUNTSEGMENTVALUEID = t1.PDACCOUNTSEGMENTVALUEID
inner join dbo.GLACCOUNT g on t1.GLACCOUNTID = g.id
inner join @hashTable ht on g.MD5HASHVALUE = ht.HASHVALUE and swt.ID = ht.ID and swt.TRANSACTIONTYPE = ht.TRANSACTIONTYPE
group by SWT.ID, SWT.TransactionType, t1.GLACCOUNTID
having count(*) = @NumSegments -- Handle collisions from the hash
) V1
inner join dbo.GLACCOUNT on V1.GLACCOUNTID = GLACCOUNT.ID
end
--PIVOT the results and add an errorcode for lines that don't have both debit and credit accounts
--simple self join is simpler and easier to read than the PIVOT command
insert into @OutputTable (ID, DEBITGLACCOUNTSID, DEBITGLACCOUNTNUMBER, CREDITGLACCOUNTSID, CREDITGLACCOUNTNUMBER, ACCOUNTNUMBERERROR)
select t1.ID, t2.GLACCOUNTID, t2.ACCOUNTNUMBER, t3.GLACCOUNTID, t3.ACCOUNTNUMBER,
case when t2.GLACCOUNTID is null or t3.GLACCOUNTID is null then (select case count(isnull(PDAccountSegmentValueID,GLAccountID)) when 2 then 2 else 1 end from @AccountCodeMappingTable where ID = t1.ID group by ID)
else 0
end
from @InputTable t1
left join @FinalTable t2 on t1.ID = t2.ID and t2.TransactionType = 1
left join @FinalTable t3 on t1.ID = t3.ID and t3.TransactionType = 2
--if no errors, don't waste time doing error messages
if exists (select 1 from @OutputTable where ACCOUNTNUMBERERROR != 0)
begin
--Get all of the segments for the transactions that have all of their segments properly mapped but the account does not exist
declare @NotExistingAccounts table (ID uniqueidentifier, TransactionType tinyint, SHORTDESCRIPTION nvarchar(30), SEPARATOR nvarchar(20), SEPARATORCODE tinyint, SEQUENCE int)
insert into @NotExistingAccounts
select OT.ID, FT.TransactionType, VALUE.SHORTDESCRIPTION, STRUCT.SEPARATOR, STRUCT.SEPARATORCODE, STRUCT.SEQUENCE
from @OutputTable OT
inner join (select SWT.ID, SWT.TransactionType
from @SegmentValues SWT
group by SWT.ID, SWT.TransactionType
having count(PDAccountSegmentValueID) = @NumSegments) FT on OT.ID = FT.ID
inner join @SegmentValues SWT on SWT.ID = FT.ID and FT.TransactionType = SWT.TransactionType
inner join dbo.PDACCOUNTSEGMENTVALUE VALUE on VALUE.ID = SWT.PDAccountSegmentValueID
inner join dbo.PDACCOUNTSTRUCTURE STRUCT on STRUCT.ID = SWT.PDAccountStructureID
where (OT.DEBITGLACCOUNTSID is null and FT.TransactionType = 1) or (OT.CREDITGLACCOUNTSID is null and FT.TransactionType = 2) and OT.ACCOUNTNUMBERERROR = 2
group by OT.ID, FT.TransactionType, VALUE.SHORTDESCRIPTION, STRUCT.SEPARATOR, STRUCT.SEPARATORCODE, STRUCT.SEQUENCE
--Update the output table with the account numbers that do not exist
update @OutputTable set
DEBITGLACCOUNTNUMBER = case when T.TransactionType = 1 and OT.DEBITGLACCOUNTSID is null then substring(T.ACCOUNT, 0, LEN(T.ACCOUNT) + @AddToString) else OT.DEBITGLACCOUNTNUMBER end
,CREDITGLACCOUNTNUMBER = case when T.TransactionType = 2 and OT.CREDITGLACCOUNTSID is null then substring(T.ACCOUNT, 0, LEN(T.ACCOUNT) + @AddToString) else OT.CREDITGLACCOUNTNUMBER end
,ACCOUNTNUMBERERROR = 3
from @OutputTable OT
inner join (select t1.ID, t1.TransactionType,
(select t2.SHORTDESCRIPTION + case t2.SEPARATORCODE when 6 then '' else SUBSTRING(t2.SEPARATOR, 0, 2) end
from @NotExistingAccounts t2
where t1.ID = t2.ID and t1.TransactionType = t2.TransactionType
order by t2.SEQUENCE
for xml path('')) [ACCOUNT]
from @NotExistingAccounts t1
group by t1.ID, t1.TransactionType) T on OT.ID = T.ID
where OT.ACCOUNTNUMBERERROR = 2
end
return
end