From b5076a6f9dc88a44009554349164728d33afc074 Mon Sep 17 00:00:00 2001 From: Fairuz Date: Thu, 16 Sep 2021 20:47:33 +0800 Subject: [PATCH] Excel library, controllers --- .gitignore | 3 +- .../Processors/FetchPackingListProcessor.php | 63 ++++ .../CustomcClearanceLogic.php | 38 ++ .../ControllersLogic/ExportExcelLogic.php | 51 +++ .../CustomcClearanceReportController.php | 17 + composer.json | 1 + config/app.php | 4 +- config/excel.php | 328 ++++++++++++++++++ resources/views/layouts/base_portal.blade.php | 13 +- routes/web.php | 2 + 10 files changed, 517 insertions(+), 3 deletions(-) create mode 100644 app/Classes/Modules/PackingLists/Processors/FetchPackingListProcessor.php create mode 100644 app/Classes/Modules/Reports/ControllersLogic/CustomcClearanceLogic.php create mode 100644 app/Classes/Modules/Reports/ControllersLogic/ExportExcelLogic.php create mode 100644 app/Http/Controllers/Reports/CustomcClearanceReportController.php create mode 100644 config/excel.php diff --git a/.gitignore b/.gitignore index 95d268cf..9b34cbea 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ db/* docker-compose.yml package-lock.json public/* -/public/* \ No newline at end of file +/public/* +storage/framework/laravel-excel/* diff --git a/app/Classes/Modules/PackingLists/Processors/FetchPackingListProcessor.php b/app/Classes/Modules/PackingLists/Processors/FetchPackingListProcessor.php new file mode 100644 index 00000000..b128aeed --- /dev/null +++ b/app/Classes/Modules/PackingLists/Processors/FetchPackingListProcessor.php @@ -0,0 +1,63 @@ +listsPackingLists = $listsPackingLists; + } + + /** + * @return array + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function execute(){ + + $packingLists = PackingList::where('type', '=', PackingListType::SHIPPING_PACKING_LIST) + ->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::SUSPENDED]) + ->whereDoesntHave('containers', function($query){ + $query->where('status', '=', ApprovalStatus::COMPLETED); + })->orderBy('created_at','desc')->limit(5)->get(); + + $packingListsArray=[]; + foreach($packingLists as $packingList){ + + $address = $packingList->owner->addresses()->first(); + $packingList->fulladdress = $address->street_one.', '.$address->street_two.', '.$address->district->name.', '.$address->post_code.' '.$address->state->name.', '.$address->country->name; + + $container = $packingList->containers()->first(); + $packingList->container_reference = $container->reference; + $packingList->container_number = $container->container_number; + + $packingListsArray[]=$packingList; + + } + + return $packingListsArray; + + } + + +} diff --git a/app/Classes/Modules/Reports/ControllersLogic/CustomcClearanceLogic.php b/app/Classes/Modules/Reports/ControllersLogic/CustomcClearanceLogic.php new file mode 100644 index 00000000..5557c185 --- /dev/null +++ b/app/Classes/Modules/Reports/ControllersLogic/CustomcClearanceLogic.php @@ -0,0 +1,38 @@ +listsPackingListProcessor = $listsPackingListProcessor; + } + + protected function notification():array { + return []; + } + + public function logic(Request $request) : JsonResponse + { + $packingLists = $this->listsPackingListProcessor->execute(); + $excelExportLogic = new ExportExcelLogic(collect($packingLists)); + $this->excelExportLogic = $excelExportLogic; + + return response()->json(['success' => true]); + } + + public function getExcelCollection(){ + return $this->excelExportLogic; + } +} diff --git a/app/Classes/Modules/Reports/ControllersLogic/ExportExcelLogic.php b/app/Classes/Modules/Reports/ControllersLogic/ExportExcelLogic.php new file mode 100644 index 00000000..ede392b4 --- /dev/null +++ b/app/Classes/Modules/Reports/ControllersLogic/ExportExcelLogic.php @@ -0,0 +1,51 @@ +data=$data; + } + public function collection() + { + return $this->data; + } + public function map($order): array + { + return [ + (string)$order->reference, + (string)$order->container_number, + (string)$order->fulladdress, + (string)$order->created_at, + "ssxxx" + ]; + } + + public function columnFormats(): array + { + return [ + 'A'=>'@', + 'B' => NumberFormat::FORMAT_DATE_DDMMYYYY, + + ]; + } + + public function headings(): array + { + return ["Reference", "Container", "Address", "Created", "Status"]; + } + +} diff --git a/app/Http/Controllers/Reports/CustomcClearanceReportController.php b/app/Http/Controllers/Reports/CustomcClearanceReportController.php new file mode 100644 index 00000000..e7d24ff0 --- /dev/null +++ b/app/Http/Controllers/Reports/CustomcClearanceReportController.php @@ -0,0 +1,17 @@ +logic($request); + return Excel::download( $customClearancelogic->getExcelCollection(), $filename.'.xlsx'); + } +} diff --git a/composer.json b/composer.json index 824d2d3f..56ab4aac 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "intervention/image": "^2.5", "laravel/framework": "^8.40", "laravel/tinker": "^2.5", + "maatwebsite/excel": "^3.1", "rinvex/countries": "^6.1", "spatie/laravel-activitylog": "^3.14", "spatie/laravel-permission": "^4.2", diff --git a/config/app.php b/config/app.php index bad26462..df3e7a90 100644 --- a/config/app.php +++ b/config/app.php @@ -178,7 +178,8 @@ return [ // Third Parties Spatie\Permission\PermissionServiceProvider::class, Barryvdh\DomPDF\ServiceProvider::class, - Meneses\LaravelMpdf\LaravelMpdfServiceProvider::class + Meneses\LaravelMpdf\LaravelMpdfServiceProvider::class, + Maatwebsite\Excel\ExcelServiceProvider::class, ], /* @@ -233,6 +234,7 @@ return [ 'View' => Illuminate\Support\Facades\View::class, 'PDF' => Barryvdh\DomPDF\Facade::class, 'MPDF' => Meneses\LaravelMpdf\Facades\LaravelMpdf::class, + 'Excel' => Maatwebsite\Excel\Facades\Excel::class, ], ]; diff --git a/config/excel.php b/config/excel.php new file mode 100644 index 00000000..c3199b92 --- /dev/null +++ b/config/excel.php @@ -0,0 +1,328 @@ + [ + + /* + |-------------------------------------------------------------------------- + | Chunk size + |-------------------------------------------------------------------------- + | + | When using FromQuery, the query is automatically chunked. + | Here you can specify how big the chunk should be. + | + */ + 'chunk_size' => 1000, + + /* + |-------------------------------------------------------------------------- + | Pre-calculate formulas during export + |-------------------------------------------------------------------------- + */ + 'pre_calculate_formulas' => false, + + /* + |-------------------------------------------------------------------------- + | Enable strict null comparison + |-------------------------------------------------------------------------- + | + | When enabling strict null comparison empty cells ('') will + | be added to the sheet. + */ + 'strict_null_comparison' => false, + + /* + |-------------------------------------------------------------------------- + | CSV Settings + |-------------------------------------------------------------------------- + | + | Configure e.g. delimiter, enclosure and line ending for CSV exports. + | + */ + 'csv' => [ + 'delimiter' => ',', + 'enclosure' => '"', + 'line_ending' => PHP_EOL, + 'use_bom' => false, + 'include_separator_line' => false, + 'excel_compatibility' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Worksheet properties + |-------------------------------------------------------------------------- + | + | Configure e.g. default title, creator, subject,... + | + */ + 'properties' => [ + 'creator' => '', + 'lastModifiedBy' => '', + 'title' => '', + 'description' => '', + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'manager' => '', + 'company' => '', + ], + ], + + 'imports' => [ + + /* + |-------------------------------------------------------------------------- + | Read Only + |-------------------------------------------------------------------------- + | + | When dealing with imports, you might only be interested in the + | data that the sheet exists. By default we ignore all styles, + | however if you want to do some logic based on style data + | you can enable it by setting read_only to false. + | + */ + 'read_only' => true, + + /* + |-------------------------------------------------------------------------- + | Ignore Empty + |-------------------------------------------------------------------------- + | + | When dealing with imports, you might be interested in ignoring + | rows that have null values or empty strings. By default rows + | containing empty strings or empty values are not ignored but can be + | ignored by enabling the setting ignore_empty to true. + | + */ + 'ignore_empty' => false, + + /* + |-------------------------------------------------------------------------- + | Heading Row Formatter + |-------------------------------------------------------------------------- + | + | Configure the heading row formatter. + | Available options: none|slug|custom + | + */ + 'heading_row' => [ + 'formatter' => 'slug', + ], + + /* + |-------------------------------------------------------------------------- + | CSV Settings + |-------------------------------------------------------------------------- + | + | Configure e.g. delimiter, enclosure and line ending for CSV imports. + | + */ + 'csv' => [ + 'delimiter' => ',', + 'enclosure' => '"', + 'escape_character' => '\\', + 'contiguous' => false, + 'input_encoding' => 'UTF-8', + ], + + /* + |-------------------------------------------------------------------------- + | Worksheet properties + |-------------------------------------------------------------------------- + | + | Configure e.g. default title, creator, subject,... + | + */ + 'properties' => [ + 'creator' => '', + 'lastModifiedBy' => '', + 'title' => '', + 'description' => '', + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'manager' => '', + 'company' => '', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Extension detector + |-------------------------------------------------------------------------- + | + | Configure here which writer/reader type should be used when the package + | needs to guess the correct type based on the extension alone. + | + */ + 'extension_detector' => [ + 'xlsx' => Excel::XLSX, + 'xlsm' => Excel::XLSX, + 'xltx' => Excel::XLSX, + 'xltm' => Excel::XLSX, + 'xls' => Excel::XLS, + 'xlt' => Excel::XLS, + 'ods' => Excel::ODS, + 'ots' => Excel::ODS, + 'slk' => Excel::SLK, + 'xml' => Excel::XML, + 'gnumeric' => Excel::GNUMERIC, + 'htm' => Excel::HTML, + 'html' => Excel::HTML, + 'csv' => Excel::CSV, + 'tsv' => Excel::TSV, + + /* + |-------------------------------------------------------------------------- + | PDF Extension + |-------------------------------------------------------------------------- + | + | Configure here which Pdf driver should be used by default. + | Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF + | + */ + 'pdf' => Excel::DOMPDF, + ], + + /* + |-------------------------------------------------------------------------- + | Value Binder + |-------------------------------------------------------------------------- + | + | PhpSpreadsheet offers a way to hook into the process of a value being + | written to a cell. In there some assumptions are made on how the + | value should be formatted. If you want to change those defaults, + | you can implement your own default value binder. + | + | Possible value binders: + | + | [x] Maatwebsite\Excel\DefaultValueBinder::class + | [x] PhpOffice\PhpSpreadsheet\Cell\StringValueBinder::class + | [x] PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class + | + */ + 'value_binder' => [ + 'default' => Maatwebsite\Excel\DefaultValueBinder::class, + ], + + 'cache' => [ + /* + |-------------------------------------------------------------------------- + | Default cell caching driver + |-------------------------------------------------------------------------- + | + | By default PhpSpreadsheet keeps all cell values in memory, however when + | dealing with large files, this might result into memory issues. If you + | want to mitigate that, you can configure a cell caching driver here. + | When using the illuminate driver, it will store each value in a the + | cache store. This can slow down the process, because it needs to + | store each value. You can use the "batch" store if you want to + | only persist to the store when the memory limit is reached. + | + | Drivers: memory|illuminate|batch + | + */ + 'driver' => 'memory', + + /* + |-------------------------------------------------------------------------- + | Batch memory caching + |-------------------------------------------------------------------------- + | + | When dealing with the "batch" caching driver, it will only + | persist to the store when the memory limit is reached. + | Here you can tweak the memory limit to your liking. + | + */ + 'batch' => [ + 'memory_limit' => 60000, + ], + + /* + |-------------------------------------------------------------------------- + | Illuminate cache + |-------------------------------------------------------------------------- + | + | When using the "illuminate" caching driver, it will automatically use + | your default cache store. However if you prefer to have the cell + | cache on a separate store, you can configure the store name here. + | You can use any store defined in your cache config. When leaving + | at "null" it will use the default store. + | + */ + 'illuminate' => [ + 'store' => null, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Transaction Handler + |-------------------------------------------------------------------------- + | + | By default the import is wrapped in a transaction. This is useful + | for when an import may fail and you want to retry it. With the + | transactions, the previous import gets rolled-back. + | + | You can disable the transaction handler by setting this to null. + | Or you can choose a custom made transaction handler here. + | + | Supported handlers: null|db + | + */ + 'transactions' => [ + 'handler' => 'db', + ], + + 'temporary_files' => [ + + /* + |-------------------------------------------------------------------------- + | Local Temporary Path + |-------------------------------------------------------------------------- + | + | When exporting and importing files, we use a temporary file, before + | storing reading or downloading. Here you can customize that path. + | + */ + 'local_path' => storage_path('framework/laravel-excel'), + + /* + |-------------------------------------------------------------------------- + | Remote Temporary Disk + |-------------------------------------------------------------------------- + | + | When dealing with a multi server setup with queues in which you + | cannot rely on having a shared local temporary path, you might + | want to store the temporary file on a shared disk. During the + | queue executing, we'll retrieve the temporary file from that + | location instead. When left to null, it will always use + | the local path. This setting only has effect when using + | in conjunction with queued imports and exports. + | + */ + 'remote_disk' => null, + 'remote_prefix' => null, + + /* + |-------------------------------------------------------------------------- + | Force Resync + |-------------------------------------------------------------------------- + | + | When dealing with a multi server setup as above, it's possible + | for the clean up that occurs after entire queue has been run to only + | cleanup the server that the last AfterImportJob runs on. The rest of the server + | would still have the local temporary file stored on it. In this case your + | local storage limits can be exceeded and future imports won't be processed. + | To mitigate this you can set this config value to be true, so that after every + | queued chunk is processed the local temporary file is deleted on the server that + | processed it. + | + */ + 'force_resync_remote' => null, + ], +]; diff --git a/resources/views/layouts/base_portal.blade.php b/resources/views/layouts/base_portal.blade.php index 87144464..c12f1e3e 100644 --- a/resources/views/layouts/base_portal.blade.php +++ b/resources/views/layouts/base_portal.blade.php @@ -22,6 +22,17 @@
+
@@ -108,4 +119,4 @@ -@endsection \ No newline at end of file +@endsection diff --git a/routes/web.php b/routes/web.php index 2eb2bcbb..ca3457bc 100644 --- a/routes/web.php +++ b/routes/web.php @@ -107,6 +107,8 @@ Route::get('/deliveries/refresh', function(){ Route::get('/order/{id}/download', 'Orders\DownloadOrderQrPdfController@download')->name('order.qr.download'); +Route::get('/report/customclearance', 'Reports\CustomcClearanceReportController@download')->name('report.customclearance'); + //Route::get('/test', function(){ // $addresses = \App\Models\Address::all(); // foreach ($addresses as $address){