aichadigital/larabill
Composer 安装命令:
composer require aichadigital/larabill
包简介
Professional billing & invoicing package for Laravel with UUID v7, VAT verification, tax calculation for Spain/EU/worldwide, and EU compliance
关键字:
README 文档
README
🔒 Stability contract (effective from v6.0.0) — larabill is a closed, stable product governed by STABILITY.md: breaking changes only enter with a qualified, documented usage imperative; every major is auto-upgradeable from the previous one; deprecations live through at least one full major before removal. As of 6.0 the deprecated backlog is empty and there is no known future breaking change.
ℹ️ Schema upgrade policy (stable versions = respect for data) — since 1.0, larabill treats your database as a contract: schema changes ship WITH their upgrade path. Every release that touches tables includes a data-aware migration (existing rows are transformed, never discarded), and breaking majors ship an
UPGRADE-X.mdguide in the dist. To upgrade an existing install:composer update aichadigital/larabill, re-runphp artisan larabill:install --no-migrate(idempotent — it publishes only the NEW migrations, skipping the ones you already have), thenphp artisan migrate. Never usemigrate:freshon a database with real data.
⚠️ Upgrading? Follow the guides sequentially: UPGRADE-4.0.md (3.x → 4.0, VAT verification moves to
lararoi), UPGRADE-5.0.md (4.x → 5.0, real fiscal series separated from the fiscal type) and UPGRADE-6.0.md (5.x → 6.0, deprecated surface removed — zero migrations).
Larabill is a professional, UUID-first billing and invoicing package for Laravel applications. It provides tax calculation for Spain/EU/worldwide and flexible invoice generation with immutability protection, plus an optional thin bridge to intra-community VAT/NIF verification (delegated to the lararoi package). The consumer app's users.id MUST be UUID v7 char(36) — see docs/setup-uuid.md and ADR-006.
🎯 Features
Core Functionality
- Invoice Management: UUID-based IDs, sequential numbering, proforma invoices, immutable records
- Tax Calculation: Spanish (IVA), Canary Islands (IGIC), Ceuta/Melilla (IPSI), EU reverse charge, worldwide
- VAT/NIF Verification (optional): thin bridge that delegates to the
lararoipackage (VIES and other providers). Not wired into invoice issuance — reverse charge is driven by theis_roi_taxedflag - Fiscal Data Management: Company and customer fiscal configurations with temporal validity
- PDF Generation: Built-in invoice PDF generation using DomPDF
- EU Compliance: Full support for EU B2B reverse charge and destination VAT rules
Technical Excellence
- String UUID v7: Ordered UUIDs for invoices and the consumer's
users.id(ADR-006) - FixedDecimal money: Precise monetary value objects backed by base-100 integers (no floating-point errors)
- Preflight check:
larabill:installaborts cleanly whenusers.idis not UUID-compatible - Temporal Validity: Fiscal configurations with
valid_from/valid_untildates - Invoice Immutability: Protection against modifications after issuance
📦 Requirements
- PHP ^8.3
- Laravel ^12.0 | ^13.0
users.idUUID v7 char(36) — seedocs/setup-uuid.md
🚀 Installation
Via Composer
composer require aichadigital/larabill
Publish Configuration
php artisan vendor:publish --tag="larabill-config"
Run the Installer
php artisan larabill:install
This will:
- Publish migrations
- Run database migrations
- Seed default tax categories and rates
Manual Installation (if preferred)
# Publish migrations php artisan vendor:publish --tag="larabill-migrations" # Run migrations php artisan migrate # Seed default data php artisan db:seed --class="AichaDigital\Larabill\Database\Seeders\TaxRatesSeeder"
⚙️ Configuration
Environment Variables
Add these to your .env file:
# Invoice Numbering LARABILL_INVOICE_PREFIX="FAC" LARABILL_PROFORMA_PREFIX="PRO" # Optional: override the User model class. Must use UUID v7 char(36) ids. LARABILL_USER_MODEL="App\\Models\\User"
Model Configuration
Configure your user model in config/larabill.php:
'models' => [ 'user' => \App\Models\User::class, 'invoice' => \AichaDigital\Larabill\Models\Invoice::class, 'invoice_item' => \AichaDigital\Larabill\Models\InvoiceItem::class, // ... ],
🏗️ Architecture
Fiscal Data Model
Larabill separates company and customer fiscal data with temporal validity:
CompanyFiscalConfig → Issuer fiscal settings (one active at a time)
UserTaxProfile → Customer fiscal data, temporally versioned per user
Invoice → Immutable invoice with fiscal snapshot
Key principles:
- The customer is a
User(ADR-003); businesses and sub-accounts are modelled withparent_user_id. The legacyCustomerFiscalDatamodel was removed. - Company config changes apply from a specific date forward
UserTaxProfilerecords are temporally versioned (valid_from/valid_until) — never modify past records- Invoices capture a fiscal snapshot at creation time
- Invoices are absolutely immutable once issued
UUID Strategy
Larabill uses string UUID v7 for invoices:
// Model with UUID use AichaDigital\Larabill\Concerns\HasUuid; class Invoice extends Model { use HasUuid; } // Migration $table->uuid('id')->primary();
Monetary Values (FixedDecimal)
Money is stored as base-100 integers and exposed as FixedDecimal value objects (from lara100), so there are no floating-point errors. You assign the unscaled base-100 integer; reading the attribute returns a FixedDecimal:
// Assign the base-100 integer (€12.34 → 1234): $invoice->total_amount = 1234; // Reading the attribute returns a FixedDecimal value object // (base-100 backed, scale 2) — not a raw int: $money = $invoice->total_amount; // FixedDecimal
Invoice and invoice-item money attributes use the FixedDecimalCast (scale 2) from the lara100 package. Note: query-builder access (->value(), ->sum(), ->where()) returns the raw integer, while Eloquent attribute access returns a FixedDecimal.
📖 Usage
Creating an Invoice
use AichaDigital\Larabill\Services\InvoiceService; $invoiceService = app(InvoiceService::class); $invoice = $invoiceService->createInvoice([ 'billable_user_id' => $user->id, // UUID v7 of the billed customer (ADR-003) 'items' => [ [ 'description' => 'Professional Service', 'quantity' => 100, // base-100: 100 = 1.0 unit 'base_price' => 10000, // base-100: 10000 = €100.00 'tax_group_id' => $taxGroup->id, // resolves the applicable VAT/IGIC/IPSI ], ], ]);
Invoice numbers are correlative per series (invoice_series_control, EU/RD 1619/2012): fiscal_number, prefix, series_number and fiscal_year all derive atomically from InvoiceNumberingService. An active CompanyFiscalConfig must exist — createInvoice() snapshots the issuer's fiscal data and refuses to emit without it.
Removed in 6.0: the former
BillingServicequick-start path is gone —InvoiceServiceis the emission path. See UPGRADE-6.0.md for the 1:1 mapping.
Tax Calculation
use AichaDigital\Larabill\Services\TaxCalculationService; $taxService = app(TaxCalculationService::class); // Calculate taxes for a single line. Amounts are base-100 integers. The // applicable rate (Spanish IVA, Canary IGIC, Ceuta/Melilla IPSI, EU reverse // charge or destination VAT) is resolved from the TaxGroup and the customer's // fiscal profile — not passed in directly. $result = $taxService->calculateForInvoiceItem([ 'quantity' => 100, // base-100: 1.0 unit 'base_price' => 10000, // base-100: €100.00 'tax_group_id' => $taxGroup->id, 'billable_user_id' => $user->id, // optional: drives B2B / destination rules ]); // $result keys (base-100 integers + breakdown): // taxable_amount, total_tax_amount, total_amount, tax_group_id, taxes_applied
VAT/NIF Verification (optional bridge to lararoi)
Intra-community VAT/NIF verification is owned by the lararoi package. Larabill exposes a single thin bridge action that delegates to lararoi's contract and returns its canonical result unchanged:
use AichaDigital\Larabill\Actions\VerifyVatNumber; // Pass the VAT number WITHOUT the country prefix ("B12345678", not "ESB12345678"). $result = VerifyVatNumber::run('B12345678', 'ES'); if ($result['is_valid']) { echo 'Valid VAT for: '.$result['company_name']; }
Providers (VIES, isvat, vatlayer, …), caching and optional tracking are configured in lararoi, not here — publish its config with php artisan vendor:publish --tag="lararoi-config". This bridge is not wired into invoice issuance: reverse charge is decided by the invoice's is_roi_taxed flag, never by a live lookup.
Company Fiscal Configuration
use AichaDigital\Larabill\Models\CompanyFiscalConfig; // Get current active config $config = CompanyFiscalConfig::getActive(); // Create new config (the previous active one is auto-closed) $newConfig = CompanyFiscalConfig::createNew([ 'tax_id' => 'ESB12345678', 'business_name' => 'Your Company S.L.', 'address' => 'Calle Test 123', 'city' => 'Madrid', 'zip_code' => '28001', 'country_code' => 'ES', 'is_oss' => true, 'valid_from' => now(), ]);
User Tax Profile
The customer is a User (ADR-003); their fiscal data lives in UserTaxProfile, temporally versioned. This replaces the removed CustomerFiscalData model.
use AichaDigital\Larabill\Models\UserTaxProfile; // Get the active fiscal profile for a user $profile = UserTaxProfile::getActiveForOwner($user->id); // Create a new profile (previous stays as history) $newProfile = UserTaxProfile::createForOwner($user->id, [ 'fiscal_name' => 'Client SARL', 'tax_id' => 'FR12345678901', 'country_code' => 'FR', 'is_company' => true, ]);
🧪 Testing
# Run all tests composer test # Run specific tests composer test -- --filter=Invoice # Run with coverage composer test-coverage # Static analysis vendor/bin/phpstan analyse
Current status (v3.1.3): 928 tests passing on SQLite, plus MySQL 8 integration tests (real column types and unique constraints) and fork-based concurrency tests. The UUID-first contract is demonstrated on MySQL 8.
📚 Documentation
| Document | Description |
|---|---|
| ARCHITECTURE.md | Core architecture and domain model |
| setup-uuid.md | UUID-first onboarding for the consumer app |
| ADR-006 | UUID-first decision (supersedes the agnostic id contract) |
| TAX_RATES_MIGRATION_GUIDE.md | Tax rates migration guide |
| STABILITY.md | Stability contract: how larabill evolves from v6.0.0 |
| UPGRADE-4.0.md | Upgrade guide: larabill 3.x → 4.0 (VAT verification bridge) |
| UPGRADE-5.0.md | Upgrade guide: larabill 4.x → 5.0 (fiscal series vs fiscal type) |
| UPGRADE-6.0.md | Upgrade guide: larabill 5.x → 6.0 (deprecated surface removed) |
| CHANGELOG.md | Version history and breaking changes |
For AI agents working with this package, see .claude/project.md.
🗺️ Roadmap
Shipped
- ✅ Core invoice management (immutable records, UUID v7, sequential numbering, proforma)
- ✅ Spanish tax system (IVA, IGIC, IPSI)
- ✅ EU reverse charge (B2B) and destination VAT
- ✅ Fiscal data with temporal validity (
CompanyFiscalConfig,UserTaxProfile) - ✅
FixedDecimalmoney type (base-100, no floating-point errors) - ✅ VeriFACTU integration (Spain AEAT) via
lara-verifactu - ✅ Grouped payments
- ✅ Legal-retention contract (
LegallyRetainable) for GDPR tooling
Under consideration
- Subscription billing
- Payment gateway integration (Stripe, PayPal, Redsys)
- Advanced reporting
See the CHANGELOG for the full release history.
🤝 Contributing
Please see CONTRIBUTING for details.
🔒 Security
Please review our security policy on how to report security vulnerabilities.
📄 License
GNU Affero General Public License v3.0 (AGPL-3.0-or-later). See LICENSE.md for details.
This means:
- ✅ You can use, modify, and distribute this software
- ✅ You must share any modifications under the same license
- ⚠️ If you run this as a network service, you must provide the source code to users
- ⚠️ You must preserve copyright and attribution notices
👥 Credits
aichadigital/larabill 适用场景与选型建议
aichadigital/larabill 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 315 次下载、GitHub Stars 达 1, 最近一次更新时间为 2026 年 01 月 08 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「vat」 「tax」 「uuid」 「laravel」 「billing」 「invoicing」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 aichadigital/larabill 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 aichadigital/larabill 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 aichadigital/larabill 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A VAT number check (Web Service) Plugin for CakePHP
API client for validating Tax Identification Number.
Validate the format of EU vat numbers.
DrUUID RFC 4122 library for PHP
Module allowing creation of tax rates and categories in the CMS via SiteConfig
PHP VAT checker based on the European Commission web service
统计信息
- 总下载量: 315
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 49
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: AGPL-3.0-or-later
- 更新时间: 2026-01-08