diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListUrgentTransactionsLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListUrgentTransactionsLogic.php new file mode 100644 index 00000000..35a57e48 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListUrgentTransactionsLogic.php @@ -0,0 +1,49 @@ +listsTransactions = $listsTransactions; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Retrieved Transactions Urgent', + 'message' => 'You have successfully retrieved a list of transactions' + ]; + } + + /** @var ListsTransactions */ + private $listsTransactions; + + + + public function logic(Request $request) : JsonResponse + { + + $query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(TransactionUrgentResource::collection($query)); + + } + + + +} diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php index 2be4a3fb..1aa5210b 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php @@ -8,6 +8,7 @@ use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\DocumentType; use App\Models\Document; +use Illuminate\Support\Facades\Log; use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf; use Webklex\PDFMerger\Facades\PDFMergerFacade as PDFMerger; use Illuminate\Support\Facades\Storage; @@ -50,22 +51,44 @@ class CreateInvoiceDocumentProcessor $oMerger = PDFMerger::init(); + + $saveDirectory = storage_path('app/documents'); + if (!file_exists($saveDirectory)) { + mkdir($saveDirectory, 0755, true); + } + $order_pdf->save(storage_path('app/documents/temp.pdf')); $oMerger->addPDF(storage_path('app/documents/temp.pdf'), 'all'); $filesystemDriver = Storage::getDefaultDriver(); foreach ($purchaseOrderDocuments as $document){ - $localFilePath = storage_path('app/documents/' . $document->files()->first()->file->file_info->original->file); - $oMerger->addPDF($localFilePath, 'all'); + $currentFile = $document->files()->first()->file->file_info->original->file; if($filesystemDriver === 's3'){ - $filePathForS3 = 'documents/'.$document->files()->first()->file->file_info->original->file; - Storage::disk('s3')->put($filePathForS3, file_get_contents($localFilePath)); + Log::info('CreateInvoiceDocumentProcessor 1: ' . $currentFile); + $fileContent = Storage::disk('s3')->get($currentFile); + $filepath = storage_path('app/documents/' . $currentFile); + $directoryPath = dirname($filepath); + if (!file_exists($directoryPath)) { + mkdir($directoryPath, 0755, true); + } + file_put_contents($filepath, $fileContent); } + + $localFilePath = storage_path('app/documents/' . $currentFile); + $oMerger->addPDF($localFilePath, 'all'); } $oMerger->merge(); $order_pdf = $oMerger; + + if($filesystemDriver === 's3'){ + $finalTempPdfPath = storage_path('app/documents/temp.pdf'); + $filePathForS3 = 'temp/temp.pdf'; + $fileContent = file_get_contents($finalTempPdfPath); + Log::info('CreateInvoiceDocumentProcessor 2 filePathForS3: ' . $filePathForS3); + Storage::disk('s3')->put($filePathForS3, $fileContent); + } } $document_object = new DocumentObject( diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index b4a3c863..fc9d5d5f 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -50,23 +50,21 @@ class Kernel extends ConsoleKernel ->withoutOverlapping(); if(env('APP_ENV') === 'production'){ - //cief todo: disable commands to avoid unintentional interfering with production starts - // $schedule->command('email-do-to-vt-command') - // ->dailyAt('10:00') - // ->withoutOverlapping(); + $schedule->command('email-do-to-vt-command') + ->dailyAt('10:00') + ->withoutOverlapping(); - // $schedule->command('seasonal-segmant-company-remove-command') - // ->dailyAt('01:00') - // ->withoutOverlapping(); + $schedule->command('seasonal-segmant-company-remove-command') + ->dailyAt('01:00') + ->withoutOverlapping(); - // $schedule->command('delete-bulk-download-files-command') - // ->hourly() - // ->withoutOverlapping(); + $schedule->command('delete-bulk-download-files-command') + ->hourly() + ->withoutOverlapping(); - // $schedule->command('booking-expired-command') - // ->dailyAt('02:00') - // ->withoutOverlapping(); - //cief todo: disable commands to avoid unintentional interfering with production + $schedule->command('booking-expired-command') + ->dailyAt('02:00') + ->withoutOverlapping(); // DISABLED BY DEFAULT // $schedule->command('purchase-order-autofill-command') diff --git a/app/Http/Controllers/Transactions/ListUrgentTransactionsController.php b/app/Http/Controllers/Transactions/ListUrgentTransactionsController.php new file mode 100644 index 00000000..b97cba14 --- /dev/null +++ b/app/Http/Controllers/Transactions/ListUrgentTransactionsController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Resources/BookingForTransactionUrgentResource.php b/app/Http/Resources/BookingForTransactionUrgentResource.php new file mode 100644 index 00000000..418c3a86 --- /dev/null +++ b/app/Http/Resources/BookingForTransactionUrgentResource.php @@ -0,0 +1,73 @@ + $this->id, + 'company_reference' => $this->company->reference, //new CompanyResource($this->company) + 'bank' => new BankResource($this->bank), + 'service' => new ServiceTypeResource($this->service), + 'marking' => $this->marking, + // 'amount' => $this->fix_amount, + // 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), + // 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + // // 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) + floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + // 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)), + // 'fixed_currency' => new CurrencyResource($this->fixedCurrency), + // 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), + // 'conversion_currency' => new CurrencyResource($this->conversionCurrency), + // 'documents' => [ + // 'purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), + // 'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), + // 'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), + // 'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), + // 'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), + // 'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), + // ], + // 'order_reference_no' => $this->modelAttributes()->where('name', BookingAttributeNames::ORDER_REFERENCE_NO)->get()->map(function ($attr) { + // return [ + // 'id' => $attr->id, + // 'value' => $attr->value + // ]; + // }), + // 'status' => $this->status, + // 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + // 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + // $this->mergeWhen($this->relationLoaded('transactions'), [ + // 'purchase_order' => new TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), + // 'payment_attempts' => TransactionResource::collection( + // $this->transactions() + // ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) + // ->whereDate('expires_on', '>=', Carbon::now()) + // ->get() + // ), + // // 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + // 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::EXPIRED)->get()), + // 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ + // $query->where(function($query){ + // $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED, ApprovalStatus::REFUNDED]); + // })->orWhere(function($query){ + // $query->where(function($query){ + // $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + // })->orWhere(function($query){ + // $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + // }); + // }); + // })->latest()->get()) + // ]) + ]; + } +} diff --git a/app/Http/Resources/DocumentForTransactionUrgentResource.php b/app/Http/Resources/DocumentForTransactionUrgentResource.php new file mode 100644 index 00000000..59c581c6 --- /dev/null +++ b/app/Http/Resources/DocumentForTransactionUrgentResource.php @@ -0,0 +1,29 @@ + $this->id, + // 'reference' => $this->reference, + // 'status' => (int) $this->status, + // 'document_type' => $this->document_type, + // 'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingResource($this->owner) : new CompanyResource($this->owner)) : null, + // 'files' => FileResource::collection($this->files), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A') + ]; + } +} diff --git a/app/Http/Resources/TransactionUrgentResource.php b/app/Http/Resources/TransactionUrgentResource.php new file mode 100644 index 00000000..04edd0d1 --- /dev/null +++ b/app/Http/Resources/TransactionUrgentResource.php @@ -0,0 +1,71 @@ +type, [TransactionType::BILL, TransactionType::REFUND, TransactionType::SUPPLIER_REFUND])){ + $booking = $this->owner->owner; + $bank = $this->owner->bank ?? $booking->bank; + } + else{ + $booking = $this->owner; + $bank = $this->bank ?? $booking->bank; + } + //Check if Transaction of type PAYMENT has an override for recipient bank - ends + $days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1); + + return [ + 'id' => $this->id, + 'booking' => new BookingForTransactionUrgentResource($booking), + // 'type' => (int) $this->type, + // 'bill_no' => $this->bill_no, + // 'payment_reference' => $this->payment_reference, + // 'payment_method' => (float) $this->payment_method, + 'recipient_bank_account' => new BankResource($bank), + // 'issuer_name' => $this->issuerCompany->name, + // 'issuer_id' => $this->issuerCompany->id, + // 'amount' => (double) ($this->type === TransactionType::SUPPLIER_REFUND ? $this->amount - $this->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->sum('amount') : $this->amount), + 'original_amount' => (double) ($this->type === TransactionType::SUPPLIER_REFUND ? $this->original_amount - $this->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->sum('original_amount') : $this->original_amount), + // 'currency' => new CurrencyResource($this->currency), + // 'original_currency' => new CurrencyResource($this->original_currency), + // 'service_charge' => (double) $this->service_charge, + // 'tax' => (double) $this->tax, + // 'currency_rate' => (double) $this->currency_rate, + // 'status' => (int) $this->status, + //'details' => TransactionDetailResource::collection($this->transactionDetails), + 'documents' => new DocumentForTransactionUrgentResource($this->documents()->first()), + //'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->bills()->first())), + //'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())), + //'refunded_amount' => $this->booking ? floatval((App()->make(CalculatesBookingRefundAmount::class))->calculateRefundAmount($this->resource, $this->booking->fix_currency_id)) : null, + // 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), + 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + // 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + 'interval' => [ + 'value' => $days->gt(Carbon::now()) ? '+' : '-', + 'duration' => $days->diff(Carbon::now())->format('%d'), + ], + //'remarks' => RemarkResource::collection($this->remarks), + //'redemption' => new VoucherRedemptionResource($this->voucherRedemption), + // 'bank' => ((int) $this->type === TransactionType::PAYMENT) ? new BankResource($bank) : null, //When a transaction (of type payment) has an override recipient bank details on booking, this is NOT null + ]; + } +} diff --git a/resources/assets/vue/components/bookings/elements/TransactionGroupComponent.vue b/resources/assets/vue/components/bookings/elements/TransactionGroupComponent.vue index 2e7c30c5..87630cb0 100644 --- a/resources/assets/vue/components/bookings/elements/TransactionGroupComponent.vue +++ b/resources/assets/vue/components/bookings/elements/TransactionGroupComponent.vue @@ -26,16 +26,26 @@ - + + + + + + + + diff --git a/resources/assets/vue/components/bookings/elements/UrgentTransactionComponent.vue b/resources/assets/vue/components/bookings/elements/UrgentTransactionComponent.vue index b684c6cc..00dd9586 100644 --- a/resources/assets/vue/components/bookings/elements/UrgentTransactionComponent.vue +++ b/resources/assets/vue/components/bookings/elements/UrgentTransactionComponent.vue @@ -18,7 +18,7 @@

{{item.recipient_bank_account.type === 3 ? item.recipient_bank_account.account_no : item.recipient_bank_account.account_no.replace(/[^\dA-Z]/g, '').replace(/(.{4})/g, '$1 ').trim()}}

-

{{item.booking.company.reference}}

+

{{item.booking.company_reference}}

{{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}

diff --git a/resources/assets/vue/components/bookings/sections/UrgentListSectionComponent.vue b/resources/assets/vue/components/bookings/sections/UrgentListSectionComponent.vue index 1148837c..8a7d339d 100644 --- a/resources/assets/vue/components/bookings/sections/UrgentListSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/UrgentListSectionComponent.vue @@ -48,7 +48,7 @@ }, methods: { fetchList(Page = 1){ - this.submit(route('api.transaction.list') + '?page='+ Page +'&filters=' + JSON.stringify({status: 2, type: 1, owner_type: 'App\\Models\\Booking', per_page: 50, order_by: { + this.submit(route('api.transaction.list.urgent') + '?page='+ Page +'&filters=' + JSON.stringify({status: 2, type: 1, owner_type: 'App\\Models\\Booking', per_page: 50, order_by: { column: 'created_at', DESC: true }}), 'get', 'urgentListSection', false, true) @@ -59,4 +59,4 @@ } } } - \ No newline at end of file + diff --git a/resources/assets/vue/components/general/elements/OpenLinkInNewTabComponent.vue b/resources/assets/vue/components/general/elements/OpenLinkInNewTabComponent.vue index 971c8ed2..145dd0f7 100644 --- a/resources/assets/vue/components/general/elements/OpenLinkInNewTabComponent.vue +++ b/resources/assets/vue/components/general/elements/OpenLinkInNewTabComponent.vue @@ -2,9 +2,10 @@
+ @click.prevent="handleClick" + v-tooltip:top="tooltip ? tooltip : ''"> - + @@ -23,7 +24,15 @@ customClass:{ type: String, default: '' - } + }, + tooltip:{ + type: String, + default: '' + }, + showSpinner: { + type: Boolean, + default: true + }, }, data() { return { diff --git a/resources/assets/vue/components/general/forms/FileUploadComponent.vue b/resources/assets/vue/components/general/forms/FileUploadComponent.vue index 15594912..3807ff01 100644 --- a/resources/assets/vue/components/general/forms/FileUploadComponent.vue +++ b/resources/assets/vue/components/general/forms/FileUploadComponent.vue @@ -97,11 +97,16 @@ vm.isLoading = true; + const pdfIconUrl = "https://assets.izyim.com/public/images/icons/pdf.png"; + const xlsIconUrl = "https://assets.izyim.com/public/images/icons/xlsx.png"; + if(file.name.split('.').pop() === 'pdf'){ - $(file.previewElement).closest("img[data-dz-thumbnail]").attr("src", asset("images/icons/pdf.png")); + // $(file.previewElement).closest("img[data-dz-thumbnail]").attr("src", asset("images/icons/pdf.png")); + $(file.previewElement).closest("img[data-dz-thumbnail]").attr("src", pdfIconUrl); } if(file.name.split('.').pop().indexOf("xls") !== -1){ - $(file.previewElement).closest("img[data-dz-thumbnail]").attr("src", asset("images/icons/xlsx.png")); + // $(file.previewElement).closest("img[data-dz-thumbnail]").attr("src", asset("images/icons/xlsx.png")); + $(file.previewElement).closest("img[data-dz-thumbnail]").attr("src", xlsIconUrl); } Promise.all(dropzone.files.map(function(file){ diff --git a/resources/assets/vue/vuex/modules/crudRequest.js b/resources/assets/vue/vuex/modules/crudRequest.js index 80c54afb..49008223 100644 --- a/resources/assets/vue/vuex/modules/crudRequest.js +++ b/resources/assets/vue/vuex/modules/crudRequest.js @@ -12,7 +12,7 @@ export default { let decodedParams = fullyDecodeURI(encodedParams); const queryParams = encodeURIComponent(decodedParams); queryDomain = encodeUrlWithoutQueryParameter(queryDomain) - console.log("queryDomain: " + queryDomain); + encodedParams = queryParams.toString(); let filteredEncodedParams = encodedParams.replace(/%3D/g,'='); filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&'); diff --git a/resources/assets/vue/vuex/modules/crudRequestV2.js b/resources/assets/vue/vuex/modules/crudRequestV2.js index 578d9564..6d1dc568 100644 --- a/resources/assets/vue/vuex/modules/crudRequestV2.js +++ b/resources/assets/vue/vuex/modules/crudRequestV2.js @@ -8,7 +8,7 @@ export default { let decodedParams = fullyDecodeURI(encodedParams); const queryParams = encodeURIComponent(decodedParams); queryDomain = encodeUrlWithoutQueryParameter(queryDomain) - console.log("queryDomain: " + queryDomain); + encodedParams = queryParams.toString(); let filteredEncodedParams = encodedParams.replace(/%3D/g,'='); filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&'); diff --git a/routes/transaction.php b/routes/transaction.php index 4d18c31b..fd3e1f64 100644 --- a/routes/transaction.php +++ b/routes/transaction.php @@ -6,6 +6,7 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => Route::get('/list', 'ListTransactionsController@list')->name('list'); Route::get('/list/job', 'ListTransactionsJobController@list')->name('list.job'); + Route::get('/list/urgent', 'ListUrgentTransactionsController@list')->name('list.urgent'); Route::delete('/suspend/{id}', 'SuspendTransactionController@suspend')->name('suspend'); route::post('/supplier/{id}/bill/create', 'CreateSupplierTransactionController@create')->name('supplier.create'); diff --git a/routes/web.php b/routes/web.php index 6a6a6d67..90711eaf 100644 --- a/routes/web.php +++ b/routes/web.php @@ -36,7 +36,7 @@ use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionWithInvo use App\Classes\Modules\Transactions\Services\DeletesTransaction; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; - +use App\Classes\General\AWSS3Helper; /* |-------------------------------------------------------------------------- @@ -621,7 +621,15 @@ Route::get('/group/invoice/{id}', function ($id) { $dompdf->setPaper('A4', 'portrait'); $dompdf->render(); - return $dompdf->stream("invoice_pdf_{$supplier->name}.pdf"); + $exportFileName = "invoice_pdf_{$supplier->name}.pdf"; + $filesystemDriver = Storage::getDefaultDriver(); + if($filesystemDriver === 's3'){ + $pdfContent = $dompdf->output(); + return response([ 'src' => AWSS3Helper::S3PDF($exportFileName, $pdfContent) ]); + } + else{ + return $dompdf->stream($exportFileName); + } })->name('group.invoice'); Route::get('/wallet/audit', function (Request $request) { @@ -1233,19 +1241,7 @@ Route::get('check-duplicate-refunds', function () { echo ''; }); -//Laravel Vapor - Starts -// Route::get('/aws-image-upload', 'AWS\AWSImageUploadController@imageUpload')->name('aws.image.upload'); -// Route::post('/aws-image-upload', 'AWS\AWSImageUploadController@imageUploadPost')->name('aws.image.upload.post'); -// Route::get('/aws-image/{filename}', 'AWS\AWSImageUploadController@displayImage')->name('aws.image.displayImage'); - -// Route::get('/token', function (Request $request) { -// $token = $request->session()->token(); -// echo $token; -// $token = csrf_token(); -// echo $token; -// }); - Route::get('/downloads', function () { return view('pages.downloads.index'); })->name('admin.download'); -//Laravel Vapor - Ends + diff --git a/vapor.yml b/vapor.yml index c70edd09..62c5b1d3 100644 --- a/vapor.yml +++ b/vapor.yml @@ -3,7 +3,9 @@ name: exchange separate-vendor: true environments: production: - domain: production.exchange.izyim.com + domain: + - production.exchange.izyim.com + - exchange.cief-malaysia.com memory: 1024 cli-memory: 512 queues: