diff --git a/app/Classes/Jobs/ListDocumentsJob.php b/app/Classes/Jobs/ListDocumentsJob.php index 6e93062b..93f1b1d3 100644 --- a/app/Classes/Jobs/ListDocumentsJob.php +++ b/app/Classes/Jobs/ListDocumentsJob.php @@ -9,8 +9,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use App\Models\JobResult; -use Illuminate\Support\Facades\Log; + class ListDocumentsJob implements ShouldQueue { @@ -43,18 +42,7 @@ class ListDocumentsJob implements ShouldQueue $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); } - $result = (App()->make(ListDocumentsJobProcessor::class))->execute($this->listGenericJobObject); - - //cief todo: Insert into DB: job id, query result, timestamp - // Store the result in the job_results table - - //cief todo: why cannot save data in table like this - // $model = new JobResult(); - // $model->job_id = $this->job->getJobId(); - // $model->result = json_encode($result); - // $model->save(); - - // Log::error(json_encode($model->id)); + (App()->make(ListDocumentsJobProcessor::class))->execute($this->listGenericJobObject); } public function getJobId(){ 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/Bookings/Services/FetchesBookingQuotation.php b/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php index 5fe85c35..1d3d7acc 100644 --- a/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php +++ b/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php @@ -13,6 +13,7 @@ use App\Classes\Modules\Currencies\Services\FetchesCurrency; use App\Classes\Modules\Vouchers\Services\Voucherify\ValidatesVoucherifyVoucher; use App\Models\Company; use App\Models\Currency; +use Illuminate\Support\Facades\Log; class FetchesBookingQuotation { @@ -62,6 +63,15 @@ class FetchesBookingQuotation $employee = $company->employees()->first(); $validateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject($company->id, $voucherCode, $calculationObject->getSubTotal(), $employee); $result = $this->validatesVoucherifyVoucher->execute($validateVoucherifyVoucherObject); + + // //A minimum charge of RM5 applies when voucher used make price to be paid by customer RM0 + // if(isset($result->order->total_amount) && $result->order->total_amount === 0){ + // // $result->order->cief_original_total_amount = $result->order->total_amount; + // $result->order->total_amount = 500; + // $result->order->total_discount_amount = $result->order->total_discount_amount - $result->order->total_amount; + // Log::info('FetchesBookingQuotation order total_amount RM0 (voucher applied) for company id ' . $company->id. ' with original amount ' . $calculationObject->getSubTotal()); + // } + $voucher = [ "code" => $result->code, "discount" => property_exists($result, 'discount') ? $result->discount : null, diff --git a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php index 597fa8bc..bda5ba5a 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 : "", $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/Vouchers/ControllersLogic/CreateVoucherLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php index a5d65544..de29aa63 100644 --- a/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php +++ b/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php @@ -6,9 +6,31 @@ 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\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 +45,61 @@ 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; + /** * 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 */ - 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) { + $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; } /** @@ -42,8 +109,125 @@ 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 - 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->attributes()->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/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/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/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 d4fd1e7b..78f67dfe 100644 --- a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php @@ -27,21 +27,26 @@ class VoucherObject implements DataTransferObject /** @var string|null */ private $endDate; + /** @var int */ + private $voucherCampaignId; + /** * VoucherObject constructor. * @param string $code * @param string $name * @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 $type, ?float $value, ?int $voucherCampaignId, ?string $startDate = '', ?string $endDate = '') { $this->code = $code; $this->name = $name; $this->type = $type; $this->value = $value; + $this->voucherCampaignId = $voucherCampaignId; $this->startDate = $startDate; $this->endDate = $endDate; } @@ -62,7 +67,6 @@ class VoucherObject implements DataTransferObject return $this->name; } - /** * @return string */ @@ -71,7 +75,6 @@ class VoucherObject implements DataTransferObject return $this->type; } - /** * @return float */ @@ -80,6 +83,14 @@ class VoucherObject implements DataTransferObject return $this->value; } + /** + * @return int + */ + public function getVoucherCampaignId(): ?int + { + return $this->voucherCampaignId; + } + /** * @return DateTime */ diff --git a/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php b/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php index 690ad59f..1026a330 100644 --- a/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php +++ b/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php @@ -4,110 +4,76 @@ 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 = $voucherifyVoucherFetched->campaign; + //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; + } + $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, + isset($voucherName) ? $voucherName : "Voucher ".Carbon::now()->format('Ymd'), + $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..dd17e76c 100644 --- a/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php +++ b/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php @@ -84,6 +84,9 @@ class BookingToVoucherifyProcessor if($voucherCode){ $redeemVoucherifyVoucherObject = new RedeemVoucherifyVoucherObject($companyId, $transaction->id, $voucherCode, $amount, $user); $redeemVoucherResult = $this->redeemsVoucherifyVoucher->execute($redeemVoucherifyVoucherObject); + + // Log::info('redeemVoucherResult: '.json_encode($redeemVoucherResult)); + $redeemedVoucher = $redeemVoucherResult->voucher; $redemptionId = $redeemVoucherResult->id; @@ -123,8 +126,9 @@ 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; + $voucherCampaignId = isset($redeemedVoucher->campaign_id) ? $redeemedVoucher->campaign_id : null; - $voucherObject= new VoucherObject($redeemedVoucher->code, isset($redeemedVoucher->metadata->name) ? $redeemedVoucher->metadata->name : "", $voucherType, $voucherValue); + $voucherObject= new VoucherObject($redeemedVoucher->code, isset($redeemedVoucher->metadata->name) ? $redeemedVoucher->metadata->name : "", $voucherType, $voucherValue, $voucherCampaignId); $voucher = $this->createsVoucher->execute($voucherObject); if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); 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..3622036a 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) { @@ -33,6 +33,7 @@ class CreatesVoucher extends AbstractUpdateRecord $model->name = $object->getName(); $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/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..25515097 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Standards/Rules/CanCreateVoucher.php @@ -0,0 +1,64 @@ +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'); + 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..c451778a --- /dev/null +++ b/app/Classes/Modules/Vouchers/Standards/Rules/CanListVoucherCampaigns.php @@ -0,0 +1,40 @@ +can('list voucher campaigns')) { + 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/ValueObjects/Constants/Vouchers.php b/app/Classes/ValueObjects/Constants/Vouchers.php index d43194f9..0e870182 100644 --- a/app/Classes/ValueObjects/Constants/Vouchers.php +++ b/app/Classes/ValueObjects/Constants/Vouchers.php @@ -5,4 +5,14 @@ namespace App\Classes\ValueObjects\Constants; final class Vouchers { public const WELCOME_50_PERCENT_OFF = 'WELCOME50%OFF'; + + public const SORRY_50 = 'SORRY50'; + public const SORRY_100 = 'SORRY100'; + public const SORRY_200 = 'SORRY200'; + + const OPTIONS_SORRY = [ + ['text' => 'SORRY 50', 'id' => Vouchers::SORRY_50], + ['text' => 'SORRY 100', 'id' => Vouchers::SORRY_100], + ['text' => 'SORRY 200', 'id' => Vouchers::SORRY_200], + ]; } 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/VoucherCampaignResource.php b/app/Http/Resources/VoucherCampaignResource.php new file mode 100644 index 00000000..ade4334b --- /dev/null +++ b/app/Http/Resources/VoucherCampaignResource.php @@ -0,0 +1,32 @@ +has('include_metadata')) { + $metadata = KeyValueBasicResource::collection($this->attributes); + } + + 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/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..e97320e5 --- /dev/null +++ b/app/Models/VoucherCampaign.php @@ -0,0 +1,29 @@ +hasMany(Voucher::class, 'voucher_campaign_id'); + } + + /** + * @return MorphMany + */ + public function attributes(): MorphMany + { + return $this->morphMany(KeyValuePair::class, 'owner'); + } +} 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/seeds/AdminUserPermissionsTableSeeder.php b/database/seeds/AdminUserPermissionsTableSeeder.php index 0c3d5acf..aa47596d 100644 --- a/database/seeds/AdminUserPermissionsTableSeeder.php +++ b/database/seeds/AdminUserPermissionsTableSeeder.php @@ -71,6 +71,8 @@ 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'], ]; foreach ($permissions as $permission){ diff --git a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue index 89a56b0f..bcfd7219 100644 --- a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue +++ b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue @@ -5,11 +5,13 @@
- - {{ item.voucher.code }}
diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index 10246745..7573253c 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -697,6 +697,7 @@ this.submit(route('api.voucher.validate'), 'post', '', false, false); } else{ + this.voucherCodeFailedReason = 'Please enter voucher code'; this.voucherValidated = true; this.voucherIsChecking = false; } diff --git a/resources/assets/vue/components/companies/elements/CustomerProfileComponent.vue b/resources/assets/vue/components/companies/elements/CustomerProfileComponent.vue index 8217fbbe..ca9a8b67 100644 --- a/resources/assets/vue/components/companies/elements/CustomerProfileComponent.vue +++ b/resources/assets/vue/components/companies/elements/CustomerProfileComponent.vue @@ -48,6 +48,9 @@
+
+ +
import componentHandler from '../../../general/mixins/componentHandler'; export default { + methods: { + hrefCustomerVoucherPage(){ + window.location.href = route('customer.reward', this.item.reference); + }, + }, mixins: [componentHandler] } diff --git a/resources/assets/vue/components/companies/sections/AddVoucherOptionsSectionComponent.vue b/resources/assets/vue/components/companies/sections/AddVoucherOptionsSectionComponent.vue new file mode 100644 index 00000000..2e438aa1 --- /dev/null +++ b/resources/assets/vue/components/companies/sections/AddVoucherOptionsSectionComponent.vue @@ -0,0 +1,110 @@ +
+
+
+
+
+
+
+
+
Add Sorry Voucher
+
+
+
+
+ + + + +
+
+
+ + {{ voucherCodeFailedReason }} + Voucher added +
+
+
+ +
+
+
+
+
+
+
+
+ + + diff --git a/resources/assets/vue/components/companies/sections/AddVoucherSectionComponent.vue b/resources/assets/vue/components/companies/sections/AddVoucherSectionComponent.vue index 65b0c2ed..1778ec2f 100644 --- a/resources/assets/vue/components/companies/sections/AddVoucherSectionComponent.vue +++ b/resources/assets/vue/components/companies/sections/AddVoucherSectionComponent.vue @@ -75,12 +75,10 @@ } else{ this.voucherFetched = false; + this.voucherCodeFailedReason = 'Voucher Invalid'; if(response.payload.data && response.payload.data.reason){ this.voucherCodeFailedReason = response.payload.data.reason; } - else{ - this.voucherCodeFailedReason = 'Voucher Invalid'; - } } this.voucherIsChecking = false; }, @@ -94,6 +92,7 @@ this.submit(this.route('api.voucher.create'), 'post', this.section, false, false); }, errorHandler(error){ + this.voucherCodeFailedReason = 'Something went wrong, please report this to our customer service'; this.voucherFetched = false; this.voucherIsChecking = false; }, diff --git a/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue index 9429593a..981e10b7 100644 --- a/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue +++ b/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue @@ -1,6 +1,11 @@