167971
System Failed to Create Deposit Checks when Transactions are Approved. Volume requires SQL resolution.
There is a situation that occurs occasionally where the deposit check object is not created when a transaction is approved by Forte. This will cause issues since the transaction will continue on as if nothing is wrong. However, the transaction will not appear in a deposit batch the way that it should, and without the deposit check to say that the invoice is satisfied, the customer could be charged for the same invoice down the line.
Normally, these can be resolved via a Manual Payment Batch. However, sometimes these occur in sufficient volume where the issue would take excessive time to resolve via the front end. Below are the set of scripts used to resolve this issue for API Alarm. The additional problem with this case was that it was caused by on-going server instability. That instability and the grequent timeouts made running the script for the entire contingent of transactions impossible. As such, there is a TOP(N) component of the script that configures the table for the number of records that can be run at one time.
Part 1 – Load the Temp Table
The first step is to run the below script to populate the temp table with the data used in Part 2.
First, run
‘--into [ZBG_CaseNumber_MMYY]’ uncommented with just the select statement to ensure there’s a copy of the data prior to making any changes.
There is a variable in the script you will need to fill in.
“and a.Submit_Date > ‘[Beginning_Date]' and a.Submit_Date < '[End_Date]'”
Change these variables to the beginning and end dates for when the issue occurred.
Before running the entire script, you should uncomment the below and use your example item to verify the process works.
“--AND I.INVOICE_NUMBER = [Example_Item]”
You will need to run the script in Part 2 to create the check. Then use the select query in Part 3 to verify the process has worked. Once run and verified, comment this line back out to run the bulk version of the script.
If you receive any time out while running Part 2, you can alter the ‘SELECT top(50)’ at the top of the script to a lower number that doesn’t time out.
/*This will show invoices, advance deposits,refunds, and unapplied cash.*/IF OBJECT_ID('tempdb..#tempt') IS NOT NULLBEGINDROP TABLE #tempt;END;SELECT TOP (50)a.ACH_Id,CAST(a.Submit_Date AS DATE) AS Submit_Date,IIF(a.Is_Credit = 'Y',-a.Amount,a.Amount) AS Amount,a.Hold_Date,a.Customer_Id,a.Type_UAIM,IIF(a.Credit_Card <> 'Y','ACH',IIF(a.Card_Type = 'AMER', 'AMER', 'CC')) AS Trans_Type,a.Invoice_Id,a.Trans_Status,IIF(a.Credit_Card <> 'Y','ACH',IIF(a.Card_Type = 'AMER', 'AMER', 'CC')) + REPLACE(EOMONTH(a.Submit_Date), '-', '') AS Batch_Desc,EOMONTH(a.Submit_Date) AS [Date],a.Merchant_Id-- INTO [ZBG_CaseNumber_MMYY]INTO #temptFROM AR_ACH AS aINNER JOIN AR_Customer AS cON c.Customer_Id = a.Customer_IdINNER JOIN AR_Invoice AS iON i.Invoice_Id = a.Invoice_IdWHERE a.Submitted = 'Y'AND a.Deposit_Check_Id = 1AND a.Voided <> 'Y'AND a.Inactive <> 'Y'AND a.Trans_Status IN ('APPROVED','REFUNDED','SETTLED')AND a.Response_Code IN ('A01','S01')AND a.Response_Type IN ('F','A')AND a.Second_Response_Type IN ('','F')AND a.Submit_Date > '[Beginning_Date]'AND a.Submit_Date < '[End_Date]'AND a.Amount <> 0AND a.Trace_Number <> ''-- AND i.Invoice_Number = 7476951-- AND CASE a.Type_UAIM-- WHEN 'I' THEN i.Net_Due-- ELSE a.Amount-- END > 0ORDER BY a.ACH_Id;GO/*Get the open batches beginning with the minimumtransaction submission date.*/IF OBJECT_ID('tempdb..#OpenBatches') IS NOT NULLBEGINDROP TABLE #OpenBatches;END;SELECT DISTINCTdb.Deposit_Batch_Id,db.Description,db.Date AS BatchDateINTO #OpenBatchesFROM AR_Deposit_Batch AS dbWHERE db.Date >= (SELECT MIN(CAST(Submit_Date AS DATE))FROM #tempt)AND db.Deposit_Id = 1ORDER BY db.Deposit_Batch_Id;GOALTER TABLE #temptADD Deposit_Batch_Id INT;GOALTER TABLE #temptADD Used VARCHAR(2);GO/*Match transactions to existing batches. */UPDATE tSETt.Batch_Desc = ob.Description,t.Date = ob.BatchDate,t.Deposit_Batch_Id = ob.Deposit_Batch_Id,t.Used = 'N'-- SELECT *FROM #tempt AS tCROSS APPLY (SELECT TOP (1)ob.*FROM #OpenBatches AS obWHERE CAST(t.Merchant_Id AS VARCHAR(10)) =LEFT(ob.Description, LEN(t.Merchant_Id))-- Match the payment method type to the batch typeAND LEFT(t.Trans_Type, 2) =SUBSTRING(ob.Description,CHARINDEX('_', ob.Description) + 1,2)-- Match the batch date to the transaction submission dateAND ob.BatchDate >= t.Submit_DateORDER BYob.BatchDate,ob.Deposit_Batch_Id) AS ob;GOIF OBJECT_ID('AchTempTab') IS NOT NULLBEGINDROP TABLE AchTempTab;END;GOSELECT *INTO AchTempTabFROM #tempt;GOSELECT *FROM AchTempTab;
Part 2 – Create the Deposit Checks
This script is rote and has no variables. The suggestion is to copy this script into a second query window in SSMS. Run Part 1 in its own window to populate the temp table. Then swap to the second window and run this script to make the checks. If it is the first time you are running the script, proceed to Part 3 for verification. Otherwise, return to Part 1 to populate the temp table with more data.
SET NOCOUNT ON;DECLARE@description VARCHAR(30),@cust_id INT,@reference VARCHAR(20), -- Customer number@usercode VARCHAR(15) = 'SedonaEFT',@deposit_batch_id INT,@date DATETIME,@ach_idx INT, -- ACH ID@amt MONEY,@branch_code VARCHAR(35),@postingDate DATETIME = GETDATE(),@collection_activity_id INT = 7, -- Payment posted@credit_card CHAR(1),@payment_meth_code VARCHAR(35),@last_4 VARCHAR(8),@type_uaim CHAR(1),@job_number VARCHAR(25),@income_account_code VARCHAR(25) = 'N/A',@invoice_id INT,@currentDate DATE = CAST(GETDATE() AS DATE),@RecordCount INT = 0;-- This is my activity loopWHILE EXISTS (SELECT 1FROM AchTempTab AS tWHERE t.used <> 'Y')BEGIN-- Grab the first ACH_ID to work onSET @ach_idx = (SELECT TOP (1) ACH_IdFROM AchTempTabWHERE used <> 'Y'ORDER BY ACH_Id);-- Test to make sure a check has not already been createdIF EXISTS (SELECT 1FROM AR_ACHWHERE ACH_Id = @ach_idxAND (Deposit_Check_Id > 1OR Voided = 'Y'))BEGINUPDATE AchTempTabSET used = 'Y'WHERE ACH_Id = @ach_idx;ENDELSEBEGIN-- Get the posting dateSELECT@date = COALESCE((SELECT t.DateFROM AchTempTab AS tWHERE t.ACH_Id = @ach_idxAND EXISTS (SELECT 1FROM GL_Accounting_Period AS glpWHERE t.Date BETWEEN glp.Start_DateAND glp.End_DateAND glp.Status IN ('O', 'R'))),@currentDate);SELECT@description = (SELECT Batch_DescFROM AchTempTabWHERE ACH_Id = @ach_idx);SELECT@deposit_batch_id = Deposit_Batch_IdFROM AR_Deposit_BatchWHERE Description = @description;SELECT@cust_id = Customer_Id,@type_uaim = Type_UAIM,@job_number = JobNumber,@invoice_id = Invoice_Id,@credit_card = Credit_Card,@last_4 = Last_Four_Digits,@amt = CASE Is_CreditWHEN 'Y' THEN -AmountELSE AmountENDFROM AR_ACHWHERE ACH_Id = @ach_idx;/*If Type_UAIM is 'I' and the amount is greater than theamount due on the invoice, turn it into unapplied cash.*/DECLARE @ZeroBalInvoice INT = 0;SELECT@ZeroBalInvoice = COUNT(*)FROM AR_ACH_Invoice AS aicINNER JOIN AR_Invoice AS invON aic.Invoice_Id = inv.Invoice_IdWHERE aic.ACH_Id = @ach_idxAND aic.Invoice_Id > 1AND aic.Amount - inv.Net_Due > 0.1;SELECT@type_uaim = CASEWHEN @type_uaim = 'I'AND @ZeroBalInvoice > 0THEN 'U'ELSE @type_uaimEND;SELECT@reference = arc.Customer_NumberFROM AR_Customer AS arcWHERE arc.Customer_Id = @cust_id;SET @branch_code = (SELECT Branch_CodeFROM AR_BranchWHERE Branch_Id = (SELECT Branch_IdFROM AR_CustomerWHERE Customer_Id = @cust_id));SET @payment_meth_code = (SELECT Payment_Method_CodeFROM AR_Payment_MethodWHERE Payment_Method_Id = (CASE @credit_cardWHEN 'Y' THEN (SELECT TOP (1) Payment_Method_IdFROM AR_Customer_CCWHERE Customer_Id = @cust_idAND Last_Four_Digits = @last_4ORDER BY Customer_CC_Id DESC)ELSE (SELECT TOP (1) Payment_Method_IdFROM AR_Customer_BankWHERE Customer_Id = @cust_idAND Last_Four_Digits = @last_4ORDER BY Customer_Bank_Id DESC)END));SELECT@payment_meth_code = ISNULL(@payment_meth_code,(SELECT Payment_Method_CodeFROM AR_Payment_MethodWHERE Payment_Method_Id = 1));DECLARE @p5 INT;EXEC dbo.Posting_Start@description,@usercode,@reference,'PYMT',@p5 OUTPUT; -- Posting IDDECLARE @checknumber VARCHAR(25) = 'ACH Processing';DECLARE @p15 INT;EXEC dbo.Deposit_Check_ADD@deposit_batch_id,@date,@payment_meth_code,'C',@reference,'','','',@checknumber,@date,@amt,@description,@branch_code,'N',@p15 OUTPUT; -- Deposit check IDUPDATE AR_Deposit_CheckSET ACH_Id = @ach_idxWHERE Deposit_Check_Id = @p15;DECLARE@adv_dep_id INT = 1,@una_cash_id INT = 1,@inv_number INT = 0,@p10 INT; -- Deposit check detail IDIF @type_uaim = 'A'BEGINEXEC Advance_Deposit_ADD@p15,@reference,@date,@job_number,@amt,0,@adv_dep_id OUTPUT;END;IF @type_uaim = 'U'BEGINEXEC Unapplied_Cash_ADD@p15,@reference,@date,@amt,0,@una_cash_id OUTPUT;END;IF @type_uaim = 'M'BEGINSELECT@income_account_code = (SELECT ISNULL(g.Account_Code, 'N/A')FROM GL_Account AS gINNER JOIN AR_ACH AS aON g.Account_Id = a.Misc_Account_IdWHERE a.ACH_Id = @ach_idx);END;IF @type_uaim = 'I'BEGINDECLARE@ach_inv_id INT,@invamt MONEY;WHILE EXISTS (SELECT 1FROM AR_ACH_Invoice AS ACHINVINNER JOIN AR_Invoice AS ARINVON ACHINV.Invoice_Id = ARINV.Invoice_IdWHERE ACHINV.ACH_Id = @ach_idxAND ACHINV.ACH_Invoice_Id > 1AND ACHINV.Invoice_Id > 1AND ACHINV.Amount <> 0AND ACHINV.Deposit_Check_Detail_Id = 1)BEGINSELECT TOP (1)@inv_number = ARINV.Invoice_Number,@ach_inv_id = ACHINV.ACH_Invoice_Id,@invamt = ACHINV.AmountFROM AR_ACH_Invoice AS ACHINVINNER JOIN AR_Invoice AS ARINVON ACHINV.Invoice_Id = ARINV.Invoice_IdWHERE ACHINV.ACH_Id = @ach_idxAND ACHINV.ACH_Invoice_Id > 1AND ACHINV.Invoice_Id > 1AND ACHINV.Amount <> 0AND ACHINV.Deposit_Check_Detail_Id = 1ORDER BY ACHINV.ACH_Invoice_Id;EXEC dbo.Deposit_Check_Detail_ADD@deposit_batch_id,@p15,@type_uaim,@una_cash_id,@adv_dep_id,@inv_number,@income_account_code,@invamt,'N/A',@p10 OUTPUT; -- Deposit check detail IDEXEC dbo.SEFT_Update_ACH_Invoice@ach_inv_id,@p10;END;END;ELSEBEGINEXEC dbo.Deposit_Check_Detail_ADD@deposit_batch_id,@p15,@type_uaim,@una_cash_id,@adv_dep_id,@inv_number,@income_account_code,@amt,'N/A',@p10 OUTPUT; -- Deposit check detail IDEND;EXEC Customer_Age@reference,@status = 0;DECLARE @register_number INT;EXEC dbo.Get_Register_For_Deposit_Check@p15,@register_number OUTPUT;DECLARE @errorcode INT;SET @errorcode = 0;DECLARE @errordescription NVARCHAR(255);SET @errordescription = '';EXEC dbo.Register_Balance_Check@register_number,@errorcode OUTPUT,@errordescription OUTPUT;SELECT@errorcode,@errordescription;EXEC dbo.ACH_Post@ach_idx,@p15;DECLARE @collection_event_id INT;EXEC dbo.Collection_Event_ADD@reference,'N/A','Posted Payment',@collection_activity_id,@postingDate,'Administrator','EFT Payment Posted',0,@amt,@collection_event_id OUTPUT;EXEC dbo.Posting_End@p5;UPDATE dSETd.Tape_Total = t.amt,d.Entered_Amount = t.amtFROM (SELECT SUM(Amount) AS amtFROM AR_Deposit_CheckWHERE Deposit_Batch_Id = @deposit_batch_id) AS tINNER JOIN AR_Deposit_Batch AS dON d.Deposit_Batch_Id = @deposit_batch_id;UPDATE AchTempTabSET used = 'Y'WHERE ACH_Id = @ach_idx;END;SELECT@RecordCount = @RecordCount + 1;SELECTCONCAT('Processed record count: ', @RecordCount);END;
Part 3 – Verify Function, Check for Errors
Once Part 2 completes, you can change the where clause, ‘where a.Ach_id = [Example]’, to have the relevant ID for your example and verify that the deposit check exists and is the appropriate batch. Then return to Part 1 and run the script for items in bulk. If you ever get a time out, you can modify this query to be for the last item before time out to verify it created a check.
SELECT cu.Customer_Number, a.ACH_Id, a.Type_UAIM, a.Entered_Date, a.Submit_Date, a.Amount [ACH Amount], a.Deposit_Check_Id, a.Trans_Status , a.Voided,c.Transaction_Date, c.Check_Number, c.Amount [Check Amount], gc.Register_Number, gc.Register_Id, gc.Account_Id, gc.Register_Type_Id, gc.Credit_Or_Debit, gc.Amount [GLC_Amount], cd.Deposit_Check_Detail_Id, cd.Type_UAIM, case cd.Type_UAIM when 'U' then cd.Unapplied_Cash_Id when 'A' then cd.Advance_Deposit_Id when 'M' then cd.Misc_Inc_Account_Id when 'I' then cd.Invoice_Id else 0 end as [Applied_Id], gd.Register_Id, gd.Account_Id, gd.Register_Type_Id, gd.Credit_Or_Debit, gd.Amount [GLCD_Amount], iv.invoice_number, iv.Invoice_Date, Net_Due, iv.Has_Pending_EFTFROM AR_ACH aINNER JOIN AR_Customer cu ON cu.Customer_Id = a.Customer_Idleft join ar_deposit_check c on c.deposit_check_id = a.deposit_check_id or c.ACH_Id = a.ACH_Idleft join AR_Deposit_Check_Detail cd on c.deposit_check_id = cd.deposit_check_idleft Join GL_Register gc on gc.Register_Id = c.Register_Idleft join GL_Register gd on gd.Register_Id = cd.Register_Idleft join AR_Invoice iv on iv.Invoice_Id = cd.Invoice_Id and cd.Invoice_Id > 1left Join AR_Unapplied_Cash u on u.Unapplied_Cash_Id = cd.Unapplied_Cash_Id and cd.Unapplied_Cash_Id > 1left Join AR_Unapplied_Cash_Detail ud on ud.Unapplied_Cash_Id = u.Unapplied_Cash_Idleft Join AR_Advance_Deposit ad on ad.Advance_Deposit_Id = cd.Advance_Deposit_Id and cd.Advance_Deposit_Id > 1left Join AR_Advance_Deposit_Detail adt on ad.Advance_Deposit_Id = adt.Advance_Deposit_Idwhere a.Ach_id = [Example]