Church Cashbook
Data Schema Manual
Manual home Return to Church Cashbook

Church Cashbook Data Schema Manual

Double-entry transaction record (worked example).

Purpose

Stores each financial entry as a double-entry transaction (debit + credit accounts). The UI can present this as simple “Money in / Money out”, but the database stores proper accounting structure.

Columns

Indexes

Constraints

Do-not-break invariants

CREATE TABLE `transactions` (
  `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
  `church_id` int UNSIGNED NOT NULL,
  `tx_date` date NOT NULL,
  `description` varchar(255) NOT NULL,
  `amount` decimal(12,2) NOT NULL,
  `debit_account_id` int UNSIGNED NOT NULL,
  `credit_account_id` int UNSIGNED NOT NULL,
  `cat_category_id` int UNSIGNED DEFAULT NULL,
  `cat_heading_id` int UNSIGNED DEFAULT NULL,
  `church_category_id` int UNSIGNED DEFAULT NULL,
  `fund_type` varchar(20) NOT NULL DEFAULT 'unrestricted',
  `receipt_path` varchar(255) DEFAULT NULL,
  `is_voided` tinyint(1) NOT NULL DEFAULT '0',
  `void_reason` varchar(255) DEFAULT NULL,
  `voided_at` datetime DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `created_by_user_id` int UNSIGNED DEFAULT NULL,
  `is_cleared` tinyint(1) NOT NULL DEFAULT '0',
  `cleared_date` date DEFAULT NULL,
  CONSTRAINT `chk_tx_cat_xor` CHECK (
    `cat_category_id` IS NULL OR `cat_heading_id` IS NULL
  )
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

ALTER TABLE `transactions`
  ADD PRIMARY KEY (`id`),
  ADD KEY `idx_tx_church_date` (`church_id`,`tx_date`),
  ADD KEY `idx_tx_category` (`church_category_id`),
  ADD KEY `fk_tx_debit` (`debit_account_id`),
  ADD KEY `fk_tx_credit` (`credit_account_id`);

ALTER TABLE `transactions`
  ADD CONSTRAINT `chk_tx_cat_xor` CHECK (`cat_category_id` IS NULL OR `cat_heading_id` IS NULL),
  ADD CONSTRAINT `fk_tx_category` FOREIGN KEY (`church_category_id`) REFERENCES `church_categories` (`id`),
  ADD CONSTRAINT `fk_tx_church` FOREIGN KEY (`church_id`) REFERENCES `churches` (`id`) ON DELETE CASCADE,
  ADD CONSTRAINT `fk_tx_credit` FOREIGN KEY (`credit_account_id`) REFERENCES `accounts` (`id`),
  ADD CONSTRAINT `fk_tx_debit` FOREIGN KEY (`debit_account_id`) REFERENCES `accounts` (`id`);