finller/laravel-invoices

在您的 Laravel 应用程序中安全地存储发票

v3.2.1 2024-09-05 21:08 UTC

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

创建发票不是一个基本操作,因为您必须确保它以安全的方式进行。此包提供所有基本功能,以在您的应用程序中存储并显示发票。

迁移到 v3

v3 引入了一种更健壮的方式来配置序列号。

  • configureSerialNumber 替换了 'setSerialNumberPrefix, 'setSerialNumberSerie, ...

安装

您可以通过 composer 安装此包

composer require finller/laravel-invoices

您可以使用以下命令发布和运行迁移

php artisan vendor:publish --tag="invoices-migrations"
php artisan migrate

您可以使用以下命令发布配置文件

php artisan vendor:publish --tag="invoices-config"

这是已发布配置文件的内容

return [

    'model_invoice' => Invoice::class,
    'model_invoice_item' => InvoiceItem::class,

    'discount_class' => InvoiceDiscount::class,

    'cascade_invoice_delete_to_invoice_items' => true,

    'serial_number' => [
        /**
         * If true, will generate a serial number on creation
         * If false, you will have to set the serial_number yourself
         */
        'auto_generate' => true,

        /**
         * Define the serial number format used for each invoice type
         *
         * P: Prefix
         * S: Serie
         * M: Month
         * Y: Year
         * C: Count
         * Example: IN0012-220234
         * Repeat letter to set the length of each information
         * Examples of formats:
         * - PPYYCCCC : IN220123 (default)
         * - PPPYYCCCC : INV220123
         * - PPSSSS-YYCCCC : INV0001-220123
         * - SSSS-CCCC: 0001-0123
         * - YYCCCC: 220123
         */
        'format' => [
            InvoiceType::Invoice->value => 'PPYYCCCC',
            InvoiceType::Quote->value => 'PPYYCCCC',
            InvoiceType::Credit->value => 'PPYYCCCC',
            InvoiceType::Proforma->value => 'PPYYCCCC',
        ],

        /**
         * Define the default prefix used for each invoice type
         */
        'prefix' => [
            InvoiceType::Invoice->value => 'IN',
            InvoiceType::Quote->value => 'QO',
            InvoiceType::Credit->value => 'CR',
            InvoiceType::Proforma->value => 'PF',
        ],

    ],

    'date_format' => 'Y-m-d',

    'default_seller' => [
        'name' => null,
        'address' => [
            'street' => null,
            'city' => null,
            'postal_code' => null,
            'state' => null,
            'country' => null,
        ],
        'email' => null,
        'phone_number' => null,
        'tax_number' => null,
        'company_number' => null,
    ],

    'default_logo' => null,

    'default_template' => 'default',

    /**
     * ISO 4217 currency code
     */
    'default_currency' => 'USD',

    /**
     * Default DOM PDF options
     *
     * @see Available options https://github.com/barryvdh/laravel-dompdf#configuration
     */
    'pdf_options' => [],
    'paper_options' => [
        'paper' => 'a4',
        'orientation' => 'portrait',
    ],
];

用法

在数据库中存储发票

发票只是一个具有InvoiceItem关系的模型,因此您可以像创建模型一样创建发票

use Finller\Invoice\Invoice;
use Finller\Invoice\InvoiceState;
use Finller\Invoice\InvoiceType;

// Define general invoice data
$invoice = new Invoice([
    'type' => InvoiceType::Invoice,
    'state' => InvoiceState::Draft,
    'description' => 'A description for my invoice',
    'seller_information' => config('invoices.default_seller'),
    'buyer_information' => [
        'name' => 'Client name',
        'address' => [],
        'tax_number' => "XYZ",
    ],
    // ...
]);

$invoice->configureSerialNumber(
    prefix: "CLI",
    serie: 42,
);

$invoice->buyer()->associate($customer);
$invoice->invoiceable()->associate($order); // optionnally associate the invoice to a model

$invoice->save();

$invoice->items()->saveMany([
    new InvoiceItem([
        'unit_price' => Money::of(100, 'USD'),
        'unit_tax' => Money::of(20, 'USD'),
        'currency' => 'USD',
        'quantity' => 1,
        'label' => 'A label for my item',
        'description' => 'A description for my item',
    ]),
]);

自动生成唯一的序列号

此包提供了一种简单的方法,以安全且自动的方式生成明确的序列号,如 "INV-0001"。

您可以在配置文件中配置序列号格式。默认格式是 PPYYCCCC(请参阅配置了解每个字母的含义)。

每次创建新发票时,如果 invoices.serial_number.auto_generate 设置为 true,则发票将获得一个唯一的序列号。

序列号依次生成,新生成的序列号基于可用的 previous 一个。为了确定哪个是 previous 序列号,您可以扩展 Finller\Invoice\Invoice 并重写 getPreviousInvoice 方法。

默认情况下,前一个发票按前缀、系列、年和月进行范围限制,正如您所期望的那样。

管理多个前缀和多个系列

在更复杂的应用程序中,您可能需要为发票使用不同的前缀和/或系列。

例如,您可能希望为每个用户定义一个系列,并使序列号看起来像:INV0001-00X,其中 1 是用户的 id。

创建发票时,您可以动态地定义前缀和系列,如下所示;

use Finller\Invoice\Invoice;
$invoice = new Invoice();

$invoice->configureSerialNumber(
    prefix: "ORG",
    serie: $buyer_id,
);

$invoice->save();

以 PDF 的形式显示您的发票

发票模型具有一个 toPdfInvoice() 方法,该方法返回一个 PdfInvoice 类。

作为控制器的响应

您可以将 pdfInvoice 实例作为响应流式传输或下载

namespace App\Http\Controllers;

use App\Models\Invoice;
use Illuminate\Http\Request;

class InvoiceController extends Controller
{
    public function show(Request $request, string $serial)
    {
        /** @var Invoice $invoice */
        $invoice = Invoice::where('serial_number', $serial)->firstOrFail();

        $this->authorize('view', $invoice);

        return $invoice->toPdfInvoice()->stream();
    }

    public function download(Request $request, string $serial)
    {
        /** @var Invoice $invoice */
        $invoice = Invoice::where('serial_number', $serial)->firstOrFail();

        $this->authorize('view', $invoice);

        return $invoice->toPdfInvoice()->download();
    }
}

作为邮件附件

Invoice 模型提供了一个 toMailAttachment 方法,使其易于与 Mailable 一起使用

namespace App\Mail;

use App\Models\Invoice;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class PaymentInvoice extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     */
    public function __construct(
        protected Invoice $invoice,
    ) {}


    public function attachments(): array
    {
        return [
            $this->invoice->toMailAttachment()
        ];
    }
}

测试

composer test

更改日志

请参阅 更改日志 了解最近更改的更多信息。

贡献

请参阅 贡献指南 了解详细信息。

安全漏洞

有关如何报告安全漏洞,请参阅 我们的安全策略

致谢

许可证

MIT 许可证 (MIT)。有关更多信息,请参阅 许可证文件