From 7e5b1fea895aee38347158ec2416488eaf9178d2 Mon Sep 17 00:00:00 2001 From: ludo Date: Sun, 7 Jan 2024 23:16:29 +0100 Subject: [PATCH] render invoice in pdf --- .../Controllers/Shop/InvoiceController.php | 1 + app/Http/Controllers/Shop/OrderController.php | 5 + app/Models/Shop/Order.php | 5 + app/Repositories/Shop/InvoicePDF.php | 84 +++++++++++++ app/Repositories/Shop/Orders.php | 27 +++- composer.json | 1 + config/invoices.php | 115 ++++++++++++++++++ routes/Shop/Orders.php | 2 +- 8 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 app/Repositories/Shop/InvoicePDF.php create mode 100644 config/invoices.php diff --git a/app/Http/Controllers/Shop/InvoiceController.php b/app/Http/Controllers/Shop/InvoiceController.php index f65ff8ff..5330e199 100644 --- a/app/Http/Controllers/Shop/InvoiceController.php +++ b/app/Http/Controllers/Shop/InvoiceController.php @@ -23,6 +23,7 @@ class InvoiceController extends Controller public function pdf($uuid) { \Debugbar::disable(); + $data = [ 'invoice' => Invoices::getByUUID($uuid), ]; diff --git a/app/Http/Controllers/Shop/OrderController.php b/app/Http/Controllers/Shop/OrderController.php index 599d3b0a..bc9865e1 100644 --- a/app/Http/Controllers/Shop/OrderController.php +++ b/app/Http/Controllers/Shop/OrderController.php @@ -82,4 +82,9 @@ class OrderController extends Controller return view('Shop.Orders.confirmed'); } + + public function getPdf($uuid) + { + return Orders::getPdfByUUID($uuid); + } } diff --git a/app/Models/Shop/Order.php b/app/Models/Shop/Order.php index 97ff4183..f3e80ed0 100644 --- a/app/Models/Shop/Order.php +++ b/app/Models/Shop/Order.php @@ -48,6 +48,11 @@ class Order extends Model return $this->belongsTo(SaleChannel::class); } + public function scopeByID($query, $id) + { + return $query->where('id', $id); + } + public function scopeByUUID($query, $uuid) { return $query->where('uuid', $uuid); diff --git a/app/Repositories/Shop/InvoicePDF.php b/app/Repositories/Shop/InvoicePDF.php new file mode 100644 index 00000000..4e79186a --- /dev/null +++ b/app/Repositories/Shop/InvoicePDF.php @@ -0,0 +1,84 @@ + 'Roosevelt Lloyd', + 'phone' => '(520) 318-9486', + 'custom_fields' => [ + 'note' => 'IDDQD', + 'business id' => '365#GG', + ], + ]); + + $customer = new Party([ + 'name' => 'Ashley Medina', + 'address' => 'The Green Street 12', + 'code' => '#22663214', + 'custom_fields' => [ + 'order number' => '> 654321 <', + ], + ]); + + $items = self::makeItems($order->details); + + $notes = [ + 'your multiline', + 'additional notes', + 'in regards of delivery or something else', + ]; + $notes = implode("
", $notes); + + $invoice = Invoice::make('receipt') + ->series('BIG') + // ability to include translated invoice status + // in case it was paid + ->status(__('invoices::invoice.paid')) + ->sequence(667) + ->serialNumberFormat('{SEQUENCE}/{SERIES}') + ->seller($client) + ->buyer($customer) + ->date(now()->subWeeks(3)) + ->dateFormat('m/d/Y') + ->payUntilDays(14) + ->currencySymbol('$') + ->currencyCode('USD') + ->currencyFormat('{SYMBOL}{VALUE}') + ->currencyThousandsSeparator('.') + ->currencyDecimalPoint(',') + ->filename($client->name . ' ' . $customer->name) + ->addItems($items) + ->notes($notes) + ->logo(public_path('vendor/invoices/sample-logo.png')) + // You can additionally save generated invoice to configured disk + ->save('public'); + + $link = $invoice->url(); + // Then send email to party with link + + // And return invoice itself to browser or have a different view + return $invoice->stream(); + } + + public static function makeItems($details) + { + $items = []; + + foreach ($details as $detail) { + $items[] = InvoiceItem::make($detail->name)->pricePerUnit($detail->price)->quantity($detail->quantity); + } + + return $items; + } +} diff --git a/app/Repositories/Shop/Orders.php b/app/Repositories/Shop/Orders.php index 105531d9..e6d8da85 100644 --- a/app/Repositories/Shop/Orders.php +++ b/app/Repositories/Shop/Orders.php @@ -4,6 +4,8 @@ namespace App\Repositories\Shop; use App\Models\Shop\Order; use App\Repositories\Core\DateStats; +use App\Repositories\Core\PDF; +use App\Repositories\Shop\Customers; use App\Traits\Model\Basic; use Illuminate\Support\Arr; use Illuminate\Support\Str; @@ -12,15 +14,34 @@ class Orders { use Basic, DateStats; - public static function getByUUID($uuid) + public static function getPdfByUUID($uuid) { - return Order::byUUID($uuid)->first(); + return self::getPdf(self::getIdByUUID($uuid), 'commande-' . $uuid . '.pdf'); + } + + public static function getPdf($id, $file = 'order.pdf') + { + $data = [ + 'order' => Orders::getFull($id), + ]; + + $customerId = Customers::getId(); + if ($customerId !== $data['order']['customer_id']) { + return response()->view('errors.403'); + } + + return PDF::view('Shop.Orders.view', $data, $file); } public static function getFullByUUID($uuid) + { + return self::getFull(self::getIdByUUID($uuid)); + } + + public static function getFull($id) { return Order::with(['customer', 'delivery', 'delivery_address', 'detail', 'invoice.address', 'sale_channel']) - ->byUUID($uuid)->first(); + ->byID($id)->first(); } public static function view($uuid) diff --git a/composer.json b/composer.json index 1055a2b3..078db426 100644 --- a/composer.json +++ b/composer.json @@ -53,6 +53,7 @@ "laravel/tinker": "^2.8", "laravel/ui": "^3.4", "laravelcollective/html": "^6.4", + "laraveldaily/laravel-invoices": "^3.3", "laravolt/avatar": "^4.1", "lavary/laravel-menu": "1.8.3", "league/climate": "^3.8", diff --git a/config/invoices.php b/config/invoices.php new file mode 100644 index 00000000..9bdf1d69 --- /dev/null +++ b/config/invoices.php @@ -0,0 +1,115 @@ + [ + + /* + * Carbon date format + */ + 'format' => 'Y-m-d', + + /* + * Due date for payment since invoice's date. + */ + 'pay_until_days' => 7, + ], + + 'serial_number' => [ + 'series' => 'AA', + 'sequence' => 1, + + /* + * Sequence will be padded accordingly, for ex. 00001 + */ + 'sequence_padding' => 5, + 'delimiter' => '.', + + /* + * Supported tags {SERIES}, {DELIMITER}, {SEQUENCE} + * Example: AA.00001 + */ + 'format' => '{SERIES}{DELIMITER}{SEQUENCE}', + ], + + 'currency' => [ + 'code' => 'eur', + + /* + * Usually cents + * Used when spelling out the amount and if your currency has decimals. + * + * Example: Amount in words: Eight hundred fifty thousand sixty-eight EUR and fifteen ct. + */ + 'fraction' => 'ct.', + 'symbol' => '€', + + /* + * Example: 19.00 + */ + 'decimals' => 2, + + /* + * Example: 1.99 + */ + 'decimal_point' => '.', + + /* + * By default empty. + * Example: 1,999.00 + */ + 'thousands_separator' => '', + + /* + * Supported tags {VALUE}, {SYMBOL}, {CODE} + * Example: 1.99 € + */ + 'format' => '{VALUE} {SYMBOL}', + ], + + 'paper' => [ + // A4 = 210 mm x 297 mm = 595 pt x 842 pt + 'size' => 'a4', + 'orientation' => 'portrait', + ], + + 'disk' => 'local', + + 'seller' => [ + /* + * Class used in templates via $invoice->seller + * + * Must implement LaravelDaily\Invoices\Contracts\PartyContract + * or extend LaravelDaily\Invoices\Classes\Party + */ + 'class' => \LaravelDaily\Invoices\Classes\Seller::class, + + /* + * Default attributes for Seller::class + */ + 'attributes' => [ + 'name' => 'Towne, Smith and Ebert', + 'address' => '89982 Pfeffer Falls Damianstad, CO 66972-8160', + 'code' => '41-1985581', + 'vat' => '123456789', + 'phone' => '760-355-3930', + 'custom_fields' => [ + /* + * Custom attributes for Seller::class + * + * Used to display additional info on Seller section in invoice + * attribute => value + */ + 'SWIFT' => 'BANK101', + ], + ], + ], + + 'dompdf_options' => [ + 'enable_php' => true, + /** + * Do not write log.html or make it optional + * @see https://github.com/dompdf/dompdf/issues/2810 + */ + 'logOutputFile' => '/dev/null', + ], +]; diff --git a/routes/Shop/Orders.php b/routes/Shop/Orders.php index 4987194d..4ca5a567 100644 --- a/routes/Shop/Orders.php +++ b/routes/Shop/Orders.php @@ -6,5 +6,5 @@ Route::prefix('Orders')->name('Orders.')->group(function () { Route::post('order', 'OrderController@store')->name('store'); Route::any('', 'OrderController@index')->name('index'); Route::get('view/{uuid?}', 'OrderController@view')->name('view'); - Route::get('pdf/{uuid?}', 'OrderController@pdf')->name('pdf'); + Route::get('pdf/{uuid?}', 'OrderController@getPdf')->name('pdf'); });