hashtagcms / invoice
Configurable, driver-based PDF invoice generation for Laravel and HashtagCMS
v1.0.0
2026-11-09 13:25 UTC
Requires
- php: ^8.3
- ext-json: *
- illuminate/console: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/database: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/filesystem: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/http: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/view: ^10.0 || ^11.0 || ^12.0 || ^13.0
Requires (Dev)
- bacon/bacon-qr-code: ^2.0 || ^3.0
- dompdf/dompdf: ^2.0 || ^3.0
- hashtagcms/hashtagcms: ^2.0.6 || ^3.0
- mockery/mockery: ^1.6
- orchestra/testbench: ^8.0 || ^9.0 || ^10.0 || ^11.0
- phpunit/phpunit: ^10.5 || ^11.0 || ^12.0
Suggests
- bacon/bacon-qr-code: Draws the UPI payment QR code on invoices that have a seller.upi id.
- barryvdh/laravel-dompdf: Installs dompdf/dompdf; any of the two satisfies the default PDF driver.
- dompdf/dompdf: Required by the default 'dompdf' PDF driver (already installed with barryvdh/laravel-dompdf).
- hashtagcms/hashtagcms: Enables the optional HashtagCMS admin module (Invoices menu, listing, settings).
Provides
None
Conflicts
None
Replaces
None
README
Configurable, driver-based PDF invoices for Laravel and HashtagCMS.
Nothing hardcoded. Numbers that never repeat. GST ready.
HashtagCMS Invoice (hashtagcms/invoice)
Why this package?
- Zero hardcoding. Currencies, symbols, decimals, date formats, numbering, paper, orientation, disks, templates, tax rules, rounding and labels all come from config, per-site admin settings, a profile, or a fluent setter. A missing setting raises an error that names the key; the package never invents a value in code.
- Money you can trust. Integer minor units, no float drift. Tax-inclusive or tax-exclusive prices, compound and fixed taxes, line and invoice discounts, five rounding modes, and a page that always adds up (
total = net + tax + shipping). - Safe numbering. A row-locked database counter plus a unique
(site, serial)index: two requests never get the same number. A number is only used after everything else succeeded, so a failed invoice never leaves a gap. - Pluggable. PDF drivers, templates, numbering, currency, tax rules and storage are all behind contracts; your own Eloquent models can be buyers and items.
🚀 Key Features
- Fluent builder and strict contracts:
Invoices::make()->buyer(...)->addItem(...)->download(), or pass your ownPartyContract/InvoiceItemContractobjects. - Document types: invoice, quotation, credit note, debit note, self invoice and an Indian GST tax invoice, each with its own number series (profiles).
- Automatic GST: IGST or CGST + SGST from the seller's and the place of supply's state, rate from the item, an HSN table or a default. It never guesses: missing information stops the invoice with a clear message.
- GST invoice layout: HSN, taxable value, tax per line, place of supply, shipping address, bank details, UPI QR, signature, the total in words (Indian lakh/crore numbering) and copy label.
- Any currency: symbol position, separators, decimals (0 to 8), unit names for the total in words; ₹ € £ ¥ print correctly in PDFs.
- HashtagCMS admin module: an Invoices menu with listing, a create form with live totals, PDF download, template previews, per-site settings and counter management.
- Records and re-rendering: every issued invoice is stored with a JSON snapshot and can be shown again exactly as issued.
- Multi-site, events, console commands, translations.
Install
composer require hashtagcms/invoice dompdf/dompdf php artisan migrate
Optional: composer require bacon/bacon-qr-code for the UPI QR code.
Quick start
use HashtagCms\Invoice\Facades\Invoices; use HashtagCms\Invoice\Data\{Buyer, InvoiceItem, Discount, Tax}; return Invoices::make() ->buyer(new Buyer(name: 'Acme Ltd', address: ['5 Buyer Lane', 'Buytown'], email: 'buy@acme.test')) ->currency('EUR') ->dueIn(14) ->addItem( InvoiceItem::make('Hosting') ->unitPrice(19.99)->quantity(3) ->discount(Discount::percent(10)) ->tax(Tax::percent('VAT', 21)) ) ->discount(Discount::fixed(5, 'Loyalty')) ->shipping(4.50) ->notes('Thank you!') ->download(); // or ->stream(), ->pdf(), ->save('s3'), ->persist()
Indian GST invoice, taxes worked out for you:
Invoices::make('gst') ->buyer(new Buyer(name: 'Priya Sharma', address: ['Pune, MAHARASHTRA, 411001'])) ->placeOfSupply('27-MAHARASHTRA') ->addItem(InvoiceItem::make('Wireless Headphones')->meta(['hsn' => '8518'])->unitPrice(4999)->quantity(2)) ->download(); // seller in Karnataka, buyer in Maharashtra: IGST 18%
Preview methods (totals(), preview(), html()) never use up an invoice number; the first output method (pdf, stream, download, save, persist) issues it once.
📚 Documentation
Full documentation lives in docs/:
| Guide | Topic |
|---|---|
| 01 Getting started | Install, first invoice, preview, records |
| 02 Architecture overview | Flow, principles, namespaces, contracts, tables |
| 03 Builder API | Every builder method, data object and event |
| 04 Calculation rules | Discounts, inclusive/exclusive tax, compound tax, rounding, worked example |
| 05 Configuration | Precedence, every config section, numbering, profiles, automatic taxes |
| 06 Templates and PDF | Templates, labels, languages, fonts, drivers, images |
| 07 Extending | Your own models, PDF driver, tax rule, contracts |
| 08 Admin module | The HashtagCMS Invoices menu, create form, settings, numbering |
| 09 Sales, purchases and GST | Credit/debit notes, self invoices, GST tax invoice, automatic GST |
| 10 Troubleshooting | Common errors and fixes |
| 11 Testing | Running the suite, what it covers |
Document types (profiles)
| Profile | Series | For |
|---|---|---|
invoice |
INV | sales invoices |
quotation |
QTN | quotes |
credit_note |
CN | refunds and corrections (allows negative totals) |
debit_note |
DN | extra charges, returns to a supplier |
self_invoice |
SI | you issue the invoice on a supplier's behalf (e.g. reverse charge) |
gst |
INV | Indian GST tax invoice (INR, gst template, automatic GST) |
Add your own under profiles in the config.
Extension points
| Contract | Default | Config key |
|---|---|---|
PdfDriverContract |
DompdfDriver, HtmlDriver |
pdf.drivers or Invoices::extend() |
SerialNumberGenerator |
DefaultSerialNumberGenerator |
serial.generator |
SequenceStore |
database | serial.store |
CurrencyResolver |
ConfigCurrencyResolver |
currency.resolver |
TemplateResolver |
ConfigTemplateResolver |
template.resolver |
TaxRule |
GstTaxResolver |
tax.rule, tax.rules |
InvoiceRepository |
EloquentInvoiceRepository |
persistence.repository |
SettingsStore |
database | settings.store |
Console
php artisan hashtagcms-invoice:install [--views] [--lang] [--force] php artisan make:invoice-template modern
Testing
composer install vendor/bin/phpunit
See docs/11-testing.md.
Contributing
Issues and pull requests are welcome. Please include a test with every change; the suite must stay green.
License
MIT


