Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Eloquent Ifrs Laravel Package

ekmungai/eloquent-ifrs

Eloquent IFRS adds double-entry accounting to Laravel, generating IFRS-compliant financial statements. Supports multiple entities, account categorization, VAT, opening balances, forex revaluation, tamper-protected ledgers, and configurable receivables aging.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

ekmungai/eloquent-ifrs is not a reporting library bolted onto existing models — it is a full double-entry general ledger implemented as Eloquent models inside your application's database. Adopting it means accepting its schema, its write path, and its domain model as the accounting source of truth for the entities it covers. That is an architectural commitment, not a dependency.

The domain model is credibly designed for the stated scope:

  • Entity → ReportingPeriod → Account → Vat → Transaction → LineItem → Assignment covers the core ledger, VAT control accounts, and receivable/payable clearing.
  • Posting is an explicit two-phase write (create() does not hit the ledger; addLineItem() and post() do). This is the correct pattern for a ledger and gives you a natural place to hook validation, authorisation, and audit events.
  • Ledger integrity is enforced at the model layer ("protected against tampering via direct database changes"), with a Recycling trait and destroyed_at columns indicating soft-delete-by-design rather than hard deletes. Good for auditability; see failure modes below.
  • Reporting is materialised in PHP (new IncomeStatement($from, $to)->getSections()), with toString() explicitly documented as debug-only. There is no JSON/API contract — you own the entire presentation and export layer, including any XBRL/iXBRL work.
  • Multi-entity is modelled (Entity, entity_id), but the ifrs.user_model configuration and the entity_id column added to your users table imply a user belongs to one entity default. True multi-tenant isolation (one user, many entities, per-entity roles) will require work on your side.

Integration feasibility

Feasible, but the install path has two sharp edges that are easy to underestimate in estimation:

  1. The package mutates your users table. It adds entity_id and destroyed_at, requires your users migration to be dated before 2014_10_12_000000, and requires your User model to implement Recyclable and use IFRSUser and Recycling traits. The README's own "DB Collision" section acknowledges this. If your users table has a non-standard PK, a UUID, or a custom User namespace, budget real time here.
  2. Laravel 11+ only, PHP 8.2+ only. This is a hard floor with no LTS-9/10 support path. If your application is on Laravel 9 or 10, this package is not adoptable without an application upgrade, which is almost certainly a larger project than the accounting integration itself.

Everything else — composer require, vendor:publish, php artisan migrate, seeding a chart of accounts — is routine. The README's worked example (cash sale, client invoice, cash purchase, supplier bill, client receipt, then Assignment to clear the invoice) is enough to get a spike running in under a day.

Technical risk

Risk Severity Notes
Single-maintainer package, 0 dependents High 367 stars but no downstream packages on Packagist means no ecosystem validation. You are likely the largest consumer.
Tight coupling to Laravel majors High Laravel 11/12/13 support is a moving target; every application major upgrade becomes a ledger upgrade.
Docs contain errors Medium The CashPurchase example is booked against $clientAccount rather than the bank account, and the illustrated Balance Sheet figures do not fully reconcile against the transaction values in the same example (bank shown as 50 against an implied 60). Treat the README as illustrative, not as specification.
Reporting scope ≠ IFRS compliance Medium This is a general ledger with an IFRS-shaped chart of accounts. It does not implement IFRS 15 revenue recognition, IFRS 16 leases, IFRS 9 ECL provisioning, or IFRS 13 fair value. "IFRS compliant reporting" is marketing-adjacent.
Tax engine depth Medium A single Vat model with rate and account_id plus one input/output code. Multi-jurisdiction VAT, OSS, reverse charge, and US sales tax are out of scope.
CI/CD signalling Low Travis CI badges and CodeClimate badges indicate older infrastructure conventions; verify the test suite actually runs green on your target PHP/Laravel matrix before committing.

Key questions to answer before committing

  1. Does post() run inside a single database transaction with row-level locking? What is the state of a Transaction and its LineItems if post() throws midway?
  2. Is "tamper protection" application-level only (model events/observers), or does it survive a direct SQL UPDATE? An auditor will ask both "can it be changed" and "can it be changed legitimately, e.g. for a correction entry."
  3. What is the documented correction model — reversal entries, or Recycling soft-delete? Which one does the package's ledger reconciliation assume?
  4. How does a user relate to more than one Entity? Is there a role/authorisation story at all, or is access control entirely on the host application?
  5. What is the post()-time validation surface — unbalanced entries, closed periods, FX rates missing, VAT account missing?
  6. What is the maintainer's stated support horizon and release cadence for Laravel majors? Is the roadmap on the docs site current?

Integration Approach

Stack fit

Good fit if — and only if — the host application is already on Laravel 11 or 12 with PHP 8.2+, uses standard Eloquent, and has a conventional users table with an id (or any single-column PK) and a migration dated before the Laravel default. MySQL and PostgreSQL are the realistic targets; verify on your specific engine before assuming, since the package's tests will not cover your configuration.

Poor fit if the application is on Laravel 9/10, uses a non-Eloquent persistence layer for users, is a polyglot stack where accounting is a separate service, or needs real-time high-volume ledger writes. In the last case, a dedicated accounting engine (or a hosted ledger API) is the better architectural choice, and this package becomes a reporting shim.

Migration path

Do not treat this as a greenfield-only decision. The workable path for an existing application:

  1. Isolate the ledger in its own database connection if your infrastructure allows it. The entity_id mutation of the users table is the only hard cross-boundary coupling; keeping ledger tables on a separate schema limits blast radius on the user table and simplifies the eventual fork-and-extend.
  2. Backfill before you write. Seed Entity, Currency, Vat, and the full chart of accounts from an accountant-reviewed mapping, then load historical balances through ReportingPeriod start-of-year opening balances rather than replaying years of transactions. Replaying history through the posting path is seductive and almost always wrong.
  3. Map existing commercial documents to transaction types deliberately. A ClientInvoice in this package is a receivable movement with VAT, not your Order or Invoice record. Expect a mapping table and a one-way sync (your domain → ledger), never bidirectional.
  4. Fork on day one. MIT licence, single maintainer, zero dependents: vendor the package into your repository or maintain a private fork with a pinned version and a short patch queue. Do not depend on upstream for fixes you need within a release cycle.

Compatibility

Pin the exact version in composer.json with a conservative constraint, and add a CI job that runs your ledger acceptance tests against the next Laravel major in a scratch branch. Because the package's own support matrix moves with new Laravel majors, your upgrade planning must include "ledger package ready" as a gate item, not an afterthought.

Sequencing

  1. Spike (1–2 weeks). Throwaway branch, stock Laravel 11 project, publish config, seed a small chart of accounts, reproduce the README's five transactions plus one Assignment. Goal: confirm post() semantics, soft-delete behaviour, and whether you can reconcile the resulting Balance Sheet by hand.
  2. Accounting design review. Have a qualified accountant define the chart of accounts, VAT codes, period structure, and opening balances before writing integration code. This is the highest-leverage step and the one most often skipped.
  3. Shadow mode. Run the ledger in parallel with your existing accounting process for at least one full reporting period. Write to the ledger, generate IncomeStatement and BalanceSheet, and reconcile against the incumbent system monthly.
  4. Read-only reporting cutover. Move management reporting onto the package while statutory filing stays with the incumbent.
  5. Write-path cutover. Only once reconciliation has been clean for a full period. Freeze the incumbent as read-only and archive it.

Operational Impact

Maintenance

Real and ongoing. You inherit:

  • Laravel major upgrade coupling. Every 12–18 months there is a Laravel major, and this package's support is versioned against it. Budget one engineer-week per upgrade cycle for the ledger alone, plus a fork-rebase if upstream lags.
  • Accounting rule changes (VAT rates, IFRS amendments, statutory chart-of-accounts revisions) land as configuration or code changes. Configuration covers naming and codes; new behaviour (e.g. a new VAT scheme) will be your patch.
  • A fork you will actually maintain. With 0 dependents and a single primary maintainer, the realistic expectation is that you carry local patches. Keep them small, rebase quarterly, and upstream anything generic.

Support

Community-only. The package is a microbooks.io community initiative with no commercial SLA, no paid support tier, and no visible governance. Effective triage policy: your team is tier 1 and tier 2; upstream is tier 3 with best-effort latency measured in weeks. Build the fork discipline accordingly, and consider retaining a fractional accountant as an on-call domain reviewer — the failure modes here are accounting failures, not stack traces.

Scaling

The scaling profile is unusual: write volume is low (a company posts tens to low thousands of transactions per month), but read cost for reports grows with total ledger history. getSections() aggregates in PHP, which means report memory and latency scale with the number of entries in the period, and cross-entity consolidation multiplies that. Practical mitigations:

  • Partition or archive by reporting period; keep open-period ledgers small.
  • Cache report output per entity/period and invalidate on post().
  • If consolidation across many entities is required, plan for a materialised summary table that you own, fed by the package's ledger, rather than calling getSections() live.

Concurrency is the other scaling concern: two simultaneous post() calls against the same account need row-level locking or a serialisation strategy. Confirm the package provides it; if not, serialise postings at the application level (queue with a per-entity lock).

Failure modes

Failure Impact Detection
post() partially succeeds Unbalanced ledger; silently wrong reports Reconciliation assertion after every post; a nightly trial-balance check (debits == credits) as a hard alert
Tamper protection blocks a legitimate correction Stuck data, manual DB surgery required Define and test the correction workflow (reversal entries) before go-live
Soft-delete / Recycling leaves orphaned references Balances disagree with expectations Period-close reconciliation against bank and control accounts
Opening balances drift after ReportingPeriod changes Prior-year comparatives break Freeze closed periods; alert on any write touching a closed period
VAT account misconfiguration (rate vs. control account) Understated/overstated liabilities Accountant review of the VAT config as a gate item
Laravel major upgrade breaks the package Reporting outage during upgrade window CI matrix against next Laravel major; freeze reports during upgrade
Direct SQL edits bypass model guards Auditor finding DB-level permissions: no human write access to ledger tables outside the app

Ramp-up

Steeper than the install instructions suggest. The install is an afternoon; operational competence is a quarter. Three distinct skill sets are needed:

  • Laravel/PHP engineering — straightforward for an existing team.
  • Double-entry fluency — the mental model behind post(), Assignment, control accounts, and clearing is not obvious to engineers without accounting exposure. Budget a half-day of internal training walking the README's five transactions through to a hand-checked Balance Sheet.
  • IFRS/statutory reporting — external. Retain an accountant to own the chart of accounts, period structure, and sign-off on report output.

A pragmatic first-quarter plan: one engineer at ~50% for the spike and integration, an accountant for two to three days of design and one day per period of reconciliation, and a TPM-owned gate that no write-path cutover happens until two consecutive periods reconcile cleanly in shadow mode. Given the package's substance but thin ecosystem validation (score 31.7, opportunity 18.5, zero dependents), the correct posture is adopt with a fork plan and a one-period shadow run — not adopt-and-hope, and not build-from-scratch, which would cost multiples of the integration effort for a domain that is already reasonably modelled here.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
dakiquang/laravel-oauth-refresh-lock
woda/laravel-worktrees
dalefranks/ramasite
faghy/laracashbook
roundly-consulting/google-places-for-laravel
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
adachsoft/changelog-linter