diff --git a/README.md b/README.md index 655cdf8..9472e53 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,11 @@ php artisan vendor:publish --tag="invoices-config" This is the contents of the published config file: ```php +use Finller\Invoice\Invoice; +use Finller\Invoice\InvoiceDiscount; +use Finller\Invoice\InvoiceItem; +use Finller\Invoice\InvoiceType; + return [ 'model_invoice' => Invoice::class, @@ -109,7 +114,9 @@ return [ 'default_logo' => null, - 'default_template' => 'default', + 'default_color' => '#050038', + + 'default_template' => 'default.layout', /** * ISO 4217 currency code @@ -121,7 +128,10 @@ return [ * * @see Available options https://github.com/barryvdh/laravel-dompdf#configuration */ - 'pdf_options' => [], + 'pdf_options' => [ + 'isPhpEnabled' => true, + ], + 'paper_options' => [ 'paper' => 'a4', 'orientation' => 'portrait', diff --git a/config/invoices.php b/config/invoices.php index 3885ec1..ad60d36 100644 --- a/config/invoices.php +++ b/config/invoices.php @@ -1,7 +1,5 @@ null, - 'default_template' => 'default', + /** + * Define the color of the header line + */ + 'default_color' => '#050038', + + 'default_template' => 'default.layout', /** * ISO 4217 currency code @@ -90,7 +93,10 @@ * * @see Available options https://github.com/barryvdh/laravel-dompdf#configuration */ - 'pdf_options' => [], + 'pdf_options' => [ + 'isPhpEnabled' => true, + ], + 'paper_options' => [ 'paper' => 'a4', 'orientation' => 'portrait', diff --git a/resources/lang/en/invoice.php b/resources/lang/en/invoice.php index 2cf6868..a2ae739 100644 --- a/resources/lang/en/invoice.php +++ b/resources/lang/en/invoice.php @@ -21,6 +21,9 @@ 'quantity' => 'Qty', 'discount_name' => 'Discount', + 'from' => 'Bill From', + 'to' => 'Bill To', + 'states' => [ 'draft' => 'Draft', 'pending' => 'Pending', diff --git a/resources/lang/fr/invoice.php b/resources/lang/fr/invoice.php index 6f2173e..0bb242b 100644 --- a/resources/lang/fr/invoice.php +++ b/resources/lang/fr/invoice.php @@ -21,6 +21,9 @@ 'quantity' => 'Qté', 'discount_name' => 'Remise', + 'from' => 'De', + 'to' => 'Pour', + 'states' => [ 'draft' => 'Brouillon', 'pending' => 'En attente', diff --git a/resources/views/default.blade.php b/resources/views/default.blade.php deleted file mode 100644 index ef4f755..0000000 --- a/resources/views/default.blade.php +++ /dev/null @@ -1,460 +0,0 @@ - - - - - {{ $invoice->name }} - - - - - - -
-
- - - - - @if ($invoice->logo) - - @endif - - - -
-

- {{ $invoice->name }} -

- @if ($invoice->state) -

- {{ $invoice->state }} -

- @endif - - - - - - - - - - - - @if ($invoice->due_at) - - - - - @endif - @if ($invoice->paid_at) - - - - - @endif - -
- {{ __('invoices::invoice.serial_number') }} - - {{ $invoice->serial_number }} -
{{ __('invoices::invoice.created_at') }} - {{ $invoice->created_at?->format(config('invoices.date_format')) }} -
{{ __('invoices::invoice.due_at') }} - {{ $invoice->due_at->format(config('invoices.date_format')) }} -
{{ __('invoices::invoice.paid_at') }} - {{ $invoice->paid_at->format(config('invoices.date_format')) }} -
-
- logo -
- - - - - - - - -
- @if ($name = data_get($invoice->seller, 'name')) -

{{ $name }}

- @endif - @if ($street = data_get($invoice->seller, 'address.street')) -

{{ $street }}

- @endif - @if ($city = data_get($invoice->seller, 'address.city')) -

{{ $city }}

- @endif - @if ($postal_code = data_get($invoice->seller, 'address.postal_code')) -

{{ $postal_code }}

- @endif - @if ($state = data_get($invoice->seller, 'address.state')) -

{{ $state }}

- @endif - @if ($country = data_get($invoice->seller, 'address.country')) -

{{ $country }}

- @endif - @if ($email = data_get($invoice->seller, 'email')) -

{{ $email }}

- @endif - @if ($phone_number = data_get($invoice->seller, 'phone_number')) -

{{ $phone_number }}

- @endif - @if ($tax_number = data_get($invoice->seller, 'tax_number')) -

{{ $tax_number }}

- @endif - @if ($company_number = data_get($invoice->seller, 'company_number')) -

{{ $company_number }}

- @endif - @foreach (data_get($invoice->seller, 'data') ?? [] as $key => $item) - @if (is_string($key)) -

{{ $key }}: {{ $item }}

- @else -

{{ $item }}

- @endif - @endforeach -
- @if ($name = data_get($invoice->buyer, 'name')) -

{{ $name }}

- @endif - @if ($street = data_get($invoice->buyer, 'address.street')) -

{{ $street }}

- @endif - @if ($city = data_get($invoice->buyer, 'address.city')) -

{{ $city }}

- @endif - @if ($postal_code = data_get($invoice->buyer, 'address.postal_code')) -

{{ $postal_code }}

- @endif - @if ($state = data_get($invoice->buyer, 'address.state')) -

{{ $state }}

- @endif - @if ($country = data_get($invoice->buyer, 'address.country')) -

{{ $country }}

- @endif - @if ($email = data_get($invoice->buyer, 'email')) -

{{ $email }}

- @endif - @if ($phone_number = data_get($invoice->buyer, 'phone_number')) -

{{ $phone_number }}

- @endif - @if ($tax_number = data_get($invoice->buyer, 'tax_number')) -

{{ $tax_number }}

- @endif - @if ($company_number = data_get($invoice->buyer, 'company_number')) -

{{ $company_number }}

- @endif - @foreach (data_get($invoice->buyer, 'data') ?? [] as $key => $item) - @if (is_string($key)) -

{{ $key }}: {{ $item }}

- @else -

{{ $item }}

- @endif - @endforeach -
- - @php - $displayTaxColumn = !$invoice->totalTaxAmount()->isZero(); - @endphp - - - - - - - - @if ($displayTaxColumn) - - @endif - - - - - @foreach ($invoice->items as $item) - - - - - @if ($displayTaxColumn) - - @endif - - - @endforeach - - @php - $colspan = $displayTaxColumn ? '3' : '2'; - @endphp - - - {{-- empty space --}} - - - - - @if ($invoice->discounts) - @foreach ($invoice->discounts as $discount) - - {{-- empty space --}} - - - - - @endforeach - @endif - @if ($invoice->tax_label || $displayTaxColumn) - - {{-- empty space --}} - - - - - @endif - - {{-- empty space --}} - - - - - -
{{ __('invoices::invoice.description') }}{{ __('invoices::invoice.quantity') }}{{ __('invoices::invoice.unit_price') }}{{ __('invoices::invoice.tax') }}{{ __('invoices::invoice.amount') }}
!$loop->last, - ])> -

{{ $item->label }}

- @if ($item->description) -

{{ $item->description }}

- @endif -
-

{{ $item->quantity }}

-
-

{{ $item->formatMoney($item->unit_price) }}

-
- @if ($item->unit_tax && $item->tax_percentage) -

{{ $item->formatMoney($item->unit_tax) }} - ({{ $item->formatPercentage($item->tax_percentage) }})

- @elseif ($item->unit_tax) -

{{ $item->formatMoney($item->unit_tax) }}

- @else -

{{ $item->formatPercentage($item->tax_percentage) }}

- @endif -
-

{{ $item->formatMoney($item->totalAmount()) }}

-
- {{ __('invoices::invoice.subtotal_amount') }} - {{ $invoice->formatMoney($invoice->subTotalAmount()) }} -
- {{ __($discount->name) ?? __('invoices::invoice.discount_name') }} - @if ($discount->percent_off) - ({{ $discount->formatPercentage($discount->percent_off) }}) - @endif - - {{ $invoice->formatMoney($discount->computeDiscountAmountOn($invoice->subTotalAmount())?->multipliedBy(-1)) }} -
- {{ $invoice->tax_label ?? __('invoices::invoice.tax_label') }} - - {{ $invoice->formatMoney($invoice->totalTaxAmount()) }} -
- {{ __('invoices::invoice.total_amount') }} - - - {{ $invoice->formatMoney($invoice->totalAmount()) }} - -
- - @if ($invoice->description) -

{{ __('invoices::invoice.description') }}

-

{!! $invoice->description !!}

- @endif - -
- - - - diff --git a/resources/views/default/invoice.blade.php b/resources/views/default/invoice.blade.php new file mode 100644 index 0000000..87e7d35 --- /dev/null +++ b/resources/views/default/invoice.blade.php @@ -0,0 +1,288 @@ +@php + $displayTaxColumn = !$invoice->totalTaxAmount()->isZero(); + $colspan = $displayTaxColumn ? '3' : '2'; +@endphp + +
+
+
+ + + + + @if ($invoice->logo) + + @endif + + + +
+

+ {{ $invoice->name }} +

+ @if ($invoice->state) +

+ {{ $invoice->state }} +

+ @endif + + + + + + + + + + + + @if ($invoice->due_at) + + + + + @endif + @if ($invoice->paid_at) + + + + + @endif + +
+ {{ __('invoices::invoice.serial_number') }} + + {{ $invoice->serial_number }} +
+ {{ __('invoices::invoice.created_at') }} + + {{ $invoice->created_at?->format(config('invoices.date_format')) }} +
+ {{ __('invoices::invoice.due_at') }} + + {{ $invoice->due_at->format(config('invoices.date_format')) }} +
+ {{ __('invoices::invoice.paid_at') }} + + {{ $invoice->paid_at->format(config('invoices.date_format')) }} +
+
+ logo +
+ + + + + + + + +
+ @php + $name = data_get($invoice->seller, 'name'); + $street = data_get($invoice->seller, 'address.street'); + $postal_code = data_get($invoice->seller, 'address.postal_code'); + $city = data_get($invoice->seller, 'address.city'); + $state = data_get($invoice->seller, 'address.state'); + $country = data_get($invoice->seller, 'address.country'); + $email = data_get($invoice->seller, 'email'); + $phone_number = data_get($invoice->seller, 'phone_number'); + $tax_number = data_get($invoice->seller, 'tax_number'); + $company_number = data_get($invoice->seller, 'company_number'); + @endphp +

{{ __('invoices::invoice.from') }}

+ @if ($name) +

{{ $name }}

+ @endif + @if ($street) +

{{ $street }}

+ @endif + @if ($postal_code || $city) +

+ {{ $postal_code }} + {{ $city }} +

+ @endif + @if ($state) +

{{ $state }}

+ @endif + @if ($country) +

{{ $country }}

+ @endif + @if ($email) +

{{ $email }}

+ @endif + @if ($phone_number) +

{{ $phone_number }}

+ @endif + @if ($tax_number) +

{{ $tax_number }}

+ @endif + @if ($company_number) +

{{ $company_number }}

+ @endif + @foreach (data_get($invoice->seller, 'data') ?? [] as $key => $item) + @if (is_string($key)) +

{{ $key }}: {{ $item }}

+ @else +

{{ $item }}

+ @endif + @endforeach +
+ @php + $name = data_get($invoice->buyer, 'name'); + $street = data_get($invoice->buyer, 'address.street'); + $postal_code = data_get($invoice->buyer, 'address.postal_code'); + $city = data_get($invoice->buyer, 'address.city'); + $state = data_get($invoice->buyer, 'address.state'); + $country = data_get($invoice->buyer, 'address.country'); + $email = data_get($invoice->buyer, 'email'); + $phone_number = data_get($invoice->buyer, 'phone_number'); + $tax_number = data_get($invoice->buyer, 'tax_number'); + $company_number = data_get($invoice->buyer, 'company_number'); + @endphp +

{{ __('invoices::invoice.to') }}

+ @if ($name) +

{{ $name }}

+ @endif + @if ($street) +

{{ $street }}

+ @endif + @if ($postal_code || $city) +

+ {{ $postal_code }} + {{ $city }} +

+ @endif + @if ($state) +

{{ $state }}

+ @endif + @if ($country) +

{{ $country }}

+ @endif + @if ($email) +

{{ $email }}

+ @endif + @if ($phone_number) +

{{ $phone_number }}

+ @endif + @if ($tax_number) +

{{ $tax_number }}

+ @endif + @if ($company_number) +

{{ $company_number }}

+ @endif + @foreach (data_get($invoice->seller, 'data') ?? [] as $key => $item) + @if (is_string($key)) +

{{ $key }}: {{ $item }}

+ @else +

{{ $item }}

+ @endif + @endforeach +
+ + + + + + + + @if ($displayTaxColumn) + + @endif + + + + + @foreach ($invoice->items as $item) + + + + + @if ($displayTaxColumn) + + @endif + + + @endforeach + + + {{-- empty space --}} + + + + + @if ($invoice->discounts) + @foreach ($invoice->discounts as $discount) + + {{-- empty space --}} + + + + + @endforeach + @endif + @if ($invoice->tax_label || $displayTaxColumn) + + {{-- empty space --}} + + + + + @endif + + {{-- empty space --}} + + + + + +
{{ __('invoices::invoice.description') }}{{ __('invoices::invoice.quantity') }}{{ __('invoices::invoice.unit_price') }}{{ __('invoices::invoice.tax') }}{{ __('invoices::invoice.amount') }}
!$loop->last])> +

{{ $item->label }}

+ @if ($item->description) +

{{ $item->description }}

+ @endif +
+

{{ $item->quantity }}

+
+

{{ $item->formatMoney($item->unit_price) }}

+
+ @if ($item->unit_tax && $item->tax_percentage) +

{{ $item->formatMoney($item->unit_tax) }} + ({{ $item->formatPercentage($item->tax_percentage) }})

+ @elseif ($item->unit_tax) +

{{ $item->formatMoney($item->unit_tax) }}

+ @else +

{{ $item->formatPercentage($item->tax_percentage) }}

+ @endif +
+

{{ $item->formatMoney($item->totalAmount()) }}

+
+ {{ __('invoices::invoice.subtotal_amount') }} + {{ $invoice->formatMoney($invoice->subTotalAmount()) }} +
+ {{ __($discount->name) ?? __('invoices::invoice.discount_name') }} + @if ($discount->percent_off) + ({{ $discount->formatPercentage($discount->percent_off) }}) + @endif + + {{ $invoice->formatMoney($discount->computeDiscountAmountOn($invoice->subTotalAmount())?->multipliedBy(-1)) }} +
+ {{ $invoice->tax_label ?? __('invoices::invoice.tax_label') }} + + {{ $invoice->formatMoney($invoice->totalTaxAmount()) }} +
+ {{ __('invoices::invoice.total_amount') }} + + + {{ $invoice->formatMoney($invoice->totalAmount()) }} + +
+ + @if ($invoice->description) +

{{ __('invoices::invoice.description') }}

+

{!! $invoice->description !!}

+ @endif + +
+
diff --git a/resources/views/default/layout.blade.php b/resources/views/default/layout.blade.php new file mode 100644 index 0000000..c1c3cd7 --- /dev/null +++ b/resources/views/default/layout.blade.php @@ -0,0 +1,27 @@ + + + + + {{ $invoice->name }} + + + @include('invoices::default.style') + + + + @include('invoices::default.invoice') + + + + + diff --git a/resources/views/default/style.blade.php b/resources/views/default/style.blade.php new file mode 100644 index 0000000..5baf1a7 --- /dev/null +++ b/resources/views/default/style.blade.php @@ -0,0 +1,222 @@ + diff --git a/src/PdfInvoice.php b/src/PdfInvoice.php index 9563485..677b7d6 100644 --- a/src/PdfInvoice.php +++ b/src/PdfInvoice.php @@ -23,28 +23,30 @@ public function __construct( public ?string $name = null, public ?string $state = null, public ?string $serial_number = null, + public ?array $seller = null, public ?array $buyer = null, - public ?Carbon $due_at = null, + public ?string $description = null, public ?Carbon $created_at = null, + public ?Carbon $due_at = null, public ?Carbon $paid_at = null, - public ?array $seller = null, - public ?string $description = null, + public ?string $tax_label = null, + public ?array $items = null, + public ?array $discounts = null, public ?string $logo = null, - public ?string $template = null, + public ?string $color = null, public ?string $filename = null, - public ?array $items = null, - public ?string $tax_label = null, - public ?array $discounts = null + public ?string $template = null, ) { $this->name = $name ?? __('invoices::invoice.invoice'); $this->seller = $seller ?? config('invoices.default_seller', []); $this->logo = $logo ?? config('invoices.default_logo', null); + $this->color = $color ?? config('invoices.default_color', null); $this->template = sprintf('invoices::%s', $template ?? config('invoices.default_template', null)); } public function generateFilename(): string { - return Str::slug("{$this->name}_{$this->serial_number}", separator: '_').'.pdf'; + return Str::slug("{$this->name}_{$this->serial_number}", separator: '-').'.pdf'; } public function getFilename(): string @@ -120,7 +122,9 @@ public function pdf(): \Barryvdh\DomPDF\PDF config('invoices.paper_options.orientation', 'portrait') ); - foreach (config('invoices.pdf_options') as $attribute => $value) { + $options = config('invoices.pdf_options') ?? []; + + foreach ($options as $attribute => $value) { $pdf->setOption($attribute, $value); }