Samson Mutunga 1 rok pred
rodič
commit
f2ea473266

+ 37 - 0
app/Http/Controllers/AdminController.php

@@ -17,6 +17,8 @@ use App\Models\UserEvent;
 use Barryvdh\DomPDF\Facade\Pdf;
 use OpenTok\MediaMode;
 use OpenTok\OpenTok;
+use Illuminate\Support\Facades\Storage;
+use Exception;
 
 class AdminController extends Controller
 {
@@ -452,4 +454,39 @@ class AdminController extends Controller
 
     $res = $this->callJava('/api/user/upsertDetailJson', $data, $this->sessionKey);
   }
+
+  public function uploadFile(Request $request, StoreOrder $order){
+    $fileRef = $request->get('file_name', 'file');
+    $storageResponse = $this->storeFileAs($request, $fileRef, StoreOrder::FILE_PATH);
+    
+    $detailJson = json_decode($order->detail_json ?? '{}', true);
+    $detailJson[$fileRef] = $storageResponse;
+    $order->detail_json = json_encode($detailJson);
+    $order->save();
+    return $this->pass();
+  }
+
+  public function emailReport(Request $request, StoreOrder $order){
+    $results_attachment = $order->getDetailJsonValue('results_attachment');
+    $params = [
+        'to' => [
+            ['email' => $order->user->getEmail(), 'name' => $order->user->displayName()]
+        ],
+        'template' => 'results-report',
+        'subject' => 'Test Results for Order #' . $order->iid,
+        'template_params' => [
+            'user' => $order->user,
+            'order' => $order,
+            'message_body' => $request->get('message')
+        ],
+        'file' => $results_attachment['path']
+    ];
+
+    try{
+        $this->sendEmailNotification($params);
+        return $this->pass();
+    }catch(Exception $e){
+        return $this->fail($e->getMessage());
+    }
+  }
 }

+ 40 - 0
app/Http/Controllers/Controller.php

@@ -9,6 +9,11 @@ use Illuminate\Routing\Controller as BaseController;
 use Illuminate\Support\Facades\Cookie;
 use Illuminate\Support\Facades\Http;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Storage;
+use App\Models\BaseModel;
+use Ramsey\Uuid\Uuid;
+use Illuminate\Support\Facades\Mail;
+use App\Mail\NotifyEmail;
 
 use App\Models\AppSession;
 
@@ -39,6 +44,18 @@ class Controller extends BaseController
         view()->share('user', $this->user);
     }
 
+    public function sendEmailNotification($details){
+        $to = $details['to'];
+        if(config('app.env') !== 'production'){            
+            $to = [
+                ['email' => config('app.testEmailAddress'), 'name' => 'Test Email Address']
+            ];
+        }
+            
+        Mail::to($to)->send(new NotifyEmail($details));
+        return true;
+    }
+
     public function callJava($endPoint, $data, $sessionKey)
     {
         $url = config('app.backendUrl') . $endPoint;
@@ -148,4 +165,27 @@ class Controller extends BaseController
         }
     }
     
+    public function storeFileAs(Request $request, $fileRef, $path){
+        $file = $request->file($fileRef);
+		if ($file) {
+			$uid = Uuid::uuid6();
+            $originalFileName = $file->getClientOriginalName();
+			$fileName = $uid . "." . $file->extension();
+			$tempPath = Storage::putFileAs($path, $file, $fileName);
+            return [
+                'path' => $tempPath,
+                'fileName' => $fileName,
+                'url' => route('view-uploaded-file', $fileName),
+                'orginalFileName' => $originalFileName
+            ];
+		}
+        return null;
+    }
+
+    public function downloadFileByPath($file, $path){
+        return Storage::response($path . '/' . $file);
+    }
+    public function viewUploadedFile(Request $request, $file){
+        return $this->downloadFileByPath($file, BaseModel::FILE_PATH);
+    }
 }

+ 36 - 0
app/Mail/NotifyEmail.php

@@ -0,0 +1,36 @@
+<?php
+  
+namespace App\Mail;
+  
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Mail\Mailable;
+use Illuminate\Queue\SerializesModels;
+  
+class NotifyEmail extends Mailable
+{
+    use Queueable, SerializesModels;
+  
+    public $details;
+  
+    /**
+     * Create a new message instance.
+     *
+     * @return void
+     */
+    public function __construct($details)
+    {
+        $this->details = $details;
+    }
+  
+    /**
+     * Build the message.
+     *
+     * @return $this
+     */
+    public function build()
+    {
+        return $this->subject($this->details['subject'])
+                    ->view('emails.templates.'.$this->details['template'], $this->details['template_params'])->attachFromStorage($this->details['file']);
+    }
+}

+ 2 - 0
app/Models/BaseModel.php

@@ -11,4 +11,6 @@ class BaseModel extends Model
     {
         return 'uid';
     }
+
+    const FILE_PATH = 'public/uploads/files';
 }

+ 18 - 0
app/Models/StoreOrder.php

@@ -12,6 +12,7 @@ class StoreOrder extends BaseModel
     use HasFactory;
 
     protected $table = 'store_order';
+    public $timestamps = false;
 
     public function user(){
         return $this->hasOne(User::class, 'id', 'user_id');
@@ -85,5 +86,22 @@ class StoreOrder extends BaseModel
     public function createdByUser(){
         return $this->hasOne(User::class, 'id', 'created_by_user_id');
     }
+
+    public function detailJson($toArray = false)
+    {
+        if($toArray){
+            return json_decode($this->detail_json ?? '{}', true);
+        }
+        return json_decode($this->detail_json ?? '{}');
+    }
+
+    public function getDetailJsonValue($field)
+    {
+        $parsed = $this->detailJson(true);
+        if (isset($parsed[$field])) {
+            return $parsed[$field];
+        }
+        return null;
+    }
     
 }

+ 1 - 0
config/app.php

@@ -22,6 +22,7 @@ return [
     'backendUrl' => env('BACKEND_URL', 'http://localhost:8080'),
     'stripeKey' => env('STRIPE_KEY'),
     'stripeSecret' => env('seti_1KyIsoCz2jQ0NuhmFeA24Pkg_secret_LfeB5Y5MSoti1xGozn0hFNL50hzqe3r'),
+    'testEmailAddress' => env('TEST_EMAIL_ADDRESS'),
 
     'standardUnitPrice' => env('STANDARD_UNIT_PRICE'),
     'standardShipping' => env('STANDARD_SHIPPING'),

+ 16 - 0
resources/views/app/my-account/admin/orders/forms/email-results-attachment.blade.php

@@ -0,0 +1,16 @@
+<div moe wide>
+    <a start show href="#">Email Results</a>
+    <form url="{{ route('admin.orders.view.email-report', $order) }}">
+        <div class="mb-2">
+            <label class="fw-bold mb-1">Message</label>
+            <textarea name="message" class="form-control form-control-sm" accept="application/pdf" style="min-height:100px;"></textarea>
+        </div>
+        <div class="mb-2">
+            <span class="me-1">Report: <i class="fas fa-paperclip fa-fw"></i> <a href="{{ $results_attachment['url'] }}" target="_blank">{{ $results_attachment['orginalFileName'] }}</a></span>
+        </div>    
+        <div>
+            <button submit class="btn btn-sm btn-primary me-2">Upload</button>
+            <button cancel class="btn btn-sm btn-default border">Cancel</button>
+        </div>
+    </form>
+</div>

+ 23 - 0
resources/views/app/my-account/admin/orders/forms/upload-results-attachment.blade.php

@@ -0,0 +1,23 @@
+<style>
+.mcp-theme-1 #uploadFile input[type="file"]::after {
+    display: none;
+}
+</style>
+<div moe wide>
+    @if(@$edit)
+    <a start show href="#"><i class="fas fa-pencil-alt"></i></a>
+    @else
+    <a start show href="#">Upload Results PDF</a>
+    @endif
+    <form url="{{ route('admin.orders.view.upload-file', $order) }}" id="uploadFile">
+        <input type="hidden" name="file_name" value="results_attachment" />
+        <div class="mb-2">
+            <label class="fw-bold mb-1">Results Attachment</label>
+            <input type="file" name="results_attachment" class="form-control form-control-sm" accept="application/pdf" />
+        </div>   
+        <div>
+            <button submit class="btn btn-sm btn-primary me-2">Upload</button>
+            <button cancel class="btn btn-sm btn-default border">Cancel</button>
+        </div>
+    </form>
+</div>

+ 19 - 0
resources/views/app/my-account/admin/orders/partials/results.blade.php

@@ -0,0 +1,19 @@
+<div>
+    <?php
+        $results_attachment = $order->getDetailJsonValue('results_attachment');
+    ?>
+    @if(!$results_attachment)
+        @include("app.my-account.admin.orders.forms.upload-results-attachment")
+    @else
+    <div class="d-flex align-items-center">
+        <span class="me-1">Report: <i class="fas fa-paperclip fa-fw"></i> <a href="{{ $results_attachment['url'] }}" target="_blank">{{ $results_attachment['orginalFileName'] }}</a></span>
+        <div>
+            @include("app.my-account.admin.orders.forms.upload-results-attachment", ['edit' => true])
+        </div>
+        <span class="text-muted mx-1">|</span>
+        <div>
+            @include('app.my-account.admin.orders.forms.email-results-attachment')
+        </div>
+    </div>
+    @endif
+</div>

+ 4 - 1
resources/views/app/my-account/admin/orders/single.blade.php

@@ -23,7 +23,10 @@
           <span>{{ friendly_date_time($order->created_at)}}</span>
         </div>
         <div>
-          {{-- <a href="{{ route('admin.orders.view.preview-invoice', $order) }}"><i class="fa-solid fa-file-pdf fa-fw"></i> Invoice</a> --}}
+          @include("app.my-account.admin.orders.partials.results")
+        </div>
+        <div>
+          <a href="{{ route('admin.orders.view.preview-invoice', $order) }}" target="_blank"><i class="fa-solid fa-file-pdf fa-fw"></i> Invoice</a>
         </div>
       </div>
       

+ 14 - 0
resources/views/emails/templates/results-report.blade.php

@@ -0,0 +1,14 @@
+<?php
+    $appUrl = config('app.url');
+?>
+
+@extends('emails.layout')
+@section('salutation')
+    Hi, {{$user->displayName()}}!
+@endsection
+
+@section('content')
+    <p class="f-fallback" style="color: #000; font-size: 15px; padding: 0 15px; line-height: 24px; margin: .4em 0 0.1875em;">
+    <?= nl2br($message_body) ?>
+    </p>
+@endsection

+ 5 - 0
routes/web.php

@@ -1,6 +1,7 @@
 <?php
 
 use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\Controller;
 use App\Http\Controllers\AppController;
 use App\Http\Controllers\LogInController;
 use App\Http\Controllers\MyAccountController;
@@ -35,6 +36,8 @@ Route::middleware('ensureUserNotLoggedIn')->group(function () {
 });
 
 Route::group(['middleware' => ['ensureUserLoggedIn']], function () {
+    Route::get('/file/view/{file}', [Controller::class, 'viewUploadedFile'])->name('view-uploaded-file');
+
     Route::get('/search-lab', [MyAccountController::class, 'searchLab'])->name('search-lab');
     Route::prefix('/my-account')->name('my-account')->group(function () {
         Route::get('/', [MyAccountController::class, 'index'])->name('.index');
@@ -70,6 +73,8 @@ Route::group(['middleware' => ['ensureUserLoggedIn']], function () {
                 Route::get('/preview-invoice', [AdminController::class, 'orderPreviewInvoice'])->name('.preview-invoice');
                 Route::get('/financial-transactions', [AdminController::class, 'orderFinancialTransactions'])->name('.financial-transactions');
                 Route::post('/order-charge', [AdminController::class, 'orderCharge'])->name('.order-charge');
+                Route::post('/file/upload', [AdminController::class, 'uploadFile'])->name('.upload-file');
+                Route::post('/email-report', [AdminController::class, 'emailReport'])->name('.email-report');
             });
 
             Route::get('/payment-methods', [AdminController::class, 'paymentMethods'])->name('.payment-methods');