{"id":27145454,"url":"https://github.com/elegantengineeringtech/laravel-invoices","last_synced_at":"2026-02-10T19:08:29.438Z","repository":{"id":63091985,"uuid":"527661364","full_name":"ElegantEngineeringTech/laravel-invoices","owner":"ElegantEngineeringTech","description":"📑 Store and generate beautiful PDF invoices in Laravel","archived":false,"fork":false,"pushed_at":"2026-01-12T11:55:32.000Z","size":359,"stargazers_count":223,"open_issues_count":1,"forks_count":25,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-01-12T19:27:40.804Z","etag":null,"topics":["invoice-generator","invoices","invoices-pdf","laravel","pdf","php"],"latest_commit_sha":null,"homepage":"https://elegantly.dev/laravel-invoices","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ElegantEngineeringTech.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-08-22T17:13:48.000Z","updated_at":"2026-01-12T11:55:29.000Z","dependencies_parsed_at":"2023-09-28T21:07:03.146Z","dependency_job_id":"f2d564f1-91fc-4a05-8160-43c474b00fcd","html_url":"https://github.com/ElegantEngineeringTech/laravel-invoices","commit_stats":{"total_commits":99,"total_committers":5,"mean_commits":19.8,"dds":"0.43434343434343436","last_synced_commit":"5424edc3ddb05ad4e7aa35ab9e10e8a0aef01b75"},"previous_names":["elegantengineeringtech/laravel-invoices","finller/laravel-invoices"],"tags_count":86,"template":false,"template_full_name":"spatie/package-skeleton-laravel","purl":"pkg:github/ElegantEngineeringTech/laravel-invoices","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElegantEngineeringTech%2Flaravel-invoices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElegantEngineeringTech%2Flaravel-invoices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElegantEngineeringTech%2Flaravel-invoices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElegantEngineeringTech%2Flaravel-invoices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ElegantEngineeringTech","download_url":"https://codeload.github.com/ElegantEngineeringTech/laravel-invoices/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElegantEngineeringTech%2Flaravel-invoices/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29313094,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T17:48:59.043Z","status":"ssl_error","status_checked_at":"2026-02-10T17:45:37.240Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["invoice-generator","invoices","invoices-pdf","laravel","pdf","php"],"created_at":"2025-04-08T09:48:31.136Z","updated_at":"2026-02-10T19:08:29.426Z","avatar_url":"https://github.com/ElegantEngineeringTech.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Everything You Need to Manage Invoices in Laravel\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/elegantly/laravel-invoices.svg?style=flat-square)](https://packagist.org/packages/elegantly/laravel-invoices)\n[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/ElegantEngineeringTech/laravel-invoices/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square)](https://github.com/ElegantEngineeringTech/laravel-invoices/actions?query=workflow%3Arun-tests+branch%3Amain)\n[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/ElegantEngineeringTech/laravel-invoices/fix-php-code-style-issues.yml?branch=main\u0026label=code%20style\u0026style=flat-square)](https://github.com/ElegantEngineeringTech/laravel-invoices/actions?query=workflow%3A\"Fix+PHP+code+style+issues\"+branch%3Amain)\n[![Total Downloads](https://img.shields.io/packagist/dt/elegantly/laravel-invoices.svg?style=flat-square)](https://packagist.org/packages/elegantly/laravel-invoices)\n\nThis package provides a robust, easy-to-use system for managing invoices within a Laravel application, with options for database storage, serial numbering, and PDF generation.\n\n![laravel-invoices](https://repository-images.githubusercontent.com/527661364/f98e92f9-62a6-48a1-a7b1-1a587b92a430)\n\n## Interactive Demo\n\nTry out [the interactive demo](https://elegantly.dev/laravel-invoices) to explore package capabilities.\n\n## Table of Contents\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [The `PdfInvoice` Class](#the-pdfinvoice-class)\n    - [Full Example](#full-example)\n    - [Rendering the Invoice as a PDF](#rendering-the-invoice-as-a-pdf)\n    - [Storing the PDF in a file](#storing-the-pdf-in-a-file)\n    - [Downloading the Invoice as a PDF](#downloading-the-invoice-as-a-pdf)\n        - [From a controller](#from-a-controller)\n        - [From a Livewire component](#from-a-livewire-component)\n    - [Rendering the Invoice as a view](#rendering-the-invoice-as-a-view)\n    - [Rendering the Invoice within a View](#rendering-the-invoice-within-a-view)\n    - [Adding Taxes](#adding-taxes)\n        - [Tax by Percentage](#tax-by-percentage)\n        - [Tax as a Fixed Amount](#tax-as-a-fixed-amount)\n    - [Adding Discounts](#adding-discounts)\n        - [Discount by Percentage](#discount-by-percentage)\n        - [Discount as a Fixed Amount](#discount-as-a-fixed-amount)\n    - [Adding Payment Instructions](#adding-payment-instructions)\n        - [QR Code Generation](#qr-code-generation)\n    - [Customization](#customization)\n        - [Customizing Fonts](#customizing-fonts)\n        - [Customizing the Invoice Template](#customizing-the-invoice-template)\n- [The `Invoice` Eloquent Model](#the-invoice-eloquent-model)\n    - [Complete Example](#complete-example)\n    - [Generating Unique Serial Numbers](#generating-unique-serial-numbers)\n    - [Using Multiple Prefixes and Series for Serial Numbers](#using-multiple-prefixes-and-series-for-serial-numbers)\n    - [Customizing the Serial Number Format](#customizing-the-serial-number-format)\n    - [Storing the Logo](#storing-the-logo)\n    - [Storing a Dynamic Logo](#storing-a-dynamic-logo)\n    - [Converting an `Invoice` Model to a `PdfInvoice`](#converting-an-invoice-model-to-a-pdfinvoice)\n    - [Display, Download, and Store Invoices](#display-download-and-store-invoices)\n    - [Attaching Invoices to Mailables](#attaching-invoices-to-mailables)\n    - [Attaching Invoices to Notifications](#attaching-invoices-to-notifications)\n    - [Customizing PDF Output from the Model](#customizing-pdf-output-from-the-model)\n        - [Using a Custom PdfInvoice Class](#using-a-custom-pdfinvoice-class)\n    - [Casting `state` and `type` to Enums](#casting-state-and-type-to-enums)\n- [Testing](#testing)\n- [Changelog](#changelog)\n- [Contributing](#contributing)\n- [Security Vulnerabilities](#security-vulnerabilities)\n- [Credits](#credits)\n- [License](#license)\n\n## Requirements\n\n- PHP 8.1+\n- Laravel 11.0+\n- `dompdf/dompdf` for PDF rendering\n- `elegantly/laravel-money` for money computation which use `brick\\money` under the hood\n\n## Installation\n\nYou can install the package via composer:\n\n```bash\ncomposer require elegantly/laravel-invoices\n```\n\nIf you intent to store your invoices using the Eloquent Model, you must publish and run the migrations with:\n\n```bash\nphp artisan vendor:publish --tag=\"invoices-migrations\"\nphp artisan migrate\n```\n\nYou can publish the config file with:\n\n```bash\nphp artisan vendor:publish --tag=\"invoices-config\"\n```\n\nThis is the contents of the published config file:\n\n```php\nuse Elegantly\\Invoices\\Models\\Invoice;\nuse Elegantly\\Invoices\\InvoiceDiscount;\nuse Elegantly\\Invoices\\Models\\InvoiceItem;\nuse Elegantly\\Invoices\\Enums\\InvoiceType;\n\nreturn [\n\n    'model_invoice' =\u003e Invoice::class,\n    'model_invoice_item' =\u003e InvoiceItem::class,\n\n    'discount_class' =\u003e InvoiceDiscount::class,\n\n    'cascade_invoice_delete_to_invoice_items' =\u003e true,\n\n    'serial_number' =\u003e [\n        /**\n         * If true, will generate a serial number on creation\n         * If false, you will have to set the serial_number yourself\n         */\n        'auto_generate' =\u003e true,\n\n        /**\n         * Define the serial number format used for each invoice type\n         *\n         * P: Prefix\n         * S: Serie\n         * M: Month\n         * Y: Year\n         * C: Count\n         * Example: IN0012-220234\n         * Repeat letter to set the length of each information\n         * Examples of formats:\n         * - PPYYCCCC : IN220123 (default)\n         * - PPPYYCCCC : INV220123\n         * - PPSSSS-YYCCCC : INV0001-220123\n         * - SSSS-CCCC: 0001-0123\n         * - YYCCCC: 220123\n         */\n        'format' =\u003e 'PPYYCCCC',\n\n        /**\n         * Define the default prefix used for each invoice type\n         */\n        'prefix' =\u003e [\n            InvoiceType::Invoice-\u003evalue =\u003e 'IN',\n            InvoiceType::Quote-\u003evalue =\u003e 'QO',\n            InvoiceType::Credit-\u003evalue =\u003e 'CR',\n            InvoiceType::Proforma-\u003evalue =\u003e 'PF',\n        ],\n\n    ],\n\n    'date_format' =\u003e 'Y-m-d',\n\n    'default_seller' =\u003e [\n        'company' =\u003e null,\n        'name' =\u003e null,\n        'address' =\u003e [\n            'street' =\u003e null,\n            'city' =\u003e null,\n            'postal_code' =\u003e null,\n            'state' =\u003e null,\n            'country' =\u003e null,\n        ],\n        'email' =\u003e null,\n        'phone' =\u003e null,\n        'tax_number' =\u003e null,\n        'fields' =\u003e [\n            //\n        ],\n    ],\n\n    /**\n     * ISO 4217 currency code\n     */\n    'default_currency' =\u003e 'USD',\n\n    'pdf' =\u003e [\n\n        'paper' =\u003e [\n            'size' =\u003e 'a4',\n            'orientation' =\u003e 'portrait',\n        ],\n\n        /**\n         * Default DOM PDF options\n         *\n         * @see Available options https://github.com/barryvdh/laravel-dompdf#configuration\n         */\n        'options' =\u003e [\n            'isRemoteEnabled' =\u003e true,\n            'isPhpEnabled' =\u003e false,\n            'fontHeightRatio' =\u003e 1,\n            /**\n             * Supported values are: 'DejaVu Sans', 'Helvetica', 'Courier', 'Times', 'Symbol', 'ZapfDingbats'\n             */\n            'defaultFont' =\u003e 'Helvetica',\n\n            'fontDir' =\u003e storage_path('fonts'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)\n            'fontCache' =\u003e storage_path('fonts'),\n            'tempDir' =\u003e sys_get_temp_dir(),\n            'chroot' =\u003e realpath(base_path()),\n        ],\n\n        /**\n         * The logo displayed in the PDF\n         */\n        'logo' =\u003e null,\n\n        /**\n         * The template used to render the PDF\n         */\n        'template' =\u003e 'default.layout',\n\n        'template_data' =\u003e [\n            /**\n             * The color displayed at the top of the PDF\n             */\n            'color' =\u003e '#050038',\n        ],\n\n    ],\n\n];\n```\n\n## The `PdfInvoice` Class\n\nThis package provides a powerful, standalone `PdfInvoice` class. Its main functionalities include the ability to:\n\n- Display your invoice as a PDF document.\n- Render your invoice within a Blade view.\n\nThe `PdfInvoice` class is also integrated with the `Invoice` Eloquent Model, allowing you to easily convert an `Invoice` model instance into its PDF representation.\n\nYou can even use this package exclusively for the `PdfInvoice` class if you don't require database storage for your invoices.\n\n### Full Example\n\n```php\nuse \\Elegantly\\Invoices\\Pdf\\PdfInvoice;\nuse \\Elegantly\\Invoices\\Pdf\\PdfInvoiceItem;\nuse \\Elegantly\\Invoices\\Support\\Seller;\nuse \\Elegantly\\Invoices\\Support\\Buyer;\nuse \\Elegantly\\Invoices\\Support\\Address;\nuse \\Elegantly\\Invoices\\Support\\PaymentInstruction;\nuse \\Elegantly\\Invoices\\InvoiceDiscount;\nuse Brick\\Money\\Money;\n\n$pdfInvoice = new PdfInvoice(\n    name: \"Invoice\",\n    state: \"paid\",\n    serial_number: \"INV-241200001\",\n    seller: new Seller(\n        company: 'elegantly',\n        name: 'Quentin Gabriele', // (optional)\n        address: new Address(\n            street: \"Place de l'Opéra\",\n            city: 'Paris',\n            postal_code: '75009',\n            country: 'France',\n        ),\n        email: 'john.doe@example.com',\n        tax_number: 'FR123456789',\n        fields: [\n            // Custom fields to display with the seller\n            \"foo\" =\u003e \"bar\"\n        ]\n    ),\n    buyer: new Buyer(\n        company: \"Doe Corporation\" // (optional)\n        name: 'John Doe', // (optional)\n        address: new Address(\n            street: '8405 Old James St.Rochester',\n            city: 'New York',\n            postal_code: '14609',\n            state: 'NY',\n            country: 'United States',\n        ),\n        shipping_address: new Address( // (optional)\n            street: [ // multiple lines street\n                '8405 Old James St.Rochester',\n                'Apartment 1',\n            ],\n            city: 'New York',\n            postal_code: '14609',\n            state: 'NY',\n            country: 'United States',\n        ),\n        email: 'john.doe@example.com',\n        fields: [\n            // Custom fields to display with the buyer\n            \"foo\" =\u003e \"bar\"\n        ]\n    ),\n    description: \"An invoice description\",\n    created_at: now(),\n    due_at: now(),\n    paid_at: now(),\n    tax_label: \"VAT France (20%)\",\n    fields: [ // custom fields to display at the top\n        'Order' =\u003e \"PO0234\"\n    ],\n    items: [\n        new PdfInvoiceItem(\n            label: \"Laratranslate Unlimitted\" ,\n            unit_price: Money::of(99.0, 'USD'),\n            tax_percentage: 20.0,\n            quantity: 1,\n            description: \"Elegant All-in-One Translations Manager for Laravel\",\n        ),\n    ],\n    discounts: [\n        new InvoiceDiscount(\n            name: \"Summer offer\",\n            code: \"SUMMER\",\n            percent_off: 50,\n        )\n    ],\n    paymentInstructions: [\n        new PaymentInstruction(\n            name: 'Bank Transfer',\n            description: 'Make a direct bank transfer using the details below.',\n            qrcode: 'data:image/png;base64,' . base64_encode(\n                file_get_contents(__DIR__.'/../resources/images/qrcode.png')\n            ),\n            fields: [\n                'Bank Name' =\u003e 'Acme Bank',\n                'Account Number' =\u003e '12345678',\n                'IBAN' =\u003e 'GB12ACME12345678123456',\n                'SWIFT/BIC' =\u003e 'ACMEGB2L',\n                'Reference' =\u003e 'INV-0032/001',\n                '\u003ca href=\"#\"\u003ePay online\u003c/a\u003e',\n            ],\n        ),\n    ],\n    logo: public_path('/images/logo.png'), // local path or base64 string\n    template: \"default.layout\", // use the default template or use your own\n    templateData: [ // custom data to pass to the template\n        'color' =\u003e '#050038'\n    ],\n);\n```\n\n### Rendering the Invoice as a PDF\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse Elegantly\\Invoices\\Pdf\\PdfInvoice;\n\nclass InvoiceController extends Controller\n{\n    public function showAsPdf()\n    {\n        $pdfInvoice = new PdfInvoice(\n            // ...\n        );\n\n        return $pdfInvoice-\u003estream();\n    }\n}\n```\n\n### Storing the PDF in a file\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse Elegantly\\Invoices\\Pdf\\PdfInvoice;\nuse Illuminate\\Support\\Facades\\Storage;\n\nclass InvoiceController extends Controller\n{\n    public function store()\n    {\n        $pdfInvoice = new PdfInvoice(\n            // ...\n        );\n\n        Storage::put(\n            \"path/to/{$pdfInvoice-\u003egetFilename()}\",\n            $pdfInvoice-\u003egetPdfOutput()\n        );\n\n        // ...\n    }\n}\n```\n\n### Downloading the Invoice as a PDF\n\n#### From a controller\n\nTo download the PDF, simply return the `download` method.\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse Elegantly\\Invoices\\Pdf\\PdfInvoice;\n\nclass InvoiceController extends Controller\n{\n    public function download()\n    {\n        $pdfInvoice = new PdfInvoice(\n            // ...\n        );\n\n        return $pdfInvoice-\u003edownload(\n            /**\n             * (optional)\n             * The default filename is the serial_number\n             */\n            filename: 'invoice.pdf'\n        );\n    }\n}\n```\n\n#### From a Livewire component\n\nTo download the PDF from a Livewire component, use the `streamDownload` method as shown below:\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse Elegantly\\Invoices\\Pdf\\PdfInvoice;\n\nclass Invoice extends Component\n{\n    public function download()\n    {\n        $pdfInvoice = new PdfInvoice(\n            // ...\n        );\n\n        return response()-\u003estreamDownload(function () use ($pdfInvoice) {\n            echo $pdf-\u003egetPdfOutput();\n        }, $pdf-\u003egetFilename()); // The default filename is the serial number\n    }\n}\n```\n\n### Rendering the Invoice as a view\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse Elegantly\\Invoices\\Pdf\\PdfInvoice;\n\nclass InvoiceController extends Controller\n{\n    public function showAsView()\n    {\n        $pdfInvoice = new PdfInvoice(\n            // ...\n        );\n\n        return $pdfInvoice-\u003eview();\n    }\n}\n```\n\n### Rendering the Invoice within a View\n\nYou can embed the invoice within a larger Blade view to create interfaces like an \"invoice builder,\" similar to the [interactive demo](https://elegantly.devlaravel-invoices).\n\nTo do this, include the main invoice partial in your view as shown below:\n\n```php\n\u003cdiv class=\"aspect-[210/297] bg-white shadow-md\"\u003e\n    @include('invoices::default.invoice', ['invoice' =\u003e $invoice])\n\u003c/div\u003e\n```\n\nThis approach allows for seamless integration of the invoice into a dynamic and customizable user interface.\n\n\u003e [!NOTE]  \n\u003e The default template uses Tailwind CSS for styling. This ensures seamless integration with websites already using Tailwind.\n\u003e If your project doesn't use Tailwind, the invoice styling may not appear as intended.\n\n### Adding Taxes\n\nTaxes are applied to individual `PdfInvoiceItem` item. You can define them either as a percentage or a fixed amount.\n\n#### Tax by Percentage\n\nTo add a tax as a percentage, set the `tax_percentage` property on the `PdfInvoiceItem`. This value should be a float between 0 and 100.\n\n```php\nuse \\Elegantly\\Invoices\\Pdf\\PdfInvoiceItem;\n\nnew PdfInvoiceItem(\n    label: \"Laratranslate Unlimitted\" ,\n    unit_price: Money::of(99.0, 'USD'),\n    tax_percentage: 20.0, // a float between 0.0 and 100.0\n),\n```\n\n#### Tax as a Fixed Amount\n\nTo apply a tax as a specific monetary amount, set the `unit_tax` property on the `PdfInvoiceItem`.\n\n```php\nuse \\Elegantly\\Invoices\\Pdf\\PdfInvoiceItem;\n\nnew PdfInvoiceItem(\n    label: \"Laratranslate Unlimitted\" ,\n    unit_price: Money::of(99.0, 'USD'),\n    unit_tax: Money::of(19.8, 'USD'),\n),\n```\n\n### Adding Discounts\n\nDiscounts are represented by the `InvoiceDiscount` class and are applied to the entire `PdfInvoice`. They cannot be attached to individual `PdfInvoiceItem`s at this time.\n\n- You can add multiple discounts to a single invoice.\n- Discounts can be specified as a fixed amount (`amount_off`) or a percentage (`percent_off`). If both are provided for the same discount, the `amount_off` value takes precedence.\n\n#### Discount by Percentage\n\nTo apply a discount as a percentage, set the `percent_off` property.\n\n```php\nuse \\Elegantly\\Invoices\\Pdf\\PdfInvoice;\nuse \\Elegantly\\Invoices\\InvoiceDiscount;\nuse Brick\\Money\\Money;\n\n$pdfInvoice = new PdfInvoice(\n    // ...\n    discounts: [\n        new InvoiceDiscount(\n            name: \"Summer offer\",\n            code: \"SUMMER\",\n            percent_off: 20.0,\n        )\n    ],\n);\n```\n\n#### Discount as a Fixed Amount\n\nTo apply a discount as a fixed amount, set the `amount_off` property.\n\n```php\nuse \\Elegantly\\Invoices\\Pdf\\PdfInvoice;\nuse \\Elegantly\\Invoices\\InvoiceDiscount;\nuse Brick\\Money\\Money;\n\n$pdfInvoice = new PdfInvoice(\n    // ...\n    discounts: [\n        new InvoiceDiscount(\n            name: \"Summer offer\",\n            code: \"SUMMER\",\n            amount_off: Money::of(20.0, 'USD'),\n        )\n    ],\n);\n```\n\n### Adding Payment Instructions\n\nYou can include detailed payment instructions directly within the generated PDF invoice. This can be helpful for providing bank transfer details, QR codes for quick payments, and custom payment links.\n\nHere’s an example of how to add a payment instruction:\n\n```php\nuse \\Elegantly\\Invoices\\Pdf\\PdfInvoice;\nuse \\Elegantly\\Invoices\\Support\\PaymentInstruction;\n\n$pdfInvoice = new PdfInvoice(\n    // ...\n    paymentInstructions: [\n        new PaymentInstruction(\n            name: 'Bank Transfer',\n            description: 'Make a direct bank transfer using the details below.',\n            qrcode: 'data:image/png;base64,' . base64_encode(\n                file_get_contents(__DIR__.'/../resources/images/qrcode.png')\n            ),\n            fields: [\n                'Bank Name' =\u003e 'Acme Bank',\n                'Account Number' =\u003e '12345678',\n                'IBAN' =\u003e 'GB12ACME12345678123456',\n                'SWIFT/BIC' =\u003e 'ACMEGB2L',\n                'Reference' =\u003e 'INV-0032/001',\n                '\u003ca href=\"#\"\u003ePay online\u003c/a\u003e',\n            ],\n        ),\n    ]\n);\n```\n\n\u003e **Note:** You can include HTML tags (e.g., links) within the `fields` array for interactive content.\n\n#### QR Code Generation\n\nTo dynamically generate QR codes, I recommend using the [`chillerlan/php-qrcode`](https://github.com/chillerlan/php-qrcode) package. It provides a simple and flexible API for generating QR codes in various formats.\n\n### Customization\n\n#### Customizing Fonts\n\nSee the [Dompdf font guide](https://github.com/dompdf/dompdf/wiki/About-Fonts-and-Character-Encoding).\n\n#### Customizing the Invoice Template\n\nTo customize the invoice template, first publish the package's views:\n\n```bash\nphp artisan vendor:publish --tag=\"invoices-views\"\n```\n\nAfter publishing, you can modify the Blade files in `resources/views/vendor/invoices/` to suit your needs.\n\n\u003e [!NOTE]\n\u003e If you introduce new CSS classes in your custom template, ensure you define their styles in the style.blade.php file.\n\nAlternatively, to use a completely different custom template, you can specify its path in the configuration file:\n\n\u003e [!WARNING]\n\u003e Your custom template file must be in `resources/views/vendor/invoices`\n\n```php\nreturn [\n\n    // ...\n\n    'pdf' =\u003e [\n\n        /**\n         * The template used to render the PDF\n         */\n        'template' =\u003e 'my-custom.layout',\n\n        'template_data' =\u003e [\n            /**\n             * The color displayed at the top of the PDF\n             */\n            'color' =\u003e '#050038',\n        ],\n\n    ],\n\n];\n```\n\nEnsure that your custom template follows the same structure and conventions as the default one to maintain compatibility with various use cases.\n\n## The `Invoice` Eloquent Model\n\nThe design of the `Invoice` Eloquent Model closely mirrors that of the `PdfInvoice` class.\n\nThis model provides powerful features for:\n\n- Generating unique and complex serial numbers.\n- Attaching your invoice to any other Eloquent model.\n- Easily including your invoice as an attachment in emails.\n\n\u003e [!NOTE]\n\u003e Remember to publish and run the database migrations\n\n### Complete Example\n\nThe following example demonstrates how to create and store an invoice.\n\nFor this illustration, let's assume the following application structure:\n\n- `Team` models have `User` models.\n- `Team` models can have multiple `Invoice` models.\n- `Invoice` models can be attached to `Order` models.\n\n```php\nuse App\\Models\\Team;\nuse App\\Models\\Order;\n\nuse Brick\\Money\\Money;\nuse Elegantly\\Invoices\\Models\\Invoice;\nuse Elegantly\\Invoices\\Enums\\InvoiceState;\nuse Elegantly\\Invoices\\Enums\\InvoiceType;\n\n$customer = Team::find(1);\n$order = Order::find(2);\n\n$invoice = new Invoice(\n    'type' =\u003e \"invoice\",\n    'state' =\u003e \"paid\",\n    'seller_information' =\u003e config('invoices.default_seller'),\n    'buyer_information' =\u003e[\n        'company' =\u003e \"Doe Corporation\" // (optional)\n        'name' =\u003e 'John Doe', // (optional)\n        'address' =\u003e [\n            'street' =\u003e '8405 Old James St.Rochester',\n            'city' =\u003e 'New York',\n            'postal_code' =\u003e '14609',\n            'state' =\u003e 'NY',\n            'country' =\u003e 'United States',\n        ],\n        'shipping_address' =\u003e [ // (optional)\n            'street' =\u003e [ // multiple lines street\n                '8405 Old James St.Rochester',\n                'Apartment 1',\n            ],\n            'city' =\u003e 'New York',\n            'postal_code' =\u003e '14609',\n            'state' =\u003e 'NY',\n            'country' =\u003e 'United States',\n        ]\n        'email' =\u003e 'john.doe@example.com',\n        'fields' =\u003e [\n            // Custom fields to display with the buyer\n            \"foo\" =\u003e \"bar\"\n        ]\n    ],\n    'description' =\u003e \"An invoice description\",\n    'due_at' =\u003e now(),\n    'paid_at' =\u003e now(),\n    'tax_type' =\u003e \"eu_VAT_FR\",\n    'tax_exempt' =\u003e null,\n);\n\n// Learn more about the serial number in the next section\n$invoice-\u003econfigureSerialNumber(\n    prefix: \"ORD\",\n    serie: $customer-\u003eid,\n    year: now()-\u003eformat('Y'),\n    month: now()-\u003eformat('m')\n);\n\n// Optional\n// Learn more about the logo in the next section\n$invoice-\u003esetLogoFromConfig();\n\n$invoice-\u003ebuyer()-\u003eassociate($customer); // optionnally associate the invoice to any model\n$invoice-\u003einvoiceable()-\u003eassociate($order); // optionnally associate the invoice to any model\n\n$invoice-\u003esave();\n\n$invoice-\u003eitems()-\u003esaveMany([\n    new InvoiceItem([\n        'label' =\u003e \"Laratranslate Unlimitted\",\n        'description' =\u003e \"Elegant All-in-One Translations Manager for Laravel\",\n        'unit_price' =\u003e Money::of(99.0, 'USD'),\n        'tax_percentage' =\u003e 20.0,\n        'quantity' =\u003e 1,\n    ]),\n]);\n```\n\n### Generating Unique Serial Numbers\n\nThis package provides a simple and reliable way to generate serial numbers automatically, such as \"INV240001\".\n\nYou can configure the format of your serial numbers in the configuration file. The default format is `PPYYCCCC`, where each letter has a specific meaning (see the config file for details).\n\nWhen `invoices.serial_number.auto_generate` is set to `true`, a unique serial number is assigned to each new invoice automatically.\n\nSerial numbers are generated sequentially, with each new serial number based on the latest available one. To define what qualifies as the `previous` serial number, you can extend the `Elegantly\\Invoices\\Models\\Invoice` class and override the `getPreviousInvoice` method.\n\nBy default, the previous invoice is determined based on criteria such as prefix, series, year, and month for accurate, scoped numbering.\n\n### Using Multiple Prefixes and Series for Serial Numbers\n\nIn more complex applications, you may need to use different prefixes and/or series for your invoices.\n\nFor instance, you might want to define a unique series for each user, creating serial numbers that look like: `INV0001-2400X`, where `0001` represents the user’s ID, `24` the year and `X` the index of the invoice.\n\n\u003e [!NOTE]\n\u003e When using IDs for series, it's recommended to plan for future growth to avoid overflow.\n\u003e Even if you have a limited number of users now, ensure that the ID can accommodate the maximum number of digits allowed by the serial number format.\n\nWhen creating an invoice, you can dynamically specify the prefix and series with `configureSerialNumber` method:\n\n```php\nuse Elegantly\\Invoices\\Models\\Invoice;\n\n$invoice = new Invoice();\n\n$invoice-\u003econfigureSerialNumber(\n    prefix: \"ORG\",\n    serie: $buyerId,\n);\n```\n\n### Customizing the Serial Number Format\n\nIn most cases, the format of your serial numbers should remain consistent, so it's recommended to set it in the configuration file.\n\nThe format you choose will determine the types of information you need to provide to `configureSerialNumber`.\n\nBelow is an example of the most complex serial number format you can create with this package:\n\n```php\nuse Elegantly\\Invoices\\Models\\Invoice;\n\n$invoice = new Invoice();\n\n$invoice-\u003econfigureSerialNumber(\n    format: \"PP-SSSSSS-YYMMCCCC\",\n    prefix: \"IN\",\n    serie: 100,\n    year: now()-\u003eformat('Y'),\n    month: now()-\u003eformat('m')\n);\n\n$invoice-\u003esave();\n\n$invoice-\u003eserial_number; // IN-000100-24010001\n```\n\n### Storing the Logo\n\nBy default, the PDF logo is loaded from the configuration defined in your config file.\n\nIf you want the logo to remain consistent over time, even if the config changes, you can store it directly in the database:\n\n```php\nuse Elegantly\\Invoices\\Models\\Invoice;\n\n$invoice = new Invoice();\n\n// Store the current config logo in the database\n$invoice-\u003esetLogoFromConfig();\n\n// ...\n\n$invoice-\u003esave();\n```\n\n### Storing a Dynamic Logo\n\nIf your application allows users to upload or select their own company logos, you can dynamically set the logo on each invoice by updating the `logo` attribute on the `Invoice` model.\n\nYou can do this in several ways:\n\n```php\nuse Elegantly\\Invoices\\Models\\Invoice;\n\n$invoice = new Invoice();\n\n// Set the logo from an uploaded file (e.g., Illuminate\\Http\\UploadedFile)\n$invoice-\u003esetLogoFromFile($file);\n\n// Set the logo from a local filesystem path\n$invoice-\u003esetLogoFromPath($path);\n\n// Set the logo directly from raw file content (string or binary data)\n$invoice-\u003elogo = $rawFileContent;\n\n// ...\n\n$invoice-\u003esave();\n```\n\n### Converting an `Invoice` Model to a `PdfInvoice`\n\nYou can obtained a `PdfInvoice` class from your `Invoice` model by calling the `toPdfInvoice` method:\n\n```php\n$invoice = Invoice::first();\n\n$pdfInvoice = $invoice-\u003etoPdfInvoice();\n```\n\n### Display, Download, and Store Invoices\n\nYou can then stream the `PdfInvoice` instance directly or initiate a download:\n\n```php\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Invoice;\nuse Illuminate\\Http\\Request;\n\nclass InvoiceController extends Controller\n{\n    public function show(Request $request, string $serial)\n    {\n        /** @var Invoice $invoice */\n        $invoice = Invoice::where('serial_number', $serial)-\u003efirstOrFail();\n\n        $this-\u003eauthorize('view', $invoice);\n\n        return $invoice-\u003etoPdfInvoice()-\u003estream();\n    }\n\n    public function download(Request $request, string $serial)\n    {\n        /** @var Invoice $invoice */\n        $invoice = Invoice::where('serial_number', $serial)-\u003efirstOrFail();\n\n        $this-\u003eauthorize('view', $invoice);\n\n        return $invoice-\u003etoPdfInvoice()-\u003edownload();\n    }\n\n    public function store(Request $request, string $serial)\n    {\n        /** @var Invoice $invoice */\n        $invoice = Invoice::where('serial_number', $serial)-\u003efirstOrFail();\n\n        Storage::put(\n            \"path/to/invoice.pdf\",\n            $invoice-\u003etoPdfInvoice()-\u003egetPdfOutput()\n        );\n\n        // ...\n    }\n}\n```\n\n### Attaching Invoices to Mailables\n\nYou can easily attach an invoice to your `Mailable` as follows:\n\n```php\nnamespace App\\Mail;\n\nuse App\\Models\\Invoice;\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Mail\\Mailable;\nuse Illuminate\\Queue\\SerializesModels;\n\nclass PaymentInvoice extends Mailable\n{\n    use Queueable, SerializesModels;\n\n    /**\n     * Create a new message instance.\n     */\n    public function __construct(\n        protected Invoice $invoice,\n    ) {}\n\n\n    public function attachments(): array\n    {\n        return [\n            $this-\u003einvoice-\u003etoMailAttachment()\n        ];\n    }\n}\n```\n\n### Attaching Invoices to Notifications\n\nYou can easily attach an invoice to your `Notification` as follows:\n\n```php\nnamespace App\\Mail;\n\nuse App\\Models\\Invoice;\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Notifications\\Notification;\nuse Illuminate\\Notifications\\Messages\\MailMessage;\n\nclass PaymentInvoice extends Notification implements ShouldQueue\n{\n    use Queueable;\n\n    /**\n     * Create a new message instance.\n     */\n    public function __construct(\n        protected Invoice $invoice,\n    ) {}\n\n    public function toMail($notifiable)\n    {\n        return (new MailMessage)\n            -\u003eattach($this-\u003einvoice);\n    }\n}\n```\n\n### Customizing PDF Output from the Model\n\nTo customize how your `Invoice` model is converted into a `PdfInvoice` object, follow these steps:\n\n1.  **Create a Custom Invoice Model**:\n\nDefine your own `App\\Models\\Invoice` class and ensure it extends the base `Elegantly\\Invoices\\Models\\Invoice`.\n\n```php\nnamespace App\\Models;\n\nclass Invoice extends \\Elegantly\\Invoices\\Models\\Invoice\n{\n    // ...\n}\n```\n\n2.  **Override the `toPdfInvoice` Method**:\n\nIn your custom `Invoice` model, override the `toPdfInvoice` method. This is where you'll implement your specific logic to construct and return the `PdfInvoice` object with your desired customizations.\n\n```php\nnamespace App\\Models;\n\nuse Elegantly\\Invoices\\Pdf\\PdfInvoice;\n\nclass Invoice extends \\Elegantly\\Invoices\\Models\\Invoice\n{\n    function toPdfInvoice(): PdfInvoice\n    {\n        return new PdfInvoice(\n            // ... your custom PdfInvoice properties and configuration\n        );\n    }\n}\n```\n\n3.  **Update the Package Configuration**:\n\nFirst, if you haven't already, publish the package's configuration file:\n\n```bash\nphp artisan vendor:publish --tag=\"invoices-config\"\n```\n\nThen, modify the `config/invoices.php` file to tell the package to use your custom model by updating the `model_invoice` key:\n\n```php\nreturn [\n    // ...\n\n    'model_invoice' =\u003e \\App\\Models\\Invoice::class,\n\n    // ...\n];\n```\n\n#### Using a Custom PdfInvoice Class\n\nYou can extend the default PdfInvoice class provided by the package to customize its behavior, such as changing the generated filename or adding additional logic.\n\n1. Create Your Custom PdfInvoice Class\n\n```php\nclass PdfInvoice extends \\Elegantly\\Invoices\\Pdf\\PdfInvoice\n{\n\n    public function __construct(\n        // your custom constructor\n    ){\n        // ...\n    }\n\n    public function getFilename(): string\n    {\n        return str($this-\u003eserial_number)\n            -\u003ereplace(['/', '\\\\'], '_')\n            -\u003eappend('.pdf')\n            -\u003evalue();\n    }\n}\n```\n\nIn this example, we're overriding the `getFilename` method.\n\n2. Return Your Custom `PdfInvoice` from the Invoice Model\n\nUpdate your `Invoice` model to return an instance of your custom `PdfInvoice` class.\n\n```php\nnamespace App\\Models;\n\nuse App\\ValueObjects\\PdfInvoice;\n\nclass Invoice extends \\Elegantly\\Invoices\\Models\\Invoice\n{\n    function toPdfInvoice(): PdfInvoice\n    {\n        return new PdfInvoice(\n            // Pass any required data to your custom PdfInvoice constructor\n        );\n    }\n}\n```\n\nBy overriding the `toPdfInvoice` method, you can inject your custom logic while preserving compatibility with the rest of the package.\n\n### Casting `state` and `type` to Enums\n\nBy default, the `type` and `state` properties on the `Invoice` model are stored as strings. This approach offers flexibility, as it doesn't restrict you to predefined values and they are not automatically cast to Enum objects.\n\nHowever, you might prefer to cast these properties to Enum objects for better type safety and code clarity. You can use your own custom Enums or the ones provided by this package (e.g., `Elegantly\\Invoices\\Enums\\InvoiceState`, `Elegantly\\Invoices\\Enums\\InvoiceType`).\n\nTo enable Enum casting for these properties, follow these steps:\n\n0.  **Create custom `InvoiceState` and `InvoiceType` Enums** (optional):\n\nIf you're working with commonly used invoice states and types, you can use the enums provided by this package:\n\n- `Elegantly\\Invoices\\Enums\\InvoiceState`\n- `Elegantly\\Invoices\\Enums\\InvoiceType`\n\nFor custom states or types, you can define your own enums.\n\nMake sure your custom enums implement the `Elegantly\\Invoices\\Contracts\\HasLabel` contract, like so:\n\n```php\nnamespace App\\Enums;\n\nuse Elegantly\\Invoices\\Contracts\\HasLabel;\n\nenum InvoiceType: string implements HasLabel\n{\n    case Invoice = 'invoice';\n    case Quote = 'quote';\n    case Credit = 'credit';\n    case Proforma = 'proforma';\n\n    public function getLabel(): string\n    {\n        return match ($this) {\n            self::Invoice =\u003e __('invoices::invoice.types.invoice'),\n            self::Quote =\u003e __('invoices::invoice.types.quote'),\n            self::Credit =\u003e __('invoices::invoice.types.credit'),\n            self::Proforma =\u003e __('invoices::invoice.types.proforma'),\n        };\n    }\n}\n```\n\n1.  **Create a Custom `Invoice` Model**:\n\nDefine your own `App\\Models\\Invoice` class that extends `\\Elegantly\\Invoices\\Models\\Invoice`.\nIn this custom model, override the `casts()` method to specify the Enum classes for the `type` and `state` attributes.\n\n```php\nnamespace App\\Models;\n\nuse Elegantly\\Invoices\\Enums\\InvoiceState;\nuse Elegantly\\Invoices\\Enums\\InvoiceType;\n\n/**\n * @property InvoiceType $type\n * @property InvoiceState $state\n */\nclass Invoice extends \\Elegantly\\Invoices\\Models\\Invoice\n{\n    protected $attributes = [\n        'type' =\u003e InvoiceType::Invoice-\u003evalue,\n        'state' =\u003e InvoiceState::Draft-\u003evalue,\n    ];\n\n    protected function casts(): array\n    {\n        return [\n            ...parent::casts(), // Merge with parent casts for other potential attributes\n            'type' =\u003e InvoiceType::class,\n            'state' =\u003e InvoiceState::class,\n        ];\n    }\n}\n```\n\n2.  **Publish Package Configuration**:\n\nIf you haven't already, publish the package's configuration file:\n\n```bash\nphp artisan vendor:publish --tag=\"invoices-config\"\n```\n\n3.  **Update Configuration to Use Your Custom Model**:\n\nModify the `config/invoices.php` file and update the `model_invoice` key to point to your newly created custom `Invoice` model:\n\n```php\nreturn [\n    // ...\n\n    'model_invoice' =\u003e \\App\\Models\\Invoice::class,\n\n    // ...\n];\n```\n\n## Testing\n\n```bash\ncomposer test\n```\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.\n\n## Contributing\n\nPlease see [CONTRIBUTING](CONTRIBUTING.md) for details.\n\n## Security Vulnerabilities\n\nPlease review [our security policy](../../security/policy) on how to report security vulnerabilities.\n\n## Credits\n\n- [Quentin Gabriele](https://github.com/QuentinGab)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felegantengineeringtech%2Flaravel-invoices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felegantengineeringtech%2Flaravel-invoices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felegantengineeringtech%2Flaravel-invoices/lists"}