USP_CREDIT_ADDEVENTREGISTRATIONREFUND
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@ID | uniqueidentifier | INOUT | |
@CHANGEAGENTID | uniqueidentifier | IN | |
@REGISTRANTID | uniqueidentifier | IN | |
@ITEMS | xml | IN | |
@REFUNDMETHODS | xml | IN | |
@COMMENT | nvarchar(500) | IN | |
@CREDITREASONCODEID | uniqueidentifier | IN | |
@CURRENTAPPUSERID | uniqueidentifier | IN | |
@TOTAL | money | IN | |
@TIMESTAMP | bigint | IN | |
@ADDRESSID | uniqueidentifier | IN |
Definition
Copy
CREATE procedure dbo.USP_CREDIT_ADDEVENTREGISTRATIONREFUND
(
@ID uniqueidentifier = null output,
@CHANGEAGENTID uniqueidentifier = null,
@REGISTRANTID uniqueidentifier = null,
@ITEMS xml = null,
@REFUNDMETHODS xml = null,
@COMMENT nvarchar(500) = '',
@CREDITREASONCODEID uniqueidentifier = null,
@CURRENTAPPUSERID uniqueidentifier = null,
@TOTAL money = null,
@TIMESTAMP bigint = null,
@ADDRESSID uniqueidentifier = null
)
as
begin
set nocount on;
if @ID is null
set @ID = newid();
if @CHANGEAGENTID is null
exec dbo.USP_CHANGEAGENT_GETORCREATECHANGEAGENT @CHANGEAGENTID output;
declare @CURRENTDATE datetime = getdate();
declare @POSTSTATUSCODE tinyint;
--Make sure nobody else has done a refund since the form was opened.
if @TIMESTAMP <> coalesce((select TSLONG from dbo.REGISTRANT where ID = @REGISTRANTID), -1)
begin
if @REGISTRANTID is null or @REGISTRANTID = '00000000-0000-0000-0000-000000000000'
raiserror('ERR_TRANSACTIONID_EVENTREGISTRATIONNOTSELECTED', 13, 1);
else
raiserror('ERR_CREDITITEMS_CONFLICTINGEVENTREGISTRATIONREFUND', 13, 1);
return 1;
end
else begin
update dbo.REGISTRANT
set DATECHANGED = getdate(), CHANGEDBYID = @CHANGEAGENTID
where ID = @REGISTRANTID;
select @POSTSTATUSCODE = LI.POSTSTATUSCODE
from dbo.EVENTREGISTRANTPAYMENT RP
inner join dbo.FINANCIALTRANSACTIONLINEITEM LI on LI.ID = RP.PAYMENTID
where RP.REGISTRANTID = @REGISTRANTID;
end
-- Get refund items from input parameter @ITEMS
declare @CREDITITEMS table(
ID uniqueidentifier,
SALESORDERITEMID uniqueidentifier,
PRICE money,
TYPECODE tinyint,
[DESCRIPTION] nvarchar(255),
AMOUNTTOREFUND money,
EVENTREGISTRANTID uniqueidentifier,
UNITVALUE money -- this needs to reflect the original price, regardless of contributed revenue. Usually, it's the same as AMOUNTTOREFUND.
);
insert into @CREDITITEMS
select
newid(),
case when T.item.value('(@SALESORDERITEMID)[1]','uniqueidentifier') = '00000000-0000-0000-0000-000000000000'
then null
else
T.item.value('(@SALESORDERITEMID)[1]','uniqueidentifier')
end SALESORDERITEMID,
T.item.value('(@PRICE)[1]','money') PRICE,
T.item.value('(@TYPECODE)[1]','tinyint') TYPECODE,
null [DESCRIPTION],
T.item.value('(@AMOUNTTOREFUND)[1]','money') AMOUNTTOREFUND,
T.item.value('(@EVENTREGISTRANTID)[1]','uniqueidentifier'),
T.item.value('(@AMOUNTTOREFUND)[1]','money') UNITVALUE
from @ITEMS.nodes('/ITEMS/ITEM') T(item)
where T.item.value('(@INCLUDE)[1]','bit') = 1;
/******** Validate refund item and payments *******/
declare @REFUNDEDITEMTOTAL money = (select sum(AMOUNTTOREFUND) from @CREDITITEMS);
-- Error if no items were selected
if not exists (select 1 from @CREDITITEMS) begin
raiserror('ERR_ITEMS_NONESELECTED', 13, 1);
return 1;
end
-- Error if the amount refunding is less than zero for any of the items
if exists (select 1 from @CREDITITEMS where AMOUNTTOREFUND < 0) begin
raiserror('ERR_ITEMS_NEGATIVEAMOUNT', 13, 1);
return 1;
end
-- Error if the payments do not add up to the refund total
if coalesce((select sum(T.item.value('(@AMOUNTREFUNDING)[1]','money')) from @REFUNDMETHODS.nodes('/REFUNDMETHODS/ITEM') T(item)),0) <> @REFUNDEDITEMTOTAL begin
raiserror('ERR_REFUNDMETHODS_DIFFERENTFROMTOTALAMOUNT', 13, 1);
return 1;
end
-- Error if the refund amount is greater than the total available to refund
if @REFUNDEDITEMTOTAL > @TOTAL begin
raiserror('ERR_REFUNDAMOUNT_EXCEEDSLIMIT', 13, 1);
return 1;
end
-- TODO: what is this, and do we need it.
declare @PAYMENTGROUPID uniqueidentifier = null;
select top(1)
@PAYMENTGROUPID = PAYMENTGROUPID
from (
select
T.item.value('(@AMOUNTREFUNDING)[1]','money') as AMOUNTPAID,
T.item.value('(@PAYMENTGROUPID)[1]','uniqueidentifier') as PAYMENTGROUPID,
T.item.value('(@PAYMENTGROUPMAXAMOUNT)[1]','money') as PAYMENTGROUPMAXAMOUNT
from @REFUNDMETHODS.nodes('/REFUNDMETHODS/ITEM') T(item)
) PAYMENTS
group by PAYMENTGROUPID, PAYMENTGROUPMAXAMOUNT
having sum(AMOUNTPAID) > PAYMENTGROUPMAXAMOUNT;
if (@PAYMENTGROUPID is not null) and (@PAYMENTGROUPID <> '00000000-0000-0000-0000-000000000000')
begin
declare @PAYMENTSLIST nvarchar(1000)
declare @PAYMENTGROUPMAXAMOUNT nvarchar(25)
select
@PAYMENTSLIST = dbo.UDA_BUILDLIST(T.item.value('(@DESCRIPTION)[1]','nvarchar(1000)'))
from @REFUNDMETHODS.nodes('/REFUNDMETHODS/ITEM') T(item)
where T.item.value('(@PAYMENTGROUPID)[1]','uniqueidentifier') = @PAYMENTGROUPID
select top(1)
@PAYMENTGROUPMAXAMOUNT = convert(nvarchar(25), T.item.value('(@PAYMENTGROUPMAXAMOUNT)[1]','money'))
from @REFUNDMETHODS.nodes('/REFUNDMETHODS/ITEM') T(item)
where T.item.value('(@PAYMENTGROUPID)[1]','uniqueidentifier') = @PAYMENTGROUPID
set @PAYMENTSLIST = 'The original transaction includes multiple payment methods, so you cannot return the full transaction amount as one refund payment. You may return up to $' + @PAYMENTGROUPMAXAMOUNT + ' among the following payments: ' + @PAYMENTSLIST + '.'
raiserror(@PAYMENTSLIST, 13, 1);
return 1;
end
-- Find contributed revenue (only for sales ER's; currently, you cannot refund BO event registrations with contributed revenue).
declare @CONTRIBUTEDREVENUE table (
CONTRIBUTEDLINEITEMID uniqueidentifier,
SOURCELINEITEMID uniqueidentifier,
TYPECODE tinyint,
[DESCRIPTION] nvarchar(200),
ORIGINALAMOUNT money
);
-- Find contributed revenue.
insert into @CONTRIBUTEDREVENUE
select
CONTRIBUTEDLI.ID CONTRIBUTEDLINEITEMID,
CONTRIBUTEDLI.SOURCELINEITEMID,
6 TYPECODE,
CONTRIBUTEDLI.[DESCRIPTION],
CONTRIBUTEDLI.BASEAMOUNT ORIGINALAMOUNT
from @CREDITITEMS CREDITITEMS
inner join dbo.EVENTREGISTRANTPAYMENT ERP on ERP.REGISTRANTID = CREDITITEMS.EVENTREGISTRANTID
inner join dbo.FINANCIALTRANSACTIONLINEITEM CONTRIBUTEDLI on CONTRIBUTEDLI.SOURCELINEITEMID = ERP.PAYMENTID -- ERP.PAYMENTID is a line item on an Order transaction, in this case.
inner join dbo.REVENUESPLIT_EXT CONTRIBUTEDLI_EXT on CONTRIBUTEDLI_EXT.ID = CONTRIBUTEDLI.ID
where
CONTRIBUTEDLI_EXT.TYPECODE = 0 -- Gift (eliminates the payment LI whose source is the earned LI)
and CONTRIBUTEDLI_EXT.APPLICATIONCODE = 1 -- Application is "Event Registration" (eliminates the payment LI whose source is the contributed LI)
and CONTRIBUTEDLI.TYPECODE = 0 -- Standard (eliminates adjustments)
and not exists ( -- Don't include refunded contributed revenue.
select 1
from dbo.FINANCIALTRANSACTIONLINEITEM REFUNDLI
inner join dbo.CREDITITEM_EXT REFUNDLI_EXT on REFUNDLI_EXT.ID = REFUNDLI.ID
where REFUNDLI.SOURCELINEITEMID = CONTRIBUTEDLI.ID
);
if @@ROWCOUNT > 0
begin
-- Subtract contributed amount from revenue refund amount on items with partially contributed revenue.
update @CREDITITEMS
set AMOUNTTOREFUND = PRICE - coalesce((select sum(ORIGINALAMOUNT) from @CONTRIBUTEDREVENUE),0);
-- At this point:
-- -- 1. The UNITVALUE of a partially contributed credit item will reflect its original price.
-- -- 2. The AMOUNTTOREFUND of a partially contributed credit item will be PRICE - CONTRIBUTEDREVENUE.
-- Otherwise the refund GL will not be generated correctly.
end
declare @INS table
(
ID uniqueidentifier,
CREDITID uniqueidentifier,
SALESORDERITEMID uniqueidentifier,
PRICE money,
TYPECODE tinyint,
[DESCRIPTION] nvarchar(700),
GROUPID uniqueidentifier,
GROUPTYPECODE tinyint,
SOURCELINEITEMID uniqueidentifier,
REFUNDAMOUNT money,
UNITVALUE money
);
with CREDITPAYMENTS_CTE as (
select
T.item.value('(@AMOUNTREFUNDING)[1]','money') AMOUNT,
case
when T.item.value('(@REVENUEID)[1]','uniqueidentifier') = '00000000-0000-0000-0000-000000000000'
then null
else
T.item.value('(@REVENUEID)[1]','uniqueidentifier')
end REVENUEID,
case
when T.item.value('(@REVENUESPLITID)[1]','uniqueidentifier') = '00000000-0000-0000-0000-000000000000'
then null
else
T.item.value('(@REVENUESPLITID)[1]','uniqueidentifier')
end REVENUESPLITID
from @REFUNDMETHODS.nodes('/REFUNDMETHODS/ITEM') T(item)
)
insert into @INS
select
newid(), -- 2013-07-10 SW: account for multiple backoffice payment methods
@ID,
CREDITPAYMENTS.SALESORDERITEMID,
coalesce(CREDITPAYMENTS.PAIDAMOUNT,0), -- switch to refund amount
6 as TYPECODE,
dbo.UFN_CONSTITUENT_BUILDNAME(REGISTRANT.CONSTITUENTID) + ' - ' + EVENT.NAME,
CREDITITEMS.EVENTREGISTRANTID GROUPID, -- why this column is called GROUPID I cannot fathom
1 GROUPTYPECODE, -- why this column exists at all is beyond my feeble comprehension
CREDITPAYMENTS.REVENUESPLITID,
CREDITPAYMENTS.EARNEDAMOUNT,
CREDITPAYMENTS.PAIDAMOUNT
from @CREDITITEMS CREDITITEMS
inner join dbo.REGISTRANT on CREDITITEMS.EVENTREGISTRANTID = REGISTRANT.ID
inner join dbo.[EVENT] on REGISTRANT.EVENTID = [EVENT].ID
outer apply (
--Backoffice payments
select
null as SALESORDERITEMID,
CREDITPAYMENT.AMOUNT EARNEDAMOUNT, -- This would not be correct if we had contributed revenue, but we don't make refunds with backoffice contributed revenue.
CREDITPAYMENT.AMOUNT PAIDAMOUNT,
CREDITPAYMENT.REVENUESPLITID
from CREDITPAYMENTS_CTE CREDITPAYMENT
inner join dbo.EVENTREGISTRANTPAYMENT on CREDITPAYMENT.REVENUESPLITID = EVENTREGISTRANTPAYMENT.PAYMENTID
where CREDITPAYMENT.REVENUESPLITID is not null
union all
--Order payments
select
SALESORDERITEM.ID as SALESORDERITEMID,
PAYMENTSPLIT.BASEAMOUNT EARNEDAMOUNT,
sum(CREDITPAYMENT.AMOUNT) PAIDAMOUNT,
PAYMENTSPLIT.ID
from CREDITPAYMENTS_CTE CREDITPAYMENT
inner join dbo.SALESORDERPAYMENT on SALESORDERPAYMENT.PAYMENTID = CREDITPAYMENT.REVENUEID
inner join dbo.SALESORDER on SALESORDER.ID = SALESORDERPAYMENT.SALESORDERID
inner join dbo.SALESORDERITEM on SALESORDERITEM.SALESORDERID = SALESORDERPAYMENT.SALESORDERID
inner join dbo.SALESORDERITEMEVENTREGISTRATION on SALESORDERITEM.ID = SALESORDERITEMEVENTREGISTRATION.ID
inner join dbo.REGISTRANT on SALESORDERITEMEVENTREGISTRATION.REGISTRANTID = REGISTRANT.ID
left join dbo.EVENTREGISTRANTPAYMENT on EVENTREGISTRANTPAYMENT.REGISTRANTID = REGISTRANT.ID
left join dbo.FINANCIALTRANSACTIONLINEITEM PAYMENTSPLIT on PAYMENTSPLIT.ID = EVENTREGISTRANTPAYMENT.PAYMENTID -- I think this is actually an order split, but don't take my word for it.
left join dbo.REVENUESPLIT_EXT on REVENUESPLIT_EXT.ID = PAYMENTSPLIT.ID
left join dbo.FINANCIALTRANSACTION on FINANCIALTRANSACTION.ID = PAYMENTSPLIT.FINANCIALTRANSACTIONID
where SALESORDERITEMEVENTREGISTRATION.REGISTRANTID = @REGISTRANTID
and FINANCIALTRANSACTION.ID = SALESORDER.REVENUEID
and REVENUESPLIT_EXT.APPLICATIONCODE = 1
and REVENUESPLIT_EXT.TYPECODE = 1
group by SALESORDERITEM.ID, PAYMENTSPLIT.ID, PAYMENTSPLIT.BASEAMOUNT
) CREDITPAYMENTS;
-- Contributed revenue
insert into @INS
select
newid(),
@ID,
null,
ORIGINALAMOUNT,
TYPECODE,
[DESCRIPTION],
null,
0 GROUPTYPECODE,
CONTRIBUTEDLINEITEMID,
ORIGINALAMOUNT,
ORIGINALAMOUNT
from @CONTRIBUTEDREVENUE;
begin try
-- Bug #167166 - MDC
-- Weird that the @TRANSACTIONDATE is being inserted into a datetimeoffset column. Always has offset 0.
declare @TRANSACTIONDATE datetime = dbo.UFN_TIMEZONEENTRY_GETSYSTEMDEFAULTDATEFROMUTC(getutcdate());
declare @CURRENCYID uniqueidentifier = (select ID from dbo.CURRENCY where ISORGANIZATIONCURRENCY = 1);
declare @PDACCOUNTSYSTEMID uniqueidentifier;
declare @ALLOWGLDISTRIBUTIONS bit;
select
@PDACCOUNTSYSTEMID = ID,
@ALLOWGLDISTRIBUTIONS = ALLOWGLDISTRIBUTIONS
from
dbo.UFN_PDACCOUNTSYSTEM_DEFAULTORSYSTEM();
declare @CONSTITUENTID uniqueidentifier = (select REGISTRANT.CONSTITUENTID from dbo.REGISTRANT where ID = @REGISTRANTID);
-- This seems shaky. If there are multiple sales order payments we're refunding, we set the SALESORDERID in CREDIT_EXT to be the first one we find.
declare @EVENTREGISTRATIONREVENUEID uniqueidentifier = (
select top 1 T.item.value('(@REVENUEID)[1]','uniqueidentifier')
from @REFUNDMETHODS.nodes('/REFUNDMETHODS/ITEM') T(item)
);
declare @ORDERID uniqueidentifier;
if @EVENTREGISTRATIONREVENUEID <> '00000000-0000-0000-0000-000000000000'
begin
select top 1 @ORDERID = SALESORDERPAYMENT.SALESORDERID
from dbo.SALESORDERPAYMENT
where PAYMENTID = @EVENTREGISTRATIONREVENUEID;
end
insert into dbo.FINANCIALTRANSACTION
(
ID,
TRANSACTIONAMOUNT,
BASEAMOUNT,
ORGAMOUNT,
TRANSACTIONCURRENCYID,
TYPECODE,
PDACCOUNTSYSTEMID,
[DESCRIPTION],
[DATE],
POSTDATE,
POSTSTATUSCODE,
PARENTID,
APPUSERID,
CONSTITUENTID,
DATEADDED, DATECHANGED, ADDEDBYID, CHANGEDBYID
)
values
(
@ID,
@REFUNDEDITEMTOTAL,
@REFUNDEDITEMTOTAL,
@REFUNDEDITEMTOTAL,
@CURRENCYID,
23, --Refund
@PDACCOUNTSYSTEMID,
@COMMENT,
@TRANSACTIONDATE,
case when @ALLOWGLDISTRIBUTIONS = 1 and isnull(@POSTSTATUSCODE, 1) != 3 then cast(@TRANSACTIONDATE as date) else null end,
case when @ALLOWGLDISTRIBUTIONS = 1 and isnull(@POSTSTATUSCODE, 1) != 3 then 1 else 3 end,
(select REVENUEID from dbo.SALESORDER where ID = @ORDERID),
@CURRENTAPPUSERID,
@CONSTITUENTID,
@CURRENTDATE, @CURRENTDATE, @CHANGEAGENTID, @CHANGEAGENTID
);
insert into dbo.CREDIT_EXT
(
ID,
SALESORDERID,
CREDITREASONCODEID,
DATEADDED, DATECHANGED, ADDEDBYID, CHANGEDBYID
)
values
(
@ID,
@ORDERID,
case @CREDITREASONCODEID
when '00000000-0000-0000-0000-000000000000' then null
else @CREDITREASONCODEID
end,
@CURRENTDATE, @CURRENTDATE, @CHANGEAGENTID, @CHANGEAGENTID
);
exec dbo.USP_CREDIT_ADDCREDITPAYMENTS @ID, @REFUNDMETHODS, @CHANGEAGENTID, @CURRENTAPPUSERID, @ADDRESSID;
insert into dbo.FINANCIALTRANSACTIONLINEITEM
(
ID,
FINANCIALTRANSACTIONID,
UNITVALUE,
QUANTITY,
[DESCRIPTION],
TRANSACTIONAMOUNT,
BASEAMOUNT,
ORGAMOUNT,
POSTDATE,
POSTSTATUSCODE,
TYPECODE,
SOURCELINEITEMID,
ADDEDBYID, CHANGEDBYID, DATEADDED, DATECHANGED
)
select
I.ID,
I.CREDITID,
I.UNITVALUE,
1 QUANTITY,
I.[DESCRIPTION],
I.REFUNDAMOUNT,
I.REFUNDAMOUNT,
I.REFUNDAMOUNT,
FT.POSTDATE,
FT.POSTSTATUSCODE,
0 TYPECODE,
I.SOURCELINEITEMID,
@CHANGEAGENTID, @CHANGEAGENTID, @CURRENTDATE, @CURRENTDATE
from @INS I
inner join dbo.FINANCIALTRANSACTION FT on FT.ID = I.CREDITID;
insert into dbo.CREDITITEM_EXT
(
ID,
CREDITID,
DISCOUNTS,
FEES,
GROUPID,
GROUPTYPECODE,
SALESORDERITEMID,
TYPECODE,
ADDEDBYID, CHANGEDBYID, DATEADDED, DATECHANGED
)
select
ID,
CREDITID,
0 DISCOUNTS,
0 FEES,
GROUPID,
GROUPTYPECODE,
SALESORDERITEMID,
TYPECODE,
@CHANGEAGENTID, @CHANGEAGENTID, @CURRENTDATE, @CURRENTDATE
from @INS;
--Add credit event registration items
-- TODO: verify, wrt bug notes from July
insert into dbo.CREDITITEMEVENTREGISTRATION
(
ID,
REGISTRANTID,
EVENTNAME,
ADDEDBYID,
CHANGEDBYID,
DATEADDED,
DATECHANGED
)
select
ID, -- 2013-07-10 SW: @INS.ID is not the same as @CREDITITEMS.ID
GROUPID,
[DESCRIPTION],
@CHANGEAGENTID,
@CHANGEAGENTID,
@CURRENTDATE,
@CURRENTDATE
from @INS;
if @ALLOWGLDISTRIBUTIONS = 1 and isnull(@POSTSTATUSCODE, 1) != 3 begin
exec dbo.USP_REFUND_CREATEGLDISTRIBUTION @ID, @CHANGEAGENTID, @CURRENTDATE;
end
end try
begin catch
exec dbo.USP_RAISE_ERROR
return 1
end catch
return 0;
end