Expense Tracker
This module provides a complete financial management system for Drupal, allowing users to record income and expense transactions through forms or file uploads. It offers interactive charts, tabular statements, and a filterable admin list for data exploration, along with a REST API for integrations. Transactions are stored as fieldable content entities, benefiting from Drupal's core features like multilingual support and Views integration.
Expense Income Tracker gives any Drupal 10 or 11 site a complete, self-contained financial management layer. Record every income and expense transaction through a clean admin form or by uploading a CSV, JSON, XML, or XLSX file — then explore the data through interactive Highcharts charts, tabular statements, and a fully filterable admin list, all without leaving the Drupal administration interface. Transactions are stored as a proper fieldable content entity (et_transaction), so they inherit the full Drupal feature set: multilingual content, URL aliases, comment threads, published/unpublished status, Views integration, and Pathauto support out of the box. A six-endpoint REST API means decoupled frontends and third-party accounting systems can read and write transactions with the same access-control rules that govern the UI. Whether you are managing a personal budget, a small-business cash-flow tracker, a corporate expense-reporting portal, or a multi-user financial intranet, Expense Income Tracker gives you the data model, the UI, and the API you need — with zero external PHP dependencies.
Features
Transactions & Data Model
- Dedicated content entity —
et_transactionis a fully fieldable entity with its own database tables, field UI, view modes, access-control handler, and list builder. Attach any Drupal field type to it exactly as you would to a node. - Income & expense classification — every transaction is typed as either income or expense; the type can be inherited automatically from a parent category transaction.
- Category hierarchy — create top-level "category" transactions (e.g. Monthly Rent, Salary) and attach child entries to them. Reports automatically group and total child transactions by category.
- Multilingual support — the entity is translatable; amounts, notes, and titles can be stored per language.
- Published / unpublished status — unpublished transactions are excluded from all reports, charts, and API responses.
- Comment threads — a dedicated
et_transaction_commentcomment type is installed automatically, giving every transaction a discussion thread powered by Drupal core's Comment module. - Free-text notes — an optional memo field stores vendor names, invoice references, project codes, or any other context alongside the monetary data.
Recurring Transactions
- Cron-driven repeat system — tick Repeat this transaction on the add/edit form and the module auto-generates copies on schedule without any manual work.
- Seven repeat frequencies — daily, weekly, monthly, yearly, working days (Mon–Fri), specific days of the week, and specific days of the month.
- Configurable end date — set a cut-off date after which no further copies are generated. Defaults to one month from today.
- Audit trail — every auto-generated copy records
created_type = automaticand stores aparent_transaction_idreference back to the source transaction.
Bulk Import
- Four supported file formats — CSV, JSON, XML, and XLSX are all accepted through the same upload form at Content → Import Transactions.
- Batch API processing — files are processed row-by-row through Drupal's Batch API, keeping memory usage flat and preventing PHP timeout errors even for thousands of rows.
- Duplicate detection — re-importing the same file is safe. If a matching parent-category title already exists, new rows are saved as children rather than creating a duplicate parent.
- Four bundled sample files — ready-to-use
.csv,.json,.xml, and.xlsxexamples are downloadable directly from the import page. - XLSX without extra libraries — Office Open XML workbooks are parsed by the bundled
ExcelReaderService; no additional PHP extensions or Composer packages are required. - Extensible column mapping — implement
hook_et_transaction_import_row_alter()to map any extra column in your file to a custom entity field. The hook fires for all four file formats and for the REST bulk-import endpoint.
Reports & Charts
- Interactive Highcharts charts — income-only, expense-only, and combined income-vs-expense charts rendered entirely in the browser. No server-side image generation required.
- Three report views — Income Reports, Expense Reports, and the side-by-side Income & Expense comparison, each available as a dedicated admin sub-tab under Reports → Income and Expense Reports.
- Flexible grouping — chart data can be grouped by day, week, month, quarter, or year.
- Eleven date-range presets — Last 7 days, Last 30 days, This/Last week, This/Last month, This/Last quarter, This/Last year, and All time. All report and statement pages share the same filter options.
- Category and author filters — drill down to a single user's transactions or a single category directly from the report form.
- Per-category data tables — below every chart, a breakdown table lists individual transactions and subtotals per category.
- Summary totals — every report page displays total income, total expenses, and net balance for the chosen period at a glance.
- Chart export — the bundled Highcharts Exporting plugin lets users save any chart as PNG, JPEG, PDF, or SVG with a single click.
- Flexible Highcharts delivery — choose between locally bundled files (no external requests, recommended for intranets), the jsDelivr CDN with an optional local fallback, or a fully custom URL.
Statements
- Tabular, print-friendly summaries — filter by date range and transaction type (All, Income, or Expense) to generate a clean statement backed by the admin transaction list at
/admin/expense-tracker/income-expense-statements. - Deep-link integration — the statements form redirects to the admin list pre-filtered to the chosen period; a "Go back to Statements" link is automatically injected above the list for easy navigation.
Currency Formatting
- Fully configurable currency display — set the symbol, position (prefix or suffix), decimal separator, and thousands separator once in settings. The formatting is applied consistently across entity pages, the admin list, Views, chart tooltips, and API responses.
- International currency support — configure Euro (
1.250,50€), British pounds (£1,250.50), Japanese yen (¥1,250), or any other currency by adjusting the four formatting options — no code changes required.
REST API
- Full CRUD —
POST /api/et-transactions,GET /api/et-transactions/{id},PATCH /api/et-transactions/{id}, andDELETE /api/et-transactions/{id}cover the complete create-read-update-delete lifecycle. - Paginated collection endpoint —
GET /api/et-transactionssupports filtering by type, date range, author, category, status, repeat flag, and a title LIKE search; sorting by any field; field selection; and pagination up to 500 items per page. Non-admin users automatically receive only their own transactions. - Bulk-import endpoint —
POST /api/et-transactions/importaccepts a JSON array of transactions with duplicate detection, optional update-on-match, and per-row error reporting. Ideal for CI pipelines, accounting software integrations, and mobile apps. - Structured response envelopes — collection responses include a
metaobject with total count, pagination info, and income/expense/net totals, alongside thedataarray and HAL-stylelinks. - Multiple authentication methods — session-based CSRF tokens, HTTP Basic Auth, OAuth 2.0 (
simple_oauth), and JWT are all supported. - Entity access respected everywhere — every REST endpoint enforces the same permissions as the admin UI. There are no bypass routes.
Views Integration
- Ships with a pre-configured
expense_tracker_adminview powering the admin transaction list, complete with currency-formatted amounts, exposed filters for title, author, date range, and transaction type, and a bulk-delete action via Views Bulk Operations. - Non-admin users automatically see only their own transactions in every view — enforced at the query level in
hook_views_query_alter. - Create additional custom views from Structure → Views using the
et_transactionentity type exactly as you would with nodes.
Pathauto & Token Support
- Five tokens —
[et_transaction:id],[et_transaction:title],[et_transaction:type],[et_transaction:date], and[et_transaction:author]are registered with Drupal's Token system and support sub-token chaining (e.g.[et_transaction:author:name],[et_transaction:date:short]). - Pathauto-ready — when the
pathautomodule is installed, URL aliases are generated automatically using any token pattern, such as/transactions/[et_transaction:type]/[et_transaction:title].
Sample & Demo Data
- 60 realistic demo transactions spanning January 2025 through June 2026 across 15 income and expense categories (Salary, Freelance, Consulting, Rent, Groceries, Utilities, Transport, Travel, Healthcare, Education, Clothing, Entertainment, Rental Income, Dividends, Bonuses), importable from the Settings page with a single click.
- Duplicate-safe import — re-importing skips existing entries by default. A one-click Remove All Sample Data button cleans up when you are done exploring.
Developer Experience
- Five hooks —
hook_et_transaction_api_normalize_alter,hook_et_transaction_api_create_alter,hook_et_transaction_api_update_alter,hook_et_transaction_collection_query_alter,hook_et_transaction_import_row_alter. - Injectable services —
expense_tracker.excel_reader(ExcelReaderService) andexpense_tracker.post_render_cacheare registered in the service container and available for injection in any custom code. - Dedicated logger channel — all module events are grouped under
expense_trackerin Reports → Recent log messages, making filtering straightforward. - Status report integration —
hook_requirements()surfaces a warning on the Drupal Status Report page if the locally bundled Highcharts files are missing at runtime. - PHP 8.1+ typed properties and
declare(strict_types=1)throughout. PHP 8 attributes (#[RestResource]) are used in place of annotation docblocks. - PSR-4 autoloading under the clean
Drupal\expense_trackernamespace. - Zero third-party PHP dependencies — no Composer packages beyond Drupal core are required. XLSX parsing is handled by a bundled, self-contained service class.
- Idempotent update hooks — all database and config update hooks are fully guarded so they can be re-run safely on existing installations without side effects.
Post-Installation
After enabling the module and its dependencies, follow these steps to start tracking transactions:
-
Install via Composer.
Runcomposer require drupal/expense_tracker drupal/views_bulk_operations, then enable withdrush en expense_tracker -y && drush cr. Alternatively, navigate to Administration → Extend, search for Expense Income Tracker, tick the checkbox, click Install, and clear caches. -
Set permissions.
Go to People → Permissions (/admin/people/permissions) and assign the following to the appropriate roles:access expense_tracker— view own transactions.access all expense_tracker— view all users' transactions.create expense_tracker— add new transactions.edit expense_tracker/edit all expense_tracker— edit own or all transactions.delete expense_tracker/delete all expense_tracker— delete own or all transactions.reports expense_tracker— view charts and statements.import expense_tracker— access the file-upload form and the bulk-import REST endpoint.config expense_tracker— access the Settings form.administer et_transactions— full admin access including Field UI, comment settings, and all module settings. Restrict to trusted roles only.
-
Adjust global settings.
Go to Configuration → Content authoring → Transaction settings (/admin/config/content/et-transaction). Key options include:- Highcharts library source — Local (bundled), CDN (jsDelivr with optional fallback), or a Custom URL.
- Currency symbol, position (prefix/suffix), decimal separator, and thousands separator.
-
Add your first transaction.
Go to Content → Expense Transactions → Add Transaction (/admin/income-expense-transactions/add). Enter a title, amount, date, and select Income or Expense. For recurring bills or income, enable the Repeat option, choose a frequency and an end date — Drupal cron will generate future copies automatically. -
Import existing data.
Go to Content → Import Transactions (/admin/expense-tracker/import/transactions). Download a bundled sample file to see the exact required format, then upload your own CSV, JSON, XML, or XLSX file. The four required columns aretitle,amount,date, andtype(case-sensitive). The Batch API processor handles large files without timeouts and reports a row count on completion. -
Explore reports and charts.
Go to Reports → Income and Expense Reports (/admin/expense-tracker-reports). Use the sub-tabs to switch between the Income, Expense, and combined Income & Expense views. Apply date range, category, and author filters to narrow the data. Use the export button to download any chart as PNG, JPEG, PDF, or SVG. -
Load demo data (optional).
Go to Configuration → Content authoring → Transaction settings → Sample Data and click Import Sample Data. This loads 60 realistic transactions across 15 categories spanning January 2025 – June 2026, ideal for exploring charts and statements before entering real data. Remove them at any time with Remove All Sample Data. -
Enable the REST API (optional).
Go to Configuration → Web services → REST (/admin/config/services/rest) and enable the three ET Transaction resources. For write operations, pass the CSRF token fromGET /session/tokenin theX-CSRF-Tokenrequest header. See the REST permissions at People → Permissions for the full list of required role assignments.
For headless or decoupled frontends, use GET /api/et-transactions?_format=json to list and filter transactions, POST /api/et-transactions?_format=json to create them, and POST /api/et-transactions/import?_format=json for bulk operations. All endpoints return JSON envelopes with data, meta, and links keys.
Upgrading
Always take a full database backup before upgrading any Drupal module. The procedure below applies whether you are moving up a single patch release or jumping across multiple minor versions.
Standard upgrade procedure
-
Back up your database.
drush sql-dump --result-file=backup-before-upgrade.sql
Store the dump outside the web root before proceeding. If something goes wrong you can restore withdrush sql-cli < backup-before-upgrade.sql. -
Update the module with Composer.
composer update drupal/expense_tracker --with-all-dependencies
Composer updates the module files and resolves any dependency version changes automatically. If you also need to updateviews_bulk_operations, include it in the same command:
composer update drupal/expense_tracker drupal/views_bulk_operations --with-all-dependencies -
Run database updates.
Via Drush (recommended):
drush updb -y
Or via the browser by navigating to/update.phpand following the on-screen steps. The module's update hooks are fully idempotent — each step checks for existing data before making any change, so runningdrush updbmore than once on an already-updated site is completely safe. -
Clear all caches.
drush cr
Or navigate to Administration → Performance → Clear all caches. This step is required even ifdrush updbreports "No pending updates." -
Import new configuration (if the release notes require it).
Most minor and patch releases do not ship configuration changes. When they do, the release notes will say so explicitly. To import:
drush config-import -y
Review the diff first withdrush config-diffif you have site-specific config customisations you need to preserve. -
Verify the Status Report.
Go to Administration → Reports → Status report (/admin/reports/status). Resolve any warnings listed under the Expense Tracker heading — the most common post-upgrade warning is a missing bundled Highcharts file when switching from CDN to Local source.
What update hooks do
Each numbered update hook is documented in expense_tracker.install. In general, updates may:
- Add new configuration keys to
expense_tracker.settingswith safe default values — existing values are never overwritten. - Create or modify database columns on the
et_transactionandet_transaction_field_datatables. - Install new comment types, entity view displays, or entity form displays required by new features.
- Fix ordering or weight issues in field displays introduced by earlier installs.
Because all hooks are idempotent and guarded with existence checks, re-running drush updb after a failed or partial update is always safe — completed steps are skipped automatically.
Upgrading Drupal core (10 → 11)
Expense Income Tracker supports Drupal 10 and 11 from the same codebase. When upgrading Drupal core itself, follow the official Drupal core upgrade guide, then run drush updb -y && drush cr as above. No special data-migration steps are required for this module's entity data — all et_transaction records remain intact through a core upgrade.
Rolling back a failed upgrade
If an upgrade causes unexpected breakage, restore your backup and redeploy the previous module version:
- Restore the database:
drush sql-cli < backup-before-upgrade.sql - Revert to the previous release via Composer:
composer require drupal/expense_tracker:^<previous-version> --update-with-all-dependencies - Clear caches:
drush cr
All transaction data stored in the database will be intact after the restore.
Additional Requirements
- Drupal 10.1 or 11.x
- PHP 8.1 or higher (PHP 8.3+ required for Drupal 11)
- Drupal core modules: Views, Comment, Path, REST, Serialization, Basic Auth (all included in Drupal core)
- Contributed module: Views Bulk Operations — required for bulk-delete on the admin transaction list
No third-party PHP libraries, JavaScript frameworks, or external services are required. The module is entirely self-contained.
Recommended Modules
-
Pathauto —
Automatically generates clean URL aliases for every transaction using the bundled[et_transaction:*]token group. A pattern such as/transactions/[et_transaction:type]/[et_transaction:title]produces SEO-friendly paths like/transactions/expense/monthly-rentwith no manual input. -
Token —
Provides the Token browser UI for Pathauto's pattern editor so editors can discover all available[et_transaction:*]tokens interactively without reading documentation. -
Simple OAuth —
Recommended for decoupled or mobile frontends that authenticate REST API requests via OAuth 2.0 access tokens rather than session cookies or HTTP Basic Auth. -
Metatag —
Adds SEO meta tags to canonical transaction pages (/et-transaction/{id}), useful if individual transactions are publicly accessible on a community or e-commerce site. -
Ultimate Cron —
For fine-grained control over how often the recurring-transaction cron job runs. Lets you schedule theexpense_trackerhook independently of other modules without editing the system crontab. -
JSON:API —
Recommended alongside the built-in REST API for fully decoupled React, Vue, or Angular frontends. Use JSON:API to query related Drupal entities and the Expense Tracker REST API for transaction-specific operations such as bulk imports and filtered collection responses with income/expense totals.
Similar Projects
-
Drupal Commerce —
Commerce is a full e-commerce platform covering products, carts, orders, and payments. Expense Income Tracker focuses specifically on recording and reporting financial transactions in a lightweight, fieldable entity model — without a storefront, checkout flow, or payment gateway. It is well-suited for internal accounting and cash-flow tracking where Commerce would be significant overkill. -
Bookkeeping —
Bookkeeping implements double-entry accounting with debit/credit ledgers. Expense Income Tracker uses a simpler income/expense model that is faster to set up and easier for non-accountants, while providing features Bookkeeping does not: interactive Highcharts reports, multi-format bulk import, a full REST API, recurring transactions, and Pathauto/token integration. -
Budget —
Budget provides basic budget-tracking fields on nodes. Expense Income Tracker provides a dedicated, fully fieldable entity type with its own access control, Views integration, REST API, and reporting layer — giving significantly more flexibility for custom field additions, integrations, and display modes. -
Voting API —
VotingAPI is a developer-focused framework for recording votes and computing results, with no frontend UI or analytics dashboard of its own. Expense Income Tracker delivers a complete, production-ready end-to-end solution — storage, admin UI, interactive charts, statements, REST API, and admin tools — with no additional modules required.
Troubleshooting
Charts are blank or Highcharts is not loading
- Go to Administration → Reports → Status report (
/admin/reports/status) and look for an Expense Tracker – Highcharts warning. It will tell you exactly which file is missing. - If using the Local source, confirm that
js/highcharts.src.jsandjs/exporting.jsexist inside the module directory. If they are missing, either re-download the full module package or switch the Highcharts source to CDN in settings. - If using the CDN source, open your browser's developer console (F12 → Network tab) and look for blocked requests to
cdn.jsdelivr.net. A Content Security Policy (CSP) header or browser extension may be blocking the request. Enable the CDN fallback option in settings so local files are served if the CDN is unreachable, then clear caches. - If using a Custom URL, confirm the URL is publicly reachable from the browser, uses HTTPS, and points directly to the
highcharts.jsfile — not a directory listing or a redirect. - Always clear caches after changing the Highcharts source setting:
drush cr. The library attachment is cached in Drupal's asset system and will not update until caches are cleared.
Recurring transactions are not being created
- Confirm cron is running. Go to Administration → Reports → Recent log messages and filter by type
cron. If no recent entries appear, configure cron at Administration → Configuration → System → Cron or add a system crontab entry:0 * * * * /usr/bin/drush -r /path/to/drupal cron --quiet - On the source transaction's edit page, verify that Repeat is checked, the Repeat end date is in the future, and the chosen frequency matches today (e.g. for Specific days of the week, confirm today's weekday is selected).
- Inspect the
last_transaction_timefield value on the source transaction. If it holds a future timestamp — which can happen after a timezone change or a manual edit — no new copy will be generated until that time passes. - Confirm the source transaction is published. The cron repeat system skips unpublished transactions.
- Run cron manually to test:
drush cron. Check Recent log messages immediately afterwards and filter byexpense_trackerto see any errors.
Import fails with "Enter a valid file" or a missing-column error
- Confirm the file contains all four required header names:
title,amount,date,type. Headers are case-sensitive and must not contain leading or trailing spaces. - For CSV files, use UTF-8 encoding without a BOM (Byte Order Mark). Files exported from Microsoft Excel may include a BOM — choose Save as → CSV UTF-8 (Comma delimited) in Excel, or open the file in a text editor and remove the BOM manually.
- Ensure the
typecolumn contains exactlyincomeorexpense(all lowercase). Any other value — includingIncomeorEXPENSE— will cause that row to be skipped or rejected. - For XML files, the root element must be
<transactions>and each row must be wrapped in an<element>tag. Download the bundledet_transaction.xmlsample from the import page and use it as a structural reference. - For XLSX files, confirm the first worksheet row contains the column headers, the file is not password-protected, and the workbook opens cleanly in Excel or LibreOffice before uploading.
- If the file type itself is rejected before validation begins, Drupal's file-field extension whitelist may be blocking it. Check that the extension is among the allowed types configured on the import form's file field.
REST API returns 403 Forbidden
- Confirm each of the three ET Transaction REST resources is individually enabled at Configuration → Web services → REST (
/admin/config/services/rest). Enabling one does not enable the others. - The authenticated user needs both the REST permission (e.g.
restful post et_transaction) and the corresponding entity permission (e.g.create expense_tracker). Neither alone is sufficient — check both at People → Permissions. - All write requests (
POST,PATCH,DELETE) require a valid CSRF token in theX-CSRF-Tokenheader. Fetch a fresh token fromGET /session/tokenbefore each write session. - When using Basic Auth, confirm the
drupal:basic_authmodule is enabled and the credentials are correctly base64-encoded in theAuthorization: Basic <base64(user:pass)>header. - Every request must include
?_format=json. Omitting it causes Drupal to return a 406 Not Acceptable or an HTML redirect instead of a JSON response. - For anonymous REST access, the relevant REST permissions must be assigned to the Anonymous user role — not only to Authenticated user.
Amounts are not currency-formatted in the transaction list
- Clear all caches (
drush cr). The currency formatter output is cached; a settings change does not take effect until caches are rebuilt. - Open the view at Structure → Views → expense_tracker_admin → Edit and confirm the Amount field has not been replaced or customised to use a plain field formatter. It should use the entity reference to
et_transactionwith the module's built-in currency formatter. - Verify the currency symbol and separators are correct at Configuration → Content authoring → Transaction settings → Currency Display.
drush updb or update.php reports errors
- Read the full error output — it will name the failing hook (e.g.
expense_tracker_update_9005). Search the issue queue for that hook name to find known fixes or patches. - All update hooks are idempotent. Fix the root cause of the failure, then re-run
drush updb -y— steps that already completed will be skipped automatically. - If a hook fails with "Config object already exists", the configuration was likely imported manually before the update ran. You can mark the hook as done and re-run:
drush php-eval "drupal_set_installed_schema_version('expense_tracker', 9005);"(replace9005with the actual failing hook number), thendrush updb -y. - Check Administration → Reports → Recent log messages filtered by the
expense_trackerchannel for the full PHP stack trace.
Comment form does not appear on transaction pages
- Confirm the
drupal:commentcore module is enabled at Administration → Extend. - Go to Administration → Structure → Comment types and verify that
et_transaction_commentis listed. If it is absent, rundrush updb -y && drush crto trigger the update hook that creates it. - On the Manage Display page for
et_transaction(Full content view mode), confirm the Comments field is enabled and not hidden.
Settings page returns 403 (Access denied)
- The settings page at
/admin/config/content/et-transactionrequires theconfig expense_trackerpermission. Grant it to the appropriate role at People → Permissions.
Module cannot be uninstalled
- Drupal will block uninstallation if any
et_transactionentities still exist in the database. Delete all transactions first — use the bulk-delete checkbox on the admin list, or run:
drush php-eval "\Drupal::entityTypeManager()->getStorage('et_transaction')->delete(\Drupal::entityTypeManager()->getStorage('et_transaction')->loadMultiple());" - Also confirm that no other enabled module lists
expense_trackeras a dependency in its.info.ymlfile. - After deleting all data and resolving dependencies, uninstall with:
drush pm-uninstall expense_tracker -y && drush cr
Translations or multilingual content is missing after an upgrade
- Run
drush locale-updateto refresh translation strings if a new release ships updated translatable strings. - If entity translations are missing, ensure the
drupal:content_translationmodule is enabled and theet_transactionentity type has content translation enabled at Configuration → Regional and language → Content language and translation.
Supporting This Module
If Expense Income Tracker saves you time on your project, the best ways to support continued development are:
- Report bugs and suggest features in the project issue queue.
- Contribute patches, automated tests, or documentation improvements via the issue queue.
- Post a review on the project page — community ratings help other Drupal developers discover the module.
- Help test release candidates against Drupal 10 and 11 minor updates and report any regressions.
When reporting an issue, please include your Drupal core version, PHP version, the exact steps to reproduce the problem, and any relevant output from Reports → Recent log messages filtered by the expense_tracker channel.
Community Documentation
- Full installation, configuration, permissions, REST API, hook, and Pathauto documentation is available in the
README.mdfile included with the module. - All five developer hooks are documented with complete, runnable code examples in
expense_tracker.api.phpinside the module directory. - Example integrations demonstrating custom column mapping during CSV/REST bulk imports, extra entity-query conditions, and custom REST response fields can be found directly in
expense_tracker.api.php. - Video walkthroughs and step-by-step tutorials for common use cases (multi-user expense reporting, headless Drupal integrations, recurring payroll entries) are welcome contributions — please link them in the issue queue.
Use Cases
Expense Income Tracker is well suited for:
- Personal finance dashboards — track income and spending categories month by month with interactive charts, all self-hosted on your own Drupal site.
- Small-business cash-flow tracking — record invoices, wages, rent, and utilities; filter reports by category and date range; export charts as PDF for accountants or stakeholders.
- Corporate expense-reporting portals — per-user access control lets employees log and review only their own transactions while finance managers access the full dataset with a single permission toggle.
- Non-profit grant and project accounting — organise income and expenditure by project using the category hierarchy, then generate per-project statements for grant reporting.
- Recurring payroll and subscription management — enter a salary or subscription once, enable monthly or yearly repeat, and let cron maintain the ledger automatically — no manual entries each cycle.
- Decoupled / headless Drupal applications — consume the REST API from a React, Vue, or Angular frontend. Use the collection endpoint's built-in filters, field selection, sorting, and pagination to build custom dashboards without any server-side Drupal rendering.
- Accounting software integrations — pull CSV exports from QuickBooks, Xero, or any CSV-exporting tool and push them into Drupal via the bulk-import REST endpoint or the file-upload form, with duplicate detection keeping re-runs safe.
- Learning management systems — track student fees, course revenue, and operational costs in a Drupal-based LMS; use per-role access to give finance staff a clean reporting layer separate from course content.