Stored Procedures [dbo].[CompleteMoversSuitePlasticPayment]
Properties
PropertyValue
ANSI Nulls OnYes
Quoted Identifier OnYes
Parameters
NameData TypeMax Length (Bytes)Direction
@inPlasticDealIdint4
@inApprovedAmountmoney8
@inStatementDetailIdint4
@inHolderNamevarchar(1000)1000
@inHolderLastNamevarchar(500)500
@inBillingAddressvarchar(1000)1000
@inBillingAddress2varchar(1000)1000
@inBillingCityvarchar(1000)1000
@inBillingStatevarchar(255)255
@inBillingPostalCodevarchar(255)255
@inBillingCountryvarchar(255)255
@inGatewayCustomerIdvarchar(40)40
@inTokenvarchar(1000)1000
@inAccessoryvarchar(1000)1000
@inExpirationDatevarchar(10)10
@inLastFourvarchar(4)4
@inTokenTypeCodevarchar(2)2
@inTokenTypeExtendedCodevarchar(32)32
@inApprovalCodevarchar(100)100
@inProcessorCodevarchar(100)100
@inTransactionIdvarchar(40)40
@inResponseCodevarchar(10)10
@inResponseMessagevarchar(255)255
@inCscResponseCodevarchar1
@inTransactionStatusvarchar(15)15
@inBillingCyclebigint8
@inCreatedAtUtcDateTimedatetime8
@inTransactionDatedatetime8
@inCurrentSysUserIdint4
@inHppSessionIdvarchar(50)50
@inMssTransactionIdvarchar(40)40
@inCurrencyCodevarchar(3)3
@inRecurringScheduleTransIdnvarchar(64)128
@outErrorCodeint4Out
@outMessagevarchar(256)256Out
Permissions
TypeActionOwning Principal
GrantExecuteMssExec
SQL Script
/**
*
* Description: Completes a plastic MoversSuite payment through the research plastic payments screen
* into MoversSuite as a cash receipt.  Depending upon if the original cash receipt was still usable
* (is voided and on a CR batch that is still in the 'System' state) or not, we will post to that
* cash receipt or we will create a new one.
*
* @param: Yes, there are lots of parameters.
*
* Error Codes:
*
*/

CREATE procedure [dbo].[CompleteMoversSuitePlasticPayment]
    @inPlasticDealId int,
    @inApprovedAmount money,
    @inStatementDetailId int,
    @inHolderName varchar(1000),
    @inHolderLastName varchar(500),
    @inBillingAddress varchar(1000),
    @inBillingAddress2 varchar(1000),
    @inBillingCity varchar(1000),
    @inBillingState varchar(255),
    @inBillingPostalCode varchar(255),
    @inBillingCountry varchar(255),
    @inGatewayCustomerId varchar(40),
    @inToken varchar(1000),
    @inAccessory varchar(1000),
    @inExpirationDate varchar(10),
    @inLastFour varchar(4),
    @inTokenTypeCode varchar(2),
    @inTokenTypeExtendedCode varchar(32),
    @inApprovalCode varchar(100),
    @inProcessorCode varchar(100),
    @inTransactionId varchar(40),
    @inResponseCode varchar(10),
    @inResponseMessage varchar(255),
    @inCscResponseCode varchar(1),
    @inTransactionStatus varchar(15),
    @inBillingCycle bigint,
    @inCreatedAtUtcDateTime datetime = null,
    @inTransactionDate datetime,
    @inCurrentSysUserId int,
    @inHppSessionId varchar(50),
    @inMssTransactionId varchar(40),
    @inCurrencyCode varchar(3),
    @inRecurringScheduleTransId nvarchar(64),
    @outErrorCode int output,
    @outMessage varchar(256) output
as
set nocount on

set @outErrorCode = 0
set @outMessage = null

-- Standard errors we report.
declare @UNKNOWN_STATEMENT_HEADER_ID int = 926
declare @UNKNOWN_CASH_RECEIPTS_BRANCH_NUMBERING int = 927
declare @UNSUCCESSFUL_PAYMENT_ON_A_POSTED_BATCH int = 928
declare @SUCCESSFUL_PAYMENT_ALREADY_RECORDED int = 929

declare @theRowCount int
declare @theOkToContinue bit = 0
declare @theHaveSuccessfulPayment bit
declare @theAccountingNoteId int
declare @thePlasticInstrumentId int
declare @theProviderId int
declare @theStatementHeaderId int
declare @theStatementDetailId int
declare @theStatementDetailDistId int
declare @theCustomerNumber varchar(15)
declare @theCRNumber varchar(20)
declare @theIsPostedOnAnother bit
declare @thePostedOnCRNumber varchar(20)

declare @theVoidedReason varchar(267)
declare @theCurrentDateTime datetime = getdate()
declare @theTokenTypeId int
declare @theOrderId int
declare @theNoteBody varchar(350)
declare @thePlasticDealDescription varchar(255)
declare @theBranchPriKey int
declare @theJournalDate datetime
declare @theDepositTransactionDate datetime
declare @thePaymentTypeId int
declare @thePaymentCodeId int
declare @theShipperName varchar(55)
declare @theOrderNumber varchar(23)
declare @theTransactionCode varchar(267)

declare @theTokenTypeTable table
(
    TokenTypeFID int
)

-- Get a simple BIT value that we can reuse and simplify this stored proc.
set @theHaveSuccessfulPayment = case when isnull( @inApprovedAmount, 0 ) != 0 then 1 else 0 end

-- Let's try and use the existing cash receipt this PlasticDeal was originally attached to.
-- Let's also get all the data we need in related tables as well.
update StatementDetail set
    @theAccountingNoteId = VoidedNote,
    @thePlasticInstrumentId = PlasticDeal.InstrumentFID,
    @theProviderId = PlasticInstrument.ProviderFID,
    @theOrderId = PlasticInstrument.OrderFID,
    @theStatementHeaderId = StatementDetail.SHPriKey,
    @theStatementDetailId = StatementDetail.SDPriKey,
    @theCustomerNumber = case
        when isnull( PlasticInstrument.CustomerNumber, '' ) != '' then rtrim( PlasticInstrument.CustomerNumber )
        when isnull( Orders.CustomerNumber, '' ) != '' then rtrim( Orders.CustomerNumber )
        else null
    end,
    @theCRNumber = StatementDetail.CRNumber,
    @thePlasticDealDescription = PlasticDeal.[Description],
    Amount = case when @theHaveSuccessfulPayment = 1 then @inApprovedAmount else 0 end,
    CheckConf = @inApprovalCode,
    VoidedBy = case when @theHaveSuccessfulPayment = 1 then null else @inCurrentSysUserId end,
    VoidedDate = case when @theHaveSuccessfulPayment = 1 then null else @theCurrentDateTime end,
    VoidedNote = case when @theHaveSuccessfulPayment = 1 then null else VoidedNote end,
    Status = case when @theHaveSuccessfulPayment = 1 then 'Open' else 'Voided' end
from PlasticDeal
inner join PlasticInstrument on PlasticInstrument.InstrumentID = PlasticDeal.InstrumentFID
inner join StatementDetail on StatementDetail.SDPriKey = PlasticDeal.StatementDetailFID
inner join StatementHeader on StatementHeader.SHPriKey = StatementDetail.SHPriKey
left outer join Orders on Orders.PriKey = PlasticInstrument.OrderFID
where PlasticDeal.DealID = @inPlasticDealId and
    PlasticDeal.ApprovedAmount = 0 and
    PlasticDeal.StatementDetailFID = @inStatementDetailId and
    StatementDetail.VoidedDate is not null and
    StatementDetail.Amount = 0 and
    (
        (
            -- We are recording GL stuff so this batch better not be posted yet.
            @theHaveSuccessfulPayment = 1 and
            StatementHeader.[Status] = 'System' and
            (
                StatementDetail.CheckConf = 'Pending' or
                StatementDetail.[Status] = 'Voided'
            )
        ) or
        (
            -- We'll just be recording that the payment failed so if the batch is
            -- already posted, we won't affect anything.
            @theHaveSuccessfulPayment = 0 and
            StatementDetail.[Status] = 'Voided'
        )
    )

-- We only will update 1 row at most and only if all of the conditions are
-- perfect for us to perform this update.  Note that this update could be
-- days or weeks after the card was submitted, so we can't do this update
-- if the StatementHeader is being processed or completed processing by
-- Payment Management.
set @theRowCount = @@rowcount

if( @theRowCount = 1 )
begin
    -- Our original StatementHeader and StatementDetail are still available
    -- for our use so we will use them as is.
    set @theOkToContinue = 1
end
else if( @theRowCount = 0 )
begin
    -- OK, we can't use that batch so we'll use another one.

    -- Retrieve information about this PlasticDeal.  We can't proceed without it.
    select
        @theAccountingNoteId = null,
        @thePlasticInstrumentId = PlasticDeal.InstrumentFID,
        @theProviderId = PlasticInstrument.ProviderFID,
        @theOrderId = isnull( PlasticDeal.OrderFID, PlasticInstrument.OrderFID ),
        @theStatementHeaderId = null,
        @theStatementDetailId = null,
        @theStatementDetailDistId = null,
        @theCustomerNumber = case
            when isnull( PlasticDeal.CustomerNumber, '' ) != '' then rtrim( PlasticDeal.CustomerNumber )
            when isnull( PlasticInstrument.CustomerNumber, '' ) != '' then rtrim( PlasticInstrument.CustomerNumber )
            when isnull( Orders.CustomerNumber, '' ) != '' then rtrim( Orders.CustomerNumber )
            else null
        end,
        @theCRNumber = null,
        @thePlasticDealDescription = PlasticDeal.[Description],
        @theBranchPriKey = StatementDetail.BranchPriKey,
        @theShipperName = dbo.FormatFirstNameLastName( Orders.FirstName, Orders.LastName ),
        @theOrderNumber = Orders.OrderNo,
        @thePaymentTypeId = StatementDetail.PTPriKey,
        @thePaymentCodeId = StatementDetail.PaymentCodePriKey,
        @theDepositTransactionDate = StatementHeader.JournalDate
    from PlasticDeal
    inner join PlasticInstrument on PlasticInstrument.InstrumentID = PlasticDeal.InstrumentFID
    -- We SHOULD always have a StatementDetail but there is no guarantee since PlasticDeal.StatementDetailFID
    -- is a nullable field.
    left outer join StatementDetail on StatementDetail.SDPriKey = PlasticDeal.StatementDetailFID
    left outer join StatementHeader on StatementHeader.SHPriKey = StatementDetail.SHPriKey
    left outer join Orders on Orders.PriKey = PlasticInstrument.OrderFID
    where PlasticDeal.DealID = @inPlasticDealId

    set @theRowCount = @@rowcount

    if( @theRowCount = 1 )
    begin
        -- We found our PlasticDeal and other necessary info.
        if( @theHaveSuccessfulPayment = 1 )
        begin
            -- Before we create a new cash receipt on a different batch,
            -- let's see if this payment already exists in PlasticDeal.
            select top 1
                @theIsPostedOnAnother = 1,
                @thePostedOnCRNumber = isnull( StatementDetail.CRNumber, '??' )
            from PlasticDeal
            inner join PlasticInstrument on PlasticInstrument.InstrumentID = PlasticDeal.InstrumentFID
            left outer join StatementDetail on StatementDetail.SDPriKey = PlasticDeal.StatementDetailFID
            where PlasticInstrument.ProviderFID= @theProviderId and
                PlasticDeal.TransactionID = @inTransactionId and
                PlasticDeal.ApprovedAmount = @inApprovedAmount

            if( isnull( @theIsPostedOnAnother, 0 ) = 1 )
            begin
                set @outErrorCode = @SUCCESSFUL_PAYMENT_ALREADY_RECORDED
                set @theOkToContinue = 0
            end
            else
            begin
                -- We'll create a new cash receipt on a different batch.
                set @theOkToContinue = 1
            end
        end
        else
        begin
            -- Why bother creating a new StatementHeader and a new StatementDetail,
            -- use another Cash Receipt Number and mark them all as void?  The original
            -- one is already voided and that batch has already been "processed".  User
            -- can try again in the future and then if the payment becomes "successful",
            -- then we can process it on a new batch, new detail and new cash receipt.
            set @outErrorCode = @UNSUCCESSFUL_PAYMENT_ON_A_POSTED_BATCH
            set @theOkToContinue = 0
        end
    end

    if( @theOkToContinue = 1 )
    begin
        -- Get a unique electronic payment cash receipts batch for our branch.
        exec GetPlasticCRNumber
            @inBranchPriKey = @theBranchPriKey,
            @outCrNumber = @theCRNumber output

        if( isnull( @theCRNumber, '' ) = '' )
        begin
            -- Not sure there is anything we can do here except report an error.
            set @outErrorCode = @UNKNOWN_CASH_RECEIPTS_BRANCH_NUMBERING
            set @theOkToContinue = 0
        end
    end

    if( @theOkToContinue = 1 )
    begin
        if( @inCreatedAtUtcDateTime is null )
        begin
            -- The only way that @inCreatedAtUtcDateTime gets used is if the
            -- CashReceiptGetPlasticBatch's @inJournalDate parameter is null.
            set @theJournalDate = @inTransactionDate
        end

        -- First, create or get a StatementHeader for a new or existing unprocessed
        -- cash receipts batch using the actual date of this transaction.
        exec CashReceiptGetPlasticBatch
            @inBranchPriKey = @theBranchPriKey,
            @inSysUserID = @inCurrentSysUserId,
            @inSuppressStatementHeaderOutput = 1,
            @inJournalDate = @theJournalDate,
            @outStatementHeaderID = @theStatementHeaderId output,
            @inProviderID = @theProviderId,
            @inCreatedAtUtcDateTime = @inCreatedAtUtcDateTime

        if( isnull( @theStatementHeaderId, 0 ) = 0 )
        begin
            -- Not sure there is anything we can do here except report an error.
            set @outErrorCode = @UNKNOWN_STATEMENT_HEADER_ID
            set @theOkToContinue = 0
        end
    end

    if( @theOkToContinue = 1 )
    begin
        -- Get the (possibly calculated deposit) transaction date from the
        -- batch we are using.  JournalDate is technically nullable but it
        -- should be set as we always set it for us.
        set @theDepositTransactionDate = isnull( ( select JournalDate from StatementHeader where SHPriKey = @theStatementHeaderId ), @inTransactionDate )

        insert into StatementDetail
        (
            SHPriKey,
            [Description],
            Amount,
            BranchPriKey,
            CheckConf,
            CreatedBy,
            CRNumber,
            PTPriKey,
            [Status],
            UnappliedAmount,
            PaymentCodePriKey,
            Balance,
            ApplyAmount,
            AmountRemaining,
            ContestCharge,
            VanLineRefund,
            CustomerNumber,
            CRPrinted,
            IsApplyGridBuilt,
            CRNote,
            DateTimeCreated
        )
        select
            SHPriKey = @theStatementHeaderId,
            [Description] = case
                when isnull( @theOrderId, 0 ) > 0 then ( select dbo.FormatFirstNameLastName( FirstName, LastName ) from Orders where PriKey = @theOrderId )
                when isnull( @theCustomerNumber, '' ) != '' then ( select CustomerName from vCustomerInformation where CustomerNumber = @theCustomerNumber )
                else left( @thePlasticDealDescription, 128 )
            end,
            Amount = @inApprovedAmount,
            BranchPriKey = @theBranchPriKey,
            CheckConf = @inApprovalCode,
            CreatedBy = @inCurrentSysUserId,
            CRNumber = @theCRNumber,
            PTPriKey = @thePaymentTypeId,
            [Status] = 'Open',
            UnappliedAmount = 0,
            PaymentCodePriKey = @thePaymentCodeId,
            Balance = 0,
            ApplyAmount = 0,
            AmountRemaining = 0,
            ContestCharge = 0,
            VanLineRefund = 0,
            -- The CustomerNumber field will not display in MoversSuite if the CustomerNumber is missing the trailing spaces.
            CustomerNumber = case
                when isnull( @theCustomerNumber, '' ) != '' then left( @theCustomerNumber + space( 15 ), 15 )
                else null
            end,
            CRPrinted = 0,
            IsApplyGridBuilt = 0,
            CRNote = @theAccountingNoteId,
            DateTimeCreated = getdate()

        set @theStatementDetailId = scope_identity()

        if( isnull( @theOrderId, 0 ) > 0 )
        begin
            insert into StatementDetailDist
            (
                SDPriKey,
                OrderControl,
                [Description],
                Amount,
                BranchPriKey,
                OrdPriKey,
                CustomerNumber,
                UnappliedCash,
                UnappliedAmount,
                PaymentCodePriKey,
                Balance,
                ApplyAmount,
                AmountRemaining,
                Adjustment,
                ApplyCheck,
                ContestCharge
            )
            select
                SDPriKey = @theStatementDetailId,
                OrderControl = Orders.OrderNo,
                [Description] = Orders.LastName,
                Amount = 0,
                BranchPriKey = @theBranchPriKey,
                OrdPriKey = @theOrderId,
                CustomerNumber = case
                    when isnull( @theCustomerNumber, '' ) != '' then @theCustomerNumber
                    else null
                end,
                UnappliedCash = 0,
                UnappliedAmount = 0,
                PaymentCodePriKey = @thePaymentCodeId,
                Balance = 0,
                ApplyAmount = 0,
                AmountRemaining = 0,
                Adjustment = 0,
                ApplyCheck = 0,
                ContestCharge = 0
            from Orders
            where PriKey = @theOrderId

            set @theStatementDetailDistId = scope_identity()
        end

        if( isnull( @theCustomerNumber, '' ) != '' )
        begin
            exec CashReceiptAddContact
                @inStatementDetailID = @theStatementDetailId,
                @inCustomerNumber = @theCustomerNumber,
                @inCustomerAddressCode = ''
        end

        insert into PlasticDeal
        (
            InstrumentFID,
            DealType,
            [Description],
            TransactionCode,
            ApprovalCode,
            ProcessorCode,
            TransactionID,
            BillingCycle,
            OriginalAmount,
            ApprovedAmount,
            OriginFID,
            StatementDetailFID,
            TransactionDate,
            ResponseCode,
            ResponseMessage,
            CscResponseCode,
            TransactionStatus,
            SysUserFID,
            ActivityDate,
            HppSessionId,
            MssTransactionId,
            CurrencyCode,
            OrderFID,
            CustomerNumber,
            BranchFID
        )
        select
            InstrumentFID = @thePlasticInstrumentId,
            DealType = PlasticDeal.DealType,
            [Description] = PlasticDeal.[Description],
            -- Yes, use the original TransactionCode since that is how this transaction
            -- is referenced in the Provider's API system.  We can get the CRNumber
            -- this payment is recorded under in Cash Receipts module from the linked
            -- StatementDetail (which is what the ResearchView does).
            TransactionCode = PlasticDeal.TransactionCode,
            ApprovalCode = @inApprovalCode,
            ProcessorCode = @inProcessorCode,
            TransactionID = @inTransactionId,
            BillingCycle = @inBillingCycle,
            OriginalAmount = PlasticDeal.OriginalAmount,
            -- We should only be getting here with successful payments.
            ApprovedAmount = @inApprovedAmount,
            OriginFID = PlasticDeal.OriginFID,
            StatementDetailFID = @theStatementDetailId,
            TransactionDate = @theDepositTransactionDate,
            ResponseCode = @inResponseCode,
            ResponseMessage = @inResponseMessage,
            CscResponseCode = @inCscResponseCode,
            TransactionStatus = @inTransactionStatus,
            SysUserFID = @inCurrentSysUserId,
            ActivityDate = PlasticDeal.ActivityDate,
            HppSessionId = @inHppSessionId,
            MssTransactionId = @inMssTransactionId,
            CurrencyCode = @inCurrencyCode,
            OrderFID = @theOrderId,
            CustomerNumber = @theCustomerNumber,
            BranchFID = @theBranchPriKey
        from PlasticDeal
        where PlasticDeal.DealID = @inPlasticDealId

        -- From now on, we use this new PlasticDeal.
        set @inPlasticDealId = scope_identity()

    end
end

if( @theOkToContinue = 1 )
begin
    -- Deal with the temporary "voided" accounting note attached to the StatementDetail...
    if( @theHaveSuccessfulPayment = 1 )
    begin
        if( @theAccountingNoteId is not null )
        begin
            -- delete the temp voided note since this is now a successful payment.
            delete from AccountingNote
            where ANPriKey = @theAccountingNoteId
        end
    end
    else -- if( @theHaveSuccessfulPayment = 0 )
    begin
        if( ( isnull( @inResponseCode, '' ) != '' ) or ( isnull( @inResponseMessage, '' ) != '' ) )
        begin
            set @theVoidedReason = concat( @inResponseCode, ': ', @inResponseMessage )
        end
        else
        begin
            set @theVoidedReason = 'Transaction did not complete successfully.'
        end

        if( @theAccountingNoteId is null )
        begin
            -- We SHOULD rarely get here since we always add a temp voided note
            -- when we create the cash receipt reference number.  If we are
            -- creating a new cash receipt on a different batch, then we can
            -- get here (but we shouldn't get here since this is an unsuccessful
            -- payment).
            insert into AccountingNote
            (
                DateCreated,
                CreatedBy,
                NoteText
            )
            select
                DateCreated = @theCurrentDateTime,
                CreatedBy = @inCurrentSysUserId,
                NoteText = @theVoidedReason

            set @theAccountingNoteId = scope_identity()

            update StatementDetail set
                VoidedNote = @theAccountingNoteId
            where StatementDetail.SDPriKey = @theStatementDetailId
        end
        else
        begin
            -- Update the temp voided note's note text now that it
            -- really is voided due to a payment failure.
            update AccountingNote set
                DateCreated = @theCurrentDateTime,
                CreatedBy = @inCurrentSysUserId,
                NoteText = @theVoidedReason
            where AccountingNote.ANPriKey = @theAccountingNoteId
        end
    end
    -- Deal with the StatementDetailDist...
    -- Doesn't appear we do anything in MoversSuiteAPI to StatementDetailDist.

    -- Deal with the PlasticInstrument...
    if( @theHaveSuccessfulPayment = 1 )
    begin
        -- Obtain a valid token type using the same stored proc
        -- we use in the app to determine the token type.
        insert into @theTokenTypeTable( TokenTypeFID )
        exec DeterminePlasticTokenTypeId
            @inCode = @inTokenTypeCode,
            @inProviderId = @theProviderId,
            @inExternalCode = @inTokenTypeExtendedCode

        -- This will always succeed because this returns the "Other Credit Card" token
        -- type if @inTokenTypeCode nor @inTokenTypeExtendedCode can't be found.
        select
            @theTokenTypeId = TokenTypeFID
        from @theTokenTypeTable

        update PlasticInstrument set
            -- All payment providers send this data in all of their responses.
            Accessory = isnull( @inAccessory, Accessory ),
            ExpirationDate = isnull( @inExpirationDate, ExpirationDate ),
            TokenTypeFID = @theTokenTypeId,
            LastFour = @inLastFour,
            Token = isnull( @inToken, '' ),
            Inactive = case
                when Token = 'Data Removed' then 1        -- honor GDPR data removal
                when isnull( @inToken, '' ) = '' then 1
                -- For Remedy and Pyxis, we ONLY get a card token back if the user authorized
                -- us to keep his card on file for futre invoices.
                when isnull( @inToken, '' ) != '' and PlasticTokenType.Code != '**' then 0
                else Inactive
            end,
            GatewayCustomerID = @inGatewayCustomerId,
            -- Remedy never sends this info in a response so it never actually changes
            -- once the PlasticInstrument is created.  CSI-Pay does send us this data
            -- in their responses since those users can change the address via the
            -- hosted payment page.
            HolderName = isnull( @inHolderName, HolderName ),
            HolderLastName = isnull( @inHolderLastName, HolderLastName ),
            BillingAddress = isnull( @inBillingAddress, BillingAddress ),
            BillingAddress2 = isnull( @inBillingAddress2, BillingAddress2 ),
            BillingCity = isnull( @inBillingCity, BillingCity ),
            BillingState = isnull( @inBillingState, BillingState ),
            BillingPostalCode = isnull( @inBillingPostalCode, BillingPostalCode ),
            BillingCountry = isnull( @inBillingCountry, BillingCountry )
        from PlasticInstrument
        inner join PlasticTokenType on PlasticTokenType.TokenTypeID = @theTokenTypeId

        where PlasticInstrument.InstrumentID = @thePlasticInstrumentId
    end
    else --if( @theHaveSuccessfulPayment = 0 )
    begin
        -- If this is a 'Pending Tokenization' card, disable it from being used in the future.
        update PlasticInstrument set
            Inactive = 1
        from PlasticInstrument
        inner join PlasticTokenType on PlasticTokenType.TokenTypeID = PlasticInstrument.TokenTypeFID
        where PlasticInstrument.InstrumentID = @thePlasticInstrumentId and
            PlasticTokenType.Code = '**'
    end

    -- Deal with the PlasticDeal...
    update PlasticDeal set
        ApprovalCode = @inApprovalCode,
        ProcessorCode = isnull( @inProcessorCode, ProcessorCode ),
        TransactionID = isnull( @inTransactionId, TransactionID ),
        ResponseCode = isnull( @inResponseCode, ResponseCode ),
        ResponseMessage = isnull( @inResponseMessage, ResponseMessage ),
        CscResponseCode = isnull( @inCscResponseCode, CscResponseCode ),
        TransactionStatus = isnull( @inTransactionStatus, TransactionStatus ),
        BillingCycle = @inBillingCycle,
        ApprovedAmount = case when @theHaveSuccessfulPayment = 1 then @inApprovedAmount else 0 end,
        CurrencyCode = isnull( @inCurrencyCode, CurrencyCode ),
        -- Set these is they are not already set (which they (mostly) should be for new deals).
        HppSessionID = isnull( HppSessionID, @inHppSessionId ),
        MssTransactionID = isnull( MssTransactionID, @inMssTransactionId ),
        OrderFID = isnull( OrderFID, @theOrderId ),
        CustomerNumber = isnull( CustomerNumber, @theCustomerNumber ),
        BranchFID = isnull( BranchFID, @theBranchPriKey )
    where PlasticDeal.DealID = @inPlasticDealId

    -- Deal with logging an OrderNote...
    if( @theHaveSuccessfulPayment = 1 )
    begin
        if( isnull( @theOrderId, 0 ) > 0 )
        begin
            -- Add an order note if we are configured to do so.
            set @theNoteBody = 'Cash receipt ' + @theCRNumber + ' processed for ' + convert( varchar(30), isnull( @inApprovedAmount, 0 ), 1 ) +
                ': ' + isnull( @thePlasticDealDescription, '' )

            exec AddPlasticPaymentOrderNote
                @inProviderId = @theProviderId,
                @inOrderId = @theOrderId,
                @inCreatedBySysUserId = @inCurrentSysUserId,
                @inNoteBody = @theNoteBody
        end

        -- Deal with the StatementHeader...
        if( isnull( @theStatementHeaderId, 0 ) > 0 )
        begin
            -- Update the batch total amount on our cash receipts batch.
            exec CashReceiptUpdateBatch
                @inOldStatementHeaderID = null,
                @inNewStatementHeaderID = @theStatementHeaderId
        end
    end
end

-- Done.  Retrieve error message if we need one.
if( @outErrorCode != 0 )
begin
    select
        @outMessage = replace( ErrorCode.[Description], '{PostedOnCRNumber}', @thePostedOnCRNumber )
    from ErrorCode
    where ErrorCode.ECPriKey = @outErrorCode
end
else --if( @outErrorCode = 0 )
begin
    declare @theResultType varchar(20) = case
        when @theHaveSuccessfulPayment = 1 then 'recorded and updated'
        else 'marked as voided'
    end

    -- @theCRNumber should always be set if we get here.
    set @outMessage = concat( 'Payment was ', @theResultType, ' on cash receipt ', isnull( @theCRNumber, '???' ), '.' )
end
GO
GRANT EXECUTE ON  [dbo].[CompleteMoversSuitePlasticPayment] TO [MssExec]
GO
Uses