diff --git a/Jenkinsfile b/Jenkinsfile index 9c3d6620..e290d7ed 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -22,7 +22,7 @@ pipeline { git( url: httpUrl, credentialsId: 'gitlab-jenkins-localhost', - branch: 'dillon/jenkins-vapor-34-a' + branch: 'dillon/jenkins-vapor-34-vue-polling' ) } } diff --git a/app/Classes/General/Eloquent/AbstractFetchRecord.php b/app/Classes/General/Eloquent/AbstractFetchRecord.php index 248deee7..36224038 100644 --- a/app/Classes/General/Eloquent/AbstractFetchRecord.php +++ b/app/Classes/General/Eloquent/AbstractFetchRecord.php @@ -27,7 +27,7 @@ abstract class AbstractFetchRecord extends AbstractGetRecord * @return Model * @throws ResourceNotFoundException */ - public function getResults(Builder $query): Model { + public function getResults(Builder $query, array $param = []): Model { if(!$query->exists()){ throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); } @@ -35,4 +35,4 @@ abstract class AbstractFetchRecord extends AbstractGetRecord return $query->first(); } -} \ No newline at end of file +} diff --git a/app/Classes/General/Eloquent/AbstractGetRecord.php b/app/Classes/General/Eloquent/AbstractGetRecord.php index ea544953..1a7eac3e 100644 --- a/app/Classes/General/Eloquent/AbstractGetRecord.php +++ b/app/Classes/General/Eloquent/AbstractGetRecord.php @@ -64,9 +64,9 @@ abstract class AbstractGetRecord * @param array $filters * @return mixed */ - public function handler(array $filters){ + public function handler(array $filters, array $params = []){ $this->filters = collect($filters); - return $this->getResults($this->applyFiltersToQuery()); + return $this->getResults($this->applyFiltersToQuery(), $params); } @@ -79,6 +79,6 @@ abstract class AbstractGetRecord * @param Builder $query * @return mixed */ - abstract function getResults(Builder $query); + abstract function getResults(Builder $query, array $params = []); } diff --git a/app/Classes/General/Eloquent/AbstractListRecord.php b/app/Classes/General/Eloquent/AbstractListRecord.php index 7b7d0df9..04c8cf79 100644 --- a/app/Classes/General/Eloquent/AbstractListRecord.php +++ b/app/Classes/General/Eloquent/AbstractListRecord.php @@ -17,11 +17,11 @@ abstract class AbstractListRecord extends AbstractGetRecord * @return mixed * @throws MalformedRequestException */ - public function execute(array $filters = []){ + public function execute(array $filters = [], array $param = []){ try{ - return $this->handler($filters); + return $this->handler($filters, $param); } catch (QueryException $exception){ log::error($exception); @@ -30,18 +30,24 @@ abstract class AbstractListRecord extends AbstractGetRecord } + /** * @param Builder $query * @return mixed */ - public function getResults(Builder $query) { + public function getResults(Builder $query, array $param = []) { $filters = $this->getDecorationFilters(); if($filters->has('order_by')){ $query = $query->orderBy($filters->get('order_by')->column, $filters->get('order_by')->DESC ? 'DESC': 'ASC'); } - return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get(); + if(!empty($param)){ + return $filters->has('per_page') ? $query->paginate($filters->get('per_page'), ['*'], 'page', $param['page']) : $query->get(); + } + else{ + return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get(); + } } diff --git a/app/Classes/General/Eloquent/Filters/JobId.php b/app/Classes/General/Eloquent/Filters/JobId.php new file mode 100644 index 00000000..42ac51a4 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/JobId.php @@ -0,0 +1,20 @@ +where('job_id', $value); + } + +} diff --git a/app/Classes/General/Helper.php b/app/Classes/General/Helper.php index 267ee401..d3c9e247 100644 --- a/app/Classes/General/Helper.php +++ b/app/Classes/General/Helper.php @@ -42,4 +42,19 @@ class Helper } } } + + /** + * @param null|string $param + * @return array + */ + static function deserializeFilters($param): array { + if(gettype($param) == "array"){ + $json = implode(',', $param); + } + else{ + $json = $param; + } + return $json !== null ? collect(json_decode($json))->toArray() : []; + } + } diff --git a/app/Classes/Jobs/ListDocuments.php b/app/Classes/Jobs/ListDocuments.php new file mode 100644 index 00000000..0b50baac --- /dev/null +++ b/app/Classes/Jobs/ListDocuments.php @@ -0,0 +1,54 @@ +listDocumentJobObject = $listDocumentJobObject; + } + + public function handle() + { + $result = (App()->make(ListDocumentProcessor::class))->execute($this->listDocumentJobObject); + + // Log::error(json_encode($result)); + + //cief todo: Insert into DB: job id, query result, timestamp + // Store the result in the job_results table + + //cief todo: why cannot save data in table like this + // $model = new JobResult(); + // $model->job_id = $this->job->getJobId(); + // $model->result = json_encode($result); + // $model->save(); + + // Log::error(json_encode($model->id)); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Modules/Bookings/Services/GetBookings.php b/app/Classes/Modules/Bookings/Services/GetBookings.php index b90697ae..fb2f92b7 100644 --- a/app/Classes/Modules/Bookings/Services/GetBookings.php +++ b/app/Classes/Modules/Bookings/Services/GetBookings.php @@ -38,7 +38,7 @@ class GetBookings extends AbstractGetRecord * @return Collection * @throws ResourceNotFoundException */ - public function getResults(Builder $query):Collection + public function getResults(Builder $query, array $param = []):Collection { if (!$query->exists()) { throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); @@ -48,4 +48,4 @@ class GetBookings extends AbstractGetRecord } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php new file mode 100644 index 00000000..518a5065 --- /dev/null +++ b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php @@ -0,0 +1,65 @@ + 'List Job', + 'message' => 'You have successfully submit a job to list Documents' + ]; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + Log::error(json_encode($request->all())); + + $listDocumentJobObject = new ListDocumentJobObject( + "Proof of Concept", + $request->all(), + $jobId + ); + + ListDocuments::dispatch($listDocumentJobObject); + + // // Create your job instance with delay, so we can back here within delay and take control in our hands. + // $job = new ListDocuments($listDocumentJobObject); + // $job->delay(now()->addSeconds(5)); + + // // Dispath your job with our custom_dispatch helper. This will return job id from jobs table + // // $jobId = $this->custom_dispatch($job); + + + $result = []; + $result['job_id'] = $jobId; + + return $this->response(['data' => $result]); + } + + //cief todo: no longer need jobId + // function custom_dispatch($job): int { + // return app(\Illuminate\Contracts\Bus\Dispatcher::class)->dispatch($job); + // } +} diff --git a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentLogic.php b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentLogic.php index 02bdac9d..784fe83e 100644 --- a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentLogic.php +++ b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentLogic.php @@ -54,10 +54,18 @@ class ListDocumentLogic extends AbstractControllerLogic $this->canListDocuments->passes(); + // dd(json_encode($request->input('filters'))); + // /"{\"per_page\":30,\"with_owner\":true,\"document_type_in\":[\"PURCHASE_ORDER\"],\"order_by\":{\"column\":\"id\",\"DESC\":true}}" + + // dd(json_encode($this->listsDocuments->deserializeFilters($request->input('filters')))); + //{"per_page":30,"with_owner":true,"document_type_in":["INVOICE"],"order_by":{"column":"id","DESC":true}} + + //{"page":"1","filters":"{\"per_page\":30,\"with_owner\":true,\"document_type_in\":[\"PURCHASE_ORDER\"],\"order_by\":{\"column\":\"id\",\"DESC\":true}}"} + $query = $this->listsDocuments->execute($this->listsDocuments->deserializeFilters($request->input('filters'))); return $this->collectionResponse(DocumentResource::collection($query)); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Documents/DataTransferObjects/ListDocumentJobObject.php b/app/Classes/Modules/Documents/DataTransferObjects/ListDocumentJobObject.php new file mode 100644 index 00000000..147ab3ee --- /dev/null +++ b/app/Classes/Modules/Documents/DataTransferObjects/ListDocumentJobObject.php @@ -0,0 +1,56 @@ +name = $name; + $this->payload = $payload; + $this->jobId = $jobId; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return array + */ + public function getPayload(): array + { + return $this->payload; + } + + /** + * @return string + */ + public function getJobId(): string + { + return $this->jobId; + } + + // public function setJobId(int $jobId) + // { + // $this->jobId = $jobId; + // } + +} diff --git a/app/Classes/Modules/Documents/Processors/ListDocumentProcessor.php b/app/Classes/Modules/Documents/Processors/ListDocumentProcessor.php new file mode 100644 index 00000000..1f16c2bd --- /dev/null +++ b/app/Classes/Modules/Documents/Processors/ListDocumentProcessor.php @@ -0,0 +1,62 @@ +listsDocuments = $listsDocuments; + $this->createsJobResult = $createsJobResult; + } + + /** + * @param ListDocumentJobObject $listDocumentJobObject + * @return null|object + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(ListDocumentJobObject $listDocumentJobObject) { + + $query = $this->listsDocuments->execute($this->listsDocuments->deserializeFilters($listDocumentJobObject->getPayload()['filters']), ['page' => $listDocumentJobObject->getPayload()['page']]); + + // Log::error('page: '.json_encode($listDocumentJobObject->getPayload()['page'])); + $result = $this->collectionResponse(DocumentResource::collection($query)); + + Log::error(json_encode($result)); + $create = $this->createsJobResult->execute($listDocumentJobObject->getJobId(), json_encode($result)); + + return $create; + } + + + /** + * @param ResourceCollection $collection + * @return JsonResponse + */ + public function collectionResponse(ResourceCollection $collection){ + return json_decode($collection->response()->getContent(), true); + } + +} diff --git a/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php new file mode 100644 index 00000000..366fda8c --- /dev/null +++ b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php @@ -0,0 +1,54 @@ + 'Retrieved Data', + 'message' => 'You have successfully retrieved data' + ]; + } + + /** @var FetchesJobResult */ + private $fetchesJobResult; + + /** + * FetchJobResultLogic constructor. + * @param FetchesJobResult $fetchesJobResult + */ + public function __construct(FetchesJobResult $fetchesJobResult) + { + $this->fetchesJobResult = $fetchesJobResult; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + $query = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]); + + return $this->resourceResponse(new JobResultResource($query)); + + } + +} diff --git a/app/Classes/Modules/Jobs/Services/CreatesJobResult.php b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php new file mode 100644 index 00000000..a3fdb93f --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php @@ -0,0 +1,24 @@ +job_id = $job_id; + $model->result = $result; + + return $this->handler($model); + } +} diff --git a/app/Classes/Modules/Jobs/Services/FetchesJobResult.php b/app/Classes/Modules/Jobs/Services/FetchesJobResult.php new file mode 100644 index 00000000..1cc99cb6 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/FetchesJobResult.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Http/Controllers/Documents/ListDocumentsJobController.php b/app/Http/Controllers/Documents/ListDocumentsJobController.php new file mode 100644 index 00000000..42378c3b --- /dev/null +++ b/app/Http/Controllers/Documents/ListDocumentsJobController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Services/FetchJobResultController.php b/app/Http/Controllers/Services/FetchJobResultController.php new file mode 100644 index 00000000..a9c4a372 --- /dev/null +++ b/app/Http/Controllers/Services/FetchJobResultController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index 85ecee16..5d27055e 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -43,7 +43,8 @@ class CompanyResource extends JsonResource 'status' => (int) $this->status, 'contact' => new ContactResource ($this->when($this->has('contacts'), $this->contacts->first())), 'address' => new AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', true)->first())), - 'employee' => new UserResource(Auth::user()->type === RoleTypes::USER ? $this->employees()->where('email', '=', Auth::user()->email)->first() : $this->employees()->orderBy('id', 'DESC')->first()), + //cief todo: this one need to decide what to do to replace Auth:user() when it is run by job queue + // 'employee' => new UserResource(Auth::user()->type === RoleTypes::USER ? $this->employees()->where('email', '=', Auth::user()->email)->first() : $this->employees()->orderBy('id', 'DESC')->first()), 'identification' => new DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->first()), 'bookings' => $this->whenLoaded('bookings', $this->bookings()->orderBy('id', 'DESC')->get(), []), 'confirmed_bookings' => $this->bookings()->whereHas('transactions', function ($query){ diff --git a/app/Http/Resources/JobResultResource.php b/app/Http/Resources/JobResultResource.php new file mode 100644 index 00000000..51bc1898 --- /dev/null +++ b/app/Http/Resources/JobResultResource.php @@ -0,0 +1,22 @@ + $this->job_id, + 'result' => $this->result, + ]; + } +} diff --git a/app/Models/JobResult.php b/app/Models/JobResult.php new file mode 100644 index 00000000..f30b5076 --- /dev/null +++ b/app/Models/JobResult.php @@ -0,0 +1,13 @@ +id(); + $table->string('job_id', 50); + $table->longText('result'); + $table->timestamps(); + + // $table->foreign('job_id')->references('id')->on('jobs')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('job_results'); + } +} diff --git a/package.json b/package.json index 68b4b646..6b27498c 100644 --- a/package.json +++ b/package.json @@ -12,14 +12,14 @@ "dependencies": { "animate.css": "^4.1.1", "bootstrap": "^4.0.0", - "bootstrap-datepicker": "^1.7.1", + "bootstrap-datepicker": "^1.10.0", "chart.js": "^2.9.4", "dropzone": "^5.7.2", "epic-spinners": "^1.1.0", "flag-icon-css": "^3.5.0", "font-awesome": "^4.7.0", "intro.js": "^3.1.0", - "jquery": "^3.2", + "jquery": "^3.7.0", "jquery.scrollbar": "^0.2.11", "jwt-decode": "^3.1.2", "laravel-vapor": "^0.6.0", @@ -29,17 +29,17 @@ "sass-loader": "10.1.0", "select2": "^4.0.6-rc.1", "v-money": "^0.8.1", - "vue": "^2.6.10", + "vue": "^2.7.14", "vue-avatar": "^2.1.8", "vue-debounce": "^2.6.0", - "vue-template-compiler": "^2.6.10", + "vue-template-compiler": "^2.7.14", "vue-the-mask": "^0.11.1", "vuelidate": "^0.7.4", "vuex": "^3.1.1" }, "devDependencies": { "axios": "^0.21.0", - "chromatic": "^6.5.4", + "chromatic": "^6.21.0", "cross-env": "^7.0.2", "del": "^6.0.0", "fancy-log": "^1.3.0", @@ -55,14 +55,14 @@ "gulp-plumber": "^1.1.0", "gulp-print": "^5.0.2", "gulp-rename": "^2.0.0", - "gulp-replace": "^1.0.0", + "gulp-replace": "^1.1.4", "gulp-sass": "^4.1.0", "gulp-streamify": "^1.0.2", "gulp-uglify": "^3.0.0", "gulp-uglify-es": "^2.0.0", "laravel-mix": "^5.0.9", "lodash": "^4.17.13", - "resolve-url-loader": "^3.1.2" + "resolve-url-loader": "^3.1.5" }, "paths": { "build": { diff --git a/resources/assets/vue/components/general/elements/ListPollingComponent.vue b/resources/assets/vue/components/general/elements/ListPollingComponent.vue new file mode 100644 index 00000000..3994fc19 --- /dev/null +++ b/resources/assets/vue/components/general/elements/ListPollingComponent.vue @@ -0,0 +1,184 @@ + + + diff --git a/resources/views/pages/billings.blade.php b/resources/views/pages/billings.blade.php index 24d8f6a9..92601059 100644 --- a/resources/views/pages/billings.blade.php +++ b/resources/views/pages/billings.blade.php @@ -2,7 +2,8 @@ @section('inner_content')
- + +
@@ -95,25 +96,33 @@
- + - +
- + - +
- -
-
- -
+ + + +
+
+ + + +
diff --git a/routes/api.php b/routes/api.php index b3054bd2..c8d008e3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -57,6 +57,10 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/voucher.php'; + require __DIR__ . '/accounting.php'; + + require __DIR__ . '/job.php'; + // require __DIR__ . '/rate.php'; // require __DIR__ . '/receipt.php'; diff --git a/routes/document.php b/routes/document.php index c186032f..07a7d18a 100644 --- a/routes/document.php +++ b/routes/document.php @@ -4,9 +4,10 @@ use Illuminate\Support\Facades\Route; Route::group(['prefix' => 'document', 'as' => 'document.', 'namespace' => 'Documents'], function () { Route::get('/list', 'ListDocumentsController@list')->name('list'); + Route::get('/list/job', 'ListDocumentsJobController@list')->name('list.job'); Route::delete('/{id}/delete', 'DeleteDocumentController@delete')->name('delete'); Route::put('/{id}/approve', 'ApproveDocumentController@approve')->name('status.approve'); Route::put('/{id}/reject', 'RejectDocumentController@reject')->name('status.reject'); Route::put('/{id}/reference/update', 'UpdateDocumentReferenceController@update')->name('reference.update'); -}); \ No newline at end of file +}); diff --git a/routes/job.php b/routes/job.php new file mode 100644 index 00000000..4c90d480 --- /dev/null +++ b/routes/job.php @@ -0,0 +1,7 @@ + 'job', 'as' => 'job.', 'namespace' => 'Services'], function () { + Route::get('/fetch/{job_id}', 'FetchJobResultController@fetch')->name('fetch'); +});