diff --git a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php index fa6a9ae7..5dced525 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php @@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Accounts\Processors\AuthenticationProcessor; use App\Classes\Modules\Accounts\Processors\CreateUserProcessor; use App\Classes\Modules\Accounts\Processors\GenerateEmailVerificationAttemptProcessor; +use App\Classes\Modules\Accounts\Processors\RegisterOnShippingProcessor; use App\Classes\Modules\Companies\Processors\AssignEmployeeProcessor; use App\Classes\Modules\Companies\Processors\AssignSegmentProcessor; use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor; @@ -21,6 +22,7 @@ use App\Classes\ValueObjects\Constants\BusinessType; use App\Classes\ValueObjects\Constants\CompanyType; use App\Classes\ValueObjects\Constants\RoleTypes; use App\Classes\Jobs\CreatePerfexCRMCustomer; +use App\Classes\Modules\Companies\Services\ConnectCompanyToShippingCompanyModule; use App\Classes\Modules\Segments\DataTransferObjects\SeasonalSegmentObject; use App\Models\Company; use App\Models\Segment; @@ -30,6 +32,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\App; use App\Classes\Modules\Segments\Services\CreatesSeasonalSegment; +use Illuminate\Support\Facades\Log; class CreateCustomerLogic extends AbstractControllerLogic { @@ -77,6 +80,12 @@ class CreateCustomerLogic extends AbstractControllerLogic /** @var CreateVoucherProcessor */ private $createVoucherProcessor; + /** @var RegisterOnShippingProcessor */ + private $registerOnShippingProcessor; + + /** @var ConnectCompanyToShippingCompanyModule */ + private $connectCompanyToShippingCompanyModule; + /** * CreateCustomerLogic constructor. * @param CreateUserProcessor $createUserProcessor @@ -90,9 +99,11 @@ class CreateCustomerLogic extends AbstractControllerLogic * @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor * @param NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor * @param CreateVoucherProcessor $createVoucherProcessor + * @param RegisterOnShippingProcessor $registerOnShippingProcessor + * @param ConnectCompanyToShippingCompanyModule $connectCompanyToShippingCompanyModule */ public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateContactProcessor $createContactProcessor, AssignEmployeeProcessor $assignEmployeeProcessor, AssignSegmentProcessor $assignSegmentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor, - CreatesSeasonalSegment $createsSeasonalSegment, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor, CreateVoucherProcessor $createVoucherProcessor) + CreatesSeasonalSegment $createsSeasonalSegment, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor, CreateVoucherProcessor $createVoucherProcessor, RegisterOnShippingProcessor $registerOnShippingProcessor, ConnectCompanyToShippingCompanyModule $connectCompanyToShippingCompanyModule) { $this->createUserProcessor = $createUserProcessor; $this->createCompanyProcessor = $createCompanyProcessor; @@ -105,6 +116,8 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; $this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor; $this->createVoucherProcessor = $createVoucherProcessor; + $this->registerOnShippingProcessor = $registerOnShippingProcessor; + $this->connectCompanyToShippingCompanyModule = $connectCompanyToShippingCompanyModule; } /** @@ -155,12 +168,25 @@ class CreateCustomerLogic extends AbstractControllerLogic CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject); } - $this->generateEmailVerificationAttemptProcessor->execute($user); + // $this->generateEmailVerificationAttemptProcessor->execute($user); $this->newCustomerToVoucherifyProcessor->execute($company->id, $user, true); $this->createVoucherProcessor->execute($user, 'WELCOME50%OFF'); + $shippingCompanyModuleId = null; + if ($request->input('shipping_company_module_id')) { + $shippingCompanyModuleId = $request->input('shipping_company_module_id'); + } else { + // 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/Accounts/Processors/RegisterOnShippingProcessor.php b/app/Classes/Modules/Accounts/Processors/RegisterOnShippingProcessor.php new file mode 100644 index 00000000..0a87fed3 --- /dev/null +++ b/app/Classes/Modules/Accounts/Processors/RegisterOnShippingProcessor.php @@ -0,0 +1,43 @@ + false]); + $formParams = $request->toArray(); + $formParams['exchange_company_id'] = $companyId; + $response = $client->request('POST', $url, ['form_params' => $formParams]); + $body = $response->getBody(); + $contents = json_decode($body, true); + $payload = $contents['payload']; + $token = explode('.', $payload['access_token'])[1]; + $decodedToken = base64_decode($token); + $shippingUser = json_decode($decodedToken, true)['user']; + + return $shippingUser['company_module_id']; + } catch(\GuzzleHttp\Exception\RequestException $exception){ + Log::error($exception->getResponse()->getBody()->getContents()); + } + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Accounts/Services/GeneratesAuthenticationTokenWithBookingId.php b/app/Classes/Modules/Accounts/Services/GeneratesAuthenticationTokenWithBookingId.php new file mode 100644 index 00000000..dbc6a8e2 --- /dev/null +++ b/app/Classes/Modules/Accounts/Services/GeneratesAuthenticationTokenWithBookingId.php @@ -0,0 +1,79 @@ +builder = $builder; + } + + + /** + * @param User $user + * @return string + */ + public function execute(User $user, $bookingId): string { + + $this->builder->manager()->setBlacklistEnabled(false); + + // generate token for the customer + $this->builder->factory()->setTTL(Carbon::now()->addDay()->timestamp); + + // set the claim based on the object + $this->setTokenClaims($user, $bookingId); + + return $this->builder->fromUser($user); + } + + + /** + * @param User $user + */ + private function setTokenClaims(User $user, $bookingId): void { + + /** @var Company $company */ + $company = $user->company()->first(); + + $claims = [ + 'id' => $user->id, + 'name' => $user->name, + 'email' => $user->email, + 'type' => $user->type, + 'status' => $user->status + ]; + + if($user->type === RoleTypes::USER) { + + /** @var Company $companyModule */ + $claims = array_merge($claims, [ + 'company_id' => $company->id, + 'company_name' => $company->name, + 'company_marking' => $company->reference, + 'booking_id' => $bookingId + ]); + } + + $this->builder->factory()->customClaims(['user' => $claims]); + + + $this->builder->factory()->buildClaimsCollection(); + + } +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ConnectBookingToShippingOrderLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ConnectBookingToShippingOrderLogic.php new file mode 100644 index 00000000..1b9d8c25 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/ConnectBookingToShippingOrderLogic.php @@ -0,0 +1,56 @@ + 'Connect Exchange Booking With Shipping Order', + 'message' => 'You have successfully connect Exchange Booking with Shipping Order' + ]; + } + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** @var ConnectBookingToShippingOrder */ + private $connectBookingToShippingOrder; + + /** + * ConnectBookingToShippingOrderLogic constructor. + * @param FetchesBooking $fetchesBooking + * @param ConnectBookingToShippingOrder $connectBookingToShippingOrder + */ + public function __construct(FetchesBooking $fetchesBooking, ConnectBookingToShippingOrder $connectBookingToShippingOrder) + { + $this->fetchesBooking = $fetchesBooking; + $this->connectBookingToShippingOrder = $connectBookingToShippingOrder; + } + + + /** + * @param Request $request + * @return void + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function execute(Request $request) + { + // to make sure the booking is exist + $booking = $this->fetchesBooking->execute(['id' => $request->route('booking_id')]); + + $this->connectBookingToShippingOrder->execute($booking, $request->route('shipping_order_id')); + + } +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/TrackBookingShipmentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/TrackBookingShipmentLogic.php new file mode 100644 index 00000000..a6b775f8 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/TrackBookingShipmentLogic.php @@ -0,0 +1,86 @@ + 'Retrieved Shipping Order', + 'message' => 'You have successfully retrieved shipping order' + ]; + } + + /** @var CanFetchBooking */ + private $canFetchBooking; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** @var GeneratesAuthenticationToken */ + private $generatesAuthenticationToken; + + /** @var GeneratesAuthenticationTokenWithBookingId */ + private $generatesAuthenticationTokenWithBookingId; + + /** + * TrackBookingShipmentLogic constructor. + * @param CanFetchBooking $canFetchBooking + * @param FetchesBooking $fetchesBooking + * @param GeneratesAuthenticationToken $generatesAuthenticationToken + * @param GeneratesAuthenticationTokenWithBookingId $generatesAuthenticationTokenWithBookingId + */ + public function __construct(CanFetchBooking $canFetchBooking, FetchesBooking $fetchesBooking, GeneratesAuthenticationToken $generatesAuthenticationToken, GeneratesAuthenticationTokenWithBookingId $generatesAuthenticationTokenWithBookingId) + { + $this->canFetchBooking = $canFetchBooking; + $this->fetchesBooking = $fetchesBooking; + $this->generatesAuthenticationToken = $generatesAuthenticationToken; + $this->generatesAuthenticationTokenWithBookingId = $generatesAuthenticationTokenWithBookingId; + } + + + /** + * @param Request $request + * @return void + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function execute(Request $request) + { + + $this->canFetchBooking->passes(); + + $booking = Booking::where('marking', $request->route('marking'))->first(); + $shippingOrder = ShippingOrderBooking::where('booking_id', $booking->id)->first(); + + $user = Auth::user(); + // if booking is connected with shipping order, we want to show the order, therefore exchange booking id is not needed + if ($shippingOrder) { + $token = $this->generatesAuthenticationToken->execute($user); + return redirect("http://127.0.0.1:8001/?exchangeToken={$token}&orderId={$shippingOrder->shipping_order_id}"); + } else { + // else create the order for current booking by putting in booking id into token + $token = $this->generatesAuthenticationTokenWithBookingId->execute($user, $booking->id); + return redirect("http://127.0.0.1:8001/?exchangeToken={$token}"); + } + + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/Services/ConnectBookingToShippingOrder.php b/app/Classes/Modules/Bookings/Services/ConnectBookingToShippingOrder.php new file mode 100644 index 00000000..fb6c2d19 --- /dev/null +++ b/app/Classes/Modules/Bookings/Services/ConnectBookingToShippingOrder.php @@ -0,0 +1,25 @@ +booking_id = $booking->id; + $model->shipping_order_id = $shippingOrderId; + + return $this->handler($model); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Companies/ControllersLogic/ApproveIdentificationDocumentLogic.php b/app/Classes/Modules/Companies/ControllersLogic/ApproveIdentificationDocumentLogic.php index cf894bfd..028e5ecb 100644 --- a/app/Classes/Modules/Companies/ControllersLogic/ApproveIdentificationDocumentLogic.php +++ b/app/Classes/Modules/Companies/ControllersLogic/ApproveIdentificationDocumentLogic.php @@ -16,8 +16,10 @@ use App\Classes\Modules\Documents\Services\ApprovesDocument; use App\Classes\Modules\Notifications\DataTransferObjects\NotificationObject; Use App\Classes\Modules\Notifications\Processors\CreateNotificationProcessor; use App\Classes\General\Interfaces\Notifiable; - +use App\Classes\Modules\Companies\Processors\ApproveIdentificationDocumentOnShippingProcessor; +use App\Classes\ValueObjects\Constants\DocumentType; use App\Models\Document; +use App\Models\ShippingCompanyConnection; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -52,6 +54,9 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic /** @var CreateNotificationProcessor */ private $createNotificationProcessor; + /** @var ApproveIdentificationDocumentOnShippingProcessor */ + private $approveIdentificationDocumentOnShippingProcessor; + /** * ApproveIdentificationDocumentLogic constructor. * @param CanApproveDocument $canApproveDocument @@ -60,8 +65,9 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic * @param FetchesDocument $fetchesDocument * @param UpdatesCompanyStatus $updatesCompanyStatus * @param CreateNotificationProcessor $createNotificationProcessor + * @param ApproveIdentificationDocumentOnShippingProcessor $approveIdentificationDocumentOnShippingProcessor */ - public function __construct(CanApproveDocument $canApproveDocument, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, UpdatesCompanyStatus $updatesCompanyStatus, CreateNotificationProcessor $createNotificationProcessor) + public function __construct(CanApproveDocument $canApproveDocument, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, UpdatesCompanyStatus $updatesCompanyStatus, CreateNotificationProcessor $createNotificationProcessor, ApproveIdentificationDocumentOnShippingProcessor $approveIdentificationDocumentOnShippingProcessor) { $this->canApproveDocument = $canApproveDocument; $this->approvesDocument = $approvesDocument; @@ -69,6 +75,7 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic $this->fetchesDocument = $fetchesDocument; $this->updatesCompanyStatus = $updatesCompanyStatus; $this->createNotificationProcessor = $createNotificationProcessor; + $this->approveIdentificationDocumentOnShippingProcessor = $approveIdentificationDocumentOnShippingProcessor; } /** @@ -80,11 +87,17 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { + $documentId = $request->route('document_id'); + + if ($request->route('shipping_company_module_id')) { + $company = ShippingCompanyConnection::where('shipping_company_module_id', $request->route('shipping_company_module_id'))->first()->company; + $documentId = $company->documents()->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->where('status', ApprovalStatus::PENDING_VERIFICATION)->first()->id; + } $status = $request->route('status'); /** @var Document $document */ - $document = $this->fetchesDocument->execute(['id' => $request->route('document_id')]); + $document = $this->fetchesDocument->execute(['id' => $documentId]); $this->canApproveDocument->passes(); @@ -102,6 +115,12 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic $this->createNotificationProcessor->execute($object); + // if this request is not calling from shipping portal, then approve the document on shipping portal for this user + $company = $document->owner()->first(); + if (!$request->route('shipping_company_module_id') && $company->shippingCompanyConnection()->first()) { + $this->approveIdentificationDocumentOnShippingProcessor->execute($request, $document->owner_id, $status); + } + return $this->resourceResponse(new DocumentResource($document)); } diff --git a/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php b/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php index 6a818ea8..75b72614 100644 --- a/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php +++ b/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php @@ -4,6 +4,7 @@ namespace App\Classes\Modules\Companies\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; +use App\Classes\Modules\Companies\Processors\CreateIdentificationDocumentOnShippingProcessor; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Companies\Services\UpdatesCompanyStatus; use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; @@ -17,8 +18,10 @@ use App\Classes\ValueObjects\Constants\DocumentType; use App\Classes\ValueObjects\Constants\Milestones; use App\Models\Company; use App\Models\Document; +use App\Models\ShippingCompanyConnection; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; class CreateIdentificationDocumentLogic extends AbstractControllerLogic { @@ -51,6 +54,9 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic /** @var CheckMilestonesForRewardProcessor */ private $checkMilestonesForRewardProcessor; + /** @var CreateIdentificationDocumentOnShippingProcessor */ + private $createIdentificationDocumentOnShippingProcessor; + /** * CreateIdentificationDocumentLogic constructor. * @param FetchesCompany $fetchesCompany @@ -59,8 +65,9 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic * @param UpdatesCompanyStatus $updatesCompanyStatus * @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor * @param CheckMilestoneForRewardProcessor $checkMilestonesForRewardProcessor + * @param CreateIdentificationDocumentOnShippingProcessor $createIdentificationDocumentOnShippingProcessor */ - public function __construct(FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesCompanyStatus $updatesCompanyStatus, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor) + public function __construct(FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesCompanyStatus $updatesCompanyStatus, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor, CreateIdentificationDocumentOnShippingProcessor $createIdentificationDocumentOnShippingProcessor) { $this->fetchesCompany = $fetchesCompany; $this->createsDocument = $createsDocument; @@ -68,6 +75,7 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic $this->updatesCompanyStatus = $updatesCompanyStatus; $this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor; $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; + $this->createIdentificationDocumentOnShippingProcessor = $createIdentificationDocumentOnShippingProcessor; } /** @@ -78,8 +86,15 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic public function logic(Request $request) : JsonResponse { + if ($request->route('shipping_company_module_id')) { + $company = ShippingCompanyConnection::where('shipping_company_module_id', $request->route('shipping_company_module_id'))->first()->company; + $companyId = $company->id; + } else { + $companyId = $request->route('id'); + } + /** @var Company $company */ - $company = $this->fetchesCompany->execute(['id' => $request->route('id')]); + $company = $this->fetchesCompany->execute(['id' => $companyId]); $object = new DocumentObject($company->type === CompanyType::COMPANY_BUSINESS ? DocumentType::SSM_REGISTRATION : DocumentType::IDENTITY_CARD, $request->input('files'), $request->input('identification_no'), ApprovalStatus::PENDING_VERIFICATION, 'identifications'); @@ -94,6 +109,11 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic $this->newLeadTaskToPerfexCRMProcessor->execute($company); } + // create identification on shipping if this request not coming from shipping + if (!$request->route('shipping_company_module_id') && $company->shippingCompanyConnection()->first()) { + $this->createIdentificationDocumentOnShippingProcessor->execute($request, $company->id); + } + //cief todo: case study 2 // $user = $company->employees()->first(); // $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_2]); diff --git a/app/Classes/Modules/Companies/ControllersLogic/LinkShippingCompanyLogic.php b/app/Classes/Modules/Companies/ControllersLogic/LinkShippingCompanyLogic.php new file mode 100644 index 00000000..231ff7ae --- /dev/null +++ b/app/Classes/Modules/Companies/ControllersLogic/LinkShippingCompanyLogic.php @@ -0,0 +1,59 @@ + 'Connect Shipping Portal Account', + 'message' => 'You have successfully connect your exchange account with your shipping portal account.' + ]; + } + + /** @var LinkShippingCompanyProcessor */ + private $linkShippingCompanyProcessor; + + /** @var ConnectCompanyToShippingCompanyModule */ + private $connectCompanyToShippingCompanyModule; + + /** + * FetchCompanyControllersLogic constructor. + * @param LinkShippingCompanyProcessor $linkShippingCompanyProcessor + * @param ConnectCompanyToShippingCompanyModule $connectCompanyToShippingCompanyModule + */ + public function __construct(LinkShippingCompanyProcessor $linkShippingCompanyProcessor, ConnectCompanyToShippingCompanyModule $connectCompanyToShippingCompanyModule) + { + $this->linkShippingCompanyProcessor = $linkShippingCompanyProcessor; + $this->connectCompanyToShippingCompanyModule = $connectCompanyToShippingCompanyModule; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + $shippingCompanyModuleId = $this->linkShippingCompanyProcessor->execute($request, $request->route('id')); + + $this->connectCompanyToShippingCompanyModule->execute($request->route('id'), $shippingCompanyModuleId); + + return $this->response([]); + + } + +} diff --git a/app/Classes/Modules/Companies/Processors/ApproveIdentificationDocumentOnShippingProcessor.php b/app/Classes/Modules/Companies/Processors/ApproveIdentificationDocumentOnShippingProcessor.php new file mode 100644 index 00000000..f1f39714 --- /dev/null +++ b/app/Classes/Modules/Companies/Processors/ApproveIdentificationDocumentOnShippingProcessor.php @@ -0,0 +1,46 @@ + false]); + $token = $request->bearerToken(); + $headers = [ + 'Authorization' => 'Bearer ' . $token, + 'Accept' => 'application/json', + ]; + $formParams = $request->toArray(); + $response = $client->request('PUT', $url, [ + 'headers' => $headers, + 'form_params' => $formParams + ]); + $body = $response->getBody(); + $contents = json_decode($body, true); + + return $contents; + } catch(\GuzzleHttp\Exception\RequestException $exception){ + Log::error($exception->getResponse()->getBody()->getContents()); + } + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Companies/Processors/CreateIdentificationDocumentOnShippingProcessor.php b/app/Classes/Modules/Companies/Processors/CreateIdentificationDocumentOnShippingProcessor.php new file mode 100644 index 00000000..37b0ba31 --- /dev/null +++ b/app/Classes/Modules/Companies/Processors/CreateIdentificationDocumentOnShippingProcessor.php @@ -0,0 +1,46 @@ + false]); + $token = $request->bearerToken(); + $headers = [ + 'Authorization' => 'Bearer ' . $token, + 'Accept' => 'application/json', + ]; + $formParams = $request->toArray(); + $response = $client->request('POST', $url, [ + 'headers' => $headers, + 'form_params' => $formParams + ]); + $body = $response->getBody(); + $contents = json_decode($body, true); + + return $contents; + } catch(\GuzzleHttp\Exception\RequestException $exception){ + Log::error($exception->getResponse()->getBody()->getContents()); + } + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Companies/Processors/LinkShippingCompanyProcessor.php b/app/Classes/Modules/Companies/Processors/LinkShippingCompanyProcessor.php new file mode 100644 index 00000000..8c5a13d4 --- /dev/null +++ b/app/Classes/Modules/Companies/Processors/LinkShippingCompanyProcessor.php @@ -0,0 +1,51 @@ + false]); + $token = $request->bearerToken(); + $headers = [ + 'Authorization' => 'Bearer ' . $token, + 'Accept' => 'application/json', + ]; + $response = $client->request('POST', $url, [ + 'headers' => $headers, + 'form_params' => [ + 'email' => $request->input('email'), + 'password' => $request->input('password') + ] + ]); + $body = $response->getBody(); + $contents = json_decode($body, true); + $payload = $contents['payload']; + + return $payload['shipping_company_module_id']; + } catch(\GuzzleHttp\Exception\RequestException $exception){ + throw new MalformedRequestException(json_decode($exception->getResponse()->getBody()->getContents(), true)['message']); + // Log::error($exception->getResponse()->getBody()->getContents()); + } + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Companies/Services/ConnectCompanyToShippingCompanyModule.php b/app/Classes/Modules/Companies/Services/ConnectCompanyToShippingCompanyModule.php new file mode 100644 index 00000000..eb00f20f --- /dev/null +++ b/app/Classes/Modules/Companies/Services/ConnectCompanyToShippingCompanyModule.php @@ -0,0 +1,23 @@ +company_id = $companyId; + $model->shipping_company_module_id = $shippingCompanyModuleId; + + return $this->handler($model); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Documents/Services/ApprovesDocument.php b/app/Classes/Modules/Documents/Services/ApprovesDocument.php index 9458774e..cf113f18 100644 --- a/app/Classes/Modules/Documents/Services/ApprovesDocument.php +++ b/app/Classes/Modules/Documents/Services/ApprovesDocument.php @@ -5,6 +5,7 @@ namespace App\Classes\Modules\Documents\Services; use App\Classes\General\Eloquent\AbstractUpdateRecord; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Models\Document; +use App\Models\User; use Carbon\Carbon; class ApprovesDocument extends AbstractUpdateRecord @@ -17,8 +18,19 @@ class ApprovesDocument extends AbstractUpdateRecord */ public function execute(Document $model) { + $user = Auth()->user(); + // if auth user is null, then this services is calling from shipping + if (!$user) { + $token = explode('.', request()->bearerToken())[1]; + $decodedToken = base64_decode($token); + $shippingUser = json_decode($decodedToken, true)['user']; + $user = User::where('email', $shippingUser['email'])->first(); + if (!$user) { + $user = User::find(1); + } + } $model->status = ApprovalStatus::APPROVED; - $model->approver = Auth()->user()->id; + $model->approver = $user->id; $model->approval_date = Carbon::now(); return $this->handler($model); diff --git a/app/Classes/Modules/Documents/Services/RejectsDocument.php b/app/Classes/Modules/Documents/Services/RejectsDocument.php index 4a7c7bfa..e56aeec0 100644 --- a/app/Classes/Modules/Documents/Services/RejectsDocument.php +++ b/app/Classes/Modules/Documents/Services/RejectsDocument.php @@ -5,6 +5,7 @@ namespace App\Classes\Modules\Documents\Services; use App\Classes\General\Eloquent\AbstractUpdateRecord; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Models\Document; +use App\Models\User; use Carbon\Carbon; class RejectsDocument extends AbstractUpdateRecord @@ -17,8 +18,19 @@ class RejectsDocument extends AbstractUpdateRecord */ public function execute(Document $model) { + $user = Auth()->user(); + // if auth user is null, then this services is calling from shipping + if (!$user) { + $token = explode('.', request()->bearerToken())[1]; + $decodedToken = base64_decode($token); + $shippingUser = json_decode($decodedToken, true)['user']; + $user = User::where('email', $shippingUser['email'])->first(); + if (!$user) { + $user = User::find(1); + } + } $model->status = ApprovalStatus::REJECTED; - $model->approver = Auth()->user()->id; + $model->approver = $user->id; $model->approval_date = Carbon::now(); return $this->handler($model); diff --git a/app/Http/Controllers/Bookings/ConnectBookingToShippingOrderController.php b/app/Http/Controllers/Bookings/ConnectBookingToShippingOrderController.php new file mode 100644 index 00000000..46670bfd --- /dev/null +++ b/app/Http/Controllers/Bookings/ConnectBookingToShippingOrderController.php @@ -0,0 +1,19 @@ +execute($request); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Bookings/TrackBookingShipmentController.php b/app/Http/Controllers/Bookings/TrackBookingShipmentController.php new file mode 100644 index 00000000..adf8490e --- /dev/null +++ b/app/Http/Controllers/Bookings/TrackBookingShipmentController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Companies/LinkShippingCompanyController.php b/app/Http/Controllers/Companies/LinkShippingCompanyController.php new file mode 100644 index 00000000..bfe9270b --- /dev/null +++ b/app/Http/Controllers/Companies/LinkShippingCompanyController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 93731db4..321f0010 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -8,6 +8,7 @@ use App\Http\Middleware\EncryptCookies; use App\Http\Middleware\RedirectIfAuthenticated; use App\Http\Middleware\TrimStrings; use App\Http\Middleware\TrustProxies; +use App\Http\Middleware\ValidateShippingToken; use App\Http\Middleware\ValidateToken; use App\Http\Middleware\VerifyCsrfToken; use Illuminate\Foundation\Http\Kernel as HttpKernel; @@ -76,6 +77,7 @@ class Kernel extends HttpKernel 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'valid.token' => ValidateToken::class, + 'valid.shipping.token' => ValidateShippingToken::class, 'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class, ]; } diff --git a/app/Http/Middleware/ValidateShippingToken.php b/app/Http/Middleware/ValidateShippingToken.php new file mode 100644 index 00000000..96601e15 --- /dev/null +++ b/app/Http/Middleware/ValidateShippingToken.php @@ -0,0 +1,57 @@ +manager = $manager; + } + + + /** + * Checks if jwt token is valid. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @return mixed + */ + public function handle($request, Closure $next) + { + try { + + $token = explode('.', $this->manager->getToken())[1]; + $decodedToken = base64_decode($token); + $shippingUser = json_decode($decodedToken, true)['user']; + if ($shippingUser['type'] === 3) { + $shippingCompanyModuleId = $shippingUser['company_module_id']; + $connection = ShippingCompanyConnection::where("shipping_company_module_id", $shippingCompanyModuleId)->first(); + + if(!$connection){ throw new AccessUnauthorisedException(); } + } + } catch (Exception $exception) { + + return (new ApiResponseObject('Authentication', 'To keep your account secure we need to re-validate your account', HttpStatus::ACCESS_UNAUTHORISED))->handler(); + + } + + return $next($request); + } +} diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index 85ecee16..9714f2f0 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -35,6 +35,7 @@ class CompanyResource extends JsonResource return [ 'id' => $this->id, + 'shipping_company_module_id' => $this->shippingCompanyConnection ? $this->shippingCompanyConnection->shipping_company_module_id : null, 'name' => $this->name, 'reference' => $this->reference, 'debtor' => $this->debtor, @@ -43,7 +44,7 @@ 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()), + 'employee' => new UserResource(Auth::user() && 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/Models/Company.php b/app/Models/Company.php index 8b2e6081..345fbb77 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Collection; @@ -147,6 +148,14 @@ class Company extends AbstractModel implements Documentable }); } + /** + * @return \Illuminate\Database\Eloquent\Relations\HasOne + **/ + public function shippingCompanyConnection(): HasOne + { + return $this->hasOne(ShippingCompanyConnection::class, 'company_id', 'id'); + } + } diff --git a/app/Models/ShippingCompanyConnection.php b/app/Models/ShippingCompanyConnection.php new file mode 100644 index 00000000..ce3a9536 --- /dev/null +++ b/app/Models/ShippingCompanyConnection.php @@ -0,0 +1,31 @@ +BelongsTo(Company::class, 'company_id', 'id'); + } + +} diff --git a/app/Models/ShippingOrderBooking.php b/app/Models/ShippingOrderBooking.php new file mode 100644 index 00000000..eb9064b8 --- /dev/null +++ b/app/Models/ShippingOrderBooking.php @@ -0,0 +1,31 @@ +BelongsTo(Booking::class, 'booking_id', 'id'); + } + +} diff --git a/database/migrations/2023_11_05_172837_create_shipping_company_connections_table.php b/database/migrations/2023_11_05_172837_create_shipping_company_connections_table.php new file mode 100644 index 00000000..54eaafb5 --- /dev/null +++ b/database/migrations/2023_11_05_172837_create_shipping_company_connections_table.php @@ -0,0 +1,35 @@ +id(); + $table->foreignId('company_id'); + $table->bigInteger('shipping_company_module_id')->unsigned()->index(); + $table->timestamps(); + $table->softDeletes(); + + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('shipping_company_connections'); + } +} diff --git a/database/migrations/2023_11_17_165004_create_shipping_order_bookings.php b/database/migrations/2023_11_17_165004_create_shipping_order_bookings.php new file mode 100644 index 00000000..0ee91c04 --- /dev/null +++ b/database/migrations/2023_11_17_165004_create_shipping_order_bookings.php @@ -0,0 +1,34 @@ +id(); + $table->foreignId('booking_id'); + $table->bigInteger('shipping_order_id')->unsigned()->index(); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('shipping_order_bookings'); + } +} diff --git a/resources/assets/images/cief-izyim-logo.png b/resources/assets/images/cief-izyim-logo.png new file mode 100644 index 00000000..126c6533 Binary files /dev/null and b/resources/assets/images/cief-izyim-logo.png differ diff --git a/resources/assets/vue/components/accounts/forms/ConnectIzyimFormComponent.vue b/resources/assets/vue/components/accounts/forms/ConnectIzyimFormComponent.vue new file mode 100644 index 00000000..aa8a278b --- /dev/null +++ b/resources/assets/vue/components/accounts/forms/ConnectIzyimFormComponent.vue @@ -0,0 +1,50 @@ + + + \ No newline at end of file diff --git a/resources/assets/vue/components/accounts/forms/IzyimLoginFormComponent.vue b/resources/assets/vue/components/accounts/forms/IzyimLoginFormComponent.vue new file mode 100644 index 00000000..effbd0b2 --- /dev/null +++ b/resources/assets/vue/components/accounts/forms/IzyimLoginFormComponent.vue @@ -0,0 +1,73 @@ + + \ No newline at end of file diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index ce4ba5a7..4e3bf257 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -271,6 +271,17 @@ +
+
+ +
+
+ + + + +
+
@@ -332,6 +343,9 @@ clickExpand(){ this.expandPaymentDetails = !this.expandPaymentDetails; }, + trackShipment(){ + window.open(route('booking.track_shipping_order', this.data.booking.marking) + '?token=' + this.$store.getters.getAccessToken, '_blank'); + }, }, mixins: [componentHandler] } diff --git a/routes/api.php b/routes/api.php index 8b4bada0..d49ef78d 100644 --- a/routes/api.php +++ b/routes/api.php @@ -25,6 +25,17 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function Route::post('online_payment/callback', 'Billplz\CallbackBillplzController@callback')->name('online_payment.callback'); + // calling from shipping portal + Route::group(['middleware' => 'valid.shipping.token'], function () { + Route::post('/shipping/order/{shipping_order_id}/booking/{booking_id}/connect', 'Bookings\ConnectBookingToShippingOrderController@connect')->name('shipping.order.connect'); + Route::group(['prefix' => 'shipping/company', 'as' => 'shipping.company.', 'namespace' => 'Companies'], function () { + Route::group(['prefix' => '{shipping_company_module_id}/identification', 'as' => 'identification.'], function () { + Route::post('/create', 'CreateIdentificationDocumentController@create')->name('create'); + Route::put('/approval/{status}', 'ApproveIdentificationDocumentController@approve')->where('status', 'approve|reject')->name('approval'); + }); + }); + }); + Route::group(['middleware' => 'valid.token'], function () { Route::get('/storage/{fileName}/fetch', 'Documents\RenderDocumentController@fileStorageServe')->where(['fileName' => '.*'])->name('storage.document.file'); diff --git a/routes/company.php b/routes/company.php index 18997c8d..b5bca0fb 100644 --- a/routes/company.php +++ b/routes/company.php @@ -3,6 +3,7 @@ use Illuminate\Support\Facades\Route; Route::group(['prefix' => 'company', 'as' => 'company.', 'namespace' => 'Companies'], function () { + Route::post('/{id}/connect_shipping', 'LinkShippingCompanyController@link')->name('connect_shipping'); Route::get('/{id}/show', 'FetchCompanyController@fetch')->name('show'); Route::get('/list', 'ListCompaniesController@list')->name('list'); Route::post('/create', 'CreateCompanyController@create')->name('create'); diff --git a/routes/web.php b/routes/web.php index ead4b3d2..1586d851 100644 --- a/routes/web.php +++ b/routes/web.php @@ -842,4 +842,6 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, } } ); -})->name('invoice.fix.byCustomerMarking'); \ No newline at end of file +})->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