diff --git a/.gitignore b/.gitignore index 095342e0..bc05095d 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ public/* /storage/app/public public /storage/framework/laravel-excel +.vapor/ +.env.production +.env.staging +.env.development diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..5e8b63c1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,18 @@ +image: dillonngo/docker-based-image:poc + +stages: + - build + +Build: + stage: build + services: + - docker:dind + script: + - docker info + # - npm install + # - gulp build + - composer install --no-dev + - vendor/bin/vapor deploy production --message="$CI_COMMIT_MESSAGE" + only: + - test + diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..4d9fc13c --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,91 @@ +// Webhook + Gitlab git pull + Vapor + +// def payload = readJSON text: "${payload}" +// String userName = payload.user_name +// String userEmail = payload.user_email +// String httpUrl = payload.project.http_url + + +pipeline { + agent { + docker { + image 'dillonngo/docker-based-image:poc' + args "--group-add 992 -v /var/run/docker.sock:/var/run/docker.sock" + } + } + environment { + HOME = '.' + } + stages { + stage('Download source code from Git') { + steps { + script{ + switch(GIT_BRANCH) { + case "vapor/production": + case "vapor/staging": + case "vapor/development": + git( + url: 'https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git', + credentialsId: 'gitlab-jenkins-localhost', + branch: GIT_BRANCH + ) + case "origin/dillon/34-jenkins-vapor": + git( + url: 'https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git', + credentialsId: 'gitlab-jenkins-localhost', + branch: 'dillon/34-jenkins-vapor' + ) + break + } + } + } + } + + stage('Install') { + steps { + sh 'composer update' + } + } + + stage('Tests') { + steps { + sh 'vendor/bin/phpunit tests/Unit' + } + } + + stage('Deploy') { + steps { + script{ + String gitCommitMessage = getCommitMessage() + println("GIT CommitMessage: " + gitCommitMessage) + println("GIT GIT_BRANCH: " + GIT_BRANCH) + switch(GIT_BRANCH) { + case "vapor/production": + sh "vendor/bin/vapor deploy production --message='${gitCommitMessage}'" + break + case "vapor/staging": + sh "vendor/bin/vapor deploy staging --message='${gitCommitMessage}'" + break + case "vapor/development": + sh "vendor/bin/vapor deploy development --message='${gitCommitMessage}'" + break + case "origin/dillon/34-jenkins-vapor": + sh "vendor/bin/vapor deploy development --message='${gitCommitMessage}'" + break + } + } + } + } + } +} + +@NonCPS +String getCommitMessage(){ + commitMessage = " " + for ( changeLogSet in currentBuild.changeSets){ + for (entry in changeLogSet.getItems()){ + commitMessage = entry.msg + } + } + return commitMessage +} diff --git a/app/Classes/Exceptions/JobResourceNotFoundException.php b/app/Classes/Exceptions/JobResourceNotFoundException.php new file mode 100644 index 00000000..a8ef358e --- /dev/null +++ b/app/Classes/Exceptions/JobResourceNotFoundException.php @@ -0,0 +1,11 @@ +getMessage(), + $exception->getTrace()[0]['file'], + $exception->getTrace()[0]['line'] + )); + } + else{ + log::error($exception); + } + return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(), $exception->getCode() ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler(); diff --git a/app/Classes/General/Eloquent/AbstractFetchRecord.php b/app/Classes/General/Eloquent/AbstractFetchRecord.php index 248deee7..503fb369 100644 --- a/app/Classes/General/Eloquent/AbstractFetchRecord.php +++ b/app/Classes/General/Eloquent/AbstractFetchRecord.php @@ -4,9 +4,11 @@ namespace App\Classes\General\Eloquent; use App\Classes\Exceptions\ResourceNotFoundException; +use App\Classes\Exceptions\JobResourceNotFoundException; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Psy\Exception\ErrorException; +use Illuminate\Support\Facades\Log; abstract class AbstractFetchRecord extends AbstractGetRecord { @@ -27,12 +29,18 @@ 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'); + $table = $query->getModel()->getTable(); + if($table ==='job_results'){ + throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided'); + } + else{ + throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); + } } 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 f927d818..1a7eac3e 100644 --- a/app/Classes/General/Eloquent/AbstractGetRecord.php +++ b/app/Classes/General/Eloquent/AbstractGetRecord.php @@ -30,11 +30,25 @@ abstract class AbstractGetRecord return $this->filters->only(self::DECORATION_FILTERS); } + // /** + // * @param null|string $json + // * @return array + // */ + // public function deserializeFilters(?string $json): array { + // return $json !== null ? collect(json_decode($json))->toArray() : []; + // } + /** - * @param null|string $json + * @param null|string $param * @return array */ - public function deserializeFilters(?string $json): array { + public function deserializeFilters($param): array { + if(gettype($param) == "array"){ + $json = implode(',', $param); + } + else{ + $json = $param; + } return $json !== null ? collect(json_decode($json))->toArray() : []; } @@ -50,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); } @@ -65,6 +79,6 @@ abstract class AbstractGetRecord * @param Builder $query * @return mixed */ - abstract function getResults(Builder $query); + abstract function getResults(Builder $query, array $params = []); -} \ No newline at end of file +} 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 ac89540b..315f0a2c 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/ListBookings.php b/app/Classes/Jobs/ListBookings.php new file mode 100644 index 00000000..6be0c9c7 --- /dev/null +++ b/app/Classes/Jobs/ListBookings.php @@ -0,0 +1,50 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + $result = (App()->make(ListBookingJobProcessor::class))->execute($this->listGenericJobObject); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Jobs/ListDocuments.php b/app/Classes/Jobs/ListDocuments.php new file mode 100644 index 00000000..e4707f49 --- /dev/null +++ b/app/Classes/Jobs/ListDocuments.php @@ -0,0 +1,61 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + $result = (App()->make(ListDocumentJobProcessor::class))->execute($this->listGenericJobObject); + + //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/Jobs/ListTransactions.php b/app/Classes/Jobs/ListTransactions.php new file mode 100644 index 00000000..67c4a6b9 --- /dev/null +++ b/app/Classes/Jobs/ListTransactions.php @@ -0,0 +1,50 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + $result = (App()->make(ListTransactionJobProcessor::class))->execute($this->listGenericJobObject); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php index 6a7dd8c1..d8eb67d6 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php @@ -178,7 +178,7 @@ class CreateCustomerLogic extends AbstractControllerLogic CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject); } - // $this->generateEmailVerificationAttemptProcessor->execute($user); + // $this->generateEmailVerificationAttemptProcessor->execute($user); //cief todo $this->newCustomerToVoucherifyProcessor->execute($company->id, $user, true); @@ -191,12 +191,12 @@ class CreateCustomerLogic extends AbstractControllerLogic // register account on shipping portal $shippingCompanyModuleId = $this->registerOnShippingProcessor->execute($request, $company->id); } - + if ($shippingCompanyModuleId) { // create shipping company connection on exchange $this->connectCompanyToShippingCompanyModule->execute($company->id, $shippingCompanyModuleId); } - + return $this->response($this->authenticationProcessor->execute($request, false)); } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php new file mode 100644 index 00000000..5a7d0994 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php @@ -0,0 +1,56 @@ + 'List Booking Job', + 'message' => 'You have successfully submit a job to list bookings' + ]; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $user = Auth::user(); + $userInfo = (object) [ + 'email' => $user->email, + 'type' => $user->type, + ]; + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $jobId, + $userInfo + ); + + ListBookings::dispatch($listGenericJobObject); + + $result = []; + $result['job_id'] = $jobId; + + return $this->response(['data' => $result]); + } + +} diff --git a/app/Classes/Modules/Bookings/Processors/ListBookingJobProcessor.php b/app/Classes/Modules/Bookings/Processors/ListBookingJobProcessor.php new file mode 100644 index 00000000..b622ce79 --- /dev/null +++ b/app/Classes/Modules/Bookings/Processors/ListBookingJobProcessor.php @@ -0,0 +1,64 @@ +listsBookings = $listsBookings; + $this->createsJobResult = $createsJobResult; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return null|object + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsBookings->execute($this->listsBookings->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + + //cief todo: remove comments + // $result = $this->collectionResponse(BookingResource::collection($query)->userInfo($listGenericJobObject->getuserInfo())); + $result = $this->collectionResponse(BookingResource::customResourceCollection($query, $listGenericJobObject->getuserInfo())); + + // $result = new JobBookingCollectionResponse($query, $listGenericJobObject->getuserInfo()); + // $result = $this->collectionResponse(new BookingResourceCollection(BookingResource::collection($query), $listGenericJobObject->getuserInfo())); + + $create = $this->createsJobResult->execute($listGenericJobObject, 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/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..4328ded8 --- /dev/null +++ b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php @@ -0,0 +1,74 @@ + 'List Document Job', + 'message' => 'You have successfully submit a job to list documents' + ]; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $user = Auth::user(); + $userInfo = (object) [ + 'email' => $user->email, + 'type' => $user->type, + ]; + + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $jobId, + $userInfo + ); + + ListDocuments::dispatch($listGenericJobObject); + + //cief todo: remove comments + // // Create your job instance with delay, so we can back here within delay and take control in our hands. + // $job = new ListDocuments($listGenericJobObject); + // $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/ControllersLogic/RenderDocumentLogic.php b/app/Classes/Modules/Documents/ControllersLogic/RenderDocumentLogic.php index 2d095750..8b314dbc 100644 --- a/app/Classes/Modules/Documents/ControllersLogic/RenderDocumentLogic.php +++ b/app/Classes/Modules/Documents/ControllersLogic/RenderDocumentLogic.php @@ -54,11 +54,17 @@ class RenderDocumentLogic extends AbstractControllerLogic $this->canRenderDocument->passes(); - if(!Storage::disk('documents')->exists($file)) + // if(!Storage::disk('documents')->exists($file)) + // { + // throw new ResourceNotFoundException(); + // } + + // return $this->response(['src' => explode('.', $file)[1] == 'pdf' ? chunk_split(base64_encode(Storage::disk('documents')->get($file))) : Storage::disk('documents')->get($file) ]); + if(!Storage::disk('s3')->exists($file)) { throw new ResourceNotFoundException(); } return $this->response(['src' => explode('.', $file)[1] == 'pdf' ? chunk_split(base64_encode(Storage::disk('documents')->get($file))) : Storage::disk('documents')->get($file) ]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Documents/Processors/ListDocumentJobProcessor.php b/app/Classes/Modules/Documents/Processors/ListDocumentJobProcessor.php new file mode 100644 index 00000000..4b0309ed --- /dev/null +++ b/app/Classes/Modules/Documents/Processors/ListDocumentJobProcessor.php @@ -0,0 +1,67 @@ +listsDocuments = $listsDocuments; + $this->createsJobResult = $createsJobResult; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return null|object + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsDocuments->execute($this->listsDocuments->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + + //cief todo: remove comments + //attempt 1 + // $result = $this->collectionResponse(DocumentResource::collection($query, $listGenericJobObject->getuserInfo())); + + //attempt 2 + // $result = new JobDocumentCollectionResponse($query, $listGenericJobObject->getuserInfo()); + $result = $this->collectionResponse(DocumentResource::customResourceCollection($query, $listGenericJobObject->getuserInfo())); + // $result = $this->collectionResponse(new DocumentResourceCollection(DocumentResource::collection($query), $listGenericJobObject->getuserInfo())); + + $create = $this->createsJobResult->execute($listGenericJobObject, 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/Documents/Services/ConvertsBase64ToFile.php b/app/Classes/Modules/Documents/Services/ConvertsBase64ToFile.php index 0e0cf6b9..6e7f17f5 100644 --- a/app/Classes/Modules/Documents/Services/ConvertsBase64ToFile.php +++ b/app/Classes/Modules/Documents/Services/ConvertsBase64ToFile.php @@ -99,12 +99,15 @@ class ConvertsBase64ToFile */ private function generateFile(FileObject $file, string $suffix = '') { - $filePath = $this->path.'/'.$file->getFileName().$suffix.'.'.$file->getExtension(); + // $filePath = $this->path.'/'.$file->getFileName().$suffix.'.'.$file->getExtension(); - Storage::disk('documents')->put($filePath, $file->getDecodedData()); + // Storage::disk('documents')->put($filePath, $file->getDecodedData()); + // return $filePath; + + $filePath = 'localhost/'.$file->getFileName().$suffix.'.'.$file->getExtension(); + Storage::put($filePath, $file->getDecodedData(), 's3'); return $filePath; - } /** diff --git a/app/Classes/Modules/Generic/DataTransferObjects/ListGenericJobObject.php b/app/Classes/Modules/Generic/DataTransferObjects/ListGenericJobObject.php new file mode 100644 index 00000000..791522c5 --- /dev/null +++ b/app/Classes/Modules/Generic/DataTransferObjects/ListGenericJobObject.php @@ -0,0 +1,99 @@ +name = $name; + $this->payload = $payload; + $this->jobId = $jobId; + $this->userInfo = $userInfo; + } + + /** + * @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; + } + + /** + * @return object + */ + public function getUserInfo(): object + { + return $this->userInfo; + } + + /** + * @return string + */ + public function getJobCommandName(): string + { + return $this->jobCommandName; + } + + /** + * @return string + */ + public function getJobCommand(): string + { + return $this->jobCommand; + } + + // public function setJobId(int $jobId) + // { + // $this->jobId = $jobId; + // } + + public function setJobCommandName(string $jobCommandName) + { + $this->jobCommandName = $jobCommandName; + } + + public function setJobCommand(string $jobCommand) + { + $this->jobCommand = $jobCommand; + } + +} 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..953e7882 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php @@ -0,0 +1,28 @@ +job_id = $listGenericJobObject->getJobId(); + $model->result = $result; + $model->url = $listGenericJobObject->getName(); + $model->job_command_name = $listGenericJobObject->getJobCommandName(); + $model->job_command = $listGenericJobObject->getJobCommand(); + + 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/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php new file mode 100644 index 00000000..5ea497a0 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php @@ -0,0 +1,47 @@ + 'List Transaction Job', + 'message' => 'You have successfully submit a job to list transactions' + ]; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $jobId + ); + + ListTransactions::dispatch($listGenericJobObject); + + $result = []; + $result['job_id'] = $jobId; + + return $this->response(['data' => $result]); + } + +} diff --git a/app/Classes/Modules/Transactions/Processors/ListTransactionJobProcessor.php b/app/Classes/Modules/Transactions/Processors/ListTransactionJobProcessor.php new file mode 100644 index 00000000..4f754cf5 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/ListTransactionJobProcessor.php @@ -0,0 +1,59 @@ +listsTransactions = $listsTransactions; + $this->createsJobResult = $createsJobResult; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return null|object + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + + $result = $this->collectionResponse(TransactionResource::collection($query)); + + $create = $this->createsJobResult->execute($listGenericJobObject, 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/Http/Controllers/AWS/AWSImageUploadController.php b/app/Http/Controllers/AWS/AWSImageUploadController.php new file mode 100644 index 00000000..f034b3a1 --- /dev/null +++ b/app/Http/Controllers/AWS/AWSImageUploadController.php @@ -0,0 +1,102 @@ +validate([ + 'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048', + ]); + + $imageName = time().'.'.$request->image->extension(); + + $request->image->storeAs('images', $imageName); + + //cief todo: checking if storage disk exist + if (Storage::disk('documents')) { + $check1 = "The disk documents exists."; + } else { + $check1 = "The disk documents does not exist."; + } + + // $diskNames = Storage::diskNames(); + + // if (count($diskNames) > 0) { + // $check2 = "The following disks are configured: " . implode(', ', $diskNames); + // } else { + // $check2 = "No storage disks are configured."; + // } + + + if (Storage::disk('public')) { + $check2 = "The disk public exists."; + } else { + $check2 = "The disk public does not exist."; + } + + if (Storage::disk('local')) { + $check3 = "The disk local exists."; + } else { + $check3 = "The disk local does not exist."; + } + + + return redirect()->back() + ->with('success','You have successfully upload image.') + ->with('image',$imageName) + ->with('check1', $check1) + ->with('check2', $check2) + ->with('check3', $check3); + } + + + public function displayImage($fileName) + { + // dd($fileName); + + //1. + // $path = 'images/'.$fileName; + // $url = Storage::url($path); + // $url = Storage::temporaryUrl('file.jpg', now()->addMinutes(5)); + // return $url; + + + //2 + // $path = 'images/'.$fileName; + // // if(Storage::disk('s3')->exists($path)){ + // return Storage::disk('s3')->get($path); + // // } + // return null; + + + //original + $path = 'images/'.$fileName; + $file = Storage::get($path); + $type = Storage::mimeType($path); + + $response = Response::make($file, 200); + $response->header("Content-Type", $type); + return $response; + + // $path = 'images/'.$fileName; + // return Storage::temporaryUrl($path, now()->addMinutes(5)); + } + +} diff --git a/app/Http/Controllers/Bookings/ListBookingsJobController.php b/app/Http/Controllers/Bookings/ListBookingsJobController.php new file mode 100644 index 00000000..9b32fc77 --- /dev/null +++ b/app/Http/Controllers/Bookings/ListBookingsJobController.php @@ -0,0 +1,22 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Documents/ListDocumentsJobController.php b/app/Http/Controllers/Documents/ListDocumentsJobController.php new file mode 100644 index 00000000..394f15bd --- /dev/null +++ b/app/Http/Controllers/Documents/ListDocumentsJobController.php @@ -0,0 +1,20 @@ +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/Controllers/Transactions/ListTransactionsJobController.php b/app/Http/Controllers/Transactions/ListTransactionsJobController.php new file mode 100644 index 00000000..fb341d5d --- /dev/null +++ b/app/Http/Controllers/Transactions/ListTransactionsJobController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index f3a7881d..09a2c237 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -11,10 +11,19 @@ use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; use Illuminate\Support\Facades\Log; class BookingResource extends JsonResource { + // protected $userInfo; + private static $userInfo; + + public function userInfo($resource, $userInfo = null) + { + parent::__construct($resource); + self::$userInfo = $userInfo; + } /** * Transform the resource into an array. @@ -27,7 +36,7 @@ class BookingResource extends JsonResource { return [ 'id' => $this->id, - 'company' => new CompanyResource($this->company), + 'company' => new CompanyResource($this->company, self::$userInfo), 'bank' => new BankResource($this->bank), 'service' => new ServiceTypeResource($this->service), 'marking' => $this->marking, @@ -72,4 +81,10 @@ class BookingResource extends JsonResource ]) ]; } + + public static function customResourceCollection($resource, $userInfo): AnonymousResourceCollection + { + self::$userInfo = $userInfo; + return parent::collection($resource); + } } diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index 9714f2f0..1e7a117f 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -19,6 +19,14 @@ use Illuminate\Support\Facades\Log; class CompanyResource extends JsonResource { + protected $userInfo; + + public function __construct($resource, $userInfo = null) + { + parent::__construct($resource); + $this->userInfo = $userInfo; + } + /** * Transform the resource into an array. * @@ -33,6 +41,28 @@ class CompanyResource extends JsonResource $segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first(); $serviceCharge = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $this->id)->first(); + $userResource = null; + + $userInfoEmail = $this->userInfo && isset($this->userInfo->email) ? $this->userInfo->email : null; + $userInfoType = $this->userInfo && isset($this->userInfo->type) ? $this->userInfo->type : null; + + if(!$userInfoEmail && Auth::user()){ + $userInfoEmail = Auth::user()->email; + } + if(!$userInfoType && Auth::user()){ + $userInfoType = Auth::user()->type; + } + + //cief todo: remove + // Log::error('CompanyResource 1: '. json_encode($userInfoEmail)); + // Log::error('CompanyResource 2: '. json_encode($userInfoType)); + + if(!is_null($userInfoEmail) && !is_null($userInfoType)){ + //cief todo: to review following merge conflict + //new UserResource(Auth::user() && Auth::user()->type === RoleTypes::USER ? $this->employees()->where('email', '=', Auth::user()->email)->first() : $this->employees()->orderBy('id', 'DESC')->first()), + $userResource = new UserResource($userInfoType === RoleTypes::USER ? $this->employees()->where('email', '=', $userInfoEmail)->first() : $this->employees()->orderBy('id', 'DESC')->first()); + } + return [ 'id' => $this->id, 'shipping_company_module_id' => $this->shippingCompanyConnection ? $this->shippingCompanyConnection->shipping_company_module_id : null, @@ -44,7 +74,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() && 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' => $userResource, '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/DocumentResource.php b/app/Http/Resources/DocumentResource.php index 59933a67..20da2c45 100644 --- a/app/Http/Resources/DocumentResource.php +++ b/app/Http/Resources/DocumentResource.php @@ -8,9 +8,21 @@ use App\Models\Document; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Resources\Json\JsonResource; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Auth; +use Illuminate\Http\Resources\Json\AnonymousResourceCollection; class DocumentResource extends JsonResource { + // protected $userInfo; + + // public function userInfo($resource, $userInfo = null) + // { + // $this->userInfo = $userInfo; + // } + + private static $userInfo; + /** * Transform the resource into an array. * @@ -19,14 +31,23 @@ class DocumentResource extends JsonResource */ public function toArray($request) { + //cief todo: remove + // Log::error('DocumentResource 1: '. json_encode(self::$userInfo)); + // Log::error('DocumentResource 2: '. json_encode($this->relationLoaded('owner'))); return [ 'id' => $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, + 'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingResource($this->owner, self::$userInfo) : new CompanyResource($this->owner, self::$userInfo)) : null, 'files' => FileResource::collection($this->files), 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A') ]; } + + public static function customResourceCollection($resource, $userInfo): AnonymousResourceCollection + { + self::$userInfo = $userInfo; + return parent::collection($resource); + } } 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/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php b/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php new file mode 100644 index 00000000..3d962eca --- /dev/null +++ b/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php @@ -0,0 +1,36 @@ +string('url')->after('result')->nullable(); + $table->string('job_command_name')->after('url')->nullable(); + $table->longText('job_command')->after('job_command_name')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('job_results', function (Blueprint $table) { + $table->dropColumn('url'); + $table->dropColumn('job_command_name'); + $table->dropColumn('job_command'); + }); + } +} diff --git a/development.Dockerfile b/development.Dockerfile new file mode 100644 index 00000000..53dee762 --- /dev/null +++ b/development.Dockerfile @@ -0,0 +1,3 @@ +FROM laravelphp/vapor:php74 + +COPY . /var/task diff --git a/docker-setup/docker-compose.yml b/docker-setup/docker-compose.yml index 4dcfa8c2..9e33f109 100644 --- a/docker-setup/docker-compose.yml +++ b/docker-setup/docker-compose.yml @@ -45,6 +45,8 @@ services: volumes: - ../:/var/www/html - ./php/default.conf:/usr/local/etc/php-fpm.d/zz-docker.conf + ports: + - "9002:9000" networks: - exchange-staging ################################################################# diff --git a/docker-setup/php/default.conf b/docker-setup/php/default.conf index dced3233..db2a7f38 100644 --- a/docker-setup/php/default.conf +++ b/docker-setup/php/default.conf @@ -3,6 +3,7 @@ daemonize = no [www] listen = 9000 +php_admin_value[max_execution_time] = 60 pm.max_children = 15 pm.max_requests = 500 diff --git a/package.json b/package.json index 5d4b92bf..6b27498c 100644 --- a/package.json +++ b/package.json @@ -12,33 +12,34 @@ "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", "noty": "^3.2.0-beta", "perfect-scrollbar": "^1.5.0", "popper.js": "^1.12", "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", @@ -54,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/production.Dockerfile b/production.Dockerfile new file mode 100644 index 00000000..53dee762 --- /dev/null +++ b/production.Dockerfile @@ -0,0 +1,3 @@ +FROM laravelphp/vapor:php74 + +COPY . /var/task diff --git a/resources/assets/images/—Pngtree—2019 chinese new year lantern_951828.jpg b/resources/assets/images/—Pngtree—2019 chinese new year lantern_951828.jpg deleted file mode 100644 index dd7ceda3..00000000 Binary files a/resources/assets/images/—Pngtree—2019 chinese new year lantern_951828.jpg and /dev/null differ diff --git a/resources/assets/vue/app.js b/resources/assets/vue/app.js index abb7a17e..f2aba812 100644 --- a/resources/assets/vue/app.js +++ b/resources/assets/vue/app.js @@ -28,6 +28,10 @@ import { debounce } from 'vue-debounce' import Avatar from 'vue-avatar'; +import Vapor from 'laravel-vapor'; +// Vapor.withBaseAssetUrl(import.meta.env.VITE_VAPOR_ASSET_URL); +window.Vapor = Vapor; + /** Application Injections */ Vue.use(vuelidate); Vue.use(VueTheMask); @@ -36,7 +40,8 @@ Vue.use(filters); Vue.directive('closable', closable); Vue.mixin({ methods: { - route: route + route: route, + asset: window.Vapor.asset }, mixins: [request, crudHandler] }); diff --git a/resources/assets/vue/components/accounts/sections/OnboardingSectionComponent.vue b/resources/assets/vue/components/accounts/sections/OnboardingSectionComponent.vue index 5f2fb8e9..f41485f7 100644 --- a/resources/assets/vue/components/accounts/sections/OnboardingSectionComponent.vue +++ b/resources/assets/vue/components/accounts/sections/OnboardingSectionComponent.vue @@ -13,7 +13,7 @@
- +
@@ -98,4 +98,4 @@ }, mixins: [componentHandler] } - \ No newline at end of file + diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue index 7df9c125..6c64fdee 100644 --- a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue @@ -117,11 +117,11 @@
- + - +
@@ -165,7 +165,7 @@ } }, created(){ - this.submit(route('api.company.list') + '?filters=' + JSON.stringify({'business_type': 3, 'status_in': [1, 2, 0]}), 'get', 'pendingOrdersSection', false, false) + this.submit(route('api.company.list') + '?filters=' + JSON.stringify({'business_type': 3, 'status_in': [1, 2, 0]}), 'get', 'pendingOrdersSection', false, false); //cief todo: Uncaught (in promise) null }, methods: { successHandler(response){ @@ -210,4 +210,4 @@ } - \ No newline at end of file + diff --git a/resources/assets/vue/components/companies/elements/NewServiceAnnouncementComponent.vue b/resources/assets/vue/components/companies/elements/NewServiceAnnouncementComponent.vue index da407cfb..1bc561a3 100644 --- a/resources/assets/vue/components/companies/elements/NewServiceAnnouncementComponent.vue +++ b/resources/assets/vue/components/companies/elements/NewServiceAnnouncementComponent.vue @@ -6,7 +6,7 @@
- +
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..f6a65342 --- /dev/null +++ b/resources/assets/vue/components/general/elements/ListPollingComponent.vue @@ -0,0 +1,185 @@ + + + diff --git a/resources/assets/vue/vuex/modules/crudRequest.js b/resources/assets/vue/vuex/modules/crudRequest.js index 67df100e..30e1b076 100644 --- a/resources/assets/vue/vuex/modules/crudRequest.js +++ b/resources/assets/vue/vuex/modules/crudRequest.js @@ -2,7 +2,21 @@ export default { actions: { crudRequest({getters, dispatch}, {endpoint, method, parameters}){ return dispatch('ensureReCaptchaIsSet').then(function () { - return fetch(endpoint, { + const queryDomain = endpoint.split('?')[0]; + let encodedParams = endpoint.split('?')[1]; + let decodedParams = fullyDecodeURI(encodedParams); + const queryParams = encodeURIComponent(decodedParams); + encodedParams = queryParams.toString(); + let filteredEncodedParams = encodedParams.replace(/%3D/g,'='); + filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&'); + console.log('filteredEncodedParams: ', filteredEncodedParams); + console.log('queryDomain: ', queryDomain); + let combinedAbsoluteUrl = queryDomain; + if(filteredEncodedParams !== undefined && filteredEncodedParams !== 'undefined'){ + combinedAbsoluteUrl = queryDomain + '?' + filteredEncodedParams; + console.log('combinedAbsoluteUrl: ', combinedAbsoluteUrl); + } + return fetch(queryDomain + '?' + filteredEncodedParams, { method: method, responseType: 'json', body: parameters ? JSON.stringify(parameters):null, @@ -23,4 +37,16 @@ export default { }); } } -} \ No newline at end of file +} + +function isEncoded(uri) { + uri = uri || ''; + return uri !== decodeURIComponent(uri); +} + +function fullyDecodeURI(uri){ + while (isEncoded(uri)){ + uri = decodeURIComponent(uri); + } + return uri; +} diff --git a/resources/views/layouts/base_debug.blade.php b/resources/views/layouts/base_debug.blade.php new file mode 100644 index 00000000..2fe79fba --- /dev/null +++ b/resources/views/layouts/base_debug.blade.php @@ -0,0 +1,23 @@ + + + + @include('vendor/head') + + + + + + +
+
+ @yield('content') +
+ @include('vendor/js') + @stack('scripts') + + diff --git a/resources/views/layouts/base_debug_child.blade.php b/resources/views/layouts/base_debug_child.blade.php new file mode 100644 index 00000000..6c44eee0 --- /dev/null +++ b/resources/views/layouts/base_debug_child.blade.php @@ -0,0 +1,26 @@ +@extends('layouts.base_debug') + +@section('content') + + @include('partials.header') +
+
+
+
+
+
+ @yield('inner_content') +
+
+
+
+ @include('partials.footer') +
+
+ +@endsection diff --git a/resources/views/pages/aws_image_upload.blade.php b/resources/views/pages/aws_image_upload.blade.php new file mode 100644 index 00000000..76c53d81 --- /dev/null +++ b/resources/views/pages/aws_image_upload.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+
+

Session: {{ session('image') }}

+

check1: {{ session('check1') }}

+

check2: {{ session('check2') }}

+

check3: {{ session('check3') }}

+ @if ($message = session('success')) +
+ + {{ $message }} +
+ + @endif + + @if (count($errors) > 0) +
+ Whoops! There were some problems with your input. +
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + + +
+ @csrf +
+
+ +
+ +
+ +
+
+
+
+
+
+@endsection diff --git a/resources/views/pages/billings.blade.php b/resources/views/pages/billings.blade.php index 4bc012d5..bbe5a933 100644 --- a/resources/views/pages/billings.blade.php +++ b/resources/views/pages/billings.blade.php @@ -95,37 +95,37 @@
- + - -
-
- + +
+
+ - -
-
- + +
+
+ - +
- + - +
-
+
-@endsection \ No newline at end of file +@endsection diff --git a/resources/views/pages/dashboards/admin.blade.php b/resources/views/pages/dashboards/admin.blade.php index d7223cc0..b6628db0 100644 --- a/resources/views/pages/dashboards/admin.blade.php +++ b/resources/views/pages/dashboards/admin.blade.php @@ -70,11 +70,11 @@
- + - +
@@ -83,11 +83,11 @@
- + - +
@@ -180,11 +180,11 @@
- + - +
@@ -202,11 +202,11 @@
- + - +
@@ -220,11 +220,11 @@
- + - +
@@ -296,11 +296,11 @@
- + - +
diff --git a/resources/views/partials/footer.blade.php b/resources/views/partials/footer.blade.php index 89caae21..0ace7afd 100644 --- a/resources/views/partials/footer.blade.php +++ b/resources/views/partials/footer.blade.php @@ -3,9 +3,9 @@
- Copyright © {{ date('Y') }} CIEF Exchange. All rights reserved. + Copyright © {{ date('Y') }} CIEF Exchange. All rights reserved. Powered by Laravel Vapor.
- \ No newline at end of file + diff --git a/routes/api.php b/routes/api.php index d49ef78d..54566bb1 100644 --- a/routes/api.php +++ b/routes/api.php @@ -78,6 +78,10 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/milestone.php'; + // require __DIR__ . '/accounting.php'; //cief todo: To check if this is needed + + require __DIR__ . '/job.php'; + // require __DIR__ . '/rate.php'; // require __DIR__ . '/receipt.php'; diff --git a/routes/booking.php b/routes/booking.php index 01cd2e35..62057dee 100644 --- a/routes/booking.php +++ b/routes/booking.php @@ -5,6 +5,7 @@ use Illuminate\Support\Facades\Route; Route::group(['prefix' => 'booking', 'as' => 'booking.', 'namespace' => 'Bookings'], function () { Route::get('/show/{marking}', 'FetchBookingController@fetch')->name('show'); Route::get('/list', 'ListBookingsController@list')->name('list'); + Route::get('/list/job', 'ListBookingsJobController@list')->name('list.job'); Route::post('/create', 'CreateBookingController@create')->name('create'); Route::put('/update/{id}', 'UpdateBookingController@update')->name('update'); Route::put('/recipient/update/{id}', 'UpdateBookingRecipientController@update')->name('update.recipient'); diff --git a/routes/company.php b/routes/company.php index b5bca0fb..19f73e34 100644 --- a/routes/company.php +++ b/routes/company.php @@ -10,7 +10,8 @@ Route::group(['prefix' => 'company', 'as' => 'company.', 'namespace' => 'Compani Route::put('/update/{id}', 'UpdateCompanyController@update')->name('update'); Route::put('/update/{id}/profile', 'UpdateCompanyProfileController@update')->name('profile.update'); Route::put('update/{id}/status', 'UpdateCompanyStatusController@update')->name('status.update'); - Route::delete('/delete/{id}', 'DeleteCompanyController@destroy')->name('delete'); + // Route::delete('/delete/{id}', 'DeleteCompanyController@destroy')->name('delete'); + Route::delete('/delete/{id}', 'DeleteCompanyController@destroy')->name('destroy'); Route::put('/name-and-debtor/update/{id}', 'UpdateCompanyNameAndDebtorController@update')->name('update.nameAndDebtor'); Route::get('/business-type/list', 'ListBusinessTypesController@list')->name('business_type.list'); diff --git a/routes/currency.php b/routes/currency.php index b621aad6..ba55c9a2 100644 --- a/routes/currency.php +++ b/routes/currency.php @@ -1,4 +1,4 @@ - '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'); +}); diff --git a/routes/transaction.php b/routes/transaction.php index e714d6b7..ad323b0e 100644 --- a/routes/transaction.php +++ b/routes/transaction.php @@ -5,6 +5,7 @@ use Illuminate\Support\Facades\Route; Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => 'transaction.'], function () { Route::get('/list', 'ListTransactionsController@list')->name('list'); + Route::get('/list/job', 'ListTransactionsJobController@list')->name('list.job'); Route::delete('/suspend/{id}', 'SuspendTransactionController@suspend')->name('suspend'); route::post('/supplier/{id}/bill/create', 'CreateSupplierTransactionController@create')->name('supplier.create'); @@ -19,7 +20,7 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => Route::post('booking/{id}/details/import', 'ImportPurchaseOrderTransactionController@import')->name('po.import'); Route::get('bulk/po/{issuer_id}/{start_date}/{end_date}', 'CreateBulkPurchaseOrderTransactionController@create')->name('po.bulk.create'); - + Route::get('wallet/list', 'ListWalletTransactionsController@list')->name('wallet.list'); Route::get('/company/{id}/account/balance', 'FetchCompanyAccountBalanceController@fetch')->name('company.account.balance'); @@ -34,4 +35,4 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => Route::post('/{id}/approve', 'CreateBulkPurchaseOrderDocumentController@aprove')->name('approve'); Route::post('/bulk/po', 'CreateBulkPurchaseOrderDocumentController@create')->name('bulk.po'); }); -}); \ No newline at end of file +}); diff --git a/routes/web.php b/routes/web.php index 081ea4b8..aa8fa3b7 100644 --- a/routes/web.php +++ b/routes/web.php @@ -157,7 +157,7 @@ Route::get('/support', function () { 'company' => null, 'booking' => null ]); -})->name('support'); +})->name('support.fetch'); //duplicate name Route::post('/support', function (Request $request) { @@ -191,7 +191,7 @@ Route::post('/support', function (Request $request) { 'booking' => $booking, ]); -})->name('support'); +})->name('support'); //duplicate name Route::get('/online_payment/redirect', 'Billplz\CallbackBillplzController@callback')->name('online_payment.redirect'); @@ -203,7 +203,7 @@ Route::get('/export/customers/leads', 'Exports\ExportCustomersToExcelController@ Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsProducts $exportsProducts) { return $exportsProducts->download('products.csv', Excel::CSV, ['Content-Type' => 'text/csv']); -})->name('products.random'); +})->name('products.random.1'); //duplicate name Route::get('/fix_bills', function () { ini_set('max_execution_time', '1000000'); @@ -232,7 +232,7 @@ Route::get('/fix_bills', function () { } -})->name('products.random'); +})->name('products.random.2'); //duplicate name Route::get('/wallet/{marking}/details', function ($marking) { $company = \App\Models\Company::where('reference', '=', $marking)->first(); @@ -278,7 +278,7 @@ Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsP })->get(); dd($bookings->count()); return $exportsProducts->download('products.csv', Excel::CSV, ['Content-Type' => 'text/csv']); -})->name('products.random'); +})->name('products.random.3'); Route::get('/auto-purchase-order-fill', 'Bookings\AutoPurchaseOrderFillController@auto')->name('assign'); @@ -582,24 +582,24 @@ Route::get('/1688/fix/{reference}', function($reference){ // // (App()->make(createPurchaseOrderFor1688OrderProcessor::class))->execute($document->owner); // } -})->name('ecommerce.fix'); +})->name('ecommerce.fix'); //duplicate name -Route::get('/po/manual/fix', function(){ +// Route::get('/po/manual/fix', function(){ -// $bookings = Booking::whereIn('company_id', [199, 510])->whereHas('documents', function($query){ -// return $query->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER); -// })->get(); -// -// foreach ($bookings as $booking){ -// $booking->status = ApprovalStatus::APPROVED; -// $booking->save(); -// -// $booking->documents()->whereIn('document_type', [DocumentType::PURCHASE_ORDER, DocumentType::DELIVER_ORDER, DocumentType::INVOICE, DocumentType::SUPPLIER_DELIVER_ORDER])->delete(); -// $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->update(['status' => ApprovalStatus::PENDING_SUBMISSION]); -// -// } +// // $bookings = Booking::whereIn('company_id', [199, 510])->whereHas('documents', function($query){ +// // return $query->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER); +// // })->get(); +// // +// // foreach ($bookings as $booking){ +// // $booking->status = ApprovalStatus::APPROVED; +// // $booking->save(); +// // +// // $booking->documents()->whereIn('document_type', [DocumentType::PURCHASE_ORDER, DocumentType::DELIVER_ORDER, DocumentType::INVOICE, DocumentType::SUPPLIER_DELIVER_ORDER])->delete(); +// // $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->update(['status' => ApprovalStatus::PENDING_SUBMISSION]); +// // +// // } -})->name('ecommerce.fix'); +// })->name('ecommerce.fix'); //duplicate name Route::get('/payment/check', function(){ @@ -818,13 +818,13 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, ->withTrashed() ->orderBy('created_at', 'asc') ->first(); - + // get the first bill_no $firstBillNo = $firstInvoice->bill_no; if (strpos($firstBillNo, '-deleted') !== false) { $firstBillNo = substr($firstBillNo, 0, strpos($firstBillNo, '-deleted')); } - + // update currentInvoice bill_no to '-deleted-' $currentInvoice = $booking->transactions()->where('type', TransactionType::INVOICE)->first(); $currentInvoice->bill_no = $currentInvoice->bill_no ."-deleted-" . Str::random(10); @@ -849,4 +849,17 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, ); })->name('invoice.fix.byCustomerMarking'); -Route::get('/booking/{marking}/track-shipping-order', 'Bookings\TrackBookingShipmentController@track')->name('booking.track_shipping_order'); \ No newline at end of file +Route::get('/booking/{marking}/track-shipping-order', 'Bookings\TrackBookingShipmentController@track')->name('booking.track_shipping_order'); + +//cief todo: To mark new api for laravel-vapor +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; + +}); diff --git a/staging.Dockerfile b/staging.Dockerfile new file mode 100644 index 00000000..53dee762 --- /dev/null +++ b/staging.Dockerfile @@ -0,0 +1,3 @@ +FROM laravelphp/vapor:php74 + +COPY . /var/task diff --git a/vapor.yml b/vapor.yml new file mode 100644 index 00000000..8140e991 --- /dev/null +++ b/vapor.yml @@ -0,0 +1,57 @@ +id: 53427 +name: exchange +separate-vendor: true +environments: + development: + memory: 1024 + cli-memory: 512 + runtime: 'php-8.2:al2' + build: + - 'COMPOSER_MIRROR_PATH_REPOS=1 composer install --no-dev' + - 'php artisan event:cache' + - 'npm ci && npm run prod && rm -rf node_modules' + production: + domain: production.exchange.izyim.com + memory: 1024 + cli-memory: 512 + database: cief-rds-mysql + storage: exchange-2.0-production + runtime: docker + timeout: 180 + build: + - 'composer update' + - 'npm install' + - 'npm run dev' + - 'gulp build' + deploy: + - 'php artisan migrate --force' + staging: + domain: staging.exchange.izyim.com + memory: 1024 + cli-memory: 512 + database: cief-rds-mysql + storage: exchange-2.0-staging + runtime: docker + timeout: 180 + build: + - 'composer update' + - 'npm install' + - 'npm run dev' + - 'gulp build' + deploy: + - 'php artisan migrate --force' + development: + domain: dev.exchange.izyim.com + memory: 1024 + cli-memory: 512 + database: cief-rds-mysql + storage: exchange-2.0-development + runtime: docker + timeout: 180 + build: + - 'composer update' + - 'npm install' + - 'npm run dev' + - 'gulp build' + deploy: + - 'php artisan migrate --force'