A complete double-entry accounting system for Larapen. Manage multiple companies, localized charts of accounts (17 international standards), journals, fiscal years, partners, taxes, bank reconciliation, recurring entries, and generate financial reports, including the French FEC export.

Multi-Company

Manage separate legal entities under one installation. Each company has its own chart, journals, partners, and fiscal years, isolated by a global query scope.

17 Chart Templates

Ship-ready charts for PCG (FR), SYSCOHADA, US/UK/CA GAAP, SKR04 (DE), PGC (ES), PCMN (BE), SNC (PT), RGS (NL), Swiss OR, CGNC (MA), SCE (TN), AASB (AU), IFRS, and more.

Double-Entry Enforcement

Every journal entry must balance before it can be posted. Draft / Posted / Reversed / Cancelled lifecycle with full audit of who posted and when.

Fiscal Years & Period Locking

Auto-generate monthly periods from fiscal year boundaries. Lock or close periods and years to prevent further posting.

Bank Reconciliation

Import bank statements, match lines to journal entries in a two-column workspace, and track system vs. statement balances.

Recurring Entries

Template-based recurring postings (daily, weekly, monthly, quarterly, yearly) with optional auto-post and a daily scheduler.

Financial Reports

Trial Balance, General Ledger, Balance Sheet, Income Statement, and Journal Book. All filter by date range and respect the active company.

Multi-Currency

Currency and exchange rates captured at company, account, journal, partner, bank account, entry, and line level.

FEC Export

Legal French “Fichier des Écritures Comptables” export (TSV, 18 columns) per Arrêté du 29 juillet 2013.

Use Cases

Small Business Bookkeeping

Run a single company with the chart of accounts matching your country (PCG, GAAP, HGB, etc.). Record invoices, payments, and expenses through journals; let the system enforce balanced entries and period locks at month/year end.

Multi-Entity Group

Consolidate several legal entities in one installation. Switch between companies from the top bar; each company is fully isolated via the company_id scope. Users can be assigned to specific companies, or granted manage-all access.

French Regulated Accounting

Run a PCG chart, store all entries as draft then post them, lock fiscal periods at year-end, and generate the FEC export for tax inspections.

SYSCOHADA (OHADA) Accounting

Benin, Côte d'Ivoire, Senegal, and other OHADA member countries ship with the full SYSCOHADA révisé chart (9 classes) and can record entries in XOF/XAF with the appropriate tax codes.

Bank Reconciliation Workflow

Upload a bank statement, let staff match transaction lines to journal lines in the reconciliation workspace, and produce a reconciliation record that shows system vs. statement balance with the exact difference.

Requirements

  • Larapen CMS v1.0.0 or later
  • PHP 8.3+
  • MySQL 8.0+
  • Core users, countries, and currencies tables must exist
  • ext-bcmath required for balance comparisons
Standalone: The accounting add-on has no dependencies on other add-ons. It integrates with the core users table (user assignment + company switching) and the core currencies table.

Installation

Step 1: Upload the Add-on

In the admin panel, go to Admin → Extensions → Add-ons and click the Upload Add-on button. Select the add-on’s ZIP file: the system extracts it automatically and the add-on appears in the installed add-ons list.

Step 2: Activate the Add-on

Find Accounting in the list and click Activate. Its migrations, seeders (if any) and permissions are set up automatically.

Step 3: Configure

Navigate to Accounting → Companies → New Company to create your first company. Choose a chart template, set the default currency, and save: the chart of accounts is seeded automatically from the selected template. Then review Accounting → Settings to tune fiscal-year rules, numbering sequences, and posting controls. See Configuration.

Step 4: (Optional) Schedule the Recurring Entry Command

The service provider registers accounting:generate-recurring to run daily at 03:00. Make sure Laravel's scheduler is wired up to cron:

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Purchase Code (License Key)

Accounting is sold as a separate product, so it has its own purchase code (license key), distinct from the purchase code of the main application and from the one of every other add-on. You are asked for it when you activate Accounting in Admin panel → Add-ons.

Our products are sold on three platforms. The way you receive a purchase code depends on where you bought the product.

Platform / Marketplace How you get the purchase code Where to find it again
bedigit.com Store
In-site purchase (Shop)
Generated automatically when the order is paid, then sent by email, either in its own license email, or inside the order confirmation email. My Account → My Licenses on bedigit.com
Gumroad Created as soon as Gumroad notifies us of the sale, then sent in a separate email, in addition to the Gumroad receipt. The license email, your Gumroad Library, and My Account → My Licenses on bedigit.com
Envato Market
CodeCanyon
Issued by Envato, not by us, and never sent by email: you download it yourself from your Envato account. Envato account → Downloads → License certificate & purchase code
Check your spam folder. For both bedigit.com Store and Gumroad purchases, the purchase code is delivered by email. Automated license emails are very often filtered, so if the message is not in your inbox, look in your spam / junk folder before contacting support, and add our sender address to your contacts or allow list.

1. bedigit.com Store (in-site purchase)

  • As soon as the order’s payment status becomes Paid, a license key is generated automatically for every licensed item in the order (one key per purchased unit: buying 3 units gives 3 distinct keys).
  • It is emailed to the address used on the order, either in a dedicated license email or inside the order confirmation email. Check your inbox and your spam / junk folder.
  • The key stays available in your account under My Account → My Licenses. Keys are masked in the list; open the license detail page to reveal and copy the full key, see the domains it is activated on, and deactivate a domain to free an activation slot.
  • The matching invoice is under My Account → My Orders.

2. Gumroad

  • A Gumroad purchase produces two separate emails: the Gumroad receipt (sent by Gumroad, giving access to the files) and a license key email (sent by bedigit.com) that contains your purchase code.
  • The license key email is generated as soon as Gumroad notifies us of the sale, so it normally arrives within seconds of the payment. Here too, check your inbox and your spam / junk folder.
  • When the Gumroad product uses Gumroad’s own license-key feature, the same key also appears in your Gumroad receipt and under Library → your purchase on gumroad.com.
  • Use the same email address on bedigit.com as on Gumroad: your keys are then linked to your account automatically and listed under My Account → My Licenses, even if you register after the purchase. You can also add a Gumroad key manually from My Account → My Gumroad Licenses.

3. Envato Market (CodeCanyon)

  • Envato purchase codes are issued and delivered by Envato Market, never emailed by us, so there is nothing to look for in your spam folder: you retrieve the code from your Envato account.
  • Log in to your Envato / CodeCanyon account, open the Downloads page, find the item, and choose License certificate & purchase code from the Download dropdown. The code is written in that certificate.
  • An Envato purchase code looks like 12345678-90ab-cdef-1234-567890abcdef (8-4-4-4-12 characters). It never changes, and renewing item support does not issue a new one.
  • Official Envato article: Where Is My Purchase Code?
Lost your purchase code? Search your mailbox (spam folder included) for “license” or “purchase code”, then check My Account → My Licenses on bedigit.com for Store and Gumroad purchases, or Downloads → License certificate on Envato. If it is still missing, open a ticket on our Help Center with your order number (Store), Gumroad sale ID or buyer email (Gumroad), or Envato username and item name (Envato).

Configuration

The add-on ships with config/accounting.php. Each key can be overridden from the environment or by adjusting the config file directly.

Key Description Default
default_standard Accounting standard assigned to a new company when none is specified. generic
default_currency Fallback currency for new companies and entries. USD
decimal_precision Number of decimal places displayed in reports and forms. 2
account_code_padding Width used when zero-padding account codes. 8
allow_post_in_closed_period When true, entries can be posted into locked/closed periods. false
entry_reference_format Template for auto-generated entry references. JE-{year}-{seq:6}
standards Array mapping standard codes (e.g. pcg, gaap_us) to their display name, country, currency, and chart seeder class. 17 entries

First Steps

  1. Create a company and pick the chart template that matches your jurisdiction.
  2. Review your chart of accounts: hide unused accounts, adjust code ranges, or add custom accounts.
  3. Create a fiscal year. Monthly periods are generated automatically from its start/end dates.
  4. Create journals for each book (Sales, Purchase, Bank, Cash, General, Adjustments…). Many templates seed these already.
  5. Add tax codes (VAT, GST, withholding, etc.) and link them to their VAT payable / receivable accounts.
  6. Add partners (customers, suppliers, employees).
  7. Record your first journal entry and post it when you are confident the debits and credits balance.

Admin: Companies

The Companies page (Accounting → Companies) manages legal entities tracked in the system. Companies are not subject to the active-company scope: authorized users can view the full list regardless of which company they are currently operating under.

Creating & Editing Companies

The form is organized into tabs:

  • General: name, slug, legal name, tax ID, registration number, country, currency, fiscal year start month, chart template, lock date, active/default flags.
  • Address: street, city, state, postal code, country code.
  • Defaults: default accounts for retained earnings, sales, purchase, bank, receivable, payable, VAT receivable, VAT payable.
  • Users: assign users to the company (with a favorite flag per user).
Chart seeding: When you set the chart template on company creation, the corresponding chart seeder runs and populates accounting_accounts for that company.

Assigned Users

The Users tab shows all members currently able to work inside the company. Use the Assign user field (Select2 autocomplete) to add a new user; the Revoke action removes them. All updates are AJAX and refresh the card in place.

A user must either be assigned to a company or hold the accounting.companies.manage-all permission to see accounting data.

Switching Between Companies

Users with the accounting.companies.switch permission can change their active company from the top bar. The chosen company is persisted in session and bound via the CompanyContext singleton: subsequent queries automatically filter by it.

Admin: Chart of Accounts

The Chart of Accounts page (Accounting → Chart of Accounts) shows the full hierarchy of accounts for the active company.

Account Fields

Field Notes
codeAccount number (e.g. 411, 512, 707). Unique within the company.
nameAccount description (e.g. “Accounts Receivable”).
typeAsset, Liability, Equity, Income, or Expense.
subtypeOptional finer grouping (e.g. current/non-current).
parentParent account for hierarchical charts.
is_groupHeader account: never postable directly.
is_reconcilableCan be matched against bank statement lines.
allow_manual_entriesDisable to force postings through services only (e.g. system-generated VAT accounts).
currency_codeOverride the company currency for this account.
opening_balanceInitial balance carried into the first fiscal year.

Import / Export

Accounts can be exported to CSV/Excel and re-imported to bulk-update the chart. An import template (with header row and sample rows) is available via Accounts → Download import template.

Admin: Journals

Journals group related entries. Each journal has its own auto-incremented sequence used to generate entry references (e.g. SA-2024-000042).

FieldNotes
codeShort journal identifier (e.g. SA, PU, BA).
nameDisplay name (Sales Journal, Purchase Journal, Bank Journal…).
typesales / purchase / bank / cash / general / opening / closing / adjustment.
sequence_prefixOptional prefix for generated references. Falls back to the journal code.
default_debit_account_id / default_credit_account_idAccounts auto-selected in the entry form for this journal.

Admin: Tax Codes

Tax codes (VAT, GST, sales tax, withholding…) can be attached to journal lines to track indirect tax. Each tax code is linked to one or two accounts: a collected account (output tax) and a paid account (input tax).

Tax codes are scoped per company and per country. Their rate is stored as a decimal (e.g. 0.2000 for 20%).

Admin: Partners

Partners are customers, suppliers, employees, and other parties referenced in journal entries. The partner form captures contact information, tax IDs, and default receivable/payable accounts.

Create / Edit Modal

  • Code: unique partner code (e.g. CUST-001, SUP-012).
  • Name: display name.
  • Type: Customer, Supplier, Both, Employee, Other.
  • Tax identifier, Registration number.
  • Address, Country, Currency (Select2).
  • Receivable account / Payable account: overrides the company defaults for this partner.

Import / Export & Bulk Actions

Partners support CSV/Excel import/export, bulk delete, and trash/restore.

Admin: Fiscal Years & Periods

A fiscal year has a start date, end date, and a status (Open, Locked, Closed). On creation, the add-on auto-generates 12 monthly periods between those two dates.

Status Transitions

  • Open: entries can be posted freely.
  • Locked: no new postings unless allow_post_in_closed_period is enabled.
  • Closed: the Close action cascades to all periods. Admins receive a Period Closing notification.
Company lock date: In addition to per-period locks, the company-level lock_date acts as a global cutoff for all postings before that date.

Admin: Journal Entries

The Journal Entries page (Accounting → Journal Entries) is the main workbench for recording transactions.

Entry Form

FieldNotes
journalWhich book the entry belongs to.
entry_dateTransaction date. Used to resolve the fiscal period.
referenceAuto-generated from the journal's sequence. Editable if you need to keep an existing numbering.
descriptionFree-text narrative.
external_referenceInvoice #, PO #, receipt #, etc.
currency_code / exchange_rateOverride the company currency and rate.
linesAt least two lines required. Each with account, optional partner, optional tax code, and a debit OR credit amount.

Entry Lifecycle

  • Draft: fully editable, deletable. Shown with a grey badge.
  • Posted: immutable. Must have balanced debits / credits.
  • Reversed: a reversal entry has been generated and posted.
  • Cancelled: manually discarded without a reversal.

Posting

Click Post on a draft entry to move it to Posted. The service verifies:

  • Status is Draft.
  • Debits equal credits (bcmath comparison).
  • The entry's period is not locked (unless the config override is enabled).

If validation fails the admin sees an error message; unbalanced drafts also generate a database notification for admins (Unbalanced Entry Notification).

Reversal

Posted entries cannot be edited, but they can be reversed. The reverse action:

  1. Creates a new entry in the same journal with debits and credits swapped.
  2. Assigns a fresh reference from the journal sequence.
  3. Posts the reversal.
  4. Flags the original entry as Reversed and links reversed_entry_id.

Bulk Actions

Entries support bulk delete (draft only), CSV/Excel export, and CSV/Excel import. Import rejects rows that would produce unbalanced entries.

Admin: Recurring Entries

Recurring entries generate a new journal entry on a schedule (rent, depreciation, subscriptions…).

FieldNotes
nameTemplate name (“Monthly Office Rent”, “Annual Software Licences”).
journalJournal used for generated entries.
recurrence_periodDaily, Weekly, Monthly, Quarterly, Yearly.
interval_countRepeat every N periods (e.g. 2 for bi-monthly).
start_date, end_dateWindow during which the template is active.
next_run_dateWhen the next entry will be generated. Advanced automatically.
auto_postIf enabled, generated entries are posted immediately.
template_linesDebit/credit lines stored as JSON; copied verbatim into each generated entry.

A daily scheduled command, accounting:generate-recurring, runs every day at 03:00 and processes all templates whose next_run_date is today or earlier. You can also trigger a template manually via the Run now action.

Admin: Bank Accounts

Bank accounts link a bookkeeping account (e.g. 512: Banque) to real banking details (bank name, IBAN, BIC, currency, opening balance). An optional default journal is used when auto-posting reconciled entries.

Admin: Bank Statements

A bank statement represents a periodic summary from the bank. It has a reference, a statement date, period start/end, opening/closing balances, and a list of statement lines (transaction date, amount, description, optional partner).

Bank statements live as Draft until posted. Posting finalizes the statement and enables matching in the reconciliation workspace.

Admin: Reconciliation

The reconciliation workspace (Reconciliation → Open a statement) displays bank statement lines on one side and unmatched journal lines on the other. Match them line-by-line; each match stores a shared reconciliation_ref on both the journal line and the bank statement line. A reconciliation record tracks the system vs. statement balance with the calculated difference.

If the difference is zero, the reconciliation status becomes Balanced. Otherwise it remains Draft until investigated.

Financial Reports

All reports accept optional date range filters and respect the active company. Access them via Accounting → Reports.

Trial Balance

Lists every active account with total debits, total credits, and the resulting balance. Totals at the bottom must equal: the is_balanced flag tells you at a glance.

General Ledger

Per-account detailed listing of every posted journal line with a running balance. Useful for auditing or investigating a specific account.

Balance Sheet

Assets, Liabilities, and Equity grouped by type at a point in time. P&L accounts are implicitly closed to the configured retained earnings account.

Income Statement (P&L)

Revenue and expenses over a period, with net income at the bottom.

Journal Book

Transactions grouped by journal with full entry and line detail. Matches the French “livre journal” requirement.

FEC Export

French businesses are required to produce a Fichier des Écritures Comptables on demand for the tax administration. The built-in FEC export generates a tab-separated file with 18 columns per the Arrêté du 29 juillet 2013:

  • JournalCode, JournalLib
  • EcritureNum, EcritureDate, EcritureLib, ValidDate
  • CompteNum, CompteLib, CompAuxNum, CompAuxLib
  • PieceRef, PieceDate
  • Debit, Credit
  • EcritureLet, DateLet (reconciliation)
  • Montantdevise, Idevise (foreign currency)

Only Posted entries are included. The date range filter defines the fiscal period exported. Download requires the accounting.reports.export-fec permission.

Accounting Standards

When creating a company you pick one of the packaged chart templates. The matching chart seeder runs and populates the chart of accounts. All 17 templates are ready out of the box:

CodeStandardCountryCurrency
genericGeneric framework-USD
pcgPlan Comptable GénéralFranceEUR
syscohadaSYSCOHADA RéviséOHADA (Benin, Senegal…)XOF / XAF
gaap_usUS GAAPUnited StatesUSD
gaap_ukUK GAAP / FRS 102United KingdomGBP
gaap_caASPE / IFRSCanadaCAD
skr04_deSKR04 / HGBGermanyEUR
pgc_esPlan General de ContabilidadSpainEUR
pcmn_bePCMNBelgiumEUR
cc_itCodice CivileItalyEUR
snc_ptSNCPortugalEUR
rgs_nlReferentie GrootboekschemaNetherlandsEUR
or_chSwiss Code of ObligationsSwitzerlandCHF
cgnc_maCGNCMoroccoMAD
sce_tnSCETunisiaTND
aasb_auAASBAustraliaAUD
ifrsIFRS GenericInternational-

Multi-Currency

Every level of the data model can override currency and exchange rate:

  • Company reporting currency.
  • Per-account override (e.g. a GBP bank account inside a EUR company).
  • Per-journal currency.
  • Per-partner currency (used when creating invoices).
  • Per-bank-account currency.
  • Per-entry currency_code + exchange_rate.
  • Per-line amount_currency, currency_code, and exchange_rate.

The FEC export surfaces Montantdevise and Idevise for foreign-currency lines.

Notifications

The add-on ships two notification types, both registered with the core notification system. Admins manage recipients and channels from Admin → Settings → Notifications.

KeyChannelsTriggerForced?
accounting_period_closing mail, database Fiscal year closed No (user can opt out)
accounting_unbalanced_entry database Draft entry fails post due to imbalance Yes (cannot be disabled per-user)

Trash & Soft Delete

Companies, accounts, partners, and journal entries use soft-delete. Deleted records land in the corresponding Trash page (e.g. Accounting → Partners → Trash). From there:

  • Restore a single record or bulk-restore several.
  • Permanently delete (force-delete) individual records, bulk, or empty the trash entirely.

Journal entries are only deletable while in Draft status. Posted entries must be reversed instead.

Updating

  1. Replace the extensions/addons/accounting folder with the new version.
  2. Run php artisan migrate --path=extensions/addons/accounting/database/migrations to apply any new migrations.
  3. Run php artisan config:clear && php artisan view:clear.
  4. If theme assets changed, run npx vite build.

Uninstallation

Switching an add-on off without losing anything is a deactivation: go to Admin panel → Add-ons, find Accounting and click Deactivate.

  • Its routes, views, admin menu entries and permissions stop being registered, and its front-end pages stop answering.
  • Its database tables and all the data they hold are kept, and its files stay under extensions/addons/accounting/. Nothing is deleted.
  • The purchase code recorded at activation is kept too, so activating the add-on again does not ask for it.
  • Deactivation is refused while another active add-on depends on this one: deactivate that add-on first.

Click Activate on the same card to switch it back on. Pending migrations are re-run, assets are republished, and the add-on picks up exactly where it left off.

Removing

Removing is permanent and destroys the add-on's data. The Remove button only appears on a deactivated add-on, so removal is always two steps:

  1. Deactivate Accounting (see Uninstallation).
  2. Click Remove on its card and confirm the prompt.

The admin panel then, in one pass:

  • runs the add-on's uninstall hook, if it ships one, while its code is still on disk;
  • revokes the permissions declared in its addon.json;
  • rolls back its migrations (this drops its database tables and every row they hold) and purges its entries from the migrations table, so a later reinstall migrates from scratch;
  • deletes its published assets: public/addons/accounting/, public/vendor/accounting/ and storage/app/public/addons/accounting/;
  • deletes the add-on directory extensions/addons/accounting/;
  • deletes its row in the addons table (the recorded purchase code goes with it) and clears the application cache.
This cannot be undone. Back up your database before removing an add-on whose data you may still need: installing it again later creates empty tables, not your old content.

Removal is refused, with an explanatory message and before anything is destroyed, when the add-on is still active, when another active add-on depends on it, or when the web server (PHP) user cannot delete extensions/addons/accounting/. In that last case, give that user write permission on the directory and on its parent, then try again.

Deleting the folder over FTP or SSH is not equivalent: the add-on's tables, its entries in the migrations table and its addons row are all left behind, and its card stays in the list. Use Remove in the admin panel instead.

Troubleshooting

“No active company” when opening an accounting page

  • The current user has no assignment and no accounting.companies.manage-all permission.
  • Assign the user to at least one company in Companies → Users tab.

“Entry is not balanced” when posting

  • Debits must equal credits to the last decimal (bccomp, 4 decimal places).
  • Watch for rounding differences with foreign currency conversions.

“Period locked” when posting

  • The entry date falls inside a Locked or Closed period.
  • Either move the entry date to an open period or reopen the period (requires accounting.fiscal-years.edit).
  • As a last resort, set allow_post_in_closed_period to true in the config.

Duplicate reference error on Reverse

  • Happens if the journal's next_sequence_number is out of sync with existing entries (typically after a manual import). The observer self-heals by taking MAX(reference) + 1, but you can also reset the counter manually in the Journal edit form.

Recurring entries not generating

  • Check that Laravel's scheduler is wired up in cron (schedule:run every minute).
  • Ensure the template is Active and its next_run_date is in the past.
  • Run php artisan accounting:generate-recurring manually to see errors.

FEC export returns no rows

  • Only Posted entries are included. Verify your date range covers posted entries.
  • Confirm the active company has the fec_country_code set (FR).

Accounting v1.0.0: Part of the Larapen CMS platform.

© BeDigit. All rights reserved.

Was this article helpful?

Thank you for your feedback!

Still need help? Create a support ticket

Create a Ticket
Sep 18, 2026