Billing & Invoicing

Comprehensive billing and invoicing system for Larapen: manage invoices, payments, credit notes, recurring invoices, expenses, product catalog, and quote requests from a single admin panel.

Invoice Management

Create, send, and track invoices with line items, taxes, discounts, and automatic numbering.

Recurring Billing

Set up recurring invoices with flexible frequencies: weekly, monthly, quarterly, or annual.

Quote System

Receive quote requests from visitors, create proposals, and convert accepted quotes to invoices.

Expense Tracking

Track expenses by category with optional approval workflow and receipt uploads.

Credit Notes

Issue credit notes against invoices for refunds and adjustments with full audit trail.

PDF & Public Links

Generate PDF invoices and quotes. Share token-based public links for customers to view and pay.

Use Cases

Freelancer / Consultant

You run a portfolio site on Larapen and need to invoice clients for completed work.

  • Create customers for each client with billing addresses and payment terms.
  • Add your services to the product catalog (e.g. “Web Development: hourly”).
  • Create invoices, attach line items, and send via email with a public payment link.
  • Track payments and generate PDF receipts.

Agency with Retainer Clients

You manage multiple clients on monthly retainers and need automated recurring billing.

  • Set up recurring invoices for each retainer client with monthly frequency.
  • Invoices are generated automatically and optionally sent to the client.
  • Track outstanding balances and overdue invoices from the billing dashboard.

Service Business with Custom Quotes

Potential clients submit quote requests through your website before engagement.

  • Embed the quote request form on your front-end with categories (e.g. “Web Design”, “SEO”).
  • Review requests in the admin panel and create detailed proposals.
  • Send the quote via email with a public link. Once accepted, convert to an invoice.

Small Business with Expense Tracking

You need a simple way to track business expenses alongside revenue.

  • Organize expenses by category (Office, Travel, Software, etc.).
  • Upload receipts and optionally require manager approval.
  • View revenue vs. expenses on the billing dashboard.

Requirements

RequirementVersion
Larapen Core≥ 1.0.0
PHP≥ 8.2
DomPDFIncluded via barryvdh/laravel-dompdf
No dependencies. This add-on has no dependencies on other Larapen add-ons. It works standalone. However, if a payment gateway add-on (Stripe, PayPal, etc.) is active, invoices can be paid online.

Installation

Step 1: Place the Add-on

Copy or symlink the billing folder into extensions/addons/billing.

Step 2: Activate the Add-on

Go to Admin → Add-ons and activate “Billing & Invoicing”.

Step 3: Run Migrations

Step 4: Set Permissions

Assign billing permissions to admin roles under Admin → Users → Roles & Permissions.

Step 5: Configure

Go to Admin → Billing → Settings to configure company details, invoice numbering, tax settings, and notification preferences.

Configuration

All configuration lives in config/billing.php and can be overridden via the admin settings panel (stored in the database via SettingService).

KeyDefaultDescription
admin_per_page15Items per page in admin listings
invoice_prefixINV-Prefix for auto-generated invoice numbers
invoice_next_number1Next invoice sequence number
payment_terms_days30Default payment terms in days
credit_note_prefixCN-Prefix for credit note numbers
credit_note_next_number1Next credit note sequence number
company_nameYour company name (appears on invoices)
company_addressCompany address for invoices
company_phoneCompany phone number
company_emailCompany email address
company_tax_numberTax/VAT number shown on invoices
tax_enabledtrueEnable tax calculations
default_tax_rate_idnullDefault tax rate to apply to new items
recurring_enabledtrueEnable recurring invoices feature
recurring_auto_sendfalseAuto-send generated recurring invoices
expenses_enabledtrueEnable expense tracking feature
expenses_require_approvalfalseRequire approval for new expenses
pdf_logoPath to logo image for PDF documents
pdf_footer_textCustom footer text on PDF documents

Notification Settings

KeyDefaultDescription
notify_invoice_senttrueNotify customer when invoice is sent
notify_payment_receivedtrueNotify customer when payment recorded
notify_invoice_overduetrueNotify customer when invoice becomes overdue
notify_recurring_generatedtrueNotify admin when recurring invoice generates
notify_credit_note_issuedtrueNotify customer when credit note issued

Quote Settings

KeyDefaultDescription
quote_validity_days30Default validity period for quotes
quote_per_page12Items per page on front-end quote listing
quote_admin_per_page15Items per page in admin quote listings
allowed_attachment_typespdf, doc, docx, xls, xlsx, jpg, jpeg, pngAllowed file types for quote request attachments
max_attachment_size10240Max attachment size in KB
notify_new_quote_requesttrueNotify admin on new quote request
notify_quote_submission_confirmationtrueSend confirmation to requester
notify_quote_request_reviewingtrueNotify requester when status changes to reviewing
notify_quote_senttrueNotify requester when quote is sent
notify_quote_request_acceptedtrueNotify requester when request accepted
notify_quote_request_rejectedtrueNotify requester when request rejected

Admin: Dashboard

The billing dashboard (/admin/billing) provides an at-a-glance overview of your financial status.

Summary Cards

  • Total Revenue: sum of all paid invoices
  • Outstanding: total balance due across unpaid invoices
  • Overdue: total from invoices past due date
  • Total Expenses: sum of all approved expenses
  • Invoice Count: total invoices created
  • Customer Count: total customers
  • Payments This Month: payment total for the current month

Revenue Chart

A 12-month bar chart showing monthly revenue trends.

Activity Panels

  • Recent Invoices: latest invoices with status badges
  • Recent Payments: latest payment entries
  • Overdue Invoices: invoices past their due date
  • Upcoming Recurring: recurring invoices due to generate soon

Admin: Customers

Manage billing customers at /admin/billing/customers. Customers can optionally be linked to a Larapen user account.

Customer Fields

FieldRequiredDescription
company_nameNoCompany or organization name
contact_nameYesPrimary contact person
contact_emailYesEmail for invoice delivery
contact_phoneNoPhone number
tax_numberNoTax/VAT number
websiteNoCustomer website URL
billing_addressNoJSON object with address fields
shipping_addressNoJSON object with address fields
default_currencyYesDefault currency code (e.g. USD)
payment_terms_daysYesPayment terms (default: 30 days)
notesNoInternal notes about this customer

Customer Detail

The customer detail page (/admin/billing/customers/{id}) shows:

  • Customer information and contact details
  • Statistics: total invoiced, total paid, outstanding balance
  • List of all invoices for this customer

Admin: Products

The product catalog (/admin/billing/products) stores reusable line items for invoices. Products are managed via modal dialogs (no separate create/edit pages).

FieldRequiredDescription
nameYesProduct name (translatable)
descriptionNoProduct description (translatable)
skuNoStock Keeping Unit (unique)
typeYesproduct or service
unit_priceYesDefault unit price
unitNoUnit of measure (hrs, pcs, kg, etc.)
currencyYesCurrency code
tax_rate_idNoDefault tax rate for this product

Available unit options: Unit, Pcs, Hrs, Days, Months, Kg, G, L, ML, M, Km, Box, Pack, Set, Service, Lot.

Admin: Tax Rates

Configure tax rates at /admin/billing/tax-rates. Tax rates are managed via modal dialogs.

FieldRequiredDescription
nameYesTax rate name (translatable), e.g. “VAT 20%”
rateYesPercentage rate (decimal, e.g. 20.0000)
is_compoundNoWhether this tax compounds on other taxes
is_defaultNoSet as the default tax rate for new items

Admin: Invoices

The invoice management center at /admin/billing/invoices. Invoices can be filtered by customer, status, and searched by number or content.

Creating an Invoice

Navigate to Billing → Invoices → Create. The invoice form includes:

  • Customer: select from existing customers
  • Currency: defaults to customer’s currency
  • Issue date and Due date: due date auto-calculated from payment terms
  • Line items: add from product catalog or enter custom items. Each item has: description (translatable), quantity, unit, unit price, tax rate
  • Discount: optional percentage or fixed amount discount
  • Notes and Terms: translatable text fields

Invoice numbers are auto-generated using the configured prefix and sequence number (e.g. INV-0001).

Invoice Lifecycle

StatusDescription
draftInvoice is being prepared. Can be edited freely.
sentInvoice has been sent to the customer. No longer editable.
partialPartial payment has been received.
paidInvoice has been fully paid.
overdueInvoice is past its due date and unpaid.
cancelledInvoice has been cancelled.
refundedInvoice payment has been refunded (via credit note).
Editing restriction: Invoices can only be edited while in draft status. Once sent, the invoice is locked.

Available Actions

  • Send: marks as sent + emails the customer with a public link
  • Update Status: manually change the invoice status
  • Duplicate: creates a copy as a new draft invoice
  • Download PDF: generates and streams a PDF
  • From Quote: convert an accepted quote into an invoice (creates customer if needed)

PDF Generation

PDF invoices are generated using InvoicePdfService with DomPDF. The PDF includes:

  • Company logo and details (from settings)
  • Customer billing information
  • Line items table with quantities, prices, tax, and totals
  • Subtotal, tax, discount, and grand total
  • Notes and terms
  • Custom footer text

Admin: Payments

Record payments at /admin/billing/payments. Payments are linked to invoices and automatically update the invoice balance.

FieldRequiredDescription
invoice_idYesThe invoice this payment applies to
amountYesPayment amount
currencyYesPayment currency
payment_methodYesCash, Bank Transfer, Check, Credit Card, PayPal, Stripe, or Other
referenceNoTransaction reference number
payment_dateYesDate the payment was received
notesNoInternal notes

When a payment is recorded, the invoice’s amount_paid and balance_due are recalculated. If the balance reaches zero, the invoice is automatically marked as paid.

Admin: Credit Notes

Manage credit notes at /admin/billing/credit-notes. Credit notes are linked to an existing invoice and customer.

Credit Note Lifecycle

StatusDescription
draftCredit note is being prepared.
issuedCredit note has been issued to the customer.
appliedCredit has been applied to reduce the customer’s balance.
voidCredit note has been voided.

Each credit note has its own line items (description, quantity, unit price, tax rate) and an auto-generated number using the configured prefix (e.g. CN-0001).

PDF generation is available for credit notes using the same InvoicePdfService.

Admin: Recurring Invoices

Set up recurring billing at /admin/billing/recurring-invoices.

Recurring Invoice Fields

FieldRequiredDescription
customer_idYesCustomer to bill
titleYesTemplate title
frequencyYesWeekly, Monthly, Quarterly, Semi-Annual, or Annual
intervalYesMultiplier (e.g. 2 = every 2 months)
start_dateYesWhen recurring starts
next_invoice_dateYesNext generation date
end_dateNoWhen to stop (null = unlimited)
occurrences_limitNoMax invoices to generate (null = unlimited)
auto_sendNoAuto-send generated invoices
itemsYesLine items stored as JSON

How It Works

  • A scheduled command runs daily at 06:00 and checks for recurring invoices where next_invoice_date ≤ today.
  • For each due recurring invoice, a new BillingInvoice is created from the template items.
  • The next_invoice_date is advanced based on the frequency and interval.
  • If auto_send is enabled, the invoice is immediately marked as sent and the customer is notified.
  • Generation stops when end_date is reached or occurrences_limit is met.

You can also manually trigger generation via the Generate Now button on a recurring invoice’s detail page.

Admin: Expenses

Track business expenses at /admin/billing/expenses. Expenses are managed via modal dialogs.

FieldRequiredDescription
category_idNoExpense category
vendorNoVendor or supplier name
referenceNoReference/receipt number
amountYesExpense amount
currencyYesCurrency code
expense_dateYesDate of expense
notesNoDescription or notes
receiptNoReceipt file upload

Expense Statuses

StatusDescription
pendingAwaiting approval (when approval is required)
approvedExpense has been approved
rejectedExpense has been rejected
Approval workflow: When expenses_require_approval is enabled in settings, new expenses start as pending. An admin with billing.expenses.edit permission can approve or reject them.

Expense Categories

Organize expenses by category at /admin/billing/expense-categories. Categories have a translatable name and description, and can be activated/deactivated.

Admin: Quote System

The quote system handles the full lifecycle from customer request to accepted proposal to invoice.

Quote Requests

View and manage incoming quote requests at /admin/billing/quotes/requests.

Request Fields

FieldDescription
reference_numberAuto-generated unique reference (e.g. QR-0001)
category_idOptional category (from the unified categories table)
company_nameRequester’s company
contact_nameRequester’s name
contact_emailRequester’s email
titleProject title (translatable)
descriptionProject description (translatable)
requirementsDetailed requirements (translatable)
budget_min / budget_maxBudget range
timelineExpected timeline
priorityLow, Normal, High, or Urgent
attachmentOptional file attachment

Request Statuses

StatusDescription
pendingNew request awaiting review
reviewingRequest is being reviewed
quotedA quote has been sent
acceptedRequest/quote accepted by requester
rejectedRequest declined
cancelledRequest cancelled

Quote Proposals

Create proposals at /admin/billing/quotes/quotes. Each quote is linked to a quote request.

Quote Fields

FieldDescription
quote_numberAuto-generated unique number
request_idLinked quote request
titleQuote title (translatable)
scopeScope of work (translatable)
termsTerms and conditions (translatable)
itemsLine items with description, quantity, unit, unit price
amountTotal quote amount
currencyCurrency code
valid_untilQuote expiration date

Quote Statuses

StatusDescription
draftQuote is being prepared
sentQuote sent to requester with public link
acceptedQuote accepted: can be converted to invoice
rejectedQuote rejected by requester
expiredQuote validity period has passed
Quote → Invoice: Once a quote is accepted, use the “Create Invoice from Quote” action to automatically generate an invoice with all the quote’s line items. If the requester isn’t an existing billing customer, one is created automatically.

Quote Categories

Manage quote categories at /admin/billing/quotes/categories. These are standard category entries from the unified categories table, scoped to quote requests. Categories appear on the public quote request form.

Admin: Settings

All billing settings are managed at /admin/billing/settings. The settings form is grouped into sections:

  • Company Information: name, address, phone, email, tax number
  • Invoice Settings: prefix, next number, payment terms
  • Credit Note Settings: prefix, next number
  • Tax Settings: enable/disable, default tax rate
  • Recurring Settings: enable/disable, auto-send
  • Expense Settings: enable/disable, require approval
  • Quote Settings: validity days, attachments, per-page
  • PDF Settings: logo, footer text
  • Notifications: toggle each notification type on/off

Settings are stored in the database via the SettingService (prefixed with billing_) and cached for performance.

Front-end: Quote Request Form

URL & Routes

RouteURLDescription
front.billing.quotes.index/quote-requests/newDisplay quote request form
front.billing.quotes.submitPOST /quote-requests/submitSubmit quote request

Localized variants are also registered (e.g. /fr/quote-requests/new).

Form Fields

Visitors can fill out the following fields:

  • Contact info: name, email, phone, company name
  • Category: select from configured quote categories
  • Project details: title, description, requirements (translatable)
  • Budget: minimum and maximum range with currency
  • Timeline: expected project timeline
  • Priority: Low, Normal, High, or Urgent
  • Attachment: optional file upload (validated against allowed types and max size)

After Submission

  • A BillingQuoteRequest record is created with a unique reference number.
  • The admin receives a NewQuoteRequestNotification (if enabled).
  • The requester receives a QuoteSubmissionConfirmationNotification (if enabled).
  • The visitor’s IP address is recorded.
Menu integration: The add-on provides a front_menu entry in addon.json with the label “Get a Quote” and route front.billing.quotes.index. This can be added to any navigation menu.

Front-end: Public Invoice View

URL & Routes

RouteURLDescription
front.billing.invoice.show/billing/invoice/{token}View invoice (public, no auth required)
front.billing.invoice.pdf/billing/invoice/{token}/pdfDownload PDF

Each invoice has a unique 64-character public_token generated on creation. This token is included in the email sent to the customer, allowing them to view and download the invoice without logging in.

The public view displays: company details, customer details, line items, totals, payment status, and notes/terms.

Front-end: Public Quote View

URL & Routes

RouteURLDescription
front.billing.quote.show/billing/quote/{token}View quote (public, no auth required)
front.billing.quote.pdf/billing/quote/{token}/pdfDownload PDF

Quotes also have a unique public_token. The public view shows: scope of work, line items, total amount, validity period, and terms.

Front-end: Online Payment

URL & Routes

RouteURLDescription
front.billing.invoice.checkout/billing/invoice/{token}/payPayment checkout page
front.billing.invoice.payPOST /billing/invoice/{token}/payProcess payment

The BillingInvoice model implements the Payable contract, making it compatible with any payment gateway add-on (Stripe, PayPal, etc.). The contract provides:

  • getPayableAmount(): returns the balance due
  • getPayableDescription(): invoice number and description
  • getPayableCurrency(): invoice currency
  • getPayableCustomerEmail(): customer email
  • getPayableCustomerName(): customer display name
  • getPayableUserId(): linked user ID (if any)
  • getPayableIdentifier(): unique identifier for the payment
  • getPaymentSuccessUrl(): redirect URL after successful payment
  • getPaymentCancelUrl(): redirect URL after cancelled payment

When payment succeeds, the invoice’s markAsPaid() method is called. On failure, markPaymentFailed() is called.

Notifications

The add-on includes 11 notification classes, all in Addons\Billing\Notifications:

Invoice & Payment Notifications

NotificationRecipientTrigger
InvoiceSentNotificationCustomerInvoice marked as sent
PaymentReceivedNotificationCustomer / AdminPayment recorded
InvoiceOverdueNotificationCustomerInvoice becomes overdue (via scheduled command)
RecurringInvoiceGeneratedNotificationAdminRecurring invoice generates a new invoice
CreditNoteIssuedNotificationCustomerCredit note issued

Quote Notifications

NotificationRecipientTrigger
NewQuoteRequestNotificationAdminNew quote request submitted
QuoteSubmissionConfirmationNotificationRequesterAfter form submission
QuoteRequestReviewingNotificationRequesterStatus changed to “reviewing”
QuoteSentNotificationRequesterQuote sent with public link
QuoteRequestAcceptedNotificationRequesterRequest accepted
QuoteRequestRejectedNotificationRequesterRequest rejected

Each notification can be individually toggled on/off in Billing → Settings.

Updating

Step 1: Replace Files

Replace the billing folder in extensions/addons/ with the new version.

Step 2: Run Migrations

Step 3: Clear Caches

Step 4: Verify

  • Check that all billing pages load correctly in the admin panel.
  • Verify the dashboard statistics are accurate.
  • Test creating a new invoice and generating a PDF.
  • Check that scheduled commands still run correctly.

Troubleshooting

Invoice PDF fails to generate

  • Ensure barryvdh/laravel-dompdf is installed: composer require barryvdh/laravel-dompdf.
  • Check that the PDF logo path (in settings) points to a valid image file.
  • Verify the storage directory is writable.

Recurring invoices not generating

  • Ensure the Laravel scheduler is running: * * * * * cd /path-to-project && php artisan schedule:run >> /dev/null 2>&1
  • Check that the recurring invoice is active (is_active = true).
  • Verify next_invoice_date is not in the future.
  • Check end_date and occurrences_limit haven’t been reached.
  • Run manually to debug: php artisan billing:generate-recurring

Overdue notifications not sent

  • Check that notify_invoice_overdue is enabled in billing settings.
  • Verify the invoice status is sent or partial (only these statuses transition to overdue).
  • Check mail configuration in .env (SMTP settings).
  • Run manually to debug: php artisan billing:check-overdue

Online payment not available

  • At least one payment gateway add-on (Stripe, PayPal, etc.) must be installed and active.
  • The invoice must implement the Payable contract (built-in).
  • The invoice must have a balance_due > 0 and a valid public_token.

Quote request form not visible

  • Ensure the billing add-on is activated.
  • Check that the route front.billing.quotes.index is accessible.
  • If using a menu link, verify the menu item points to the correct route.

Customer not linked to user account

  • The user_id field on billing customers is optional.
  • When converting a quote to an invoice, a new billing customer is created automatically if one doesn’t exist for the requester.
  • You can manually link a customer to a user via the customer edit form.

Tax calculations seem incorrect

  • Tax is calculated per line item, not on the invoice total.
  • Verify the correct tax rate is assigned to each line item.
  • Check if compound tax rates are being used correctly: compound taxes apply on top of other taxes.
  • Ensure tax_enabled is set to true in billing settings.

Was this article helpful?

Thank you for your feedback!

Still need help? Create a support ticket

Create a Ticket