diff --git a/app/Http/Controllers/ContractController.php b/app/Http/Controllers/ContractController.php index 95da4db..efea617 100644 --- a/app/Http/Controllers/ContractController.php +++ b/app/Http/Controllers/ContractController.php @@ -267,6 +267,7 @@ class ContractController extends Controller 'date' => $payment->date, 'amount' => $payment->amount->format(), 'type' => $payment->type, + 'print_link' => $payment->print_link, 'delete_link' => $payment->delete_link, ]; }), diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 785fbe0..3c53a21 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -6,6 +6,7 @@ use Carbon\Carbon; use Inertia\Inertia; use App\Models\Payment; use App\Models\Contract; +use Barryvdh\DomPDF\Facade as PDF; use App\Enums\PaymentType; use Illuminate\Http\Request; use Illuminate\Validation\Rule; @@ -41,6 +42,20 @@ class PaymentController extends Controller return Redirect::route('contracts.show', $payment->contract); } + public function print(Contract $contract, Payment $payment) + { + $contxt = stream_context_create([ + 'ssl' => [ + 'verify_peer' => FALSE, + 'verify_peer_name' => FALSE, + 'allow_self_signed'=> TRUE + ] + ]); + $pdf = PDF::setOptions(['isHtml5ParserEnabled' => true, 'isRemoteEnabled' => true])->loadView('receipt', compact('contract', 'payment')); + $pdf->getDomPDF()->setHttpContext($contxt); + return $pdf->stream($payment->date . '_quittung.pdf'); + } + public function destroy(Request $request, Contract $contract) { if (Payment::destroy((int)$request->get('id'))) { diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 7dd5759..85b40e7 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -65,6 +65,11 @@ class Payment extends Model }; } + public function getPrintLinkAttribute() + { + return route('payments.print', [$this->contract->id, $this->id]); + } + public function getDeleteLinkAttribute() { return route('payments.destroy', [$this->contract->id, $this->id]); diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 8fbd222..d8c65bc 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -4,6 +4,7 @@ namespace App\Providers; use App\Models\Car; use App\Models\Contact; +use App\Models\Payment; use App\Models\Contract; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; @@ -56,12 +57,16 @@ class RouteServiceProvider extends ServiceProvider }); Route::bind('contract', function ($value) { - if (in_array(Route::currentRouteName(), ['contracts.show', 'contracts.restore', 'payments.destroy'])) { + if (in_array(Route::currentRouteName(), ['contracts.show', 'contracts.restore', 'payments.destroy', 'payments.print'])) { return Contract::withTrashed()->find($value); } return Contract::find($value); }); + Route::bind('payment', function ($value) { + return \App\Models\Payment::find($value); + }); + Route::prefix('api') ->middleware('api') ->namespace($this->namespace) diff --git a/public/js/app.js b/public/js/app.js index 173c286..6a8f81d 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -20493,6 +20493,10 @@ __webpack_require__.r(__webpack_exports__); key: 'type', value: 'Bezahlart', sortable: false + }, { + key: 'print', + value: 'Quittung', + sortable: false }, { key: 'delete', value: '', @@ -26153,26 +26157,27 @@ var _hoisted_13 = { "class": "flex items-center" }; var _hoisted_14 = ["onClick"]; -var _hoisted_15 = { - key: 2, +var _hoisted_15 = ["href"]; +var _hoisted_16 = { + key: 3, "class": "2xl:px-5 lg:px-3 px-2 2xl:py-4 lg:py-3 py-2 flex items-center" }; -var _hoisted_16 = { +var _hoisted_17 = { key: 0, "class": "border-t w-px" }; -var _hoisted_17 = { +var _hoisted_18 = { key: 0 }; -var _hoisted_18 = ["colspan"]; -var _hoisted_19 = { +var _hoisted_19 = ["colspan"]; +var _hoisted_20 = { key: 3 }; -var _hoisted_20 = { +var _hoisted_21 = { "class": "inline-flex font-medium text-gray-500 ml-3" }; -var _hoisted_21 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Keine Einträge gefunden "); +var _hoisted_22 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Keine Einträge gefunden "); function render(_ctx, _cache, $props, $setup, $data, $options) { var _this = this; @@ -26294,12 +26299,25 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { name: "trash-alt" })], 8 /* PROPS */ - , _hoisted_14)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_15, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($options.resolve(col.key, row)), 1 + , _hoisted_14)) : col.key == 'print' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", { + key: 2, + "class": "2xl:px-5 lg:px-3 px-2 2xl:py-4 lg:py-3 py-2 flex items-center", + target: "_blank", + href: row.print_link + }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_unicon, { + fill: "#b2b7ff", + "hover-fill": "indigo", + height: "24", + width: "24", + name: "file-download" + })], 8 + /* PROPS */ + , _hoisted_15)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_16, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($options.resolve(col.key, row)), 1 /* TEXT */ ))]); }), 128 /* KEYED_FRAGMENT */ - )), row.link && !$props.hideArrow ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("td", _hoisted_16, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_inertia_link, { + )), row.link && !$props.hideArrow ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("td", _hoisted_17, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_inertia_link, { "class": "xl:pr-4 pr-2 xl:py-4 py-2 flex items-center", href: row.link, tabindex: "-1" @@ -26319,18 +26337,18 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { , ["href"])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)]); }), 128 /* KEYED_FRAGMENT */ - )), $props.data.total === 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("tr", _hoisted_17, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("td", { + )), $props.data.total === 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("tr", _hoisted_18, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("td", { "class": "border-t px-6 py-4", colspan: $props.columns.length }, "Keine Einträge gefunden", 8 /* PROPS */ - , _hoisted_18)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)])])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_19, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", _hoisted_20, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_unicon, { + , _hoisted_19)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)])])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_20, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", _hoisted_21, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_unicon, { fill: "#7e8491", "class": "mr-2", height: "24", width: "24", name: "meh" - }), _hoisted_21])])), $props.data.links ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(_component_Paginator, { + }), _hoisted_22])])), $props.data.links ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(_component_Paginator, { key: 4, "class": "mt-6", links: $props.data.links diff --git a/resources/js/Components/Payments/View.vue b/resources/js/Components/Payments/View.vue index f31c833..44c0a2d 100644 --- a/resources/js/Components/Payments/View.vue +++ b/resources/js/Components/Payments/View.vue @@ -24,6 +24,7 @@ export default { { key: 'date', value: 'Datum', sortable: false }, { key: 'amount', value: 'Betrag', sortable: false }, { key: 'type', value: 'Bezahlart', sortable: false }, + { key: 'print', value: 'Quittung', sortable: false }, { key: 'delete', value: '', sortable: false }, ], }; diff --git a/resources/js/Components/SimpleTable.vue b/resources/js/Components/SimpleTable.vue index b5dd1c8..4978b12 100644 --- a/resources/js/Components/SimpleTable.vue +++ b/resources/js/Components/SimpleTable.vue @@ -38,6 +38,9 @@ + + + {{ resolve(col.key, row) }} diff --git a/resources/views/receipt.blade.php b/resources/views/receipt.blade.php new file mode 100644 index 0000000..cc72646 --- /dev/null +++ b/resources/views/receipt.blade.php @@ -0,0 +1,134 @@ + + + + + + + Quittung - {{ $contract->car->name }} - {{ $contract->contact->full_title }} + + + + + + + + + +
+
+Your SwissCar GmbH
+Bernstrasse 27
+8952 Schlieren
+
+Tel: 079 680 34 44
+E-Mail: info@yourswisscar.com
+
+MwSt-Nr: CHE-226.272.050
+                
+
+ + + + +

+ Quittung +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VerkäuferYour SwissCar GmbHKäufer{{ $contract->contact->full_title }}
StrasseBernstrasse 27Strasse{{ $contract->contact->address }}
PLZ / Ort8952 SchlierenPLZ / Ort{{ $contract->contact->full_city }}
Telefon079 680 34 44Telefon{{ $contract->contact->phone }}
  E-Mail{{ $contract->contact->email }}
 
+ + + + + + + + + +
Fahrzeug:
{{ $contract->car->name_with_year }}, Stammnr.: {{ $contract->car->stammnummer }}
 
Hiermit wird die folgende Einzahlung für das oben genannte Fahrzeug bestätigt:
+ + + + + + + + + + + + + + + + +

+
Datum{{ $payment->date }}
Zahlungsart{{ $payment->type }}
Betrag

{{ $payment->amount->format() }}

 
 
 
+ + + + + + + +
Ort, Datum
 
Schlieren, {{ $payment->date }}
+ + \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index d294df2..518f2e9 100644 --- a/routes/web.php +++ b/routes/web.php @@ -72,6 +72,7 @@ Route::middleware(['auth:sanctum', 'verified'])->group(function () { Route::get('create', [PaymentController::class, 'create'])->name('payments.create'); Route::delete('delete', [PaymentController::class, 'destroy'])->name('payments.destroy'); Route::post('/', [PaymentController::class, 'store'])->name('payments.store'); + Route::get('{payment}/print', [PaymentController::class, 'print'])->name('payments.print'); }); });