USP_RECURRINGGIFT_APPLYPAYMENTTOINSTALLMENTS
Applies a payment to recurring gift installments.
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@APPLICATIONID | uniqueidentifier | IN | |
@CHANGEAGENTID | uniqueidentifier | IN | |
@CURRENTDATE | datetime | IN | |
@PAYMENTID | uniqueidentifier | IN | |
@APPLIEDAMOUNT | money | IN | |
@NEXTTRANSACTIONDATE | date | INOUT | |
@APPLICATIONCURRENCYID | uniqueidentifier | IN | |
@APPLICATIONEXCHANGERATEID | uniqueidentifier | IN | |
@PREVIOUSLYAPPLIEDAMOUNT | money | IN | |
@PREVIOUSLYAPPLIEDAMOUNTCONVERTED | money | IN | |
@PAYMENTDATE | date | IN | |
@APPLICATIONEFFECTIVEDATETIME | datetime | IN |
Definition
Copy
CREATE procedure dbo.USP_RECURRINGGIFT_APPLYPAYMENTTOINSTALLMENTS (
@APPLICATIONID uniqueidentifier,
@CHANGEAGENTID uniqueidentifier,
@CURRENTDATE datetime,
@PAYMENTID uniqueidentifier,
@APPLIEDAMOUNT money,
@NEXTTRANSACTIONDATE date output,
@APPLICATIONCURRENCYID uniqueidentifier = null,
@APPLICATIONEXCHANGERATEID uniqueidentifier = null,
@PREVIOUSLYAPPLIEDAMOUNT money = null,
@PREVIOUSLYAPPLIEDAMOUNTCONVERTED money = null, --deprecated
@PAYMENTDATE date = null,
@APPLICATIONEFFECTIVEDATETIME datetime = null
)
as
begin
set nocount on;
if @APPLICATIONCURRENCYID is null
set @APPLICATIONCURRENCYID = dbo.UFN_CURRENCY_GETORGANIZATIONCURRENCY();
if not exists(select 'x' from dbo.RECURRINGGIFTINSTALLMENT where REVENUEID = @APPLICATIONID)
begin
exec dbo.USP_RECURRINGGIFT_FIXMISSINGINSTALLMENTSCHEDULE @APPLICATIONID, @CHANGEAGENTID, @CURRENTDATE
end
set @NEXTTRANSACTIONDATE = null;
declare @RGAMOUNT money;
declare @RGTRANSACTIONAMOUNT money;
declare @RGORGANIZATIONAMOUNT money;
declare @RGTRANSACTIONCURRENCYID uniqueidentifier;
declare @RGBASECURRENCYID uniqueidentifier;
declare @RGBASEEXCHANGERATEID uniqueidentifier;
declare @RGORGANIZATIONEXCHANGERATEID uniqueidentifier;
declare @LASTINSTALLMENTDATE date;
select
@RGAMOUNT = AMOUNT,
@RGTRANSACTIONAMOUNT = TRANSACTIONAMOUNT,
@RGORGANIZATIONAMOUNT = ORGANIZATIONAMOUNT,
@RGTRANSACTIONCURRENCYID = TRANSACTIONCURRENCYID,
@RGBASECURRENCYID = BASECURRENCYID,
@RGBASEEXCHANGERATEID = BASEEXCHANGERATEID,
@RGORGANIZATIONEXCHANGERATEID = ORGANIZATIONEXCHANGERATEID
from dbo.REVENUE
where ID = @APPLICATIONID;
exec dbo.USP_RECURRINGGIFT_ADDMISSINGINSTALLMENTS
@APPLICATIONID,
@CHANGEAGENTID,
@CURRENTDATE,
@RGAMOUNT,
@LASTINSTALLMENTDATE output,
@RGBASECURRENCYID,
@RGORGANIZATIONAMOUNT,
@RGORGANIZATIONEXCHANGERATEID,
@RGTRANSACTIONAMOUNT,
@RGTRANSACTIONCURRENCYID,
@RGBASEEXCHANGERATEID;
declare @INSTALLMENTID uniqueidentifier;
declare @INSTALLMENTBALANCE money;
declare @INSTALLMENTAMOUNT money;
declare @INSTALLMENTDATE date;
declare @EXISTINGPAYMENTID uniqueidentifier;
declare @EXISTINGWRITEOFFID uniqueidentifier;
declare @EXISTINGADJUSTMENTID uniqueidentifier;
declare @APPLYREMAINING bit;
declare @NEXTINSTALLMENTEXISTS bit;
declare @FETCHROW smallint;
declare @APPLIEDAMOUNTCONVERTED money;
declare @AMOUNTPAIDCONVERTED money;
declare @AMOUNTLEFTCONVERTED money;
declare @PAYAMOUNTCONVERTED money;
declare @PAYMENTBASECURRENCYID uniqueidentifier;
declare @PAYMENTTRANSACTIONCURRENCYID uniqueidentifier;
declare @PAYMENTBASEEXCHANGERATEID uniqueidentifier;
declare @PAYMENTORGANIZATIONEXCHANGERATEID uniqueidentifier;
declare @PAYMENTRANSACTIONCURRENCYDECIMALDIGITS tinyint;
declare @REVENUEDATE datetime;
declare @ORGANIZATIONCURRENCYID uniqueidentifier = dbo.UFN_CURRENCY_GETORGANIZATIONCURRENCY();
-- The APPLICATIONEFFECTIVEDATE is the date we are treating as "today" for the payment handling rules.
-- On a new application, this date will always be the current date.
-- When adding money to an existing application, this will be the date the application was first created.
-- The only place where the behavior will be inconsistent regarding the use of this date to delineate past vs. future
-- is the installment underpayment rule - we will still write-off or adjust an installment in the past (in relation to today),
-- even if it's after the application effective date. This is noted again below.
if @APPLICATIONEFFECTIVEDATETIME is null
set @APPLICATIONEFFECTIVEDATETIME = @CURRENTDATE;
declare @APPLICATIONEFFECTIVEDATE date = @APPLICATIONEFFECTIVEDATETIME;
-- payment handling rules
declare @FIRSTINSTALLMENTCODE tinyint,
@INSTALLMENTUNDERPAYMENTCODE tinyint,
@APPLYTOPASTINSTALLMENTS bit,
@PASTBALANCEUNDERPAYMENTCODE tinyint,
@OVERPAYMENTCODE tinyint;
if dbo.UFN_RECURRINGGIFT_ISMEMBERSHIP(@APPLICATIONID) = 1
select @FIRSTINSTALLMENTCODE = 0, --oldest first
@INSTALLMENTUNDERPAYMENTCODE = 0, --leave balance
@APPLYTOPASTINSTALLMENTS = 1,
@PASTBALANCEUNDERPAYMENTCODE = 0, --leave balance
@OVERPAYMENTCODE = 0 --apply to future
else
begin
declare @USEEFFECTIVEDATE datetime;
if @PREVIOUSLYAPPLIEDAMOUNT is not null
set @USEEFFECTIVEDATE = @APPLICATIONEFFECTIVEDATETIME;
select @FIRSTINSTALLMENTCODE = FIRSTINSTALLMENTCODE, --0=oldest first, 1=most recent first
@INSTALLMENTUNDERPAYMENTCODE = INSTALLMENTUNDERPAYMENTCODE, --0=leave balance, 1=write-off, 2=adjust
@APPLYTOPASTINSTALLMENTS = APPLYTOPASTINSTALLMENTS,
@PASTBALANCEUNDERPAYMENTCODE = PASTBALANCEUNDERPAYMENTCODE, --0=leave balance, 1=write-off, 2=adjust
@OVERPAYMENTCODE = OVERPAYMENTCODE --0=apply to future, 1=adjust, 2=donation(handled at a higher level)
from dbo.UFN_RECURRINGGIFTSETTING(@USEEFFECTIVEDATE);
end
select
@REVENUEDATE = cast(FINANCIALTRANSACTION.DATE as datetime),
@PAYMENTBASECURRENCYID = isnull(REVENUE_EXT.NONPOSTABLEBASECURRENCYID, CURRENCYSET.BASECURRENCYID),
@PAYMENTTRANSACTIONCURRENCYID = FINANCIALTRANSACTION.TRANSACTIONCURRENCYID,
@PAYMENTBASEEXCHANGERATEID = FINANCIALTRANSACTION.BASEEXCHANGERATEID,
@PAYMENTORGANIZATIONEXCHANGERATEID = FINANCIALTRANSACTION.ORGEXCHANGERATEID,
@PAYMENTRANSACTIONCURRENCYDECIMALDIGITS = CURRENCY.DECIMALDIGITS
from
dbo.FINANCIALTRANSACTION
inner join dbo.REVENUE_EXT on FINANCIALTRANSACTION.ID = REVENUE_EXT.ID
inner join dbo.PDACCOUNTSYSTEM on FINANCIALTRANSACTION.PDACCOUNTSYSTEMID = PDACCOUNTSYSTEM.ID
inner join dbo.CURRENCYSET on PDACCOUNTSYSTEM.CURRENCYSETID = CURRENCYSET.ID
inner join dbo.CURRENCY on FINANCIALTRANSACTION.TRANSACTIONCURRENCYID = CURRENCY.ID
where
FINANCIALTRANSACTION.ID = @PAYMENTID
and FINANCIALTRANSACTION.DELETEDON is null;
if @APPLICATIONEXCHANGERATEID is null
set @APPLIEDAMOUNTCONVERTED = (isnull(@PREVIOUSLYAPPLIEDAMOUNT,0) + @APPLIEDAMOUNT);
else
set @APPLIEDAMOUNTCONVERTED = dbo.UFN_CURRENCY_CONVERT((isnull(@PREVIOUSLYAPPLIEDAMOUNT,0) + @APPLIEDAMOUNT), @APPLICATIONEXCHANGERATEID);
set @PAYAMOUNTCONVERTED =
coalesce(
(
select
sum(RECURRINGGIFTINSTALLMENTPAYMENT.AMOUNT)
from
dbo.RECURRINGGIFTINSTALLMENT
inner join dbo.RECURRINGGIFTINSTALLMENTPAYMENT on
RECURRINGGIFTINSTALLMENTPAYMENT.RECURRINGGIFTINSTALLMENTID = RECURRINGGIFTINSTALLMENT.ID
and RECURRINGGIFTINSTALLMENTPAYMENT.PAYMENTID = @PAYMENTID
where
RECURRINGGIFTINSTALLMENT.REVENUEID = @APPLICATIONID
), 0);
set @AMOUNTPAIDCONVERTED = @PAYAMOUNTCONVERTED;
set @AMOUNTLEFTCONVERTED = @APPLIEDAMOUNTCONVERTED - @PAYAMOUNTCONVERTED;
-- Update installments with no balance to use the new exchange rate and account for their amounts before handling installments that
-- have a remaining balance.
-- Since the transaction currency of the payment and the recurring gift cannot change we know
-- that edited payments previously used a null application exchange rate if the current rate is null
if @APPLICATIONEXCHANGERATEID is not null
update dbo.RECURRINGGIFTINSTALLMENTPAYMENT
set
APPLICATIONEXCHANGERATEID = @APPLICATIONEXCHANGERATEID,
CHANGEDBYID = @CHANGEAGENTID,
DATECHANGED = @CURRENTDATE
from
dbo.RECURRINGGIFTINSTALLMENT
left join dbo.RECURRINGGIFTINSTALLMENTPAYMENT on
RECURRINGGIFTINSTALLMENTPAYMENT.RECURRINGGIFTINSTALLMENTID = RECURRINGGIFTINSTALLMENT.ID
and RECURRINGGIFTINSTALLMENTPAYMENT.PAYMENTID = @PAYMENTID
where
RECURRINGGIFTINSTALLMENT.REVENUEID = @APPLICATIONID
and dbo.UFN_RECURRINGGIFTINSTALLMENT_GETINSTALLMENTBALANCE(RECURRINGGIFTINSTALLMENT.ID) <= 0
and RECURRINGGIFTINSTALLMENTPAYMENT.APPLICATIONEXCHANGERATEID <> @APPLICATIONEXCHANGERATEID;
declare @WRITEOFFAMOUNT money;
declare @ADJUSTINSTALLMENT bit;
declare @NEWINSTALLMENTAMOUNT money;
set @NEXTINSTALLMENTEXISTS = 0;
set @FETCHROW = 0;
declare INSTALLMENTCURSOR cursor local fast_forward for
with INSTALLMENTS as (
select RGI.ID,
dbo.UFN_RECURRINGGIFTINSTALLMENT_GETINSTALLMENTBALANCE(RGI.ID) +
isnull(W.TRANSACTIONAMOUNT,0) + -- add any payment-handling writeoff to the balance
case when E.OLDAMOUNT > E.NEWAMOUNT then E.OLDAMOUNT - E.NEWAMOUNT else 0 end BALANCE, -- add any payment-handling adjustment to the balance
-- if there is an underpayment adjustment, use the original amount, otherwise use the current installment amount
isnull(case when RGI.TRANSACTIONAMOUNT < E.OLDAMOUNT then E.OLDAMOUNT end,RGI.TRANSACTIONAMOUNT) INSTALLMENTAMOUNT,
RGI.DATE,
-- for edits
RGIP.ID PAYMENTID,
W.ID WRITEOFFID,
E.ID ADJUSTMENTID,
case when RGI.STATUSCODE in(0,1) or W.TRANSACTIONAMOUNT > 0 or E.OLDAMOUNT > E.NEWAMOUNT then 1 else 0 end HASBALANCE
from dbo.RECURRINGGIFTINSTALLMENT RGI
left join dbo.RECURRINGGIFTINSTALLMENTPAYMENT RGIP on RGIP.RECURRINGGIFTINSTALLMENTID = RGI.ID and RGIP.PAYMENTID = @PAYMENTID
outer apply (select W.ID, IW.TRANSACTIONAMOUNT
from dbo.RECURRINGGIFTINSTALLMENTWRITEOFF IW
inner join dbo.RECURRINGGIFTWRITEOFF W on W.ID = IW.WRITEOFFID
where IW.RECURRINGGIFTINSTALLMENTID = RGI.ID
and W.PAYMENTID = @PAYMENTID) W
left join dbo.RECURRINGGIFTINSTALLMENTEVENT E on E.RECURRINGGIFTINSTALLMENTID = RGI.ID and E.PAYMENTID = @PAYMENTID
where RGI.REVENUEID = @APPLICATIONID
)
select ID, BALANCE, INSTALLMENTAMOUNT, DATE, PAYMENTID, WRITEOFFID, ADJUSTMENTID, MOSTRECENTINSTALLMENTREPEATED
from (select ID, BALANCE, INSTALLMENTAMOUNT, DATE, PAYMENTID, WRITEOFFID, ADJUSTMENTID, 0 MOSTRECENTINSTALLMENTREPEATED
from INSTALLMENTS
where HASBALANCE = 1
-- we're increasing an existing payment amount, the previous amount fully paid an installment, and the overpayment should adjust that installment
or ((@APPLYTOPASTINSTALLMENTS = 0 or DATE > @APPLICATIONEFFECTIVEDATE) and @OVERPAYMENTCODE = 1 and PAYMENTID is not null)
union all
-- Repeat the most recent installment if the payment handling rules dictate that money
-- should be applied to the most recent installment first, then other past installments,
-- then any remaining should be applied to the most recent installment with an amount adjustment.
-- The balance of this installment will be 0 at the time it is accessed again.
select ID, 0, INSTALLMENTAMOUNT, DATE, PAYMENTID, WRITEOFFID, ADJUSTMENTID, 1
from (select top 1 ID, INSTALLMENTAMOUNT, DATE, PAYMENTID, WRITEOFFID, ADJUSTMENTID
from INSTALLMENTS
where DATE <= @APPLICATIONEFFECTIVEDATE
and @APPLYTOPASTINSTALLMENTS = 1
and @OVERPAYMENTCODE = 1
and (HASBALANCE = 1 or PAYMENTID is not null)
order by DATE desc) m) i
order by case when DATE <= @APPLICATIONEFFECTIVEDATE then 1 else 2 end, -- today/past, then future
MOSTRECENTINSTALLMENTREPEATED, -- repeated most recent installment after other today/past installments
case when DATE > @APPLICATIONEFFECTIVEDATE or @FIRSTINSTALLMENTCODE = 0 then DATE end, -- date asc if appropriate (past installments by rule, future installments always)
case when DATE <= @APPLICATIONEFFECTIVEDATE and @FIRSTINSTALLMENTCODE = 1 then DATE end desc; -- date desc if appropriate
open INSTALLMENTCURSOR;
fetch next from INSTALLMENTCURSOR into @INSTALLMENTID, @INSTALLMENTBALANCE, @INSTALLMENTAMOUNT, @INSTALLMENTDATE, @EXISTINGPAYMENTID, @EXISTINGWRITEOFFID, @EXISTINGADJUSTMENTID, @APPLYREMAINING;
while @@FETCH_STATUS = 0
begin
set @FETCHROW = @FETCHROW + 1;
set @WRITEOFFAMOUNT = 0;
set @ADJUSTINSTALLMENT = 0;
-- exit the loop if we have applied all the money
if @AMOUNTLEFTCONVERTED = 0 and
@FETCHROW > 1 and -- we will apply a $0 payment to the first installment, so don't exit yet
(@INSTALLMENTDATE > @APPLICATIONEFFECTIVEDATE or
@PASTBALANCEUNDERPAYMENTCODE = 0 or
@APPLYREMAINING = 1) -- we don't need to write-off or adjust this installment
begin
set @NEXTINSTALLMENTEXISTS = 1;
set @NEXTTRANSACTIONDATE = coalesce(@NEXTTRANSACTIONDATE,@INSTALLMENTDATE);
break;
end
-- we have money left to apply (@FETCHROW=1 is to apply a $0 payment to the first installment)
if @AMOUNTLEFTCONVERTED > 0 or @FETCHROW = 1
begin
-- check for donation error (we have money left after applying money to all appropriate installments per the rules)
if @OVERPAYMENTCODE = 2 and
@AMOUNTLEFTCONVERTED > 0 and
@FETCHROW > 1 and
(@APPLYTOPASTINSTALLMENTS = 0 or
(@APPLYTOPASTINSTALLMENTS = 1 and @INSTALLMENTDATE > @APPLICATIONEFFECTIVEDATE))
raiserror('More money is being applied to the recurring gift than is allowed according to the payment handling rules; the excess should have been split off as a donation.', 13, 1);
-- determine amount to apply, and any write-off or adjustment actions needed for this installment
if @AMOUNTLEFTCONVERTED <= @INSTALLMENTBALANCE or -- exact amount or underpayment of current installment
((@APPLYTOPASTINSTALLMENTS = 0 or @INSTALLMENTDATE > @APPLICATIONEFFECTIVEDATE) and @OVERPAYMENTCODE = 1) -- adjust amount for overpayment (thus making this an exact payment)
begin
set @PAYAMOUNTCONVERTED = @AMOUNTLEFTCONVERTED;
if @AMOUNTLEFTCONVERTED < @INSTALLMENTBALANCE
begin
set @NEXTINSTALLMENTEXISTS = 1;
set @NEXTTRANSACTIONDATE = @INSTALLMENTDATE;
if @INSTALLMENTUNDERPAYMENTCODE = 2 -- adjust amount
set @ADJUSTINSTALLMENT = 1;
-- write-off rule only applies to past/today installments
-- this is intentionally @CURRENTDATE, not @APPLICATIONEFFECTIVEDATE - we still want to apply the installment underpayment rule for
-- any past installment, even if it's after the application effective date
else if @INSTALLMENTUNDERPAYMENTCODE = 1 and @INSTALLMENTDATE <= @CURRENTDATE -- write-off
set @WRITEOFFAMOUNT = @INSTALLMENTBALANCE - @AMOUNTLEFTCONVERTED;
end
else if @AMOUNTLEFTCONVERTED > @INSTALLMENTBALANCE
set @ADJUSTINSTALLMENT = 1;
end
else if @APPLYREMAINING = 1
begin
-- to be here:
-- the overpayment rule is "adjust"
-- apply to past installments is true
-- We've applied the payment to all the past installments but still have more money.
-- Thus we need to apply it to the most recent installment, which has been fetched again from the cursor at this point.
-- The balance on this installment is 0, so the full remainder will be added to the installment amount below.
set @PAYAMOUNTCONVERTED = @AMOUNTLEFTCONVERTED;
set @ADJUSTINSTALLMENT = 1;
-- add the remaining money to the payment record created for this installment on an earlier loop iteration
select @EXISTINGPAYMENTID = ID
from dbo.RECURRINGGIFTINSTALLMENTPAYMENT
where RECURRINGGIFTINSTALLMENTID = @INSTALLMENTID
and PAYMENTID = @PAYMENTID;
end
else
-- only apply up to the balance of the installment
set @PAYAMOUNTCONVERTED = @INSTALLMENTBALANCE;
set @AMOUNTPAIDCONVERTED = @AMOUNTPAIDCONVERTED + @PAYAMOUNTCONVERTED;
set @AMOUNTLEFTCONVERTED = @AMOUNTLEFTCONVERTED - @PAYAMOUNTCONVERTED;
-- delete any existing write-off to make room for more money
if @EXISTINGWRITEOFFID is not null
begin
delete from dbo.RECURRINGGIFTWRITEOFF
where ID = @EXISTINGWRITEOFFID;
set @EXISTINGWRITEOFFID = null;
end
-- adjust the installment amount if appropriate
if @ADJUSTINSTALLMENT = 1 or @EXISTINGADJUSTMENTID is not null
begin
set @NEWINSTALLMENTAMOUNT = @INSTALLMENTAMOUNT - @INSTALLMENTBALANCE + @PAYAMOUNTCONVERTED;
exec dbo.USP_RECURRINGGIFT_ADJUSTINSTALLMENTAMOUNT
@INSTALLMENTID,
@INSTALLMENTAMOUNT,
@NEWINSTALLMENTAMOUNT,
@RGTRANSACTIONCURRENCYID,
@RGBASECURRENCYID,
@RGBASEEXCHANGERATEID,
@RGORGANIZATIONEXCHANGERATEID,
0,
@PAYMENTID,
@APPLICATIONEFFECTIVEDATETIME,
@CHANGEAGENTID,
@CURRENTDATE
end
-- apply the payment
if @EXISTINGPAYMENTID is null
insert into dbo.RECURRINGGIFTINSTALLMENTPAYMENT (
ID,
RECURRINGGIFTINSTALLMENTID,
PAYMENTID,
AMOUNT,
APPLICATIONCURRENCYID,
APPLICATIONEXCHANGERATEID,
ADDEDBYID, CHANGEDBYID, DATEADDED, DATECHANGED)
values (
newid(),
@INSTALLMENTID,
@PAYMENTID,
@PAYAMOUNTCONVERTED,
@APPLICATIONCURRENCYID,
@APPLICATIONEXCHANGERATEID,
@CHANGEAGENTID, @CHANGEAGENTID, @CURRENTDATE, @CURRENTDATE);
else
update dbo.RECURRINGGIFTINSTALLMENTPAYMENT
set AMOUNT = (AMOUNT + @PAYAMOUNTCONVERTED),
APPLICATIONEXCHANGERATEID = @APPLICATIONEXCHANGERATEID,
CHANGEDBYID = @CHANGEAGENTID,
DATECHANGED = @CURRENTDATE
where ID = @EXISTINGPAYMENTID;
end
else if @PASTBALANCEUNDERPAYMENTCODE = 1
-- We don't have any money left to apply, we are still looping through installments in order to write them off.
set @WRITEOFFAMOUNT = @INSTALLMENTBALANCE;
else if @PASTBALANCEUNDERPAYMENTCODE = 2
begin
-- We don't have any money left to apply, we are still looping through installments in order to adjust their amounts so that the balance is $0.
set @NEWINSTALLMENTAMOUNT = @INSTALLMENTAMOUNT - @INSTALLMENTBALANCE;
exec dbo.USP_RECURRINGGIFT_ADJUSTINSTALLMENTAMOUNT
@INSTALLMENTID,
@INSTALLMENTAMOUNT,
@NEWINSTALLMENTAMOUNT,
@RGTRANSACTIONCURRENCYID,
@RGBASECURRENCYID,
@RGBASEEXCHANGERATEID,
@RGORGANIZATIONEXCHANGERATEID,
2,
@PAYMENTID,
@APPLICATIONEFFECTIVEDATETIME,
@CHANGEAGENTID,
@CURRENTDATE
end
-- write-off the remaining installment balance if appropriate
if @WRITEOFFAMOUNT > 0 and @EXISTINGWRITEOFFID is null
exec dbo.USP_RECURRINGGIFT_ADDPAYMENTHANDLINGWRITEOFF
@APPLICATIONID,
@INSTALLMENTID,
@PAYMENTID,
@PAYMENTDATE,
@WRITEOFFAMOUNT,
@RGBASECURRENCYID,
@RGBASEEXCHANGERATEID,
@RGTRANSACTIONCURRENCYID,
@RGORGANIZATIONEXCHANGERATEID,
@CHANGEAGENTID,
@CURRENTDATE
fetch next from INSTALLMENTCURSOR into @INSTALLMENTID, @INSTALLMENTBALANCE, @INSTALLMENTAMOUNT, @INSTALLMENTDATE, @EXISTINGPAYMENTID, @EXISTINGWRITEOFFID, @EXISTINGADJUSTMENTID, @APPLYREMAINING;
end
--When a cursor is used, it should be explicitly closed/deallocated in case of blocking or USP running long
close INSTALLMENTCURSOR;
deallocate INSTALLMENTCURSOR;
-- check for donation error (we have money left after applying the payment to all available installments and we are not applying money to future installments)
if @OVERPAYMENTCODE = 2 and
@AMOUNTLEFTCONVERTED > 0
raiserror('More money is being applied to the recurring gift than is allowed according to the payment handling rules; the excess should have been split off as a donation.', 13, 1);
-- create additional (future) installments for any remaining amount
while @AMOUNTLEFTCONVERTED > 0
begin
set @INSTALLMENTID = newid();
set @LASTINSTALLMENTDATE = dbo.UFN_REVENUE_GETNEXTTRANSACTIONDATE_BYID_1_1(@APPLICATIONID,@LASTINSTALLMENTDATE);
if @AMOUNTLEFTCONVERTED <= @RGTRANSACTIONAMOUNT
begin
set @PAYAMOUNTCONVERTED = @AMOUNTLEFTCONVERTED;
if @AMOUNTLEFTCONVERTED < @RGTRANSACTIONAMOUNT
begin
set @NEXTINSTALLMENTEXISTS = 1;
set @NEXTTRANSACTIONDATE = @LASTINSTALLMENTDATE;
end
end
else
set @PAYAMOUNTCONVERTED = @RGTRANSACTIONAMOUNT;
set @AMOUNTPAIDCONVERTED = @AMOUNTPAIDCONVERTED + @PAYAMOUNTCONVERTED;
set @AMOUNTLEFTCONVERTED = @AMOUNTLEFTCONVERTED - @PAYAMOUNTCONVERTED;
if @RGAMOUNT is NULL
raiserror('The payment could not be saved. The associated recurring gift has been deleted.', 13, 1)
insert into dbo.RECURRINGGIFTINSTALLMENT (
ID,
REVENUEID,
AMOUNT,
DATE,
BASECURRENCYID,
ORGANIZATIONAMOUNT,
ORGANIZATIONEXCHANGERATEID,
TRANSACTIONAMOUNT,
TRANSACTIONCURRENCYID,
BASEEXCHANGERATEID,
ADDEDBYID, CHANGEDBYID, DATEADDED, DATECHANGED)
values (
@INSTALLMENTID,
@APPLICATIONID,
@RGAMOUNT,
@LASTINSTALLMENTDATE,
@RGBASECURRENCYID,
@RGORGANIZATIONAMOUNT,
@RGORGANIZATIONEXCHANGERATEID,
@RGTRANSACTIONAMOUNT,
@RGTRANSACTIONCURRENCYID,
@RGBASEEXCHANGERATEID,
@CHANGEAGENTID, @CHANGEAGENTID, @CURRENTDATE, @CURRENTDATE);
if @INSTALLMENTUNDERPAYMENTCODE = 2 -- adjust amount
exec dbo.USP_RECURRINGGIFT_ADJUSTINSTALLMENTAMOUNT
@INSTALLMENTID,
@RGTRANSACTIONAMOUNT,
@PAYAMOUNTCONVERTED,
@RGTRANSACTIONCURRENCYID,
@RGBASECURRENCYID,
@RGBASEEXCHANGERATEID,
@RGORGANIZATIONEXCHANGERATEID,
0,
@PAYMENTID,
@APPLICATIONEFFECTIVEDATETIME,
@CHANGEAGENTID,
@CURRENTDATE
insert into dbo.RECURRINGGIFTINSTALLMENTPAYMENT (
ID,
RECURRINGGIFTINSTALLMENTID,
PAYMENTID,
AMOUNT,
APPLICATIONCURRENCYID,
APPLICATIONEXCHANGERATEID,
ADDEDBYID, CHANGEDBYID, DATEADDED, DATECHANGED)
values (
newid(),
@INSTALLMENTID,
@PAYMENTID,
@PAYAMOUNTCONVERTED,
@APPLICATIONCURRENCYID,
@APPLICATIONEXCHANGERATEID,
@CHANGEAGENTID, @CHANGEAGENTID, @CURRENTDATE, @CURRENTDATE);
end
-- if no installments remain w/ a balance, create next installment
if @NEXTINSTALLMENTEXISTS = 0
begin
set @NEXTTRANSACTIONDATE = dbo.UFN_REVENUE_GETNEXTTRANSACTIONDATE_BYID_1_1(@APPLICATIONID,@LASTINSTALLMENTDATE)
if @NEXTTRANSACTIONDATE <= coalesce((select ENDDATE from dbo.REVENUESCHEDULE where ID = @APPLICATIONID),@NEXTTRANSACTIONDATE)
insert into dbo.RECURRINGGIFTINSTALLMENT (
ID,
REVENUEID,
AMOUNT,
DATE,
BASECURRENCYID,
ORGANIZATIONAMOUNT,
ORGANIZATIONEXCHANGERATEID,
TRANSACTIONAMOUNT,
TRANSACTIONCURRENCYID,
BASEEXCHANGERATEID,
ADDEDBYID, CHANGEDBYID, DATEADDED, DATECHANGED)
values (
newid(),
@APPLICATIONID,
@RGAMOUNT,
@NEXTTRANSACTIONDATE,
@RGBASECURRENCYID,
@RGORGANIZATIONAMOUNT,
@RGORGANIZATIONEXCHANGERATEID,
@RGTRANSACTIONAMOUNT,
@RGTRANSACTIONCURRENCYID,
@RGBASEEXCHANGERATEID,
@CHANGEAGENTID, @CHANGEAGENTID, @CURRENTDATE, @CURRENTDATE);
end
exec dbo.USP_RECURRINGGIFT_UPDATEREVENUESCHEDULE
@APPLICATIONID,
1,
null,
null,
null,
@RGAMOUNT,
@RGBASECURRENCYID,
@RGORGANIZATIONAMOUNT,
@RGORGANIZATIONEXCHANGERATEID,
@RGTRANSACTIONAMOUNT,
@RGTRANSACTIONCURRENCYID,
@RGBASEEXCHANGERATEID,
@CHANGEAGENTID,
@CURRENTDATE
end