This proc RECALCULATES AND UPDATES a record in PostAP, by setting the outstanding and fForeignOutstanding values based on the allocations in the cAllocs field.
Recalculate - v2
--select * from postap p where p.AccountLink = 868 declare @vendorId bigint = 868 ;with AllocValues as ( SELECT p.AccountLink,p.AutoIdx, CmD = p.Credit - p.Debit, p.Outstanding, p.fForeignOutstanding ,SUM(a.fAmount) as AllocAmount ,SUM(a.fForeignAmount) as AllocAmountForeign ,AllocOutstanding = ROUND((p.Credit - p.Debit)- COALESCE(CASE WHEN p.Credit > 0 THEN 1 ELSE -1 END * SUM(a.fAmount),0),2) ,AllocOutstandingForeign = CASE WHEN V.bForCurAcc = 1 THEN ROUND((p.fForeignCredit - p.fForeignDebit)- COALESCE(CASE WHEN p.fForeignCredit > 0 THEN 1 ELSE -1 END * SUM(a.fForeignAmount),0),2) ELSE 0 END from PostAP p LEFT JOIN Vendor V ON p.AccountLink = V.DCLink OUTER APPLY _as_GL_AllocsSplit_NTEXT(p.cAllocs) a --where p.AccountLink = 868 GROUP BY p.AccountLink,p.AutoIdx, p.Outstanding, p.fForeignOutstanding,p.Credit, p.Debit,p.fForeignCredit, p.fForeignDebit ,V.bForCurAcc ) ,Diff as (select * ,DiffHC = Outstanding - AllocOutstanding ,DiffFC = fForeignOutstanding - AllocOutstandingForeign from AllocValues A WHERE ABS(Outstanding - AllocOutstanding) > 0.01 OR ABS(fForeignOutstanding - AllocOutstandingForeign) > 0.01) --select * from Diff UPDATE p SET p.Outstanding = Diff.AllocOutstanding , p.fForeignOutstanding = Diff.AllocOutstandingForeign FROM PostAP p INNER JOIN Diff ON p.AutoIdx = Diff.AutoIdx
CREATE OR ALTER PROCEDURE dbo._as_RecalcPostAPOutstanding @PostAPAutoIdx INT, @Preview BIT = 0 AS BEGIN SET NOCOUNT ON; ------------------------------------------------------------------ -- USAGE: -- -- Preview the recalculated outstanding amounts without updating: -- EXEC dbo._as_RecalcPostAPOutstanding -- @PostAPAutoIdx = 12345, -- @Preview = 1; -- -- -- Recalculate and update outstanding amounts: -- EXEC dbo._as_RecalcPostAPOutstanding -- @PostAPAutoIdx = 12345; ------------------------------------------------------------------ -- 1) Fetch stored & source values DECLARE @StoredOutstanding FLOAT, @StoredForeignOutstanding FLOAT, @Credit FLOAT, @Debit FLOAT, @ForeignCredit FLOAT, @ForeignDebit FLOAT --@cAllocs NTEXT; SELECT @StoredOutstanding = outstanding, @StoredForeignOutstanding = fForeignOutstanding, @Credit = Credit, @Debit = Debit, @ForeignCredit = fForeignCredit, @ForeignDebit = fForeignDebit -- @cAllocs = cAllocs FROM dbo.PostAP WHERE PostAP.AutoIdx = @PostAPAutoIdx; IF @@ROWCOUNT = 0 BEGIN RAISERROR('No PostAP record found for PostAPAutoIdx = %d', 16, 1, @PostAPAutoIdx); RETURN; END -- 2) Calculate base outstanding from Credit–Debit DECLARE @BaseOutstanding FLOAT = @Credit - @Debit, @BaseForeignOutstanding FLOAT = @ForeignCredit - @ForeignDebit; -- 3) Sum allocations from cAllocs DECLARE @AllocatedAmount FLOAT = 0, @AllocatedForeign FLOAT = 0; SELECT @AllocatedAmount = ISNULL(SUM(t.fAmount), 0), @AllocatedForeign = ISNULL(SUM(t.fForeignAmount), 0) FROM PostAP p cross apply dbo._as_GL_AllocsSplit_NTEXT(p.cAllocs) t where p.AutoIdx = @PostAPAutoIdx -- 4) Compute new outstanding values DECLARE @NewOutstanding FLOAT, @NewForeignOutstanding FLOAT; SELECT @NewOutstanding = CASE WHEN @BaseOutstanding > 0 THEN @BaseOutstanding - @AllocatedAmount ELSE -(ABS(@BaseOutstanding) - @AllocatedAmount) END , @NewForeignOutstanding = CASE WHEN @BaseForeignOutstanding > 0 THEN @BaseForeignOutstanding - @AllocatedForeign ELSE -(ABS(@BaseForeignOutstanding ) - @AllocatedForeign) END -- 5) If preview, show stored vs base vs new IF @Preview = 1 BEGIN SELECT p.AutoIdx AS PostAPAutoIdx, p.Outstanding AS StoredOutstanding, @BaseOutstanding AS CalculatedBaseOutstanding, @AllocatedAmount as AllocatedAmount, p.Credit - p.Debit as CmD, @NewOutstanding AS NewOutstanding, @StoredOutstanding - @NewOutstanding AS DifferenceFromStored, @StoredForeignOutstanding AS StoredForeignOutstanding, @BaseForeignOutstanding AS CalculatedBaseForeignOutstanding, @NewForeignOutstanding AS NewForeignOutstanding, @StoredForeignOutstanding - @NewForeignOutstanding AS ForeignDifferenceFromStored FROM PostAP p where p.AutoIdx = @PostAPAutoIdx RETURN; END -- 6) Otherwise, apply update in a transaction BEGIN TRAN; BEGIN TRY UPDATE dbo.PostAP SET outstanding = @NewOutstanding, fForeignOutstanding = @NewForeignOutstanding WHERE PostAP.AutoIdx = @PostAPAutoIdx; COMMIT TRAN; END TRY BEGIN CATCH ROLLBACK TRAN; THROW; END CATCH END GO