diff --git a/app/Classes/Exceptions/JobResourceNotFoundException.php b/app/Classes/Exceptions/JobResourceNotFoundException.php new file mode 100644 index 00000000..a8ef358e --- /dev/null +++ b/app/Classes/Exceptions/JobResourceNotFoundException.php @@ -0,0 +1,11 @@ +info(sprintf( + "Uncaught exception '%s' with message '%s' in %s:%d", + get_class($exception), + $exception->getMessage(), + $exception->getTrace()[0]['file'], + $exception->getTrace()[0]['line'] + )); + } + else{ + log::error($exception); + } + return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(), $exception->getCode() ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler(); diff --git a/app/Classes/General/Abstracts/AbstractRule.php b/app/Classes/General/Abstracts/AbstractRule.php index d2e0568b..5b424df0 100644 --- a/app/Classes/General/Abstracts/AbstractRule.php +++ b/app/Classes/General/Abstracts/AbstractRule.php @@ -10,7 +10,7 @@ use App\Classes\General\Interfaces\DataTransferObject; abstract class AbstractRule { - abstract protected function authorized(): bool; + abstract protected function authorized($object): bool; abstract protected function validators($object): bool; @@ -26,8 +26,8 @@ abstract class AbstractRule */ public function passes(?DataTransferObject $object = null): bool { try { - if(!$this->authorized()){ - throw new AccessForbiddenException('You don\'t have permission to preform this action'); + if(!$this->authorized($object)){ + throw new AccessForbiddenException('You don\'t have permission to perform this action'); } $this->validators($object); @@ -36,11 +36,11 @@ abstract class AbstractRule return true; } catch(AccessForbiddenException $exception){ - throw new AccessForbiddenException('You don\'t have permission to preform this action'); + throw new AccessForbiddenException('You don\'t have permission to perform this action'); } catch(\Exception $exception){ throw new RequestValidationException($exception->getMessage()); } } -} \ No newline at end of file +} diff --git a/app/Classes/General/Eloquent/AbstractFetchRecord.php b/app/Classes/General/Eloquent/AbstractFetchRecord.php index 248deee7..503fb369 100644 --- a/app/Classes/General/Eloquent/AbstractFetchRecord.php +++ b/app/Classes/General/Eloquent/AbstractFetchRecord.php @@ -4,9 +4,11 @@ namespace App\Classes\General\Eloquent; use App\Classes\Exceptions\ResourceNotFoundException; +use App\Classes\Exceptions\JobResourceNotFoundException; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Psy\Exception\ErrorException; +use Illuminate\Support\Facades\Log; abstract class AbstractFetchRecord extends AbstractGetRecord { @@ -27,12 +29,18 @@ abstract class AbstractFetchRecord extends AbstractGetRecord * @return Model * @throws ResourceNotFoundException */ - public function getResults(Builder $query): Model { + public function getResults(Builder $query, array $param = []): Model { if(!$query->exists()){ - throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); + $table = $query->getModel()->getTable(); + if($table ==='job_results'){ + throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided'); + } + else{ + throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); + } } return $query->first(); } -} \ No newline at end of file +} diff --git a/app/Classes/General/Eloquent/AbstractGetRecord.php b/app/Classes/General/Eloquent/AbstractGetRecord.php index f927d818..1a7eac3e 100644 --- a/app/Classes/General/Eloquent/AbstractGetRecord.php +++ b/app/Classes/General/Eloquent/AbstractGetRecord.php @@ -30,11 +30,25 @@ abstract class AbstractGetRecord return $this->filters->only(self::DECORATION_FILTERS); } + // /** + // * @param null|string $json + // * @return array + // */ + // public function deserializeFilters(?string $json): array { + // return $json !== null ? collect(json_decode($json))->toArray() : []; + // } + /** - * @param null|string $json + * @param null|string $param * @return array */ - public function deserializeFilters(?string $json): array { + public function deserializeFilters($param): array { + if(gettype($param) == "array"){ + $json = implode(',', $param); + } + else{ + $json = $param; + } return $json !== null ? collect(json_decode($json))->toArray() : []; } @@ -50,9 +64,9 @@ abstract class AbstractGetRecord * @param array $filters * @return mixed */ - public function handler(array $filters){ + public function handler(array $filters, array $params = []){ $this->filters = collect($filters); - return $this->getResults($this->applyFiltersToQuery()); + return $this->getResults($this->applyFiltersToQuery(), $params); } @@ -65,6 +79,6 @@ abstract class AbstractGetRecord * @param Builder $query * @return mixed */ - abstract function getResults(Builder $query); + abstract function getResults(Builder $query, array $params = []); -} \ No newline at end of file +} diff --git a/app/Classes/General/Eloquent/AbstractListRecord.php b/app/Classes/General/Eloquent/AbstractListRecord.php index 7b7d0df9..f898f108 100644 --- a/app/Classes/General/Eloquent/AbstractListRecord.php +++ b/app/Classes/General/Eloquent/AbstractListRecord.php @@ -17,11 +17,11 @@ abstract class AbstractListRecord extends AbstractGetRecord * @return mixed * @throws MalformedRequestException */ - public function execute(array $filters = []){ + public function execute(array $filters = [], array $param = []){ try{ - return $this->handler($filters); + return $this->handler($filters, $param); } catch (QueryException $exception){ log::error($exception); @@ -30,18 +30,24 @@ abstract class AbstractListRecord extends AbstractGetRecord } + /** * @param Builder $query * @return mixed */ - public function getResults(Builder $query) { + public function getResults(Builder $query, array $param = []) { $filters = $this->getDecorationFilters(); if($filters->has('order_by')){ $query = $query->orderBy($filters->get('order_by')->column, $filters->get('order_by')->DESC ? 'DESC': 'ASC'); } - return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get(); + if(!empty($param)){ + return $filters->has('per_page') ? $query->paginate($filters->get('per_page'), ['*'], 'page', $param['page']) : $query->get(); //page data from query parameters e.g ?page=1 + } + else{ + return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get(); + } } diff --git a/app/Classes/General/Eloquent/Filters/CurrencyRateIsNotEqual.php b/app/Classes/General/Eloquent/Filters/CurrencyRateIsNotEqual.php new file mode 100644 index 00000000..0372e760 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/CurrencyRateIsNotEqual.php @@ -0,0 +1,20 @@ +where('currency_rate', '!=', $value); + } + +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/DoesNotHaveRefundInProgress.php b/app/Classes/General/Eloquent/Filters/DoesNotHaveRefundInProgress.php new file mode 100644 index 00000000..60618626 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/DoesNotHaveRefundInProgress.php @@ -0,0 +1,24 @@ +whereDoesntHave('transactions', function ($query) { + return $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION]); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/GroupByImportedDate.php b/app/Classes/General/Eloquent/Filters/GroupByImportedDate.php new file mode 100644 index 00000000..25f20fa3 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/GroupByImportedDate.php @@ -0,0 +1,18 @@ +groupby('imported_date'); + } +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/HasActiveReward.php b/app/Classes/General/Eloquent/Filters/HasActiveReward.php index 5770ca6e..26385b96 100644 --- a/app/Classes/General/Eloquent/Filters/HasActiveReward.php +++ b/app/Classes/General/Eloquent/Filters/HasActiveReward.php @@ -2,7 +2,6 @@ namespace App\Classes\General\Eloquent\Filters; -use App\Classes\ValueObjects\Constants\RoleTypes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\Auth; @@ -12,33 +11,17 @@ class HasActiveReward implements Filter /** * @param Builder $builder * @param $value - * @return mixed + * @return Builder|mixed */ public static function apply(Builder $builder, $value) { - if(in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)){ - // $userId = $value !== 1 ? $value : Auth::user()->id; - $userId = $value; - return $builder->where('user_id', $userId) - ->where(function ($query) { - $query->whereHas('reward', function ($subquery) { - $subquery->where('is_active', true); - }) - ->orWhereDoesntHave('reward'); - }) - ->whereDoesntHave('voucher.redemptions.transaction.booking.company.employees', function ($query) use ($userId) { - $query->where('user_id', $userId); + return $builder->where('user_id', Auth::user()->id) //cief todo: should not use Auth::user()->id + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); }); - } - else{ - return $builder->where('user_id', Auth::user()->id) - ->where(function ($query) { - $query->whereHas('reward', function ($subquery) { - $subquery->where('is_active', true); - }) - ->orWhereDoesntHave('reward'); - }) - ->whereDoesntHave('voucher.redemptions.transaction.owner'); - } + // ->orWhereDoesntHave('reward'); + }); } + } diff --git a/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php b/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php new file mode 100644 index 00000000..5d69aa4b --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php @@ -0,0 +1,26 @@ +where('user_id', $value) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }); + // ->orWhereDoesntHave('reward'); + }); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/HasPendingVerifyTransaction.php b/app/Classes/General/Eloquent/Filters/HasPendingVerifyTransaction.php new file mode 100644 index 00000000..c97af23c --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasPendingVerifyTransaction.php @@ -0,0 +1,23 @@ +whereHas('transactions', function ($q) { + $q->where('status', ApprovalStatus::PENDING_VERIFICATION); + }); + } +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/HasVouchersAllWithCompany.php b/app/Classes/General/Eloquent/Filters/HasVouchersAllWithCompany.php new file mode 100644 index 00000000..be4d335b --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasVouchersAllWithCompany.php @@ -0,0 +1,53 @@ +type, RoleTypes::ADMIN_ROLES)){ + // $userId = $value !== 1 ? $value : Auth::user()->id; + $userId = $value; + $user = User::where('id', $userId)->first(); + $users = $user->company()->first()->employees; + $userIds = $users->pluck('id'); + + return $builder->whereIn('user_id', $userIds) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }) + ->orWhereDoesntHave('reward'); + }) + ->whereDoesntHave('voucher.redemptions.transaction.booking.company.employees', function ($query) use ($userId) { + $query->where('user_id', $userId); + }); + } + else{ + $user = User::where('id', Auth::user()->id)->first(); + $users = $user->company()->first()->employees; + $userIds = $users->pluck('id'); + + return $builder->whereIn('user_id', $userIds) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }) + ->orWhereDoesntHave('reward'); + }) + ->whereDoesntHave('voucher.redemptions.transaction.owner'); + } + } +} diff --git a/app/Classes/General/Eloquent/Filters/HasVouchersAllWithUser.php b/app/Classes/General/Eloquent/Filters/HasVouchersAllWithUser.php new file mode 100644 index 00000000..79a02914 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasVouchersAllWithUser.php @@ -0,0 +1,44 @@ +type, RoleTypes::ADMIN_ROLES)){ + // $userId = $value !== 1 ? $value : Auth::user()->id; + $userId = $value; + return $builder->where('user_id', $userId) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }) + ->orWhereDoesntHave('reward'); + }) + ->whereDoesntHave('voucher.redemptions.transaction.booking.company.employees', function ($query) use ($userId) { + $query->where('user_id', $userId); + }); + } + else{ + return $builder->where('user_id', Auth::user()->id) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }) + ->orWhereDoesntHave('reward'); + }) + ->whereDoesntHave('voucher.redemptions.transaction.owner'); + } + } +} diff --git a/app/Classes/General/Eloquent/Filters/ImportedDateFrom.php b/app/Classes/General/Eloquent/Filters/ImportedDateFrom.php new file mode 100644 index 00000000..140bbb20 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/ImportedDateFrom.php @@ -0,0 +1,18 @@ +whereDate('imported_date', '>=', date('Y-m-d',strtotime($value))); + } +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/ImportedDateTo.php b/app/Classes/General/Eloquent/Filters/ImportedDateTo.php new file mode 100644 index 00000000..11bd3857 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/ImportedDateTo.php @@ -0,0 +1,18 @@ +whereDate('imported_date', '<=', date('Y-m-d',strtotime($value))); + } +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/IsNotFullyRefunded.php b/app/Classes/General/Eloquent/Filters/IsNotFullyRefunded.php new file mode 100644 index 00000000..fdbb2994 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/IsNotFullyRefunded.php @@ -0,0 +1,24 @@ +withSum(['transactions as total_refund_amount' => function($q) { + $q->refunds()->where('status', ApprovalStatus::APPROVED); + }], 'original_amount') + ->having('total_refund_amount', '<', DB::raw('original_amount')); + } +} diff --git a/app/Classes/General/Eloquent/Filters/IsPartialRefund.php b/app/Classes/General/Eloquent/Filters/IsPartialRefund.php new file mode 100644 index 00000000..1378a94c --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/IsPartialRefund.php @@ -0,0 +1,26 @@ +whereHas('owner', function ($q) use ($value) { + if ($value) { + $q->where('original_amount', '!=', DB::raw('transactions.original_amount')); + } else { + $q->where('original_amount', DB::raw('transactions.original_amount')); + } + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/RandomName.php b/app/Classes/General/Eloquent/Filters/JobId.php similarity index 75% rename from app/Classes/General/Eloquent/Filters/RandomName.php rename to app/Classes/General/Eloquent/Filters/JobId.php index 54024e96..42ac51a4 100644 --- a/app/Classes/General/Eloquent/Filters/RandomName.php +++ b/app/Classes/General/Eloquent/Filters/JobId.php @@ -4,7 +4,7 @@ namespace App\Classes\General\Eloquent\Filters; use Illuminate\Database\Eloquent\Builder; -class RandomName implements Filter +class JobId implements Filter { /** @@ -14,7 +14,7 @@ class RandomName implements Filter */ public static function apply(Builder $builder, $value) { - return $builder->where('is_active', $value); + return $builder->where('job_id', $value); } } diff --git a/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php new file mode 100644 index 00000000..547ec9bd --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php @@ -0,0 +1,20 @@ +orderBy('id', 'desc'); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/OwnerDoesNotHaveTransactionType.php b/app/Classes/General/Eloquent/Filters/OwnerDoesNotHaveTransactionType.php new file mode 100644 index 00000000..4dcd401c --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OwnerDoesNotHaveTransactionType.php @@ -0,0 +1,24 @@ +whereDoesntHave('owner', function($query) use($value) { + return $query->whereHas('transactions', function($query) use($value) { + return $query->where('transactions.type', $value); + }); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/OwnerHasTransactionType.php b/app/Classes/General/Eloquent/Filters/OwnerHasTransactionType.php new file mode 100644 index 00000000..7f96643f --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OwnerHasTransactionType.php @@ -0,0 +1,24 @@ +whereHas('owner', function($query) use($value) { + return $query->whereHas('transactions', function($query) use($value) { + return $query->where('transactions.type', $value); + }); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/ReceiverIn.php b/app/Classes/General/Eloquent/Filters/ReceiverIn.php new file mode 100644 index 00000000..3ce91559 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/ReceiverIn.php @@ -0,0 +1,20 @@ +whereIn('receiver', $value); + } + +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/RequestSignature.php b/app/Classes/General/Eloquent/Filters/RequestSignature.php new file mode 100644 index 00000000..67dde0a3 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/RequestSignature.php @@ -0,0 +1,19 @@ +where('request_signature', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/ResultNotNull.php b/app/Classes/General/Eloquent/Filters/ResultNotNull.php new file mode 100644 index 00000000..3f6a0341 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/ResultNotNull.php @@ -0,0 +1,18 @@ +whereNotNull('result'); + } +} diff --git a/app/Classes/General/Eloquent/Filters/StatementTransactionInvoiceReference.php b/app/Classes/General/Eloquent/Filters/StatementTransactionInvoiceReference.php new file mode 100644 index 00000000..9e3ba1e9 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/StatementTransactionInvoiceReference.php @@ -0,0 +1,22 @@ +whereHas('owners', function ($query) use ($value) { + return $query->where('Invoice_reference', $value); + }); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/StatementTransactionOwnerReference.php b/app/Classes/General/Eloquent/Filters/StatementTransactionOwnerReference.php new file mode 100644 index 00000000..c0a7beaf --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/StatementTransactionOwnerReference.php @@ -0,0 +1,22 @@ +whereHas('owners', function ($query) use ($value) { + return $query->where('owner_reference', $value); + }); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/StatementTransactionReceiptReference.php b/app/Classes/General/Eloquent/Filters/StatementTransactionReceiptReference.php new file mode 100644 index 00000000..f808f784 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/StatementTransactionReceiptReference.php @@ -0,0 +1,22 @@ +whereHas('owners', function ($query) use ($value) { + return $query->where('receipt_reference', $value); + }); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/WithoutBillGroup.php b/app/Classes/General/Eloquent/Filters/WithoutBillGroup.php new file mode 100644 index 00000000..6d6794e8 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/WithoutBillGroup.php @@ -0,0 +1,22 @@ +whereDoesntHave('billGroup'); + } +} \ No newline at end of file diff --git a/app/Classes/General/Helper.php b/app/Classes/General/Helper.php index ac89540b..45c72f53 100644 --- a/app/Classes/General/Helper.php +++ b/app/Classes/General/Helper.php @@ -2,6 +2,7 @@ namespace App\Classes\General; +use Illuminate\Http\Resources\Json\ResourceCollection; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; @@ -42,4 +43,27 @@ class Helper } } } + + /** + * @param null|string $param + * @return array + */ + static function deserializeFilters($param): array { + if(gettype($param) == "array"){ + $json = implode(',', $param); + } + else{ + $json = $param; + } + return $json !== null ? collect(json_decode($json))->toArray() : []; + } + + /** + * @param ResourceCollection $collection + * @return array + */ + static function collectionResponse(ResourceCollection $collection){ + return json_decode($collection->response()->getContent(), true); + } + } diff --git a/app/Classes/General/Interfaces/KeyValueInterface.php b/app/Classes/General/Interfaces/KeyValueInterface.php new file mode 100644 index 00000000..8089e46a --- /dev/null +++ b/app/Classes/General/Interfaces/KeyValueInterface.php @@ -0,0 +1,12 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + $result = (App()->make(ListBookingsJobProcessor::class))->execute($this->listGenericJobObject); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Jobs/ListDocumentsJob.php b/app/Classes/Jobs/ListDocumentsJob.php new file mode 100644 index 00000000..93f1b1d3 --- /dev/null +++ b/app/Classes/Jobs/ListDocumentsJob.php @@ -0,0 +1,51 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + (App()->make(ListDocumentsJobProcessor::class))->execute($this->listGenericJobObject); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Jobs/ListTransactionsJob.php b/app/Classes/Jobs/ListTransactionsJob.php new file mode 100644 index 00000000..a2b28656 --- /dev/null +++ b/app/Classes/Jobs/ListTransactionsJob.php @@ -0,0 +1,52 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + $result = (App()->make(ListTransactionsJobProcessor::class))->execute($this->listGenericJobObject); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Jobs/SendWelcomeVoucherEmail.php b/app/Classes/Jobs/SendWelcomeVoucherEmail.php new file mode 100644 index 00000000..b6ef687e --- /dev/null +++ b/app/Classes/Jobs/SendWelcomeVoucherEmail.php @@ -0,0 +1,70 @@ +user = $user; + $this->voucher = $voucher; + $this->emailSentCount = $emailSentCount; + } + + + public function handle() + { + $currentDatetime = Carbon::now(); + $dateToCompare = Carbon::parse($this->voucher->end_date); + if (!$this->user->hasAttribute($this->voucher->code."_EMAIL_COUNT") + && $this->user->rewards->where('voucher_id', $this->voucher->id)->count() > 0 + && $currentDatetime->isBefore($dateToCompare)) + { + //Key #1 + $keyValuePairObject = new KeyValuePairObject( + $this->voucher->code."_EMAIL_COUNT", + $this->emailSentCount + ); + (App()->make(CreatesKeyValuePair::class))->execute($this->user, $keyValuePairObject); + + //Key #2 + $keyValuePairObject = new KeyValuePairObject( + $this->voucher->code."_EMAIL_DATE_".$this->emailSentCount, + Carbon::now() + ); + (App()->make(CreatesKeyValuePair::class))->execute($this->user, $keyValuePairObject); + + $this->user->notify(new WelcomeVoucherEmail($this->user, $this->voucher)); + } + } +} diff --git a/app/Classes/Jobs/UpdatePerfexCRMInvoice.php b/app/Classes/Jobs/UpdatePerfexCRMInvoice.php index 26131bca..80a60c15 100644 --- a/app/Classes/Jobs/UpdatePerfexCRMInvoice.php +++ b/app/Classes/Jobs/UpdatePerfexCRMInvoice.php @@ -57,16 +57,15 @@ class UpdatePerfexCRMInvoice implements ShouldQueue $number = 'EXC-'.$number; $invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $number); - Log::error(json_encode('UpdatePerfexCRMInvoice debug $number: '.$number)); + Log::channel('perfex_crm')->info(('UpdatePerfexCRMInvoice debug $number: '.$number)); if(is_null($invoice)){ $result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction); if ($result) { $invoiceId = $result->payload['id']; } else { - // Log::error(json_encode('UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed')); $log['message'] = 'UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed'; - Helper::debugLogger($log); + Log::channel('perfex_crm')->info($log); } } else{ @@ -75,7 +74,7 @@ class UpdatePerfexCRMInvoice implements ShouldQueue //This only run when invoice already exist and the invoice does not have a PAID status if($invoiceStatus != PerfexCRMInvoiceStatus::PAID){ - Log::error(json_encode('UpdatePerfexCRMInvoice debug $this->updatePerfexCRMInvoiceObject->getProjectId(): '.$this->updatePerfexCRMInvoiceObject->getProjectId())); + Log::channel('perfex_crm')->info('UpdatePerfexCRMInvoice debug $this->updatePerfexCRMInvoiceObject->getProjectId(): '.$this->updatePerfexCRMInvoiceObject->getProjectId()); //update invoice (App()->make(UpdatesPerfexCRMInvoice::class))->execute($invoice, $this->updatePerfexCRMInvoiceObject->getProjectId()); diff --git a/app/Classes/Jobs/UpdatePerfexCRMPrelude.php b/app/Classes/Jobs/UpdatePerfexCRMPrelude.php index 3b05ac63..1bf9dede 100644 --- a/app/Classes/Jobs/UpdatePerfexCRMPrelude.php +++ b/app/Classes/Jobs/UpdatePerfexCRMPrelude.php @@ -41,7 +41,11 @@ class UpdatePerfexCRMPrelude implements ShouldQueue { $serviceTypeName = $this->transaction->owner->company->services()->where('id', $this->transaction->owner->service_id)->first()->name; $booking = $this->transaction->booking; - $bankDetails = $this->generateBankDetails($booking->bank); + $bank = $booking->bank; //cief todo: 66 + if($this->transaction->bank){ + $bank = $this->transaction->bank; + } + $bankDetails = $this->generateBankDetails($bank); $data = [ 'amount' => number_format($this->transaction->amount, 2, '.', ''), diff --git a/app/Classes/Modules/Accounting/ControllersLogic/HistoryImportedTransactionMappedControllerLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/HistoryImportedTransactionMappedControllerLogic.php new file mode 100644 index 00000000..2f96c613 --- /dev/null +++ b/app/Classes/Modules/Accounting/ControllersLogic/HistoryImportedTransactionMappedControllerLogic.php @@ -0,0 +1,49 @@ + 'Retrieved History Imported Invoices', + 'message' => 'You have successfully retrieved history imported invoices' + ]; + } + + /** @var ListTransactionMappingLogs */ + private $listTransactionMappingLogs; + + /** + * UpdateAnnouncementLogic constructor. + * @param ListTransactionMappingLogs $listTransactionMappingLogs + */ + public function __construct( + ListTransactionMappingLogs $listTransactionMappingLogs + ) { + $this->listTransactionMappingLogs = $listTransactionMappingLogs; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request): JsonResponse + { + $query = $this->listTransactionMappingLogs->execute($this->listTransactionMappingLogs->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(TransactionMappingLogResource::collection($query)); + } +} diff --git a/app/Classes/Modules/Accounting/ControllersLogic/UpdateStatementTransactionStatusLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/UpdateStatementTransactionStatusLogic.php index 55051959..b208c2e3 100644 --- a/app/Classes/Modules/Accounting/ControllersLogic/UpdateStatementTransactionStatusLogic.php +++ b/app/Classes/Modules/Accounting/ControllersLogic/UpdateStatementTransactionStatusLogic.php @@ -2,16 +2,14 @@ namespace App\Classes\Modules\Accounting\ControllersLogic; -use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Accounting\Services\FetchesBankStatementTransaction; -use App\Http\Resources\BankStatementTransactionResource; -use App\Classes\Modules\Accounting\Services\UpdatesBankStatementTransactionOwnerStatus; -use App\Classes\ValueObjects\Constants\ApprovalStatus; -use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; - +use Illuminate\Http\JsonResponse; +use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\General\Abstracts\AbstractControllerLogic; +use App\Http\Resources\BankStatementTransactionOwnerResource; +use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; +use App\Classes\Modules\Accounting\Services\FetchesBankStatementTransactionOwner; +use App\Classes\Modules\Accounting\Services\UpdatesBankStatementTransactionOwnerStatus; class UpdateStatementTransactionStatusLogic extends AbstractControllerLogic { @@ -27,29 +25,23 @@ class UpdateStatementTransactionStatusLogic extends AbstractControllerLogic ]; } - /** @var FetchesBankStatementTransaction */ - private $fetchesBankStatementTransaction; + /** @var FetchesBankStatementTransactionOwner */ + private $fetchesBankStatementTransactionOwner; /** @var UpdatesBankStatementTransactionOwnerStatus */ private $updatesBankStatementTransactionOwnerStatus; - /** @var UpdatesTransactionStatus */ - private $updatesTransactionStatus; - /** * UpdateAnnouncementLogic constructor. - * @param FetchesBankStatementTransaction $fetchesBankStatementTransaction + * @param FetchesBankStatementTransactionOwner $fetchesBankStatementTransactionOwner * @param UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus - * @param UpdatesTransactionStatus $updatesTransactionStatus */ public function __construct( - FetchesBankStatementTransaction $fetchesBankStatementTransaction, - UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus, - UpdatesTransactionStatus $updatesTransactionStatus + FetchesBankStatementTransactionOwner $fetchesBankStatementTransactionOwner, + UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus ) { - $this->fetchesBankStatementTransaction = $fetchesBankStatementTransaction; + $this->fetchesBankStatementTransactionOwner = $fetchesBankStatementTransactionOwner; $this->updatesBankStatementTransactionOwnerStatus = $updatesBankStatementTransactionOwnerStatus; - $this->updatesTransactionStatus = $updatesTransactionStatus; } /** @@ -61,21 +53,10 @@ class UpdateStatementTransactionStatusLogic extends AbstractControllerLogic */ public function logic(Request $request): JsonResponse { - $statementTrasaction = $this->fetchesBankStatementTransaction->execute(['id' => $request->route('id')]); - - $statementTrasactionOwner = $statementTrasaction->owners()->where('status', '!=', ApprovalStatus::REJECTED)->first(); + $statementTrasactionOwner = $this->fetchesBankStatementTransactionOwner->execute(['id' => $request->route('id')]); $this->updatesBankStatementTransactionOwnerStatus->execute($statementTrasactionOwner, $request->route('status') == 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED); - // todo-new: approve payments status, need to check the owner(if system is shipping, need to api with shipping portal) - // if ($request->route('status') == 'approve') { - // if ($statementTrasactionOwner->transaction->type === StatementTransactionOwnerType::SALES) { - // if ($statementTrasactionOwner->owner->status === ApprovalStatus::PENDING_VERIFICATION) { - // $this->updatesTransactionStatus->execute($statementTrasactionOwner->owner, ApprovalStatus::APPROVED); - // } - // } - // } - - return $this->resourceResponse(new BankStatementTransactionResource($statementTrasaction)); + return $this->resourceResponse(new BankStatementTransactionOwnerResource($statementTrasactionOwner)); } } diff --git a/app/Classes/Modules/Accounting/Processors/ListShippingPortalTransactions.php b/app/Classes/Modules/Accounting/Processors/ListShippingPortalTransactions.php index f80c3c0e..18ec9c36 100644 --- a/app/Classes/Modules/Accounting/Processors/ListShippingPortalTransactions.php +++ b/app/Classes/Modules/Accounting/Processors/ListShippingPortalTransactions.php @@ -13,6 +13,7 @@ class ListShippingPortalTransactions { try { $url = 'https://izyim.cief-malaysia.com/public/api/v1/transactions/mappable/query/with-details'; + // $url = 'http://127.0.0.1:8001/public/api/v1/transactions/mappable/query/with-details'; $client = new \GuzzleHttp\Client(['verify' => false]); $response = $client->request('GET', $url . '?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters=' . json_encode($filters)); $body = $response->getBody(); diff --git a/app/Classes/Modules/Accounting/Services/FetchesBankStatementTransactionOwner.php b/app/Classes/Modules/Accounting/Services/FetchesBankStatementTransactionOwner.php new file mode 100644 index 00000000..17c620f5 --- /dev/null +++ b/app/Classes/Modules/Accounting/Services/FetchesBankStatementTransactionOwner.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Accounting/Services/ListTransactionMappingLogs.php b/app/Classes/Modules/Accounting/Services/ListTransactionMappingLogs.php new file mode 100644 index 00000000..fdeff835 --- /dev/null +++ b/app/Classes/Modules/Accounting/Services/ListTransactionMappingLogs.php @@ -0,0 +1,32 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php index fa6a9ae7..148aca84 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php @@ -16,6 +16,7 @@ use App\Classes\Modules\Vouchers\Processors\Voucherify\NewCustomerToVoucherifyPr use App\Classes\Modules\Vouchers\Processors\CreateVoucherProcessor; use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject; use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject; +use App\Classes\Modules\Rewards\Services\CreatesUserReward; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\BusinessType; use App\Classes\ValueObjects\Constants\CompanyType; @@ -30,6 +31,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\App; use App\Classes\Modules\Segments\Services\CreatesSeasonalSegment; +use App\Classes\ValueObjects\Constants\Vouchers; class CreateCustomerLogic extends AbstractControllerLogic { @@ -77,6 +79,9 @@ class CreateCustomerLogic extends AbstractControllerLogic /** @var CreateVoucherProcessor */ private $createVoucherProcessor; + /** @var CreatesUserReward */ + private $createsUserReward; + /** * CreateCustomerLogic constructor. * @param CreateUserProcessor $createUserProcessor @@ -90,9 +95,10 @@ class CreateCustomerLogic extends AbstractControllerLogic * @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor * @param NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor * @param CreateVoucherProcessor $createVoucherProcessor + * @param CreatesUserReward $createsUserReward */ 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, CreatesUserReward $createsUserReward) { $this->createUserProcessor = $createUserProcessor; $this->createCompanyProcessor = $createCompanyProcessor; @@ -105,6 +111,7 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; $this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor; $this->createVoucherProcessor = $createVoucherProcessor; + $this->createsUserReward = $createsUserReward; } /** @@ -159,7 +166,13 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->newCustomerToVoucherifyProcessor->execute($company->id, $user, true); - $this->createVoucherProcessor->execute($user, 'WELCOME50%OFF'); + $voucher = $this->createVoucherProcessor->execute($user, Vouchers::WELCOME_50_PERCENT_OFF); + if($voucher){ + $voucherCount = $user->rewards->where('voucher_id', $voucher->id)->count(); + if($voucherCount === 0){ + $this->createsUserReward->execute(null, $user, $voucher->id); + } + } return $this->response($this->authenticationProcessor->execute($request, false)); diff --git a/app/Classes/Modules/Accounts/ControllersLogic/UserEmailVerificationLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/UserEmailVerificationLogic.php index bae6f5eb..13a8bcc7 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/UserEmailVerificationLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/UserEmailVerificationLogic.php @@ -9,6 +9,9 @@ use App\Classes\Modules\Accounts\Services\CompletesEmailVerificationAttempt; use App\Classes\Modules\Accounts\Services\FetchesEmailVerificationAttempt; use App\Classes\Modules\Accounts\Services\VerifiesUser; use App\Classes\Modules\Accounts\Standards\Criteria\EmailVerificationActiveAttemptExists; +use App\Classes\Modules\Vouchers\Services\FetchesVoucher; +use App\Classes\Jobs\SendWelcomeVoucherEmail; +use App\Classes\ValueObjects\Constants\Vouchers; use App\Models\UserEmailVerification; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -36,19 +39,29 @@ class UserEmailVerificationLogic extends AbstractControllerLogic /** @var VerifiesUser */ private $verifiesUser; + /** @var SendWelcomeVoucherEmail */ + private $sendWelcomeVoucherEmail; + + /** @var FetchesVoucher */ + private $fetchesVoucher; + /** * UserEmailVerificationLogic constructor. * @param EmailVerificationActiveAttemptExists $emailVerificationActiveAttemptExists * @param CompletesEmailVerificationAttempt $completesEmailVerificationAttempt * @param FetchesEmailVerificationAttempt $fetchesEmailVerificationAttempt * @param VerifiesUser $verifiesUser + * @param SendWelcomeVoucherEmail $sendWelcomeVoucherEmail + * @param FetchesVoucher $fetchesVoucher */ - public function __construct(EmailVerificationActiveAttemptExists $emailVerificationActiveAttemptExists, CompletesEmailVerificationAttempt $completesEmailVerificationAttempt, FetchesEmailVerificationAttempt $fetchesEmailVerificationAttempt, VerifiesUser $verifiesUser) + public function __construct(EmailVerificationActiveAttemptExists $emailVerificationActiveAttemptExists, CompletesEmailVerificationAttempt $completesEmailVerificationAttempt, FetchesEmailVerificationAttempt $fetchesEmailVerificationAttempt, VerifiesUser $verifiesUser, SendWelcomeVoucherEmail $sendWelcomeVoucherEmail, FetchesVoucher $fetchesVoucher) { $this->emailVerificationActiveAttemptExists = $emailVerificationActiveAttemptExists; $this->completesEmailVerificationAttempt = $completesEmailVerificationAttempt; $this->fetchesEmailVerificationAttempt = $fetchesEmailVerificationAttempt; $this->verifiesUser = $verifiesUser; + $this->sendWelcomeVoucherEmail = $sendWelcomeVoucherEmail; + $this->fetchesVoucher = $fetchesVoucher; } /** @@ -68,9 +81,19 @@ class UserEmailVerificationLogic extends AbstractControllerLogic $this->completesEmailVerificationAttempt->execute($attempt); - $this->verifiesUser->execute($attempt->user); + $user = $attempt->user; + $this->verifiesUser->execute($user); + + // if (env('SENDING_EMAIL_WELCOME_VOUCHER_ENABLED', false)){ + if (app()->environment('production') && env('SENDING_EMAIL_WELCOME_VOUCHER_ENABLED', false)){ + try{ //In case voucher got deleted unintentionally + $voucher = $this->fetchesVoucher->execute(['code' => Vouchers::WELCOME_50_PERCENT_OFF]); + if($voucher) $this->sendWelcomeVoucherEmail::dispatch($user, $voucher, 1); + } + catch(\Exception $e){} + } return $this->response([]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Accounts/DataTransferObjects/KeyValuePairObject.php b/app/Classes/Modules/Accounts/DataTransferObjects/KeyValuePairObject.php new file mode 100644 index 00000000..fd1eff49 --- /dev/null +++ b/app/Classes/Modules/Accounts/DataTransferObjects/KeyValuePairObject.php @@ -0,0 +1,44 @@ +key = $key; + $this->value = $value; + } + + /** + * @return string + */ + public function getKey(): string + { + return $this->key; + } + + /** + * @return string + */ + public function getValue(): string + { + return $this->value; + } + +} diff --git a/app/Classes/Modules/Accounts/Services/CreatesKeyValuePair.php b/app/Classes/Modules/Accounts/Services/CreatesKeyValuePair.php new file mode 100644 index 00000000..6634bed2 --- /dev/null +++ b/app/Classes/Modules/Accounts/Services/CreatesKeyValuePair.php @@ -0,0 +1,28 @@ +key = $object->getKey(); + $model->value = $object->getValue(); + + return $this->handler($kv->attributesKVP(), $model); + + } +} diff --git a/app/Classes/Modules/Accounts/Services/DeletesKeyValuePair.php b/app/Classes/Modules/Accounts/Services/DeletesKeyValuePair.php new file mode 100644 index 00000000..a52288af --- /dev/null +++ b/app/Classes/Modules/Accounts/Services/DeletesKeyValuePair.php @@ -0,0 +1,19 @@ +handler($model); + } +} diff --git a/app/Classes/Modules/Accounts/Services/UpdatesKeyValuePair.php b/app/Classes/Modules/Accounts/Services/UpdatesKeyValuePair.php new file mode 100644 index 00000000..0a800d79 --- /dev/null +++ b/app/Classes/Modules/Accounts/Services/UpdatesKeyValuePair.php @@ -0,0 +1,22 @@ +key = $object->getKey(); + $model->value = $object->getValue(); + return $this->handler($model); + } +} diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanAuthenticateUser.php b/app/Classes/Modules/Accounts/Standards/Rules/CanAuthenticateUser.php index ad2be911..e1a4b50d 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanAuthenticateUser.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanAuthenticateUser.php @@ -26,7 +26,7 @@ class CanAuthenticateUser extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanCreateUser.php b/app/Classes/Modules/Accounts/Standards/Rules/CanCreateUser.php index 2da56844..7a32df58 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanCreateUser.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanCreateUser.php @@ -26,7 +26,7 @@ class CanCreateUser extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanDeleteUser.php b/app/Classes/Modules/Accounts/Standards/Rules/CanDeleteUser.php index f106bcc7..9c1e3ad6 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanDeleteUser.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanDeleteUser.php @@ -10,7 +10,7 @@ class CanDeleteUser extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanFetchUser.php b/app/Classes/Modules/Accounts/Standards/Rules/CanFetchUser.php index 740e231c..5f39c290 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanFetchUser.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanFetchUser.php @@ -12,7 +12,7 @@ class CanFetchUser extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanGeneratePasswordReset.php b/app/Classes/Modules/Accounts/Standards/Rules/CanGeneratePasswordReset.php index 8a9b8226..dd314f81 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanGeneratePasswordReset.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanGeneratePasswordReset.php @@ -33,7 +33,7 @@ class CanGeneratePasswordReset extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanListUsers.php b/app/Classes/Modules/Accounts/Standards/Rules/CanListUsers.php index d1ba2ea0..a4186733 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanListUsers.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanListUsers.php @@ -13,7 +13,7 @@ class CanListUsers extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanRegisterUser.php b/app/Classes/Modules/Accounts/Standards/Rules/CanRegisterUser.php index d0720d1c..64aefd00 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanRegisterUser.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanRegisterUser.php @@ -24,7 +24,7 @@ class CanRegisterUser extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanResendEmailVerification.php b/app/Classes/Modules/Accounts/Standards/Rules/CanResendEmailVerification.php index 4a9f016c..2ac8e942 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanResendEmailVerification.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanResendEmailVerification.php @@ -13,7 +13,7 @@ class CanResendEmailVerification extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanResetPassword.php b/app/Classes/Modules/Accounts/Standards/Rules/CanResetPassword.php index cf620414..adaed65d 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanResetPassword.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanResetPassword.php @@ -34,7 +34,7 @@ class CanResetPassword extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; diff --git a/app/Classes/Modules/Accounts/Standards/Rules/CanUpdateUser.php b/app/Classes/Modules/Accounts/Standards/Rules/CanUpdateUser.php index a523ac12..c5abcd0f 100644 --- a/app/Classes/Modules/Accounts/Standards/Rules/CanUpdateUser.php +++ b/app/Classes/Modules/Accounts/Standards/Rules/CanUpdateUser.php @@ -26,7 +26,7 @@ class CanUpdateUser extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Addresses/Standards/Rules/CanCreateAddress.php b/app/Classes/Modules/Addresses/Standards/Rules/CanCreateAddress.php index 42508b1d..685e2e6e 100644 --- a/app/Classes/Modules/Addresses/Standards/Rules/CanCreateAddress.php +++ b/app/Classes/Modules/Addresses/Standards/Rules/CanCreateAddress.php @@ -26,7 +26,7 @@ class CanCreateAddress extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Addresses/Standards/Rules/CanDeleteAddress.php b/app/Classes/Modules/Addresses/Standards/Rules/CanDeleteAddress.php index c13a890c..a03ea389 100644 --- a/app/Classes/Modules/Addresses/Standards/Rules/CanDeleteAddress.php +++ b/app/Classes/Modules/Addresses/Standards/Rules/CanDeleteAddress.php @@ -13,7 +13,7 @@ class CanDeleteAddress extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Addresses/Standards/Rules/CanFetchAddress.php b/app/Classes/Modules/Addresses/Standards/Rules/CanFetchAddress.php index ffe53bee..61e7df25 100644 --- a/app/Classes/Modules/Addresses/Standards/Rules/CanFetchAddress.php +++ b/app/Classes/Modules/Addresses/Standards/Rules/CanFetchAddress.php @@ -13,7 +13,7 @@ class CanFetchAddress extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Addresses/Standards/Rules/CanListAddresses.php b/app/Classes/Modules/Addresses/Standards/Rules/CanListAddresses.php index aa02c55c..363332ec 100644 --- a/app/Classes/Modules/Addresses/Standards/Rules/CanListAddresses.php +++ b/app/Classes/Modules/Addresses/Standards/Rules/CanListAddresses.php @@ -13,7 +13,7 @@ class CanListAddresses extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Addresses/Standards/Rules/CanUpdateAddress.php b/app/Classes/Modules/Addresses/Standards/Rules/CanUpdateAddress.php index 355b590a..a03db81b 100644 --- a/app/Classes/Modules/Addresses/Standards/Rules/CanUpdateAddress.php +++ b/app/Classes/Modules/Addresses/Standards/Rules/CanUpdateAddress.php @@ -26,7 +26,7 @@ class CanUpdateAddress extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Announcements/Standards/Rules/CanAssignSegment.php b/app/Classes/Modules/Announcements/Standards/Rules/CanAssignSegment.php index 625a07a1..75d9e361 100644 --- a/app/Classes/Modules/Announcements/Standards/Rules/CanAssignSegment.php +++ b/app/Classes/Modules/Announcements/Standards/Rules/CanAssignSegment.php @@ -13,7 +13,7 @@ class CanAssignSegment extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Announcements/Standards/Rules/CanCreateAnnouncement.php b/app/Classes/Modules/Announcements/Standards/Rules/CanCreateAnnouncement.php index a01e0de1..7fe2fddb 100644 --- a/app/Classes/Modules/Announcements/Standards/Rules/CanCreateAnnouncement.php +++ b/app/Classes/Modules/Announcements/Standards/Rules/CanCreateAnnouncement.php @@ -24,7 +24,7 @@ class CanCreateAnnouncement extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; } diff --git a/app/Classes/Modules/Announcements/Standards/Rules/CanDeleteAnnouncement.php b/app/Classes/Modules/Announcements/Standards/Rules/CanDeleteAnnouncement.php index 8a41deab..36d3edc7 100644 --- a/app/Classes/Modules/Announcements/Standards/Rules/CanDeleteAnnouncement.php +++ b/app/Classes/Modules/Announcements/Standards/Rules/CanDeleteAnnouncement.php @@ -10,7 +10,7 @@ class CanDeleteAnnouncement extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Announcements/Standards/Rules/CanListAnnouncements.php b/app/Classes/Modules/Announcements/Standards/Rules/CanListAnnouncements.php index a4c02847..0c47546f 100644 --- a/app/Classes/Modules/Announcements/Standards/Rules/CanListAnnouncements.php +++ b/app/Classes/Modules/Announcements/Standards/Rules/CanListAnnouncements.php @@ -11,7 +11,7 @@ class CanListAnnouncements extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; } diff --git a/app/Classes/Modules/Announcements/Standards/Rules/CanUpdateAnnouncement.php b/app/Classes/Modules/Announcements/Standards/Rules/CanUpdateAnnouncement.php index d861d255..4d20fe3a 100644 --- a/app/Classes/Modules/Announcements/Standards/Rules/CanUpdateAnnouncement.php +++ b/app/Classes/Modules/Announcements/Standards/Rules/CanUpdateAnnouncement.php @@ -26,7 +26,7 @@ class CanUpdateAnnouncement extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Banks/ControllersLogic/UpdateBankLogic.php b/app/Classes/Modules/Banks/ControllersLogic/UpdateBankLogic.php index 8509ed6b..88172f47 100644 --- a/app/Classes/Modules/Banks/ControllersLogic/UpdateBankLogic.php +++ b/app/Classes/Modules/Banks/ControllersLogic/UpdateBankLogic.php @@ -3,21 +3,17 @@ namespace App\Classes\Modules\Banks\ControllersLogic; use App\Http\Resources\BankResource; - use App\Classes\General\Abstracts\AbstractControllerLogic; - use App\Classes\Modules\Banks\Services\FetchesBank; - use App\Classes\Modules\Banks\Standards\Rules\CanUpdateBank; use App\Classes\Modules\Banks\Services\UpdatesBank; +use App\Classes\Modules\Banks\Services\CreatesOrUpdateBank; use App\Classes\Modules\Banks\Services\CreatesBankLog; - +use App\Classes\Modules\Banks\Processors\UpdateBankProcessor; use App\Classes\Modules\Banks\DataTransferObjects\BankObject; - -use ErrorException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Support\Facades\DB; + class UpdateBankLogic extends AbstractControllerLogic { @@ -44,24 +40,36 @@ class UpdateBankLogic extends AbstractControllerLogic /** @var CreatesBankLog */ private $createsBankLog; + /** @var CreatesOrUpdateBank */ + private $createsOrUpdateBank; + + /** @var UpdateBankProcessor */ + private $updateBankProcessor; + /** * UpdateBankLogic constructor. * @param CanUpdateBank $canUpdateBank * @param UpdatesBank $updatesBank * @param FetchesBank $fetchesBank * @param CreatesBankLog $createsBankLog + * @param CreatesOrUpdateBank $createsOrUpdateBank + * @param UpdateBankProcessor $updateBankProcessor */ public function __construct( CanUpdateBank $canUpdateBank, UpdatesBank $updatesBank, FetchesBank $fetchesBank, - CreatesBankLog $createsBankLog + CreatesBankLog $createsBankLog, + CreatesOrUpdateBank $createsOrUpdateBank, + UpdateBankProcessor $updateBankProcessor ) { $this->canUpdateBank = $canUpdateBank; $this->updatesBank = $updatesBank; $this->fetchesBank = $fetchesBank; $this->createsBankLog = $createsBankLog; + $this->createsOrUpdateBank = $createsOrUpdateBank; + $this->updateBankProcessor = $updateBankProcessor; } /** @@ -74,15 +82,15 @@ class UpdateBankLogic extends AbstractControllerLogic public function logic(Request $request) : JsonResponse { $bankObject = new BankObject( - $request->input('company_id'), + $request->input('company_id'), $request->input('account_type'), $request->input('bank_name'), - $request->input('holder_name'), + $request->input('holder_name'), $request->input('account_no'), - $request->input('bank_branch'), - $request->input('swift'), + $request->input('bank_branch'), + $request->input('swift'), $request->input('snap'), - $request->input('country_id'), + $request->input('country_id'), $request->input('reference') ); @@ -90,12 +98,10 @@ class UpdateBankLogic extends AbstractControllerLogic $this->canUpdateBank->passes($bankObject); - $bank_query = $this->updatesBank->execute($bank, $bankObject); - -// $bankLog = $this->createsBankLog->execute($bank_query); + $bank_query = $this->updateBankProcessor->execute($bankObject, $bank, $request->input('bill_no') ?? '', (int) $request->input('transaction_id') ?? 0 ); return $this->resourceResponse(new BankResource($bank_query)); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Banks/ControllersLogic/UpdateBankMetadataLogic.php b/app/Classes/Modules/Banks/ControllersLogic/UpdateBankMetadataLogic.php new file mode 100644 index 00000000..e73d051a --- /dev/null +++ b/app/Classes/Modules/Banks/ControllersLogic/UpdateBankMetadataLogic.php @@ -0,0 +1,67 @@ + 'Update Bank Metadata', + 'message' => 'You have successfully updated the Bank metadata' + ]; + } + + /** @var CanUpdateBankMetadata */ + private $canUpdateBankMetadata; + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** + * UpdateBankMetadataLogic constructor. + * @param CanUpdateBankMetadata $canUpdateBankMetadata + * @param FetchesTransaction $fetchesTransaction + */ + public function __construct( + CanUpdateBankMetadata $canUpdateBankMetadata, + FetchesTransaction $fetchesTransaction + ) + { + $this->canUpdateBankMetadata = $canUpdateBankMetadata; + $this->fetchesTransaction = $fetchesTransaction; + } + + /** + * @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 + { + $bankMetadataObject = new BankMetadataObject( + $request->input('transactionId'), + ); + + $this->canUpdateBankMetadata->passes($bankMetadataObject); + + $transaction = $this->fetchesTransaction->execute(['id' => $request->input('transactionId')]); + $transaction->attributesKVP()->delete(); + + return $this->response([]); + } + +} diff --git a/app/Classes/Modules/Banks/DataTransferObjects/BankMetadataObject.php b/app/Classes/Modules/Banks/DataTransferObjects/BankMetadataObject.php new file mode 100644 index 00000000..dae7a61e --- /dev/null +++ b/app/Classes/Modules/Banks/DataTransferObjects/BankMetadataObject.php @@ -0,0 +1,29 @@ +transaction_id = $transaction_id; + } + + /** + * @return int + */ + public function getTransactionId(): int + { + return $this->transaction_id; + } +} diff --git a/app/Classes/Modules/Banks/Processors/UpdateBankProcessor.php b/app/Classes/Modules/Banks/Processors/UpdateBankProcessor.php new file mode 100644 index 00000000..6030c11d --- /dev/null +++ b/app/Classes/Modules/Banks/Processors/UpdateBankProcessor.php @@ -0,0 +1,97 @@ +updatesBank = $updatesBank; + $this->createsOrUpdateBank = $createsOrUpdateBank; + $this->createsKeyValuePair = $createsKeyValuePair; + $this->fetchesTransaction = $fetchesTransaction; + } + + /** + * @param BankObject $bankObject + * @param Bank $bank + * @param string $billNo + * @param int $transactionId + * @return Model + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(BankObject $bankObject, Bank $bank, string $billNo, int $transactionId) { + $result = null; + if($billNo && $transactionId){ + $transaction = $this->fetchesTransaction->execute(['id' => $transactionId]); + //If payment transaction do not have a bank yet, create one + if(!$transaction->bank){ + $result = $this->createsOrUpdateBank->execute($bankObject); + + // if ($result->wasRecentlyCreated) { + //Key #1 for Bank + $kvp = $bank->attributesKVP()->where('key', 'App\Models\Bank')->where('value', $result->id)->latest()->first(); + if(!$kvp){ + $keyValuePairObject = new KeyValuePairObject( + "App\Models\Bank", + $result->id + ); + $this->createsKeyValuePair->execute($bank, $keyValuePairObject); + } + + //Key #2 for Payment Transaction (owner type: booking) + $keyValuePairObject = new KeyValuePairObject( + "App\Models\Bank", + $result->id + ); + $this->createsKeyValuePair->execute($transaction, $keyValuePairObject); + // } + + } + else{ + $result = $this->updatesBank->execute($transaction->bank, $bankObject); + } + } + else{ + $result = $this->updatesBank->execute($bank, $bankObject); + } + + return $result; + } +} diff --git a/app/Classes/Modules/Banks/Services/CreatesOrUpdateBank.php b/app/Classes/Modules/Banks/Services/CreatesOrUpdateBank.php new file mode 100644 index 00000000..1c582229 --- /dev/null +++ b/app/Classes/Modules/Banks/Services/CreatesOrUpdateBank.php @@ -0,0 +1,44 @@ + $object->getCompanyId(), + 'account_no' => $object->getAccountNo(), + 'reference' => $object->getReference(), + 'bank_name' => $object->getBankName(), + 'holder_name' => $object->getHolderName(), + 'bank_branch' => $object->getBankBranch(), + 'type' => $object->getType(), + 'country_id' => $object->getCountryId(), + 'created_by' => Auth::id(), + 'creator_type' => in_array($user->type, RoleTypes::ADMIN_ROLES) ? RoleTypes::ADMIN : RoleTypes::USER, + ]; + + $values = [ + 'swift' => $object->getSwift(), + 'snap' => $object->getSnap(), + ]; + + $model = Bank::updateOrCreate($attributes, $values); //Bank::firstOrCreate($attributes, $values); + + return $model; + } +} diff --git a/app/Classes/Modules/Banks/Standards/Rules/CanCreateBank.php b/app/Classes/Modules/Banks/Standards/Rules/CanCreateBank.php index 8cef85d8..cc155da8 100644 --- a/app/Classes/Modules/Banks/Standards/Rules/CanCreateBank.php +++ b/app/Classes/Modules/Banks/Standards/Rules/CanCreateBank.php @@ -24,7 +24,7 @@ class CanCreateBank extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; } diff --git a/app/Classes/Modules/Banks/Standards/Rules/CanDeleteBank.php b/app/Classes/Modules/Banks/Standards/Rules/CanDeleteBank.php index 074550e5..82d7b571 100644 --- a/app/Classes/Modules/Banks/Standards/Rules/CanDeleteBank.php +++ b/app/Classes/Modules/Banks/Standards/Rules/CanDeleteBank.php @@ -10,7 +10,7 @@ class CanDeleteBank extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Banks/Standards/Rules/CanListBanks.php b/app/Classes/Modules/Banks/Standards/Rules/CanListBanks.php index d01232e7..f3a8616e 100644 --- a/app/Classes/Modules/Banks/Standards/Rules/CanListBanks.php +++ b/app/Classes/Modules/Banks/Standards/Rules/CanListBanks.php @@ -12,7 +12,7 @@ class CanListBanks extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; } diff --git a/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBank.php b/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBank.php index e7a6d0fc..10f0b653 100644 --- a/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBank.php +++ b/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBank.php @@ -26,7 +26,7 @@ class CanUpdateBank extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBankMetadata.php b/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBankMetadata.php new file mode 100644 index 00000000..d102a763 --- /dev/null +++ b/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBankMetadata.php @@ -0,0 +1,66 @@ +validation = $validation; + } + + /** + * @return bool + */ + protected function authorized($object): bool + { + //cief todo: 66 - temporary workaround + // if (!Auth::user()->can('update bank_metadata')) { + // return false; + // } + + // return true; + + if (in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)) { + return true; + } + + return false; + } + + /** + * @param BankMetadataObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return $this->validation->validate($object); + } + + /** + * @param BankMetadataObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Banks/Standards/Validators/BankMetadataValidation.php b/app/Classes/Modules/Banks/Standards/Validators/BankMetadataValidation.php new file mode 100644 index 00000000..37e134c4 --- /dev/null +++ b/app/Classes/Modules/Banks/Standards/Validators/BankMetadataValidation.php @@ -0,0 +1,38 @@ + $object->getTransactionId(), + ]; + } + + /** + * @return array + */ + protected function rules(): array + { + return [ + 'transaction_id' => 'required', + ]; + } + + /** + * @return array + */ + protected function messages(): array + { + return []; + } +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php index 61f78dcb..47aa11cb 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php @@ -2,6 +2,7 @@ namespace App\Classes\Modules\Bookings\ControllersLogic; +use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Companies\Services\FetchesCompany; @@ -15,6 +16,7 @@ use App\Classes\Modules\Bookings\Services\GeneratesBookingMarking; use App\Classes\Modules\Bookings\DataTransferObjects\BookingObject; use App\Classes\Modules\PerfexCRM\Processors\BookingToPerfexCRMProcessor; use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor; +use App\Classes\ValueObjects\Constants\BookingAttributeNames; use App\Classes\ValueObjects\Constants\Milestones; use App\Http\Resources\BookingResource; @@ -84,6 +86,21 @@ class CreateBookingLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { + if (in_array($request->input('service_id'), [4, 10])) { + if (!$request['order_reference_no']) { + throw new MalformedRequestException('At least 1 order reference required.'); + } + + if ($request['order_reference_no']) { + foreach ($request['order_reference_no'] as $index => $reference) { + if (!$reference) { + $index += 1; + throw new MalformedRequestException("Order reference {$index} cannot be empty"); + } + } + } + } + $company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]); $object = new BookingObject($request->input('service_id'), $request->input('transferable_bank_id'), $this->generatesBookingMarking->execute(), number_format( floatval(str_replace(',', '', $request->input('fix_amount'))), 5, '.', ''), $request->input('type') === 1 ? $request->input('convertible_currency_id') : 1, $request->input('convertible_currency_id'), 1); @@ -97,6 +114,15 @@ class CreateBookingLogic extends AbstractControllerLogic $this->bookingToPerfexCRMProcessor->execute($booking); } + if (in_array($request->input('service_id'), [4, 10])) { + foreach ($request['order_reference_no'] as $order_reference) { + $booking->modelAttributes()->create([ + 'name' => BookingAttributeNames::ORDER_REFERENCE_NO, + 'value' => $order_reference + ]); + } + } + //cief todo: case study 5 // $user = $company->employees()->first(); // $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_5]); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php index c429d91d..ab654675 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php @@ -19,6 +19,7 @@ use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject; use App\Http\Resources\TransactionResource; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor; use App\Classes\Modules\Vouchers\Processors\Voucherify\BookingToVoucherifyProcessor; @@ -77,6 +78,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic /** @var BookingToVoucherifyProcessor */ private $bookingToVoucherifyProcessor; + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + /** * CreateBookingPaymentLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -90,8 +94,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic * @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor * @param RecalculatesWalletBalance $recalculatesWalletBalance * @param BookingToVoucherifyProcessor $bookingToVoucherifyProcessor + * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor) + public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; @@ -104,6 +109,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor; $this->recalculatesWalletBalance = $recalculatesWalletBalance; $this->bookingToVoucherifyProcessor = $bookingToVoucherifyProcessor; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } /** @@ -119,7 +125,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $request->input('amount'))), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')]); - $outstanding = $this->calculatesBookingOutstanding->execute($booking); + $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding .'.'); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index d31ee2ce..e6bf4f1c 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -14,11 +14,15 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Transactions\Services\CreatesTransaction; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Bookings\Services\FetchesBookingQuotation; +use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject; +use App\Classes\Modules\Remarks\DataTransferObjects\RemarkObject; +use App\Classes\Modules\Transactions\ControllersLogic\UpdateRefundTransactionStatusLogic; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionRefundCalculationObject; +use App\Classes\ValueObjects\Constants\PaymentMethodType; +use App\Classes\Modules\Remarks\Processors\CreateRemarkProcessor; class CreateBookingRefundLogic extends AbstractControllerLogic { @@ -48,8 +52,11 @@ class CreateBookingRefundLogic extends AbstractControllerLogic /** @var CreatesTransaction */ private $createsTransaction; - /** @var CalculatesBookingRefundAmount */ - private $calculatesBookingRefundAmount; + /** @var UpdateRefundTransactionStatusLogic */ + private $updateRefundTransactionStatusLogic; + + /** @var CreateRemarkProcessor */ + private $createRemarkProcessor; /** * CreateBookingPaymentLogic constructor. @@ -58,16 +65,18 @@ class CreateBookingRefundLogic extends AbstractControllerLogic * @param UpdatesTransactionStatus $updatesTransactionStatus * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber * @param CreatesTransaction $createsTransaction - * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount + * @param UpdateRefundTransactionStatusLogic $updateRefundTransactionStatusLogic + * @param CreateRemarkProcessor $createRemarkProcessor */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) + public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, UpdateRefundTransactionStatusLogic $updateRefundTransactionStatusLogic, CreateRemarkProcessor $createRemarkProcessor) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createsTransaction = $createsTransaction; - $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; + $this->updateRefundTransactionStatusLogic = $updateRefundTransactionStatusLogic; + $this->createRemarkProcessor = $createRemarkProcessor; } /** @@ -82,27 +91,98 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $booking = $transaction->owner; + $invoice = $booking->transactions()->where('type', TransactionType::INVOICE)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + + if(auth()->user()->type === 3) { + throw new MalformedRequestException('You do not have the permission to refund the order.'); + } + $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); - $refund = $transaction->transactions()->refunds()->sum('amount'); + $refund = $transaction->transactions()->refunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->sum('original_amount'); + + $refundInPending = $transaction->transactions()->refunds()->where('status', ApprovalStatus::PENDING_VERIFICATION)->sum('original_amount'); if($refund + $request->input('amount') > $transaction->original_amount) throw new MalformedRequestException('Your refund must not be greater than '. $transaction->original_amount .'.'); - $amount = $transaction->booking->fix_currency_id == 1 ? $request->input('amount') : $request->input('amount') / $transaction->currency_rate; + // $transactionRefundCalculationObject = new TransactionRefundCalculationObject($booking, $transaction, $request->input('amount')); + // $transactionRefundCalculationObject->init(); + if ((float)$request->input('amount') === (float)$transaction->original_amount) { + $refundAmount = $transaction->original_amount / $transaction->currency_rate; + $service_charges_to_refund = $transaction->service_charge; + } else { + $refundAmount = bcdiv($request->input('amount'), $transaction->currency_rate, 7); - $transactionRefundCalculationObject = new TransactionRefundCalculationObject($booking, $transaction, $amount); - $transactionRefundCalculationObject->init(); + $bookingAmountBeforeCurrentRefund = $booking->fix_amount - $refundInPending; + + $bookingAmountAfterRefunded = $booking->fix_amount - $refundInPending - $request->input('amount'); + + $isFullyRefund = ($refund + $request->input('amount')) == $transaction->original_amount; + + $voucherCode = null; + $redemptionId = null; + + if ($transaction->voucherRedemption) { + // $voucherCode = $transaction->voucherRedemption->voucher->code; + $redemptionId = $transaction->voucherRedemption->redemption_id; + } + + $conversionObjectBeforeCurrentRefund = new CurrencyConversionObject($bookingAmountBeforeCurrentRefund, $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, $transaction->payment_method); + + $conversionObjectAfterRefund = new CurrencyConversionObject($isFullyRefund ? $request->input('amount') : $bookingAmountAfterRefunded, $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, $transaction->payment_method); + + $quotationBeforeCurrentRefund = $this->fetchBookingQuotation->execute($booking->company, $conversionObjectBeforeCurrentRefund, $voucherCode, $redemptionId); + + $quotationAfterRefund = $this->fetchBookingQuotation->execute($booking->company, $conversionObjectAfterRefund, $voucherCode, $redemptionId); + + $service_charges_to_refund = $isFullyRefund ? $quotationBeforeCurrentRefund->getServiceCharge() : $quotationBeforeCurrentRefund->getServiceCharge() - $quotationAfterRefund->getServiceCharge(); + } + + // refund service charges if booking is not E2E + $refundTotal = $refundAmount; + + if ($booking->service_id !== 5) { + $refundTotal = $refundTotal + $service_charges_to_refund + $transaction->tax; + } else { + $service_charges_to_refund = 0; + } $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, - 1, $transactionRefundCalculationObject->getConversionObject()->getPaymentMethod(), - $transactionRefundCalculationObject->getRefundTotalAmount(), $transactionRefundCalculationObject->getAmount(), 1, - $transactionRefundCalculationObject->getConversionObject()->getCurrencyId(), $transactionRefundCalculationObject->getTransaction()->currency_rate, - $transactionRefundCalculationObject->getRefundTax(), $transactionRefundCalculationObject->getRefundServiceCharge(), null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); + 1, PaymentMethodType::CASH, + $refundTotal, $request->input('amount'), 1, + $transaction->original_currency_id, $transaction->currency_rate, + 0, $service_charges_to_refund, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); - $transaction = $this->createsTransaction->execute($transaction, $object); + $refund_transaction = $this->createsTransaction->execute($transaction, $object); - return $this->resourceResponse(new TransactionResource($transaction)); + $bookingInWhiteForm = $transaction->transactions()->bills()->first(); + + // create supplier refund + if ($bookingInWhiteForm) { + $billNumber = $this->generatesTransactionBillNumber->execute('SRFD-'); + $supplierRefundTotal = bcdiv($request->input('amount'), $bookingInWhiteForm->currency_rate, 7); + + $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_REFUND, 1, $bookingInWhiteForm->issuer, + 1, PaymentMethodType::CASH, + $supplierRefundTotal, $request->input('amount'), 1, + $transaction->original_currency_id, $bookingInWhiteForm->currency_rate, + 0, 0, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); + + $transaction = $this->createsTransaction->execute($transaction, $object); + } else { + $request->route()->setParameter('id', $refund_transaction->id); + $request->route()->setParameter('status', ApprovalStatus::APPROVED); + $this->updateRefundTransactionStatusLogic->execute($request); + + } + + if($request->input('refundRemark')){ + $remarkObject = new RemarkObject($request->input('refundRemark'), Auth()->user()->id); + $this->createRemarkProcessor->execute($this->fetchesTransaction->execute(['id' => $refund_transaction->id]), $remarkObject); + } + + return $this->resourceResponse(new TransactionResource($refund_transaction)); } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ExpireBookingPaymentControllerLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ExpireBookingPaymentControllerLogic.php index 8ee2bbfa..1b0a9ebb 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/ExpireBookingPaymentControllerLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/ExpireBookingPaymentControllerLogic.php @@ -45,7 +45,7 @@ class ExpireBookingPaymentControllerLogic extends AbstractControllerLogic $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); $payment = $booking->transactions() - ->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->payments()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) ->first(); $payment->status = ApprovalStatus::EXPIRED; diff --git a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php index d9857548..d1f2286e 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php @@ -18,7 +18,7 @@ class FetchBookingLogic extends AbstractControllerLogic */ protected function notification():array { return [ - 'title' => 'Retrieved Address', + 'title' => 'Retrieved Booking', 'message' => 'You have successfully retrieved a Address' ]; } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php index 8effdb2f..e9a42101 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php @@ -14,6 +14,7 @@ use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Models\Booking; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic { @@ -40,6 +41,9 @@ class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic /** @var CalculatesBookingOutstanding */ private $calculatesBookingOutstanding; + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + /** * FetchBookingPaymentQuotationLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -47,12 +51,13 @@ class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic * @param FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit * @param CalculatesBookingOutstanding $calculatesBookingOutstanding */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, GeneratesBookingQuotation $generatesBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, CalculatesBookingOutstanding $calculatesBookingOutstanding) + public function __construct(FetchesBookingQuotation $fetchBookingQuotation, GeneratesBookingQuotation $generatesBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, CalculatesBookingOutstanding $calculatesBookingOutstanding, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->generatesBookingQuotation = $generatesBookingQuotation; $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } /** @@ -66,7 +71,7 @@ class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $request->input('amount'))), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')]); - $outstanding = $this->calculatesBookingOutstanding->execute($booking); + $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '.$booking->fixedCurrency->short_code.' '. number_format((float)$outstanding, 2, '.', ',')); //Voucherify diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php new file mode 100644 index 00000000..ce7d5a85 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php @@ -0,0 +1,75 @@ + 'List Booking Job', + 'message' => 'You have successfully submit a job to list bookings' + ]; + } + + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListPackingListsJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $user = Auth::user(); + $userInfo = (object) [ + 'type' => $user->type, + ]; + + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $requestSignature, + null, + $jobId, + $userInfo + ); + + ListBookingsJob::dispatch($listGenericJobObject)->onQueue('high_priority'); + + $result = []; + $result['job_id'] = $jobId; + + $this->createsJobResult->execute($listGenericJobObject); + + return $this->response(['data' => $result]); + } + +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php index fabdd058..e40a947d 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php @@ -81,7 +81,7 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic $minimum_amount = $booking->fix_amount - $this->calculatesBookingOutstanding->execute($booking); - if ((float)$input_amount < $minimum_amount) { + if (((float)$input_amount + 0.01) < (float)$minimum_amount) { throw new MalformedRequestException('Booking Amount cannot be less than '. $minimum_amount .'.'); } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingOrderReferenceLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingOrderReferenceLogic.php new file mode 100644 index 00000000..ab096c69 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingOrderReferenceLogic.php @@ -0,0 +1,73 @@ + 'Updated Booking Order References', + 'message' => 'You have successfully updated the Booking Order References' + ]; + } + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** + * UpdateBookingOrderReferenceLogic constructor. + * @param FetchesBooking $fetchesBooking + */ + public function __construct(FetchesBooking $fetchesBooking) + { + $this->fetchesBooking = $fetchesBooking; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + if (!$request['order_reference_no']) { + throw new MalformedRequestException('At least 1 order reference required.'); + } + + if ($request['order_reference_no']) { + foreach ($request['order_reference_no'] as $index => $reference) { + if (!$reference) { + $index += 1; + throw new MalformedRequestException("Order reference {$index} cannot be empty"); + } + } + } + + $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); + $booking->modelAttributes()->delete(); + + foreach ($request['order_reference_no'] as $order_reference) { + $booking->modelAttributes()->create([ + 'name' => BookingAttributeNames::ORDER_REFERENCE_NO, + 'value' => $order_reference + ]); + } + + return $this->resourceResponse(new BookingResource($booking)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingRecipientLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingRecipientLogic.php new file mode 100644 index 00000000..8bdee9e3 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingRecipientLogic.php @@ -0,0 +1,94 @@ + 'Updated Booking', + 'message' => 'You have successfully updated the Booking' + ]; + } + + /** @var CanUpdateBooking */ + private $canUpdateBooking; + + /** @var UpdatesBooking */ + private $updatesBooking; + + /** @var FetchesBooking */ + private $fetchesBooking; + + + /** + * UpdateBookingRecipientLogic constructor. + * @param CanUpdateBooking $canUpdateBooking + * @param UpdatesBooking $updatesBooking + * @param FetchesBooking $fetchesBooking + */ + public function __construct( + CanUpdateBooking $canUpdateBooking, + UpdatesBooking $updatesBooking, + FetchesBooking $fetchesBooking + ) + { + $this->canUpdateBooking = $canUpdateBooking; + $this->updatesBooking = $updatesBooking; + $this->fetchesBooking = $fetchesBooking; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + try { + DB::beginTransaction(); + + $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); + + + $booking_object = new BookingObject( + $booking->service_id, + $request->input('transferable_bank_id', $booking->transferable_bank_id), + $booking->marking, + $booking->fix_amount, + $booking->fix_currency_id, + $booking->convertible_currency_id, + $booking->conversion_currency_id + ); + $this->canUpdateBooking->passes($booking_object); + $booking = $this->updatesBooking->execute($booking, $booking_object); + + DB::commit(); + + return $this->resourceResponse(new BookingResource($booking)); + + } catch (\Exception $exception){ + throw new ErrorException($exception->getMessage(), $exception->getCode()); + } + } + +} diff --git a/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php b/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php new file mode 100644 index 00000000..2a09eb12 --- /dev/null +++ b/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php @@ -0,0 +1,46 @@ +listsBookings = $listsBookings; + $this->updateJobResultProcessor = $updateJobResultProcessor; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsBookings->execute($this->listsBookings->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + foreach ($query->items() as &$item) { + $item['userInfo'] = $listGenericJobObject->getUserInfo(); + } + $resultCurrent = Helper::collectionResponse(ListBookingJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); + } +} diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php index da3fe0b4..9cb7717e 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php @@ -24,10 +24,22 @@ class CalculatesBookingCurrencyAverageRate public function execute(Booking $booking, $type){ + $transaction = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->latest()->get()[0]; + + $voucherRedemption = $transaction->voucherRedemption; + + $discount = 0; + + if ($voucherRedemption) { + $discount = $voucherRedemption->value; + } + if ($type == TransactionType::PAYMENT) { $totalPayment = $booking->fix_currency_id === 1 ? $booking->transactions()->payments()->complete()->sum('original_amount') : $booking->transactions()->payments()->complete()->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); - return $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) / $totalPayment; + return $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) / ($totalPayment + $discount); } else if ($type == TransactionType::BILL) { diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingOutstanding.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingOutstanding.php index 5f2c7733..f3a70a6a 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingOutstanding.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingOutstanding.php @@ -13,20 +13,25 @@ class CalculatesBookingOutstanding /** @var CalculatesBookingFloatingAmount */ private $calculatesBookingFloatingAmount; + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + /** * CalculatesBookingOutstanding constructor. * @param CalculatesBookingPayableAmount $calculatesBookingPayableAmount * @param CalculatesBookingFloatingAmount $calculatesBookingFloatingAmount + * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount */ - public function __construct(CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingFloatingAmount $calculatesBookingFloatingAmount) + public function __construct(CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingFloatingAmount $calculatesBookingFloatingAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount; $this->calculatesBookingFloatingAmount = $calculatesBookingFloatingAmount; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } public function execute(Booking $booking){ - return $booking->fix_amount - $this->calculatesBookingFloatingAmount->execute($booking, $booking->fix_currency_id) - $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id); + return $booking->fix_amount - $this->calculatesBookingFloatingAmount->execute($booking, $booking->fix_currency_id) - $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); } } \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php index 14a4a9ef..8792aaa6 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php @@ -2,19 +2,30 @@ namespace App\Classes\Modules\Bookings\Services; - use App\Classes\ValueObjects\Constants\ApprovalStatus; -use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\Booking; -use Carbon\Carbon; class CalculatesBookingRefundAmount { + public function execute(Booking $booking, int $type, ?string $payment_reference = null): float + { + $refundAmounts = $booking->transactions()->payments()->complete()->get()->map(function ($payment) use ($type) { + return $this->calculateRefundAmount($payment, $type); + }); - public function execute(Booking $booking, int $type, ?string $payment_reference = NULL){ - return $type === 1 ? - $booking->transactions()->refunds($payment_reference) - ->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total') : $booking->transactions()->refunds($payment_reference)->sum('original_amount'); + $totalRefundAmount = $refundAmounts->sum(); + + return $totalRefundAmount; } -} \ No newline at end of file + public function calculateRefundAmount($payment, int $type): float + { + $refundTransactions = $payment->transactions()->refunds()->whereIn('status', [ApprovalStatus::APPROVED]); + + if ($type === 1) { + return $refundTransactions->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); + } + + return $refundTransactions->sum('original_amount'); + } +} diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php index fc355d64..099d4571 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php @@ -13,7 +13,7 @@ class CalculatesBookingTransferredAmount public function execute(Booking $booking){ return $booking->transactions()->payments()->complete()->whereHas('transactions', function($query){ - return $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + return $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->where('type', TransactionType::BILL); })->sum('original_amount'); } diff --git a/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php b/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php index 5fe85c35..a1291207 100644 --- a/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php +++ b/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php @@ -11,8 +11,10 @@ use App\Classes\Modules\Vouchers\DataTransferObjects\ValidatedVoucherObject; use App\Classes\Modules\Vouchers\DataTransferObjects\ValidateVoucherifyVoucherObject; use App\Classes\Modules\Currencies\Services\FetchesCurrency; use App\Classes\Modules\Vouchers\Services\Voucherify\ValidatesVoucherifyVoucher; +use App\Classes\Modules\Vouchers\Services\Voucherify\FetchesVoucherifyRedemption; use App\Models\Company; use App\Models\Currency; +use Illuminate\Support\Facades\Log; class FetchesBookingQuotation { @@ -26,27 +28,34 @@ class FetchesBookingQuotation /** @var ValidatesVoucherifyVoucher */ private $validatesVoucherifyVoucher; + /** @var FetchesVoucherifyRedemption */ + private $fetchesVoucherifyRedemption; + /** * FetchesBookingQuotation constructor. * @param FetchesCompanyServiceSettings $fetchesCompanyServiceSettings * @param FetchesCurrency $fetchesCurrency + * @param ValidatesVoucherifyVoucher $validatesVoucherifyVoucher + * @param FetchesVoucherifyRedemption $fetchesVoucherifyRedemption */ - public function __construct(FetchesCompanyServiceSettings $fetchesCompanyServiceSettings, FetchesCurrency $fetchesCurrency, ValidatesVoucherifyVoucher $validatesVoucherifyVoucher) + public function __construct(FetchesCompanyServiceSettings $fetchesCompanyServiceSettings, FetchesCurrency $fetchesCurrency, ValidatesVoucherifyVoucher $validatesVoucherifyVoucher, FetchesVoucherifyRedemption $fetchesVoucherifyRedemption) { $this->fetchesCompanyServiceSettings = $fetchesCompanyServiceSettings; $this->fetchesCurrency = $fetchesCurrency; $this->validatesVoucherifyVoucher = $validatesVoucherifyVoucher; + $this->fetchesVoucherifyRedemption = $fetchesVoucherifyRedemption; } /** * @param Company $company * @param CurrencyConversionObject $conversionObject - * @param string $voucherCode + * @param null|string $voucherCode + * @param null|string $redemptionId * @return CalculationObject * @throws MalformedRequestException */ - public function execute(Company $company, CurrencyConversionObject $conversionObject, ?string $voucherCode = null){ + public function execute(Company $company, CurrencyConversionObject $conversionObject, ?string $voucherCode = null, ?string $redemptionId = null){ if($conversionObject->getAmount() <= 0) throw new MalformedRequestException('Your transfer must be greater than zero.'); $configurations = $this->fetchesCompanyServiceSettings->execute($company, $conversionObject); @@ -57,10 +66,30 @@ class FetchesBookingQuotation $calculationObject = new CalculationObject($conversionObject, $configurations, null); + $voucher = null; + //Voucherify if($voucherCode){ - $employee = $company->employees()->first(); - $validateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject($company->id, $voucherCode, $calculationObject->getSubTotal(), $employee); + $employeeWhoOwnsTheVoucher = null; + + $employees = $company->first()->employees; + if(count($employees) > 1){ + foreach($employees as $singleEmployee){ + $userRewards = $singleEmployee->rewards; + foreach($userRewards as $userReward){ + if ($userReward->voucher && $userReward->voucher->code === $voucherCode) { + Log::info('1. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $voucherCode); + $employeeWhoOwnsTheVoucher = $singleEmployee; + } + } + } + } + + if(!$employeeWhoOwnsTheVoucher){ + $employeeWhoOwnsTheVoucher = $company->employees()->first(); + } + + $validateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject($company->id, $voucherCode, $calculationObject->getSubTotal(), $employeeWhoOwnsTheVoucher); $result = $this->validatesVoucherifyVoucher->execute($validateVoucherifyVoucherObject); $voucher = [ "code" => $result->code, @@ -68,7 +97,24 @@ class FetchesBookingQuotation "metadata" => $result->metadata, "order" => $result->order, ]; - $validatedVoucherObject = new ValidatedVoucherObject(isset($voucher['metadata']->name) ? $voucher['metadata']->name: "", $voucher['code'], $voucher['discount']->type ?? 'AMOUNT', $voucher['order']->total_discount_amount, $voucher['order']->total_amount); + } + else if($redemptionId){ + $result = $this->fetchesVoucherifyRedemption->execute($redemptionId); + $voucher = [ + "code" => $result->voucher->code ?? null, + "discount" => null, + "metadata" => null, + "order" => $result->order ?? null, + ]; + } + + if($voucher){ + $validatedVoucherObject = new ValidatedVoucherObject( + isset($voucher['metadata']->name) ? $voucher['metadata']->name : "", + $voucher['code'], + $voucher['discount']->type ?? 'AMOUNT', + $voucher['order']->total_discount_amount, + $voucher['order']->total_amount); $calculationObject = new CalculationObject($conversionObject, $configurations, $validatedVoucherObject); } diff --git a/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php b/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php index 8ea1b88d..5c1ecdd9 100644 --- a/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php +++ b/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php @@ -19,7 +19,31 @@ class GeneratesBookingQuotation $hours = $date->diffInHours($date->copy()->addMinutes($paymentAttemptLimit)->subDays($days)) ; $minutes = $date->diffInMinutes($date->copy()->addMinutes($paymentAttemptLimit)->subDays($days)->subHours($hours)); - $receive_date = $currencyConversionObject ? Carbon::now()->endOfDay()->addWeekdays($currencyConversionObject->getServiceId() === 3 ? 3 : 1)->timezone('Asia/Singapore')->format('4:00 \P\M, jS M, Y \G\M\T T') : null; + // Initialize $receive_date to null by default + $receive_date = null; + + if ($currencyConversionObject) { + $serviceId = $currencyConversionObject->getServiceId(); + + switch ($serviceId) { + case 3: + $daysToAdd = 3; + break; + case 5: + $daysToAdd = 7; + break; + default: + $daysToAdd = 1; + break; + } + + $receive_date = Carbon::now() + ->endOfDay() + ->addWeekdays($daysToAdd) + ->timezone('Asia/Singapore') + ->format('4:00 \P\M, jS M, Y \G\M\T T'); + } + return [ 'bank' => new BankResource(Bank::find($calculationObject->getConfigurations()->getBankId())), diff --git a/app/Classes/Modules/Bookings/Standards/Rules/CanCreateBooking.php b/app/Classes/Modules/Bookings/Standards/Rules/CanCreateBooking.php index 7871acfe..0f8b7d0d 100644 --- a/app/Classes/Modules/Bookings/Standards/Rules/CanCreateBooking.php +++ b/app/Classes/Modules/Bookings/Standards/Rules/CanCreateBooking.php @@ -25,7 +25,7 @@ class CanCreateBooking extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; } diff --git a/app/Classes/Modules/Bookings/Standards/Rules/CanDeleteBooking.php b/app/Classes/Modules/Bookings/Standards/Rules/CanDeleteBooking.php index d1fcfe15..9ca591f6 100644 --- a/app/Classes/Modules/Bookings/Standards/Rules/CanDeleteBooking.php +++ b/app/Classes/Modules/Bookings/Standards/Rules/CanDeleteBooking.php @@ -11,7 +11,7 @@ class CanDeleteBooking extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules diff --git a/app/Classes/Modules/Bookings/Standards/Rules/CanFetchBooking.php b/app/Classes/Modules/Bookings/Standards/Rules/CanFetchBooking.php index c6f17684..0ac3f447 100644 --- a/app/Classes/Modules/Bookings/Standards/Rules/CanFetchBooking.php +++ b/app/Classes/Modules/Bookings/Standards/Rules/CanFetchBooking.php @@ -13,7 +13,7 @@ class CanFetchBooking extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Bookings/Standards/Rules/CanListBookings.php b/app/Classes/Modules/Bookings/Standards/Rules/CanListBookings.php index a66e9610..2147f321 100644 --- a/app/Classes/Modules/Bookings/Standards/Rules/CanListBookings.php +++ b/app/Classes/Modules/Bookings/Standards/Rules/CanListBookings.php @@ -12,7 +12,7 @@ class CanListBookings extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Bookings/Standards/Rules/CanMergeBooking.php b/app/Classes/Modules/Bookings/Standards/Rules/CanMergeBooking.php index f348346e..973b67d1 100644 --- a/app/Classes/Modules/Bookings/Standards/Rules/CanMergeBooking.php +++ b/app/Classes/Modules/Bookings/Standards/Rules/CanMergeBooking.php @@ -33,7 +33,7 @@ class CanMergeBooking extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; } diff --git a/app/Classes/Modules/Bookings/Standards/Rules/CanUpdateBooking.php b/app/Classes/Modules/Bookings/Standards/Rules/CanUpdateBooking.php index 7158a825..2433cefb 100644 --- a/app/Classes/Modules/Bookings/Standards/Rules/CanUpdateBooking.php +++ b/app/Classes/Modules/Bookings/Standards/Rules/CanUpdateBooking.php @@ -26,7 +26,7 @@ class CanUpdateBooking extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules diff --git a/app/Classes/Modules/Companies/Standards/Rules/CanAssignEmployee.php b/app/Classes/Modules/Companies/Standards/Rules/CanAssignEmployee.php index f34f83ff..79a2a696 100644 --- a/app/Classes/Modules/Companies/Standards/Rules/CanAssignEmployee.php +++ b/app/Classes/Modules/Companies/Standards/Rules/CanAssignEmployee.php @@ -26,7 +26,7 @@ class CanAssignEmployee extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Companies/Standards/Rules/CanAssignSegment.php b/app/Classes/Modules/Companies/Standards/Rules/CanAssignSegment.php index c6dab1d9..892e5d8e 100644 --- a/app/Classes/Modules/Companies/Standards/Rules/CanAssignSegment.php +++ b/app/Classes/Modules/Companies/Standards/Rules/CanAssignSegment.php @@ -24,7 +24,7 @@ class CanAssignSegment extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Companies/Standards/Rules/CanCreateCompany.php b/app/Classes/Modules/Companies/Standards/Rules/CanCreateCompany.php index 75015ff0..1b8a2115 100644 --- a/app/Classes/Modules/Companies/Standards/Rules/CanCreateCompany.php +++ b/app/Classes/Modules/Companies/Standards/Rules/CanCreateCompany.php @@ -24,7 +24,7 @@ class CanCreateCompany extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Companies/Standards/Rules/CanCreateIdentificationDocument.php b/app/Classes/Modules/Companies/Standards/Rules/CanCreateIdentificationDocument.php index 3182408a..eff63893 100644 --- a/app/Classes/Modules/Companies/Standards/Rules/CanCreateIdentificationDocument.php +++ b/app/Classes/Modules/Companies/Standards/Rules/CanCreateIdentificationDocument.php @@ -25,7 +25,7 @@ class CanCreateIdentificationDocument extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Companies/Standards/Rules/CanDeleteCompany.php b/app/Classes/Modules/Companies/Standards/Rules/CanDeleteCompany.php index b2621b4f..cb8dbadf 100644 --- a/app/Classes/Modules/Companies/Standards/Rules/CanDeleteCompany.php +++ b/app/Classes/Modules/Companies/Standards/Rules/CanDeleteCompany.php @@ -13,7 +13,7 @@ class CanDeleteCompany extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Companies/Standards/Rules/CanFetchCompany.php b/app/Classes/Modules/Companies/Standards/Rules/CanFetchCompany.php index 1d2bad1d..ca2c3e69 100644 --- a/app/Classes/Modules/Companies/Standards/Rules/CanFetchCompany.php +++ b/app/Classes/Modules/Companies/Standards/Rules/CanFetchCompany.php @@ -13,7 +13,7 @@ class CanFetchCompany extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Companies/Standards/Rules/CanListCompanies.php b/app/Classes/Modules/Companies/Standards/Rules/CanListCompanies.php index 35cd974c..3c268aa3 100644 --- a/app/Classes/Modules/Companies/Standards/Rules/CanListCompanies.php +++ b/app/Classes/Modules/Companies/Standards/Rules/CanListCompanies.php @@ -13,7 +13,7 @@ class CanListCompanies extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Companies/Standards/Rules/CanUpdateCompany.php b/app/Classes/Modules/Companies/Standards/Rules/CanUpdateCompany.php index c7bd1f70..06b41599 100644 --- a/app/Classes/Modules/Companies/Standards/Rules/CanUpdateCompany.php +++ b/app/Classes/Modules/Companies/Standards/Rules/CanUpdateCompany.php @@ -24,7 +24,7 @@ class CanUpdateCompany extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Contacts/Standards/Rules/CanCreateContact.php b/app/Classes/Modules/Contacts/Standards/Rules/CanCreateContact.php index 9c739feb..dca4874d 100644 --- a/app/Classes/Modules/Contacts/Standards/Rules/CanCreateContact.php +++ b/app/Classes/Modules/Contacts/Standards/Rules/CanCreateContact.php @@ -26,7 +26,7 @@ class CanCreateContact extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Currencies/Standards/Rules/CanCreateCurrency.php b/app/Classes/Modules/Currencies/Standards/Rules/CanCreateCurrency.php index 873e03ce..1fb7b52e 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/CanCreateCurrency.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/CanCreateCurrency.php @@ -24,7 +24,7 @@ class CanCreateCurrency extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Currencies/Standards/Rules/CanDeleteCurrency.php b/app/Classes/Modules/Currencies/Standards/Rules/CanDeleteCurrency.php index 60820e79..cbd666ab 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/CanDeleteCurrency.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/CanDeleteCurrency.php @@ -10,7 +10,7 @@ class CanDeleteCurrency extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Currencies/Standards/Rules/CanFetchCurrency.php b/app/Classes/Modules/Currencies/Standards/Rules/CanFetchCurrency.php index 624809ed..1911c901 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/CanFetchCurrency.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/CanFetchCurrency.php @@ -10,7 +10,7 @@ class CanFetchCurrency extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Currencies/Standards/Rules/CanListCurrency.php b/app/Classes/Modules/Currencies/Standards/Rules/CanListCurrency.php index 38a74f65..e7bde1c1 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/CanListCurrency.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/CanListCurrency.php @@ -10,7 +10,7 @@ class CanListCurrency extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules diff --git a/app/Classes/Modules/Currencies/Standards/Rules/CanUpdateCurrency.php b/app/Classes/Modules/Currencies/Standards/Rules/CanUpdateCurrency.php index d7e2ca93..7d098f7b 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/CanUpdateCurrency.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/CanUpdateCurrency.php @@ -26,7 +26,7 @@ class CanUpdateCurrency extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanCreateRate.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanCreateRate.php index cf63f89c..69c2110b 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanCreateRate.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanCreateRate.php @@ -25,7 +25,7 @@ class CanCreateRate extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules if (!Auth::user()->can('add currency_rate')) { diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanDeleteRate.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanDeleteRate.php index 37fff506..cfc2b769 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanDeleteRate.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanDeleteRate.php @@ -11,7 +11,7 @@ class CanDeleteRate extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanFetchRate.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanFetchRate.php index 4006e36f..0d6457fe 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanFetchRate.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanFetchRate.php @@ -13,7 +13,7 @@ class CanFetchRate extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanListRates.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanListRates.php index bd49c263..b06950cb 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanListRates.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanListRates.php @@ -11,7 +11,7 @@ class CanListRates extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanUpdateRate.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanUpdateRate.php index 8a153c54..c777b0af 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanUpdateRate.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanUpdateRate.php @@ -26,7 +26,7 @@ class CanUpdateRate extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules diff --git a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php new file mode 100644 index 00000000..f803494a --- /dev/null +++ b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php @@ -0,0 +1,75 @@ + 'List Document Job', + 'message' => 'You have successfully submit a job to list documents' + ]; + } + + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListDocumentJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $user = Auth::user(); + $userInfo = (object) [ + 'email' => $user->email, + 'type' => $user->type, + ]; + + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $requestSignature, + null, + $jobId, + $userInfo + ); + + ListDocumentsJob::dispatch($listGenericJobObject)->onQueue('high_priority'); + + $result = []; + $result['job_id'] = $jobId; + + $this->createsJobResult->execute($listGenericJobObject); + + return $this->response(['data' => $result]); + } +} diff --git a/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php b/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php new file mode 100644 index 00000000..70777f0c --- /dev/null +++ b/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php @@ -0,0 +1,47 @@ +listsDocuments = $listsDocuments; + $this->updateJobResultProcessor = $updateJobResultProcessor; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsDocuments->execute($this->listsDocuments->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + foreach ($query->items() as &$item) { + $item['userInfo'] = $listGenericJobObject->getUserInfo(); + } + $resultCurrent = Helper::collectionResponse(ListDocumentJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); + } +} + diff --git a/app/Classes/Modules/Documents/Standards/Rules/CanApproveDocument.php b/app/Classes/Modules/Documents/Standards/Rules/CanApproveDocument.php index 544b605c..66d75000 100644 --- a/app/Classes/Modules/Documents/Standards/Rules/CanApproveDocument.php +++ b/app/Classes/Modules/Documents/Standards/Rules/CanApproveDocument.php @@ -12,7 +12,7 @@ class CanApproveDocument extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Documents/Standards/Rules/CanCreateDocument.php b/app/Classes/Modules/Documents/Standards/Rules/CanCreateDocument.php index abac99e3..862f79f4 100644 --- a/app/Classes/Modules/Documents/Standards/Rules/CanCreateDocument.php +++ b/app/Classes/Modules/Documents/Standards/Rules/CanCreateDocument.php @@ -25,7 +25,7 @@ class CanCreateDocument extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Documents/Standards/Rules/CanCreateFile.php b/app/Classes/Modules/Documents/Standards/Rules/CanCreateFile.php index d029cf2a..6016b65e 100644 --- a/app/Classes/Modules/Documents/Standards/Rules/CanCreateFile.php +++ b/app/Classes/Modules/Documents/Standards/Rules/CanCreateFile.php @@ -25,7 +25,7 @@ class CanCreateFile extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Documents/Standards/Rules/CanDeleteDocument.php b/app/Classes/Modules/Documents/Standards/Rules/CanDeleteDocument.php index e5bc4891..94d88ee8 100644 --- a/app/Classes/Modules/Documents/Standards/Rules/CanDeleteDocument.php +++ b/app/Classes/Modules/Documents/Standards/Rules/CanDeleteDocument.php @@ -12,7 +12,7 @@ class CanDeleteDocument extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Documents/Standards/Rules/CanListDocuments.php b/app/Classes/Modules/Documents/Standards/Rules/CanListDocuments.php index f5145df6..ab2806df 100644 --- a/app/Classes/Modules/Documents/Standards/Rules/CanListDocuments.php +++ b/app/Classes/Modules/Documents/Standards/Rules/CanListDocuments.php @@ -10,7 +10,7 @@ class CanListDocuments extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { /* diff --git a/app/Classes/Modules/Documents/Standards/Rules/CanRenderDocument.php b/app/Classes/Modules/Documents/Standards/Rules/CanRenderDocument.php index 0275d6f9..c01f2143 100644 --- a/app/Classes/Modules/Documents/Standards/Rules/CanRenderDocument.php +++ b/app/Classes/Modules/Documents/Standards/Rules/CanRenderDocument.php @@ -10,7 +10,7 @@ class CanRenderDocument extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Documents/Standards/Rules/CanUpdateDocument.php b/app/Classes/Modules/Documents/Standards/Rules/CanUpdateDocument.php index f07fb166..8171cb95 100644 --- a/app/Classes/Modules/Documents/Standards/Rules/CanUpdateDocument.php +++ b/app/Classes/Modules/Documents/Standards/Rules/CanUpdateDocument.php @@ -25,7 +25,7 @@ class CanUpdateDocument extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Documents/Standards/Rules/CanUpdateDocumentReference.php b/app/Classes/Modules/Documents/Standards/Rules/CanUpdateDocumentReference.php index e6a29785..5feb6e1c 100644 --- a/app/Classes/Modules/Documents/Standards/Rules/CanUpdateDocumentReference.php +++ b/app/Classes/Modules/Documents/Standards/Rules/CanUpdateDocumentReference.php @@ -11,7 +11,7 @@ class CanUpdateDocumentReference extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Exports/Services/ExportCurrencyVendorOrder.php b/app/Classes/Modules/Exports/Services/ExportCurrencyVendorOrder.php new file mode 100644 index 00000000..2d3a79f9 --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportCurrencyVendorOrder.php @@ -0,0 +1,44 @@ +request = $request; + } + + public function view(): View + { + $id = $this->request->route('id'); + + $group = Group::findOrFail($id); + + $supplier = $group->issuerCompany; + + $transferFeeTransactions = $group->transactions()->with([ + 'transactions' => function ($transaction) { + return $transaction->where('type', TransactionType::TRANSFER_FEE); + } + ])->get()->pluck('transactions')->flatten(); + + return view('pages.pdfs.currency_vendor_order_inner', [ + 'transactions' => $group->transactions, + 'transferFeeTransactions' => $transferFeeTransactions, + 'supplier' => $supplier + ]); + } +} diff --git a/app/Classes/Modules/Exports/Services/ExportsAnalyticBillingTransactions.php b/app/Classes/Modules/Exports/Services/ExportsAnalyticBillingTransactions.php index af4c88c4..d368574f 100644 --- a/app/Classes/Modules/Exports/Services/ExportsAnalyticBillingTransactions.php +++ b/app/Classes/Modules/Exports/Services/ExportsAnalyticBillingTransactions.php @@ -65,8 +65,12 @@ class ExportsAnalyticBillingTransactions implements FromCollection, WithHeadings $bill = $transaction; $payment = $transaction->owner; $booking = $payment->owner; + $bank = $booking->bank; //cief todo: 66 + if($payment->bank){ + $bank = $payment->bank; + } $company = $booking->company; - $ecommerce = str::contains($booking->bank->bank_name, ['浙江网商银行']); + $ecommerce = str::contains($bank->bank_name, ['浙江网商银行']); return [ $booking->id, @@ -88,4 +92,4 @@ class ExportsAnalyticBillingTransactions implements FromCollection, WithHeadings $bill->created_at ]; } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Exports/Services/ExportsImportedInvoiceMappeds.php b/app/Classes/Modules/Exports/Services/ExportsImportedInvoiceMappeds.php index e629675f..ead22543 100644 --- a/app/Classes/Modules/Exports/Services/ExportsImportedInvoiceMappeds.php +++ b/app/Classes/Modules/Exports/Services/ExportsImportedInvoiceMappeds.php @@ -59,7 +59,6 @@ class ExportsImportedInvoiceMappeds implements FromQuery, WithHeadings, WithHead */ public function map($transaction): array { - // dd($transaction); $this->count += 1; $data = $transaction->data; return [ diff --git a/app/Classes/Modules/Exports/Services/ExportsImportedReceiptMappeds.php b/app/Classes/Modules/Exports/Services/ExportsImportedReceiptMappeds.php new file mode 100644 index 00000000..efe95fd3 --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsImportedReceiptMappeds.php @@ -0,0 +1,86 @@ +dateTime = $request->input('date').' '.$request->input('time'); + $this->count = 0; + } + + public function headings(): array + { + return [ + 'Check', + 'Doc No', + 'Doc Date', + 'Debtor Code', + 'Company Name', + 'Description', + 'Payment Amount', + 'Created User', + 'Curr.', + 'To Home Rate', + 'Local Payment Amount', + 'Cancelled', + 'Mapped Status', + 'Mapped Reference No', + ]; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + return TransactionMappingLog::where('imported_date', $this->dateTime); + } + + /** + * @param Transaction $transaction + * + * @return array + */ + public function map($transaction): array + { + $this->count += 1; + $data = $transaction->data; + return [ + $this->count, + Arr::get($data,'doc_no'), + Arr::get($data,'doc_date'), + Arr::get($data,'debtor_code'), + Arr::get($data,'company_name'), + Arr::get($data,'description'), + Arr::get($data,'payment_amount'), + Arr::get($data,'created_user'), + Arr::get($data,'curr'), + Arr::get($data,'to_home_rate'), + Arr::get($data,'local_payment_amount'), + Arr::get($data,'cancelled'), + Arr::get($data,'2nd_doc_no'), + Arr::get($data,'mapped_status'), + Arr::get($data,'mapped_result_reference'), + ]; + + } +} diff --git a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php index a7041b1c..85df0be8 100644 --- a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php +++ b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php @@ -108,13 +108,13 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading '500-0000', 'CIEF' ]; - } else { + } elseif ($statementTransactionOwner->owner_id) { $row = (App()->make(ListShippingPortalTransactions::class))->execute([ 'id' => $statementTransactionOwner->owner_id, 'with_company' => true, ]); - if (empty($row) || $row[0]['status'] != 'success') { + if (!empty($row) && $row[0]['status'] == 'success') { $textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Fetch Shipping Transaction Fail ' . json_encode([ 'id' => $statementTransactionOwner->owner_id, 'with_company' => true, @@ -125,46 +125,46 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading $textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Shipping Portal Respnose ' . json_encode($row) . PHP_EOL; file_put_contents($errorFilePath, $textToAppend, FILE_APPEND); - Log::info('Error in Exports Invoice Transactions ' . $this->counter); + $row = $row[0]; return [ - 'Transaction Not Found', - $transaction->posting_date->format('m/d/Y H:m'), - $transaction->transaction_description.' - '.$transaction->transaction_description_2, - $statementTransactionOwner->system, + '<>', + Carbon::parse($row['created_at'])->format('m/d/Y H:m'), + $row['debtor_code'], + $row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['marking'], '', + 'MYR', + $row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['bill_no'], + $row['type'] === ShippingTransactionType::PAYMENT ? '' : 'W1', + $row['type'] === ShippingTransactionType::PAYMENT ? 'PLEASE REFER TO THE ATTACHED APPENDIX REF `' . $row['order_reference'] : 'CREDIT SALES', '', - '', - '', - '', - '', - 0, - $transaction->amount, - '', - '', - '', - '' + 1, + round($row['amount'], 2), + '500-0000', + 'CIEF' ]; + } - - $row = $row[0]; - - return [ - '<>', - Carbon::parse($row['updated_at'])->format('m/d/Y H:m'), - $row['debtor_code'], - $row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['marking'], - '', - 'MYR', - $row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['bill_no'], - $row['type'] === ShippingTransactionType::PAYMENT ? '' : 'W1', - $row['type'] === ShippingTransactionType::PAYMENT ? 'PLEASE REFER TO THE ATTACHED APPENDIX REF `' . $row['order_reference'] : 'CREDIT SALES', - '', - 1, - round($row['amount'], 2), - '500-0000', - 'CIEF' - ]; } + + return [ + 'Transaction Not Found', + $transaction->posting_date->format('m/d/Y H:m'), + $transaction->transaction_description.' - '.$transaction->transaction_description_2, + $statementTransactionOwner->system, + '', + '', + '', + '', + '', + '', + 0, + $transaction->amount, + '', + '', + '', + '' + ]; } + } diff --git a/app/Classes/Modules/Exports/Services/ExportsWhiteFormTransactions.php b/app/Classes/Modules/Exports/Services/ExportsWhiteFormTransactions.php new file mode 100644 index 00000000..78579fc1 --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsWhiteFormTransactions.php @@ -0,0 +1,99 @@ +request = $request; + } + + public function headings(): array + { + return [ + 'Bank Name', + 'Bank Details', + 'Bank Acc No.', + 'Order amount', + 'Booking Reference', + ]; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + $start_date = $this->request->input('startDate', null); + if ($start_date) { + $start_date = Carbon::parse($this->request->input('startDate'))->format('Y-m-d'); + } + + $end_date = $this->request->input('endDate', null); + if ($end_date) { + $end_date = Carbon::parse($this->request->input('endDate'))->format('Y-m-d'); + } + + $query = Group::query(); + + // todo-new: confirm this + // $query->where('type', ::PAYMENT)->where('payment_method', '!=', PaymentMethodType::WALLET); + // $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + + if ($start_date && $end_date) { + $query->whereBetween('created_at', [ + Carbon::parse($start_date)->format('Y-m-d 0:00:00'), + Carbon::parse($end_date)->format('Y-m-d 23:59:59') + ]); + } elseif ($start_date && !$end_date) { + $query->where('created_at', '>=', Carbon::parse($start_date)->format('Y-m-d 0:00:00')); + } elseif (!$start_date && $end_date) { + $query->where('created_at', '<=', Carbon::parse($end_date)->format('Y-m-d 23:59:59')); + } + + return $query; + } + + /** + * @param Company $group + * + * @return array + */ + public function map($group): array + { + $supplier = $group->issuerCompany; + $supplerBank = $supplier->banks->first(); + + $bank_name = $supplerBank->bank_name; + $holder_name = $supplerBank->holder_name; + $account_no = $supplerBank->account_no; + + $bookingReference = $group->transactions()->get()->pluck('owner.owner.marking')->toArray(); + + return [ + $bank_name, + $holder_name, + $account_no, + $group->amount, + implode(",", $bookingReference) + ]; + } +} diff --git a/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php new file mode 100644 index 00000000..c4b72cf0 --- /dev/null +++ b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php @@ -0,0 +1,51 @@ + 'Retrieved Data', + 'message' => 'You have successfully retrieved data' + ]; + } + + /** @var FetchesJobResultProcessor */ + private $fetchesJobResultProcessor; + + /** + * FetchJobResultLogic constructor. + * @param FetchesJobResultProcessor $fetchesJobResultProcessor + */ + public function __construct(FetchesJobResultProcessor $fetchesJobResultProcessor) + { + $this->fetchesJobResultProcessor = $fetchesJobResultProcessor; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + $query = $this->fetchesJobResultProcessor->execute($request); + return $this->resourceResponse(new JobResultResource($query)); + } + +} diff --git a/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php b/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php new file mode 100644 index 00000000..953d77d7 --- /dev/null +++ b/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php @@ -0,0 +1,118 @@ +name = $name; + $this->payload = $payload; + $this->jobId = $jobId; + $this->requestSignature = $requestSignature; + $this->resultSignature = $resultSignature; + $this->userInfo = $userInfo; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return array + */ + public function getPayload(): array + { + return $this->payload; + } + + /** + * @return string + */ + public function getJobId(): string + { + return $this->jobId; + } + + /** + * @return string + */ + public function getRequestSignature(): string + { + return $this->requestSignature; + } + + /** + * @return string + */ + public function getResultSignature(): ?string + { + return $this->resultSignature; + } + + /** + * @return object + */ + public function getUserInfo(): object + { + return $this->userInfo; + } + + /** + * @return string + */ + public function getJobCommandName(): string + { + return $this->jobCommandName; + } + + /** + * @return string + */ + public function getJobCommand(): string + { + return $this->jobCommand; + } + + + public function setJobCommandName(string $jobCommandName) + { + $this->jobCommandName = $jobCommandName; + } + + public function setJobCommand(string $jobCommand) + { + $this->jobCommand = $jobCommand; + } + +} diff --git a/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php b/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php new file mode 100644 index 00000000..636c56b0 --- /dev/null +++ b/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php @@ -0,0 +1,60 @@ +result = $result; + $this->resultSignature = $resultSignature; + $this->jobCommandName = $jobCommandName; + $this->jobCommand = $jobCommand; + } + + /** + * @return string + */ + public function getResult(): string + { + return $this->result; + } + + /** + * @return array + */ + public function getResultSignature(): string + { + return $this->resultSignature; + } + + /** + * @return string + */ + public function getJobCommandName(): string + { + return $this->jobCommandName; + } + + /** + * @return string + */ + public function getJobCommand(): string + { + return $this->jobCommand; + } +} diff --git a/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php new file mode 100644 index 00000000..89783fe8 --- /dev/null +++ b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php @@ -0,0 +1,47 @@ +fetchesJobResult = $fetchesJobResult; + } + + + /** + * @param Request $request + * @return Model + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + * @throws \App\Classes\Exceptions\ResourceNotFoundException + */ + public function execute(Request $request){ + + $res1 = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]); + if($request->route('is_last')){ + $res2 = $this->fetchesJobResult->execute(['request_signature' => $res1->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); + return $res2; + } + + if(!$res1->result){ + throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided'); + } + + return $res1; + } +} diff --git a/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php new file mode 100644 index 00000000..0106417d --- /dev/null +++ b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php @@ -0,0 +1,64 @@ +fetchesJobResult = $fetchesJobResult; + $this->updatesJobResult = $updatesJobResult; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @param array $resultCurrent + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject, $resultCurrent) { + $jobResultCurrent = $this->fetchesJobResult->execute(['job_id' => $listGenericJobObject->getJobId()]); + $resultCurrentJson = json_encode($resultCurrent); + $resultSignatureCurrent = md5($resultCurrentJson); + + try{ + $jobResultExisting = $this->fetchesJobResult->execute(['request_signature' => $jobResultCurrent->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); + $resultSignatureExisting = $jobResultExisting->result_signature; + //if($resultSignatureExisting != $resultSignatureCurrent){ + $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); + //} + } catch (JobResourceNotFoundException $exception){ + $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); + } + } + + private function updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $jobCommandName, $jobCommand){ + $updateJobResultObject = new UpdateJobResultObject( + $resultCurrentJson, + $resultSignatureCurrent, + $jobCommandName, + $jobCommand + ); + $create = $this->updatesJobResult->execute($jobResultCurrent, $updateJobResultObject); + } +} diff --git a/app/Classes/Modules/Jobs/Services/CreatesJobResult.php b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php new file mode 100644 index 00000000..e70e0e6a --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php @@ -0,0 +1,26 @@ +job_id = $listGenericJobObject->getJobId(); + $model->request_signature = $listGenericJobObject->getRequestSignature(); + $model->result_signature = $listGenericJobObject->getResultSignature(); + $model->url = $listGenericJobObject->getName(); + + return $this->handler($model); + } +} diff --git a/app/Classes/Modules/Jobs/Services/FetchesJobResult.php b/app/Classes/Modules/Jobs/Services/FetchesJobResult.php new file mode 100644 index 00000000..1cc99cb6 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/FetchesJobResult.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Jobs/Services/ListsJobResult.php b/app/Classes/Modules/Jobs/Services/ListsJobResult.php new file mode 100644 index 00000000..55f3b267 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/ListsJobResult.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php b/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php new file mode 100644 index 00000000..ab3d9385 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php @@ -0,0 +1,28 @@ +result = $updateJobResultObject->getResult(); + $model->result_signature = $updateJobResultObject->getResultSignature(); + $model->job_command_name = $updateJobResultObject->getJobCommandName(); + $model->job_command = $updateJobResultObject->getJobCommand(); + + return $this->handler($model); + + } +} diff --git a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php index 597fa8bc..23eb27b3 100644 --- a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php +++ b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php @@ -149,7 +149,7 @@ class CheckMilestonesForRewardProcessor $voucherEndDate = $result->expiration_date; //create voucher - $voucherObject = new VoucherObject($result->code, isset($voucherName) ? $voucherName : "", $voucherType, $voucherValue, $voucherStartDate, $voucherEndDate); + $voucherObject = new VoucherObject($result->code, isset($voucherName) ? $voucherName : "", null, $voucherType, $voucherValue, null, $voucherStartDate, $voucherEndDate); $voucher = $this->createsVoucher->execute($voucherObject); if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); $voucherId = $voucher->id; diff --git a/app/Classes/Modules/Milestones/Standards/Rules/CanAssignReward.php b/app/Classes/Modules/Milestones/Standards/Rules/CanAssignReward.php index 35e8b31d..464f5f55 100644 --- a/app/Classes/Modules/Milestones/Standards/Rules/CanAssignReward.php +++ b/app/Classes/Modules/Milestones/Standards/Rules/CanAssignReward.php @@ -27,7 +27,7 @@ class CanAssignReward extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { if (!Auth::user()->can('edit milestone')) { return false; diff --git a/app/Classes/Modules/Milestones/Standards/Rules/CanCreateMilestone.php b/app/Classes/Modules/Milestones/Standards/Rules/CanCreateMilestone.php index be25b64f..7b63a3ef 100644 --- a/app/Classes/Modules/Milestones/Standards/Rules/CanCreateMilestone.php +++ b/app/Classes/Modules/Milestones/Standards/Rules/CanCreateMilestone.php @@ -25,7 +25,7 @@ class CanCreateMilestone extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { if (!Auth::user()->can('add milestone')) { return false; diff --git a/app/Classes/Modules/Milestones/Standards/Rules/CanDeleteMilestone.php b/app/Classes/Modules/Milestones/Standards/Rules/CanDeleteMilestone.php index c0c7fde7..2869d10f 100644 --- a/app/Classes/Modules/Milestones/Standards/Rules/CanDeleteMilestone.php +++ b/app/Classes/Modules/Milestones/Standards/Rules/CanDeleteMilestone.php @@ -11,7 +11,7 @@ class CanDeleteMilestone extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { if (!Auth::user()->can('delete milestone')) { return false; diff --git a/app/Classes/Modules/Milestones/Standards/Rules/CanUpdateMilestone.php b/app/Classes/Modules/Milestones/Standards/Rules/CanUpdateMilestone.php index 9f7db714..62b4df95 100644 --- a/app/Classes/Modules/Milestones/Standards/Rules/CanUpdateMilestone.php +++ b/app/Classes/Modules/Milestones/Standards/Rules/CanUpdateMilestone.php @@ -25,7 +25,7 @@ class CanUpdateMilestone extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { if (!Auth::user()->can('edit milestone')) { return false; diff --git a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php index 4edb2ef5..dae44588 100644 --- a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php +++ b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php @@ -108,12 +108,12 @@ class CreatePerfexCRMInvoiceProcessor $email = null; if ($firstSupplier) { $email = $firstSupplier->email; - Log::error('CreatePerfexCRMInvoiceProcessor debug:'.$email); + Log::channel('perfex_crm')->info('CreatePerfexCRMInvoiceProcessor debug:'.$email); } else { $bookingMarking = $transaction->owner->marking; $serviceTypeName = $transaction->owner->company->services()->where('id', $transaction->owner->service_id)->first()->name; $projectName = 'Exchange | '.$serviceTypeName.' | '.$bookingMarking; - Log::error('$projectName: '.$projectName); + Log::channel('perfex_crm')->info('$projectName: '.$projectName); return $email; } diff --git a/app/Classes/Modules/PerfexCRM/Processors/FetchPerfexCRMInvoiceProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/FetchPerfexCRMInvoiceProcessor.php index 4c8ee9bf..c073fb7a 100644 --- a/app/Classes/Modules/PerfexCRM/Processors/FetchPerfexCRMInvoiceProcessor.php +++ b/app/Classes/Modules/PerfexCRM/Processors/FetchPerfexCRMInvoiceProcessor.php @@ -62,7 +62,7 @@ class FetchPerfexCRMInvoiceProcessor $invoiceId = $result->payload['id']; } else { $log['message'] = 'FetchPerfexCRMInvoiceProcessor failed for transaction > bill_no: '.$number; - Helper::debugLogger($log); + Log::channel('perfex_crm')->info($log); } } else{ diff --git a/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php index fbf64be8..ac422c33 100644 --- a/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php +++ b/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php @@ -217,8 +217,8 @@ class UpdatePerfexCRMProcessor } $result = $this->fetchesPerfexCRMTask->execute($taskName, $milestoneId, 'project', $projectId, $updatePerfexCRMObject->getInvoiceId()); - // Log::error("UpdatePerfexCRMProcessor task: ".$taskName." , ".json_encode($result)); - Log::error("UpdatePerfexCRMProcessor task: ".$taskName); + // Log::channel('perfex_crm')->info("UpdatePerfexCRMProcessor task: ".$taskName." , ".json_encode($result)); + Log::channel('perfex_crm')->info("UpdatePerfexCRMProcessor task: ".$taskName); if(isset($result->payload)){ //&& $result->payload[0]['status'] == PerfexCRMTaskStatus::NOT_STARTED diff --git a/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php b/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php index e6e7323e..92e90a52 100644 --- a/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php @@ -24,7 +24,7 @@ class ConvertsPerfexCRMLeadToCustomer return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php index e5a19ce3..b7eabaa7 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php @@ -27,7 +27,7 @@ class CreatesPerfexCRMCustomer $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php index 519c1495..12d3d7e8 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php @@ -34,7 +34,7 @@ class CreatesPerfexCRMCustomerContact $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php index f5d4de3e..1f513f31 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php @@ -33,7 +33,7 @@ class CreatesPerfexCRMCustomerProject $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php index ba0c2755..df952c4b 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php @@ -53,7 +53,7 @@ class CreatesPerfexCRMInvoice $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php index f3e92529..64590232 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php @@ -33,7 +33,7 @@ class CreatesPerfexCRMInvoicePayment $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php index 373f4171..5ecef6e7 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php @@ -40,7 +40,7 @@ class CreatesPerfexCRMLead $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php index 80cb49bf..91afd314 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php @@ -36,7 +36,7 @@ class CreatesPerfexCRMMilestone $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php index feb8f9c8..45105fa9 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php @@ -56,7 +56,7 @@ class CreatesPerfexCRMTask $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php index 9f3928f6..6efebec4 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php @@ -24,7 +24,7 @@ class FetchesPerfexCRMCustomer return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php index cd7aff30..7946cfec 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php @@ -26,7 +26,7 @@ class FetchesPerfexCRMInvoice return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php index df9c754d..a3543b20 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php @@ -24,7 +24,7 @@ class FetchesPerfexCRMLead return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php index 30ae0737..9c482fe7 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php @@ -30,7 +30,7 @@ class FetchesPerfexCRMMilestone return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php index c55f2c01..ce9762d8 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php @@ -30,7 +30,7 @@ class FetchesPerfexCRMProject return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php index 6cd4f052..0ab2b0fd 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php @@ -44,7 +44,7 @@ class FetchesPerfexCRMTask return (object) $data; }else{ - Helper::debugLogger($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php index 6d91c081..15963c31 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php @@ -38,7 +38,7 @@ class UpdatesPerfexCRMCustomer $data = $response->json(); return (object) $data; }else{ - Helper::debugLogger($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php index 9adb9460..9825dde2 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php @@ -60,7 +60,7 @@ class UpdatesPerfexCRMInvoice $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php index f8fbc944..69ac7fa8 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php @@ -41,7 +41,7 @@ class UpdatesPerfexCRMLead $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php index cf782806..4b65347e 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php @@ -33,7 +33,7 @@ class UpdatesPerfexCRMProject $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php index 95a09525..053fa16d 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php @@ -40,7 +40,7 @@ class UpdatesPerfexCRMTask $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/Receipts/Standards/Rules/CanCreateReceipt.php b/app/Classes/Modules/Receipts/Standards/Rules/CanCreateReceipt.php index ea6b4f02..37d24609 100644 --- a/app/Classes/Modules/Receipts/Standards/Rules/CanCreateReceipt.php +++ b/app/Classes/Modules/Receipts/Standards/Rules/CanCreateReceipt.php @@ -23,7 +23,7 @@ class CanCreateReceipt extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Receipts/Standards/Rules/CanCreateReceiptDetail.php b/app/Classes/Modules/Receipts/Standards/Rules/CanCreateReceiptDetail.php index 71466752..4c38c481 100644 --- a/app/Classes/Modules/Receipts/Standards/Rules/CanCreateReceiptDetail.php +++ b/app/Classes/Modules/Receipts/Standards/Rules/CanCreateReceiptDetail.php @@ -23,7 +23,7 @@ class CanCreateReceiptDetail extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php new file mode 100644 index 00000000..46d822c5 --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php @@ -0,0 +1,62 @@ + 'Created Remark', + 'message' => 'You have successfully created a new Remark' + ]; + } + + /** @var CreateRemarkProcessor */ + private $createRemarkProcessor; + + /** + * CreateRemarkLogic constructor. + * @param CreateRemarkProcessor $createRemarkProcessor + */ + public function __construct(CreateRemarkProcessor $createRemarkProcessor) + { + $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 + { + $classs = '\\App\\Models\\' . Str::studly($request->input('model_type')); + + if (!class_exists($classs)) { + throw new MalformedRequestException('Unable to process this entity'); + } + + $remarkOwner = $classs::find($request->route('id')); + + $remarkObject = new RemarkObject($request->input('content'), auth()->user()->id); + + $remmark = $this->createRemarkProcessor->execute($remarkOwner, $remarkObject); + + return $this->resourceResponse(new RemarkResource($remmark)); + } +} diff --git a/app/Classes/Modules/Remarks/ControllersLogic/DeleteRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/DeleteRemarkLogic.php new file mode 100644 index 00000000..b593d603 --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/DeleteRemarkLogic.php @@ -0,0 +1,66 @@ + 'Deleted Remark', + 'message' => 'You have successfully deleted a Remark' + ]; + } + + + /** @var CanDeleteRemark */ + private $canDeleteRemark; + + /** @var DeletesRemark */ + private $deletesRemark; + + /** @var FetchesRemark */ + private $fetchesRemark; + + /** + * DeleteRemarkControllersLogic constructor. + * @param CanDeleteRemark $canDeleteRemark + * @param DeletesRemark $deletesRemark + * @param FetchesRemark $fetchesRemark + */ + public function __construct(CanDeleteRemark $canDeleteRemark, DeletesRemark $deletesRemark, FetchesRemark $fetchesRemark) + { + $this->canDeleteRemark = $canDeleteRemark; + $this->deletesRemark = $deletesRemark; + $this->fetchesRemark = $fetchesRemark; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canDeleteRemark->passes(); + + $query = $this->fetchesRemark->execute(['id' => $request->route('id')]); + + $this->deletesRemark->execute($query); + + return $this->response([]); + } + +} diff --git a/app/Classes/Modules/Remarks/ControllersLogic/FetchRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/FetchRemarkLogic.php new file mode 100644 index 00000000..9c5aa5af --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/FetchRemarkLogic.php @@ -0,0 +1,59 @@ + 'Retrieved Remark', + 'message' => 'You have successfully retrieved a Remark' + ]; + } + + /** @var CanFetchRemark */ + private $canFetchRemark; + + /** @var FetchesRemark */ + private $fetchesRemark; + + /** + * FetchRemarkControllersLogic constructor. + * @param CanFetchRemark $canFetchRemark + * @param FetchesRemark $fetchesRemark + */ + public function __construct(CanFetchRemark $canFetchRemark, FetchesRemark $fetchesRemark) + { + $this->canFetchRemark = $canFetchRemark; + $this->fetchesRemark = $fetchesRemark; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canFetchRemark->passes(); + + $query = $this->fetchesRemark->execute(['id' => $request->route('id')]); + + return $this->resourceResponse(new RemarkResource($query)); + } + +} diff --git a/app/Classes/Modules/Remarks/ControllersLogic/ListRemarksLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/ListRemarksLogic.php new file mode 100644 index 00000000..c70ccee1 --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/ListRemarksLogic.php @@ -0,0 +1,59 @@ + 'Retrieved Remarks', + 'message' => 'You have successfully retrieved a list of Remarks' + ]; + } + + /** @var CanListRemarks */ + private $canListRemarks; + + /** @var ListsRemarks */ + private $listsRemarks; + + /** + * ListRemarksLogic constructor. + * @param CanListRemarks $canListRemarks + * @param ListsRemarks $listsRemarks + */ + public function __construct(CanListRemarks $canListRemarks, ListsRemarks $listsRemarks) + { + $this->canListRemarks = $canListRemarks; + $this->listsRemarks = $listsRemarks; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canListRemarks->passes(); + + $query = $this->listsRemarks->execute($this->listsRemarks->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(RemarkResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Remarks/ControllersLogic/UpdateRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/UpdateRemarkLogic.php new file mode 100644 index 00000000..f120efab --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/UpdateRemarkLogic.php @@ -0,0 +1,71 @@ + 'Updated Remark', + 'message' => 'You have successfully updated the Remark' + ]; + } + + /** @var CanUpdateRemark */ + private $canUpdateRemark; + + /** @var UpdatesRemark */ + private $updatesRemark; + + /** @var FetchesRemark */ + private $fetchesRemark; + + /** + * UpdateRemarkLogic constructor. + * @param CanUpdateRemark $canUpdateRemark + * @param UpdatesRemark $updatesRemark + * @param FetchesRemark $fetchesRemark + */ + public function __construct(CanUpdateRemark $canUpdateRemark, UpdatesRemark $updatesRemark, FetchesRemark $fetchesRemark) + { + $this->canUpdateRemark = $canUpdateRemark; + $this->updatesRemark = $updatesRemark; + $this->fetchesRemark = $fetchesRemark; + } + + + /** + * @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 + { + $object = new RemarkObject($request->input('content'), auth()->user()->id); + + $this->canUpdateRemark->passes($object); + + $query = $this->fetchesRemark->execute(['id' => $request->route('id')]); + + $query = $this->updatesRemark->execute($query, $object); + + return $this->resourceResponse(new RemarkResource($query)); + } + +} diff --git a/app/Classes/Modules/Remarks/DataTransferObjects/RemarkObject.php b/app/Classes/Modules/Remarks/DataTransferObjects/RemarkObject.php new file mode 100644 index 00000000..44a9507f --- /dev/null +++ b/app/Classes/Modules/Remarks/DataTransferObjects/RemarkObject.php @@ -0,0 +1,38 @@ +commenterID = $commenterID; + $this->content = $content; + } + + /** + * @return int + */ + public function getCommenterId(): string + { + return $this->commenterID; + } + + /** + * @return string + */ + public function getContent(): ?string + { + return $this->content; + } + +} diff --git a/app/Classes/Modules/Remarks/Processors/CreateRemarkProcessor.php b/app/Classes/Modules/Remarks/Processors/CreateRemarkProcessor.php new file mode 100644 index 00000000..aadbe502 --- /dev/null +++ b/app/Classes/Modules/Remarks/Processors/CreateRemarkProcessor.php @@ -0,0 +1,47 @@ +createsRemark = $createsRemark; + $this->canCreateRemark = $canCreateRemark; + } + + + /** + * @param Remarkable $remarkable + * @param RemarkObject $object + * @return \Illuminate\Database\Eloquent\Model + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function execute(Remarkable $remarkable, RemarkObject $object){ + + $this->canCreateRemark->passes($object); + return $this->createsRemark->execute($remarkable, $object); + + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Remarks/Services/CreatesRemark.php b/app/Classes/Modules/Remarks/Services/CreatesRemark.php new file mode 100644 index 00000000..ac0d57a3 --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/CreatesRemark.php @@ -0,0 +1,31 @@ +commenter_id = $object->getCommenterId(); + $model->content = $object->getContent(); + + return $this->handler($remarkable->remarks(), $model); + + } +} diff --git a/app/Classes/Modules/Remarks/Services/DeletesRemark.php b/app/Classes/Modules/Remarks/Services/DeletesRemark.php new file mode 100644 index 00000000..4c29be9d --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/DeletesRemark.php @@ -0,0 +1,19 @@ +handler($model); + } +} diff --git a/app/Classes/Modules/Remarks/Services/FetchesRemark.php b/app/Classes/Modules/Remarks/Services/FetchesRemark.php new file mode 100644 index 00000000..a3b5c765 --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/FetchesRemark.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Remarks/Services/ListsRemarks.php b/app/Classes/Modules/Remarks/Services/ListsRemarks.php new file mode 100644 index 00000000..53479558 --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/ListsRemarks.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Remarks/Services/UpdatesRemark.php b/app/Classes/Modules/Remarks/Services/UpdatesRemark.php new file mode 100644 index 00000000..4ba9501c --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/UpdatesRemark.php @@ -0,0 +1,26 @@ +commenter_id = $object->getCommenterId(); + $model->content = $object->getContent(); + + return $this->handler($model); + + } +} diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php b/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php new file mode 100644 index 00000000..a7d2e5b1 --- /dev/null +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php @@ -0,0 +1,57 @@ +RemarkValidation = $RemarkValidation; + } + + + /** + * @return bool + */ + protected function authorized($object): bool + { + // TODO Set Authorization rules + return true; + + } + + /** + * @param RemarkObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return $this->RemarkValidation->validate($object); + + } + + + /** + * @param RemarkObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php b/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php new file mode 100644 index 00000000..1c61ac9d --- /dev/null +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php @@ -0,0 +1,43 @@ +RemarkValidation = $RemarkValidation; + } + + + /** + * @return bool + */ + protected function authorized($object): bool + { + // TODO Set Authorization rules + return true; + + } + + /** + * @param RemarkObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return $this->RemarkValidation->validate($object); + + } + + + /** + * @param RemarkObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Remarks/Standards/Validators/RemarkValidation.php b/app/Classes/Modules/Remarks/Standards/Validators/RemarkValidation.php new file mode 100644 index 00000000..b35d3bde --- /dev/null +++ b/app/Classes/Modules/Remarks/Standards/Validators/RemarkValidation.php @@ -0,0 +1,41 @@ + $object->getCommenterId(), + 'content' => $object->getContent(), + ]; + } + + /** + * @return array + */ + protected function rules(): array { + return [ + 'commenter_id' => 'required', + 'content' => 'required', + ]; + } + + /** + * @return array + */ + protected function messages(): array { + return []; + } + +} diff --git a/app/Classes/Modules/Rewards/Standards/Rules/CanCreateReward.php b/app/Classes/Modules/Rewards/Standards/Rules/CanCreateReward.php index 5249b35c..2479f7df 100644 --- a/app/Classes/Modules/Rewards/Standards/Rules/CanCreateReward.php +++ b/app/Classes/Modules/Rewards/Standards/Rules/CanCreateReward.php @@ -25,7 +25,7 @@ class CanCreateReward extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { if (!Auth::user()->can('add reward')) { return false; diff --git a/app/Classes/Modules/Rewards/Standards/Rules/CanDeleteReward.php b/app/Classes/Modules/Rewards/Standards/Rules/CanDeleteReward.php index 888b0d1e..71a29b4c 100644 --- a/app/Classes/Modules/Rewards/Standards/Rules/CanDeleteReward.php +++ b/app/Classes/Modules/Rewards/Standards/Rules/CanDeleteReward.php @@ -11,7 +11,7 @@ class CanDeleteReward extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { if (!Auth::user()->can('delete reward')) { return false; diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanCreateConstant.php b/app/Classes/Modules/Segments/Standards/Rules/CanCreateConstant.php index 55f9c61a..c1619917 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanCreateConstant.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanCreateConstant.php @@ -25,7 +25,7 @@ class CanCreateConstant extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanCreateSegment.php b/app/Classes/Modules/Segments/Standards/Rules/CanCreateSegment.php index f7b05a10..82a783bc 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanCreateSegment.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanCreateSegment.php @@ -25,7 +25,7 @@ class CanCreateSegment extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules if (!Auth::user()->can('add segment')) { diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanDeleteSegment.php b/app/Classes/Modules/Segments/Standards/Rules/CanDeleteSegment.php index 9faf4da6..5a8adf70 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanDeleteSegment.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanDeleteSegment.php @@ -11,7 +11,7 @@ class CanDeleteSegment extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanFetchSegment.php b/app/Classes/Modules/Segments/Standards/Rules/CanFetchSegment.php index e6756305..c3449de1 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanFetchSegment.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanFetchSegment.php @@ -13,7 +13,7 @@ class CanFetchSegment extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanListSegments.php b/app/Classes/Modules/Segments/Standards/Rules/CanListSegments.php index 9d01231d..88cf4369 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanListSegments.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanListSegments.php @@ -10,7 +10,7 @@ class CanListSegments extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { return true; } diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanUpdateConstant.php b/app/Classes/Modules/Segments/Standards/Rules/CanUpdateConstant.php index 650b249c..85841dec 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanUpdateConstant.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanUpdateConstant.php @@ -26,7 +26,7 @@ class CanUpdateConstant extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanUpdateSegment.php b/app/Classes/Modules/Segments/Standards/Rules/CanUpdateSegment.php index 8287dfd6..81823722 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanUpdateSegment.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanUpdateSegment.php @@ -27,7 +27,7 @@ class CanUpdateSegment extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules diff --git a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanCreateServiceType.php b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanCreateServiceType.php index 0fb57c32..5b7f68fc 100644 --- a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanCreateServiceType.php +++ b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanCreateServiceType.php @@ -26,7 +26,7 @@ class CanCreateServiceType extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanDeleteServiceType.php b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanDeleteServiceType.php index 1a832257..a5325dbd 100644 --- a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanDeleteServiceType.php +++ b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanDeleteServiceType.php @@ -13,7 +13,7 @@ class CanDeleteServiceType extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanFetchServiceType.php b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanFetchServiceType.php index e76497c8..61963bd1 100644 --- a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanFetchServiceType.php +++ b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanFetchServiceType.php @@ -13,7 +13,7 @@ class CanFetchServiceType extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanListServiceTypes.php b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanListServiceTypes.php index 44dc0e8b..e55c42d9 100644 --- a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanListServiceTypes.php +++ b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanListServiceTypes.php @@ -13,7 +13,7 @@ class CanListServiceTypes extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanUpdateServiceType.php b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanUpdateServiceType.php index 0e066109..f7e01f25 100644 --- a/app/Classes/Modules/ServiceTypes/Standards/Rules/CanUpdateServiceType.php +++ b/app/Classes/Modules/ServiceTypes/Standards/Rules/CanUpdateServiceType.php @@ -26,7 +26,7 @@ class CanUpdateServiceType extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php new file mode 100644 index 00000000..00117f9e --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php @@ -0,0 +1,93 @@ +fetchesTransaction = $fetchesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->approvesDocument = $approvesDocument; + $this->rejectsDocument = $rejectsDocument; + $this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount; + } + + /** + * @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; + + /** @var CalculatesBillGroupPaymentAmount */ + private $calculatesBillGroupPaymentAmount; + + /** + * @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('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); + + $billGroup = $transaction->owner; + $billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup); + + if ($status === 'reject') { + $billGroup->status = ApprovalStatus::PENDING_SUBMISSION; + $billGroup->save(); + } else { + if ($billGroupPayment['outstanding_amount'] <= 0 && $billGroupPayment['floating_amount'] <= 0) { + $billGroup->status = ApprovalStatus::APPROVED; + $billGroup->save(); + } + } + + return $this->response([]); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CancelBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CancelBillGroupLogic.php new file mode 100644 index 00000000..615ae342 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/CancelBillGroupLogic.php @@ -0,0 +1,66 @@ + 'Cancel Bill Group Transaction', + 'message' => 'You have successfully cancelled this Bill Group Transaction' + ]; + } + + /** @var FetchesBillGroup */ + private $fetchesBillGroup; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** + * CancelBillGroupLogic constructor. + * @param FetchesBillGroup $fetchesBillGroup + * @param UpdatesTransactionStatus $updatesTransactionStatus + */ + public function __construct(FetchesBillGroup $fetchesBillGroup, UpdatesTransactionStatus $updatesTransactionStatus) + { + $this->fetchesBillGroup = $fetchesBillGroup; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $billGroup = $this->fetchesBillGroup->execute(['id' => $request->route('id')]); + + $transactions = $billGroup->transactions()->get(); + + foreach($transactions as $transaction) { + if ($transaction->status === ApprovalStatus::APPROVED || $transaction->status === ApprovalStatus::COMPLETED) { + $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION); + } + } + + $billGroup->status = ApprovalStatus::PENDING_VERIFICATION; + $billGroup->save(); + + return $this->resourceResponse(new BillGroupResource($billGroup)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php new file mode 100644 index 00000000..2563c230 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php @@ -0,0 +1,94 @@ + 'Payment Proof Document', + 'message' => 'You have successfully submitted your payment proof document' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var CreatesDocument */ + private $createsDocument; + + /** @var CreatesFiles */ + private $createsFile; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** @var CalculatesBillGroupPaymentAmount */ + private $calculatesBillGroupPaymentAmount; + + /** + * CreateBillGroupPaymentProofDocumentLogic constructor. + * @param FetchesTransaction $fetchesTransaction + * @param CreatesDocument $createsDocument + * @param CreatesFiles $createsFile + * @param UpdatesTransactionStatus $updatesTransactionStatus + * @param CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount + */ + public function __construct(FetchesTransaction $fetchesTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesTransactionStatus $updatesTransactionStatus, CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount) + { + $this->fetchesTransaction = $fetchesTransaction; + $this->createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + + $object = new DocumentObject(DocumentType::BILL_GROUP_PAYMENT_PROOF, $request->input('files'), '', ApprovalStatus::PENDING_VERIFICATION, 'bill_group_payments'); + + /** @var Document $document */ + $document = $this->createsDocument->execute($transaction, $object); + + $this->createsFile->execute($document, $object); + + $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION); + + $billGroup = $transaction->owner; + $billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup); + + if ($billGroupPayment['outstanding_amount'] <= 0 && $billGroup->transactions()->where('status', ApprovalStatus::PENDING_SUBMISSION)->count() === 0) { + $billGroup->status = ApprovalStatus::PENDING_VERIFICATION; + $billGroup->save(); + } + + return $this->response([]); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php new file mode 100644 index 00000000..75be47d4 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php @@ -0,0 +1,95 @@ + 'Create Bill Group Payment Transaction', + 'message' => 'You have successfully created payment for this Bill Group' + ]; + } + + /** @var FetchesBillGroup */ + private $fetchesBillGroup; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var CreatesTransaction */ + private $createsTransaction; + + /** @var CalculatesBillGroupPaymentAmount */ + private $calculatesBillGroupPaymentAmount; + + /** + * CreateBillGroupPaymentTransactionLogic constructor. + * @param FetchesBillGroup $fetchesBillGroup + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param CreatesTransaction $createsTransaction + * @param CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount + */ + public function __construct(FetchesBillGroup $fetchesBillGroup, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount) + { + $this->fetchesBillGroup = $fetchesBillGroup; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsTransaction = $createsTransaction; + $this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $billGroup = $this->fetchesBillGroup->execute(['id' => $request->route('id')]); + + $billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup); + $outstanding_amount = $billGroupPayment['outstanding_amount']; + + if ($billGroupPayment['outstanding_amount'] <= 0) { + if ($billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->count() !== 0) { + throw new MalformedRequestException('Invalid bill group, payment transaction already exist.'); + } + } + + $payAmount = floatval(str_replace(',', '', $request->input('payAmount'))); + if($payAmount > round($outstanding_amount, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding_amount .'.'); + + if ($billGroupPayment['outstanding_amount'] == 0 && $payAmount == 0) { + $billGroup->status = ApprovalStatus::APPROVED; + $billGroup->save(); + } else { + $billNumber = $this->generatesTransactionBillNumber->execute('SPLR-PYMT-'); + $transaction_object = new TransactionObject($billNumber, TransactionType::SUPPLIER_PAYMENT, $billGroup->issuer, + $billGroup->receiver, $billGroup->issuerCompany->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, + $payAmount, $payAmount, 1, 1, 1, + 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, [], ''); + $this->createsTransaction->execute($billGroup, $transaction_object); + } + + return $this->resourceResponse(new BillGroupResource($billGroup)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php new file mode 100644 index 00000000..e75ab158 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php @@ -0,0 +1,212 @@ + 'Create Supplier White Form Order', + 'message' => 'You have successfully created currency supplier white form order' + ]; + } + + /** @var FetchesCompany */ + private $fetchesCompany; + + /** @var CreatesTransaction */ + private $createsTransaction; + + /** @var CreatesDocument */ + private $createsDocument; + + /** @var CreatesFiles */ + private $createsFile; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var UpdateGroupLogic */ + private $updateGroupLogic; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + + /** + * CreateSupplierBillGroupLogic constructor. + * @param FetchesCompany $fetchesCompany + * @param CreatesTransaction $createsTransaction + * @param CreatesDocument $createsDocument + * @param CreatesFiles $createsFile + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param UpdateGroupLogic $updateGroupLogic + * @param UpdatesTransactionStatus $updatesTransactionStatus + */ + public function __construct(FetchesCompany $fetchesCompany, CreatesTransaction $createsTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber, UpdateGroupLogic $updateGroupLogic, UpdatesTransactionStatus $updatesTransactionStatus) + { + $this->fetchesCompany = $fetchesCompany; + $this->createsTransaction = $createsTransaction; + $this->createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->updateGroupLogic = $updateGroupLogic; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + public function logic(Request $request): JsonResponse + { + + $supplier = $this->fetchesCompany->execute(['id' => $request->route('id')]); + + $payments = $request->input('payments'); + $supplierRefunds = $request->input('supplierRefunds'); + + foreach ($supplierRefunds as $supplierRefund) { + $refund = Transaction::find($supplierRefund['id']); + + if ($refund->owner->transactions()->where('type', TransactionType::BILL)->first()->issuer !== $supplier->id) { + throw new MalformedRequestException('The supplier refund and bill group does not belongs to same supplier.'); + } + + if ($refund->type !== TransactionType::SUPPLIER_REFUND) { + throw new MalformedRequestException('Only transaction type supplier refund can be used for bill refund.'); + } + + if ($refund->currency_rate == 1) { + throw new MalformedRequestException('Supplier refund with currecy rate 1 cannot be used for bill refund.'); + } + } + + $amount = 0; + $original_amount = 0; + + foreach ($payments as $payment) { + $amount += $payment['amount']; + $original_amount += $payment['original_amount']; + } + + $service_charges = 0; + + // if ($supplier->id === 4548 || $supplier->id === 2729) { + // $amount = round(floatval(str_replace(',', '', $request->input('payment_total'))), 2); + // } else { + $service_charges = floatval(str_replace(',', '', $request->input('service_charges'))); + // } + + $rate = $original_amount / $amount; + + // if ($supplier->id === 4548 || $supplier->id === 2729) { + // $request['rate'] = $rate; + // $request['supplier_id'] = $supplier->id; + // foreach ($payments as $payment) { + // $request->route()->setParameter('id', $payment['id']); + // $this->updateGroupLogic->execute($request); + // } + // } + + $billGroup = new BillGroup(); + $billGroup->issuer = $supplier->id; + $billGroup->receiver = 1; + $billGroup->reference = $this->generatesTransactionBillNumber->execute('BSPO-'); + $billGroup->amount = round(($amount + $service_charges), 2); + $billGroup->original_amount = round($original_amount, 2); + $billGroup->currency_id = 1; + $billGroup->original_currency_id = $payments[0]['original_currency']['id']; + $billGroup->currency_rate = $rate; + $billGroup->tax = 0; + $billGroup->service_charge = round($service_charges, 2); + $billGroup->status = ApprovalStatus::PENDING_SUBMISSION; + $billGroup->save(); + + foreach ($payments as $payment) { + $billGroup->groups()->sync($payment['id'], false); + } + + //create bill refund + $amount += $service_charges; + + foreach ($supplierRefunds as $supplierRefund) { + $refund = Transaction::find($supplierRefund['id']); + $deductedRefunds = $refund->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->get(); + $refundDeductableAmount = $refund->amount - $deductedRefunds->sum('amount'); + $refundDeductableOriginalAmount = $refund->original_amount - $deductedRefunds->sum('original_amount'); + + $amount -= $refundDeductableAmount; + $original_amount -= $refundDeductableOriginalAmount; + + if ($amount > 0) { + $deductedRefundAmount = $refundDeductableAmount; + $deductedRefundOriginalAmount = $refundDeductableOriginalAmount; + + $this->updatesTransactionStatus->execute($refund, ApprovalStatus::COMPLETED); + } + + if ($amount < 0) { + $deductedRefundAmount = $refundDeductableAmount + $amount; + $deductedRefundOriginalAmount = $refundDeductableOriginalAmount + $original_amount; + } + + $billNumber = $this->generatesTransactionBillNumber->execute('BRFD-'); + + $object = new TransactionObject( + $billNumber, + TransactionType::BILL_REFUND, + $supplier->id, + 1, + 1, + PaymentMethodType::CASH, + $deductedRefundAmount, + $deductedRefundOriginalAmount, + $refund->currency_id, + $refund->original_currency_id, + $deductedRefundOriginalAmount / $deductedRefundAmount, + 0, + 0, + null, + ApprovalStatus::APPROVED, + [] + ); + + $transaction = $this->createsTransaction->execute($refund, $object); + + $billGroup->billRefunds()->sync($transaction->id, false); + } + + $billGroup->amount = round($amount, 2); + $billGroup->save(); + + return $this->response([]); + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php index 2dcbd0f7..a9297894 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php @@ -3,6 +3,7 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; +use App\Classes\Exceptions\MalformedRequestException; use App\Classes\Modules\Transactions\Processors\CreateSupplierTransactionProcessor; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Models\Document; @@ -18,6 +19,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Documents\Services\CreatesDocument; use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; +use App\Classes\Modules\Transactions\Services\FetchesTransaction; class CreateSupplierTransactionLogic extends AbstractControllerLogic { @@ -26,7 +28,8 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic /** * @return array */ - protected function notification():array { + protected function notification(): array + { return [ 'title' => 'Create Supplier Transactions', 'message' => 'You have successfully created currency supplier transactions' @@ -48,6 +51,9 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic /** @var GeneratesTransactionBillNumber */ private $generatesTransactionBillNumber; + /** @var FetchesTransaction */ + private $fetchesTransaction; + /** * CreateSupplierTransactionLogic constructor. @@ -56,17 +62,19 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic * @param CreatesDocument $createsDocument * @param CreatesFiles $createsFile * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param FetchesTransaction $fetchesTransaction */ - public function __construct(FetchesCompany $fetchesCompany, CreateSupplierTransactionProcessor $createSupplierTransactionProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber) + public function __construct(FetchesCompany $fetchesCompany, CreateSupplierTransactionProcessor $createSupplierTransactionProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber, FetchesTransaction $fetchesTransaction) { $this->fetchesCompany = $fetchesCompany; $this->createSupplierTransactionProcessor = $createSupplierTransactionProcessor; $this->createsDocument = $createsDocument; $this->createsFile = $createsFile; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->fetchesTransaction = $fetchesTransaction; } - public function logic(Request $request) : JsonResponse + public function logic(Request $request): JsonResponse { $supplier = $this->fetchesCompany->execute(['id' => $request->route('id')]); @@ -75,9 +83,26 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic $payments = $request->input('payments'); + // todo-refund: activate this for partial refund + foreach ($payments as $payment) { + $payment = $this->fetchesTransaction->execute(['id' => $payment['id']]); + + $pendingRefundRequest = $payment->transactions()->refunds()->where('status', ApprovalStatus::PENDING_VERIFICATION)->first(); + + if ($pendingRefundRequest) { + throw new MalformedRequestException('Unable to create supplier order for pending refund request payment'); + } + + $totalRefund = $payment->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->sum('original_amount'); + + if ($payment->original_amount - $totalRefund <= 0) { + throw new MalformedRequestException('Unable to create supplier order for fully refunded payment'); + } + } + $this->createSupplierTransactionProcessor->execute($supplier, $rate, $payments); - if(!count($this->createSupplierTransactionProcessor->getBills())) return $this->response([]); + if (!count($this->createSupplierTransactionProcessor->getBills())) return $this->response([]); $group = new Group(); $group->save(); @@ -105,6 +130,10 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic $service_charge += $row->service_charge; } + $transferFee = (float)$this->createSupplierTransactionProcessor->getTransferTransactions()->sum('service_charge'); + $original_amount += $transferFee; + $amount = $amount + ($transferFee / $currency_rate) + $service_charge; + $group->issuer = $issuer; $group->receiver = $receiver; $group->reference = $this->generatesTransactionBillNumber->execute('SPO-'); @@ -122,7 +151,7 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic $object = new DocumentObject( DocumentType::CURRENCY_VENDOR_ORDER, - [chunk_split('data:application/pdf;base64,'.base64_encode($pdf->output()))], + [chunk_split('data:application/pdf;base64,' . base64_encode($pdf->output()))], '', ApprovalStatus::COMPLETED, 'currency_vendor_order' diff --git a/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php new file mode 100644 index 00000000..1122c111 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php @@ -0,0 +1,83 @@ + 'Delete Bill Group Transaction', + 'message' => 'You have successfully deleted this Bill Group Transaction' + ]; + } + + /** @var FetchesBillGroup */ + private $fetchesBillGroup; + + /** @var DeletesTransaction */ + private $deletesTransaction; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** + * DeleteBillGroupLogic constructor. + * @param FetchesBillGroup $fetchesBillGroup + * @param DeletesTransaction $deletesTransaction + * @param UpdatesTransactionStatus $updatesTransactionStatus + */ + public function __construct(FetchesBillGroup $fetchesBillGroup, DeletesTransaction $deletesTransaction, UpdatesTransactionStatus $updatesTransactionStatus) + { + $this->fetchesBillGroup = $fetchesBillGroup; + $this->deletesTransaction = $deletesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $billGroup = $this->fetchesBillGroup->execute(['id' => $request->route('id')]); + + $transactions = $billGroup->transactions()->get(); + + foreach($transactions as $transaction) { + $this->deletesTransaction->execute($transaction); + } + + $groups = $billGroup->groups()->get(); + + foreach($groups as $group) { + $billGroup->groups()->detach($group->id); + } + + $billRefunds = $billGroup->billRefunds()->get(); + + foreach($billRefunds as $billRefund) { + $billGroup->billRefunds()->detach($billRefund->id); + $this->deletesTransaction->execute($billRefund); + $this->updatesTransactionStatus->execute($billRefund->owner, ApprovalStatus::APPROVED); + } + + $billGroup->delete(); + + return $this->resourceResponse(new BillGroupResource($billGroup)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/DeleteRefundTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/DeleteRefundTransactionLogic.php new file mode 100644 index 00000000..65446adf --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/DeleteRefundTransactionLogic.php @@ -0,0 +1,112 @@ + 'Deleted Refund Transaction', + 'message' => 'You have successfully deleted a transaction' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var DeletesTransaction */ + private $deletesTransaction; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + + /** @var CalculatesBookingPaidAmount */ + private $calculatesBookingPaidAmount; + + /** @var UpdateBookingAmountLogic */ + private $updateBookingAmountLogic; + + /** + * CreatePaymentVerificationDocumentLogic constructor. + * @param FetchesTransaction $fetchesTransaction + * @param DeletesTransaction $deletesTransaction + * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount + * @param UpdateBookingAmountLogic $updateBookingAmountLogic + * @param calculatesBookingPaidAmount $calculatesBookingPaidAmount + */ + public function __construct(FetchesTransaction $fetchesTransaction, DeletesTransaction $deletesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, CalculatesBookingRefundAmount $calculatesBookingRefundAmount, UpdateBookingAmountLogic $updateBookingAmountLogic, CalculatesBookingPaidAmount $calculatesBookingPaidAmount) + { + $this->fetchesTransaction = $fetchesTransaction; + $this->deletesTransaction = $deletesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; + $this->updateBookingAmountLogic = $updateBookingAmountLogic; + $this->calculatesBookingPaidAmount = $calculatesBookingPaidAmount; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request): JsonResponse + { + // delete refund transaction + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + $this->deletesTransaction->execute($transaction); + + // Update payment_transaction status + $payment_transaction = $transaction->owner; + $this->updatesTransactionStatus->execute($payment_transaction, ApprovalStatus::APPROVED); + + // delete wallet top up transaction + $booking = $transaction->owner->owner; + Transaction::where('type', TransactionType::CREDIT_NOTE) + ->where('amount', $transaction->amount) + ->where('payment_reference', 'like', '%' . $booking->marking . '%') + ->delete(); + + // update back the latest booking amount + $request['fix_amount'] = $this->calculatesBookingPaidAmount->execute($booking); + $request->route()->setParameter('id', $booking->id); + $this->updateBookingAmountLogic->execute($request); + + // if have SUPPLIER_REFUND transaction + $bookingInWhiteForm = $payment_transaction->transactions()->bills()->first(); + if ($bookingInWhiteForm) { + + $whiteFormTransaction = Transaction::where('type', TransactionType::SUPPLIER_REFUND) + ->where('payment_reference', $transaction->payment_reference) + ->first(); + + // Log::info($whiteFormTransaction->id); + + $whiteFormTransaction->delete(); + } + + return $this->response([]); + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListBillGroupsLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListBillGroupsLogic.php new file mode 100644 index 00000000..0e39585b --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListBillGroupsLogic.php @@ -0,0 +1,42 @@ +listsBillGroups = $listsBillGroups; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Retrieved Bill Groups', + 'message' => 'You have successfully retrieved a list of bill groups' + ]; + } + + /** @var ListsBillGroups */ + private $listsBillGroups; + + public function logic(Request $request) : JsonResponse + { + $query = $this->listsBillGroups->execute($this->listsBillGroups->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(BillGroupResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php new file mode 100644 index 00000000..a9147c49 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php @@ -0,0 +1,74 @@ + 'List Transaction Job', + 'message' => 'You have successfully submit a job to list transactions' + ]; + } + + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListTransactionsJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $user = Auth::user(); + $userInfo = (object) [ + 'type' => $user->type, + ]; + + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $requestSignature, + null, + $jobId, + $userInfo + ); + + ListTransactionsJob::dispatch($listGenericJobObject)->onQueue('high_priority'); + + $result = []; + $result['job_id'] = $jobId; + + $this->createsJobResult->execute($listGenericJobObject); + + return $this->response(['data' => $result]); + } + +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php index aa432aea..431e1867 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php @@ -16,14 +16,17 @@ use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; use App\Classes\Modules\Transactions\Services\FetchesGroup; use App\Classes\Modules\Transactions\Services\UpdatesTransaction; use App\Classes\Modules\Transactions\Services\CalculatesTransactionTransferFee; +use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\SegmentConstants; use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Models\Transaction; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use ErrorException; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf; class UpdateGroupLogic extends AbstractControllerLogic @@ -60,6 +63,9 @@ class UpdateGroupLogic extends AbstractControllerLogic /** @var CreatesFiles */ private $createsFile; + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + /** * UpdateGroupLogic constructor. * @param FetchesGroup $fetchesGroup @@ -69,8 +75,9 @@ class UpdateGroupLogic extends AbstractControllerLogic * @param CalculatesTransactionTransferFee $calculatesTransactionTransferFee * @param CreatesDocument $createsDocument * @param CreatesFiles $createsFile + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber */ - public function __construct(FetchesGroup $fetchesGroup, FetchesCompany $fetchesCompany, CalculatesTransactionServiceCharge $calculatesTransactionServiceCharge, UpdatesTransaction $updatesTransaction, CalculatesTransactionTransferFee $calculatesTransactionTransferFee, CreatesDocument $createsDocument, CreatesFiles $createsFile) + public function __construct(FetchesGroup $fetchesGroup, FetchesCompany $fetchesCompany, CalculatesTransactionServiceCharge $calculatesTransactionServiceCharge, UpdatesTransaction $updatesTransaction, CalculatesTransactionTransferFee $calculatesTransactionTransferFee, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber) { $this->fetchesGroup = $fetchesGroup; $this->fetchesCompany = $fetchesCompany; @@ -79,6 +86,7 @@ class UpdateGroupLogic extends AbstractControllerLogic $this->calculatesTransactionTransferFee = $calculatesTransactionTransferFee; $this->createsDocument = $createsDocument; $this->createsFile = $createsFile; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; } /** @@ -125,6 +133,18 @@ class UpdateGroupLogic extends AbstractControllerLogic $billTransaction = $this->updatesTransaction->execute($transaction, $object); + $supplierRefundTransactions = $transaction->owner->transactions()->supplierRefunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->get(); + + foreach ($supplierRefundTransactions as $supplierRefundTransaction) { + $claimBefore = $supplierRefundTransaction->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->exists(); + + if (!$claimBefore) { + $supplierRefundTransaction->currency_rate = $rate; + $supplierRefundTransaction->amount = $supplierRefundTransaction->original_amount / $rate; + $supplierRefundTransaction->save(); + } + } + $transferTransaction = $transaction->transactions()->where('type', TransactionType::TRANSFER_FEE)->first(); $transferFee = $this->calculatesTransactionTransferFee->execute($billTransaction->original_amount, $constant); @@ -150,8 +170,61 @@ class UpdateGroupLogic extends AbstractControllerLogic $this->updatesTransaction->execute($transferTransaction, $object); } + // group transfer fee from supplier currency order dashboard manual input + if ($request->input('group_transfer_fee')) { + $fee = $request->input('group_transfer_fee'); + + $group_transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + if ($group_transfer_fee) { + $group_transfer_fee->amount = $fee; + $group_transfer_fee->original_amount = $fee; + $group_transfer_fee->save(); + } else { + $transferFeeNumber = $this->generatesTransactionBillNumber->execute('TRFR-'); + $object = new TransactionObject($transferFeeNumber, TransactionType::TRANSFER_FEE, 1, $supplier->id, + $supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, + $fee, $fee, $group->original_currency_id, $group->original_currency_id, + 1, 0, 0, null, ApprovalStatus::APPROVED); + + $model = new Transaction(); + $model->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(); + $model->payment_reference = $object->getPaymentReference(); + + $group->morphTransactions()->save($model); + } + } + + $group_transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + $group_transfer_fee_original_amount = 0; + + if ($group_transfer_fee) { + $group_transfer_fee_original_amount = $group_transfer_fee->original_amount; + } + + $transferFeeTransactions = $group->transactions()->with([ + 'transactions' => function ($transaction) { + return $transaction->where('type', TransactionType::TRANSFER_FEE); + }])->get()->pluck('transactions')->flatten(); + $group->issuer = $supplier->id; - $group->amount = $group->transactions()->sum('amount'); + $group->original_amount = $group->transactions()->sum('original_amount') + ((float)$transferFeeTransactions->sum('service_charge') + (float)$group_transfer_fee_original_amount); + $group->amount = $group->transactions()->sum('amount') + (((float)$transferFeeTransactions->sum('service_charge') + (float)$group_transfer_fee_original_amount) / $rate) + $group->transactions()->sum('service_charge'); $group->currency_rate = $rate; $group->tax = $group->transactions()->sum('tax'); $group->service_charge = $group->transactions()->sum('service_charge'); @@ -160,12 +233,7 @@ class UpdateGroupLogic extends AbstractControllerLogic $group->documents()->delete(); - $transferFeeTransactions = $group->transactions()->with([ - 'transactions' => function ($transaction) { - return $transaction->where('type', TransactionType::TRANSFER_FEE); - }])->get()->pluck('transactions')->flatten(); - - $pdf = LaravelMpdf::loadView('pages.pdfs.currency_vendor_order', ['transactions' => $group->transactions, 'transferFeeTransactions' => $transferFeeTransactions, 'supplier' => $supplier]); + $pdf = LaravelMpdf::loadView('pages.pdfs.currency_vendor_order', ['transactions' => $group->transactions, 'transferFeeTransactions' => $transferFeeTransactions, 'supplier' => $supplier, 'groupTransferFeeOriginalAmount' => $group_transfer_fee_original_amount]); $object = new DocumentObject( DocumentType::CURRENCY_VENDOR_ORDER, diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php new file mode 100644 index 00000000..b4cd4d02 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php @@ -0,0 +1,101 @@ + 'Update Group Transfer Fee', + 'message' => 'You have successfully updated transfer fee for this Group Transaction' + ]; + } + + /** @var FetchesGroup */ + private $fetchesGroup; + + /** @var CreatesTransaction */ + private $createsTransaction; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** + * UpdateGroupTransferFeeLogic constructor. + * @param FetchesGroup $fetchesGroup + * @param CreatesTransaction $createsTransaction + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + */ + public function __construct(FetchesGroup $fetchesGroup, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber) + { + $this->fetchesGroup = $fetchesGroup; + $this->createsTransaction = $createsTransaction; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $group = $this->fetchesGroup->execute(['id' => $request->route('id')]); + $supplier = $group->issuerCompany; + $fee = $request->input('fee'); + + $transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + if ($transfer_fee) { + $transfer_fee->amount = $fee; + $transfer_fee->original_amount = $fee; + $transfer_fee->save(); + } else { + $transferFeeNumber = $this->generatesTransactionBillNumber->execute('TRFR-'); + $object = new TransactionObject($transferFeeNumber, TransactionType::TRANSFER_FEE, 1, $supplier->id, + $supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, + $fee, $fee, $group->original_currency_id, $group->original_currency_id, + 1, 0, 0, null, ApprovalStatus::APPROVED); + + $model = new Transaction(); + $model->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(); + $model->payment_reference = $object->getPaymentReference(); + + $group->morphTransactions()->save($model); + } + + return $this->resourceResponse(new GroupResource($group)); + } + +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index b86e4878..d2b921d1 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -2,8 +2,9 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; - +use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; +use App\Classes\Modules\Bookings\ControllersLogic\UpdateBookingAmountLogic; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; @@ -13,7 +14,10 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use App\Classes\Modules\Wallets\Processors\CreditWalletProcessor; - +use App\Classes\Modules\Bookings\Services\CalculatesBookingPayableAmount; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; +use App\Classes\ValueObjects\Constants\TransactionType; +use Illuminate\Support\Facades\Auth; class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic { @@ -43,6 +47,15 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic /** @var CreditWalletProcessor */ private $creditWalletProcessor; + /** @var CalculatesBookingPayableAmount */ + private $calculatesBookingPayableAmount; + + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + + /** @var UpdateBookingAmountLogic */ + private $updateBookingAmountLogic; + /** * CreatePaymentVerificationDocumentLogic constructor. * @param FetchesCompany $fetchesCompany @@ -50,14 +63,20 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic * @param UpdatesTransactionStatus $updatesTransactionStatus * @param DeletesDocument $deletesDocument * @param CreditWalletProcessor $creditWalletProcessor + * @param CalculatesBookingPayableAmount $calculatesBookingPayableAmount + * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount + * @param UpdateBookingAmountLogic $updateBookingAmountLogic */ - public function __construct(FetchesCompany $fetchesCompany, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument, CreditWalletProcessor $creditWalletProcessor) + public function __construct(FetchesCompany $fetchesCompany, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument, CreditWalletProcessor $creditWalletProcessor, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount, UpdateBookingAmountLogic $updateBookingAmountLogic) { $this->fetchesCompany = $fetchesCompany; $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->deletesDocument = $deletesDocument; $this->creditWalletProcessor = $creditWalletProcessor; + $this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; + $this->updateBookingAmountLogic = $updateBookingAmountLogic; } /** @@ -67,19 +86,46 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); - - $transaction = $this->updatesTransactionStatus->execute($transaction, $request->input('status')); - - $booking = $transaction->owner->owner; - - $reference = 'Credit Voucher for Overpaid for Ref. '.$booking->marking; - - if ($transaction->status == ApprovalStatus::APPROVED) { - $this->creditWalletProcessor->execute($booking->company, $transaction->type, $transaction->amount, $reference); + if(auth()->user()->type === 3) { + throw new MalformedRequestException('You do not have the permission to refund the order.'); } + $refundTransaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + $refundTransaction = $this->updatesTransactionStatus->execute($refundTransaction, $request->route('status')); + + $paymentTransaction = $refundTransaction->owner; + + $supplierRefundTransaction = $paymentTransaction->transactions()->supplierRefunds()->where('status', [ApprovalStatus::PENDING_VERIFICATION])->first(); + + $booking = $paymentTransaction->owner; + + $reference = $paymentTransaction->amount - $refundTransaction->amount < 0.01 ? 'Fully Refund for Ref. ' . $booking->marking : 'Partially Refund for Ref. ' . $booking->marking; + + $refundAmount = $this->calculatesBookingRefundAmount->calculateRefundAmount($paymentTransaction, $booking->fix_currency_id); + + $paidAmount = $paymentTransaction->original_amount - $refundAmount; + + if ($refundTransaction->status == ApprovalStatus::APPROVED) { + $this->creditWalletProcessor->execute($booking->company, $refundTransaction->type, $refundTransaction->amount, $reference); + $po_transaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + + if ($po_transaction) { + $this->updatesTransactionStatus->execute($po_transaction, (float) number_format($po_transaction->amount, 2, '.', '') === (float) number_format((float)$booking->fix_amount - $refundTransaction->original_amount, 2, '.', '') ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::PENDING_SUBMISSION); + } + + $request['fix_amount'] = $booking->fix_amount - $refundTransaction->original_amount; + $request->route()->setParameter('id', $booking->id); + $this->updateBookingAmountLogic->execute($request); + } + + if ($supplierRefundTransaction) { + $this->updatesTransactionStatus->execute($supplierRefundTransaction, $request->route('status')); + } + + if (!$paidAmount > 0) { + $this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::REFUNDED); + } return $this->response([]); } diff --git a/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php index 8dab2d24..28a34057 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php @@ -24,6 +24,7 @@ use App\Classes\ValueObjects\Constants\DocumentType; use App\Models\Booking; use App\Models\Document; use Carbon\Carbon; +use Illuminate\Support\Facades\Log; use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf; class CreateProformaInvoiceTransactionProcessor @@ -102,37 +103,55 @@ class CreateProformaInvoiceTransactionProcessor */ public function execute(Booking $booking) { - $po_order_transaction = $booking->transactions() ->where('type', TransactionType::PURCHASE_ORDER) ->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]) ->first(); - $outstanding = $this->calculatesBookingOutstanding->execute($booking); + $transaction = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->first(); - $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $outstanding)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::CASH); + if (!$transaction) { + $outstanding = $this->calculatesBookingOutstanding->execute($booking); - $configurations = $this->fetchesBookingQuotation->execute($booking->company, $conversionObject); + $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $outstanding)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0 : 1, PaymentMethodType::CASH); + + $configurations = $this->fetchesBookingQuotation->execute($booking->company, $conversionObject); + + $paymentAttemptLimit = $this->fetchesCompanyPaymentAttemptLimit->execute($booking->company); + + $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); - $paymentAttemptLimit = $this->fetchesCompanyPaymentAttemptLimit->execute($booking->company); + $object = new TransactionObject( + $billNumber, + TransactionType::PAYMENT, + 1, + $booking->company->id, + $configurations->getConfigurations()->getBankId(), + $configurations->getConversionObject()->getPaymentMethod(), + $configurations->getTotal(), + $configurations->getForeignTotal(), + 1, + $configurations->getConversionObject()->getCurrencyId(), + $configurations->getConfigurations()->getRate(), + $configurations->getTax(), + $configurations->getServiceCharge(), + Carbon::now()->addMinutes($paymentAttemptLimit), + ApprovalStatus::PENDING_SUBMISSION, + [], + isset($billPlzBill) ? $billPlzBill->id : NULL + ); - $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); - - - $object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, - $configurations->getConfigurations()->getBankId(), $configurations->getConversionObject()->getPaymentMethod(), - $configurations->getTotal(), $configurations->getForeignTotal(), 1, - $configurations->getConversionObject()->getCurrencyId(), $configurations->getConfigurations()->getRate(), - $configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], isset($billPlzBill) ? $billPlzBill->id : NULL); - - $this->createsTransaction->execute($booking, $object); + $this->createsTransaction->execute($booking, $object); + } $billNumber = $this->generatesTransactionBillNumber->execute('PROFORMA-'); - $payable_amount = $booking->transactions()->payments()->where(function($query){ - return $query->where(function($query){ + $payable_amount = $booking->transactions()->payments()->where(function ($query) { + return $query->where(function ($query) { return $query->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString()); - })->orWhere(function($query){ + })->orWhere(function ($query) { return $query->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); }); })->sum('amount'); @@ -142,14 +161,16 @@ class CreateProformaInvoiceTransactionProcessor ->where('type', TransactionType::PAYMENT) ->first(); - $booking_currency_average_rate = $booking_amount / $booking->transactions()->payments()->where(function($query){ - return $query->where(function($query){ + $paymentAmount = $booking->transactions()->payments()->where(function ($query) { + return $query->where(function ($query) { return $query->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString()); - })->orWhere(function($query){ + })->orWhere(function ($query) { return $query->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); }); })->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); + $booking_currency_average_rate = $booking_amount / $paymentAmount; + $total_service_charge = $booking->transactions() ->where('type', TransactionType::PAYMENT) ->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED]) @@ -160,6 +181,11 @@ class CreateProformaInvoiceTransactionProcessor ->whereIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED]) ->sum('tax'); + // delete prev proforma transactions + $booking->transactions() + ->where('type', TransactionType::PROFORMA) + ->delete(); + $transaction_object = new TransactionObject( $billNumber, TransactionType::PROFORMA, @@ -178,14 +204,14 @@ class CreateProformaInvoiceTransactionProcessor ApprovalStatus::APPROVED ); - $perofrma_transaction = $this->createsTransaction->execute($po_order_transaction->booking, $transaction_object); + $proforma_transaction = $this->createsTransaction->execute($po_order_transaction->booking, $transaction_object); $supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]); - $purchase_order_pdf = LaravelMpdf::loadView('pages.pdfs.proforma_invoice', ['invoice_transaction' => $perofrma_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]); + $purchase_order_pdf = LaravelMpdf::loadView('pages.pdfs.proforma_invoice', ['invoice_transaction' => $proforma_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]); $document_object = new DocumentObject( DocumentType::PROFORMA_INVOICE, - [chunk_split('data:application/pdf;base64,'.base64_encode($purchase_order_pdf->output()))], + [chunk_split('data:application/pdf;base64,' . base64_encode($purchase_order_pdf->output()))], '', ApprovalStatus::COMPLETED, 'proforma_invoices' @@ -194,7 +220,5 @@ class CreateProformaInvoiceTransactionProcessor /** @var Document $document */ $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); $this->createsFile->execute($document, $document_object); - - } } diff --git a/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php index 9b944a5b..b514b404 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php @@ -81,15 +81,19 @@ class CreateSupplierTransactionProcessor if($payment->status !== ApprovalStatus::APPROVED) continue; + $totalRefund = $payment->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->sum('original_amount'); + + $original_amount_after_refund = $payment->original_amount - $totalRefund; + $this->updatesTransactionStatus->execute($payment, ApprovalStatus::COMPLETED); $billNumber = $this->generatesTransactionBillNumber->execute('SPLR-'); $constant = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $supplier->id)->first(); - $serviceCharge = $this->calculatesTransactionServiceCharge->execute($payment->original_amount, $rate, $constant); + $serviceCharge = $this->calculatesTransactionServiceCharge->execute($original_amount_after_refund, $rate, $constant); $object = new TransactionObject($billNumber, TransactionType::BILL, $supplier->id, 1, $supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, - $payment->original_amount * (1 / $rate), $payment->original_amount, 1, $payment->original_currency_id, + $original_amount_after_refund * (1 / $rate), $original_amount_after_refund, 1, $payment->original_currency_id, $rate, 0, $serviceCharge, null, ApprovalStatus::PENDING_SUBMISSION); /** @var Transaction $billTransaction */ @@ -101,7 +105,7 @@ class CreateSupplierTransactionProcessor $transferFee = $this->calculatesTransactionTransferFee->execute($billTransaction->original_amount, $constant); $object = new TransactionObject($transferFeeNumber, TransactionType::TRANSFER_FEE, 1, $supplier->id, $supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, - $payment->original_amount, $payment->original_amount, $payment->original_currency_id, $payment->original_currency_id, + $original_amount_after_refund, $original_amount_after_refund, $payment->original_currency_id, $payment->original_currency_id, 1, 0, $transferFee, null, ApprovalStatus::PENDING_VERIFICATION); $this->pushTransferFee($this->createsTransaction->execute($billTransaction, $object)); diff --git a/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php b/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php new file mode 100644 index 00000000..475d4715 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php @@ -0,0 +1,45 @@ +listsTransactions = $listsTransactions; + $this->updateJobResultProcessor = $updateJobResultProcessor; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + + $resultCurrent = Helper::collectionResponse(ListTransactionJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); + } +} + diff --git a/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php b/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php new file mode 100644 index 00000000..d0e7dfcf --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php @@ -0,0 +1,25 @@ +billRefunds->sum('amount')), 7); + $floating_amount = round(floatval($billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION])->sum('amount')), 7); + $paid_amount = round(floatval($billGroup->transactions()->where('status', ApprovalStatus::APPROVED)->sum('amount')), 7); + $outstanding_amount = $billGroup->amount - $paid_amount - $floating_amount; + $outstanding_amount = round($outstanding_amount, 7); + + return [ + 'bill_refund_amount' => $bill_refund_amount, + 'floating_amount' => $floating_amount, + 'paid_amount' => $paid_amount, + 'outstanding_amount' => $outstanding_amount, + ]; + } +} diff --git a/app/Classes/Modules/Transactions/Services/FetchesBillGroup.php b/app/Classes/Modules/Transactions/Services/FetchesBillGroup.php new file mode 100644 index 00000000..55e5eb11 --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/FetchesBillGroup.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Transactions/Services/ListsBillGroups.php b/app/Classes/Modules/Transactions/Services/ListsBillGroups.php new file mode 100644 index 00000000..26379706 --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/ListsBillGroups.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Transactions/Standards/Rules/CanCreateTransaction.php b/app/Classes/Modules/Transactions/Standards/Rules/CanCreateTransaction.php index 39fdd05a..c8f24a8e 100644 --- a/app/Classes/Modules/Transactions/Standards/Rules/CanCreateTransaction.php +++ b/app/Classes/Modules/Transactions/Standards/Rules/CanCreateTransaction.php @@ -23,7 +23,7 @@ class CanCreateTransaction extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Transactions/Standards/Rules/CanCreateTransactionDetail.php b/app/Classes/Modules/Transactions/Standards/Rules/CanCreateTransactionDetail.php index 2669ffbf..537d2813 100644 --- a/app/Classes/Modules/Transactions/Standards/Rules/CanCreateTransactionDetail.php +++ b/app/Classes/Modules/Transactions/Standards/Rules/CanCreateTransactionDetail.php @@ -23,7 +23,7 @@ class CanCreateTransactionDetail extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php index a5d65544..e345ebcf 100644 --- a/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php +++ b/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php @@ -6,9 +6,32 @@ namespace App\Classes\Modules\Vouchers\ControllersLogic; use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Vouchers\Processors\CreateVoucherProcessor; +use App\Classes\Modules\Vouchers\Services\Voucherify\FetchesVoucherifyVoucher; +use App\Classes\Modules\Vouchers\Services\Voucherify\ValidatesVoucherifyVoucher; +use App\Classes\Modules\Vouchers\Services\Voucherify\CreatesVoucherifyVoucherInACampaign; +use App\Classes\Modules\Vouchers\Services\Voucherify\ListsVoucherifyVouchers; +use App\Classes\Modules\Vouchers\Services\Voucherify\FetchesVoucherifyCampaign; +use App\Classes\Modules\Vouchers\Processors\Voucherify\NewCustomerToVoucherifyProcessor; +use App\Classes\Modules\Vouchers\Services\CreatesVoucher; +use App\Classes\Modules\Vouchers\Services\FetchesVoucher; +use App\Classes\Modules\Vouchers\Services\UpdatesVoucherCampaign; +use App\Classes\Modules\Rewards\Services\CreatesUserReward; +use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair; +use App\Classes\Modules\Accounts\Services\UpdatesKeyValuePair; +use App\Classes\Modules\Vouchers\Standards\Rules\CanCreateVoucher; +use App\Classes\Modules\Vouchers\DataTransferObjects\ValidateVoucherifyVoucherObject; +use App\Classes\Modules\Vouchers\DataTransferObjects\CreateVoucherObject; +use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject; +use App\Classes\Modules\Vouchers\DataTransferObjects\VoucherCampaignObject; +use App\Classes\ValueObjects\Constants\RoleTypes; +use App\Classes\ValueObjects\Constants\Vouchers; use App\Models\User; +use App\Models\VoucherCampaign; +use Carbon\Carbon; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Log; class CreateVoucherLogic extends AbstractControllerLogic @@ -23,16 +46,66 @@ class CreateVoucherLogic extends AbstractControllerLogic ]; } + /** @var ValidatesVoucherifyVoucher */ + private $validatesVoucherifyVoucher; + + /** @var CreatesVoucherifyVoucherInACampaign */ + private $createsVoucherifyVoucherInACampaign; + + /** @var ListsVoucherifyVouchers */ + private $listsVoucherifyVouchers; + + /** @var FetchesVoucherifyCampaign */ + private $fetchesVoucherifyCampaign; + + /** @var CreatesUserReward */ + private $createsUserReward; + /** @var CreateVoucherProcessor */ private $createVoucherProcessor; + /** @var CanCreateVoucher */ + private $canCreateVoucher; + + /** @var CreatesKeyValuePair */ + private $createsKeyValuePair; + + /** @var UpdatesKeyValuePair */ + private $updatesKeyValuePair; + + /** @var UpdatesVoucherCampaign */ + private $updatesVoucherCampaign; + + /** @var NewCustomerToVoucherifyProcessor */ + private $newCustomerToVoucherifyProcessor; + /** * CreateVoucherLogic constructor. + * @param ValidatesVoucherifyVoucher $validatesVoucherifyVoucher + * @param CreatesVoucherifyVoucherInACampaign $createsVoucherifyVoucherInACampaign + * @param ListsVoucherifyVouchers $listsVoucherifyVouchers + * @param FetchesVoucherifyCampaign $fetchesVoucherifyCampaign + * @param CreatesUserReward $createsUserReward * @param CreateVoucherProcessor $createVoucherProcessor + * @param CanCreateVoucher $canCreateVoucher + * @param CreatesKeyValuePair $createsKeyValuePair + * @param UpdatesKeyValuePair $updatesKeyValuePair + * @param UpdatesVoucherCampaign $updatesVoucherCampaign + * @param NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor */ - public function __construct(CreateVoucherProcessor $createVoucherProcessor) + public function __construct(CreatesUserReward $createsUserReward, ValidatesVoucherifyVoucher $validatesVoucherifyVoucher, CreateVoucherProcessor $createVoucherProcessor, CreatesVoucherifyVoucherInACampaign $createsVoucherifyVoucherInACampaign, CanCreateVoucher $canCreateVoucher, ListsVoucherifyVouchers $listsVoucherifyVouchers, FetchesVoucherifyCampaign $fetchesVoucherifyCampaign, CreatesKeyValuePair $createsKeyValuePair, UpdatesKeyValuePair $updatesKeyValuePair, UpdatesVoucherCampaign $updatesVoucherCampaign, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor) { + $this->createsUserReward = $createsUserReward; + $this->validatesVoucherifyVoucher = $validatesVoucherifyVoucher; $this->createVoucherProcessor = $createVoucherProcessor; + $this->createsVoucherifyVoucherInACampaign = $createsVoucherifyVoucherInACampaign; + $this->canCreateVoucher = $canCreateVoucher; + $this->listsVoucherifyVouchers = $listsVoucherifyVouchers; + $this->fetchesVoucherifyCampaign = $fetchesVoucherifyCampaign; + $this->createsKeyValuePair = $createsKeyValuePair; + $this->updatesKeyValuePair = $updatesKeyValuePair; + $this->updatesVoucherCampaign = $updatesVoucherCampaign; + $this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor; } /** @@ -42,8 +115,131 @@ class CreateVoucherLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $user = User::where('id', $request->input('userId'))->first(); - $result = $this->createVoucherProcessor->execute($user, $request->input('voucherCode'), null); + //Process request input + $userParam = User::where('id', $request->input('userId'))->first(); + $voucherCodeInput = $request->input('voucherCode'); + $userRewardObject = new CreateVoucherObject( + $voucherCodeInput, + $userParam, + ); + $this->canCreateVoucher->passes($userRewardObject); + + //Initialize variables + $result = null; + + $user = Auth::user(); /** @var User $user */ + if($user && isset($user->type) && in_array($user->type, RoleTypes::ADMIN_ROLES) && $userParam){ + $user = User::where('id', $userParam->id)->first(); + } + else{ + $user = $userParam ? $userParam : $user; + } + + //Voucherify - To check if user exist at Voucherify, create if not exist + $voucherify_entity = $user->voucherifyEntities()->first(); + if(!$voucherify_entity){ + $this->newCustomerToVoucherifyProcessor->execute($user->company()->first()->id, $user, false); + } + + //Voucherify - creates new voucher at voucherify + if ($voucherCodeInput === Vouchers::SORRY_50 || $voucherCodeInput === Vouchers::SORRY_100 || $voucherCodeInput === Vouchers::SORRY_200 ) { + $result = $this->newVoucherifyVoucherIssuanceHandler($voucherCodeInput); + } + else //Voucherify - validates existing voucher at voucherify + { + $result = $this->existingVoucherValidationHandler($voucherCodeInput, $user); + } + + //Save validated voucher info to local DB + if(!isset($result['reason'] ) && $result['validatedVoucherCode']){ + $voucher = $this->createVoucherProcessor->execute($user, $result['validatedVoucherCode'], $result['voucherCampaignId'] ?? null); + $voucherCount = $user->rewards->where('voucher_id', $voucher->id)->count(); + if($voucherCount == 0){ + $result = $this->createsUserReward->execute(null, $user, $voucher->id); + } + else{ + $result['reason'] = 'Voucher already added'; + } + } + + //Unset property that is set for internal processing + unset($result['validatedVoucherCode']); + unset($result['voucherCampaignId']); + return $this->response(['data' => $result]); } + + private function newVoucherifyVoucherIssuanceHandler($voucherCodeInput){ + $result = []; + $total = 0; + $limit = 0; + $voucherCampaign = VoucherCampaign::where('slug', strtolower($voucherCodeInput))->first(); + + if($voucherCampaign){ + $result['voucherCampaignId'] = $voucherCampaign->id; + $voucherList = $this->listsVoucherifyVouchers->execute($voucherCampaign->campaign_id); //Remote Voucherify + if (isset($voucherList->vouchers) && isset($voucherList->total)) { + $total = $voucherList->total; + } + $voucherifyCampaign = $this->fetchesVoucherifyCampaign->execute($voucherCampaign->campaign_id); //Remote Voucherify + + $campaignName = $voucherifyCampaign->name; + $campaignId = $voucherifyCampaign->id; + $campaignMetadata = $voucherifyCampaign->metadata; + + if(isset($campaignMetadata) && isset($campaignMetadata['voucher_limit_per_month'])){ + $limit = (int) $campaignMetadata['voucher_limit_per_month']; + } + + $voucherCampaignObject= new VoucherCampaignObject($campaignId, $campaignName, null, $limit); + $this->updatesVoucherCampaign->execute($voucherCampaign, $voucherCampaignObject); + + if($total >= $voucherCampaign['limit_per_month']){ + $result['reason'] = 'Quota for the month exceeded'; + } + else{ + //To track voucher issuance by admin + $total = $voucherList->total + 1; + $key = strtoupper($campaignId)."_".strtoupper(Carbon::now()->format('M'))."_TOTAL"; + $keyValuePairObject = new KeyValuePairObject( + $key, + $total + ); + $metadata = $voucherCampaign->attributesKVP()->where('key', $key)->first(); + if($metadata){ + $this->updatesKeyValuePair->execute($metadata, $keyValuePairObject); + } + else{ + $this->createsKeyValuePair->execute($voucherCampaign, $keyValuePairObject); + } + + $createdVoucher = $this->createsVoucherifyVoucherInACampaign->execute($campaignName, ""); //Remote Voucherify + if(isset($createdVoucher->message)){ + $result['reason'] = $createdVoucher->message; + } + else{ + $result['validatedVoucherCode'] = $createdVoucher->code; + } + } + } + else{ + $result['reason'] = 'Campaign not set'; + } + + return $result; + } + + private function existingVoucherValidationHandler(string $voucherCodeInput, User $user){ + $result = []; + $ValidateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject(0, $voucherCodeInput, 0.00, $user); + $voucherifyVoucherValidated = $this->validatesVoucherifyVoucher->execute($ValidateVoucherifyVoucherObject); //Remote Voucherify + + if(isset($voucherifyVoucherValidated->reason)){ + $result['reason'] = $voucherifyVoucherValidated->reason; + } + else if($voucherifyVoucherValidated){ + $result['validatedVoucherCode'] = $voucherCodeInput; + } + return $result; + } } diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php index 16356f0f..013be9d6 100644 --- a/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php +++ b/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php @@ -4,9 +4,11 @@ namespace App\Classes\Modules\Vouchers\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Rewards\Services\ListsUserRewards; +use App\Classes\ValueObjects\Constants\RoleTypes; use App\Http\Resources\UserRewardResource; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; class ListUserVouchersLogic extends AbstractControllerLogic { @@ -40,6 +42,11 @@ class ListUserVouchersLogic extends AbstractControllerLogic public function logic(Request $request) : JsonResponse { $query = $this->listsUserRewards->execute($this->listsUserRewards->deserializeFilters($request->input('filters'))); + + if(in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)){ + $request->merge(['isAdmin' => true]); + } + return $this->collectionResponse(UserRewardResource::collection($query)); } diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/ListVoucherCampaignsLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/ListVoucherCampaignsLogic.php new file mode 100644 index 00000000..3e3e13d6 --- /dev/null +++ b/app/Classes/Modules/Vouchers/ControllersLogic/ListVoucherCampaignsLogic.php @@ -0,0 +1,60 @@ +listsVoucherCampaigns = $listsVoucherCampaigns; + $this->canListVoucherCampaigns = $canListVoucherCampaigns; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Retrieved Voucher Campaigns', + 'message' => 'You have successfully retrieved a list of voucher campaigns' + ]; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $this->canListVoucherCampaigns->passes(); + + $query = $this->listsVoucherCampaigns->execute($this->listsVoucherCampaigns->deserializeFilters($request->input('filters'))); + + $filters = json_decode($request->input('filters'), true); + if(isset($filters['include_metadata'])){ + $request->merge(['include_metadata' => true]); + } + + return $this->collectionResponse(VoucherCampaignResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php index 4b820eb1..41b2724d 100644 --- a/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php +++ b/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php @@ -10,6 +10,7 @@ use App\Classes\Modules\Vouchers\DataTransferObjects\ValidateVoucherifyVoucherOb use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use App\Models\Booking; +use Illuminate\Support\Facades\Log; class ValidateVoucherLogic extends AbstractControllerLogic { @@ -42,12 +43,36 @@ class ValidateVoucherLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { + $employeeWhoOwnsTheVoucher = null; $booking = Booking::find($request->input('itemId')); - $employee = $booking->company->employees()->first(); + $employees = $booking->company->employees()->get(); - $validateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject($booking->company_id, $request->input('voucherCode'), $request->input('amount'), $employee); + if(count($employees) > 1){ + foreach($employees as $singleEmployee){ + $userRewards = $singleEmployee->rewards; + foreach($userRewards as $userReward){ + if ($userReward->voucher && $userReward->voucher->code === $request->input('voucherCode')) { + Log::info('2. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $request->input('voucherCode')); + $employeeWhoOwnsTheVoucher = $singleEmployee; + } + } + } + } + + if(!$employeeWhoOwnsTheVoucher){ + $employeeWhoOwnsTheVoucher = $booking->company->employees()->first(); + } + + $amount = $this->floatvalue($request->input('amount')); + + $validateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject($booking->company_id, $request->input('voucherCode'), $amount, $employeeWhoOwnsTheVoucher); $result = $this->validatesVoucherifyVoucher->execute($validateVoucherifyVoucherObject); return $this->response(['data' => $result]); } + private function floatvalue($val){ + $val = str_replace(",",".",$val); + $val = preg_replace('/\.(?=.*\.)/', '', $val); + return floatval($val); + } } diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherObject.php new file mode 100644 index 00000000..74ef0e19 --- /dev/null +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherObject.php @@ -0,0 +1,44 @@ +user = $user; + $this->voucherCode = $voucherCode; + } + + + /** + * @return string + */ + public function getVoucherCode(): string + { + return $this->voucherCode; + } + + /** + * @return null|User + */ + public function getUser(): ?User + { + return $this->user; + } + +} diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyCustomerObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyCustomerObject.php index 9678dafe..e61d1d00 100644 --- a/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyCustomerObject.php +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyCustomerObject.php @@ -65,9 +65,9 @@ class CreateVoucherifyCustomerObject implements DataTransferObject */ public function getAcquisitionChannel(): string { - if(!$this->isNew){ - return ""; - } + // if(!$this->isNew){ + // return ""; + // } return $this->acquisitionChannel; } diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/ValidateVoucherifyVoucherObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/ValidateVoucherifyVoucherObject.php index b48bee16..956afc00 100644 --- a/app/Classes/Modules/Vouchers/DataTransferObjects/ValidateVoucherifyVoucherObject.php +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/ValidateVoucherifyVoucherObject.php @@ -17,8 +17,8 @@ class ValidateVoucherifyVoucherObject implements DataTransferObject /** @var float */ private $amount; - /** @var User */ - private $user; + /** @var User */ + private $user; //this will affect certain voucher that limit user redemption e.g. one user one redemption per campaign /** * ValidateVoucherifyVoucherObject constructor. diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherCampaignObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherCampaignObject.php new file mode 100644 index 00000000..f7fd04ee --- /dev/null +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherCampaignObject.php @@ -0,0 +1,67 @@ +campaign_id = $campaign_id; + $this->name = $name; + $this->description = $description; + $this->limitPerMonth = $limitPerMonth; + } + + /** + * @return string + */ + public function getCampaignId(): string + { + return $this->campaign_id; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return string|null + */ + public function getDescription(): ?string + { + return $this->description; + } + + /** + * @return int + */ + public function getLimitPerMonth(): int + { + return $this->limitPerMonth; + } +} diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php index f624b3cc..70564b7f 100644 --- a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php @@ -3,6 +3,7 @@ namespace App\Classes\Modules\Vouchers\DataTransferObjects; use App\Classes\General\Interfaces\DataTransferObject; +use Carbon\Carbon; use DateTime; use Illuminate\Support\Facades\Log; @@ -14,6 +15,9 @@ class VoucherObject implements DataTransferObject /** @var string|null */ private $name; + /** @var string|null */ + private $description; + /** @var string|null */ private $type; @@ -26,21 +30,28 @@ class VoucherObject implements DataTransferObject /** @var string|null */ private $endDate; + /** @var int */ + private $voucherCampaignId; + /** * VoucherObject constructor. * @param string $code * @param string $name + * @param string $description * @param string $type * @param float $value + * @param int $voucherCampaignId * @param string $startDate * @param string $endDate */ - public function __construct(string $code, ?string $name, ?string $type, ?float $value, ?string $startDate = '', ?string $endDate = '') + public function __construct(string $code, ?string $name, ?string $description, ?string $type, ?float $value, ?int $voucherCampaignId, ?string $startDate = '', ?string $endDate = '') { $this->code = $code; $this->name = $name; + $this->description = $description; $this->type = $type; $this->value = $value; + $this->voucherCampaignId = $voucherCampaignId; $this->startDate = $startDate; $this->endDate = $endDate; } @@ -61,6 +72,13 @@ class VoucherObject implements DataTransferObject return $this->name; } + /** + * @return string + */ + public function getDescription(): ?string + { + return $this->description; + } /** * @return string @@ -70,7 +88,6 @@ class VoucherObject implements DataTransferObject return $this->type; } - /** * @return float */ @@ -79,6 +96,14 @@ class VoucherObject implements DataTransferObject return $this->value; } + /** + * @return int + */ + public function getVoucherCampaignId(): ?int + { + return $this->voucherCampaignId; + } + /** * @return DateTime */ @@ -86,7 +111,8 @@ class VoucherObject implements DataTransferObject { try { if(!$this->startDate) return null; - $dateTime = new DateTime($this->startDate); + // $dateTime = new DateTime($this->startDate); + $dateTime = Carbon::parse($this->startDate)->tz('Asia/Kuala_Lumpur'); return $dateTime; } catch (\Exception $e) { Log::error($e); @@ -101,7 +127,7 @@ class VoucherObject implements DataTransferObject { try { if(!$this->endDate) return null; - $dateTime = new DateTime($this->endDate); + $dateTime = Carbon::parse($this->endDate)->tz('Asia/Kuala_Lumpur'); return $dateTime; } catch (\Exception $e) { Log::error($e); diff --git a/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php b/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php index 690ad59f..92a3a484 100644 --- a/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php +++ b/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php @@ -4,110 +4,83 @@ namespace App\Classes\Modules\Vouchers\Processors; use App\Classes\Modules\Vouchers\Services\Voucherify\FetchesVoucherifyVoucher; -use App\Classes\Modules\Vouchers\Services\Voucherify\ValidatesVoucherifyVoucher; use App\Classes\Modules\Vouchers\Services\CreatesVoucher; use App\Classes\Modules\Vouchers\Services\FetchesVoucher; -use App\Classes\Modules\Rewards\Services\CreatesUserReward; use App\Classes\Modules\Vouchers\DataTransferObjects\VoucherObject; -use App\Classes\Modules\Vouchers\DataTransferObjects\ValidateVoucherifyVoucherObject; -use App\Classes\ValueObjects\Constants\RoleTypes; use App\Models\User; -use Illuminate\Support\Facades\Auth; +use Carbon\Carbon; use Illuminate\Support\Facades\Log; - class CreateVoucherProcessor { /** @var FetchesVoucherifyVoucher */ private $fetchesVoucherifyVoucher; - /** @var ValidatesVoucherifyVoucher */ - private $validatesVoucherifyVoucher; - /** @var CreatesVoucher */ private $createsVoucher; - /** @var CreatesUserReward */ - private $createsUserReward; - /** @var FetchesVoucher */ private $fetchesVoucher; /** * CreateVoucherProcessor constructor. * @param FetchesVoucherifyVoucher $fetchesVoucherifyVoucher - * @param ValidatesVoucherifyVoucher $validatesVoucherifyVoucher * @param CreatesVoucher $createsVoucher - * @param CreatesUserReward $createsUserReward * @param FetchesVoucher $fetchesVoucher */ - public function __construct(FetchesVoucherifyVoucher $fetchesVoucherifyVoucher, CreatesVoucher $createsVoucher, CreatesUserReward $createsUserReward, FetchesVoucher $fetchesVoucher, ValidatesVoucherifyVoucher $validatesVoucherifyVoucher) + public function __construct(FetchesVoucherifyVoucher $fetchesVoucherifyVoucher, CreatesVoucher $createsVoucher, FetchesVoucher $fetchesVoucher) { $this->fetchesVoucherifyVoucher = $fetchesVoucherifyVoucher; $this->createsVoucher = $createsVoucher; - $this->createsUserReward = $createsUserReward; $this->fetchesVoucher = $fetchesVoucher; - $this->validatesVoucherifyVoucher = $validatesVoucherifyVoucher; } /** - * @param ?User $userParam + * @param null|User $user * @param string $voucherCodeInput - * @return array + * @param null|int $campaignId + * @return mixed * @throws \App\Classes\Exceptions\AccessForbiddenException * @throws \App\Classes\Exceptions\MalformedRequestException * @throws \App\Classes\Exceptions\RequestValidationException */ - public function execute(?User $userParam, string $voucherCodeInput) { - try{ - $result = null; - $user = Auth::user(); /** @var User $user */ - if($user && isset($user->type) && in_array($user->type, RoleTypes::ADMIN_ROLES) && $userParam){ - $user = User::where('id', $userParam->id)->first(); - } - else{ - $user = $userParam ? $userParam : $user; - } - - //Voucherify - Validates Voucher - $ValidateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject(0, $voucherCodeInput, 0.00, $user); - $voucherifyVoucherValidated = $this->validatesVoucherifyVoucher->execute($ValidateVoucherifyVoucherObject); - - if(isset($voucherifyVoucherValidated->reason)){ - $result = []; - $result['reason'] = $voucherifyVoucherValidated->reason; - } - else if($voucherifyVoucherValidated){ - $voucher = $this->recordVoucherInfo($user, $voucherCodeInput); - $voucherCount = $user->rewards->where('voucher_id', $voucher->id)->count(); - if($voucherCount == 0){ - $result = $this->createsUserReward->execute(null, $user, $voucher->id); - } - else{ - $result['reason'] = 'Voucher already added'; - } - } - - return $result; - } catch (\Exception $e) { - Log::error($e); - } - } - - private function recordVoucherInfo(User $user, string $voucherCodeInput){ - //Voucherify - Get Voucher + public function execute(?User $user, string $voucherCodeInput, ?int $campaignId = null) { + //Remotely - Get Voucher Voucherify $voucherifyVoucherFetched = $this->fetchesVoucherifyVoucher->execute($user, $voucherCodeInput); + $voucherName = null; + $voucherDescription = null; + + //Voucher stored locally need a name, by default use campaign name, else look into campaign metadata for displayname + if(isset($voucherifyVoucherFetched->metadata) && isset($voucherifyVoucherFetched->metadata->displayname)){ + $voucherName = $voucherifyVoucherFetched->metadata->displayname; + } + else{ + $voucherName = $voucherifyVoucherFetched->campaign; + } + + if(isset($voucherifyVoucherFetched->metadata) && isset($voucherifyVoucherFetched->metadata->display_description)){ + $voucherDescription = $voucherifyVoucherFetched->metadata->display_description; + } - $voucherName = $voucherifyVoucherFetched->campaign; $voucherType = $voucherifyVoucherFetched->discount->type; $voucherValue = isset($voucherifyVoucherFetched->discount->amount_off) ? $voucherifyVoucherFetched->discount->amount_off : $voucherifyVoucherFetched->discount->percent_off; $voucherCode = $voucherifyVoucherFetched->code; $voucherStartDate = $voucherifyVoucherFetched->start_date; $voucherEndDate = $voucherifyVoucherFetched->expiration_date; - $voucherObject= new VoucherObject($voucherCode, isset($voucherName) ? $voucherName : "Voucherify Voucher Added Manually", $voucherType, $voucherValue, $voucherStartDate, $voucherEndDate); + //Locally - Create and Fetch Voucher + $voucherObject = new VoucherObject( + $voucherCode, + $voucherName ?? "Voucher ".Carbon::now()->format('Ymd'), + $voucherDescription, + $voucherType, + $voucherValue, + $campaignId, + $voucherStartDate, + $voucherEndDate); $voucher = $this->createsVoucher->execute($voucherObject); + if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherCodeInput]); return $voucher; } diff --git a/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php b/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php index 323b2eaf..c4d959d2 100644 --- a/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php +++ b/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php @@ -18,6 +18,7 @@ use App\Classes\ValueObjects\Constants\VoucherifyEntityType; use App\Models\User; use App\Models\Transaction; use App\Models\Voucher; +use App\Models\VoucherCampaign; use Illuminate\Support\Facades\Log; class BookingToVoucherifyProcessor @@ -82,8 +83,30 @@ class BookingToVoucherifyProcessor $voucherify_customer_id = ""; $voucherify_order_id = ""; if($voucherCode){ - $redeemVoucherifyVoucherObject = new RedeemVoucherifyVoucherObject($companyId, $transaction->id, $voucherCode, $amount, $user); + $employeeWhoOwnsTheVoucher = null; + + $employees = $user->company()->first()->employees; + if(count($employees) > 1){ + foreach($employees as $singleEmployee){ + $userRewards = $singleEmployee->rewards; + foreach($userRewards as $userReward){ + if ($userReward->voucher && $userReward->voucher->code === $voucherCode) { + Log::info('3. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $voucherCode); + $employeeWhoOwnsTheVoucher = $singleEmployee; + } + } + } + } + + if(!$employeeWhoOwnsTheVoucher){ + $employeeWhoOwnsTheVoucher = $user; + } + + $redeemVoucherifyVoucherObject = new RedeemVoucherifyVoucherObject($companyId, $transaction->id, $voucherCode, $amount, $employeeWhoOwnsTheVoucher); $redeemVoucherResult = $this->redeemsVoucherifyVoucher->execute($redeemVoucherifyVoucherObject); + + // Log::info('redeemVoucherResult: '.json_encode($redeemVoucherResult)); + $redeemedVoucher = $redeemVoucherResult->voucher; $redemptionId = $redeemVoucherResult->id; @@ -95,9 +118,9 @@ class BookingToVoucherifyProcessor $voucherify_customer_id = $redeemVoucherResult->customer->id; } - $voucher = $this->recordVoucherInfo($redeemedVoucher, $transaction); + $voucher = $this->recordVoucherInfo($redeemedVoucher); $this->createsVoucherRedemption->execute($transaction, $voucher, $redemptionId, $voucherDiscountAmount); - $this->recordVoucherForUserInfo($user, $voucher); + $this->recordVoucherForUserInfo($employeeWhoOwnsTheVoucher, $voucher); } else{ $createVoucherifyOrderObject = new CreateVoucherifyOrderObject($user, $companyId, $transaction->id, $amount, true, $transaction->type == TransactionType::TOP_UP); @@ -123,8 +146,14 @@ class BookingToVoucherifyProcessor //Create records at 3 tables $voucherValue = isset($redeemedVoucher->discount->amount_off) ? $redeemedVoucher->discount->amount_off : $redeemedVoucher->discount->percent_off; $voucherType = $redeemedVoucher->discount ? $redeemedVoucher->discount->type : null; + $voucherifyCampaignId = isset($redeemedVoucher->campaign_id) ? $redeemedVoucher->campaign_id : null; - $voucherObject= new VoucherObject($redeemedVoucher->code, isset($redeemedVoucher->metadata->name) ? $redeemedVoucher->metadata->name : "", $voucherType, $voucherValue); + $voucherCampaign = null; + if($voucherifyCampaignId){ + $voucherCampaign = VoucherCampaign::where('campaign_id', $voucherifyCampaignId)->first(); + } + + $voucherObject= new VoucherObject($redeemedVoucher->code, isset($redeemedVoucher->metadata->displayname) ? $redeemedVoucher->metadata->displayname : "", null, $voucherType, $voucherValue, $voucherCampaign ? $voucherCampaign->id : null); $voucher = $this->createsVoucher->execute($voucherObject); if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); diff --git a/app/Classes/Modules/Vouchers/Processors/Voucherify/NewCustomerToVoucherifyProcessor.php b/app/Classes/Modules/Vouchers/Processors/Voucherify/NewCustomerToVoucherifyProcessor.php index 006bcd94..3fd2ccee 100644 --- a/app/Classes/Modules/Vouchers/Processors/Voucherify/NewCustomerToVoucherifyProcessor.php +++ b/app/Classes/Modules/Vouchers/Processors/Voucherify/NewCustomerToVoucherifyProcessor.php @@ -44,7 +44,9 @@ class NewCustomerToVoucherifyProcessor $createVoucherifyCustomerObject = new CreateVoucherifyCustomerObject($companyId, $user, $isNew); $result = $this->createsVoucherifyCustomer->execute($createVoucherifyCustomerObject); - if($result && isset($result->id)){ + $voucherify_entity = $user->voucherifyEntities()->get(); + + if($result && isset($result->id) && count($voucherify_entity) === 0){ $voucherEntityObject = new VoucherEntityObject($result->id, VoucherifyEntityType::CUSTOMER); $this->createsVoucherEntityMapping->execute($createVoucherifyCustomerObject->getUser(), $voucherEntityObject); } diff --git a/app/Classes/Modules/Vouchers/Services/CheckIfVoucherCampaignExists.php b/app/Classes/Modules/Vouchers/Services/CheckIfVoucherCampaignExists.php new file mode 100644 index 00000000..9e299dab --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/CheckIfVoucherCampaignExists.php @@ -0,0 +1,27 @@ +repository = $repository; + } + + public function execute(string $campaignId): bool { + return $this->repository->where('campaign_id', $campaignId)->exists(); + } + +} diff --git a/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php b/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php index 9162dda8..88a9a133 100644 --- a/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php +++ b/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php @@ -22,7 +22,7 @@ class CreatesVoucher extends AbstractUpdateRecord /** * @param VoucherObject $object - * @return \Illuminate\Database\Eloquent\Model + * @return \Illuminate\Database\Eloquent\Model|null * @throws \App\Classes\Exceptions\MalformedRequestException */ public function execute(VoucherObject $object) { @@ -31,8 +31,10 @@ class CreatesVoucher extends AbstractUpdateRecord $model = new Voucher(); $model->code = $object->getCode(); $model->name = $object->getName(); + $model->description = $object->getDescription(); $model->type = $object->getType(); $model->value = $object->getValue(); + $model->voucher_campaign_id = $object->getVoucherCampaignId(); $model->start_date = $object->getStartDate(); $model->end_date = $object->getEndDate(); return $this->handler($model); diff --git a/app/Classes/Modules/Vouchers/Services/CreatesVoucherCampaign.php b/app/Classes/Modules/Vouchers/Services/CreatesVoucherCampaign.php new file mode 100644 index 00000000..171c2d18 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/CreatesVoucherCampaign.php @@ -0,0 +1,41 @@ +campaignExists = $campaignExists; + } + + /** + * @param VoucherCampaignObject $object + * @return \Illuminate\Database\Eloquent\Model|null + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(VoucherCampaignObject $object) { + if(!$this->campaignExists->execute($object->getCampaignId())) + { + $model = new VoucherCampaign(); + $model->campaign_id = $object->getCampaignId(); + $model->name = $object->getName(); + $model->description = $object->getDescription(); + $model->limit_per_month = $object->getLimitPerMonth(); + return $this->handler($model); + } + return null; + } +} diff --git a/app/Classes/Modules/Vouchers/Services/FetchesVoucherCampaign.php b/app/Classes/Modules/Vouchers/Services/FetchesVoucherCampaign.php new file mode 100644 index 00000000..b5f66178 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/FetchesVoucherCampaign.php @@ -0,0 +1,34 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Vouchers/Services/ListsVoucherCampaigns.php b/app/Classes/Modules/Vouchers/Services/ListsVoucherCampaigns.php new file mode 100644 index 00000000..d9b141ff --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/ListsVoucherCampaigns.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Vouchers/Services/UpdatesVoucherCampaign.php b/app/Classes/Modules/Vouchers/Services/UpdatesVoucherCampaign.php new file mode 100644 index 00000000..06501569 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/UpdatesVoucherCampaign.php @@ -0,0 +1,26 @@ +name = $object->getName(); + $model->description = $object->getDescription(); + $model->limit_per_month = $object->getLimitPerMonth(); + + return $this->handler($model); + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyCustomer.php b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyCustomer.php index a15fe9c3..5964fce4 100644 --- a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyCustomer.php +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyCustomer.php @@ -59,7 +59,7 @@ class CreatesVoucherifyCustomer return $result; } catch (\Voucherify\ClientException $e) { // throw $e; - Log::error($e); + Log::error('CreatesVoucherifyCustomer '.$e); return null; } } diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyOrder.php b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyOrder.php index 90e5d682..2abb6166 100644 --- a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyOrder.php +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyOrder.php @@ -55,7 +55,7 @@ class CreatesVoucherifyOrder $result = $this->voucherifyClient->orders->create($orderObj); return $result; } catch (\Voucherify\ClientException $e) { - Log::error($e); + Log::error('CreatesVoucherifyOrder '.$e); return null; } } diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucher.php b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucher.php index ad95946b..db4f7198 100644 --- a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucher.php +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucher.php @@ -52,7 +52,7 @@ class CreatesVoucherifyVoucher ]); return $result; } catch (\Voucherify\ClientException $e) { - Log::error($e); + Log::error('CreatesVoucherifyVoucher '.$e); return null; } } diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucherInACampaign.php b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucherInACampaign.php new file mode 100644 index 00000000..1916b1ef --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucherInACampaign.php @@ -0,0 +1,40 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param string $campaignName + * @param string $code + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(string $campaignName, string $code) + { + try { + $result = $this->voucherifyClient->campaigns->addVoucherWithCode($campaignName, $code); + return $result; + } catch (\Voucherify\ClientException $e) { + Log::error('CreatesVoucherifyVoucherInACampaign '.$e); + return null; + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyCampaign.php b/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyCampaign.php new file mode 100644 index 00000000..afd6b941 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyCampaign.php @@ -0,0 +1,60 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param string $campaignId + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(string $campaignId) + { + //REST API - Direct Query + try{ + $response = Http::withHeaders([ + 'X-App-Id' => config('voucherify.application_id'), + 'X-App-Token' => config('voucherify.client_secret_key'), + ]) + ->get(config('voucherify.url').'/v1/campaigns/'.$campaignId); + + if($response->successful()){ + $data = $response->json(); + return (object) $data; + }else{ + Log::error($response); + return null; + } + }catch(\Exception $exception){ + throw new MalformedRequestException('Unable to get correct response from Voucherify: ' . $exception->getMessage()); + } + + //PHP SDK + // try { + // $result = $this->voucherifyClient->campaigns->get($name); //this is undefined in voucherify php sdk + // return $result; + // } catch (\Voucherify\ClientException $e) { + // Log::error('FetchesVoucherifyCampaign '.$e); + // return null; + // } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyRedemption.php b/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyRedemption.php new file mode 100644 index 00000000..03966926 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyRedemption.php @@ -0,0 +1,38 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param string $redemptionId + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(string $redemptionId) + { + try { + $result = $this->voucherifyClient->redemptions->get($redemptionId); + return $result; + } catch (\Voucherify\ClientException $e) { + Log::error('FetchesVoucherifyRedemption '.$e); + return null; + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyVoucher.php b/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyVoucher.php index 8c4d33b7..3ad962d6 100644 --- a/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyVoucher.php +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyVoucher.php @@ -40,7 +40,7 @@ class FetchesVoucherifyVoucher return $result; } catch (\Voucherify\ClientException $e) { - Log::error($e); + Log::error('FetchesVoucherifyVoucher '.$e); return null; } } diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/ListsVoucherifyVouchers.php b/app/Classes/Modules/Vouchers/Services/Voucherify/ListsVoucherifyVouchers.php new file mode 100644 index 00000000..217b9a3a --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/ListsVoucherifyVouchers.php @@ -0,0 +1,85 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param string $campaignId + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(string $campaignId) + { + + //PHP SDK +// try { +// $listVouchers = $this->voucherifyClient->vouchers->getList([ +// "campaign" => $campaignName, +// ]); +// if (isset($listVouchers->vouchers) && isset($listVouchers->total) && $listVouchers->total > 0) { +// $campaignId = $listVouchers->vouchers[0]->campaign_id; +// } +// } catch (\Voucherify\ClientException $e) { +// Log::error('ListsVoucherifyVouchers '.$e); +// return null; +// } + + //REST API - Direct Query + try{ + $dateRange = $this->getDateRangeForMonth(Carbon::now()->year, Carbon::now()->month); + $queryString = http_build_query([ + 'limit' => 50, + 'campaign_id' => $campaignId, + '[created_at][after]' => $dateRange['start'], + '[created_at][before]' => $dateRange['end'], + ]); + //$queryString = 'limit=50&campaign_id=' . $campaignId . '&[created_at][after]='. $dateRange['start'] . '&[created_at][before]='. $dateRange['end']; + $response = Http::withHeaders([ + 'X-App-Id' => config('voucherify.application_id'), + 'X-App-Token' => config('voucherify.client_secret_key'), + ]) + ->get(config('voucherify.url').'/v1/vouchers?'.$queryString); + + if($response->successful()){ + $data = $response->json(); + return (object) $data; + }else{ + Log::error($response); + return null; + } + }catch(\Exception $exception){ + throw new MalformedRequestException('Unable to get correct response from Voucherify: ' . $exception->getMessage()); + } + } + + private function getDateRangeForMonth($year, $month) { + $startDate = Carbon::createFromFormat('Y-m-d H:i:s', "{$year}-{$month}-01 00:00:00", 'Asia/Kuala_Lumpur')->startOfDay()->setTimezone('UTC'); + $endDate = Carbon::createFromFormat('Y-m-d H:i:s', "{$year}-{$month}-01 00:00:00", 'Asia/Kuala_Lumpur')->endOfMonth()->setTimezone('UTC'); + + return [ + 'start' => $startDate->toISOString(), + 'end' => $endDate->toISOString(), //'2024-07-11T15:59:59.999999Z' + ]; + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/RedeemsVoucherifyVoucher.php b/app/Classes/Modules/Vouchers/Services/Voucherify/RedeemsVoucherifyVoucher.php index 7c44889b..eca9d611 100644 --- a/app/Classes/Modules/Vouchers/Services/Voucherify/RedeemsVoucherifyVoucher.php +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/RedeemsVoucherifyVoucher.php @@ -3,6 +3,7 @@ namespace App\Classes\Modules\Vouchers\Services\Voucherify; use App\Classes\Modules\Vouchers\DataTransferObjects\RedeemVoucherifyVoucherObject; +use Illuminate\Support\Facades\Log; class RedeemsVoucherifyVoucher { @@ -45,6 +46,7 @@ class RedeemsVoucherifyVoucher ]); return $result; } catch (\Voucherify\ClientException $e) { + Log::error('RedeemsVoucherifyVoucher '.$e); throw $e; } } diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/UpdatesVoucherifyOrder.php b/app/Classes/Modules/Vouchers/Services/Voucherify/UpdatesVoucherifyOrder.php index 80aae605..51c6c29e 100644 --- a/app/Classes/Modules/Vouchers/Services/Voucherify/UpdatesVoucherifyOrder.php +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/UpdatesVoucherifyOrder.php @@ -36,7 +36,7 @@ class UpdatesVoucherifyOrder ]); return $result; } catch (\Voucherify\ClientException $e) { - Log::error($e); + Log::error('UpdatesVoucherifyOrder '.$e); return null; } } diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/ValidatesVoucherifyVoucher.php b/app/Classes/Modules/Vouchers/Services/Voucherify/ValidatesVoucherifyVoucher.php index 3fa322d5..7c22db5c 100644 --- a/app/Classes/Modules/Vouchers/Services/Voucherify/ValidatesVoucherifyVoucher.php +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/ValidatesVoucherifyVoucher.php @@ -41,6 +41,7 @@ class ValidatesVoucherifyVoucher ] ] ]; + if ($validateVoucherifyVoucherObject->getAmount()) { $validateVoucherObj['order'] = [ "amount" => $validateVoucherifyVoucherObject->getAmount() * 100 //converting it to cents @@ -63,7 +64,7 @@ class ValidatesVoucherifyVoucher return $result; } catch (\Voucherify\ClientException $e) { // throw $e; - Log::error($e); + Log::error('ValidatesVoucherifyVoucher '.$e); return null; } } diff --git a/app/Classes/Modules/Vouchers/Standards/Rules/CanCreateVoucher.php b/app/Classes/Modules/Vouchers/Standards/Rules/CanCreateVoucher.php new file mode 100644 index 00000000..af40f6aa --- /dev/null +++ b/app/Classes/Modules/Vouchers/Standards/Rules/CanCreateVoucher.php @@ -0,0 +1,66 @@ +voucherValidation = $voucherValidation; + } + + /** + * @param CreateVoucherObject $object + * @return bool + */ + protected function authorized($object): bool + { + $isAuthorized = true; + switch ($object->getVoucherCode()) { + case Vouchers::SORRY_50: + case Vouchers::SORRY_100: + case Vouchers::SORRY_200: + // $isAuthorized = Auth::user()->can('add voucher'); + $isAuthorized = in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES); + break; + default: + $isAuthorized = true; + break; + } + return $isAuthorized; + } + + /** + * @param CreateVoucherObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return true; + } + + /** + * @param CreateVoucherObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } +} diff --git a/app/Classes/Modules/Vouchers/Standards/Rules/CanListVoucherCampaigns.php b/app/Classes/Modules/Vouchers/Standards/Rules/CanListVoucherCampaigns.php new file mode 100644 index 00000000..e5c384ee --- /dev/null +++ b/app/Classes/Modules/Vouchers/Standards/Rules/CanListVoucherCampaigns.php @@ -0,0 +1,42 @@ +can('list voucher campaigns')) { + if (!in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)) { + return false; + } + return true; + } + + /** + * @param $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return true; + } + + /** + * @param $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } +} diff --git a/app/Classes/Modules/Vouchers/Standards/Validators/VoucherValidation.php b/app/Classes/Modules/Vouchers/Standards/Validators/VoucherValidation.php new file mode 100644 index 00000000..d22e0064 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Standards/Validators/VoucherValidation.php @@ -0,0 +1,47 @@ + $object->getUser(), + 'voucherCode' => $object->getVoucherCode(), + ]; + + return $data; + } + + /** + * @param null|string $type + * @return array + */ + protected function rules(): array { + return [ + 'user' => [ + 'required', + ], + 'voucherCode' => [ + 'required', + ] + ]; + } + + /** + * @return array + */ + protected function messages(): array { + return []; + } + +} diff --git a/app/Classes/Modules/Wallets/Standards/Rules/CanCreateCompanyWallet.php b/app/Classes/Modules/Wallets/Standards/Rules/CanCreateCompanyWallet.php index 0f1dd065..f07e3ae0 100644 --- a/app/Classes/Modules/Wallets/Standards/Rules/CanCreateCompanyWallet.php +++ b/app/Classes/Modules/Wallets/Standards/Rules/CanCreateCompanyWallet.php @@ -26,7 +26,7 @@ class CanCreateCompanyWallet extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Wallets/Standards/Rules/CanCreateWalletTransaction.php b/app/Classes/Modules/Wallets/Standards/Rules/CanCreateWalletTransaction.php index 8beafb37..ad217040 100644 --- a/app/Classes/Modules/Wallets/Standards/Rules/CanCreateWalletTransaction.php +++ b/app/Classes/Modules/Wallets/Standards/Rules/CanCreateWalletTransaction.php @@ -23,7 +23,7 @@ class CanCreateWalletTransaction extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Wallets/Standards/Rules/CanListWallet.php b/app/Classes/Modules/Wallets/Standards/Rules/CanListWallet.php index c87cb316..de944f61 100644 --- a/app/Classes/Modules/Wallets/Standards/Rules/CanListWallet.php +++ b/app/Classes/Modules/Wallets/Standards/Rules/CanListWallet.php @@ -23,7 +23,7 @@ class CanListWallet extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Wallets/Standards/Rules/CanTopUpWallet.php b/app/Classes/Modules/Wallets/Standards/Rules/CanTopUpWallet.php index 9a005498..0f3cbc64 100644 --- a/app/Classes/Modules/Wallets/Standards/Rules/CanTopUpWallet.php +++ b/app/Classes/Modules/Wallets/Standards/Rules/CanTopUpWallet.php @@ -23,7 +23,7 @@ class CanTopUpWallet extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Wallets/Standards/Rules/CanWithdrawWallet.php b/app/Classes/Modules/Wallets/Standards/Rules/CanWithdrawWallet.php index 6fb4019d..a2cd3b6a 100644 --- a/app/Classes/Modules/Wallets/Standards/Rules/CanWithdrawWallet.php +++ b/app/Classes/Modules/Wallets/Standards/Rules/CanWithdrawWallet.php @@ -23,7 +23,7 @@ class CanWithdrawWallet extends AbstractRule /** * @return bool */ - protected function authorized(): bool + protected function authorized($object): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Notifications/WelcomeVoucherEmail.php b/app/Classes/Notifications/WelcomeVoucherEmail.php new file mode 100644 index 00000000..0800b8cc --- /dev/null +++ b/app/Classes/Notifications/WelcomeVoucherEmail.php @@ -0,0 +1,43 @@ +user = $user; + $this->voucher = $voucher; + } + + + public function toMail() + { + $this->voucher->end_date = Carbon::parse($this->voucher->end_date)->format('Y-m-d'); + $mailMessage = (new MailMessage) + ->subject('Welcome Voucher') + ->view('emails.accounts.welcome_voucher', ['user' => $this->user, 'voucher' => $this->voucher]); + + return $mailMessage; + } + + +} diff --git a/app/Classes/ValueObjects/Constants/BankAccountType.php b/app/Classes/ValueObjects/Constants/BankAccountType.php index c1ae288e..0393091f 100644 --- a/app/Classes/ValueObjects/Constants/BankAccountType.php +++ b/app/Classes/ValueObjects/Constants/BankAccountType.php @@ -8,6 +8,8 @@ final class BankAccountType { public const EXTERNAL = 2; - public const ALIPAY= 3; + public const ALIPAY_1688 = 3; + + public const ALIPAY_RECIPIENT = 4; } diff --git a/app/Classes/ValueObjects/Constants/BookingAttributeNames.php b/app/Classes/ValueObjects/Constants/BookingAttributeNames.php new file mode 100644 index 00000000..491ad0a2 --- /dev/null +++ b/app/Classes/ValueObjects/Constants/BookingAttributeNames.php @@ -0,0 +1,8 @@ + "PAYMENT_ATTEMPT", + self::PAYMENT => "PAYMENT", + self::INVOICE => "INVOICE", + self::BILL => "BILL", + self::PROFORMA => "PROFORMA", + self::TOP_UP => "TOP_UP", + self::REFUND => "REFUND", + self::PURCHASE_ORDER => "PURCHASE_ORDER", + self::SUPPLIER_DELIVER => "SUPPLIER_DELIVER", + self::CREDIT_NOTE => "CREDIT_NOTE", + self::DEBIT_NOTE => "DEBIT_NOTE", + self::WITHDRAW => "WITHDRAW", + self::TRANSFER_FEE => "TRANSFER_FEE", + self::CASH_BACK => "CASH_BACK", + self::SUPPLIER_PAYMENT => "SUPPLIER_PAYMENT", + self::SUPPLIER_REFUND => "SUPPLIER_REFUND", + ]; + + } diff --git a/app/Classes/ValueObjects/Constants/Vouchers.php b/app/Classes/ValueObjects/Constants/Vouchers.php new file mode 100644 index 00000000..4c6c8bb1 --- /dev/null +++ b/app/Classes/ValueObjects/Constants/Vouchers.php @@ -0,0 +1,20 @@ + 'SORRY 50', 'id' => Vouchers::SORRY_50], + ['text' => 'SORRY 100', 'id' => Vouchers::SORRY_100], + ['text' => 'SORRY 200', 'id' => Vouchers::SORRY_200], + ['text' => 'PROM150%', 'id' => Vouchers::PROM150PERCENT], + ]; +} diff --git a/app/Console/Commands/AutoFillPurchaseOrderCommand.php b/app/Console/Commands/AutoFillPurchaseOrderCommand.php new file mode 100644 index 00000000..65a6fa93 --- /dev/null +++ b/app/Console/Commands/AutoFillPurchaseOrderCommand.php @@ -0,0 +1,113 @@ +generatesPurchaseOrderProducts = $generatesPurchaseOrderProducts; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + // 5. If purchase order not fill up in 2 month, auto fill up it + $bookings = Booking::where('status', ApprovalStatus::APPROVED) + ->where('created_at', '<', now()->subDays(60)->endOfDay()) + ->whereHas('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }) + ->whereDoesntHave('transactions', function($transaction){ + $transaction->where('type', TransactionType::PURCHASE_ORDER); + $transaction->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]); + })->get(); + + foreach ($bookings as $booking) { + $po = Transaction::where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::APPROVED)->where('issuer', $booking->company_id) + ->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first(); + + + if (!$po) { + $po = Transaction::where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::APPROVED)->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first(); + } + + $products = $this->generatesPurchaseOrderProducts->execute($po, $booking->fix_amount); + + $deference = $booking->fix_amount - $products->sum('total'); + + if($deference > -150 && $deference < 150 && $deference != 0) { + + $products->push([ + 'description' => $deference < 0 ? 'Discount':'Shipping Fee', + 'quantity' => 1, + 'stockCode' => '', + 'total' => $deference, + 'unit_price' => $deference + ]); + } + + $billNumber = $this->generatesTransactionBillNumber->execute('XPO-'); + + $total = $products->sum('total'); + + $object = new TransactionObject($billNumber, TransactionType::PURCHASE_ORDER, $booking->company->id, 1, + 1, PaymentMethodType::CASH, + $total, $total, $booking->fix_currency_id, $booking->fix_currency_id, + 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $products->toArray()); + + $this->createPurchaseOrderTransactionProcessor->execute($booking, $object); + } + } +} diff --git a/app/Console/Commands/DeleteDuplicate1688BankAccount.php b/app/Console/Commands/DeleteDuplicate1688BankAccount.php new file mode 100644 index 00000000..57b65733 --- /dev/null +++ b/app/Console/Commands/DeleteDuplicate1688BankAccount.php @@ -0,0 +1,75 @@ +get(); + + $groupedBanks = $records->groupBy(function($item, $key) { + return $item['company_id'] . '-' . $item['account_no']; + }); + + foreach ($groupedBanks as $key => $banksWithSameUserAndAccountNo) { + // Sort banks by created_at or updated_at to find the latest one + $sortedBanks = $banksWithSameUserAndAccountNo->sortByDesc('created_at'); + + // Retain the latest bank + $latestBank = $sortedBanks->first(); + + // Get all IDs except the latest one + $idsToDelete = $sortedBanks->pluck('id')->slice(1); + + foreach ($idsToDelete as $id) { + Booking::where('bank_id', $id)->update([ + 'bank_id' => $latestBank->id + ]); + } + + $this->info('for company id: ' . $latestBank->company_id . ', account no: ' . $latestBank->account_no . ', duplicated id: ' . $idsToDelete); + // Delete the rest + Bank::whereIn('id', $idsToDelete)->delete(); + } + } +} diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php new file mode 100644 index 00000000..17a0158e --- /dev/null +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -0,0 +1,101 @@ +updatesBookingStatus = $updatesBookingStatus; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + // 1. Cancel booking without payment & purchase order (1 month) + $bookings = Booking::where('status', ApprovalStatus::APPROVED) + ->where('created_at', '<', now()->subDays(30)->endOfDay()) + ->where('service_id', '!=', 4) + ->where(function ($query) { + $query->whereDoesntHave('transactions') + ->orWhereDoesntHave('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PURCHASE_ORDER)->orWhere(function ($q) { + $q->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED]); + }); + }); + })->get(); + + foreach ($bookings as $booking) { + $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); + $this->info(Carbon::now() . " : Expired Booking without payment & purchase order, booking id: " . $booking->id); + $transactions = $booking->transactions; + + foreach ($transactions as $transaction) { + $prevStatus = $transaction->status; + $transaction->status = ApprovalStatus::EXPIRED; + $transaction->save(); + $this->info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); + } + } + + // 2. Cancel booking without payment but with purchase order (2 month) + $bookings = Booking::where('status', ApprovalStatus::APPROVED) + ->where('created_at', '<', now()->subDays(60)->endOfDay()) + ->where(function ($query) { + $query->whereDoesntHave('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED]); + })->whereHas('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PURCHASE_ORDER); + }); + })->get(); + + foreach ($bookings as $booking) { + $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); + $this->info(Carbon::now() . " : Expired Booking without payment but with purchase order, booking id: " . $booking->id); + $transactions = $booking->transactions; + + foreach ($transactions as $transaction) { + $prevStatus = $transaction->status; + $transaction->status = ApprovalStatus::EXPIRED; + $transaction->save(); + $this->info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); + } + } + } +} diff --git a/app/Console/Commands/ExpiredRefundedBookingCommand.php b/app/Console/Commands/ExpiredRefundedBookingCommand.php new file mode 100644 index 00000000..92900a71 --- /dev/null +++ b/app/Console/Commands/ExpiredRefundedBookingCommand.php @@ -0,0 +1,197 @@ +updatesBookingStatus = $updatesBookingStatus; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsTransaction = $createsTransaction; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + // 3. Cancel fully refunded payment & cancel booking + $transactions = Transaction::where('type', TransactionType::CREDIT_NOTE)->where('payment_reference', 'LIKE', "%refund%")->get(); + + foreach ($transactions as $transaction) { + // get the booking marking + $payment_reference = explode(" ", trim($transaction->payment_reference)); + // $marking = substr($transaction->payment_reference, -5); + $marking = trim(end($payment_reference)); + + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode(".", trim($transaction->payment_reference)); + $marking = trim(end($payment_reference)); + } + + // for a special payment reference on transaction id: 140231 + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode("No", trim($transaction->payment_reference)); + $marking = end($payment_reference); + } + + // for a special payment reference on transaction id: 152013 + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode(" ", trim($transaction->payment_reference)); + $marking = end($payment_reference); + $marking = prev($payment_reference); + } + + if (preg_match('/^[0-9]+$/', $marking)) { + $booking = Booking::where('marking', $marking)->first(); + + if ($booking) { + $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + if (!$bookingPayment) { + $bookingPaymentCount = $booking->transactions()->payments()->count(); + if ($bookingPaymentCount > 1) { + $this->info("Credit note transaction id: {$transaction->id}, there are {$bookingPaymentCount} payment for the booking."); + foreach ($booking->transactions()->payments()->get() as $bp) { + if ($transaction->amount - $bp->amount < 0.01) { + $bookingPayment = $bp; + break; + } + } + } + + if (!$bookingPayment) { + $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::SUSPENDED, ApprovalStatus::EXPIRED, ApprovalStatus::REJECTED])->orderBy('id', 'DESC')->first(); + } + } + + if ($bookingPayment) { + $status = ApprovalStatus::APPROVAL_STATUS_ID[$bookingPayment->status]; + $this->info("Credit note transaction id: {$transaction->id}, the payment for the booking is in status {$status}"); + + $bookingPaymentAmount = $bookingPayment->amount; + // check if the booking is fully refund + $amountDifference = bcsub($transaction->amount, $bookingPaymentAmount, 7); + + $isFullyRefund = false; + if (abs($amountDifference) < 0.01) { + $isFullyRefund = true; + // update fully refunded booking payment transaction + $bookingPayment->status = ApprovalStatus::REFUNDED; + $bookingPayment->save(); + + //expired booking + // $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); + $this->info("Credit note transaction id: {$transaction->id} is fully refunded, the refunded amount was {$transaction->amount} the payment reference is: {$transaction->payment_reference}"); + // $this->info("Credit note transaction id: {$transaction->id}, Rejected Booking Transaction Payment id: {$bookingPayment->id}, the payment amount was {$bookingPayment->amount}"); + // $this->info("Credit note transaction id: {$transaction->id}, Expired Booking id: {$booking->id}"); + } else { + $this->info("Credit note transaction id: {$transaction->id} is not fully refunded, the refunded amount was {$transaction->amount}, the payment amount was {$bookingPayment->amount}, the payment reference is: {$transaction->payment_reference}"); + } + + $refund = $bookingPayment->transactions()->refunds()->where('amount', $transaction->amount)->where('status', ApprovalStatus::APPROVED)->first(); + + $bookingInWhiteForm = $bookingPayment->transactions()->bills()->first(); + + if ($refund) { + $this->info("Credit note transaction id: {$transaction->id}, already created same amount of refund transaction for same booking payment transaction"); + } + + if (!$refund) { + $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); + + $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, + 1, PaymentMethodType::CASH, + $transaction->amount, $isFullyRefund ? $bookingPayment->original_amount : $transaction->amount * $bookingPayment->currency_rate, 1, + $bookingPayment->original_currency_id, $bookingPayment->currency_rate, + 0, 0, null, ApprovalStatus::APPROVED, [], $bookingPayment->bill_no); + + $transaction = $this->createsTransaction->execute($bookingPayment, $object); + } + + if ($bookingInWhiteForm) { + $original_amount = $isFullyRefund ? $bookingPayment->original_amount : bcmul($transaction->amount, $bookingPayment->currency_rate, 7); + $supplier_refund_amount = bcdiv($original_amount, $bookingInWhiteForm->currency_rate, 7); + + $this->info("Credit note transaction id: {$transaction->id}, booking is in white form, white form currency rate is {$bookingInWhiteForm->currency_rate}"); + + // if ($isFullyRefund && $bookingInWhiteForm->currency_rate == 1) { + // dd ($bookingInWhiteForm->owner_id); + // } + + $refund = $bookingPayment->transactions()->supplierRefunds()->where('original_amount', $original_amount)->first(); + + if (!$refund) { + $billNumber = $this->generatesTransactionBillNumber->execute('SRFD-'); + + $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_REFUND, 1, $bookingInWhiteForm->issuer, + 1, PaymentMethodType::CASH, + $supplier_refund_amount, $original_amount, 1, + $bookingPayment->original_currency_id, $bookingInWhiteForm->currency_rate, + 0, 0, null, ApprovalStatus::APPROVED, [], $bookingPayment->bill_no); + + $transaction = $this->createsTransaction->execute($bookingPayment, $object); + } + } + } else { + // $bookingPayment = $booking->transactions()->payments()->where('status', ApprovalStatus::REFUNDED)->orderBy('id', 'DESC')->first(); + + // if ($bookingPayment) { + // $this->info("Credit note transaction id: {$transaction->id}, booking payment refunded"); + // } else { + $this->info("Credit note transaction id: {$transaction->id}, booking payment not found, the payment reference is: {$transaction->payment_reference}"); + // } + } + } else { + $this->info("Credit note transaction id: {$transaction->id}, booking marking not found, the payment reference is: {$transaction->payment_reference}"); + } + } else { + $this->info("Credit note transaction id: {$transaction->id} does not have booking marking, the payment reference is: {$transaction->payment_reference}"); + } + } + } +} diff --git a/app/Console/Commands/FixExpiredBookingWithRefundedPaymentTransactionCommand.php b/app/Console/Commands/FixExpiredBookingWithRefundedPaymentTransactionCommand.php new file mode 100644 index 00000000..b8e27996 --- /dev/null +++ b/app/Console/Commands/FixExpiredBookingWithRefundedPaymentTransactionCommand.php @@ -0,0 +1,67 @@ +whereHas('transactions', function ($q) { + $q->where('type', TransactionType::PAYMENT)->where('status', ApprovalStatus::EXPIRED)->whereHas('transactions', function ($q2) { + $q2->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + })->get(); + + foreach ($bookings as $booking) { + $payment_transactions = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereHas('transactions', function ($q2) { + $q2->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->get(); + + foreach ($payment_transactions as $payment) { + $payment_original_amount = $payment->original_amount; + $refund_original_amount = $payment->transactions()->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('original_amount'); + + if ($payment_original_amount - $refund_original_amount < 0.01) { + $this->info("Updated booking id: $booking->id, payment transaction id: $payment->id, from EXPIRED to REFUNDED"); + + $payment->status = ApprovalStatus::REFUNDED; + $payment->save(); + } + } + } + } +} diff --git a/app/Console/Commands/OneTimeTestVoucherifyEmailCommand.php b/app/Console/Commands/OneTimeTestVoucherifyEmailCommand.php new file mode 100644 index 00000000..377bf052 --- /dev/null +++ b/app/Console/Commands/OneTimeTestVoucherifyEmailCommand.php @@ -0,0 +1,90 @@ +fetchesVoucher = $fetchesVoucher; + $this->generatesEmailVerificationAttempt = $generatesEmailVerificationAttempt; + $this->sendUserVerificationEmail = $sendUserVerificationEmail; + $this->generatesPasswordReset = $generatesPasswordReset; + $this->sendResetPasswordEmail = $sendResetPasswordEmail; + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + try{ //In case voucher got deleted unintentionally + $user = User::where('id', 3974)->first(); //5436, 3974 + + Log::info(json_encode($user)); + $voucher = $this->fetchesVoucher->execute(['code' => Vouchers::WELCOME_50_PERCENT_OFF]); + Log::info(json_encode($voucher)); + if($voucher) SendWelcomeVoucherEmail::dispatch($user, $voucher, 1); + + // $attempt = $this->generatesEmailVerificationAttempt->execute($user); + // $this->sendUserVerificationEmail::dispatch($user, $attempt); + + // $attempt = $this->generatesPasswordReset->execute($user); + // $this->sendResetPasswordEmail::dispatch($user, $attempt); + } + catch(\Exception $e){} + + } + +} diff --git a/app/Console/Commands/UpdateBillGroupAndGroupToIncludeTransferFee.php b/app/Console/Commands/UpdateBillGroupAndGroupToIncludeTransferFee.php new file mode 100644 index 00000000..7b3508c7 --- /dev/null +++ b/app/Console/Commands/UpdateBillGroupAndGroupToIncludeTransferFee.php @@ -0,0 +1,140 @@ +updateGroupLogic = $updateGroupLogic; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + + // update group to include transfer fee + $groups = Group::where('created_at', '>=', '2024-06-01')->get(); + + foreach ($groups as $group) { + $group_transfer_fee = 0; + + $morph_transaction = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + if ($morph_transaction) { + $group_transfer_fee = $morph_transaction->original_amount; + } + + + $originalTransferFees = (float)Transaction::where('type', TransactionType::TRANSFER_FEE)->whereIn('owner_id', $group->transactions->pluck('id'))->sum('service_charge'); + $correctOriginalAmount = $group->transactions()->sum('original_amount'); + $correctOriginalAmount = $correctOriginalAmount + $originalTransferFees + $group_transfer_fee; + $correctAmount = $group->transactions()->sum('amount'); + $transferFees = $originalTransferFees / $group->currency_rate; + $correctAmount = $correctAmount + $transferFees + ($group_transfer_fee / $group->currency_rate) + $group->service_charge; + + if ($group->original_amount != $correctOriginalAmount || $group->amount != $correctAmount) { + $group->original_amount = $correctOriginalAmount; + $group->amount = $correctAmount; + $group->save(); + + $this->info("updated group id: {$group->id}, added transfer fee CNY {$correctOriginalAmount}"); + } + } + + // update group calculation to include individual group transfer fee + // $groups = Group::whereHas('morphTransactions', function ($q) { + // $q->where('type', TransactionType::TRANSFER_FEE); + // })->get(); + + // foreach ($groups as $group) { + // $route = FacadesRoute::getRoutes()->getByName('api.transaction.group.update'); + // $request = Request::create(route('api.transaction.group.update', $group->id)); + // $uri = $route->uri; + // $request->setRouteResolver(function () use ($request, $uri) { + // // Associate Route to request so we can access route parameters. + // return (new Route('PUT', $uri, []))->bind($request); + // }); + + // $request['rate'] = $group->currency_rate; + // $request['supplier_id'] = $group->issuer; + // $this->updateGroupLogic->execute($request); + + // $group_transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + // $this->info("updated group id: {$group->id}, added transfer fee to individual white form CNY {$group_transfer_fee->original_amount}"); + // } + + // update bill group calculation to include individual group transfer fee + $billGroups = BillGroup::all(); + + foreach ($billGroups as $billGroup) { + // ignore those has bill group refund + if ($billGroup->billRefunds()->count() > 0) { + continue; + } + + $totalOriginal = round($billGroup->groups()->sum('original_amount'), 2); + $total = round($billGroup->groups()->sum('amount') + $billGroup->service_charge, 2); + + // update bill group payment transaction amount if there is only 1 payment transaction + $payment_transactions = $billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get(); + + if ($payment_transactions->count() === 1) { + $payment_transaction = $payment_transactions->first(); + + if ($payment_transaction->amount - ($billGroup->amount + $billGroup->service_charge) < 0.01) { + $payment_transaction->original_amount = $total; + $payment_transaction->amount = $total; + $payment_transaction->save(); + $this->info("updated bill group payment transaction id: {$payment_transaction->id}, update original amount to CNY {$totalOriginal}"); + } + } + + // update bill group amount and original amount + $billGroup->original_amount = $totalOriginal; + $billGroup->amount = $total; + $billGroup->save(); + + $this->info("updated bill group id: {$billGroup->id}, added transfer fee, final original amount is CNY {$totalOriginal}"); + } + } +} diff --git a/app/Console/Commands/UpdateWrongFullyRefundPaymentReference.php b/app/Console/Commands/UpdateWrongFullyRefundPaymentReference.php new file mode 100644 index 00000000..20ba3360 --- /dev/null +++ b/app/Console/Commands/UpdateWrongFullyRefundPaymentReference.php @@ -0,0 +1,69 @@ +whereDate('created_at', '>=', Carbon::createFromDate(2024, 4, 2))->get(); + + foreach ($transactions as $transaction) { + $booking_marking = trim(explode('.', $transaction->payment_reference)[1]); + $booking = Booking::where('marking', $booking_marking)->first(); + + if ($booking) { + $payments = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED])->get(); + + if ($payments->count() === 0) { + $this->info("Booking ID: {$booking->id}, payment not found"); + } else if ($payments->count() > 1) { + $this->info("Booking ID: {$booking->id}, more than 1 payment found"); + } else { + $payment = $payments->first(); + + if (!($payment->amount - $transaction->amount < 0.01)) { + $transaction->payment_reference = str_replace('Fully', 'Partially', $transaction->payment_reference); + $transaction->save(); + $this->info("Updated Payment Reference of Transaction ID: {$transaction->id}, corrected from Fully Refund to Partially Refund"); + } + } + } + } + } +} diff --git a/app/Console/Commands/UpdateWrongGroupCurrencyRate.php b/app/Console/Commands/UpdateWrongGroupCurrencyRate.php new file mode 100644 index 00000000..fbe7245b --- /dev/null +++ b/app/Console/Commands/UpdateWrongGroupCurrencyRate.php @@ -0,0 +1,126 @@ +createsDocument = $createsDocument; + $this->createsFile = $createsFile; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + $groups = Group::where('currency_rate', '>', 100)->get(); + + foreach ($groups as $group) { + $transactions = $group->transactions()->get(); + + $rate = DB::table('transaction_logs')->where('transaction_id', $transactions->first()->id)->latest('updated_at')->first()->currency_rate; + + $supplier = $group->issuerCompany; + + foreach ($transactions as $transaction) { + $transaction->currency_rate = $rate; + $transaction->amount = $transaction->original_amount / $rate; + $transaction->save(); + + $supplierRefundTransactions = $transaction->owner->transactions()->supplierRefunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->get(); + + foreach ($supplierRefundTransactions as $supplierRefundTransaction) { + $claimBefore = $supplierRefundTransaction->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->exists(); + + if (!$claimBefore) { + $supplierRefundTransaction->currency_rate = $rate; + $supplierRefundTransaction->amount = $supplierRefundTransaction->original_amount / $rate; + $supplierRefundTransaction->save(); + } + } + } + + $group_transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + $group_transfer_fee_original_amount = 0; + + if ($group_transfer_fee) { + $group_transfer_fee_original_amount = $group_transfer_fee->original_amount; + } + + $transferFeeTransactions = $group->transactions()->with([ + 'transactions' => function ($transaction) { + return $transaction->where('type', TransactionType::TRANSFER_FEE); + } + ])->get()->pluck('transactions')->flatten(); + + $group->original_amount = $group->transactions()->sum('original_amount') + ((float)$transferFeeTransactions->sum('service_charge') + (float)$group_transfer_fee_original_amount); + $group->amount = $group->transactions()->sum('amount') + (((float)$transferFeeTransactions->sum('service_charge') + (float)$group_transfer_fee_original_amount) / $rate) + $group->transactions()->sum('service_charge'); + $group->currency_rate = $rate; + $group->tax = $group->transactions()->sum('tax'); + $group->service_charge = $group->transactions()->sum('service_charge'); + + $group->save(); + + $group->documents()->delete(); + + $pdf = LaravelMpdf::loadView('pages.pdfs.currency_vendor_order', ['transactions' => $group->transactions, 'transferFeeTransactions' => $transferFeeTransactions, 'supplier' => $supplier, 'groupTransferFeeOriginalAmount' => $group_transfer_fee_original_amount]); + + $object = new DocumentObject( + DocumentType::CURRENCY_VENDOR_ORDER, + [chunk_split('data:application/pdf;base64,' . base64_encode($pdf->output()))], + '', + ApprovalStatus::COMPLETED, + 'currency_vendor_order' + ); + + /** @var Document $document */ + $document = $this->createsDocument->execute($group, $object); + $this->createsFile->execute($document, $object); + + $this->info("Group ID: {$group->id} updated to currency rate {$rate}"); + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index d6557046..e455eea1 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -43,6 +43,15 @@ class Kernel extends ConsoleKernel ->hourly() ->appendOutputTo(storage_path().'/logs/delete-bulk-download-files.log') ->withoutOverlapping(); + + $schedule->command('booking:expired') + ->dailyAt('02:00') + ->appendOutputTo(storage_path().'/logs/expire-booking.log') + ->withoutOverlapping(); + + // $schedule->command('purchaseOrder:autoFill') + // ->dailyAt('03:00') + // ->withoutOverlapping(); } /** diff --git a/app/Http/Controllers/Accounting/HistoryImportedTransactionMappedController.php b/app/Http/Controllers/Accounting/HistoryImportedTransactionMappedController.php new file mode 100644 index 00000000..8b4a2cde --- /dev/null +++ b/app/Http/Controllers/Accounting/HistoryImportedTransactionMappedController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Banks/UpdateBankMetadataController.php b/app/Http/Controllers/Banks/UpdateBankMetadataController.php new file mode 100644 index 00000000..3b89c1ff --- /dev/null +++ b/app/Http/Controllers/Banks/UpdateBankMetadataController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Bookings/ListBookingsJobController.php b/app/Http/Controllers/Bookings/ListBookingsJobController.php new file mode 100644 index 00000000..9b32fc77 --- /dev/null +++ b/app/Http/Controllers/Bookings/ListBookingsJobController.php @@ -0,0 +1,22 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Bookings/UpdateBookingOrderReferenceController.php b/app/Http/Controllers/Bookings/UpdateBookingOrderReferenceController.php new file mode 100644 index 00000000..64af979e --- /dev/null +++ b/app/Http/Controllers/Bookings/UpdateBookingOrderReferenceController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Bookings/UpdateBookingRecipientController.php b/app/Http/Controllers/Bookings/UpdateBookingRecipientController.php new file mode 100644 index 00000000..670db6da --- /dev/null +++ b/app/Http/Controllers/Bookings/UpdateBookingRecipientController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Documents/ListDocumentsJobController.php b/app/Http/Controllers/Documents/ListDocumentsJobController.php new file mode 100644 index 00000000..8b763085 --- /dev/null +++ b/app/Http/Controllers/Documents/ListDocumentsJobController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Exports/ExportCustomersToExcelController.php b/app/Http/Controllers/Exports/ExportCustomersToExcelController.php index 733c84fa..59f3aba0 100644 --- a/app/Http/Controllers/Exports/ExportCustomersToExcelController.php +++ b/app/Http/Controllers/Exports/ExportCustomersToExcelController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Exports; +use App\Classes\Modules\Exports\Services\ExportCurrencyVendorOrder; use App\Classes\Modules\Exports\Services\ExportsCustomers; use App\Classes\Modules\Exports\Services\ExportsTransactions; use App\Classes\Modules\Exports\Services\ExportsBookingTransactions; @@ -18,6 +19,8 @@ use Maatwebsite\Excel\Excel; use App\Classes\Modules\Exports\Services\ExportsImportedInvoiceMappeds; use App\Models\TransactionMappingLog; use App\Classes\Modules\Exports\Services\ExportsReceiptTransactions; +use App\Classes\Modules\Exports\Services\ExportsImportedReceiptMappeds; +use App\Classes\Modules\Exports\Services\ExportsWhiteFormTransactions; class ExportCustomersToExcelController { @@ -35,6 +38,12 @@ class ExportCustomersToExcelController public function export(ExportsCustomers $exportsCustomers, Request $request){ return $exportsCustomers->download('customers.csv', Excel::CSV, ['Content-Type' => 'text/csv']); } + public function exportCurrencyVendorOrder(ExportCurrencyVendorOrder $exportCurrencyVendorOrder, Request $request){ + $exportCurrencyVendorOrder = new ExportCurrencyVendorOrder($request); + $response = $exportCurrencyVendorOrder->download('CurrencyVendorOrder.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); + ob_end_clean(); + return $response; + } public function transactions(ExportsTransactions $exportsTransactions, Request $request){ return $exportsTransactions->download('transactions.csv', Excel::CSV, ['Content-Type' => 'text/csv']); @@ -53,6 +62,13 @@ class ExportCustomersToExcelController return $response; } + public function whiteFormTransactions(Request $request){ + $exportsTransactions = new ExportsWhiteFormTransactions($request); + $response = $exportsTransactions->download('white-form-transactions.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); + ob_end_clean(); + return $response; + } + public function walletTransactions(Request $request){ $exportsTransactions = new ExportsWalletTransactions($request); $response = $exportsTransactions->download('wallet-transactions.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); @@ -91,4 +107,10 @@ class ExportCustomersToExcelController ob_end_clean(); return $response; } + + public function importedReceiptMapped(ExportsImportedReceiptMappeds $exportsImportedReceiptMappeds, Request $request) { + $response = $exportsImportedReceiptMappeds->download($request->input('fileName').'.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); + ob_end_clean(); + return $response; + } } \ No newline at end of file diff --git a/app/Http/Controllers/Imports/ImportStatementInvoiceController.php b/app/Http/Controllers/Imports/ImportStatementInvoiceController.php index 75953f2b..e4c35eb5 100644 --- a/app/Http/Controllers/Imports/ImportStatementInvoiceController.php +++ b/app/Http/Controllers/Imports/ImportStatementInvoiceController.php @@ -100,6 +100,7 @@ class ImportStatementInvoiceController TransactionMappingLog::create([ 'imported_date'=>$importDate, + 'type' => 'invoices', 'data'=>$row, ]); array_push($data, $row); diff --git a/app/Http/Controllers/Imports/ImportStatementReceiptsController.php b/app/Http/Controllers/Imports/ImportStatementReceiptsController.php index a43f2dda..6c117642 100644 --- a/app/Http/Controllers/Imports/ImportStatementReceiptsController.php +++ b/app/Http/Controllers/Imports/ImportStatementReceiptsController.php @@ -69,6 +69,7 @@ class ImportStatementReceiptsController TransactionMappingLog::create([ 'imported_date'=>$importDate, + 'type' => 'receipts', 'data'=>$row, ]); array_push($data, $row); diff --git a/app/Http/Controllers/Jobs/FetchJobResultController.php b/app/Http/Controllers/Jobs/FetchJobResultController.php new file mode 100644 index 00000000..cfef2f5c --- /dev/null +++ b/app/Http/Controllers/Jobs/FetchJobResultController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Remarks/CreateRemarkController.php b/app/Http/Controllers/Remarks/CreateRemarkController.php new file mode 100644 index 00000000..a66aa8fd --- /dev/null +++ b/app/Http/Controllers/Remarks/CreateRemarkController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Remarks/DeleteRemarkController.php b/app/Http/Controllers/Remarks/DeleteRemarkController.php new file mode 100644 index 00000000..8d0163c0 --- /dev/null +++ b/app/Http/Controllers/Remarks/DeleteRemarkController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Remarks/FetchRemarkController.php b/app/Http/Controllers/Remarks/FetchRemarkController.php new file mode 100644 index 00000000..ba43be07 --- /dev/null +++ b/app/Http/Controllers/Remarks/FetchRemarkController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Remarks/ListRemarksController.php b/app/Http/Controllers/Remarks/ListRemarksController.php new file mode 100644 index 00000000..f76f752e --- /dev/null +++ b/app/Http/Controllers/Remarks/ListRemarksController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Remarks/UpdateRemarkController.php b/app/Http/Controllers/Remarks/UpdateRemarkController.php new file mode 100644 index 00000000..ae53f6b7 --- /dev/null +++ b/app/Http/Controllers/Remarks/UpdateRemarkController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Transactions/ApproveBillGroupPaymentVerificationController.php b/app/Http/Controllers/Transactions/ApproveBillGroupPaymentVerificationController.php new file mode 100644 index 00000000..fbae0c1a --- /dev/null +++ b/app/Http/Controllers/Transactions/ApproveBillGroupPaymentVerificationController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Transactions/CancelBillGroupController.php b/app/Http/Controllers/Transactions/CancelBillGroupController.php new file mode 100644 index 00000000..2eab79c8 --- /dev/null +++ b/app/Http/Controllers/Transactions/CancelBillGroupController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/CreateBillGroupPaymentProofDocumentController.php b/app/Http/Controllers/Transactions/CreateBillGroupPaymentProofDocumentController.php new file mode 100644 index 00000000..dab95ed8 --- /dev/null +++ b/app/Http/Controllers/Transactions/CreateBillGroupPaymentProofDocumentController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/CreateBillGroupPaymentTransactionController.php b/app/Http/Controllers/Transactions/CreateBillGroupPaymentTransactionController.php new file mode 100644 index 00000000..7e94c84e --- /dev/null +++ b/app/Http/Controllers/Transactions/CreateBillGroupPaymentTransactionController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/CreateSupplierBillGroupController.php b/app/Http/Controllers/Transactions/CreateSupplierBillGroupController.php new file mode 100644 index 00000000..7ab2f48a --- /dev/null +++ b/app/Http/Controllers/Transactions/CreateSupplierBillGroupController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/DeleteBillGroupController.php b/app/Http/Controllers/Transactions/DeleteBillGroupController.php new file mode 100644 index 00000000..2b76632b --- /dev/null +++ b/app/Http/Controllers/Transactions/DeleteBillGroupController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/DeleteRefundTransactionController.php b/app/Http/Controllers/Transactions/DeleteRefundTransactionController.php new file mode 100644 index 00000000..0940ce49 --- /dev/null +++ b/app/Http/Controllers/Transactions/DeleteRefundTransactionController.php @@ -0,0 +1,14 @@ +execute($request); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Transactions/ListBillGroupsController.php b/app/Http/Controllers/Transactions/ListBillGroupsController.php new file mode 100644 index 00000000..94dbd5e1 --- /dev/null +++ b/app/Http/Controllers/Transactions/ListBillGroupsController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/ListTransactionsJobController.php b/app/Http/Controllers/Transactions/ListTransactionsJobController.php new file mode 100644 index 00000000..fb341d5d --- /dev/null +++ b/app/Http/Controllers/Transactions/ListTransactionsJobController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/UpdateGroupTransferFeeController.php b/app/Http/Controllers/Transactions/UpdateGroupTransferFeeController.php new file mode 100644 index 00000000..948dff39 --- /dev/null +++ b/app/Http/Controllers/Transactions/UpdateGroupTransferFeeController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Vouchers/ListVoucherCampaignsController.php b/app/Http/Controllers/Vouchers/ListVoucherCampaignsController.php new file mode 100644 index 00000000..ad3268e5 --- /dev/null +++ b/app/Http/Controllers/Vouchers/ListVoucherCampaignsController.php @@ -0,0 +1,21 @@ +execute($request); + } + +} diff --git a/app/Http/Resources/BillGroupResource.php b/app/Http/Resources/BillGroupResource.php new file mode 100644 index 00000000..748dc392 --- /dev/null +++ b/app/Http/Resources/BillGroupResource.php @@ -0,0 +1,83 @@ +make(CalculatesBillGroupPaymentAmount::class))->execute($this->resource); + $bill_refund_amount = $billGroupPayment['bill_refund_amount']; + $floating_amount = $billGroupPayment['floating_amount']; + $paid_amount = $billGroupPayment['paid_amount']; + $outstanding_amount = $billGroupPayment['outstanding_amount']; + + return [ + 'id' => $this->id, + 'reference' => $this->reference, + 'original_amount' => (float) $this->original_amount, + 'original_currency' => new CurrencyResource($this->original_currency), + 'issuer_name' => $this->issuerCompany->name, + 'issuer_id' => $this->issuerCompany->id, + 'invoice_amount' => (float) $this->amount + $bill_refund_amount - $this->service_charge, + 'amount' => (float) $this->amount, + 'service_charge' => (float) $this->service_charge, + 'currency' => new CurrencyResource($this->currency), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + 'currency_rate' => (float) $this->currency_rate, + 'status' => $this->status, + 'groups' => GroupResource::collection($this->groups), + 'bill_refund_amount' => $bill_refund_amount, + 'floating_amount' => $floating_amount, + 'paid_amount' => $paid_amount, + 'outstanding_amount' => $outstanding_amount, + 'payment_history' => $this->transactions->map(function ($transaction) { + return [ + 'id' => $transaction->id, + 'type' => (int) $transaction->type, + 'bill_no' => $transaction->bill_no, + 'payment_method' => (float) $transaction->payment_method, + 'amount' => (float) $transaction->amount, + 'original_amount' => (float) $transaction->original_amount, + 'currency' => new CurrencyResource($transaction->currency), + 'original_currency' => new CurrencyResource($transaction->original_currency), + 'service_charge' => (float) $transaction->service_charge, + 'tax' => (float) $transaction->tax, + 'status' => (int) $transaction->status, + 'statusText' => ApprovalStatus::APPROVAL_STATUS_ID[(int) $transaction->status], + 'documents' => $transaction->documents()->first() ? new DocumentResource($transaction->documents()->first()) : null, + 'updated_at' => Carbon::parse($transaction->updated_at)->format('d-m-Y h:i:s A'), + ]; + }), + 'bill_refunds' => $this->billRefunds->map(function ($transaction) { + return [ + 'id' => $transaction->id, + 'type' => (int) $transaction->type, + 'bill_no' => $transaction->bill_no, + 'payment_method' => (float) $transaction->payment_method, + 'amount' => (float) $transaction->amount, + 'original_amount' => (float) $transaction->original_amount, + 'currency' => new CurrencyResource($transaction->currency), + 'original_currency' => new CurrencyResource($transaction->original_currency), + 'service_charge' => (float) $transaction->service_charge, + 'tax' => (float) $transaction->tax, + 'status' => (int) $transaction->status, + 'statusText' => ApprovalStatus::APPROVAL_STATUS_ID[(int) $transaction->status], + 'updated_at' => Carbon::parse($transaction->updated_at)->format('d-m-Y h:i:s A'), + ]; + }), + ]; + } +} diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index f3a7881d..83e53249 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -7,15 +7,14 @@ use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding; use App\Classes\Modules\Bookings\Services\CalculatesBookingPayableAmount; use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\ValueObjects\Constants\BookingAttributeNames; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; -use Illuminate\Support\Facades\Log; class BookingResource extends JsonResource { - /** * Transform the resource into an array. * @@ -34,7 +33,8 @@ class BookingResource extends JsonResource 'amount' => $this->fix_amount, 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + // 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) + floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)), 'fixed_currency' => new CurrencyResource($this->fixedCurrency), 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), 'conversion_currency' => new CurrencyResource($this->conversionCurrency), @@ -46,6 +46,12 @@ class BookingResource extends JsonResource 'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), 'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), ], + 'order_reference_no' => $this->modelAttributes()->where('name', BookingAttributeNames::ORDER_REFERENCE_NO)->get()->map(function ($attr) { + return [ + 'id' => $attr->id, + 'value' => $attr->value + ]; + }), 'status' => $this->status, 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), @@ -57,10 +63,11 @@ class BookingResource extends JsonResource ->whereDate('expires_on', '>=', Carbon::now()) ->get() ), - 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + // 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::EXPIRED)->get()), 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ $query->where(function($query){ - $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED, ApprovalStatus::REFUNDED]); })->orWhere(function($query){ $query->where(function($query){ $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index 85ecee16..82b4cf3e 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -15,7 +15,6 @@ use App\Models\SegmentConstant; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Log; class CompanyResource extends JsonResource { @@ -57,7 +56,7 @@ class CompanyResource extends JsonResource 'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments', 'personal_banks' => BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)), 'recipient_banks' => [ - 'accounts' => BankResource::collection($this->banks->where('type', BankAccountType::EXTERNAL)), + 'accounts' => BankResource::collection($this->banks->whereIn('type', [BankAccountType::EXTERNAL, BankAccountType::ALIPAY_1688, BankAccountType::ALIPAY_RECIPIENT])->whereIn('creator_type', [null])), 'default' => new BankResource($this->banks->where('type', BankAccountType::EXTERNAL)->where('default', true)->first()) ], 'segments' => SegmentResource::collection($this->segments), diff --git a/app/Http/Resources/DocumentResource.php b/app/Http/Resources/DocumentResource.php index 59933a67..c0f801bb 100644 --- a/app/Http/Resources/DocumentResource.php +++ b/app/Http/Resources/DocumentResource.php @@ -3,10 +3,7 @@ namespace App\Http\Resources; use App\Models\Booking; -use App\Models\Company; -use App\Models\Document; use Carbon\Carbon; -use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Resources\Json\JsonResource; class DocumentResource extends JsonResource diff --git a/app/Http/Resources/GroupResource.php b/app/Http/Resources/GroupResource.php index abd017ec..fdddd195 100644 --- a/app/Http/Resources/GroupResource.php +++ b/app/Http/Resources/GroupResource.php @@ -21,6 +21,13 @@ class GroupResource extends JsonResource */ public function toArray($request) { + $transfer_fee = $this->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + if ($transfer_fee) { + $transfer_fee = (float) $transfer_fee->amount; + } else { + $transfer_fee = 0; + } if(!$this->issuerCompany){ dd($this->id); @@ -36,6 +43,7 @@ class GroupResource extends JsonResource 'currency' => new CurrencyResource($this->currency), 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), 'currency_rate' => (float) $this->currency_rate, + 'transfer_fee' => $transfer_fee, 'transactions' => $this->transactions()->get()->pluck('owner.owner.marking'), 'complete_transactions' => $this->transactions()->whereHasMorph('owner', [Transaction::class], function($query){ return $query->whereHas('booking', function($query){ diff --git a/app/Http/Resources/JobResultResource.php b/app/Http/Resources/JobResultResource.php new file mode 100644 index 00000000..51bc1898 --- /dev/null +++ b/app/Http/Resources/JobResultResource.php @@ -0,0 +1,22 @@ + $this->job_id, + 'result' => $this->result, + ]; + } +} diff --git a/app/Http/Resources/KeyValueBasicResource.php b/app/Http/Resources/KeyValueBasicResource.php new file mode 100644 index 00000000..94725a0a --- /dev/null +++ b/app/Http/Resources/KeyValueBasicResource.php @@ -0,0 +1,24 @@ + $this->id, + 'key' => $this->key, + 'value' => $this->value, + ]; + } +} diff --git a/app/Http/Resources/ListBookingJobResource.php b/app/Http/Resources/ListBookingJobResource.php new file mode 100644 index 00000000..06f8c38d --- /dev/null +++ b/app/Http/Resources/ListBookingJobResource.php @@ -0,0 +1,81 @@ +userInfo = $userInfo ?? ($resource->userInfo ?? null); + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + * @throws \Illuminate\Contracts\Container\BindingResolutionException + */ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'company' => new CompanyResource($this->company, $this->userInfo), + 'bank' => new BankResource($this->bank), + 'service' => new ServiceTypeResource($this->service), + 'marking' => $this->marking, + 'amount' => $this->fix_amount, + 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'fixed_currency' => new CurrencyResource($this->fixedCurrency), + 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), + 'conversion_currency' => new CurrencyResource($this->conversionCurrency), + 'documents' => [ + 'purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), + 'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), + 'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), + 'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), + 'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), + 'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), + ], + 'status' => $this->status, + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + $this->mergeWhen($this->relationLoaded('transactions'), [ + 'purchase_order' => new TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), + 'payment_attempts' => TransactionResource::collection( + $this->transactions() + ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) + ->whereDate('expires_on', '>=', Carbon::now()) + ->get() + ), + 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ + $query->where(function($query){ + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); + })->orWhere(function($query){ + $query->where(function($query){ + $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + }); + })->latest()->get()) + ]) + ]; + } +} diff --git a/app/Http/Resources/ListDocumentJobResource.php b/app/Http/Resources/ListDocumentJobResource.php new file mode 100644 index 00000000..edf549ef --- /dev/null +++ b/app/Http/Resources/ListDocumentJobResource.php @@ -0,0 +1,31 @@ + $this->id, + 'reference' => $this->reference, + 'status' => (int) $this->status, + 'document_type' => $this->document_type, + 'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingV2Resource($this->owner, $this->userInfo) : new CompanyV2Resource($this->owner, $this->userInfo)) : null, + 'files' => FileResource::collection($this->files), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A') + ]; + } +} diff --git a/app/Http/Resources/ListTransactionJobResource.php b/app/Http/Resources/ListTransactionJobResource.php new file mode 100644 index 00000000..1547c09e --- /dev/null +++ b/app/Http/Resources/ListTransactionJobResource.php @@ -0,0 +1,64 @@ +type, [TransactionType::BILL, TransactionType::REFUND])){ + $booking = $this->owner->owner; + $bank = $this->owner->bank ?? $booking->bank; + } + else{ + $booking = $this->owner; + $bank = $this->bank ?? $booking->bank; + } + //Check if Transaction of type PAYMENT has an override for recipient bank - ends + $days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1); + + return [ + 'id' => $this->id, + 'booking' => new BookingResource($booking), + 'type' => (int) $this->type, + 'bill_no' => $this->bill_no, + 'payment_reference' => $this->payment_reference, + 'payment_method' => (float) $this->payment_method, + 'recipient_bank_account' => new BankResource($bank), + 'issuer_name' => $this->issuerCompany->name, + 'issuer_id' => $this->issuerCompany->id, + 'amount' => (double) $this->amount, + 'original_amount' => (double) $this->original_amount, + 'currency' => new CurrencyResource($this->currency), + 'original_currency' => new CurrencyResource($this->original_currency), + 'service_charge' => (double) $this->service_charge, + 'tax' => (double) $this->tax, + 'currency_rate' => (double) $this->currency_rate, + 'status' => (int) $this->status, + 'details' => TransactionDetailResource::collection($this->transactionDetails), + 'documents' => new DocumentResource($this->documents()->first()), + 'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->bills()->first())), + 'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())), + 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), + 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + 'interval' => [ + 'value' => $days->gt(Carbon::now()) ? '+' : '-', + 'duration' => $days->diff(Carbon::now())->format('%d'), + ], + 'redemption' => new VoucherRedemptionResource($this->voucherRedemption) + ]; + } +} diff --git a/app/Http/Resources/PaymentTransactionResource.php b/app/Http/Resources/PaymentTransactionResource.php index 456ece3d..01da84b2 100644 --- a/app/Http/Resources/PaymentTransactionResource.php +++ b/app/Http/Resources/PaymentTransactionResource.php @@ -18,8 +18,18 @@ class PaymentTransactionResource extends JsonResource */ public function toArray($request) { - - $booking = in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner; + $booking = null; //cief todo: 66 + $bank = null; + //Check if Transaction of type PAYMENT has an override for recipient bank - starts + if(in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])){ + $booking = $this->owner->owner; + $bank = $this->owner->bank ?? $booking->bank; + } + else{ + $booking = $this->owner; + $bank = $this->bank ?? $booking->bank; + } + //Check if Transaction of type PAYMENT has an override for recipient bank - ends $booking_marking = ''; switch ($this->owner_type) { @@ -38,7 +48,7 @@ class PaymentTransactionResource extends JsonResource 'bill_no' => $this->bill_no, 'payment_reference' => $this->payment_reference, 'payment_method' => (float) $this->payment_method, - 'recipient_bank_account' => new BankResource($booking->bank), + 'recipient_bank_account' => new BankResource($bank), 'issuer_name' => $this->issuerCompany->name, 'issuer_id' => $this->issuerCompany->id, 'amount' => (double) $this->amount, diff --git a/app/Http/Resources/RemarkResource.php b/app/Http/Resources/RemarkResource.php new file mode 100644 index 00000000..24081934 --- /dev/null +++ b/app/Http/Resources/RemarkResource.php @@ -0,0 +1,26 @@ + $this->id, + 'commenter' => new UserResource($this->commenter), + 'owner_id' => $this->owner_id, + 'content' => $this->content, + 'created_at' => $this->created_at->format('d-m-Y H:i'), + 'long_ago' => $this->created_at->diffForHumans() + ]; + } +} diff --git a/app/Http/Resources/TransactionMappingLogResource.php b/app/Http/Resources/TransactionMappingLogResource.php new file mode 100644 index 00000000..954294f1 --- /dev/null +++ b/app/Http/Resources/TransactionMappingLogResource.php @@ -0,0 +1,23 @@ + $this->id, + 'imported_date' => $this->imported_date, + 'type' => $this->type + ]; + } +} diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index 27fd17ab..e14c32c0 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -2,6 +2,8 @@ namespace App\Http\Resources; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; +use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\Booking; use Carbon\Carbon; @@ -17,8 +19,18 @@ class TransactionResource extends JsonResource */ public function toArray($request) { - - $booking = in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner; + $booking = null; //cief todo: 66 + $bank = null; + //Check if Transaction of type PAYMENT has an override for recipient bank - starts + if(in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND, TransactionType::SUPPLIER_REFUND])){ + $booking = $this->owner->owner; + $bank = $this->owner->bank ?? $booking->bank; + } + else{ + $booking = $this->owner; + $bank = $this->bank ?? $booking->bank; + } + //Check if Transaction of type PAYMENT has an override for recipient bank - ends $days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1); return [ @@ -28,11 +40,11 @@ class TransactionResource extends JsonResource 'bill_no' => $this->bill_no, 'payment_reference' => $this->payment_reference, 'payment_method' => (float) $this->payment_method, - 'recipient_bank_account' => new BankResource($booking->bank), + 'recipient_bank_account' => new BankResource($bank), 'issuer_name' => $this->issuerCompany->name, 'issuer_id' => $this->issuerCompany->id, - 'amount' => (double) $this->amount, - 'original_amount' => (double) $this->original_amount, + 'amount' => (double) ($this->type === TransactionType::SUPPLIER_REFUND ? $this->amount - $this->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->sum('amount') : $this->amount), + 'original_amount' => (double) ($this->type === TransactionType::SUPPLIER_REFUND ? $this->original_amount - $this->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->sum('original_amount') : $this->original_amount), 'currency' => new CurrencyResource($this->currency), 'original_currency' => new CurrencyResource($this->original_currency), 'service_charge' => (double) $this->service_charge, @@ -43,13 +55,17 @@ class TransactionResource extends JsonResource 'documents' => new DocumentResource($this->documents()->first()), 'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->bills()->first())), 'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())), + 'refunded_amount' => $this->booking ? floatval((App()->make(CalculatesBookingRefundAmount::class))->calculateRefundAmount($this->resource, $this->booking->fix_currency_id)) : null, 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), 'interval' => [ 'value' => $days->gt(Carbon::now()) ? '+' : '-', 'duration' => $days->diff(Carbon::now())->format('%d'), ], - 'redemption' => new VoucherRedemptionResource($this->voucherRedemption) + 'remarks' => RemarkResource::collection($this->remarks), + 'redemption' => new VoucherRedemptionResource($this->voucherRedemption), + 'bank' => ((int) $this->type === TransactionType::PAYMENT) ? new BankResource($bank) : null, //When a transaction (of type payment) has an override recipient bank details on booking, this is NOT null ]; } } diff --git a/app/Http/Resources/UserRewardResource.php b/app/Http/Resources/UserRewardResource.php index ed693b4c..25080270 100644 --- a/app/Http/Resources/UserRewardResource.php +++ b/app/Http/Resources/UserRewardResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; + use Illuminate\Http\Resources\Json\JsonResource; class UserRewardResource extends JsonResource @@ -14,6 +15,13 @@ class UserRewardResource extends JsonResource */ public function toArray($request) { + $emailReminder = null; + if ($request->has('isAdmin')) { + $keyValuePairs = $this->user->attributesKVP()->get(); + $emailReminder = KeyValueBasicResource::collection($keyValuePairs); + $this->voucher->email = $emailReminder; + } + return [ 'id' => $this->id, 'user_id' => $this->user_id, diff --git a/app/Http/Resources/V2/BookingV2Resource.php b/app/Http/Resources/V2/BookingV2Resource.php new file mode 100644 index 00000000..ee17181e --- /dev/null +++ b/app/Http/Resources/V2/BookingV2Resource.php @@ -0,0 +1,82 @@ +userInfo = $userInfo ?? ($resource->userInfo ?? null); + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + * @throws \Illuminate\Contracts\Container\BindingResolutionException + */ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'company' => new CompanyV2Resource($this->company, $this->userInfo), + 'bank' => new V1\BankResource($this->bank), + 'service' => new V1\ServiceTypeResource($this->service), + 'marking' => $this->marking, + 'amount' => $this->fix_amount, + 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'fixed_currency' => new V1\CurrencyResource($this->fixedCurrency), + 'convertible_currency' => new V1\CurrencyResource($this->convertibleCurrency), + 'conversion_currency' => new V1\CurrencyResource($this->conversionCurrency), + 'documents' => [ + 'purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), + 'delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), + 'invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), + 'supplier_delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), + 'proforma_invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), + 'ecommerce_purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), + ], + 'status' => $this->status, + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + $this->mergeWhen($this->relationLoaded('transactions'), [ + 'purchase_order' => new V1\TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), + 'payment_attempts' => V1\TransactionResource::collection( + $this->transactions() + ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) + ->whereDate('expires_on', '>=', Carbon::now()) + ->get() + ), + 'expired_payment_attempts' => V1\TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + 'payment_history' => V1\TransactionResource::collection($this->transactions()->where(function($query){ + $query->where(function($query){ + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); + })->orWhere(function($query){ + $query->where(function($query){ + $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + }); + })->latest()->get()) + ]) + ]; + } +} diff --git a/app/Http/Resources/V2/CompanyV2Resource.php b/app/Http/Resources/V2/CompanyV2Resource.php new file mode 100644 index 00000000..3f2cb4c2 --- /dev/null +++ b/app/Http/Resources/V2/CompanyV2Resource.php @@ -0,0 +1,100 @@ +userInfo = $userInfo; + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + */ + public function toArray($request) + { + $lastPayment = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->orderBy('id', 'DESC')->first(); + $totalPayments = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount'); + + $segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first(); + $serviceCharge = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $this->id)->first(); + + $userResource = null; + + $userInfoEmail = $this->userInfo && isset($this->userInfo->email) ? $this->userInfo->email : null; + $userInfoType = $this->userInfo && isset($this->userInfo->type) ? $this->userInfo->type : null; + + if(!$userInfoEmail && Auth::user()){ + $userInfoEmail = Auth::user()->email; + } + if(!$userInfoType && Auth::user()){ + $userInfoType = Auth::user()->type; + } + + if(!is_null($userInfoEmail) && !is_null($userInfoType)){ + $userResource = new V1\UserResource($userInfoType === RoleTypes::USER ? $this->employees()->where('email', '=', $userInfoEmail)->first() : $this->employees()->orderBy('id', 'DESC')->first()); + } + + return [ + 'id' => $this->id, + 'name' => $this->name, + 'reference' => $this->reference, + 'debtor' => $this->debtor, + 'type' => (int) $this->type, + 'business_type' => (int) $this->business_type, + 'status' => (int) $this->status, + 'contact' => new V1\ContactResource ($this->when($this->has('contacts'), $this->contacts->first())), + 'address' => new V1\AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', true)->first())), + 'employee' => $userResource, + 'identification' => new V1\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){ + $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->count(), + 'total_payments' => (float) $totalPayments, + 'average_spending_per_day' => (float) $totalPayments / ($this->created_at->diff(Carbon::now())->days === 0 ? 1 : $this->created_at->diff(Carbon::now())->days), + 'average_spending_per_booking' => (float) $totalPayments > 0 ? $totalPayments / $this->bookings()->whereHas('transactions', function ($query){ + $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->count() : $totalPayments, + 'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments', + 'personal_banks' => V1\BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)), + 'recipient_banks' => [ + 'accounts' => V1\BankResource::collection($this->banks->where('type', BankAccountType::EXTERNAL)->whereIn('creator_type', [null])), + 'default' => new V1\BankResource($this->banks->where('type', BankAccountType::EXTERNAL)->where('default', true)->first()) + ], + 'segments' => V1\SegmentResource::collection($this->segments), + 'seasonalSegment' => $this->whenLoaded('seasonalSegments', V1\SeasonalSegmentResource::collection($this->seasonalSegments)), + 'services' => (new FetchesCompanyServices())->getServices($this->servicesConfigurations()), + 'wallet' => $this->whenLoaded('wallets', new V1\WalletResource($this->wallets()->with('transactions')->first()), new V1\WalletResource($this->wallets()->first())), + 'created_at' => $this->created_at->format('d-m-Y'), + $this->mergeWhen($this->business_type === BusinessType::CURRENCY_VENDOR, [ + 'currencies' => $segment ? V1\CurrencyResource::collection(Currency::whereIn('id', $segment->detail->currencies)->get()) : [], + 'service_charge' => $serviceCharge + ]) + + ]; + } +} diff --git a/app/Http/Resources/VoucherCampaignResource.php b/app/Http/Resources/VoucherCampaignResource.php new file mode 100644 index 00000000..ebc6964c --- /dev/null +++ b/app/Http/Resources/VoucherCampaignResource.php @@ -0,0 +1,32 @@ +has('include_metadata')) { + $metadata = KeyValueBasicResource::collection($this->attributesKVP()->latest()->get()); + } + + return [ + // 'id' => $this->id, + 'campaign_id' => $this->campaign_id, + 'name' => $this->name, + 'description' => $this->description, + 'limit_per_month' => $this->limit_per_month, + 'metadata' => $metadata + ]; + } +} diff --git a/app/Http/Resources/VoucherResource.php b/app/Http/Resources/VoucherResource.php index 54193eeb..f4315bd1 100644 --- a/app/Http/Resources/VoucherResource.php +++ b/app/Http/Resources/VoucherResource.php @@ -2,7 +2,9 @@ namespace App\Http\Resources; +use ArrayObject; use Illuminate\Http\Resources\Json\JsonResource; +use Illuminate\Support\Facades\Log; class VoucherResource extends JsonResource { @@ -14,18 +16,28 @@ class VoucherResource extends JsonResource */ public function toArray($request) { - $filteredRedemptions = $this->redemptions->filter(function ($redemption) { - return $redemption->transaction && $redemption->transaction->owner; - }); + $filteredRedemptions = new ArrayObject([]); + if ($request->has('filters') && (str_contains($request->input('filters'), "has_vouchers_all_with_user") )) { + //|| str_contains($request->input('filters'), "has_vouchers_all_with_company") + $filteredRedemptions = new ArrayObject([]); + } + else{ + $filteredRedemptions = $this->redemptions->filter(function ($redemption) { + return $redemption->transaction && $redemption->transaction->owner; + }); + } + return [ 'id' => $this->id, 'name' => $this->name, + 'description' => $this->description, 'code' => $this->code, 'type' => $this->type, 'value' => (float) $this->value, 'start_date' => $this->start_date, 'end_date' => $this->end_date, - 'is_redeemed' => $filteredRedemptions->count() > 0 + 'is_redeemed' => $filteredRedemptions->count() > 0, + 'email' => $this->email ? new KeyValueBasicResource($this->email->where('key', $this->code.'_EMAIL_COUNT')->first()) : null, ]; } } diff --git a/app/Models/Bank.php b/app/Models/Bank.php index 3b0bb915..42cdf3df 100644 --- a/app/Models/Bank.php +++ b/app/Models/Bank.php @@ -7,6 +7,8 @@ use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\MorphMany; +use App\Classes\General\Interfaces\KeyValueInterface; /** * Class Bank @@ -21,10 +23,29 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; * @property int default * @property int status */ -class Bank extends AbstractModel +class Bank extends AbstractModel implements KeyValueInterface { use SoftDeletes; - + + /** + * + * @var array + */ + protected $fillable = [ + 'company_id', + 'reference', + 'bank_name', + 'holder_name', + 'account_no', + 'bank_branch', + 'swift', + 'snap', + 'type', + 'country_id', + 'created_by', + 'creator_type', + ]; + protected $table = 'banks'; /** @@ -42,7 +63,7 @@ class Bank extends AbstractModel { return $this->BelongsTo(Company::class, 'company_id', 'id'); } - + /** * @return HasMany */ @@ -50,4 +71,12 @@ class Bank extends AbstractModel { return $this->HasMany(Transaction::class, 'recipient_bank_account_id'); } + + /** + * @return MorphMany + */ + public function attributesKVP(): MorphMany + { + return $this->morphMany(KeyValuePair::class, 'owner'); + } } diff --git a/app/Models/BillGroup.php b/app/Models/BillGroup.php new file mode 100644 index 00000000..9270d8e8 --- /dev/null +++ b/app/Models/BillGroup.php @@ -0,0 +1,76 @@ +MorphMany(Transaction::class, 'owner'); + } + + use HasRelationships; + use \Staudenmeir\EloquentHasManyDeep\HasTableAlias; + + public function billRefunds() + { + return $this->belongsToMany(Transaction::class, BillGroupRefund::class); + } + + /** + * @return MorphMany + */ + public function documents(): morphMany + { + return $this->morphMany(Document::class, 'owner'); + } + + /** + * @return BelongsTo + */ + public function currency(): BelongsTo + { + return $this->BelongsTo(Currency::class, 'currency_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function issuerCompany(): BelongsTo + { + return $this->BelongsTo( Company::class, 'issuer', 'id'); + } + + /** + * @return BelongsTo + */ + public function original_currency(): BelongsTo + { + return $this->BelongsTo(Currency::class, 'original_currency_id', 'id'); + } + + public function groups() + { + return $this->belongsToMany(Group::class, BillGroupPayment::class, 'bill_group_id', 'group_id'); + } +} diff --git a/app/Models/BillGroupPayment.php b/app/Models/BillGroupPayment.php new file mode 100644 index 00000000..e34f692c --- /dev/null +++ b/app/Models/BillGroupPayment.php @@ -0,0 +1,27 @@ +BelongsTo(BillGroup::class, 'bill_group_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function group(): BelongsTo + { + return $this->BelongsTo(Group::class, 'group_id', 'id'); + } +} diff --git a/app/Models/BillGroupRefund.php b/app/Models/BillGroupRefund.php new file mode 100644 index 00000000..aa430873 --- /dev/null +++ b/app/Models/BillGroupRefund.php @@ -0,0 +1,27 @@ +BelongsTo(BillGroup::class, 'bill_group_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function transaction(): BelongsTo + { + return $this->BelongsTo(Transaction::class, 'transaction_id', 'id'); + } +} diff --git a/app/Models/Booking.php b/app/Models/Booking.php index ca80d0c3..ff0b45b9 100644 --- a/app/Models/Booking.php +++ b/app/Models/Booking.php @@ -107,6 +107,11 @@ class Booking extends AbstractModel implements Documentable, Transactionable return $this->hasManyDeep(Transaction::class, [Transaction::class.' as alias'], [['owner_type', 'owner_id'], ['owner_type', 'owner_id']], [null, null]); } + public function modelAttributes(): MorphMany + { + return $this->morphMany(ModelAttribute::class, 'owner'); + } + protected static function booted() { if (auth()->user()) { diff --git a/app/Models/Group.php b/app/Models/Group.php index 01dd257e..2b8cceae 100644 --- a/app/Models/Group.php +++ b/app/Models/Group.php @@ -6,6 +6,7 @@ use App\Classes\General\Traits\LogData; use Illuminate\Database\Eloquent\Model; use App\Classes\General\Interfaces\Documentable; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\MorphMany; use Staudenmeir\EloquentHasManyDeep\HasManyDeep; use Staudenmeir\EloquentHasManyDeep\HasRelationships; @@ -20,6 +21,14 @@ class Group extends Model implements Documentable return $this->belongsToMany(Transaction::class, GroupTransaction::class); } + /** + * @return MorphMany + */ + public function morphTransactions(): MorphMany + { + return $this->MorphMany(Transaction::class, 'owner'); + } + /** * @return MorphMany */ @@ -60,4 +69,12 @@ class Group extends Model implements Documentable { return $this->BelongsTo(Currency::class, 'original_currency_id', 'id'); } + + /** + * @return BelongsToMany + */ + public function billGroup(): BelongsToMany + { + return $this->belongsToMany(BillGroup::class, BillGroupPayment::class, 'group_id', 'bill_group_id'); + } } diff --git a/app/Models/JobResult.php b/app/Models/JobResult.php new file mode 100644 index 00000000..f30b5076 --- /dev/null +++ b/app/Models/JobResult.php @@ -0,0 +1,13 @@ +morphTo(); + } +} diff --git a/app/Models/ModelAttribute.php b/app/Models/ModelAttribute.php new file mode 100644 index 00000000..bbd3511c --- /dev/null +++ b/app/Models/ModelAttribute.php @@ -0,0 +1,27 @@ + "array" + ]; + + public function owner(): morphTo + { + return $this->morphTo(); + } + +} diff --git a/app/Models/Remark.php b/app/Models/Remark.php new file mode 100644 index 00000000..f2de3a5c --- /dev/null +++ b/app/Models/Remark.php @@ -0,0 +1,27 @@ +morphTo(); + } + + /** + * @return BelongsTo + */ + public function commenter(): BelongsTo + { + return $this->BelongsTo(User::class, 'commenter_id', 'id'); + } +} diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 185fdb36..c84c0238 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -3,6 +3,8 @@ namespace App\Models; use App\Classes\General\Interfaces\Documentable; +use App\Classes\General\Interfaces\KeyValueInterface; +use App\Classes\General\Interfaces\Remarkable; use App\Classes\General\Interfaces\Transactionable; use App\Classes\General\Interfaces\Voucherifiable; use App\Classes\General\Traits\LogData; @@ -21,7 +23,7 @@ use Staudenmeir\EloquentHasManyDeep\HasTableAlias; use App\Models\StatementTransactionOwner; -class Transaction extends AbstractModel implements Documentable, Transactionable, Voucherifiable +class Transaction extends AbstractModel implements Documentable, Transactionable, Voucherifiable, Remarkable, KeyValueInterface { use HasTableAlias; use SoftDeletes; @@ -186,6 +188,20 @@ class Transaction extends AbstractModel implements Documentable, Transactionable return $query->where('type', TransactionType::REFUND); } + /** + * @param Builder $query + * @param string $payment_reference + * @return Builder + */ + public function scopeSupplierRefunds(Builder $query, ?string $payment_reference = NULL) + { + if($payment_reference){ + $query->where('payment_reference', $payment_reference); + } + + return $query->where('type', TransactionType::SUPPLIER_REFUND); + } + /** * @param Builder $query @@ -245,4 +261,33 @@ class Transaction extends AbstractModel implements Documentable, Transactionable return $this->morphMany(VoucherEntityMapping::class, 'owner'); } + /** + * @return MorphMany + */ + public function remarks(): morphMany + { + return $this->morphMany(Remark::class, 'owner'); + } + + /** + * @return MorphMany + */ + public function attributesKVP(): MorphMany + { + return $this->morphMany(KeyValuePair::class, 'owner'); + } + + /** + * + * @return Model|null + */ + public function getBankAttribute() + { + $keyValuePairs = $this->attributesKVP()->where('key', 'App\Models\Bank')->latest()->first(); + if($keyValuePairs){ + $bank = Bank::where('id', $keyValuePairs->value)->first(); + return $bank; + } + return null; + } } diff --git a/app/Models/TransactionMappingLog.php b/app/Models/TransactionMappingLog.php index d6093f39..e9ddab33 100644 --- a/app/Models/TransactionMappingLog.php +++ b/app/Models/TransactionMappingLog.php @@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Model; class TransactionMappingLog extends Model { - protected $fillable = ['imported_by','data','imported_date']; + protected $fillable = ['imported_by','data','imported_date','type']; protected $casts = [ 'data' => 'array', diff --git a/app/Models/User.php b/app/Models/User.php index 4bc7ec17..46e8635f 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Classes\General\Interfaces\KeyValueInterface; use App\Classes\General\Interfaces\Voucherifiable; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -26,7 +27,8 @@ class User extends AbstractModel implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, - Voucherifiable + Voucherifiable, + KeyValueInterface { use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes; @@ -101,4 +103,21 @@ class User extends AbstractModel implements { return $this->HasMany(UserReward::class, 'user_id', 'id'); } + + public function hasAttribute(string $key, $value = null): bool + { + $query = $this->attributesKVP()->where('key', $key); + + if ($value !== null) { + $query->where('value', $value); + } + + return $query->exists(); + } + + + public function attributesKVP(): MorphMany + { + return $this->morphMany(KeyValuePair::class, 'owner'); + } } diff --git a/app/Models/Voucher.php b/app/Models/Voucher.php index b8df7dca..49001e1d 100644 --- a/app/Models/Voucher.php +++ b/app/Models/Voucher.php @@ -2,6 +2,7 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -14,6 +15,14 @@ class Voucher extends AbstractModel */ public function redemptions(): HasMany { - return $this->HasMany(VoucherRedemption::class, 'voucher_id', 'id'); + return $this->hasMany(VoucherRedemption::class, 'voucher_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function campaign(): BelongsTo + { + return $this->belongsTo(VoucherCampaign::class, 'voucher_campaign_id'); } } diff --git a/app/Models/VoucherCampaign.php b/app/Models/VoucherCampaign.php new file mode 100644 index 00000000..4e14cc12 --- /dev/null +++ b/app/Models/VoucherCampaign.php @@ -0,0 +1,29 @@ +hasMany(Voucher::class, 'voucher_campaign_id'); + } + + /** + * @return MorphMany + */ + public function attributesKVP(): MorphMany + { + return $this->morphMany(KeyValuePair::class, 'owner'); + } +} diff --git a/config/logging.php b/config/logging.php index fb872693..d4894384 100644 --- a/config/logging.php +++ b/config/logging.php @@ -104,6 +104,23 @@ return [ 'path' => storage_path('logs/regenerateInvoice.log'), 'level' => 'info', ], + 'guzzleShippingPortal' => [ + 'driver' => 'errorlog', + 'level' => 'debug', + ], + + 'vue_polling' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel_vue_plling.log'), + 'level' => 'info', + ], + + 'perfex_crm' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel_perfex_crm.log'), + 'level' => 'info', + ], + ], ]; diff --git a/config/queue.php b/config/queue.php index 00b76d65..fc718e49 100644 --- a/config/queue.php +++ b/config/queue.php @@ -34,6 +34,13 @@ return [ 'driver' => 'sync', ], + 'high_priority' => [ + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'high_priority', + 'retry_after' => 90, + ], + 'database' => [ 'driver' => 'database', 'table' => 'jobs', diff --git a/database/migrations/2023_08_08_124848_create_job_results_table.php b/database/migrations/2023_08_08_124848_create_job_results_table.php new file mode 100644 index 00000000..ef448407 --- /dev/null +++ b/database/migrations/2023_08_08_124848_create_job_results_table.php @@ -0,0 +1,35 @@ +id(); + $table->string('job_id', 50); + $table->longText('result')->nullable(); + $table->timestamps(); + + // $table->foreign('job_id')->references('id')->on('jobs')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('job_results'); + } +} diff --git a/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php b/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php new file mode 100644 index 00000000..8e6b8342 --- /dev/null +++ b/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php @@ -0,0 +1,36 @@ +longText('url')->after('result')->nullable(); + $table->string('job_command_name')->after('url')->nullable(); + $table->longText('job_command')->after('job_command_name')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('job_results', function (Blueprint $table) { + $table->dropColumn('url'); + $table->dropColumn('job_command_name'); + $table->dropColumn('job_command'); + }); + } +} diff --git a/database/migrations/2023_12_04_224416_create_bill_groups_table.php b/database/migrations/2023_12_04_224416_create_bill_groups_table.php new file mode 100644 index 00000000..e5fd986c --- /dev/null +++ b/database/migrations/2023_12_04_224416_create_bill_groups_table.php @@ -0,0 +1,44 @@ +id(); + $table->string('reference')->unique(); + $table->foreignId('issuer')->unsigned(); + $table->foreignId('receiver')->unsigned(); + $table->decimal('amount', 14, 5)->default(0.00); + $table->decimal('original_amount', 14, 5)->default(0.00); + $table->foreignId('currency_id')->unsigned(); + $table->foreignId('original_currency_id')->unsigned(); + $table->decimal('currency_rate', 14, 5)->default(0.00); + $table->decimal('tax', 14, 5)->default(0.00); + $table->decimal('service_charge', 14, 5)->default(0.00); + $table->integer('status')->default(ApprovalStatus::PENDING_VERIFICATION); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('bill_groups'); + } +} diff --git a/database/migrations/2023_12_04_224509_create_bill_group_payments_table.php b/database/migrations/2023_12_04_224509_create_bill_group_payments_table.php new file mode 100644 index 00000000..5e0d2aa2 --- /dev/null +++ b/database/migrations/2023_12_04_224509_create_bill_group_payments_table.php @@ -0,0 +1,34 @@ +id(); + $table->foreignId('bill_group_id')->constrained('bill_groups'); + $table->foreignId('group_id')->constrained('groups'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('bill_group_payments'); + } +} diff --git a/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php new file mode 100644 index 00000000..12c6d57f --- /dev/null +++ b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php @@ -0,0 +1,34 @@ +string('request_signature')->after('job_id')->nullable(); + $table->string('result_signature')->after('request_signature')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('job_results', function (Blueprint $table) { + $table->dropColumn('request_signature'); + $table->dropColumn('result_signature'); + }); + } +} diff --git a/database/migrations/2023_12_26_152448_add_type_to_transaction_mapping_logs_table.php b/database/migrations/2023_12_26_152448_add_type_to_transaction_mapping_logs_table.php new file mode 100644 index 00000000..3927920a --- /dev/null +++ b/database/migrations/2023_12_26_152448_add_type_to_transaction_mapping_logs_table.php @@ -0,0 +1,40 @@ +string('type',50)->default('invoices')->after('imported_date'); + }); + + foreach (DB::table('transaction_mapping_logs')->get() as $key => $value) { + $data = json_decode($value->data); + DB::table('transaction_mapping_logs')->where('id',$value->id)->update([ + 'type' => (isset($data->description) ? 'receipts' : 'invoices') + ]); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('transaction_mapping_logs', function (Blueprint $table) { + $table->dropColumn('type'); + }); + } +} diff --git a/database/migrations/2024_02_22_222130_create_bill_group_refunds_table.php b/database/migrations/2024_02_22_222130_create_bill_group_refunds_table.php new file mode 100644 index 00000000..f7b278b1 --- /dev/null +++ b/database/migrations/2024_02_22_222130_create_bill_group_refunds_table.php @@ -0,0 +1,22 @@ +id(); + $table->foreignId('bill_group_id')->unsigned()->on('bill_groups'); + $table->foreignId('transaction_id')->unsigned()->on('transactions'); + }); + } + + public function down() + { + Schema::dropIfExists('bill_group_refunds'); + } +} diff --git a/database/migrations/2024_03_08_135259_create_key_value_pairs_table.php b/database/migrations/2024_03_08_135259_create_key_value_pairs_table.php new file mode 100644 index 00000000..b952ff56 --- /dev/null +++ b/database/migrations/2024_03_08_135259_create_key_value_pairs_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('owner_type'); //'user', 'order', 'transaction' + $table->unsignedBigInteger('owner_id'); + $table->string('key'); + $table->string('value'); + $table->timestamps(); + + $table->index(['owner_type', 'owner_id']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('key_value_pairs'); + } +} diff --git a/database/migrations/2024_04_24_180633_create_remarks_table.php b/database/migrations/2024_04_24_180633_create_remarks_table.php new file mode 100644 index 00000000..6656fd77 --- /dev/null +++ b/database/migrations/2024_04_24_180633_create_remarks_table.php @@ -0,0 +1,41 @@ +id(); + $table->morphs('owner'); + $table->bigInteger('commenter_id')->unsigned()->index(); + $table->string('content',200); + $table->integer('type')->default(RemarkTypes::INTERNAL); + $table->softDeletes(); + $table->timestamps(); + }); + + Schema::table('remarks', function (Blueprint $table) { + $table->string('owner_type', 191)->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('remarks'); + } +} diff --git a/database/migrations/2024_07_14_175408_create_model_attributes_table.php b/database/migrations/2024_07_14_175408_create_model_attributes_table.php new file mode 100644 index 00000000..f05f6f8f --- /dev/null +++ b/database/migrations/2024_07_14_175408_create_model_attributes_table.php @@ -0,0 +1,24 @@ +id(); + $table->morphs('owner'); + $table->string('name'); + $table->json('value'); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('model_attributes'); + } +} diff --git a/database/migrations/2024_07_15_194853_create_voucher_campaigns_table.php b/database/migrations/2024_07_15_194853_create_voucher_campaigns_table.php new file mode 100644 index 00000000..f02685d6 --- /dev/null +++ b/database/migrations/2024_07_15_194853_create_voucher_campaigns_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('campaign_id'); + $table->string('name'); + $table->string('slug')->unique(); + $table->text('description')->nullable(); + $table->integer('limit_per_month')->default(0); + $table->boolean('is_display')->default(false); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('voucher_campaigns'); + } +} diff --git a/database/migrations/2024_07_15_195005_add_voucher_campaign_id_to_vouchers_table.php b/database/migrations/2024_07_15_195005_add_voucher_campaign_id_to_vouchers_table.php new file mode 100644 index 00000000..80c5b5a9 --- /dev/null +++ b/database/migrations/2024_07_15_195005_add_voucher_campaign_id_to_vouchers_table.php @@ -0,0 +1,33 @@ +foreignId('voucher_campaign_id')->nullable()->constrained('voucher_campaigns')->onDelete('set null'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('vouchers', function (Blueprint $table) { + $table->dropForeign(['voucher_campaign_id']); + $table->dropColumn('voucher_campaign_id'); + }); + } +} diff --git a/database/migrations/2024_07_25_205651_add_created_by_and_creator_type_to_banks_table.php b/database/migrations/2024_07_25_205651_add_created_by_and_creator_type_to_banks_table.php new file mode 100644 index 00000000..1d99906f --- /dev/null +++ b/database/migrations/2024_07_25_205651_add_created_by_and_creator_type_to_banks_table.php @@ -0,0 +1,35 @@ +unsignedBigInteger('created_by')->nullable()->after('country_id'); + $table->unsignedInteger('creator_type')->nullable()->after('created_by'); // 'admin' or 'customer', see RoleTypes.php for more + $table->foreign('created_by')->references('id')->on('users')->onDelete('set null'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('banks', function (Blueprint $table) { + $table->dropForeign(['created_by']); + $table->dropColumn(['created_by', 'creator_type']); + }); + } +} diff --git a/database/migrations/2024_07_31_212359_add_deleted_at_to_key_value_pairs.php b/database/migrations/2024_07_31_212359_add_deleted_at_to_key_value_pairs.php new file mode 100644 index 00000000..df64b4a8 --- /dev/null +++ b/database/migrations/2024_07_31_212359_add_deleted_at_to_key_value_pairs.php @@ -0,0 +1,32 @@ +softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('key_value_pairs', function (Blueprint $table) { + $table->dropSoftDeletes(); + }); + } +} diff --git a/database/migrations/2024_08_24_173025_add_description_to_vouchers_table.php b/database/migrations/2024_08_24_173025_add_description_to_vouchers_table.php new file mode 100644 index 00000000..6dde0c8a --- /dev/null +++ b/database/migrations/2024_08_24_173025_add_description_to_vouchers_table.php @@ -0,0 +1,32 @@ +text('description')->after('name')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('vouchers', function (Blueprint $table) { + $table->dropColumn('description'); + }); + } +} diff --git a/database/seeds/AdminUserPermissionsTableSeeder.php b/database/seeds/AdminUserPermissionsTableSeeder.php index 0c3d5acf..ee86dc8a 100644 --- a/database/seeds/AdminUserPermissionsTableSeeder.php +++ b/database/seeds/AdminUserPermissionsTableSeeder.php @@ -71,6 +71,10 @@ class AdminUserPermissionsTableSeeder extends Seeder ['name' => 'delete milestone', 'guard_name' => 'web'], ['name' => 'delete reward', 'guard_name' => 'web'], + ['name' => 'add voucher', 'guard_name' => 'web'], + ['name' => 'list voucher campaigns', 'guard_name' => 'web'], + + ['name' => 'update bank_metadata', 'guard_name' => 'web'], ]; foreach ($permissions as $permission){ diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index 87d72f71..eb94b74f 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -48,6 +48,6 @@ class DatabaseSeeder extends Seeder $this->call(DummyDataSeeder::class); } - DB::commit(); + // DB::commit(); } } diff --git a/public/images/alipay_logo.png b/public/images/alipay_logo.png new file mode 100644 index 00000000..5bd88d72 Binary files /dev/null and b/public/images/alipay_logo.png differ diff --git a/resources/assets/vue/app.js b/resources/assets/vue/app.js index abb7a17e..39e22279 100644 --- a/resources/assets/vue/app.js +++ b/resources/assets/vue/app.js @@ -34,6 +34,13 @@ Vue.use(VueTheMask); Vue.use(filters); Vue.directive('closable', closable); +Vue.directive('tooltip', function(el, binding){ + $(el).tooltip({ + title: binding.value, + placement: binding.arg, + trigger: 'hover' + }) +}) Vue.mixin({ methods: { route: route diff --git a/resources/assets/vue/components/accounting/elements/HistoryImportedInvoices.vue b/resources/assets/vue/components/accounting/elements/HistoryImportedInvoices.vue new file mode 100644 index 00000000..d3d68cfb --- /dev/null +++ b/resources/assets/vue/components/accounting/elements/HistoryImportedInvoices.vue @@ -0,0 +1,39 @@ + + + diff --git a/resources/assets/vue/components/accounting/elements/HistoryImportedReceipts.vue b/resources/assets/vue/components/accounting/elements/HistoryImportedReceipts.vue new file mode 100644 index 00000000..00138fa5 --- /dev/null +++ b/resources/assets/vue/components/accounting/elements/HistoryImportedReceipts.vue @@ -0,0 +1,39 @@ + + + diff --git a/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue b/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue index f92fc5d7..d1b59663 100644 --- a/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue +++ b/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue @@ -75,7 +75,7 @@
{{ owner.reference }} -
+
@@ -90,6 +90,21 @@ > + + + + + +
@@ -144,7 +159,7 @@ contentText="Are you sure you want to reject this mapping?" modalType="delete" class="text-center" - :apiRoute="route('api.accounting.statement_transaction.owner.status.update', item.id, 'reject')" + :apiRoute="route('api.accounting.statement_transaction.owner.status.update', item.owners.pending_verification[0].id, 'reject')" apiMethod="post" :section="section" > diff --git a/resources/assets/vue/components/accounting/sections/ImportedInvoiceMappedComponent.vue b/resources/assets/vue/components/accounting/sections/ImportedInvoiceMappedComponent.vue index f10f9181..185da370 100644 --- a/resources/assets/vue/components/accounting/sections/ImportedInvoiceMappedComponent.vue +++ b/resources/assets/vue/components/accounting/sections/ImportedInvoiceMappedComponent.vue @@ -98,21 +98,17 @@ }, methods: { appendComponentTitle() { - this.componentTitle = this.section == 'importInvoiceMapping' ? 'Imported Invoices Mapped' : 'Imported Receipts Mapped'; + this.componentTitle = 'Imported Invoices Mapped'; }, appendComponentTableHeader() { - if (this.section == 'importInvoiceMapping') { - this.tableHeaders = ['No','Doc No','Date','Debtor Code','Debtor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No','Payment Received Date']; - } else { - this.tableHeaders = ['No','OR No','Date','Creditor Code','Creditor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No']; - } + this.tableHeaders = ['No','Doc No','Date','Debtor Code','Debtor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No','Payment Received Date']; }, importInvoice(){ this.isLoading = true; this.parameters = { files: this.files }; - this.submit(this.route('api.'+(this.section == 'importInvoiceMapping' ? 'import_invoices' : 'import_receipts')+'.upload'), 'post', this.section, true, false); + this.submit(this.route('api.import_invoices.upload'), 'post', this.section, true, false); }, successHandler(response){ @@ -128,7 +124,7 @@ downloadInvoiceMapped() { var arrDateTime = this.importedDate.split(" "); - const fileName = this.section == 'importInvoiceMapping' ? 'InvoiceMapped' : 'ReceiptMapped'; + const fileName = 'importInvoiceMapping'; window.open(this.route('importedInvoiceMapped.export')+'?date='+arrDateTime[0]+'&time='+arrDateTime[1]+'&fileName='+fileName, '_blank'); }, diff --git a/resources/assets/vue/components/accounting/sections/ImportedReceiptMappedComponent.vue b/resources/assets/vue/components/accounting/sections/ImportedReceiptMappedComponent.vue new file mode 100644 index 00000000..25db762e --- /dev/null +++ b/resources/assets/vue/components/accounting/sections/ImportedReceiptMappedComponent.vue @@ -0,0 +1,138 @@ + + + \ No newline at end of file diff --git a/resources/assets/vue/components/accounting/sections/ReportTransactionsMappedComponent.vue b/resources/assets/vue/components/accounting/sections/ReportTransactionsMappedComponent.vue index e3d4e0d2..86da623c 100644 --- a/resources/assets/vue/components/accounting/sections/ReportTransactionsMappedComponent.vue +++ b/resources/assets/vue/components/accounting/sections/ReportTransactionsMappedComponent.vue @@ -3,19 +3,74 @@
-
-
-
-
Mapped Report
+
+ +
+
+
+
Mapped Report
+
+
+
+
+
History Imported Invoices Report
+
+
+
+
+
History Imported Receipts Report
+
+
-
+
+
+
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+
+
+ + + + +
+
+ + + + +
+
+
+
Mapped Report
+
+
+
+
@@ -35,7 +90,7 @@
- + @@ -44,22 +99,175 @@
+ + +
+
+
+
+
+
+
+ + + + +
+
+ + + + +
+
+
+
History Imported Invoices Report
+
+
+
+
+
+
+
+
Date
+
+
+
+ + + + +
+
+
+
+ + +
+
+
+
+
+
+
+ + + + +
+
+ + + + +
+
+
+
History Imported Receipts Report
+
+
+
+
+
+
+
+
Date
+
+
+
+ + + + +
+
+
+
\ No newline at end of file diff --git a/resources/assets/vue/components/banks/forms/BankAccountFormComponent.vue b/resources/assets/vue/components/banks/forms/BankAccountFormComponent.vue index 9c89c89d..3bf4f46a 100644 --- a/resources/assets/vue/components/banks/forms/BankAccountFormComponent.vue +++ b/resources/assets/vue/components/banks/forms/BankAccountFormComponent.vue @@ -133,12 +133,15 @@
-
+
{{disabled ? 'Change Recipient Account' : 'Cancel'}}
-
+
Add Account
+
+
Update Details
+
@@ -179,6 +182,22 @@ type: String, required: false, default: 'RMB' + }, + isEditing: { + type: Boolean, + default: false + }, + isCancelButtonHidden: { + type: Boolean, + default: false + }, + billNo: { + type: String, + default: '' + }, + transactionId: { + type: Number, + default: 0 } }, data(){ @@ -194,6 +213,8 @@ swift: '', snap: '', country_id: this.country_id, + bill_no: this.billNo, + transaction_id: this.transactionId, } } }, @@ -224,10 +245,24 @@ }, methods: { submitForm(){ - this.submit(route('api.bank.create'), 'post', this.section, true, false); + if(this.isEditing){ + this.parameters.company_id = this.company_id; + this.parameters.account_type = this.type; + this.parameters.bill_no = this.billNo; + this.parameters.transaction_id = this.transactionId; + this.submit(route('api.bank.update', this.parameters.id), 'put', this.section, true, false); + } + else{ + this.submit(route('api.bank.create'), 'post', this.section, true, false); + } }, successHandler(response){ - this.type !== 2 ? this.closeModal() : this.$emit('createdBank', response.payload.data); + if(this.isEditing){ + this.type !== 2 ? this.closeModal() : this.$emit('updatedBankDetails', response.payload.data, this.transactionId); + } + else{ + this.type !== 2 ? this.closeModal() : this.$emit('createdBank', response.payload.data); + } this.formHandler(); this.resetForm(); }, diff --git a/resources/assets/vue/components/banks/forms/PhoneAccountFormComponent.vue b/resources/assets/vue/components/banks/forms/PhoneAccountFormComponent.vue index 76401d2b..dde77e9c 100644 --- a/resources/assets/vue/components/banks/forms/PhoneAccountFormComponent.vue +++ b/resources/assets/vue/components/banks/forms/PhoneAccountFormComponent.vue @@ -39,12 +39,15 @@
-
+
{{disabled ? 'Change Recipient Account' : 'Cancel'}}
-
+
+
+ +
@@ -80,6 +83,22 @@ type: Object, required: false, default: null + }, + isEditing: { + type: Boolean, + default: false + }, + isCancelButtonHidden: { + type: Boolean, + default: false + }, + billNo: { + type: String, + default: '' + }, + transactionId: { + type: Number, + default: 0 } }, data(){ @@ -93,6 +112,8 @@ account_no: '', bank_branch: '', country_id: this.country_id, + bill_no: this.billNo, + transaction_id: this.transactionId, }, englishTextWarning: false, confirmProceedEnglishText: false, @@ -115,10 +136,24 @@ submitForm(){ this.parameters.account_type = 3; this.parameters.bank_name = '-'; - this.submit(route('api.bank.create'), 'post', this.section, true, false); + if(this.isEditing){ + this.parameters.company_id = this.company_id; + this.parameters.account_type = this.type; + this.parameters.bill_no = this.billNo; + this.parameters.transaction_id = this.transactionId; + this.submit(route('api.bank.update', this.parameters.id), 'put', this.section, true, false); + } + else{ + this.submit(route('api.bank.create'), 'post', this.section, true, false); + } }, successHandler(response){ - this.type !== 2 ? this.closeModal() : this.$emit('createdBank', response.payload.data); + if(this.isEditing){ + this.type !== 2 ? this.closeModal() : this.$emit('updatedBankDetails', response.payload.data, this.transactionId); + } + else{ + this.type !== 2 ? this.closeModal() : this.$emit('createdBank', response.payload.data); + } this.formHandler(); this.resetForm(); }, @@ -140,4 +175,4 @@ mixins: [FormHandler] } - \ No newline at end of file + diff --git a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue index 45722aaf..7efc8507 100644 --- a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue +++ b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue @@ -1,20 +1,56 @@