Seeders
What data gets seeded by default and how to run individual seeders.
Signals ships with database seeders that populate your application with reference data, permissions, roles, and optional demo content. Running php artisan db:seed executes all default seeders in the correct dependency order.
What Runs by Default
The DatabaseSeeder calls these seeders in order. The list is not maintained by hand: it mirrors SeederPanelCatalog::bootStartClasses(), the single source of truth shared with the admin seeders panel, and a docs test fails if the two drift apart.
| # | Seeder | Purpose |
|---|---|---|
| 1 | CountrySeeder |
ISO 3166-1 countries with currency codes, phone prefixes, and default timezones |
| 2 | LanguageSeeder |
The default English language record |
| 3 | LanguageTranslationSeeder |
Additional UI languages and their translated string packs |
| 4 | ListsSeeder |
System-managed lists (Settings → Lists) |
| 5 | CurrencySeeder |
ISO 4217 currency definitions, with GBP/USD/EUR enabled |
| 6 | ExchangeRateSeeder |
Baseline GBP→USD and GBP→EUR rates for a clean install |
| 7 | WarehouseSeeder |
A default warehouse ("Main Warehouse") if none exist |
| 8 | TaxTypeSeeder |
Default company and product tax types |
| 9 | TaxZoneSeeder |
Tax zones (UK, EU Account States, EU Other, World) and country memberships |
| 10 | TaxCategorySeeder |
Catalogue item tax categories (Standard, Reduced, Zero Rated, Exempt) |
| 11 | TaxRateSeeder |
Default tax rates (Standard 20%, Reduced 5%, Zero 0%) |
| 12 | TaxRuleSeeder |
Class-map rule tying the default tax types to the Standard rate |
| 13 | TaxZoneRuleSeeder |
UK-seller zone-matching rules for domestic and cross-border scenarios |
| 14 | RevenueGroupSeeder |
Revenue groups (Dry Hire, Wet Hire, Sales, Services) |
| 15 | CostGroupSeeder |
Cost groups (Equipment Sub-Hire, Crew Sub-Hire, Transport, Consumables, Equipment Purchase) |
| 16 | CatalogueItemGroupSeeder |
Default catalogue item groups (Audio, Lighting, Video, Staging, etc.) |
| 17 | PermissionSeeder |
All system permissions for role-based access control |
| 18 | RoleSeeder |
System roles with permission assignments |
| 19 | DispatchStageSeeder |
Outbound dispatch board stages (To pick, Picking, Packed, Loaded) |
| 20 | ReturnStageSeeder |
Inbound returns board stages (Due back, Receiving, Exceptions, Closed) |
| 21 | EmailLayoutSeeder |
The master branded email layout wrapped around system emails |
| 22 | EmailTemplateSeeder |
System email templates (magic link, password reset, invitation, digest, test) |
| 23 | NotificationTypeSeeder |
Notification type definitions with channel defaults |
| 24 | DocumentTemplateSeeder |
System document templates (quotes, invoices, and so on) for every warehouse |
| 25 | CommunicationTemplateSeeder |
System customer-communication templates for every warehouse |
| 26 | ViewSeeder |
System-managed live filters for accounts, catalogue_items, stock, and activities |
| 27 | RateSpecificationPresetSeeder |
Industry-standard rate specification presets |
| 28 | DiscountCategorySeeder |
Default discount categories (Trade Discount, Preferred Customer, Staff) |
| 29 | PriceCategorySeeder |
Default price categories with tier multipliers (Trade Day 1 / Day 2+, Retail) |
| 30 | CatalogueItemSeeder |
Sample catalogue items across rental, sale, and service types |
| 31 | ReportSeeder |
The sixteen system reports (revenue, outstanding invoices, tax returns, pipeline, turnover, shortages, accounts, catalogue) |
In disposable environments (local, testing, conformance) it also creates a development owner account ([email protected]). Outside those environments the account is skipped and the omission is logged.
ActivitySeeder is intentionally not in the boot-start set — it is a no-op, and demo activities live in DemoDataSeeder instead.
CountrySeeder
Loads all ISO 3166-1 country records from database/data/countries.json — 250 countries, each with a code, name, currency code, phone prefix, and default timezone. Uses updateOrCreate keyed on code — safe to re-run.
LanguageSeeder
Creates the single default language record, English (UK) - RMS Compatible (en), marked default and active. Every language string falls back to this record.
LanguageTranslationSeeder
Adds the optional UI languages alongside the default and upserts their translated string packs:
| Code | Language |
|---|---|
en-srf |
English (UK) - SRF Opinionated |
fr |
French (Français) |
de |
German (Deutsch) |
it |
Italian (Italiano) |
es |
Spanish (Español) |
pt |
Portuguese (Português) |
zh |
Chinese (中文) |
String packs are upserted on language_id + key and never overwrite a string that has already been translated in the UI — safe to re-run.
ListsSeeder
Creates the system-managed lists used throughout the platform (Settings → Lists). The editable contact and CRM lists are:
| List | Values |
|---|---|
| Address Type | Billing, Shipping, Primary, Registered |
| Email Type | Work, Personal, Billing, Support |
| Phone Type | Work, Mobile, Home, Fax |
| Link Type | Website, LinkedIn, Facebook, Instagram, X (Twitter), YouTube |
| Relationship Type | Employee, Director, Contractor, Agent |
| Lawful Basis Type | Legitimate interest (prospect/customer/supplier), Consent, Contract, Legal obligation, Vital interests, Public task, Not applicable |
| Location Type | Internal, External |
| Rating | None, 1–5 Stars |
| Invoice Term | Due on Receipt, Net 7/14/30/45/60/90, End of Month |
| Locale | 17 locale codes (en-GB, en-US, fr-FR, de-DE, and others) |
| File Category | Contract, Invoice, Quote, Purchase Order, Certificate, and 8 others |
| Vehicle Type | Van, Truck 7.5t, Artic, Trailer, Car |
| Vehicle Assignment Role | Delivery, Collection, On-site, Standby |
It also seeds the read-only status and classification lists that mirror application enums, so reports and filters can label them: Activity Type, Credit Note Status, Invoice Status, Rental Status, Repair Status, Repair Reason, Stock Check Status, Stock Check Discrepancy Resolution, Warehouse Transfer Status, Asset Cost Type, Asset Retirement Reason, Usage Metric, Import Batch Status, Import Plan Status, Import Conflict Strategy, Import Source Format, Export Format, and Export Job Status.
All values are marked is_system = true and use updateOrCreate — safe to re-run.
CurrencySeeder
Upserts the full ISO 4217 catalogue (over 200 currencies) from brick/money, including each currency's name, symbol, and decimal places. Only GBP, USD, and EUR are enabled; everything else is disabled and can be switched on in settings. Uses upsert keyed on code — safe to re-run.
ExchangeRateSeeder
Seeds two indicative manual rates effective 2026-01-01 so a clean install can price in more than one currency: GBP→USD at 1.27000000 and GBP→EUR at 1.18000000, each with its inverse. These are placeholder figures, not live market data — replace them before quoting in foreign currency.
WarehouseSeeder
Creates a default warehouse called Main Warehouse (GB, marked default) if no warehouses exist. It runs early in DatabaseSeeder so that later seeders which need a warehouse — document templates, communication templates, sample catalogue items and stock — have one to attach to.
Note: The setup wizard (
php artisan signals:setup) handles warehouse creation interactively, so this seeder is primarily useful for automated deployments.
TaxTypeSeeder
Creates the default tax typeification records:
- Company Tax type: Standard (default)
- CatalogueItem Tax Types: Standard (default), Exempt
It also writes the default product tax type into tax.default_catalogue_item_tax_type_id when that setting is still unset. Uses updateOrCreate — safe to re-run.
TaxZoneSeeder
Creates the four tax zones used by zone-matching rules and attaches country memberships to each:
| Slug | Zone | Account countries |
|---|---|---|
uk |
United Kingdom | GB |
eu_account |
EU Account States | Current EU account countries |
eu_other |
EU Other | CH, NO, IS, LI, AD, MC, SM, VA |
world |
Rest of World | Catch-all for every country not mapped above |
If a default warehouse exists and has no zone, it is attached to the UK zone. Uses updateOrCreate keyed on slug — safe to re-run.
TaxCategorySeeder
Creates the four product tax categories used to classify catalogue items: Standard (default), Reduced, Zero Rated, and Exempt. Uses updateOrCreate keyed on slug — safe to re-run.
TaxRateSeeder
Creates three default tax rates suitable for UK VAT:
| Name | Rate |
|---|---|
| Standard | 20% |
| Reduced | 5% |
| Zero | 0% |
Uses updateOrCreate — safe to re-run.
TaxRuleSeeder
Creates the single class-map rule that ties the default company tax type and default product tax type to the Standard rate. Without it, TaxCalculator falls back to zero tax for an otherwise ordinary product/company pairing. Depends on TaxTypeSeeder and TaxRateSeeder.
TaxZoneRuleSeeder
Creates the UK-seller zone-matching rules used for cross-border scenarios. Higher priority wins; a null buyer type or tax-ID flag acts as a wildcard.
| Priority | Rule | Result |
|---|---|---|
| 110 | Tax exempt supply (government) | Exempt |
| 110 | Tax exempt supply (charity) | Exempt |
| 100 | UK domestic | Standard |
| 90 | UK to EU B2B reverse charge (validated tax ID) | Reverse charge |
| 80 | UK to EU B2B without tax ID | Standard |
| 70 | UK to EU B2C | Standard |
| 65 | Outside scope supply (business, validated tax ID) | Outside scope |
| 60 | UK export zero rated | Zero rated |
Uses updateOrCreate keyed on name, zones, buyer type, and tax-ID flag — safe to re-run.
RevenueGroupSeeder
Creates four revenue groups used for categorising rental line items:
- Dry Hire
- Wet Hire
- Sales
- Services
Uses updateOrCreate — safe to re-run.
CostGroupSeeder
Creates five cost groups used for categorising rental costs:
- Equipment Sub-Hire
- Crew Sub-Hire
- Transport
- Consumables
- Equipment Purchase
Uses updateOrCreate — safe to re-run.
CatalogueItemGroupSeeder
Creates 10 default catalogue item groups with sort order:
Audio, Lighting - Generic, Lighting - Moving Heads, Video, Staging, Power, Rigging, Furniture, Transport, Consumables.
Uses updateOrCreate — safe to re-run.
PermissionSeeder
Creates every permission used by the role-based access control system — over 200 keys following the resource.action naming convention. Most domains follow the same shape: an .access key that opens the UI area, a .view key that grants read, and then the write and workflow actions.
| Area | Domains |
|---|---|
| Administration | settings.*, users.*, roles.*, numbering.*, email-templates.manage, notifications.manage, custom-fields.*, lists.*, tax-types.*, static-data.*, languages.*, webhooks.manage, events.read, plugins.manage, action-log.view, evidence.view, workflows.* (including publish) |
| CRM | accounts.*, addresses.*, activities.*, conversations.* |
| Customer communications | communications.draft (compose for review), communications.approve (approve, discard, and send) |
| Sales | rentals.* (including unlock_rates and dispatch_add_items), projects.*, shortages.*, documents.*, document_templates.* |
| Finance | invoices.* (including issue, billing-run, void, credit), credit-notes.apply, payments.record, costs.view |
| Purchasing | purchase_orders.*, virtual_stock.*, virtual_assets.* |
| Catalogue | catalogue-items.* (including supplier_costs), kits.*, rates.*, pricing.* |
| Warehouse | assets.*, availability.view, flightcases.*, repairs.*, stock_checks.*, warehouse_transfers.*, dispatch.*, returns.*, scanning.* |
| Assets & compliance | equipment_tests.* (including override_dispatch), equipment-test-results.*, usage-readings.*, asset-costs.*, asset-retirements.*, vehicles.* |
| Scheduling | facilities.*, services.*, resource-assignments.*, scheduling-conflicts.* |
| Data & reporting | reports.*, imports.* (including undo), exports.* |
| Interfaces | api.*, cli.access, mcp.access, system.read, schema.read |
Uses Permission::findOrCreate() — safe to re-run. The authoritative list is PermissionSeeder::permissions().
RoleSeeder
Creates the five system roles and assigns their default permission sets. Owner access is handled separately via the is_owner flag on users — it is not a Spatie role, and any legacy Owner, Manager, Operator, or Viewer role left by an older seed is deleted.
| Role | Cost visibility | All warehouses | Access level |
|---|---|---|---|
| Admin | Yes | Yes | Every permission |
| Operations Manager | Yes | No | Everything except settings.*, users.*, roles.*, and numbering.edit, plus custom fields, import/export management, and the equipment_test dispatch override |
| Sales | No | No | Rentals (not unlock_rates), projects, activities, conversations, invoices, purchase orders, virtual stock, payments, accounts and addresses, shortage view/resolve, quote and invoice documents, plus read-only catalogue_items and reports |
| Warehouse | No | No | Stock, catalogue_items, flightcases, kits, repairs, stock checks, warehouse transfers, equipment_test results, usage readings, dispatch, returns, scanning, asset cost creation and retirements, plus read-only accounts, vehicles, equipment_tests, and reports |
| Read Only | No | No | Every .view and .access permission except scanning, plus import/export viewing |
All roles are marked is_system = true and cannot be deleted through the UI. RoleSeeder calls PermissionSeeder internally, so permissions always exist first.
DispatchStageSeeder
Creates the four outbound dispatch board stages, keyed and ordered:
| Key | Label | Terminal |
|---|---|---|
to_pick |
To pick | No |
picking |
Picking | No |
packed |
Packed | No |
loaded |
Loaded | Yes |
Uses updateOrCreate keyed on key — safe to re-run.
ReturnStageSeeder
Creates the four inbound returns board stages, keyed and ordered:
| Key | Label | Terminal |
|---|---|---|
due_back |
Due back | No |
receiving |
Receiving | No |
exceptions |
Exceptions | No |
closed |
Closed | Yes |
Uses updateOrCreate keyed on key — safe to re-run.
EmailLayoutSeeder
Creates the master Signals email layout in email_layouts — the branded chrome (shell, styles, header, body slot, footer) wrapped around every system email. It is a faithful conversion of the static Blade view resources/views/emails/layouts/signals.blade.php, which is retained as the hard fallback, so the two must stay visually in step.
| Key | Name | Flags |
|---|---|---|
signals |
Signals | is_system, is_active, and is_default when no default exists yet |
Re-running refreshes the name, description, and system flag but never overwrites an edited body, and it drops the cached default layout. See Email Layouts.
EmailTemplateSeeder
Creates the global system email templates. Five of them are derived from the matching per-warehouse communication template definitions so the global and per-warehouse copies never diverge; test_email and embedding_budget_exceeded are defined locally.
| Key | Name | Purpose |
|---|---|---|
magic_link |
From auth.magic_link |
Sent when a user requests a magic-link sign-in |
new_sign_in |
From auth.new_sign_in |
Sent when a new device or browser signs in to a user's account |
password_reset |
From password.reset |
Sent when a user requests a password reset |
user_invited |
From user.invited |
Sent when a new user is invited |
notification_digest |
From notification.digest |
Sent as the daily batched notification digest |
test_email |
Test Email | Sent when testing email configuration from admin settings |
embedding_budget_exceeded |
AI Embeddings Budget Exceeded | Sent to administrators when the monthly AI token budget is reached |
Templates support merge fields (e.g. {{ user.name }}, {{ company.name }}). Uses updateOrCreate keyed on key — safe to re-run.
NotificationTypeSeeder
Registers every notification type definition on the NotificationRegistry and syncs it to the notification_types table. Each definition carries a category, audience, available channels, default channels, default recipient rules, and a merge-field data schema used by the template editor.
| Category | Types |
|---|---|
| Users | user.invited |
| System | update.failed, password.reset, auth.magic_link, auth.new_sign_in, notification.digest |
| Rentals | rental.created, .confirmed, .cancelled, .on_hold, .checked_out, .checked_in, .late_return, .quote_expiring |
| Conversations | conversation.mentioned |
| Shortages | shortage.escalated, .acknowledged, .resolution.confirmed, .waitlist.created, .waitlist.matched, .waitlist.expired |
| Invoicing | invoice.created, .overdue, .payment_received, .credit_note, statement.emailed |
| Documents | document.finalised, .emailed, .public_link_created, .portal_question, .approved, .declined, invoice.portal_payment_received |
| Compliance | repair.created, .updated, .released, equipment_test.completed, .failed, .due, .overdue, certification.expiring, stock_check.submitted |
| Flightcases | flightcase.contents_overrun |
| Virtual Stock | virtual_stock.overrun |
| Data | import_batch.committed, .failed, import_plan.completed, .undone, export.completed, export.failed |
| Reports | report.scheduled_delivery, report.threshold_alert |
| Scheduling | scheduling.conflict_detected, .conflict_resolved, .demand_unmet, .assignment_confirmed, .assignment_cancelled, .assignment_rescheduled (no types for created/started/completed — audit trail only) |
Syncing is non-destructive: user channel preferences and edited recipient rules survive a re-run. The authoritative list is NotificationTypeSeeder::types().
DocumentTemplateSeeder
Seeds the system document template set for every existing warehouse, so each warehouse gets its own editable copy. Templates are keyed system-{type} and marked is_system, is_default, and is_active; the body, header, footer, styles, and page config come from SystemDocumentTemplates::definitions().
The set covers quotes, invoices, credit notes, deposit invoices, pro formas, statements, receipts, delivery notes, pick lists, return lists, purchase orders, asset and asset labels, equipment_test certificates and summaries, product spec sheets, virtual stock summaries, repair reports, stock check reports, warehouse transfer manifests, activity summaries, fleet vehicle summaries, scan session reports, and flightcase manifests.
It also runs any document template seeders registered by active plugins. Seeding is idempotent per warehouse (firstOrCreate on warehouse + slug), and CreateWarehouse calls the same seeder with a bulk-insert fast path when a brand-new warehouse is created. See Document Templates.
CommunicationTemplateSeeder
Seeds the customer-facing communication templates for every existing warehouse, one per notification type that can be sent to a customer — magic link, password reset, user invitation, notification digest, rental created/confirmed/cancelled/checked out/late return/quote expiring, shortage escalated/waitlist matched, virtual stock overrun, equipment_test failed/due/overdue, certification expiring, invoice created/overdue/payment received/credit note, statement emailed, document emailed, scheduled report delivery, report threshold alert, and scheduling demand unmet.
Each template links to its notification type key and supplies the subject, body, eyebrow, preheader, and footer context rendered inside the email layout. Idempotent per warehouse, with the same fresh-warehouse bulk path as document templates.
ViewSeeder
Creates system-managed live filters for each entity type. These views appear in the API and UI view selectors and cannot be deleted by users.
| Entity | Views created |
|---|---|
| Accounts | All Accounts (default), Companies Only, Contacts Only, Active Venues, Inactive Accounts |
| Catalogue items | All Catalogue items (default), Rental Catalogue items, Sale Catalogue items, Active Catalogue items, Inactive Catalogue items |
| Assets | All Assets (default), Barcoded Stock, Loose Stock |
| Activities | All Activities (default), Scheduled Activities, Completed Activities |
| CatalogueItem Groups | All CatalogueItem Groups (default) |
| Rentals | All Rentals (default), Drafts, Quotes, Orders |
| Shortage Resolutions | All Shortage Resolutions (default), Pending Resolutions, Confirmed Resolutions |
Uses updateOrCreate keyed on name + entity type — safe to re-run.
RateSpecificationPresetSeeder
Creates the 11 industry-standard rate specification presets from RatePresets::all(): Daily Rate, Weekly Rate, Monthly Rate, Hourly Rate, Half Hourly Rate, Fixed Rate, Fixed Rate and Factor, Fixed Rate and Subs Days, Daily Multiplier and Factor, Hourly Multiplier and Factor, and Monthly Multiplier and Factor. Presets are identified by a preset_slug and use updateOrCreate — safe to re-run. See the Rate specifications page for details on each preset.
DiscountCategorySeeder
Creates the three default discount categories used to classify CRM pricing agreements: Trade Discount, Preferred Customer, and Staff. Uses updateOrCreate keyed on name — safe to re-run.
PriceCategorySeeder
Creates the two default price categories with their day tiers:
| Category | Tiers |
|---|---|
| Trade | Day 1 at ×1.0000, Day 2+ at ×0.8000 |
| Retail | Day 1 at ×1.0000 |
Uses updateOrCreate keyed on name — safe to re-run.
CatalogueItemSeeder
Creates 14 sample catalogue_items across rental, sale, and service types to demonstrate the catalogue, along with a default rate for each and stock (barcoded assets or loose quantities) in the default warehouse:
| Group | Catalogue items |
|---|---|
| Audio | Shure SM58, JBL EON615, Yamaha TF1 Mixing Console |
| Lighting - Moving Heads | Robe Esprite, Martin MAC Aura XB |
| Lighting - Generic | Chauvet COLORado Panel Q40, ETC Source Four 750W |
| Video | Barco UDX-4K32, Samsung 55" LED Display |
| Staging | Stage Deck 8x4, Stage Leg 1m |
| Power | Power Distribution 63A 3-Phase |
| Consumables | Gaffer Tape 50m Black (sale item) |
| (none) | Lighting Technician (service item) |
Rental and service catalogue items are priced against the daily-rate preset, sale catalogue items against fixed-rate. Catalogue items are created with firstOrCreate keyed on sku (rates on product + warehouse + transaction type, stock on asset number) — safe to re-run. It depends on CatalogueItemGroupSeeder, TaxTypeSeeder, RateSpecificationPresetSeeder, and a warehouse having run first.
ReportSeeder
Creates the twenty-two system reports every install starts with, built on the rentals, invoices, invoice_taxes, credit_notes, purchase_orders, accounts, catalogue_items, assets, equipment_test_results, and repairs report sources:
| Report | Key | Source | What it answers |
|---|---|---|---|
| Revenue by Warehouse | revenue-by-warehouse |
invoices |
Invoiced revenue and invoice count per warehouse, last twelve months |
| Outstanding Invoices | outstanding-invoices |
invoices |
Unpaid balance and invoice count by status, for invoices with something still owed |
| VAT Return | vat-return |
invoice_taxes |
Taxable base and tax charged per rate, last quarter, with per-rate subtotals and a grand total |
| Tax by Treatment | tax-by-treatment |
invoice_taxes |
Taxable base and tax charged per tax treatment (standard, reverse charge, exempt), year to date |
| Invoiced Revenue by Month | invoiced-revenue-by-month |
invoices |
Invoiced, paid, and outstanding totals per calendar month, last twelve months |
| Payments Received by Month | payments-received-by-month |
invoices |
Cash collected per calendar month, windowed on when each invoice was paid |
| Revenue by Currency | revenue-by-currency |
invoices |
Invoiced and outstanding totals per billing currency, year to date |
| Top Clients | top-clients |
invoices |
Accounts ranked by invoiced revenue, last twelve months |
| Pipeline by Stage | pipeline-by-stage |
rentals |
Value and count of enquiries, quotes, and orders raised, last twelve months |
| Rental Turnover by Warehouse | rental-turnover-by-warehouse |
rentals |
Charge value and job count per warehouse, by hire start date |
| Rental Revenue by Month | rental-revenue-by-month |
rentals |
Charge value of rentals per calendar month, by hire start date |
| Revenue Mix by Warehouse | revenue-mix-by-warehouse |
rentals |
Rental, sale, and service charge split per warehouse |
| Upcoming Shortages | upcoming-shortages |
rentals |
Rentals starting in the next thirty days that are short of equipment, by warehouse |
| Uninvoiced Orders | uninvoiced-orders |
rentals |
Orders that have started but carry no invoice yet, by account |
| Aged Receivables | aged-receivables |
invoices |
Overdue balance and invoice count per account — everything past its due date and still unpaid |
| Credit Notes by Status | credit-notes-by-status |
credit_notes |
What was credited back to customers, by credit note status, last twelve months |
| Supplier Spend | supplier-spend |
purchase_orders |
Purchase order value per supplier, by the date each order was placed |
| Fleet by Warehouse | fleet-by-warehouse |
assets |
Equipment held, allocated, and unavailable at each warehouse |
| Equipment Test Outcomes | equipment-test-outcomes |
equipment_test_results |
Pass and fail counts per test, last twelve months, with subtotals |
| Repairs by Status | repairs-by-status |
repairs |
Equipment in repair by status and the reason it was raised, with subtotals |
| New Accounts by Type | new-accounts-by-type |
accounts |
Accounts added over the last twelve months by contact, company, and venue |
| Catalogue Composition | catalogue-composition |
catalogue_items |
Item count per catalogue type, split by active state, with subtotals |
The rental reports window on starts_at — the date the kit goes out — except pipeline-by-stage, which asks when work came in and so windows on created_at. uninvoiced-orders and upcoming-shortages state their scope as filters in the definition (orders only, not yet invoiced; short of equipment) rather than leaving it to whoever reads the figures.
The two tax reports read the frozen invoice_taxes snapshots — the figures the tax engine wrote when each invoice was generated — and never recalculate tax. Both window on the invoice's issued_at rather than the snapshot's own timestamp, and both exclude drafts, void invoices, and proformas through filters stored in the definition, so the "what counts as a tax document" decision is visible and editable rather than compiled into the reporting engine.
aged-receivables is the one report whose filter is relative rather than only its window: it asks for invoices due before {today}, resolved at execution in the company timezone, so "overdue" means overdue on the day someone runs it. The resolved instant is part of the result cache key, so it can never serve yesterday's list.
fleet-by-warehouse and repairs-by-status carry no money measure. An asset and a repair record no cost of their own — those figures live on asset_costs — so a spend-per-repair report is a question for a future source rather than one these can answer.
Each is seeded with visibility = system, so it is visible to every user, owned by nobody, and refused if anything tries to delete it. Definitions store a relative date token (last_12_months) rather than fixed dates, so a seeded report still means "the last twelve months" a year from now.
Reports are addressed by their stable key, which is what lets a dashboard report widget — or a plugin — point at one without knowing its id. Uses firstOrNew on key — safe to re-run, and it restores a system report that has gone missing.
ActivitySeeder
Retained as a no-op and deliberately excluded from the boot-start set. Sample activities are created by DemoDataSeeder instead, tagged demo-data so they can be cleared again.
DemoDataSeeder
A curated end-to-end demo dataset for development, evaluation, and demos — not a bulk load. It creates:
- 3 demo warehouses (London Warehouse, Manchester Depot, Edinburgh Office)
- Roughly 10 companies, 10 venues, and 10 contacts with addresses, relationships, and notifications
- Account enrichment: discount and price categories with tiers, plus EU B2B, charity, tax-exempt, and rest-of-world tax variants
- Catalogue item enrichment: supplier costs, kits, bundle rules, assets, repairs, stock checks, warehouse transfers, and a flightcaseable barcoded catalogue item with assets
- Around 12 rentals across draft, quotation, order, dispatched, and returned states — including deal prices, surcharges, quantity breaks, quote versioning, costs, involved_contacts, and a multi-currency deal
- Quote-to-cash: draft, paid, partial-with-refund-and-credit-note, deposit, pro-forma, and overdue invoices, plus billing runs and payments
- Sub-hire: a draft purchase order plus a sent/received one with confirmed virtual stock intake
- Flightcases, fleet vehicles and compliance, dispatch and returns workflows, generated and portal-approval documents, communication logs, webhooks, custom fields, and activities
All demo records are tagged demo-data so they can be identified and cleared later. This seeder is not included in the default DatabaseSeeder. Use the Artisan commands below or the admin panel.
# Seed demo data
php artisan signals:seed-demo
# Remove demo data (deletes all records tagged 'demo-data')
php artisan signals:clear-demo
Note: Running
DemoDataSeedermultiple times will create duplicate warehouses and accounts. Usesignals:clear-demobefore re-seeding.
VolumeTestSeeder
A load and performance testing tool, not an end-user demo, and hidden from the admin panel unless SIGNALS_VOLUME_SEEDER=true. It bulk-inserts 2,000 companies, 500 venues, and 3,000 contacts (configurable on the seeder class) with emails, phones, and relationships, to exercise list pagination, search, and N+1 behaviour. Records are tagged volume-test and are removed by signals:clear-demo alongside demo data.
Running Seeders
# Run all default seeders
php artisan db:seed
# Run a specific seeder
php artisan db:seed --class=PermissionSeeder
php artisan db:seed --class=ViewSeeder
# Run in production (requires --force flag)
php artisan db:seed --force
php artisan db:seed --class=PermissionSeeder --force
You can also run seeders from the admin panel under Settings > System > Database Seeders, which shows the current status of each seeder and lets you run them individually.
Idempotency
Almost every seeder uses updateOrCreate, firstOrCreate, upsert, or findOrCreate and is safe to run repeatedly:
- CountrySeeder —
updateOrCreateoncode - LanguageSeeder / LanguageTranslationSeeder —
updateOrCreateoncode; strings upserted without overwriting existing translations - ListsSeeder —
updateOrCreateon list and entry name - CurrencySeeder —
upsertoncode - ExchangeRateSeeder —
updateOrCreateon currency pair and effective date - WarehouseSeeder — no-op once any warehouse exists
- TaxTypeSeeder / TaxCategorySeeder / TaxRateSeeder —
updateOrCreateonnameorslug - TaxZoneSeeder —
updateOrCreateonslug, memberships re-synced - TaxRuleSeeder / TaxZoneRuleSeeder —
updateOrCreateon the rule's matching keys - RevenueGroupSeeder / CostGroupSeeder / CatalogueItemGroupSeeder —
updateOrCreateonname - PermissionSeeder —
Permission::findOrCreate() - RoleSeeder —
Role::findOrCreate()andsyncPermissions() - DispatchStageSeeder / ReturnStageSeeder —
updateOrCreateonkey - EmailLayoutSeeder —
updateOrCreateonkey; never overwrites an edited body - EmailTemplateSeeder —
updateOrCreateonkey - NotificationTypeSeeder —
syncToDatabase()via the registry, preserving preferences - DocumentTemplateSeeder / CommunicationTemplateSeeder —
firstOrCreateon warehouse + slug - ViewSeeder —
updateOrCreateon name + entity type - RateSpecificationPresetSeeder —
updateOrCreateonpreset_slug - DiscountCategorySeeder / PriceCategorySeeder —
updateOrCreateonname - CatalogueItemSeeder —
firstOrCreateonsku - ReportSeeder —
firstOrNewonkey; restores a missing or soft-deleted system report - ActivitySeeder — no-op; safe to run at any time
- DemoDataSeeder — not idempotent; use
signals:clear-demobefore re-seeding - VolumeTestSeeder — not idempotent; use
signals:clear-demobefore re-seeding