diff --git a/app/Classes/General/Eloquent/Filters/ClaimantId.php b/app/Classes/General/Eloquent/Filters/ClaimantId.php new file mode 100644 index 00000000..7d473825 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/ClaimantId.php @@ -0,0 +1,20 @@ +where('claimant_id', $value); + } + +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/PackingListDeliveryStatus.php b/app/Classes/General/Eloquent/Filters/PackingListDeliveryStatus.php new file mode 100644 index 00000000..3cc41510 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/PackingListDeliveryStatus.php @@ -0,0 +1,31 @@ +whereHas('containers', function ($query){ + $query->where('containers.status', ApprovalStatus::COMPLETED); + })->whereDoesntHave('transports') : ($value == 2 ? $builder->whereHas('transports', function (Builder $query) use ($value) { + $query->whereDoesntHave('schedules', function (Builder $query) use ($value) { + $query->where('status', '!=', ApprovalStatus::EXPIRED)->where('eta', '<=', Carbon::now()); + }); + }) : $builder->whereHas('transports', function (Builder $query) use ($value) { + $query->whereHas('schedules', function (Builder $query) use ($value) { + $query->where('status', '!=', ApprovalStatus::EXPIRED)->where('eta', '<=', Carbon::now()); + }); + })); + } +} diff --git a/app/Classes/General/Interfaces/Notifiable.php b/app/Classes/General/Interfaces/Notifiable.php new file mode 100644 index 00000000..e9d8f22d --- /dev/null +++ b/app/Classes/General/Interfaces/Notifiable.php @@ -0,0 +1,15 @@ +getBillplzBill = $getBillplzBill; + $this->fetchesTransaction = $fetchesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->updatesWalletBalance = $updatesWalletBalance; + } + + + /** + * @param Request $request + * @return bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws MalformedRequestException + * @throws ResourceNotFoundException + */ + public function execute(Request $request) + { + $billplzXSignatureObject = new BillplzXSignatureObject($request); + + if(!$billplzXSignatureObject->isValidSignature()){ + throw new MalformedRequestException('Billplz Payment validation failed.'); + } + + $billPlz = $this->getBillplzBill->execute($billplzXSignatureObject->getBillPlzId()); + + if(!$billPlz) throw new ResourceNotFoundException('Billplz bill not found.'); + + $transaction = $this->fetchesTransaction->execute(['payment_reference' => $billplzXSignatureObject->getBillPlzId()]); + + if($billPlz->state === 'paid') { + $status = ApprovalStatus::APPROVED; + } + + if($billPlz->state === 'due') { + $status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION; + } + + if($transaction->status !== ApprovalStatus::COMPLETED){ + + if($transaction->owner instanceof Wallet && $transaction->status !== ApprovalStatus::APPROVED && $status === ApprovalStatus::APPROVED) { + $this->updatesWalletBalance->execute($transaction->owner, $transaction->amount); + } + $this->updatesTransactionStatus->execute($transaction, $status); + + } + + + $token = Auth::fromUser(User::find(1)); + $request->headers->set('Authorization', 'Bearer '.$token); + + $marking = $transaction->owner instanceof Booking ? $transaction->booking->marking : $transaction->owner->owner->bookings()->orderBy('id', 'DESC')->first()->marking; + + return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $marking, 'transaction' => $transaction, 'status' => $status]); + + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Billplzs/ControllersLogic/CreateBillplzBillLogic.php b/app/Classes/Modules/Billplzs/ControllersLogic/CreateBillplzBillLogic.php new file mode 100644 index 00000000..a7069841 --- /dev/null +++ b/app/Classes/Modules/Billplzs/ControllersLogic/CreateBillplzBillLogic.php @@ -0,0 +1,54 @@ + 'Created Billplz Bill', + 'message' => 'You have successfully created a new Bill' + ]; + } + + /** @var CreatesBillplzBill */ + private $createsBillplzBill; + + /** + * CreateBookingLogic constructor. + * @param CreatesBillplzBill $createsBillplzBill + */ + public function __construct(CreatesBillplzBill $createsBillplzBill) + { + $this->createsBillplzBill = $createsBillplzBill; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $billPlz = $this->createsBillplzBill->execute($request->user()->name, $request->user()->email, $request->input('description'), 200, $request->input('bankName')); + + if(!$billPlz) throw new MalformedRequestException('Unable to get correct response from billplz server.'); + + return $this->response(['data' => $billPlz]); + + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Billplzs/DataTransferObjects/BillplzXSignatureObject.php b/app/Classes/Modules/Billplzs/DataTransferObjects/BillplzXSignatureObject.php new file mode 100644 index 00000000..c1295886 --- /dev/null +++ b/app/Classes/Modules/Billplzs/DataTransferObjects/BillplzXSignatureObject.php @@ -0,0 +1,120 @@ +type = $request->exists('billplz') ? 'redirect' : 'callback'; + + $this->request = $this->type === 'redirect' ? $request->input('billplz') : $request; + + $this->billPlzId = $this->request['id']; + + $this->status = $this->request['transaction_status']; + + $this->requestXSignature = $this->request['x_signature']; + + $this->_constructBillplzArray()->_natSortBillplzArray()->_constructBillplzString()->_computeBillplzXSignature(); + } + + private function _constructBillplzArray(){ + + $this->billPlzConstructArray = collect($this->request)->forget('x_signature')->map(function($item, $key){ + return $this->type === 'redirect' ? 'billplz'.$key.$item : $key.$item; + })->toArray(); + + return $this; + } + + private function _natCaseSortBillplzArray(){ + natcasesort($this->billPlzConstructArray); + return $this; + } + + private function _natSortBillplzArray(){ + natsort($this->billPlzConstructArray); + return $this; + } + + private function _constructBillplzString(){ + $this->billPlzConstructString = implode('|', $this->billPlzConstructArray); + return $this; + } + + private function _computeBillplzXSignature(){ + $this->billPlzComputedXSignature = hash_hmac('sha256', $this->billPlzConstructString, config('billplz.x_signature_key')); + return $this; + } + + public function getBillPlzId(): string + { + return $this->billPlzId; + } + + public function getStatus(): string + { + return $this->status; + } + + /** + * @return array + */ + public function getBillPlzConstructArray(): array + { + return $this->billPlzConstructArray; + } + + /** + * @return string + */ + public function getBillPlzConstructString(): string + { + return $this->billPlzConstructString; + } + + /** + * @return string + */ + public function getBillPlzComputedXSignature(): string + { + return $this->billPlzComputedXSignature; + } + + public function isValidSignature(): bool + { + return $this->billPlzComputedXSignature === $this->requestXSignature ? true : false; + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Billplzs/Services/CreatesBillplzBill.php b/app/Classes/Modules/Billplzs/Services/CreatesBillplzBill.php new file mode 100644 index 00000000..5b331fca --- /dev/null +++ b/app/Classes/Modules/Billplzs/Services/CreatesBillplzBill.php @@ -0,0 +1,57 @@ +post(config('billplz.base_url').'/api/v3/bills', [ + 'collection_id' => $wallet ? config('billplz.wallet_collection_id') : config('billplz.collection_id'), + 'name' => $name, + 'email' => $email, + 'description' => $description, + 'amount' => $this->finalizeAmount($amount), + 'redirect_url' => route('online_payment.redirect'), + 'callback_url' => route('api.online_payment.callback'), + 'reference_1_label' => 'Bank Code', + 'reference_1' => $bankCode ? $bankCode : '', + 'reference_2_label' => 'Bill Number', + 'reference_2' => $billNumber + ]); + + if($response->successful()){ + $data = $response->json(); + + $data['url'] = $data['url'].'?auto_submit=true'; + + return (object) $data; + }else{ + return null; + } + }catch(\Exception $exception){ + throw new MalformedRequestException('Unable to get correct response from billplz server' . $exception->getMessage()); + } + } + + protected function finalizeAmount($amount){ + $number = round($amount, 2) * 100; + return (string) $number; + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Billplzs/Services/GetBillplzBill.php b/app/Classes/Modules/Billplzs/Services/GetBillplzBill.php new file mode 100644 index 00000000..2a86b403 --- /dev/null +++ b/app/Classes/Modules/Billplzs/Services/GetBillplzBill.php @@ -0,0 +1,31 @@ +get(config('billplz.base_url').'/api/v3/bills/'.$billPlzId); + + if($response->successful()){ + $data = $response->json(); + + return (object) $data; + }else{ + return null; + } + }catch(\Exception $exception){ + throw new MalformedRequestException('Unable to get correct response from billplz server'); + } + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Companies/ControllersLogic/ListCompanyModulesLogic.php b/app/Classes/Modules/Companies/ControllersLogic/ListCompanyModulesLogic.php new file mode 100644 index 00000000..6d7bbc26 --- /dev/null +++ b/app/Classes/Modules/Companies/ControllersLogic/ListCompanyModulesLogic.php @@ -0,0 +1,61 @@ + 'Retrieved Company Moduels', + 'message' => 'You have successfully retrieved a list of Companies' + ]; + } + + /** @var CanListCompanies */ + private $canListCompanies; + + /** @var ListsCompanyModules */ + private $listsCompanyModules; + + /** + * ListCompaniesControllersLogic constructor. + * @param CanListCompanies $canListCompanies + * @param ListsCompanyModules $listsCompanyModules + */ + public function __construct(CanListCompanies $canListCompanies, ListsCompanyModules $listsCompanyModules) + { + $this->canListCompanies = $canListCompanies; + $this->listsCompanyModules = $listsCompanyModules; + } + + + /** + * @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 + { + $this->canListCompanies->passes(); + + $query = $this->listsCompanyModules->execute($this->listsCompanyModules->deserializeFilters($request->input('filters'))); + return $this->collectionResponse(CompanyModuleResource::collection($query)); + + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Companies/Services/ListsCompanyModules.php b/app/Classes/Modules/Companies/Services/ListsCompanyModules.php new file mode 100644 index 00000000..906578c1 --- /dev/null +++ b/app/Classes/Modules/Companies/Services/ListsCompanyModules.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Notifications/DataTransferObjects/NotificationObject.php b/app/Classes/Modules/Notifications/DataTransferObjects/NotificationObject.php new file mode 100644 index 00000000..40dc4f3c --- /dev/null +++ b/app/Classes/Modules/Notifications/DataTransferObjects/NotificationObject.php @@ -0,0 +1,101 @@ +title = $title; + $this->description = $description; + $this->subject = $subject; + $this->target = $target; + $this->causer = $causer; + $this->status = $status; + } + + /** + * @return int + */ + public function getTitle(): string + { + return $this->title; + } + + /** + * @return int + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * @return Notifiable + */ + public function getSubject(): Notifiable + { + return $this->subject; + } + + /** + * @return Notifiable + */ + public function getTarget(): Notifiable + { + return $this->target; + } + + /** + * @return Notifiable + */ + public function getCauser(): Notifiable + { + return $this->causer; + } + + /** + * @return int + */ + public function getStatus(): int + { + return $this->status; + } + + +} diff --git a/app/Classes/Modules/Notifications/Processors/CreateNotificationProcessor.php b/app/Classes/Modules/Notifications/Processors/CreateNotificationProcessor.php new file mode 100644 index 00000000..d6b077f8 --- /dev/null +++ b/app/Classes/Modules/Notifications/Processors/CreateNotificationProcessor.php @@ -0,0 +1,27 @@ +createsNotification = $createsNotification; + } + + public function execute(NotificationObject $object) + { + $notification = $this->createsNotification->execute($object); + return $notification; + } +} diff --git a/app/Classes/Modules/Notifications/Services/CreatesNotification.php b/app/Classes/Modules/Notifications/Services/CreatesNotification.php new file mode 100644 index 00000000..4f5ca5fd --- /dev/null +++ b/app/Classes/Modules/Notifications/Services/CreatesNotification.php @@ -0,0 +1,30 @@ +title = $object->getTitle(); + $model->description = $object->getDescription(); + $model->status = $object->getStatus(); + $model->subject_type = get_class($object->getSubject()); + $model->subject_id = $object->getSubject()->id; + $model->target_type = get_class($object->getTarget()); + $model->target_id = $object->getTarget()->id; + $model->causer_type = get_class($object->getCauser()); + $model->causer_id = $object->getCauser()->id; + $model->save(); + + return $model; + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Orders/ControllersLogic/CreateOrderRemarkLogic.php b/app/Classes/Modules/Orders/ControllersLogic/CreateOrderRemarkLogic.php deleted file mode 100644 index e134bcc7..00000000 --- a/app/Classes/Modules/Orders/ControllersLogic/CreateOrderRemarkLogic.php +++ /dev/null @@ -1,60 +0,0 @@ - 'Created Order', - 'message' => 'You have successfully created a new Order' - ]; - } - - /** @var FetchesOrder */ - private $fetchesOrder; - - /** @var CreateRemarkProcessor */ - private $createRemarkProcessor; - - /** - * CreateOrderRemarkLogic constructor. - * @param FetchesOrder $fetchesOrder - * @param CreateRemarkProcessor $createRemarkProcessor - */ - public function __construct(FetchesOrder $fetchesOrder, CreateRemarkProcessor $createRemarkProcessor) - { - $this->fetchesOrder = $fetchesOrder; - $this->createRemarkProcessor = $createRemarkProcessor; - } - - /** - * @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 - { - $order = $this->fetchesOrder->execute(['id' => $request->route('id')]); - - $object = new RemarkObject($request->input('content'), auth()->user()->id); - - $this->createRemarkProcessor->execute($order, $object); - - return $this->resourceResponse(new OrderResource($order)); - - } -} diff --git a/app/Classes/Modules/PackingLists/ControllersLogic/Containers/CreateContainerRemarkLogic.php b/app/Classes/Modules/PackingLists/ControllersLogic/Containers/CreateContainerRemarkLogic.php index bb4b2a06..f35b828e 100644 --- a/app/Classes/Modules/PackingLists/ControllersLogic/Containers/CreateContainerRemarkLogic.php +++ b/app/Classes/Modules/PackingLists/ControllersLogic/Containers/CreateContainerRemarkLogic.php @@ -20,8 +20,8 @@ class CreateContainerRemarkLogic extends AbstractControllerLogic */ protected function notification():array { return [ - 'title' => 'Created Container', - 'message' => 'You have successfully created a new Container' + 'title' => 'Created Container Remark', + 'message' => 'You have successfully created a new Container Remark' ]; } diff --git a/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php index a5bf50b0..46d822c5 100644 --- a/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php +++ b/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php @@ -4,18 +4,16 @@ namespace App\Classes\Modules\Remarks\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Remarks\Services\CreatesRemark; -use App\Classes\Modules\Remarks\Standards\Rules\CanCreateRemark; use App\Classes\Modules\Remarks\DataTransferObjects\RemarkObject; -use App\Classes\Modules\Accounts\Services\FetchesUser; -use App\Http\Resources\RemarkResource; -use ErrorException; +use App\Classes\Modules\Remarks\Processors\CreateRemarkProcessor; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Str; +use App\Classes\Exceptions\MalformedRequestException; +use App\Http\Resources\RemarkResource; class CreateRemarkLogic extends AbstractControllerLogic { - /** * @return array */ @@ -26,25 +24,16 @@ class CreateRemarkLogic extends AbstractControllerLogic ]; } - /** @var CanCreateRemark */ - private $canCreateRemark; - - /** @var CreatesRemark */ - private $createsRemark; - - /** @var FetchesUser */ - private $fetchesUser; + /** @var CreateRemarkProcessor */ + private $createRemarkProcessor; /** * CreateRemarkLogic constructor. - * @param CanCreateRemark $canCreateRemark - * @param CreatesRemark $createsRemark + * @param CreateRemarkProcessor $createRemarkProcessor */ - public function __construct(CanCreateRemark $canCreateRemark, CreatesRemark $createsRemark, FetchesUser $fetchesUser) + public function __construct(CreateRemarkProcessor $createRemarkProcessor) { - $this->canCreateRemark = $canCreateRemark; - $this->createsRemark = $createsRemark; - $this->fetchesUser = $fetchesUser; + $this->createRemarkProcessor = $createRemarkProcessor; } /** @@ -56,15 +45,18 @@ class CreateRemarkLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { + $classs = '\\App\\Models\\' . Str::studly($request->input('model_type')); - $object = new RemarkObject($request->input('content'), $request->input('commenter_id')); + if (!class_exists($classs)) { + throw new MalformedRequestException('Unable to process this entity'); + } + + $remarkOwner = $classs::find($request->route('id')); - $this->canCreateRemark->passes($object); + $remarkObject = new RemarkObject($request->input('content'), auth()->user()->id); - $query = $this->createsRemark->execute($this->fetchesUser->execute(['id' => $request->input('commenter_id')]), $object); - - return $this->resourceResponse(new RemarkResource($query)); + $remmark = $this->createRemarkProcessor->execute($remarkOwner, $remarkObject); + return $this->resourceResponse(new RemarkResource($remmark)); } - } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ApprovePaymentTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ApprovePaymentTransactionLogic.php new file mode 100644 index 00000000..5db49ddf --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ApprovePaymentTransactionLogic.php @@ -0,0 +1,81 @@ +fetchesTransaction = $fetchesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->approvesDocument = $approvesDocument; + $this->rejectsDocument = $rejectsDocument; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Payment Status', + 'message' => 'You have successfully updated the payment status' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** @var ApprovesDocument */ + private $approvesDocument; + + /** @var RejectsDocument */ + private $rejectsDocument; + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + + $status = $request->route('status'); + + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('transaction_id')]); + + $status === 'approve' ? $this->approvesDocument->execute($transaction->documents()->first()) : $this->rejectsDocument->execute($transaction->documents()->first()); + + $this->updatesTransactionStatus->execute($transaction, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED); + + // $this->createInvoiceTransactionProcessor->execute($transaction->booking); + return $this->response([]); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentTransactionLogic.php new file mode 100644 index 00000000..bd99d86d --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentTransactionLogic.php @@ -0,0 +1,121 @@ + 'Create Payment Transactions', + 'message' => 'You have successfully created currency supplier transactions' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var FetchesSegmentConstant */ + private $fetchesSegmentConstant; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var CreatesPaymentTransaction */ + private $createsPaymentTransaction; + + /** @var CreatesBillplzBill */ + private $createsBillplzBill; + + /** @var CreatesTransactionDetail */ + private $createsTransactionDetail; + + public function __construct( + FetchesTransaction $fetchesTransaction, + GeneratesTransactionBillNumber $generatesTransactionBillNumber, + CreatesPaymentTransaction $createsPaymentTransaction, + CreatesTransactionDetail $createsTransactionDetail, + CreatesBillplzBill $createsBillplzBill + ) + { + $this->fetchesTransaction = $fetchesTransaction; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsPaymentTransaction = $createsPaymentTransaction; + $this->createsTransactionDetail = $createsTransactionDetail; + $this->createsBillplzBill = $createsBillplzBill; + } + + public function logic(Request $request) : JsonResponse + { + $invoice_transaction = $this->fetchesTransaction->execute(['id' => $request->input('transaction_id')]); + $amount = $request->input('amount'); + $company_module = $invoice_transaction->owner()->first()->owner()->first()->companyModule()->first(); + + $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); + $payment_reference = null; + if ($request->input('payment_method') == 5) { + $payment_method = PaymentMethodType::PAYMENT_GATEWAY; + $billPlzBill = $this->createsBillplzBill->execute( + $company_module->name, + $company_module->employees()->first()->email, + 'This payment is credit topup for company ref. ' . $company_module->reference, $amount, $billNumber, + $request->input('bank_code'), true + ); + + $payment_reference = $billPlzBill->id; + } + else { + $payment_method = PaymentMethodType::CASH; + } + + $object = new TransactionObject( + $billNumber, + TransactionType::PAYMENT, + $company_module->id, + 1, + 1, + $payment_method, + $request->input('amount'), + $request->input('amount'), + 1, + 1, + 0, + 0, + 0, + null, + ApprovalStatus::PENDING_SUBMISSION, + null, + $payment_reference + ); + + $payment_transaction = $this->createsPaymentTransaction->execute($invoice_transaction, $object); + + return $this->response([]); + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateShippingInvoiceTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateShippingInvoiceTransactionLogic.php index b6edcc5f..f988d73c 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateShippingInvoiceTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateShippingInvoiceTransactionLogic.php @@ -8,29 +8,24 @@ use App\Classes\Modules\PackingLists\Services\FetchesPackingList; use App\Classes\Modules\SegmentConstants\Services\FetchesSegmentConstant; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\Modules\Transactions\Services\CreatesTransaction; +use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail; +use App\Classes\Modules\Documents\Services\CreatesDocument; +use App\Classes\Modules\Documents\Services\CreatesFiles; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; +use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject; +use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; + use App\Classes\ValueObjects\Constants\OrderRoleTypes; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\ValueObjects\Constants\DocumentType; -// use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; -// use App\Classes\Modules\Transactions\Services\FetchesTransaction; -// use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -// use App\Classes\Modules\Documents\Services\CreatesDocument; -// use App\Classes\Modules\Documents\Services\CreatesFiles; -// use App\Classes\ValueObjects\Constants\DocumentType; -// use App\Models\Document; -// use App\Models\Transaction; -// use Barryvdh\DomPDF\PDF; -// use Carbon\Carbon; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; - -// use Meneses\LaravelLaravelMpdf\Facades\LaravelLaravelMpdf; -// use Meneses\LaravelMpdf\Facades\LaravelMpdf; +use Meneses\LaravelMpdf\Facades\LaravelMpdf; class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic { @@ -58,36 +53,23 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic /** @var CreatesTransaction */ private $createsTransaction; - // /** @var FetchesTransaction */ - // private $fetchesTransaction; - // /** @var UpdatesTransactionStatus */ - // private $updatesTransactionStatus; - // /** @var CreatesDocument */ - // private $createsDocument; - // /** @var CreatesFiles */ - // private $createsFile; - // /** @var PDF */ - // private $pdf; + /** @var CreatesTransactionDetail */ + private $createsTransactionDetail; - /** - * CreateSupplierTransactionLogic constructor. - * @param FetchesPackingList $fetchesPackingList - * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber - * @param CreatesTransaction $createsTransaction - * @param FetchesTransaction $fetchesTransaction - * @param UpdatesTransactionStatus $updatesTransactionStatus - * @param PDF $pdf - */ + /** @var CreatesDocument */ + private $createsDocument; + + /** @var CreatesFiles */ + private $createsFile; + public function __construct( FetchesPackingList $fetchesPackingList, FetchesSegmentConstant $fetchesSegmentConstant, GeneratesTransactionBillNumber $generatesTransactionBillNumber, - CreatesTransaction $createsTransaction - - // UpdatesTransactionStatus $updatesTransactionStatus, - // CreatesDocument $createsDocument, - // CreatesFiles $createsFile, - // PDF $pdf + CreatesTransaction $createsTransaction, + CreatesTransactionDetail $createsTransactionDetail, + CreatesDocument $createsDocument, + CreatesFiles $createsFile ) { @@ -95,11 +77,9 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic $this->fetchesSegmentConstant = $fetchesSegmentConstant; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createsTransaction = $createsTransaction; - - // $this->updatesTransactionStatus = $updatesTransactionStatus; - // $this->createsDocument = $createsDocument; - // $this->createsFile = $createsFile; - // $this->pdf = $pdf; + $this->createsTransactionDetail = $createsTransactionDetail; + $this->createsDocument = $createsDocument; + $this->createsFile = $createsFile; } public function logic(Request $request) : JsonResponse @@ -185,8 +165,31 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic ApprovalStatus::PENDING_SUBMISSION ); - $transactions = $this->createsTransaction->execute($packing_list, $object); + $invoice_transaction = $this->createsTransaction->execute($packing_list, $object); + $object_detail = new TransactionDetailObject( + $invoice_transaction->bill_no, + $invoice_transaction->bill_no, + 1, + $invoice_transaction->amount, + $invoice_transaction->amount + ); + $transaction_detail = $this->createsTransactionDetail->execute($invoice_transaction, $object_detail); + + $transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice_transaction]); + + $document_object = new DocumentObject( + DocumentType::SHIPPING_INVOICE, + [chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))], + '', + ApprovalStatus::COMPLETED, + 'shipping_invoice' + ); + /** @var Document $document */ + $document = $this->createsDocument->execute($invoice_transaction, $document_object); + $this->createsFile->execute($document, $document_object); + + // dd('yess'); return $this->response([]); } } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UploadPaymentVerificationDocumentLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UploadPaymentVerificationDocumentLogic.php new file mode 100644 index 00000000..3ea3b667 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/UploadPaymentVerificationDocumentLogic.php @@ -0,0 +1,87 @@ + 'Payment Verify Document', + 'message' => 'You have successfully submitted your payment verify document' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var CreatesDocument */ + private $createsDocument; + + /** @var CreatesFiles */ + private $createsFile; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** + * CreatePaymentVerificationDocumentLogic constructor. + * @param FetchesTransaction $fetchesTransaction + * @param CreatesDocument $createsDocument + * @param CreatesFiles $createsFile + * @param UpdatesTransactionStatus $updatesTransactionStatus + */ + public function __construct(FetchesTransaction $fetchesTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesTransactionStatus $updatesTransactionStatus) + { + $this->fetchesTransaction = $fetchesTransaction; + $this->createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('transaction_id')]); + + $object = new DocumentObject( + DocumentType::CUSTOMER_PAYMENT_PROOF, + $request->input('files'), + '', + ApprovalStatus::PENDING_VERIFICATION, + 'payments' + ); + + /** @var Document $document */ + $document = $this->createsDocument->execute($transaction, $object); + + $this->createsFile->execute($document, $object); + + $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION); + + return $this->response([]); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/DataTransferObjects/TransactionObject.php b/app/Classes/Modules/Transactions/DataTransferObjects/TransactionObject.php index b4153751..5e943e29 100644 --- a/app/Classes/Modules/Transactions/DataTransferObjects/TransactionObject.php +++ b/app/Classes/Modules/Transactions/DataTransferObjects/TransactionObject.php @@ -57,6 +57,9 @@ class TransactionObject implements DataTransferObject /** @var array|null */ private $details; + /** @var string */ + private $paymentReference; + /** * TransactionObject constructor. * @param string $billNo @@ -92,7 +95,8 @@ class TransactionObject implements DataTransferObject float $serviceCharge, ?Carbon $expiresOn, ?int $status = ApprovalStatus::PENDING_SUBMISSION, - ?array $details = [] + ?array $details = [], + ?string $paymentReference = null ) { $this->billNo = $billNo; @@ -111,6 +115,7 @@ class TransactionObject implements DataTransferObject $this->expiresOn = $expiresOn; $this->status = $status; $this->details = $details; + $this->paymentReference = $paymentReference; } /** @@ -243,7 +248,11 @@ class TransactionObject implements DataTransferObject }, $this->details); } - - - + /** + * @return string|null + */ + public function getPaymentReference(): ?string + { + return $this->paymentReference; + } } \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/Services/CreatesPaymentTransaction.php b/app/Classes/Modules/Transactions/Services/CreatesPaymentTransaction.php new file mode 100644 index 00000000..54afd914 --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/CreatesPaymentTransaction.php @@ -0,0 +1,37 @@ +bill_no = $object->getBillNo(); + $model->type = $object->getTransactionType(); + $model->issuer = $object->getIssuer(); + $model->receiver = $object->getReceiver(); + $model->recipient_bank_account_id = $object->getRecipientBankAccountId(); + $model->payment_method = $object->getPaymentMethod(); + $model->amount = $object->getAmount(); + $model->original_amount = $object->getOriginalAmount(); + $model->currency_id = $object->getCurrencyId(); + $model->original_currency_id = $object->getOriginalCurrencyId(); + $model->currency_rate = $object->getCurrencyRate(); + $model->tax = $object->getTax(); + $model->service_charge = $object->getServiceCharge(); + $model->expires_on = $object->getExpiresOn(); + $model->status = $object->getStatus(); + + return $this->handler($transaction->transactions(), $model); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/Services/CreatesTransactionDetail.php b/app/Classes/Modules/Transactions/Services/CreatesTransactionDetail.php index 0e852ddf..bdb0f387 100644 --- a/app/Classes/Modules/Transactions/Services/CreatesTransactionDetail.php +++ b/app/Classes/Modules/Transactions/Services/CreatesTransactionDetail.php @@ -18,8 +18,8 @@ class CreatesTransactionDetail extends AbstractUpdateRelationshipRecord */ public function execute(Transaction $transaction, TransactionDetailObject $object) { $model = new TransactionDetail(); - $model->product_code = $object->getCode(); - $model->product_name = $object->getName(); + $model->reference = $object->getReference(); + $model->name = $object->getName(); $model->quantity = $object->getQuantity(); $model->price = $object->getPrice(); $model->amount = $object->getAmount(); diff --git a/app/Classes/ValueObjects/Constants/DocumentType.php b/app/Classes/ValueObjects/Constants/DocumentType.php index 2b053163..75db231a 100644 --- a/app/Classes/ValueObjects/Constants/DocumentType.php +++ b/app/Classes/ValueObjects/Constants/DocumentType.php @@ -21,4 +21,8 @@ final class DocumentType { public const DELIVER_ORDER = 'DELIVER_ORDER'; public const INVOICE = 'INVOICE'; public const SUPPLIER_DELIVER_ORDER = 'SUPPLIER_DELIVER_ORDER'; + + + public const SHIPPING_INVOICE = 'SHIPPING_INVOICE'; + } diff --git a/app/Classes/ValueObjects/Constants/NotificationType.php b/app/Classes/ValueObjects/Constants/NotificationType.php new file mode 100644 index 00000000..0c9ec5a4 --- /dev/null +++ b/app/Classes/ValueObjects/Constants/NotificationType.php @@ -0,0 +1,11 @@ + 'Unknown Action', - 'message' => 'unknown message..' + public const NEW_ARRIVED_PARCEL = [ + 'title' => 'New Arrived Parcel', + 'message' => 'you have received new parcel for your order #-' ]; + public const UNDEFINED = [ + 'title' => 'UNDEFINED TITLE', + 'message' => 'undefined message' + ]; } \ No newline at end of file diff --git a/app/Classes/ValueObjects/Constants/TransactionType.php b/app/Classes/ValueObjects/Constants/TransactionType.php index d61589fa..07277b64 100644 --- a/app/Classes/ValueObjects/Constants/TransactionType.php +++ b/app/Classes/ValueObjects/Constants/TransactionType.php @@ -6,9 +6,10 @@ final class TransactionType { public const SHIPPING_INVOICE = 1; + public const PAYMENT = 2; + // public const PAYMENT_ATTEMPT = 0; - // public const PAYMENT = 1; // public const INVOICE = 2; diff --git a/app/Http/Controllers/Billplz/CallbackBillplzController.php b/app/Http/Controllers/Billplz/CallbackBillplzController.php new file mode 100644 index 00000000..9ee281e6 --- /dev/null +++ b/app/Http/Controllers/Billplz/CallbackBillplzController.php @@ -0,0 +1,22 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Billplz/CreateBillplzBillController.php b/app/Http/Controllers/Billplz/CreateBillplzBillController.php new file mode 100644 index 00000000..c10bad79 --- /dev/null +++ b/app/Http/Controllers/Billplz/CreateBillplzBillController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Companies/ListCompanyModulesController.php b/app/Http/Controllers/Companies/ListCompanyModulesController.php new file mode 100644 index 00000000..68bca75e --- /dev/null +++ b/app/Http/Controllers/Companies/ListCompanyModulesController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Orders/CreateOrderRemarkController.php b/app/Http/Controllers/Orders/CreateOrderRemarkController.php deleted file mode 100644 index 3464566a..00000000 --- a/app/Http/Controllers/Orders/CreateOrderRemarkController.php +++ /dev/null @@ -1,14 +0,0 @@ -execute($request); - } -} \ No newline at end of file diff --git a/app/Http/Controllers/Orders/DownloadOrderQrPdfController.php b/app/Http/Controllers/Orders/DownloadOrderQrPdfController.php index b87012ec..3218be52 100644 --- a/app/Http/Controllers/Orders/DownloadOrderQrPdfController.php +++ b/app/Http/Controllers/Orders/DownloadOrderQrPdfController.php @@ -24,9 +24,9 @@ class DownloadOrderQrPdfController $warehousePrefix = ''; $deliveryPrefix = ''; $customerMarking = ''; + $remark = $warehouse->remarks()->first()->content; if($warehouse->reference === WarehouseReferences::VT_GUANG_ZHOU || $warehouse->reference === WarehouseReferences::VT_YIWU) { - $remark = '周一 至 周六 , 早上八点到下午六点'; $customerMarking = $order->companyModule->connections()->first()->invitee_reference.'/'; if(strtolower($deliveryAddress->state->name) === 'sabah' || strtolower($deliveryAddress->state->name) === 'labuan') { $deliveryPrefix = 'SB/'; @@ -38,12 +38,10 @@ class DownloadOrderQrPdfController } if($warehouse->reference === WarehouseReferences::YD_YIWU){ - $remark = '周一 至 周六 , 早上九点到下午六点'; $warehousePrefix = 'YW/'; } if($warehouse->reference === WarehouseReferences::YD_GUANG_ZHOU){ - $remark = '周日 至 周五 , 早上八点到下午六点'; $warehousePrefix = 'YD/'; if(strtolower($deliveryAddress->state->name) === 'sabah' || strtolower($deliveryAddress->state->name) === 'labuan') { diff --git a/app/Http/Controllers/Transactions/ApprovePaymentTransactionController.php b/app/Http/Controllers/Transactions/ApprovePaymentTransactionController.php new file mode 100644 index 00000000..cbb00610 --- /dev/null +++ b/app/Http/Controllers/Transactions/ApprovePaymentTransactionController.php @@ -0,0 +1,15 @@ +execute($request); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Transactions/CreatePaymentTransactionController.php b/app/Http/Controllers/Transactions/CreatePaymentTransactionController.php new file mode 100644 index 00000000..7636b16e --- /dev/null +++ b/app/Http/Controllers/Transactions/CreatePaymentTransactionController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/UploadPaymentVerificationDocumentController.php b/app/Http/Controllers/Transactions/UploadPaymentVerificationDocumentController.php new file mode 100644 index 00000000..6c32a34d --- /dev/null +++ b/app/Http/Controllers/Transactions/UploadPaymentVerificationDocumentController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Resources/CompanyModuleResource.php b/app/Http/Resources/CompanyModuleResource.php index e1f253be..7af3ae8d 100644 --- a/app/Http/Resources/CompanyModuleResource.php +++ b/app/Http/Resources/CompanyModuleResource.php @@ -39,6 +39,7 @@ class CompanyModuleResource extends JsonResource 'reference' => $this->reference, 'address' => new AddressResource($defaultAddress), 'company' => new CompanyResource($this->whenLoaded('company')), + 'remarks' => RemarkResource::collection($this->remarks), 'marking' => $marking ]; diff --git a/app/Http/Resources/CountryResource.php b/app/Http/Resources/CountryResource.php new file mode 100644 index 00000000..f15c41f8 --- /dev/null +++ b/app/Http/Resources/CountryResource.php @@ -0,0 +1,24 @@ + $this->id, + 'name' => $this->name, + 'short_code' => $this->short_code, + 'phone_code' => $this->phone_code, + ]; + } +} diff --git a/app/Http/Resources/PackingListResource.php b/app/Http/Resources/PackingListResource.php index 82065b18..5256e3de 100644 --- a/app/Http/Resources/PackingListResource.php +++ b/app/Http/Resources/PackingListResource.php @@ -3,6 +3,7 @@ namespace App\Http\Resources; use App\Classes\ValueObjects\Constants\PackingListType; +use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\RoleTypes; use App\Models\Order; use App\Models\PackingList; @@ -32,7 +33,8 @@ class PackingListResource extends JsonResource 'packages' => PackageResource::collection($packages), $this->mergeWhen($this->owner instanceof Order, [ 'order' => New OrderResource($this->owner) - ]) + ]), + 'shippng_transaction' => new TransactionResource($this->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->first()), ]; } } diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index ef652fd7..05c35038 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -18,7 +18,7 @@ class TransactionResource extends JsonResource return [ 'id' => $this->id, - 'booking' => new BookingResource($this->booking), + // 'booking' => new BookingResource($this->booking), 'type' => (int) $this->type, 'bill_no' => $this->bill_no, 'amount' => (double) $this->amount, diff --git a/app/Models/AbstractModel.php b/app/Models/AbstractModel.php index 7a7c9c06..f459750f 100644 --- a/app/Models/AbstractModel.php +++ b/app/Models/AbstractModel.php @@ -3,11 +3,39 @@ namespace App\Models; +use App\Classes\General\Interfaces\Notifiable; use Illuminate\Database\Eloquent\Model; use Spatie\Activitylog\Traits\LogsActivity; +use Illuminate\Database\Eloquent\Relations\MorphTo; -class AbstractModel extends Model +class AbstractModel extends Model implements Notifiable { use LogsActivity; protected static $logFillable = true; + + /** + * @return MorphTo + */ + public function subject(): MorphTo + { + return $this->MorphTo('subject'); + } + + /** + * @return MorphTo + */ + public function target(): MorphTo + { + return $this->MorphTo('target'); + } + + /** + * @return MorphTo + */ + public function causer(): MorphTo + { + return $this->MorphTo('causer'); + } + + } \ No newline at end of file diff --git a/app/Models/CompanyModule.php b/app/Models/CompanyModule.php index 180d8286..6a6d53ed 100644 --- a/app/Models/CompanyModule.php +++ b/app/Models/CompanyModule.php @@ -23,6 +23,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use PhpParser\Node\Expr\AssignOp\Mod; use Staudenmeir\EloquentHasManyDeep\HasManyDeep; use Staudenmeir\EloquentHasManyDeep\HasRelationships; +use App\Classes\General\Interfaces\Remarkable; /** * Class CompanyModule @@ -32,7 +33,7 @@ use Staudenmeir\EloquentHasManyDeep\HasRelationships; * @property integer type * @property integer status */ -class CompanyModule extends AbstractModel implements Addressable, Documentable, Contactable, ContainerOwner, Packable +class CompanyModule extends AbstractModel implements Addressable, Documentable, Contactable, ContainerOwner, Packable, Remarkable { use HasRelationships; use SoftDeletes; @@ -139,7 +140,7 @@ class CompanyModule extends AbstractModel implements Addressable, Documentable, */ public function banks(): HasMany { - return $this->HasMany(Bank::class, 'company_id'); + return $this->HasMany(BankAccount::class, 'company_id'); } /** @@ -177,6 +178,14 @@ class CompanyModule extends AbstractModel implements Addressable, Documentable, return $query->where('type', '=', BusinessType::WAREHOUSE); } + /** + * @return MorphMany + */ + public function remarks(): morphMany + { + return $this->morphMany(Remark::class, 'owner'); + } + } diff --git a/app/Models/Notification.php b/app/Models/Notification.php new file mode 100644 index 00000000..06bd6024 --- /dev/null +++ b/app/Models/Notification.php @@ -0,0 +1,18 @@ +BelongsTo(Package::class, 'package_id', 'id'); + } +} diff --git a/app/Models/Order.php b/app/Models/Order.php index 5aabfd44..5011fd36 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -6,6 +6,7 @@ use App\Classes\General\Interfaces\Addressable; use App\Classes\General\Interfaces\Contactable; use App\Classes\General\Interfaces\Packable; use App\Classes\General\Interfaces\Remarkable; +use App\Classes\General\Interfaces\Notifiable; use App\Classes\ValueObjects\Constants\PackingListType; use App\Classes\ValueObjects\Constants\RoleTypes; use App\Classes\ValueObjects\Constants\ApprovalStatus; @@ -16,7 +17,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\MorphMany; -class Order extends AbstractModel implements Addressable, Packable, Remarkable +class Order extends AbstractModel implements Addressable, Packable, Remarkable, Notifiable { use SoftDeletes; @@ -153,8 +154,8 @@ class Order extends AbstractModel implements Addressable, Packable, Remarkable /** * @return morphMany */ - public function transactions(): morphMany - { - return $this->morphMany(Transaction::class, 'owner'); - } + // public function transactions(): morphMany + // { + // return $this->morphMany(Transaction::class, 'owner'); + // } } diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 232964d9..d2432941 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Classes\General\Interfaces\Documentable; +use App\Classes\General\Interfaces\Transactionable; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; use Carbon\Carbon; @@ -10,9 +11,9 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\MorphMany; +use Illuminate\Database\Eloquent\Relations\MorphTo; - -class Transaction extends AbstractModel implements Documentable +class Transaction extends AbstractModel implements Documentable, Transactionable { protected $table = 'transactions'; @@ -29,6 +30,14 @@ class Transaction extends AbstractModel implements Documentable return $this->morphMany(Order::class, 'owner'); } + /** + * @return MorphMany + */ + public function transactions(): MorphMany + { + return $this->MorphMany(Transaction::class, 'owner'); + } + /** * @return MorphMany */ diff --git a/app/Models/User.php b/app/Models/User.php index dccda6d2..daabe09d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\MorphMany; use Spatie\Permission\Traits\HasRoles; +use Illuminate\Database\Eloquent\SoftDeletes; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Notifications\Notifiable; @@ -24,8 +25,9 @@ class User extends AbstractModel implements AuthorizableContract, CanResetPasswordContract { - use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail; + use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes; + protected $dates = ['deleted_at']; /** * Get the identifier that will be stored in the subject claim of the JWT. diff --git a/config/billplz.php b/config/billplz.php new file mode 100644 index 00000000..904cea31 --- /dev/null +++ b/config/billplz.php @@ -0,0 +1,13 @@ + env('BILLPLZ_BASE_URL', 'https://www.billplz.com'), + 'api_key' => env('BILLPLZ_API_KEY', '0fa4c710-761b-4a7a-a501-c2c2d02643d5'), + 'x_signature_key' => env('BILLPLZ_X_SIGNATURE_KEY', 'S-pbNVthVRsvnPfZlgLwqqOg'), + 'collection_id' => env('BILLPLZ_COLLECTION_ID', 'hev2wdjy'), + 'wallet_collection_id' => env('BILLPLZ_WALLET_COLLECTION_ID', 'hev2wdjy'), + 'redirect_url' => env('BILLPLZ_REDIRECT_URL', 'localhost'), + 'callback_url' => env('BILLPLZ_CALLBACK_URL', 'localhost'), + 'maybank' => 'MB2U0227', + 'cimb' => 'BCBB0235' +]; \ No newline at end of file diff --git a/database/migrations/2022_02_18_120837_create_notifications_table.php b/database/migrations/2022_02_18_120837_create_notifications_table.php new file mode 100644 index 00000000..d14cdc89 --- /dev/null +++ b/database/migrations/2022_02_18_120837_create_notifications_table.php @@ -0,0 +1,40 @@ +id(); + $table->string('title'); + $table->text('description'); + $table->morphs('subject'); + $table->morphs('target'); + $table->morphs('causer'); + $table->integer('status')->default(ApprovalStatus::APPROVED); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('notifications'); + } +} diff --git a/database/migrations/2022_03_14_133555_add_deleted_at_to_users_table.php b/database/migrations/2022_03_14_133555_add_deleted_at_to_users_table.php new file mode 100644 index 00000000..13fa1389 --- /dev/null +++ b/database/migrations/2022_03_14_133555_add_deleted_at_to_users_table.php @@ -0,0 +1,32 @@ +softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + // + }); + } +} diff --git a/resources/assets/vue/components/companies/sections/CustomerProfileDetailsSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerProfileDetailsSectionComponent.vue new file mode 100644 index 00000000..f61275e2 --- /dev/null +++ b/resources/assets/vue/components/companies/sections/CustomerProfileDetailsSectionComponent.vue @@ -0,0 +1,180 @@ + + \ No newline at end of file diff --git a/resources/assets/vue/components/companies/sections/WarehouseDetailsSectionComponent.vue b/resources/assets/vue/components/companies/sections/WarehouseDetailsSectionComponent.vue new file mode 100644 index 00000000..7428e1b3 --- /dev/null +++ b/resources/assets/vue/components/companies/sections/WarehouseDetailsSectionComponent.vue @@ -0,0 +1,54 @@ + + \ No newline at end of file diff --git a/resources/assets/vue/components/companies/sections/WarehouseSectionComponent.vue b/resources/assets/vue/components/companies/sections/WarehouseSectionComponent.vue new file mode 100644 index 00000000..bf7f8363 --- /dev/null +++ b/resources/assets/vue/components/companies/sections/WarehouseSectionComponent.vue @@ -0,0 +1,112 @@ + + \ No newline at end of file diff --git a/resources/assets/vue/components/containers/elements/ContainerComponent.vue b/resources/assets/vue/components/containers/elements/ContainerComponent.vue index 8230862a..e60059a1 100644 --- a/resources/assets/vue/components/containers/elements/ContainerComponent.vue +++ b/resources/assets/vue/components/containers/elements/ContainerComponent.vue @@ -51,6 +51,9 @@

{{item.status === 3 ? 'Un-stuffed' : 'In Progress'}}

+ + +
diff --git a/resources/assets/vue/components/containers/elements/PackingListComponent.vue b/resources/assets/vue/components/containers/elements/PackingListComponent.vue index 078fd100..b5fdc4ab 100644 --- a/resources/assets/vue/components/containers/elements/PackingListComponent.vue +++ b/resources/assets/vue/components/containers/elements/PackingListComponent.vue @@ -26,17 +26,45 @@

{{item.transport ? item.transport.current_schedule.eta : 'n/a'}}

-
-
Release
-
Hold
+
+
+
+
Release
+
Hold
+
+
Unclaimed
+
+
+
+
+
+
Generate Invoice
+
+
+
+ + + +
+ +
+
-
Unclaimed
diff --git a/resources/assets/vue/components/orders/forms/DeleteOrderRemarkFormComponent.vue b/resources/assets/vue/components/general/forms/DeleteRemarkFormComponent.vue similarity index 94% rename from resources/assets/vue/components/orders/forms/DeleteOrderRemarkFormComponent.vue rename to resources/assets/vue/components/general/forms/DeleteRemarkFormComponent.vue index a23d077f..4e50d8c4 100644 --- a/resources/assets/vue/components/orders/forms/DeleteOrderRemarkFormComponent.vue +++ b/resources/assets/vue/components/general/forms/DeleteRemarkFormComponent.vue @@ -5,9 +5,9 @@
-
+

Are you Sure?

-
Are you sure you want to delete this comment?
+
Are you sure you want to delete this remark?
diff --git a/resources/assets/vue/components/general/forms/RemarkFormComponent.vue b/resources/assets/vue/components/general/forms/RemarkFormComponent.vue new file mode 100644 index 00000000..8b67c246 --- /dev/null +++ b/resources/assets/vue/components/general/forms/RemarkFormComponent.vue @@ -0,0 +1,74 @@ + + \ No newline at end of file diff --git a/resources/assets/vue/components/orders/forms/OrderRemarkFormComponent.vue b/resources/assets/vue/components/orders/forms/OrderRemarkFormComponent.vue deleted file mode 100644 index b57e0115..00000000 --- a/resources/assets/vue/components/orders/forms/OrderRemarkFormComponent.vue +++ /dev/null @@ -1,49 +0,0 @@ - - diff --git a/resources/assets/vue/components/orders/sections/OrderProfileSectionComponent.vue b/resources/assets/vue/components/orders/sections/OrderProfileSectionComponent.vue index 3f98964b..7156d78c 100644 --- a/resources/assets/vue/components/orders/sections/OrderProfileSectionComponent.vue +++ b/resources/assets/vue/components/orders/sections/OrderProfileSectionComponent.vue @@ -35,38 +35,24 @@
Remark:
-
-
-
Add a Remark
-
-
-
{{order.remarks[0].content}}
- - - - - - - - + +
-
-
-
- -
-
-
-
- Cancel -
-
-
-
+
+
Add a Remark
-
- +
+
{{ order.remarks[0].content }}
+ + + + + + + + +
@@ -465,7 +451,6 @@ section: 'orderProfileSection', isLoading: true, order: null, - isEditRemark: false, addComment: false, } }, diff --git a/resources/assets/vue/components/settings/elements/WarehouseChargesComponent.vue b/resources/assets/vue/components/settings/elements/WarehouseChargesComponent.vue index 59611841..0498cd55 100644 --- a/resources/assets/vue/components/settings/elements/WarehouseChargesComponent.vue +++ b/resources/assets/vue/components/settings/elements/WarehouseChargesComponent.vue @@ -7,7 +7,7 @@
-
+
Warehouse Name
@@ -19,7 +19,7 @@
-
+
Extra Charges
@@ -27,17 +27,43 @@
-
MYR 0.00
+
MYR 0.00
+ + +
+
+
+
+
Remarks
+
+
+
+
+
+ {{ data.remarks[0].content }} + + +
+
+
+ Add +
+ + + + + + +
+
-
Edit
- - - + + View Details
@@ -56,7 +82,7 @@ required: false }, section: { - default: '' + default: 'warhouseListSection' }, }, mixins: [modalFormHandler] diff --git a/resources/views/pages/customers/profile_details.blade.php b/resources/views/pages/customers/profile_details.blade.php new file mode 100644 index 00000000..10534ff7 --- /dev/null +++ b/resources/views/pages/customers/profile_details.blade.php @@ -0,0 +1,4 @@ +@extends('layouts.base_portal') +@section('inner_content') + +@endsection \ No newline at end of file diff --git a/resources/views/pages/delivery_list.blade.php b/resources/views/pages/delivery_list.blade.php new file mode 100644 index 00000000..284da34e --- /dev/null +++ b/resources/views/pages/delivery_list.blade.php @@ -0,0 +1,135 @@ +@extends('layouts.base_portal') +@section('inner_content') + +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Pending Arrangement
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Pending Delivery
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Delivered
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Marking
+
Quantity
+
CBM
+
Overweight CBM
+
Total CBM
+
status
+
Delivery Date
+
Action
+
+ + + +
+
+
+
+
+
Marking
+
Quantity
+
CBM
+
Overweight CBM
+
Total CBM
+
status
+
Delivery Date
+
+ + + +
+
+
+
+
+
Marking
+
Quantity
+
CBM
+
Overweight CBM
+
Total CBM
+
status
+
Delivery Date
+
+ + + +
+
+
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/pages/pdfs/shipping_invoice.blade.php b/resources/views/pages/pdfs/shipping_invoice.blade.php new file mode 100644 index 00000000..df4f2298 --- /dev/null +++ b/resources/views/pages/pdfs/shipping_invoice.blade.php @@ -0,0 +1,144 @@ +@extends('layouts.base_pdf') +@section('inner_content') +
+ +

+
{{ $invoice_transaction->bill_no }}
+
+ + + + + + + + + + + + +
+ + + CIEF WORLDWIDE SDN BHD + + + (1134596-M)
+ Malaysian Global Innovation & Creativity Center
+ Level 1 CWS, Block 3730, Persiaran APEC,
+ 63000 Cyberjaya, Malaysian.
+ Tel: 018-2909252 +
+
+ + Invoice + +
+ +
EI#: {{ $invoice_transaction->bill_no }}
+ + @php + $companyModule = $invoice_transaction->owner->owner->companyModule; + @endphp + +
Ref# {{ $invoice_transaction->owner->owner->reference }}
+ +
Date: {{ $invoice_transaction->created_at }}
+
 
+ +
+ + Bill To + +
+
+ {{ $companyModule->name }} +
+
+ @php + $addresses = $invoice_transaction->owner->owner->addresses()->where('status', '=', 2)->first(); + @endphp + {{ $addresses->street_one }} + {{ $addresses->street_two }} , + {{ $addresses->district()->first()->name }}, + {{ $addresses->postcode }} + {{ $addresses->state()->first()->name }}, + {{ $addresses->country()->first()->name }} +
+
+ @php + $contact = $companyModule->contacts()->first(); + @endphp + Phone: {{ $contact ? $contact->phone : '' }} +
+
+ +
+
+ + + + + + + + + + + + @foreach ($invoice_transaction->transactionDetails as $key => $transaction_detail) + + + + + + + + @endforeach + + + + + + + + + + + + + @if($invoice_transaction->tax > 0) + + + + + + @endif + + + + + + +
NoDescriptionQuantityUnit Price (RM)Total Amount
(RM)
{{ $key + 1 }}{{ $transaction_detail->name }}{{ $transaction_detail->quantity }} + {{ $transaction_detail->price }} + + {{ $transaction_detail->amount }} +
Subtotal + {{ number_format($invoice_transaction->amount, 2) }} +
Service Charges + {{ number_format($invoice_transaction->service_charge, 2) }} +
Tax{{ number_format($invoice_transaction->tax, 2) }}
Total + {{ number_format($invoice_transaction->amount, 2) }} +
+ + + + + + +
This is generated by computer. No signature required.Page {PAGENO} of {nbpg}
+
+@endsection diff --git a/resources/views/pages/settings.blade.php b/resources/views/pages/settings.blade.php index b6d89f9f..51718eae 100644 --- a/resources/views/pages/settings.blade.php +++ b/resources/views/pages/settings.blade.php @@ -152,13 +152,13 @@
-
+
-
Warehouse Charges
+
Warehouses
@@ -412,7 +412,7 @@
-
+
@@ -420,13 +420,13 @@
- Warehouse Charges + Warehouses
- + diff --git a/resources/views/pages/templates/warehouseDetails.blade.php b/resources/views/pages/templates/warehouseDetails.blade.php new file mode 100644 index 00000000..092dd826 --- /dev/null +++ b/resources/views/pages/templates/warehouseDetails.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+
+
+
+
+
Parcel in Warehouse
+
+
+ + + +
+
+ +
+
+ + + + +
+
+@endsection \ No newline at end of file diff --git a/resources/views/pages/warehouse.blade.php b/resources/views/pages/warehouse.blade.php new file mode 100644 index 00000000..ce290140 --- /dev/null +++ b/resources/views/pages/warehouse.blade.php @@ -0,0 +1,25 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+
+
+
+
+
Warehouse List
+
+
+
+
+ + + +
+
+
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/pages/warehouse_list.blade.php b/resources/views/pages/warehouse_list.blade.php index 58e96926..f9d8183b 100644 --- a/resources/views/pages/warehouse_list.blade.php +++ b/resources/views/pages/warehouse_list.blade.php @@ -2,11 +2,38 @@ @section('inner_content')
- +
+
+
Arrived Parcel
+
+
+
+
+
+
+
On Hold Parcel
+
+
+
+
Marking
+
Quantity
+
CBM
+
Overweight CBM
+
Total CBM
+
status
+
Delivery Date
+
+
+ + + +
@endsection \ No newline at end of file diff --git a/resources/views/partials/footer.blade.php b/resources/views/partials/footer.blade.php index e7020345..459488fb 100644 --- a/resources/views/partials/footer.blade.php +++ b/resources/views/partials/footer.blade.php @@ -3,7 +3,7 @@
- Copyright © 2021 CIEF IZYIM. All rights reserved. + Copyright © {{ date('Y'); }} CIEF IZYIM. All rights reserved.
diff --git a/resources/views/partials/menu.blade.php b/resources/views/partials/menu.blade.php index cf62bda3..4ec00248 100644 --- a/resources/views/partials/menu.blade.php +++ b/resources/views/partials/menu.blade.php @@ -60,7 +60,18 @@ style=" fill:#000000;">
+
+
+
+ +
+
@@ -74,6 +85,17 @@
Containers
+
+
+ +
+
+
Warehouse
+
+
'api', 'prefix' => 'v1', 'as' => 'api.'], function Route::get('/storage/{fileName}/fetch', 'Documents\RenderDocumentController@fileStorageServe')->where(['fileName' => '.*'])->name('storage.document.file'); + Route::post('online_payment/callback', 'Billplz\CallbackBillplzController@callback')->name('online_payment.callback'); + require __DIR__ . '/company.php'; require __DIR__ . '/document.php'; @@ -54,10 +56,7 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/announcement.php'; - Route::get('/report/customer/{marking}/{from?}/{to?}', 'Reports\MonthlyReportController@customerReport')->name('report.customer'); - Route::get('/report/sales/{from?}/{to?}', 'Reports\MonthlyReportController@salesReport')->name('report.sales'); - Route::get('/report/profit/{model}/{value}/{from?}/{to?}', 'Reports\MonthlyReportController@profitModelReport')->name('report.profit'); - Route::get('/report/service', 'Reports\MonthlyReportController@serviceReport')->name('report.service'); + require __DIR__ . '/report.php'; }); diff --git a/routes/company.php b/routes/company.php index 55c731b2..abcf7201 100644 --- a/routes/company.php +++ b/routes/company.php @@ -32,4 +32,5 @@ Route::group(['prefix' => 'company', 'as' => 'company.', 'namespace' => 'Compani Route::put('/{document_id}/approval/{status}', 'ApproveIdentificationDocumentController@approve')->where('status', 'approve|reject')->name('approval'); }); -}); \ No newline at end of file + Route::get('/module/list', 'ListCompanyModulesController@list')->name('module.list'); +}); diff --git a/routes/order.php b/routes/order.php index 2071cae4..79a67bd8 100644 --- a/routes/order.php +++ b/routes/order.php @@ -18,6 +18,4 @@ Route::group(['prefix' => 'order', 'as' => 'order.', 'namespace' => 'Orders'], f Route::put('/assign-remark/{id}', 'AssignOrderRemarkController@create')->name('assign.remark'); Route::get('/{id}/shipping-cost', 'ShippingCostController@calculate')->name('shipping.cost'); - - Route::post('/{id}/remark/create', 'CreateOrderRemarkController@create')->name('remark.create'); }); diff --git a/routes/remark.php b/routes/remark.php index 33756eee..91ae4676 100644 --- a/routes/remark.php +++ b/routes/remark.php @@ -5,7 +5,7 @@ use Illuminate\Support\Facades\Route; Route::group(['namespace' => 'Remarks', 'as' => 'remark.', 'prefix' => 'remark'], function () { Route::get('/{id}/show', 'FetchRemarkController@fetch')->name('show'); Route::get('/list', 'ListRemarksController@list')->name('list'); - Route::post('/create', 'CreateRemarkController@create')->name('create'); + Route::post('/{id}/create', 'CreateRemarkController@create')->name('create'); Route::put('/update/{id}', 'UpdateRemarkController@update')->name('update'); Route::delete('/delete/{id}', 'DeleteRemarkController@delete')->name('delete'); }); diff --git a/routes/report.php b/routes/report.php new file mode 100644 index 00000000..cd084cf6 --- /dev/null +++ b/routes/report.php @@ -0,0 +1,13 @@ + 'report', 'as' => 'report.', 'namespace' => 'Reports'], function () { + Route::get('/customer/{marking}/{from?}/{to?}', 'MonthlyReportController@customerReport')->name('customer'); + + Route::get('/sales/{from?}/{to?}', 'MonthlyReportController@salesReport')->name('sales'); + + Route::get('/profit/{model}/{value}/{from?}/{to?}', 'MonthlyReportController@profitModelReport')->name('profit'); + + Route::get('/service', 'MonthlyReportController@serviceReport')->name('service'); +}); diff --git a/routes/transaction.php b/routes/transaction.php index 7b4f7fd0..c3e1b2f2 100644 --- a/routes/transaction.php +++ b/routes/transaction.php @@ -7,8 +7,20 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => Route::get('/list', 'ListTransactionsController@list')->name('list'); // Route::delete('/suspend/{id}', 'SuspendTransactionController@suspend')->name('suspend'); + Route::post('/payment/create', 'CreatePaymentTransactionController@create')->name('payment.create'); + Route::post('/payment/upload-verification-document/{transaction_id}', 'UploadPaymentVerificationDocumentController@upload')->name('verification.create'); + Route::put('/payment/approve/{transaction_id}/{status}', 'ApprovePaymentTransactionController@approve')->where('status', 'approve|reject')->name('approval'); + + route::post('/shipping-invoice/create', 'CreateShippingInvoiceTransactionController@create')->name('supplier.create'); + // Route::group(['prefix' => '{id}/payment', 'as' => 'payment.'], function () { + // Route::post('quotation', 'FetchBookingPaymentQuotationController@fetch')->name('quotation'); + // Route::post('create', 'CreateBookingPaymentController@create')->name('create'); + // Route::post('{payment_id}/verification/create', 'CreatePaymentVerificationController@create')->name('verification.create'); + // Route::put('/{payment_id}/approval/{status}', 'ApprovePaymentVerificationController@approve')->where('status', 'approve|reject')->name('approval'); + // }); + // route::post('{id}/bill/verification', 'CreatePaymentProofDocumentController@verify')->name('bill.verification'); diff --git a/routes/web.php b/routes/web.php index 3b2c90de..bb35d287 100644 --- a/routes/web.php +++ b/routes/web.php @@ -80,6 +80,10 @@ Route::get('/warehouse-list', function () { return view('pages.warehouse_list'); })->name('warehouse.list'); +Route::get('/delivery-list', function () { + return view('pages.delivery_list'); +})->name('delivery.list'); + Route::get('/unclaimed-packinglist', function () { return view('pages.unclaimed_packinglist'); })->name('unclaimed-packinglist.list'); @@ -99,6 +103,12 @@ Route::get('/customer/{marking}', function ($marking) { return view('pages.customers.profile', ['id' => $id]); })->name('customer.profile'); +Route::get('/customer/{marking}/details', function ($marking) { + $connection = CompanyConnection::where('invitee_reference', $marking)->first(); + $id = $connection->invitee->company->id; + return view('pages.customers.profile_details', ['id' => $id]); +})->name('customer.profile.details'); + Route::get('/orders/refresh', function(){ FetchWarehouseReceiveListFromVTPortalJob::withChain([ @@ -194,6 +204,31 @@ Route::get('/yd', function (){ (App()->make(FetchOrderListsFromYdPortalProcessor::class))->execute(); }); +Route::get('/min_cbm', function (){ + $companies = CompanyModule::where('type', \App\Classes\ValueObjects\Constants\BusinessType::IMPORTER)->whereHas('orders', function ($query){ + return $query->whereHas('packingLists')->whereDoesntHave('packingLists', function($query){ + return $query->whereHas('packages', function($query){ + return $query->selectRaw('sum((width/100) * (height/100) * (length/100) * quantity) as cbm')->where('type', \App\Classes\ValueObjects\Constants\PackingListType::SHIPPING_PACKING_LIST)->where('status', '!=', 5)->having('cbm', '>', 0.3); + }); + }); + })->limit(1)->get(); + + $i = 0; + foreach ($companies as $company) { + $marking = $company->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference; + echo ''.$i++.'. '.$marking.'
'; + } +}); + +Route::get('/warehouse', function () { + return view('pages.warehouse'); +})->name('warehouse'); + +Route::get('/warehouse/{id}/show', function ($id) { + // $connection = CompanyConnection::where('invitee_reference', '2417MEN')->first(); + // $id = $connection->invitee->company->id; + return view('pages.templates.warehouseDetails', ['id' => $id]); +})->name('warehouse.show'); Route::get('/export/customer-latest-order-date/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@export'); Route::get('/export/packing-list/{id}', 'Exports\ExportContainerPackingListController@export')->name('container.packaging_list.export'); @@ -236,4 +271,6 @@ Route::get('/customers/active/{active_start}/{active_end}/{inactive_start?}/{ina echo $key + 1 .'. '.$marking.' '.$totalCbm.'

'; } -}); \ No newline at end of file +}); + +Route::get('/online_payment/redirect', 'Billplz\CallbackBillplzController@callback')->name('online_payment.redirect'); \ No newline at end of file