Monthly breakdown of Receipts and Payments


SqlServer, SqlServer Useful functions

Introduction


    • Monthly breakdown of Receipts and Payments
    • ๐Ÿ’ฐ Running cash balance per month
    • ๐Ÿงพ Opening balance carried forward from April 1st

    This will give you a ledger-style view of cash flow across months, which is perfect for financial tracking.

     

    โœ… What We'll Build

     

    Month

    Receipts

    Payments

    Net Flow

    Running Balance

    Apr 2025

    15000.00

    8000.00

    7000.00

    48000.00

    May 2025

    12000.00

    5000.00

    7000.00

    55000.00

    ...

    ...

    ...

    ...

    ...

     

    ๐Ÿง  Strategy

    1. Get the opening balance from AccountHierarchyNew (as before).
    2. Aggregate monthly Receipts and Payments from VoucherDetails where Receipt_PaymentMode = 'Cash'.
    3. Calculate Net Flow = Receipts - Payments.
    4. Use SUM(...) OVER (ORDER BY Month) to compute the running balance.
    5. Prepend the opening balance as the first row.

     

    โœ… Final Monthly Cash Flow Procedure

     

    ALTER PROCEDURE [dbo].[GetMonthlyCashFlowSummary] @FromDate DATE = NULL, @ToDate DATE = NULL AS BEGIN -- 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: Monthly Receipts and Payments from VoucherDetails ;WITH MonthlyData AS ( SELECT FORMAT(ReceiptDate, 'yyyy-MM') AS Month, SUM(CASE WHEN TransactionType = 'Credit' THEN TransactionNetAmount ELSE 0 END) AS Receipts, SUM(CASE WHEN TransactionType = 'Debit' THEN TransactionNetAmount ELSE 0 END) AS Payments FROM VoucherDetails WHERE Receipt_PaymentMode = 'Cash' AND ReceiptDate >= @FromDate AND ReceiptDate <= @ToDate GROUP BY FORMAT(ReceiptDate, 'yyyy-MM') ), WithNetFlow AS ( SELECT Month, Receipts, Payments, (Receipts - Payments) AS NetFlow FROM MonthlyData ), WithRunningBalance AS ( SELECT Month, Receipts, Payments, NetFlow, SUM(NetFlow) OVER (ORDER BY Month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + ISNULL(@OpeningBalance, 0) AS RunningBalance FROM WithNetFlow ) -- Step 3: Final output with opening balance row SELECT 'Opening Balance' AS Month, NULL AS Receipts, NULL AS Payments, NULL AS NetFlow, @OpeningBalance AS RunningBalance UNION ALL SELECT Month, Receipts, Payments, NetFlow, RunningBalance FROM WithRunningBalance ORDER BY CASE WHEN Month = 'Opening Balance' THEN 0 ELSE 1 END, Month; END;

    ๎ท›๎ทœ๎ท™๎ทš

     

     

    ๐Ÿงพ Output Example

     

    Month

    Receipts

    Payments

    NetFlow

    RunningBalance

    Opening Balance

    NULL

    NULL

    NULL

    41000.00

    2025-04

    15000.00

    8000.00

    7000.00

    48000.00

    2025-05

    12000.00

    5000.00

    7000.00

    55000.00

    ...

    ...

    ...

    ...

    ...

     

     

Description


create PROCEDURE [dbo].[GetMonthlyCashFlowSummary]
    @FromDate DATE = NULL,
    @ToDate DATE = NULL
AS
BEGIN
    -- 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(TransactionAmount)
    FROM AccountHierarchyNew
    WHERE AccountType = 'Cash-In-Hand'
      AND TransactionDate = DATEFROMPARTS(YEAR(@FromDate), 4, 1);
 
    -- Step 2: Monthly Receipts and Payments from VoucherDetails
    ;WITH MonthlyData AS (
        SELECT 
            FORMAT(ReceiptDate, 'yyyy-MM') AS MonthKey,
            MIN(DATEFROMPARTS(YEAR(ReceiptDate), MONTH(ReceiptDate), 1)) AS MonthStart,
            SUM(CASE WHEN TransactionType = 'Credit' THEN TransactionNetAmount ELSE 0 END) AS Receipts,
            SUM(CASE WHEN TransactionType = 'Debit' THEN TransactionNetAmount ELSE 0 END) AS Payments
        FROM VoucherDetails
        WHERE Receipt_PaymentMode = 'Cash'
          AND ReceiptDate >= @FromDate
          AND ReceiptDate <= @ToDate
        GROUP BY FORMAT(ReceiptDate, 'yyyy-MM')
    ),
    WithNetFlow AS (
        SELECT 
            MonthKey,
            MonthStart,
            Receipts,
            Payments,
            (Receipts - Payments) AS NetFlow
        FROM MonthlyData
    ),
    WithRunningBalance AS (
        SELECT 
            MonthKey,
            MonthStart,
            Receipts,
            Payments,
            NetFlow,
            SUM(NetFlow) OVER (ORDER BY MonthStart ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + ISNULL(@OpeningBalance, 0) AS RunningBalance
        FROM WithNetFlow
    )
 
    -- Step 3: Final output with opening balance row
    SELECT *
    FROM (
        SELECT 
            'Opening Balance' AS MonthLabel,
            NULL AS Receipts,
            NULL AS Payments,
            NULL AS NetFlow,
            @OpeningBalance AS RunningBalance,
            0 AS SortOrder,
            CAST(NULL AS DATE) AS MonthStart
        UNION ALL
        SELECT 
            MonthKey,
            Receipts,
            Payments,
            NetFlow,
            RunningBalance,
            1 AS SortOrder,
            MonthStart
        FROM WithRunningBalance
    ) AS Final
    ORDER BY SortOrder, MonthStart;
END;