Getting Cash-flow-statement
SqlServer,
SqlServer Useful functions
Introduction
Description
Step-by-Step Plan
๐น Step 1: Get Opening Balance from AccountHierarchyNew
-
Filter for
Category = 'Cash-In-Hand'
-
Use
TransactionDate = '1st April'
of the current financial year
DECLARE @OpeningBalance DECIMAL(18,2); SELECT @OpeningBalance = SUM(TransactionNetAmount) FROM AccountHierarchyNew WHERE Category = 'Cash-In-Hand' AND TransactionDate = DATEFROMPARTS(YEAR(GETDATE()), 4, 1);
๐น Step 2: Calculate Net Cash Movement from VoucherDetails
-
Filter for
Receipt_PaymentMode = 'Cash'
-
Use
TransactionType = 'Credit'
and 'Debit'
-
Restrict to the month range (
@FromDate
to @ToDate
)
DECLARE @CashMovement DECIMAL(18,2); SELECT @CashMovement = SUM(CASE WHEN TransactionType = 'Credit' THEN TransactionNetAmount ELSE 0 END) - SUM(CASE WHEN TransactionType = 'Debit' THEN TransactionNetAmount ELSE 0 END) FROM VoucherDetails WHERE Receipt_PaymentMode = 'Cash' AND (@FromDate IS NULL OR ReceiptDate >= @FromDate) AND (@ToDate IS NULL OR ReceiptDate <= @ToDate);
๎ท๎ท
๐น Step 3: Compute Cash Balance
DECLARE @CashBalance DECIMAL(18,2); SET @CashBalance = ISNULL(@OpeningBalance, 0) + ISNULL(@CashMovement, 0);
๐น Step 4: Inject Opening Balance into Receipts
We’ll insert a synthetic row into the #BaseData
temp table before the rest of the logic:
INSERT INTO #BaseData (Section, Category, Account, Amount) VALUES ('Receipts', 'Cash', 'Opening Balance', @CashBalance);
๐งฉ Final Integration Snippet
Here’s how you’d plug this into your existing procedure:
-- Step 1: Opening Balance DECLARE @OpeningBalance DECIMAL(18,2); SELECT @OpeningBalance = SUM(TransactionNetAmount) FROM AccountHierarchyNew WHERE Category = 'Cash-In-Hand' AND TransactionDate = DATEFROMPARTS(YEAR(GETDATE()), 4, 1); -- Step 2: Cash Movement DECLARE @CashMovement DECIMAL(18,2); SELECT @CashMovement = SUM(CASE WHEN TransactionType = 'Credit' THEN TransactionNetAmount ELSE 0 END) - SUM(CASE WHEN TransactionType = 'Debit' THEN TransactionNetAmount ELSE 0 END) FROM VoucherDetails WHERE Receipt_PaymentMode = 'Cash' AND (@FromDate IS NULL OR ReceiptDate >= @FromDate) AND (@ToDate IS NULL OR ReceiptDate <= @ToDate); -- Step 3: Cash Balance DECLARE @CashBalance DECIMAL(18,2); SET @CashBalance = ISNULL(@OpeningBalance, 0) + ISNULL(@CashMovement, 0); -- Step 4: Inject into Receipts INSERT INTO #BaseData (Section, Category, Account, Amount) VALUES ('Receipts', 'Cash', 'Opening Balance', @CashBalance);
๎ท๎ท๎ท๎ท
๐งพ Result
This will ensure that your Receipts section includes a row like:
Category
|
Account
|
Amount
|
Cash
|
Opening Balance
|
12345.67
|
Would you like to also show the closing balance for the month as a separate row under Payments or as a summary line?
A Final Version including Opening Balance as a Row On REceipt Side and Clsoing Balance on Payement Side
ALTER PROCEDURE [dbo].[GetCategoryAccountSummary]
@FromDate DATE = NULL,
@ToDate DATE = NULL
AS
BEGIN
-- Step 0: Normalize date range
IF @FromDate IS NULL SET @FromDate = DATEFROMPARTS(YEAR(GETDATE()), 4, 1);
IF @ToDate IS NULL SET @ToDate = EOMONTH(GETDATE());
-- Step 1: Get Opening Balance from AccountHierarchyNew
DECLARE @OpeningBalance DECIMAL(18,2);
SELECT @OpeningBalance = SUM(TransactionNetAmount)
FROM AccountHierarchyNew
WHERE Category = 'Cash-In-Hand'
AND TransactionDate = DATEFROMPARTS(YEAR(@FromDate), 4, 1);
-- Step 2: Calculate Net Cash Movement from VoucherDetails
DECLARE @CashMovement DECIMAL(18,2);
SELECT @CashMovement =
SUM(CASE WHEN TransactionType = 'Credit' THEN TransactionNetAmount ELSE 0 END) -
SUM(CASE WHEN TransactionType = 'Debit' THEN TransactionNetAmount ELSE 0 END)
FROM VoucherDetails
WHERE Receipt_PaymentMode = 'Cash'
AND ReceiptDate >= @FromDate
AND ReceiptDate <= @ToDate;
-- Step 3: Compute Cash Balance
DECLARE @CashBalance DECIMAL(18,2);
SET @CashBalance = ISNULL(@OpeningBalance, 0) + ISNULL(@CashMovement, 0);
-- Step 4: Prepare base data
CREATE TABLE #BaseData (
Section NVARCHAR(20),
Category NVARCHAR(100),
Account NVARCHAR(100),
Amount DECIMAL(18, 2)
);
-- Step 5: Insert actual voucher data
INSERT INTO #BaseData (Section, Category, Account, Amount)
SELECT
CASE
WHEN Prefix IN ('R', 'A') THEN 'Receipts'
WHEN Prefix = 'V' THEN 'Payments'
END AS Section,
Receipt_PaymentMode AS Category,
AccountType AS Account,
TransactionNetAmount AS Amount
FROM VoucherDetails
WHERE
Prefix IN ('R', 'A', 'V')
AND ReceiptDate >= @FromDate
AND ReceiptDate <= @ToDate;
-- Step 6: Inject synthetic opening balance row under Receipts
INSERT INTO #BaseData (Section, Category, Account, Amount)
VALUES ('Receipts', 'Cash', 'Opening Balance', @CashBalance);
-- Step 7: Inject synthetic closing balance row under Payments
INSERT INTO #BaseData (Section, Category, Account, Amount)
VALUES ('Payments', 'Cash', 'Closing Balance', @CashBalance);
-- Step 8: Prepare Receipts and Payments with row numbers
WITH ReceiptsCTE AS (
SELECT
ROW_NUMBER() OVER (ORDER BY Category, Account) AS RowNum,
Category AS ReceiptCategory,
Account AS ReceiptAccount,
SUM(Amount) AS Receipts
FROM #BaseData
WHERE Section = 'Receipts'
GROUP BY Category, Account
),
PaymentsCTE AS (
SELECT
ROW_NUMBER() OVER (ORDER BY Category, Account) AS RowNum,
Category AS PaymentCategory,
Account AS PaymentAccount,
SUM(Amount) AS Payments
FROM #BaseData
WHERE Section = 'Payments'
GROUP BY Category, Account
),
Combined AS (
SELECT
R.ReceiptCategory,
R.ReceiptAccount,
R.Receipts,
P.PaymentCategory,
P.PaymentAccount,
P.Payments
FROM ReceiptsCTE R
FULL OUTER JOIN PaymentsCTE P ON R.RowNum = P.RowNum
)
-- Step 9: Final output with grand total row
SELECT *
FROM (
SELECT
ReceiptCategory,
ReceiptAccount,
Receipts,
PaymentCategory,
PaymentAccount,
Payments,
0 AS SortOrder
FROM Combined
UNION ALL
SELECT
'TOTAL',
NULL,
SUM(Receipts),
'TOTAL',
NULL,
SUM(Payments),
1 AS SortOrder
FROM Combined
) AS FinalResult
ORDER BY SortOrder, ReceiptCategory, ReceiptAccount;
DROP TABLE #BaseData;
END;