瀏覽代碼

wip print documents

3.x
Andrew Wallo 7 月之前
父節點
當前提交
dda5c032b2

+ 14
- 0
app/Filament/Company/Resources/Sales/EstimateResource/Pages/ViewEstimate.php 查看文件

@@ -34,6 +34,20 @@ class ViewEstimate extends ViewRecord
34 34
     protected function getHeaderActions(): array
35 35
     {
36 36
         return [
37
+            Actions\Action::make('printPdf')
38
+                ->label('Export PDF')
39
+                ->icon('heroicon-o-document-arrow-down')
40
+                ->outlined()
41
+                ->action(function (Estimate $record) {
42
+                    $url = route('documents.print', [
43
+                        'documentType' => $record::documentType(),
44
+                        'id' => $record->id,
45
+                    ]);
46
+
47
+                    $title = 'Print Estimate';
48
+
49
+                    $this->js("window.printPdf('{$url}', '{$title}')");
50
+                }),
37 51
             Actions\EditAction::make()
38 52
                 ->label('Edit estimate')
39 53
                 ->outlined(),

+ 14
- 0
app/Filament/Company/Resources/Sales/InvoiceResource/Pages/ViewInvoice.php 查看文件

@@ -34,6 +34,20 @@ class ViewInvoice extends ViewRecord
34 34
     protected function getHeaderActions(): array
35 35
     {
36 36
         return [
37
+            Actions\Action::make('printPdf')
38
+                ->label('Export PDF')
39
+                ->icon('heroicon-o-document-arrow-down')
40
+                ->outlined()
41
+                ->action(function (Invoice $record) {
42
+                    $url = route('documents.print', [
43
+                        'documentType' => $record::documentType(),
44
+                        'id' => $record->id,
45
+                    ]);
46
+
47
+                    $title = 'Print Invoice';
48
+
49
+                    $this->js("window.printPdf('{$url}', '{$title}')");
50
+                }),
37 51
             Actions\EditAction::make()
38 52
                 ->label('Edit invoice')
39 53
                 ->outlined(),

+ 14
- 0
app/Filament/Company/Resources/Sales/RecurringInvoiceResource/Pages/ViewRecurringInvoice.php 查看文件

@@ -34,6 +34,20 @@ class ViewRecurringInvoice extends ViewRecord
34 34
     protected function getHeaderActions(): array
35 35
     {
36 36
         return [
37
+            Actions\Action::make('printPdf')
38
+                ->label('Export PDF')
39
+                ->icon('heroicon-o-document-arrow-down')
40
+                ->outlined()
41
+                ->action(function (RecurringInvoice $record) {
42
+                    $url = route('documents.print', [
43
+                        'documentType' => $record::documentType(),
44
+                        'id' => $record->id,
45
+                    ]);
46
+
47
+                    $title = 'Print Recurring Invoice';
48
+
49
+                    $this->js("window.printPdf('{$url}', '{$title}')");
50
+                }),
37 51
             Actions\EditAction::make()
38 52
                 ->label('Edit recurring invoice')
39 53
                 ->outlined(),

+ 48
- 0
app/Http/Controllers/DocumentPrintController.php 查看文件

@@ -0,0 +1,48 @@
1
+<?php
2
+
3
+namespace App\Http\Controllers;
4
+
5
+use App\DTO\DocumentDTO;
6
+use App\Enums\Accounting\DocumentType;
7
+use App\Enums\Setting\Template;
8
+use App\Models\Accounting\Estimate;
9
+use App\Models\Accounting\Invoice;
10
+use App\Models\Accounting\RecurringInvoice;
11
+use App\Models\Setting\DocumentDefault;
12
+use Illuminate\Http\Request;
13
+
14
+class DocumentPrintController extends Controller
15
+{
16
+    protected array $documentModels = [
17
+        'invoice' => Invoice::class,
18
+        'recurring_invoice' => RecurringInvoice::class,
19
+        'estimate' => Estimate::class,
20
+    ];
21
+
22
+    public function show(Request $request, string $documentType, int $id)
23
+    {
24
+        if (! isset($this->documentModels[$documentType])) {
25
+            abort(404, "Invalid document type: {$documentType}");
26
+        }
27
+
28
+        $modelClass = $this->documentModels[$documentType];
29
+        $document = $modelClass::findOrFail($id);
30
+        $documentTypeEnum = $document::documentType();
31
+
32
+        if ($documentTypeEnum === DocumentType::RecurringInvoice) {
33
+            $documentTypeEnum = DocumentType::Invoice;
34
+        }
35
+
36
+        $defaults = DocumentDefault::query()
37
+            ->type($documentTypeEnum)
38
+            ->first();
39
+
40
+        $template = $defaults?->template ?? Template::Default;
41
+        $document = DocumentDTO::fromModel($document);
42
+
43
+        return view('print-document', [
44
+            'document' => $document,
45
+            'template' => $template,
46
+        ]);
47
+    }
48
+}

+ 1
- 0
app/Providers/AppServiceProvider.php 查看文件

@@ -32,6 +32,7 @@ class AppServiceProvider extends ServiceProvider
32 32
         FilamentAsset::register([
33 33
             Js::make('top-navigation', __DIR__ . '/../../resources/js/top-navigation.js'),
34 34
             Js::make('history-fix', __DIR__ . '/../../resources/js/history-fix.js'),
35
+            Js::make('custom-print', __DIR__ . '/../../resources/js/custom-print.js'),
35 36
         ]);
36 37
     }
37 38
 }

+ 11
- 11
composer.lock 查看文件

@@ -220,23 +220,23 @@
220 220
         },
221 221
         {
222 222
             "name": "andrewdwallo/transmatic",
223
-            "version": "v1.1.1",
223
+            "version": "v1.2.0",
224 224
             "source": {
225 225
                 "type": "git",
226 226
                 "url": "https://github.com/andrewdwallo/transmatic.git",
227
-                "reference": "30f5384e7e3b693beaf528b01650570a916daf47"
227
+                "reference": "b70c5a5ed58e6ed951651cb4ea00357e53c1748d"
228 228
             },
229 229
             "dist": {
230 230
                 "type": "zip",
231
-                "url": "https://api.github.com/repos/andrewdwallo/transmatic/zipball/30f5384e7e3b693beaf528b01650570a916daf47",
232
-                "reference": "30f5384e7e3b693beaf528b01650570a916daf47",
231
+                "url": "https://api.github.com/repos/andrewdwallo/transmatic/zipball/b70c5a5ed58e6ed951651cb4ea00357e53c1748d",
232
+                "reference": "b70c5a5ed58e6ed951651cb4ea00357e53c1748d",
233 233
                 "shasum": ""
234 234
             },
235 235
             "require": {
236 236
                 "aws/aws-sdk-php-laravel": "^3.8",
237 237
                 "ext-intl": "*",
238 238
                 "ext-json": "*",
239
-                "illuminate/contracts": "^10.0|^11.0",
239
+                "illuminate/contracts": "^10.0|^11.0|^12.0",
240 240
                 "php": "^8.1",
241 241
                 "spatie/laravel-package-tools": "^1.14.0"
242 242
             },
@@ -244,10 +244,10 @@
244 244
                 "larastan/larastan": "^2.9",
245 245
                 "laravel/pint": "^1.0",
246 246
                 "nunomaduro/collision": "^7.8|^8.0",
247
-                "orchestra/testbench": "^8.8|^9.0",
248
-                "pestphp/pest": "^2.20",
249
-                "pestphp/pest-plugin-arch": "^2.0",
250
-                "pestphp/pest-plugin-laravel": "^2.0",
247
+                "orchestra/testbench": "^8.8|^9.0|^10.0",
248
+                "pestphp/pest": "^2.20|^3.0",
249
+                "pestphp/pest-plugin-arch": "^2.0|^3.0",
250
+                "pestphp/pest-plugin-laravel": "^2.0|^3.0",
251 251
                 "phpstan/extension-installer": "^1.1",
252 252
                 "phpstan/phpstan-deprecation-rules": "^1.0",
253 253
                 "phpstan/phpstan-phpunit": "^1.0",
@@ -296,9 +296,9 @@
296 296
             ],
297 297
             "support": {
298 298
                 "issues": "https://github.com/andrewdwallo/transmatic/issues",
299
-                "source": "https://github.com/andrewdwallo/transmatic/tree/v1.1.1"
299
+                "source": "https://github.com/andrewdwallo/transmatic/tree/v1.2.0"
300 300
             },
301
-            "time": "2025-01-26T05:48:43+00:00"
301
+            "time": "2025-03-02T00:21:46+00:00"
302 302
         },
303 303
         {
304 304
             "name": "anourvalar/eloquent-serialize",

+ 21
- 0
resources/js/custom-print.js 查看文件

@@ -0,0 +1,21 @@
1
+function printPdf(url, title) {
2
+    if (title) {
3
+        document.title = title;
4
+    }
5
+
6
+    const iframe = document.createElement('iframe');
7
+    iframe.style.visibility = 'hidden';
8
+    iframe.style.position = 'absolute';
9
+    iframe.style.width = '0';
10
+    iframe.style.height = '0';
11
+    iframe.src = url;
12
+    document.body.appendChild(iframe);
13
+
14
+    iframe.onload = function () {
15
+        try {
16
+            iframe.contentWindow.print();
17
+        } catch (e) {
18
+            console.error('Error printing PDF:', e);
19
+        }
20
+    };
21
+}

+ 66
- 0
resources/views/print-document.blade.php 查看文件

@@ -0,0 +1,66 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+    <title>Invoice #{{ $document->number }}</title>
5
+    <meta charset="utf-8">
6
+    <meta name="viewport" content="width=device-width, initial-scale=1">
7
+    <meta name="color-scheme" content="light">
8
+
9
+    <!-- Include Tailwind -->
10
+    <script src="https://cdn.tailwindcss.com?plugins=typography"></script>
11
+    <script>
12
+        tailwind.config = {
13
+            darkMode: 'class'
14
+        }
15
+    </script>
16
+
17
+    {!! $document->getFontHtml() !!}
18
+
19
+    <style>
20
+        :root {
21
+            color-scheme: light;
22
+        }
23
+
24
+        body {
25
+            background-color: white;
26
+            color: black;
27
+        }
28
+
29
+        .inv-paper {
30
+            font-family: '{{ $document->font->getLabel() }}', sans-serif;
31
+        }
32
+
33
+        @media print {
34
+            body {
35
+                print-color-adjust: exact !important;
36
+                -webkit-print-color-adjust: exact !important;
37
+                margin: 0;
38
+                padding: 0;
39
+            }
40
+
41
+            @page {
42
+                size: auto;
43
+                margin: 0;
44
+            }
45
+
46
+            .inv-container {
47
+                padding: 0 !important;
48
+                margin: 0 !important;
49
+            }
50
+
51
+            .inv-paper {
52
+                box-shadow: none !important;
53
+                border-radius: 0 !important;
54
+                overflow: hidden !important;
55
+                max-height: none !important;
56
+            }
57
+        }
58
+    </style>
59
+</head>
60
+<body class="bg-white">
61
+    @include("filament.infolists.components.document-templates.{$template->value}", [
62
+        'document' => $document,
63
+        'preview' => false,
64
+    ])
65
+</body>
66
+</html>

+ 6
- 0
routes/web.php 查看文件

@@ -1,7 +1,13 @@
1 1
 <?php
2 2
 
3
+use App\Http\Controllers\DocumentPrintController;
3 4
 use Illuminate\Support\Facades\Route;
4 5
 
5 6
 Route::get('/', function () {
6 7
     return view('welcome');
7 8
 });
9
+
10
+Route::middleware(['auth'])->group(function () {
11
+    Route::get('documents/{documentType}/{id}/print', [DocumentPrintController::class, 'show'])
12
+        ->name('documents.print');
13
+});

Loading…
取消
儲存