Church Cashbook Data Schema Manual
Annual budget lines per church/FY/category for variance reporting.
DDL source: uploaded
budgets.sql.Purpose
The budgets table stores annual budget amounts used for variance reporting (Budget vs Actual) by church and financial year.
How it relates to the system
- Budgets are compared against actual totals derived from
transactions(excluding voided items). - Budgets are typically entered/edited by authorised Treasurers only (governance rule).
Columns
- id —
intUNSIGNED NOT NULL - church_id —
intUNSIGNED NOT NULL - fy_start_year —
intNOT NULL - church_category_id —
intUNSIGNED NOT NULL - amount —
decimal(12,2) NOT NULL DEFAULT '0.00' - created_by_user_id —
intUNSIGNED DEFAULT NULL - created_at —
datetimeNOT NULL DEFAULT CURRENT_TIMESTAMP - updated_by_user_id —
intUNSIGNED DEFAULT NULL - updated_at —
datetimeNOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Indexes
- PRIMARY KEY `id`
- idx_budget_church_fy (`church_id`,`fy_start_year`)
- idx_budget_cat (`church_category_id`)
- idx_budget_created_by (`created_by_user_id`)
- idx_budget_updated_by (`updated_by_user_id`)
Constraints
- fk_budgets_church:
church_id→churches.idON DELETE RESTRICT ON UPDATE CASCADE, ADD CONSTRAINT `fk_budgets_church_category` FOREIGN KEY (`church_category_id`) REFERENCES `church_categories` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE, ADD CONSTRAINT `fk_budgets_created_by_user` FOREIGN KEY (`created_by_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, ADD CONSTRAINT `fk_budgets_updated_by_user` FOREIGN KEY (`updated_by_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE - chk_budgets_cat_xor — CHECK constraint:
cat_category_idandcat_heading_idare mutually exclusive; at most one may be non-NULL on any row. Enforced at DB level (MySQL 8.0.16+ / MariaDB 10.2.1+); the application also enforces this invariant in the budgets save path. Added: migration SCH-02.
Operational notes
- Invariant: budgets are annual and category-level; they do not affect balances.
- Governance: edits should be logged (activity + audit where appropriate).
- Data quality: keep category wording stable over time to preserve comparability.
DDL
-- phpMyAdmin SQL Dump
-- version 5.2.1
-- https://www.phpmyadmin.net/
--
-- Host: localhost:8889
-- Generation Time: Feb 24, 2026 at 08:00 PM
-- Server version: 8.0.40
-- PHP Version: 8.3.14
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `church_accounts`
--
-- --------------------------------------------------------
--
-- Table structure for table `budgets`
--
CREATE TABLE `budgets` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`church_id` int UNSIGNED NOT NULL,
`fy_start_year` int NOT NULL,
`cat_category_id` int UNSIGNED DEFAULT NULL,
`cat_heading_id` int UNSIGNED DEFAULT NULL,
`church_category_id` int UNSIGNED NOT NULL,
`amount` decimal(12,2) NOT NULL DEFAULT '0.00',
`created_by_user_id` int UNSIGNED DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_by_user_id` int UNSIGNED DEFAULT NULL,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `chk_budgets_cat_xor` CHECK (
`cat_category_id` IS NULL OR `cat_heading_id` IS NULL
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `budgets`
--
ALTER TABLE `budgets`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `uq_budget_church_fy_cat` (`church_id`,`fy_start_year`,`church_category_id`),
ADD KEY `idx_budget_church_fy` (`church_id`,`fy_start_year`),
ADD KEY `idx_budget_cat` (`church_category_id`),
ADD KEY `idx_budget_created_by` (`created_by_user_id`),
ADD KEY `idx_budget_updated_by` (`updated_by_user_id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `budgets`
--
ALTER TABLE `budgets`
MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `budgets`
--
ALTER TABLE `budgets`
ADD CONSTRAINT `chk_budgets_cat_xor` CHECK (`cat_category_id` IS NULL OR `cat_heading_id` IS NULL),
ADD CONSTRAINT `fk_budgets_church` FOREIGN KEY (`church_id`) REFERENCES `churches` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE,
ADD CONSTRAINT `fk_budgets_church_category` FOREIGN KEY (`church_category_id`) REFERENCES `church_categories` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE,
ADD CONSTRAINT `fk_budgets_created_by_user` FOREIGN KEY (`created_by_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
ADD CONSTRAINT `fk_budgets_updated_by_user` FOREIGN KEY (`updated_by_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;