Skip to content

Commit 48819a2

Browse files
committed
store logo in db
1 parent 24ff59d commit 48819a2

File tree

5 files changed

+152
-96
lines changed

5 files changed

+152
-96
lines changed

README.md

Lines changed: 85 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,15 @@ Try out [the interactive demo](https://elegantly.dev/laravel-invoices) to explor
4242
- [Generating Unique Serial Numbers](#generating-unique-serial-numbers)
4343
- [Using Multiple Prefixes and Series for Serial Numbers](#using-multiple-prefixes-and-series-for-serial-numbers)
4444
- [Customizing the Serial Number Format](#customizing-the-serial-number-format)
45+
- [Storing the Logo](#storing-the-logo)
46+
- [Storing a Dynamic Logo](#storing-a-dynamic-logo)
4547
- [Converting an `Invoice` Model to a `PdfInvoice`](#converting-an-invoice-model-to-a-pdfinvoice)
4648
- [Display, Download, and Store Invoices](#display-download-and-store-invoices)
4749
- [Attaching Invoices to Mailables](#attaching-invoices-to-mailables)
4850
- [Attaching Invoices to Notifications](#attaching-invoices-to-notifications)
4951
- [Customizing PDF Output from the Model](#customizing-pdf-output-from-the-model)
5052
- [Using a Custom PdfInvoice Class](#using-a-custom-pdfinvoice-class)
5153
- [Casting `state` and `type` to Enums](#casting-state-and-type-to-enums)
52-
- [Using a Dynamic Logo](#using-a-dynamic-logo)
5354
- [Testing](#testing)
5455
- [Changelog](#changelog)
5556
- [Contributing](#contributing)
@@ -143,6 +144,7 @@ return [
143144
'date_format' => 'Y-m-d',
144145

145146
'default_seller' => [
147+
'company' => null,
146148
'name' => null,
147149
'address' => [
148150
'street' => null,
@@ -154,7 +156,9 @@ return [
154156
'email' => null,
155157
'phone' => null,
156158
'tax_number' => null,
157-
'company_number' => null,
159+
'fields' => [
160+
//
161+
],
158162
],
159163

160164
/**
@@ -657,7 +661,7 @@ For this illustration, let's assume the following application structure:
657661

658662
- `Team` models have `User` models.
659663
- `Team` models can have multiple `Invoice` models.
660-
- `Invoice` models can be attached to `Offer` models.
664+
- `Invoice` models can be attached to `Order` models.
661665

662666
```php
663667
use App\Models\Team;
@@ -672,40 +676,40 @@ $customer = Team::find(1);
672676
$order = Order::find(2);
673677

674678
$invoice = new Invoice(
675-
'type'=> "invoice",
676-
'state'=> "paid",
677-
'seller_information'=> config('invoices.default_seller'),
678-
'buyer_information'=>[
679-
'company'=> "Doe Corporation" // (optional)
680-
'name'=> 'John Doe', // (optional)
681-
'address'=> [
682-
'street'=> '8405 Old James St.Rochester',
683-
'city'=> 'New York',
684-
'postal_code'=> '14609',
685-
'state'=> 'NY',
686-
'country'=> 'United States',
679+
'type' => "invoice",
680+
'state' => "paid",
681+
'seller_information' => config('invoices.default_seller'),
682+
'buyer_information' =>[
683+
'company' => "Doe Corporation" // (optional)
684+
'name' => 'John Doe', // (optional)
685+
'address' => [
686+
'street' => '8405 Old James St.Rochester',
687+
'city' => 'New York',
688+
'postal_code' => '14609',
689+
'state' => 'NY',
690+
'country' => 'United States',
687691
],
688-
'shipping_address'=> [ // (optional)
689-
'street'=> [ // multiple lines street
692+
'shipping_address' => [ // (optional)
693+
'street' => [ // multiple lines street
690694
'8405 Old James St.Rochester',
691695
'Apartment 1',
692696
],
693-
'city'=> 'New York',
694-
'postal_code'=> '14609',
695-
'state'=> 'NY',
696-
'country'=> 'United States',
697+
'city' => 'New York',
698+
'postal_code' => '14609',
699+
'state' => 'NY',
700+
'country' => 'United States',
697701
]
698-
'email'=> '[email protected]',
699-
'fields'=> [
702+
'email' => '[email protected]',
703+
'fields' => [
700704
// Custom fields to display with the buyer
701705
"foo" => "bar"
702706
]
703707
],
704-
'description'=> "An invoice description",
705-
'due_at'=> now(),
706-
'paid_at'=> now(),
707-
'tax_type'=> "eu_VAT_FR",
708-
'tax_exempt'=> null,
708+
'description' => "An invoice description",
709+
'due_at' => now(),
710+
'paid_at' => now(),
711+
'tax_type' => "eu_VAT_FR",
712+
'tax_exempt' => null,
709713
);
710714

711715
// Learn more about the serial number in the next section
@@ -714,7 +718,11 @@ $invoice->configureSerialNumber(
714718
serie: $customer->id,
715719
year: now()->format('Y'),
716720
month: now()->format('m')
717-
)
721+
);
722+
723+
// Optional
724+
// Learn more about the logo in the next section
725+
$invoice->setLogoFromConfig();
718726

719727
$invoice->buyer()->associate($customer); // optionnally associate the invoice to any model
720728
$invoice->invoiceable()->associate($order); // optionnally associate the invoice to any model
@@ -758,11 +766,12 @@ When creating an invoice, you can dynamically specify the prefix and series with
758766

759767
```php
760768
use Elegantly\Invoices\Models\Invoice;
769+
761770
$invoice = new Invoice();
762771

763772
$invoice->configureSerialNumber(
764773
prefix: "ORG",
765-
serie: $buyer_id,
774+
serie: $buyerId,
766775
);
767776
```
768777

@@ -775,6 +784,7 @@ The format you choose will determine the types of information you need to provid
775784
Below is an example of the most complex serial number format you can create with this package:
776785

777786
```php
787+
use Elegantly\Invoices\Models\Invoice;
778788

779789
$invoice = new Invoice();
780790

@@ -791,6 +801,50 @@ $invoice->save();
791801
$invoice->serial_number; // IN-000100-24010001
792802
```
793803

804+
### Storing the Logo
805+
806+
By default, the PDF logo is loaded from the configuration defined in your config file.
807+
808+
If you want the logo to remain consistent over time, even if the config changes, you can store it directly in the database:
809+
810+
```php
811+
use Elegantly\Invoices\Models\Invoice;
812+
813+
$invoice = new Invoice();
814+
815+
// Store the current config logo in the database
816+
$invoice->setLogoFromConfig();
817+
818+
// ...
819+
820+
$invoice->save();
821+
```
822+
823+
### Storing a Dynamic Logo
824+
825+
If 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.
826+
827+
You can do this in several ways:
828+
829+
```php
830+
use Elegantly\Invoices\Models\Invoice;
831+
832+
$invoice = new Invoice();
833+
834+
// Set the logo from an uploaded file (e.g., Illuminate\Http\UploadedFile)
835+
$invoice->setLogoFromFile($file);
836+
837+
// Set the logo from a local filesystem path
838+
$invoice->setLogoFromPath($path);
839+
840+
// Set the logo directly from raw file content (string or binary data)
841+
$invoice->logo = $rawFileContent;
842+
843+
// ...
844+
845+
$invoice->save();
846+
```
847+
794848
### Converting an `Invoice` Model to a `PdfInvoice`
795849

796850
You can obtained a `PdfInvoice` class from your `Invoice` model by calling the `toPdfInvoice` method:
@@ -907,7 +961,7 @@ class PaymentInvoice extends Notification implements ShouldQueue
907961
public function toMail($notifiable)
908962
{
909963
return (new MailMessage)
910-
->attach($this->invoice->toMailAttachment());
964+
->attach($this->invoice);
911965
}
912966
}
913967
```
@@ -1117,68 +1171,6 @@ return [
11171171
];
11181172
```
11191173

1120-
### Using a Dynamic Logo
1121-
1122-
In scenarios where the invoice logo needs to be set dynamically (for instance, allowing users to upload their own company logo), you can achieve this by overriding the `getLogo` method in your `Invoice` model.
1123-
1124-
Follow these steps:
1125-
1126-
1. **Create a Custom `Invoice` Model**:
1127-
1128-
Define your own `App\Models\Invoice` that extends `\Elegantly\Invoices\Models\Invoice` class.
1129-
Inside this custom model, implement the `getLogo` method to return the path or data for your dynamic logo.
1130-
1131-
> [!NOTE]
1132-
> The `getLogo` method must return either a base64-encoded data URL (e.g., `data:image/png;base64,...`) or a local filesystem path to the logo image.
1133-
1134-
Here's an example of how you might implement this:
1135-
1136-
```php
1137-
namespace App\Models;
1138-
1139-
use Illuminate\Http\File;
1140-
1141-
class Invoice extends \Elegantly\Invoices\Models\Invoice
1142-
{
1143-
public function getLogo(): ?string
1144-
{
1145-
$logoPath = public_path('logo.png'); // Replace with your dynamic logic
1146-
1147-
if (!file_exists($logoPath)) {
1148-
return null; // Or a default logo
1149-
}
1150-
1151-
$file = new File($logoPath);
1152-
$mime = $file->getMimeType();
1153-
$logoData = "data:{$mime};base64," . base64_encode(file_get_contents($logoPath)); // Use file_get_contents for raw data
1154-
1155-
return $logoData;
1156-
}
1157-
}
1158-
```
1159-
1160-
2. **Publish Package Configuration**:
1161-
1162-
If you haven't done so already, publish the package's configuration file:
1163-
1164-
```bash
1165-
php artisan vendor:publish --tag="invoices-config"
1166-
```
1167-
1168-
3. **Update Configuration to Use Your Custom Model**:
1169-
1170-
Modify the `config/invoices.php` file and update the `model_invoice` key to point to your custom `Invoice` model:
1171-
1172-
```php
1173-
return [
1174-
// ...
1175-
1176-
'model_invoice' => \App\Models\Invoice::class,
1177-
1178-
// ...
1179-
];
1180-
```
1181-
11821174
## Testing
11831175

11841176
```bash

resources/views/default/invoice.blade.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
</td>
6565
@if ($invoice->logo)
6666
<td class="p-0 align-top" width="20%">
67-
<img src="{{ $invoice->logo }}" alt="logo" height="100">
67+
<img src="{{ $invoice->logo }}" alt="logo" height="100" />
6868
</td>
6969
@endif
7070
</tr>
@@ -302,7 +302,7 @@
302302
</td>
303303
@if ($paymentInstruction->qrcode)
304304
<td class="min-w-28 p-0 align-top">
305-
<img src="{{ $paymentInstruction->qrcode }}" class="w-28 bg-white">
305+
<img src="{{ $paymentInstruction->qrcode }}" class="w-28 bg-white" />
306306
</td>
307307
@endif
308308
</tr>

src/Models/Invoice.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Elegantly\Invoices\Support\Seller;
2020
use Elegantly\Money\MoneyCast;
2121
use Exception;
22+
use finfo;
2223
use Illuminate\Contracts\Mail\Attachable;
2324
use Illuminate\Database\Eloquent\Builder;
2425
use Illuminate\Database\Eloquent\Collection;
@@ -28,6 +29,8 @@
2829
use Illuminate\Database\Eloquent\Relations\HasMany;
2930
use Illuminate\Database\Eloquent\Relations\HasOne;
3031
use Illuminate\Database\Eloquent\Relations\MorphTo;
32+
use Illuminate\Http\File;
33+
use Illuminate\Http\UploadedFile;
3134
use Illuminate\Mail\Attachment;
3235

3336
/**
@@ -71,6 +74,7 @@
7174
* @property ?int $serial_number_year
7275
* @property ?int $serial_number_month
7376
* @property int $serial_number_count
77+
* @property ?string $logo Binary format
7478
*/
7579
class Invoice extends Model implements Attachable
7680
{
@@ -458,11 +462,49 @@ public function toMailAttachment(): Attachment
458462
return $this->toPdfInvoice()->toMailAttachment();
459463
}
460464

465+
/**
466+
* Store the default logo in database
467+
*/
468+
public function setLogoFromConfig(): static
469+
{
470+
/** @var ?string */
471+
$path = config('invoices.pdf.logo');
472+
473+
if ($path) {
474+
return $this->setLogoFromPath($path);
475+
}
476+
477+
return $this;
478+
}
479+
480+
public function setLogoFromFile(File|UploadedFile $file): static
481+
{
482+
$this->logo = $file->getContent();
483+
484+
return $this;
485+
}
486+
487+
public function setLogoFromPath(string $path): static
488+
{
489+
if ($file = file_get_contents($path)) {
490+
$this->logo = $file;
491+
}
492+
493+
return $this;
494+
}
495+
461496
/**
462497
* @return string|null A base64 encoded data url or a path to a local file
463498
*/
464499
public function getLogo(): ?string
465500
{
501+
if ($this->logo) {
502+
$finfo = new finfo(FILEINFO_MIME_TYPE);
503+
$mimeType = $finfo->buffer($this->logo);
504+
505+
return "data:{$mimeType};base64,".base64_encode($this->logo);
506+
}
507+
466508
return null;
467509
}
468510

src/Pdf/PdfInvoice.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
use Elegantly\Invoices\Support\Buyer;
1717
use Elegantly\Invoices\Support\PaymentInstruction;
1818
use Elegantly\Invoices\Support\Seller;
19+
use Illuminate\Contracts\Mail\Attachable;
1920
use Illuminate\Http\Response;
2021
use Illuminate\Mail\Attachment;
2122
use Illuminate\Support\Arr;
2223
use Illuminate\Support\Str;
2324
use Symfony\Component\HttpFoundation\HeaderUtils;
2425

25-
class PdfInvoice
26+
class PdfInvoice implements Attachable
2627
{
2728
use FormatForPdf;
2829

0 commit comments

Comments
 (0)