diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..ae145ac7 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [{ + "name": "Listen for XDebug on Docker", + "type": "php", + "request": "launch", + "port": 9002, + "pathMappings": { + "/var/www/html": "${workspaceFolder}", + }, + "log": true + }] +} diff --git a/app/Classes/General/Eloquent/Filters/Code.php b/app/Classes/General/Eloquent/Filters/Code.php new file mode 100644 index 00000000..dc98ed43 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/Code.php @@ -0,0 +1,20 @@ +where('code', '=', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/HasActiveReward.php b/app/Classes/General/Eloquent/Filters/HasActiveReward.php new file mode 100644 index 00000000..5770ca6e --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasActiveReward.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/HasUsedVoucher.php b/app/Classes/General/Eloquent/Filters/HasUsedVoucher.php new file mode 100644 index 00000000..fe6cdd92 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasUsedVoucher.php @@ -0,0 +1,30 @@ +where('user_id', Auth::user()->id) + ->where(function ($query) { + $query->whereHas('voucher', function ($subquery) { + $subquery->whereHas('redemptions', function ($subsubquery) { + $subsubquery->whereHas('transaction', function ($subsubsubquery) { + $subsubsubquery->whereHas('owner'); + }); + }); + }); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/HasUsedVoucherForAdmin.php b/app/Classes/General/Eloquent/Filters/HasUsedVoucherForAdmin.php new file mode 100644 index 00000000..83b38ccb --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasUsedVoucherForAdmin.php @@ -0,0 +1,38 @@ +id; + + return $builder->where('user_id', $userId) + ->where(function ($query) use ($userId){ + $query->whereHas('voucher', function ($subquery) use ($userId){ + $subquery->whereHas('redemptions', function ($subsubquery) use ($userId){ + $subsubquery->whereHas('transaction', function ($subsubsubquery) use ($userId){ + $subsubsubquery->whereHas('booking', function ($s4query) use ($userId){ + $s4query->whereHas('company', function ($s5query) use ($userId) { + $s5query->whereHas('employees', function ($s6query) use ($userId){ + $s6query->where('user_id', $userId); + }); + }); + }); + }); + }); + }); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/UserId.php b/app/Classes/General/Eloquent/Filters/UserId.php new file mode 100644 index 00000000..7b8cb9e9 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/UserId.php @@ -0,0 +1,20 @@ +where('user_id', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/isActive.php b/app/Classes/General/Eloquent/Filters/isActive.php new file mode 100644 index 00000000..46a2cde7 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/isActive.php @@ -0,0 +1,20 @@ +where('is_active', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/isActive2.php b/app/Classes/General/Eloquent/Filters/isActive2.php new file mode 100644 index 00000000..2cd372cb --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/isActive2.php @@ -0,0 +1,19 @@ +where('is_active', $value); + } +} diff --git a/app/Classes/General/Helper.php b/app/Classes/General/Helper.php index 267ee401..ac89540b 100644 --- a/app/Classes/General/Helper.php +++ b/app/Classes/General/Helper.php @@ -29,7 +29,7 @@ class Helper * @param $log * @return array */ - static function debugLoggerForPerfexCRM($log){ + static function debugLogger($log){ if($log && isset($log['message'])){ $message = $log['message']; $substring = 'No data were found'; diff --git a/app/Classes/General/Interfaces/Voucherifiable.php b/app/Classes/General/Interfaces/Voucherifiable.php new file mode 100644 index 00000000..b42427e1 --- /dev/null +++ b/app/Classes/General/Interfaces/Voucherifiable.php @@ -0,0 +1,11 @@ +createUserProcessor = $createUserProcessor; $this->createCompanyProcessor = $createCompanyProcessor; @@ -91,8 +101,10 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->assignSegmentProcessor = $assignSegmentProcessor; $this->authenticationProcessor = $authenticationProcessor; $this->generateEmailVerificationAttemptProcessor = $generateEmailVerificationAttemptProcessor; - $this->createPerfexCRMLeadProcessor = $createPerfexCRMLeadProcessor; $this->createsSeasonalSegment = $createsSeasonalSegment; + $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; + $this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor; + $this->createVoucherProcessor = $createVoucherProcessor; } /** @@ -106,6 +118,7 @@ class CreateCustomerLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { + /** @var User $user */ $user = $this->createUserProcessor->execute($request, RoleTypes::USER, App::environment(['local']) ? ApprovalStatus::APPROVED : ApprovalStatus::PENDING_VERIFICATION); @@ -132,7 +145,6 @@ class CreateCustomerLogic extends AbstractControllerLogic } if(config('perfexcrm.is_enabled') == 'true'){ - //$this->createPerfexCRMLeadProcessor->execute($request); $createLeadPerfexCRMObject = new CreateLeadPerfexCRMObject( $request->input('name'), $request->input('email'), @@ -145,7 +157,11 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->generateEmailVerificationAttemptProcessor->execute($user); - return $this->response($this->authenticationProcessor->execute($request)); + $this->newCustomerToVoucherifyProcessor->execute($company->id, $user, true); + + $this->createVoucherProcessor->execute($user, 'WELCOME2EXCHANGE'); + + return $this->response($this->authenticationProcessor->execute($request, false)); } } diff --git a/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php b/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php index fabb88c6..a310fdb3 100644 --- a/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php +++ b/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php @@ -8,6 +8,9 @@ use App\Classes\Modules\Accounts\Services\AuthenticationRedirect; use App\Classes\Modules\Accounts\Services\FetchesUser; use App\Classes\Modules\Accounts\Services\GeneratesAuthenticationToken; use App\Classes\Modules\Accounts\Standards\Rules\CanAuthenticateUser; +use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor; +use App\Classes\Modules\Vouchers\Processors\Voucherify\NewCustomerToVoucherifyProcessor; +use App\Classes\ValueObjects\Constants\Milestones; use Illuminate\Http\Request; class AuthenticationProcessor @@ -28,6 +31,13 @@ class AuthenticationProcessor /** @var AuthenticationRedirect */ private $authenticationRedirect; + /** @var CheckMilestonesForRewardProcessor */ + private $checkMilestonesForRewardProcessor; + + /** @var NewCustomerToVoucherifyProcessor */ + private $newCustomerToVoucherifyProcessor; + + /** * AuthenticationProcessor constructor. * @param CanAuthenticateUser $canAuthenticateUser @@ -35,14 +45,18 @@ class AuthenticationProcessor * @param GeneratesAuthenticationToken $generatesAuthenticationToken * @param FetchesUser $fetchesUser * @param AuthenticationRedirect $authenticationRedirect + * @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor + * @param NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor */ - public function __construct(CanAuthenticateUser $canAuthenticateUser, AuthenticatesUser $authenticatesUser, GeneratesAuthenticationToken $generatesAuthenticationToken, FetchesUser $fetchesUser, AuthenticationRedirect $authenticationRedirect) + public function __construct(CanAuthenticateUser $canAuthenticateUser, AuthenticatesUser $authenticatesUser, GeneratesAuthenticationToken $generatesAuthenticationToken, FetchesUser $fetchesUser, AuthenticationRedirect $authenticationRedirect, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor) { $this->canAuthenticateUser = $canAuthenticateUser; $this->authenticatesUser = $authenticatesUser; $this->generatesAuthenticationToken = $generatesAuthenticationToken; $this->fetchesUser = $fetchesUser; $this->authenticationRedirect = $authenticationRedirect; + $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; + $this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor; } @@ -53,7 +67,7 @@ class AuthenticationProcessor * @throws \App\Classes\Exceptions\AccessUnauthorisedException * @throws \App\Classes\Exceptions\RequestValidationException */ - public function execute(Request $request): array { + public function execute(Request $request, bool $isSignIn = true): array { $object = new AuthenticationCredentialsObject($request->input('email'), $request->input('password')); @@ -63,8 +77,13 @@ class AuthenticationProcessor $user = $this->fetchesUser->execute(['email' => $object->getEmail()]); + if($isSignIn){ + $this->newCustomerToVoucherifyProcessor->execute(0, $user, false); + } + + //cief todo: case study 1 + $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_1]); + return ['access_token' => $this->generatesAuthenticationToken->execute($user), 'redirect_url' => $this->authenticationRedirect->url($user)]; - } - -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Addresses/ControllersLogic/CreateAddressLogic.php b/app/Classes/Modules/Addresses/ControllersLogic/CreateAddressLogic.php index 8fd6fe7f..a760254f 100644 --- a/app/Classes/Modules/Addresses/ControllersLogic/CreateAddressLogic.php +++ b/app/Classes/Modules/Addresses/ControllersLogic/CreateAddressLogic.php @@ -9,10 +9,12 @@ use App\Classes\Modules\Addresses\Services\FetchesDistrict; use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress; use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject; use App\Classes\Modules\Companies\Services\FetchesCompany; +use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor; use App\Http\Resources\AddressResource; use ErrorException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Classes\ValueObjects\Constants\Milestones; class CreateAddressLogic extends AbstractControllerLogic { @@ -39,19 +41,25 @@ class CreateAddressLogic extends AbstractControllerLogic /** @var CreatesAddress */ private $createsAddress; + /** @var CheckMilestonesForRewardProcessor */ + private $checkMilestonesForRewardProcessor; + + /** * CreateAddressLogic constructor. * @param CanCreateAddress $canCreateAddress * @param FetchesDistrict $fetchesDistrict * @param FetchesCompany $fetchesCompany * @param CreatesAddress $createsAddress + * @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor */ - public function __construct(CanCreateAddress $canCreateAddress, FetchesDistrict $fetchesDistrict, FetchesCompany $fetchesCompany, CreatesAddress $createsAddress) + public function __construct(CanCreateAddress $canCreateAddress, FetchesDistrict $fetchesDistrict, FetchesCompany $fetchesCompany, CreatesAddress $createsAddress, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor) { $this->canCreateAddress = $canCreateAddress; $this->fetchesDistrict = $fetchesDistrict; $this->fetchesCompany = $fetchesCompany; $this->createsAddress = $createsAddress; + $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; } /** @@ -70,10 +78,15 @@ class CreateAddressLogic extends AbstractControllerLogic $this->canCreateAddress->passes($object); - $query = $this->createsAddress->execute($this->fetchesCompany->execute(['id' => $request->input('company_id')]), $object); + $company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]); + $query = $this->createsAddress->execute($company, $object); + + //cief todo: case study 6 + // $user = $company->employees()->first(); + // $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_6]); return $this->resourceResponse(new AddressResource($query)); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Banks/ControllersLogic/CreateBankLogic.php b/app/Classes/Modules/Banks/ControllersLogic/CreateBankLogic.php index dc67848a..bb9a3468 100644 --- a/app/Classes/Modules/Banks/ControllersLogic/CreateBankLogic.php +++ b/app/Classes/Modules/Banks/ControllersLogic/CreateBankLogic.php @@ -8,7 +8,10 @@ use App\Classes\Modules\Banks\Standards\Rules\CanCreateBank; use App\Classes\Modules\Banks\Services\CreatesBank; use App\Classes\Modules\Banks\Services\CreatesBankLog; use App\Classes\Modules\Banks\DataTransferObjects\BankObject; +use App\Classes\Modules\Companies\Services\FetchesCompany; +use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor; use App\Http\Resources\BankResource; +use App\Classes\ValueObjects\Constants\Milestones; use ErrorException; use Illuminate\Http\JsonResponse; @@ -36,21 +39,34 @@ class CreateBankLogic extends AbstractControllerLogic /** @var CreatesBankLog */ private $createsBankLog; + /** @var FetchesCompany */ + private $fetchesCompany; + + /** @var CheckMilestonesForRewardProcessor */ + private $checkMilestonesForRewardProcessor; + + /** * CreateBankLogic constructor. * @param CanCreateBank $canCreateBank * @param CreatesBank $createsBank * @param CreatesBankLog $createsBankLog + * @param FetchesCompany $fetchesCompany + * @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor */ public function __construct( CanCreateBank $canCreateBank, CreatesBank $createsBank, - CreatesBankLog $createsBankLog + CreatesBankLog $createsBankLog, + FetchesCompany $fetchesCompany, + CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor ) { $this->canCreateBank = $canCreateBank; $this->createsBank = $createsBank; $this->createsBankLog = $createsBankLog; + $this->fetchesCompany = $fetchesCompany; + $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; } /** @@ -73,7 +89,12 @@ class CreateBankLogic extends AbstractControllerLogic // $bankLog = $this->createsBankLog->execute($bank); + //cief todo: case study 4 + // $company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]); + // $user = $company->employees()->first(); + // $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_4]); + return $this->resourceResponse(new BankResource($bank)); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php index a93a3654..61f78dcb 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php @@ -14,7 +14,8 @@ 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\Milestones; use App\Http\Resources\BookingResource; use App\Models\Booking; @@ -50,6 +51,10 @@ class CreateBookingLogic extends AbstractControllerLogic /** @var BookingToPerfexCRMProcessor */ private $bookingToPerfexCRMProcessor; + /** @var CheckMilestonesForRewardProcessor */ + private $checkMilestonesForRewardProcessor; + + /** * CreateBookingLogic constructor. * @param CanCreateBooking $canCreateBooking @@ -57,14 +62,16 @@ class CreateBookingLogic extends AbstractControllerLogic * @param GeneratesBookingMarking $generatesBookingMarking * @param FetchesCompany $fetchesCompany * @param BookingToPerfexCRMProcessor $bookingToPerfexCRMProcessor + * @param CheckMilestoneForRewardProcessor $checkMilestonesForRewardProcessor */ - public function __construct(CanCreateBooking $canCreateBooking, CreatesBooking $createsBooking, GeneratesBookingMarking $generatesBookingMarking, FetchesCompany $fetchesCompany, BookingToPerfexCRMProcessor $bookingToPerfexCRMProcessor) + public function __construct(CanCreateBooking $canCreateBooking, CreatesBooking $createsBooking, GeneratesBookingMarking $generatesBookingMarking, FetchesCompany $fetchesCompany, BookingToPerfexCRMProcessor $bookingToPerfexCRMProcessor, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor) { $this->canCreateBooking = $canCreateBooking; $this->createsBooking = $createsBooking; $this->generatesBookingMarking = $generatesBookingMarking; $this->fetchesCompany = $fetchesCompany; $this->bookingToPerfexCRMProcessor = $bookingToPerfexCRMProcessor; + $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; } @@ -90,6 +97,10 @@ class CreateBookingLogic extends AbstractControllerLogic $this->bookingToPerfexCRMProcessor->execute($booking); } + //cief todo: case study 5 + // $user = $company->employees()->first(); + // $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_5]); + return $this->resourceResponse(new BookingResource($booking)); } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php index 199531f4..c429d91d 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php @@ -8,24 +8,20 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding; use App\Classes\Modules\Bookings\Services\FetchesBookingQuotation; use App\Classes\Modules\Companies\Services\FetchesCompanyPaymentAttemptLimit; -use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject; -use App\Classes\Modules\Vouchers\DataTransferObjects\VoucherObject; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; use App\Classes\Modules\Transactions\Services\CreatesTransaction; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -use App\Classes\Modules\Vouchers\Services\FetchesVoucher; -use App\Classes\Modules\Vouchers\Services\CreatesVoucher; -use App\Classes\Modules\Vouchers\Services\CreatesVoucherRedemption; -use App\Classes\Modules\Vouchers\Services\RedeemsVoucher; use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance; use App\Classes\ValueObjects\Constants\ApprovalStatus; 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\Transactions\Processors\CreateCashBackTransactionProcessor; +use App\Classes\Modules\Vouchers\Processors\Voucherify\BookingToVoucherifyProcessor; use App\Models\Booking; use App\Models\Transaction; @@ -78,17 +74,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic /** @var RecalculatesWalletBalance */ private $recalculatesWalletBalance; - /** @var FetchesVoucher */ - private $fetchesVoucher; + /** @var BookingToVoucherifyProcessor */ + private $bookingToVoucherifyProcessor; - /** @var CreatesVoucher */ - private $createsVoucher; - - /** @var CreatesVoucherRedemption */ - private $createsVoucherRedemption; - - /** @var RedeemsVoucher */ - private $redeemsVoucher; /** * CreateBookingPaymentLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -101,12 +89,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic * @param UpdatesTransactionStatus $updatesTransactionStatus * @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor * @param RecalculatesWalletBalance $recalculatesWalletBalance - * @param FetchesVoucher $fetchesVoucher - * @param CreatesVoucher $createsVoucher - * @param CreatesVoucherRedemption $createsVoucherRedemption - * @param RedeemVoucher $redeemVoucher + * @param 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, FetchesVoucher $fetchesVoucher, CreatesVoucher $createsVoucher, CreatesVoucherRedemption $createsVoucherRedemption, RedeemsVoucher $redeemsVoucher) + 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) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; @@ -118,10 +103,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $this->updatesTransactionStatus = $updatesTransactionStatus; $this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor; $this->recalculatesWalletBalance = $recalculatesWalletBalance; - $this->fetchesVoucher = $fetchesVoucher; - $this->createsVoucher = $createsVoucher; - $this->createsVoucherRedemption = $createsVoucherRedemption; - $this->redeemsVoucher = $redeemsVoucher; + $this->bookingToVoucherifyProcessor = $bookingToVoucherifyProcessor; } /** @@ -131,11 +113,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $voucherCode = $request->input('voucher_code'); //cief to, json_encode and json_decode ??? - // if($voucherReqInput){ - // $voucherObject = json_decode($voucherReqInput); - // $validatedVoucherObject = new ValidatedVoucherObject($voucherObject->metadata->name, $voucherObject->code, $voucherObject->discount->type, $voucherObject->discount->amount_off); - // } + $voucherCode = $request->input('voucher_code'); $booking = Booking::find($request->route('id')); @@ -189,34 +167,12 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $transaction = $this->createsTransaction->execute($booking, $object); // $cash_back_transaction = $this->createCashBackTransactionProcessor->execute($transaction); + $this->bookingToVoucherifyProcessor->execute($booking->company->employees()->first(), $transaction, $booking->company->id, $configurations->getSubTotal(), $configurations->getVoucherDiscountAmount(), $voucherCode); + if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET){ $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); } - //Voucherify - if($voucherCode){ - $employee = $booking->company->employees()->first(); - - $result = $this->redeemsVoucher->execute($voucherCode, $configurations->getSubTotal(), $employee); - $voucher = $result->voucher; - $redemptionId = $result->id; - //Update Database - $voucherValue = 0.00; - if(isset($voucher->discount->amount_off)){ - $voucherValue =$voucher->discount->amount_off; - } - if($voucherValue == 0.00){ - if(isset($voucher->discount->percent_off)){ - $voucherValue =$voucher->discount->percent_off; - } - } - - $voucherObject= new VoucherObject($voucher->code, isset($voucher->metadata->name) ? $voucher->metadata->name : "", $voucher->discount->type, $voucherValue); - $voucher = $this->createsVoucher->execute($voucherObject); - if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); - $this->createsVoucherRedemption->execute($transaction, $voucher, $redemptionId, $configurations->getVoucherDiscountAmount()); - } - return $this->resourceResponse(new TransactionResource($transaction)); } diff --git a/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php b/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php index c81f7bba..5fe85c35 100644 --- a/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php +++ b/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php @@ -8,8 +8,9 @@ use App\Classes\Modules\Bookings\DataTransferObjects\CalculationObject; use App\Classes\Modules\Companies\Services\FetchesCompanyServiceSettings; use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject; 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\ValidatesVoucher; +use App\Classes\Modules\Vouchers\Services\Voucherify\ValidatesVoucherifyVoucher; use App\Models\Company; use App\Models\Currency; @@ -22,19 +23,19 @@ class FetchesBookingQuotation /** @var FetchesCurrency */ private $fetchesCurrency; - /** @var ValidatesVoucher */ - private $validatesVoucher; + /** @var ValidatesVoucherifyVoucher */ + private $validatesVoucherifyVoucher; /** * FetchesBookingQuotation constructor. * @param FetchesCompanyServiceSettings $fetchesCompanyServiceSettings * @param FetchesCurrency $fetchesCurrency */ - public function __construct(FetchesCompanyServiceSettings $fetchesCompanyServiceSettings, FetchesCurrency $fetchesCurrency, ValidatesVoucher $validatesVoucher) + public function __construct(FetchesCompanyServiceSettings $fetchesCompanyServiceSettings, FetchesCurrency $fetchesCurrency, ValidatesVoucherifyVoucher $validatesVoucherifyVoucher) { $this->fetchesCompanyServiceSettings = $fetchesCompanyServiceSettings; $this->fetchesCurrency = $fetchesCurrency; - $this->validatesVoucher = $validatesVoucher; + $this->validatesVoucherifyVoucher = $validatesVoucherifyVoucher; } @@ -59,15 +60,15 @@ class FetchesBookingQuotation //Voucherify if($voucherCode){ $employee = $company->employees()->first(); - - $result = $this->validatesVoucher->execute($voucherCode, $calculationObject->getSubTotal(), $employee); + $validateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject($company->id, $voucherCode, $calculationObject->getSubTotal(), $employee); + $result = $this->validatesVoucherifyVoucher->execute($validateVoucherifyVoucherObject); $voucher = [ "code" => $result->code, - "discount" => $result->discount, + "discount" => property_exists($result, 'discount') ? $result->discount : null, "metadata" => $result->metadata, "order" => $result->order, ]; - $validatedVoucherObject = new ValidatedVoucherObject(isset($voucher['metadata']->name) ? $voucher['metadata']->name: "", $voucher['code'], $voucher['discount']->type, $voucher['order']->total_discount_amount, $voucher['order']->total_amount); + $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/Companies/ControllersLogic/AssignCompanyToSegmentLogic.php b/app/Classes/Modules/Companies/ControllersLogic/AssignCompanyToSegmentLogic.php index f814057f..7df8e2f0 100644 --- a/app/Classes/Modules/Companies/ControllersLogic/AssignCompanyToSegmentLogic.php +++ b/app/Classes/Modules/Companies/ControllersLogic/AssignCompanyToSegmentLogic.php @@ -7,8 +7,10 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Companies\Processors\AssignSegmentProcessor; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Segments\DataTransferObjects\SeasonalSegmentObject; +use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor; use App\Classes\Modules\Segments\Services\CreatesSeasonalSegment; use App\Http\Resources\CompanyResource; +use App\Classes\ValueObjects\Constants\Milestones; use App\Models\SeasonalSegment; use Carbon\Carbon; use Illuminate\Http\JsonResponse; @@ -36,17 +38,22 @@ class AssignCompanyToSegmentLogic extends AbstractControllerLogic /** @var CreatesSeasonalSegment */ private $createsSeasonalSegment; + /** @var CheckMilestonesForRewardProcessor */ + private $checkMilestonesForRewardProcessor; + /** * AssignCompanyToSegmentLogic constructor. * @param FetchesCompany $fetchesCompany * @param AssignSegmentProcessor $assignCompanyToSegmentProcessor * @param CreatesSeasonalSegment $createsSeasonalSegment + * @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor */ - public function __construct(FetchesCompany $fetchesCompany, AssignSegmentProcessor $assignCompanyToSegmentProcessor, CreatesSeasonalSegment $createsSeasonalSegment) + public function __construct(FetchesCompany $fetchesCompany, AssignSegmentProcessor $assignCompanyToSegmentProcessor, CreatesSeasonalSegment $createsSeasonalSegment, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor) { $this->fetchesCompany = $fetchesCompany; $this->assignCompanyToSegmentProcessor = $assignCompanyToSegmentProcessor; $this->createsSeasonalSegment = $createsSeasonalSegment; + $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; } /** @@ -75,12 +82,16 @@ class AssignCompanyToSegmentLogic extends AbstractControllerLogic // } $start_date = $request->input('starting_on') ? $request->input('starting_on') : Carbon::now(); - + $seasonalSegmentObject = new SeasonalSegmentObject($company->id, $request->input('segment_id'), $start_date, $request->input('ending_on') ?? null); $this->createsSeasonalSegment->execute($seasonalSegmentObject); - } - + } + + //cief todo: case study 3 + $user = $company->employees()->first(); + $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_3]); + return $this->resourceResponse(new CompanyResource($company)); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php b/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php index c08dc4ef..b59e77f6 100644 --- a/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php +++ b/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php @@ -10,9 +10,11 @@ use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; use App\Classes\Modules\Documents\Services\CreatesDocument; use App\Classes\Modules\Documents\Services\CreatesFiles; use App\Classes\Modules\PerfexCRM\Processors\NewLeadTaskToPerfexCRMProcessor; +use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\CompanyType; use App\Classes\ValueObjects\Constants\DocumentType; +use App\Classes\ValueObjects\Constants\Milestones; use App\Models\Company; use App\Models\Document; use Illuminate\Http\JsonResponse; @@ -46,6 +48,9 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic /** @var NewLeadTaskToPerfexCRMProcessor */ private $newLeadTaskToPerfexCRMProcessor; + /** @var CheckMilestonesForRewardProcessor */ + private $checkMilestonesForRewardProcessor; + /** * CreateIdentificationDocumentLogic constructor. * @param FetchesCompany $fetchesCompany @@ -53,14 +58,16 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic * @param CreatesFiles $createsFile * @param UpdatesCompanyStatus $updatesCompanyStatus * @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor + * @param CheckMilestoneForRewardProcessor $checkMilestonesForRewardProcessor */ - public function __construct(FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesCompanyStatus $updatesCompanyStatus, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor) + public function __construct(FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesCompanyStatus $updatesCompanyStatus, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor) { $this->fetchesCompany = $fetchesCompany; $this->createsDocument = $createsDocument; $this->createsFile = $createsFile; $this->updatesCompanyStatus = $updatesCompanyStatus; $this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor; + $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; } /** @@ -87,6 +94,10 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic $this->newLeadTaskToPerfexCRMProcessor->execute($company); } + //cief todo: case study 2 + $user = $company->employees()->first(); + $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_2]); + return $this->response([]); } diff --git a/app/Classes/Modules/Milestones/ControllersLogic/CreateMilestoneLogic.php b/app/Classes/Modules/Milestones/ControllersLogic/CreateMilestoneLogic.php new file mode 100644 index 00000000..db30f789 --- /dev/null +++ b/app/Classes/Modules/Milestones/ControllersLogic/CreateMilestoneLogic.php @@ -0,0 +1,70 @@ + 'Create Milestone', + 'message' => 'You have successfully created a milestone' + ]; + } + + /** @var FetchesReward */ + private $fetchesReward; + + /** @var CreateMilestoneProcessor */ + private $createMilestoneProcessor; + + /** @var AssignRewardProcessor */ + private $assignRewardProcessor; + + /** + * CreateMilestoneLogic constructor. + */ + public function __construct(CreateMilestoneProcessor $createMilestoneProcessor, FetchesReward $fetchesReward, AssignRewardProcessor $assignRewardProcessor) + { + $this->createMilestoneProcessor = $createMilestoneProcessor; + $this->fetchesReward = $fetchesReward; + $this->assignRewardProcessor = $assignRewardProcessor; + } + + /** + * @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 + { + $milestone = $this->createMilestoneProcessor->execute($request); + + //Extra checking to make sure that each reward exists + $rewardIds = $request->input('reward_ids'); + foreach ($rewardIds as $rewardId) { + /** @var Reward $reward */ + $this->fetchesReward->execute(['id' => $rewardId]); + } + + $object = new AchievementObject($milestone, $rewardIds); + $this->assignRewardProcessor->execute($object); + + return $this->resourceResponse(new MilestoneResource($milestone)); + } +} diff --git a/app/Classes/Modules/Milestones/ControllersLogic/DeleteMilestoneLogic.php b/app/Classes/Modules/Milestones/ControllersLogic/DeleteMilestoneLogic.php new file mode 100644 index 00000000..5a2fbef2 --- /dev/null +++ b/app/Classes/Modules/Milestones/ControllersLogic/DeleteMilestoneLogic.php @@ -0,0 +1,74 @@ + 'Delete Milestone', + 'message' => 'You have successfully deleted the Milestone' + ]; + } + + /** @var CanDeleteMilestone */ + private $canDeleteMilestone; + + /** @var DeletesMilestone */ + private $deletesMilestone; + + /** @var FetchesMilestone */ + private $fetchesMiestone; + + + /** + * DeleteMilestoneLogic constructor. + * @param CanDeleteMilestone $canDeleteMilestone + * @param DeletesMilestone $deletesMilestone + * @param FetchesMilestone $fetchesMiestone + */ + public function __construct( + CanDeleteMilestone $canDeleteMilestone, + DeletesMilestone $deletesMilestone, + FetchesMilestone $fetchesMiestone + ) + { + $this->canDeleteMilestone = $canDeleteMilestone; + $this->deletesMilestone = $deletesMilestone; + $this->fetchesMiestone = $fetchesMiestone; + } + + /** + * @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->fetchesMiestone->execute(['id' => $request->route('id')]); + $this->canDeleteMilestone->passes(); + $this->deletesMilestone->execute($query); + + return $this->resourceResponse(new MilestoneResource($query)); + } + +} diff --git a/app/Classes/Modules/Milestones/ControllersLogic/ListMilestoneProgressLogic.php b/app/Classes/Modules/Milestones/ControllersLogic/ListMilestoneProgressLogic.php new file mode 100644 index 00000000..55c78eb2 --- /dev/null +++ b/app/Classes/Modules/Milestones/ControllersLogic/ListMilestoneProgressLogic.php @@ -0,0 +1,50 @@ + 'Retrieved Milestone Progress', + 'message' => 'You have successfully retrieved a list of Milestone Progress' + ]; + } + + + /** @var ListsMilestoneProgress */ + private $listsMilestoneProgress; + + /** + * ListMilestoneProgressLogic constructor. + * @param ListsMilestoneProgress $listsMilestoneProgress + */ + public function __construct(ListsMilestoneProgress $listsMilestoneProgress) + { + $this->listsMilestoneProgress = $listsMilestoneProgress; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $query = $this->listsMilestoneProgress->execute($this->listsMilestoneProgress->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(MilestoneProgressResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Milestones/ControllersLogic/ListMilestonesLogic.php b/app/Classes/Modules/Milestones/ControllersLogic/ListMilestonesLogic.php new file mode 100644 index 00000000..202041e8 --- /dev/null +++ b/app/Classes/Modules/Milestones/ControllersLogic/ListMilestonesLogic.php @@ -0,0 +1,50 @@ + 'Retrieved Milestones', + 'message' => 'You have successfully retrieved a list of Milestones' + ]; + } + + + /** @var ListsMilestones */ + private $listsMilestones; + + /** + * ListMilestonesLogic constructor. + * @param ListsMilestones $listsMilestones + */ + public function __construct(ListsMilestones $listsMilestones) + { + $this->listsMilestones = $listsMilestones; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $query = $this->listsMilestones->execute($this->listsMilestones->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(MilestoneResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Milestones/ControllersLogic/UpdateMilestoneLogic.php b/app/Classes/Modules/Milestones/ControllersLogic/UpdateMilestoneLogic.php new file mode 100644 index 00000000..a7a0c655 --- /dev/null +++ b/app/Classes/Modules/Milestones/ControllersLogic/UpdateMilestoneLogic.php @@ -0,0 +1,73 @@ + 'Update Milestone', + 'message' => 'You have successfully updated a milestone' + ]; + } + + /** @var FetchesReward */ + private $fetchesReward; + + /** @var UpdateMilestoneProcessor */ + private $updateMilestoneProcessor; + + /** @var AssignRewardProcessor */ + private $assignRewardProcessor; + + /** + * UpdateMilestoneLogic constructor. + * @param UpdateMilestoneProcessor $updateMilestoneProcessor + * @param FetchesReward $fetchesReward + * @param AssignRewardProcessor $assignRewardProcessor + */ + public function __construct(UpdateMilestoneProcessor $updateMilestoneProcessor, FetchesReward $fetchesReward, AssignRewardProcessor $assignRewardProcessor) + { + $this->updateMilestoneProcessor = $updateMilestoneProcessor; + $this->fetchesReward = $fetchesReward; + $this->assignRewardProcessor = $assignRewardProcessor; + } + + /** + * @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 + { + $milestone = $this->updateMilestoneProcessor->execute($request); + + //Extra checking to make sure that each reward exists + $rewardIds = $request->input('reward_ids'); + foreach ($rewardIds as $rewardId) { + /** @var Reward $reward */ + $this->fetchesReward->execute(['id' => $rewardId]); + } + + $object = new AchievementObject($milestone, $rewardIds); + $this->assignRewardProcessor->execute($object); + + return $this->resourceResponse(new MilestoneResource($milestone)); + } +} diff --git a/app/Classes/Modules/Milestones/DataTransferObjects/AchievementObject.php b/app/Classes/Modules/Milestones/DataTransferObjects/AchievementObject.php new file mode 100644 index 00000000..c5eccfd4 --- /dev/null +++ b/app/Classes/Modules/Milestones/DataTransferObjects/AchievementObject.php @@ -0,0 +1,43 @@ +milestone = $milestone; + $this->rewardIds = $rewardIds; + } + + /** + * @return Milestone + */ + public function getMilestone(): Milestone + { + return $this->milestone; + } + + /** + * @return array + */ + public function getRewardIds(): array + { + return $this->rewardIds; + } + +} diff --git a/app/Classes/Modules/Milestones/DataTransferObjects/MilestoneObject.php b/app/Classes/Modules/Milestones/DataTransferObjects/MilestoneObject.php new file mode 100644 index 00000000..306a0502 --- /dev/null +++ b/app/Classes/Modules/Milestones/DataTransferObjects/MilestoneObject.php @@ -0,0 +1,55 @@ +id = $id; + $this->name = $name; + $this->description = $description; + } + + /** + * @return int + */ + public function getId(): int + { + return $this->id; + } + + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return string + */ + public function getDescription(): string + { + return $this->description; + } +} diff --git a/app/Classes/Modules/Milestones/Processors/AssignRewardProcessor.php b/app/Classes/Modules/Milestones/Processors/AssignRewardProcessor.php new file mode 100644 index 00000000..a76166d5 --- /dev/null +++ b/app/Classes/Modules/Milestones/Processors/AssignRewardProcessor.php @@ -0,0 +1,44 @@ +canAssignReward = $canAssignReward; + $this->assignsReward = $assignsReward; + } + + /** + * @param AchievementObject $object + * @return Model + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function execute(AchievementObject $object): Model { + + $this->canAssignReward->passes($object); + + return $this->assignsReward->execute($object); + } + +} diff --git a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php new file mode 100644 index 00000000..597fa8bc --- /dev/null +++ b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php @@ -0,0 +1,170 @@ +createsVoucherifyVoucher = $createsVoucherifyVoucher; + $this->createsVoucher = $createsVoucher; + $this->fetchesMilestone = $fetchesMilestone; + $this->createsMilestoneProgress = $createsMilestoneProgress; + $this->createsUserReward = $createsUserReward; + $this->fetchesVoucherifyVoucher = $fetchesVoucherifyVoucher; + $this->fetchesVoucher = $fetchesVoucher; + $this->validatesVoucherifyVoucher = $validatesVoucherifyVoucher; + } + + + /** + * @param User $user + * @param array $milestone_constants + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \Voucherify\ClientException + */ + public function execute(User $user, array $milestone_constants) + { + try{ + foreach($milestone_constants as $constant) + { + //update milestone progress + /** @var Milestone $milestone */ + $milestone = $this->fetchesMilestone->execute(['name' => $constant]); + $result = null; + if($user->milestoneProgress->count() > 0){ + $result = $user->milestoneProgress->where('milestone_id', $milestone->id)->first(); + } + + if(!$result){ + $result = $this->createsMilestoneProgress->execute($milestone, $user->id); + } + + if($result){ + //fetch completed miletones + $completedMilestones = MilestoneProgress::where('user_id', $user->id)->pluck('milestone_id'); + $rewards = $milestone->rewards; + + //check for rewards that have a corresponding milestone count + if(count($rewards) > 0){ + $this->checkMilestoneForReward($user, $completedMilestones, $rewards); + } + } + } + } catch (\Exception $e) { + Log::error($e); + } + } + + /** + * @param User $user + * @param object $completedMilestones + * @param object $rewards + * @return void + */ + private function checkMilestoneForReward(User $user, object $completedMilestones, object $rewards) + { + $milestoneIds = $rewards[0]->milestones->pluck('id'); + if ($milestoneIds->intersect($completedMilestones)->count() >= count($rewards[0]->milestones)) { + /** @var Reward $reward */ + foreach ($rewards as $reward) { + $result = null; + if (!$user->rewards->contains('reward_id', $reward->id)) { + $voucherId = 0; + $voucherName = ''; + $voucherType = ""; + if($reward->type == RewardType::REWARD_AMOUNT){ + //Voucherify - Create Voucher + $result = $this->createsVoucherifyVoucher->execute($user, intval($reward->value)); + } + else{ + //Voucherify - Validates Voucher + $ValidateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject(0, $reward->value, 0.00, $user); + $voucherifyVoucherValidated = $this->validatesVoucherifyVoucher->execute($ValidateVoucherifyVoucherObject); + + if(!isset($voucherifyVoucherValidated->reason)){ + //Voucherify - Get Voucher + $result = $this->fetchesVoucherifyVoucher->execute($user, $reward->value); + } + } + + if($result && !isset($result->reason)){ + $voucherName = isset($result->campaign) ? $result->campaign : $reward->name; + $voucherType = $result->discount->type; + $voucherValue = isset($result->discount->amount_off) ? $result->discount->amount_off : $result->discount->percent_off; + $voucherStartDate = $result->start_date; + $voucherEndDate = $result->expiration_date; + + //create voucher + $voucherObject = new VoucherObject($result->code, isset($voucherName) ? $voucherName : "", $voucherType, $voucherValue, $voucherStartDate, $voucherEndDate); + $voucher = $this->createsVoucher->execute($voucherObject); + if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); + $voucherId = $voucher->id; + + //create reward to user (user_reward) + $voucherCount = $user->rewards->where('voucher_id', $voucher->id)->count(); + if($voucherCount == 0){ + $this->createsUserReward->execute($reward, $user, $voucherId); + } + } + else{ + Log::info('CheckMilestonesForRewardProcessor: no voucher fetched or created for reward '. json_encode($reward)); + } + } + } + } + } +} diff --git a/app/Classes/Modules/Milestones/Processors/CreateMilestoneProcessor.php b/app/Classes/Modules/Milestones/Processors/CreateMilestoneProcessor.php new file mode 100644 index 00000000..3c562d8d --- /dev/null +++ b/app/Classes/Modules/Milestones/Processors/CreateMilestoneProcessor.php @@ -0,0 +1,51 @@ +canCreateMilestone = $canCreateMilestone; + $this->createsMilestone = $createsMilestone; + } + + + /** + * @param Request $request + * @return Model + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function execute(Request $request): Model + { + $userMilestoneObject = new MilestoneObject( + $request->input('id'), + $request->input('name'), + $request->input('description') + ); + + $this->canCreateMilestone->passes($userMilestoneObject); + + return $this->createsMilestone->execute($userMilestoneObject); + } + +} diff --git a/app/Classes/Modules/Milestones/Processors/UpdateMilestoneProcessor.php b/app/Classes/Modules/Milestones/Processors/UpdateMilestoneProcessor.php new file mode 100644 index 00000000..b1fdbc14 --- /dev/null +++ b/app/Classes/Modules/Milestones/Processors/UpdateMilestoneProcessor.php @@ -0,0 +1,59 @@ +canUpdateMilestone = $canUpdateMilestone; + $this->updatesMilestone = $updatesMilestone; + $this->fetchesMilestone = $fetchesMilestone; + } + + + /** + * @param Request $request + * @return Model + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function execute(Request $request): Model + { + $milestoneObject = new MilestoneObject( + $request->input('id'), + $request->input('name'), + $request->input('description') + ); + + $this->canUpdateMilestone->passes($milestoneObject); + + $milestone = $this->fetchesMilestone->execute(['id' => $request->route('id')]); + + return $this->updatesMilestone->execute($milestone, $milestoneObject); + } + +} diff --git a/app/Classes/Modules/Milestones/Services/AssignsReward.php b/app/Classes/Modules/Milestones/Services/AssignsReward.php new file mode 100644 index 00000000..4d50a89e --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/AssignsReward.php @@ -0,0 +1,29 @@ +getMilestone()->rewards()->attach($object->getReward()->id); + $object->getMilestone()->rewards()->sync($object->getRewardIds()); + + return $object->getMilestone(); + + } catch (QueryException $exception){ + throw new MalformedRequestException($exception); + } + } +} diff --git a/app/Classes/Modules/Milestones/Services/CheckIfMilestoneProgressExists.php b/app/Classes/Modules/Milestones/Services/CheckIfMilestoneProgressExists.php new file mode 100644 index 00000000..f6b73820 --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/CheckIfMilestoneProgressExists.php @@ -0,0 +1,27 @@ +repository = $repository; + } + + public function execute(int $user_id, int $milestone_id): bool { + return $this->repository->where('user_id', $user_id)->where('milestone_id', $milestone_id)->exists(); + } + +} diff --git a/app/Classes/Modules/Milestones/Services/CreatesMilestone.php b/app/Classes/Modules/Milestones/Services/CreatesMilestone.php new file mode 100644 index 00000000..9ec9e2d1 --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/CreatesMilestone.php @@ -0,0 +1,25 @@ +name = $object->getName(); + $model->description = $object->getDescription(); + + return $this->handler($model); + } +} diff --git a/app/Classes/Modules/Milestones/Services/CreatesMilestoneProgress.php b/app/Classes/Modules/Milestones/Services/CreatesMilestoneProgress.php new file mode 100644 index 00000000..bd04c624 --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/CreatesMilestoneProgress.php @@ -0,0 +1,40 @@ +isMilestoneProgressExists = $isMilestoneProgressExists; + } + + + /** + * @param Milestone $milestone + * @param string $userId + * @return \Illuminate\Database\Eloquent\Model|null + */ + public function execute(Milestone $milestone, string $userId) { + if(!$this->isMilestoneProgressExists->execute($userId, $milestone->id)) + { + $model = new MilestoneProgress(); + $model->user_id = $userId; + + return $this->handler($milestone->progress(), $model); + } + + return null; + } +} diff --git a/app/Classes/Modules/Milestones/Services/DeletesMilestone.php b/app/Classes/Modules/Milestones/Services/DeletesMilestone.php new file mode 100644 index 00000000..f829d8e1 --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/DeletesMilestone.php @@ -0,0 +1,19 @@ +handler($model); + } +} diff --git a/app/Classes/Modules/Milestones/Services/FetchesMilestone.php b/app/Classes/Modules/Milestones/Services/FetchesMilestone.php new file mode 100644 index 00000000..e0c12881 --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/FetchesMilestone.php @@ -0,0 +1,34 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Milestones/Services/ListsMilestoneProgress.php b/app/Classes/Modules/Milestones/Services/ListsMilestoneProgress.php new file mode 100644 index 00000000..2cdf6de2 --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/ListsMilestoneProgress.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Milestones/Services/ListsMilestones.php b/app/Classes/Modules/Milestones/Services/ListsMilestones.php new file mode 100644 index 00000000..dae7c076 --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/ListsMilestones.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Milestones/Services/UpdatesMilestone.php b/app/Classes/Modules/Milestones/Services/UpdatesMilestone.php new file mode 100644 index 00000000..fbe463aa --- /dev/null +++ b/app/Classes/Modules/Milestones/Services/UpdatesMilestone.php @@ -0,0 +1,24 @@ +name = $object->getName(); + $model->description = $object->getDescription(); + + return $this->handler($model); + } +} diff --git a/app/Classes/Modules/Milestones/Standards/Rules/CanAssignReward.php b/app/Classes/Modules/Milestones/Standards/Rules/CanAssignReward.php new file mode 100644 index 00000000..35e8b31d --- /dev/null +++ b/app/Classes/Modules/Milestones/Standards/Rules/CanAssignReward.php @@ -0,0 +1,57 @@ +milestoneRewardValidation = $milestoneRewardValidation; + } + + /** + * @return bool + */ + protected function authorized(): bool + { + if (!Auth::user()->can('edit milestone')) { + return false; + } + return true; + } + + /** + * @param AchievementObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return $this->milestoneRewardValidation->validate($object); + } + + /** + * @param AchievementObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Milestones/Standards/Rules/CanCreateMilestone.php b/app/Classes/Modules/Milestones/Standards/Rules/CanCreateMilestone.php new file mode 100644 index 00000000..be25b64f --- /dev/null +++ b/app/Classes/Modules/Milestones/Standards/Rules/CanCreateMilestone.php @@ -0,0 +1,54 @@ +milestoneValidation = $milestoneValidation; + } + + /** + * @return bool + */ + protected function authorized(): bool + { + if (!Auth::user()->can('add milestone')) { + return false; + } + return true; + } + + /** + * @param MilestoneObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return $this->milestoneValidation->validate($object, 'POST'); + } + + /** + * @param MilestoneObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } +} diff --git a/app/Classes/Modules/Milestones/Standards/Rules/CanDeleteMilestone.php b/app/Classes/Modules/Milestones/Standards/Rules/CanDeleteMilestone.php new file mode 100644 index 00000000..c0c7fde7 --- /dev/null +++ b/app/Classes/Modules/Milestones/Standards/Rules/CanDeleteMilestone.php @@ -0,0 +1,44 @@ +can('delete milestone')) { + return false; + } + + return true; + + } + + /** + * @param MilestoneObject $object + * @return bool + */ + protected function validators($object): bool + { + return true; + + } + + + /** + * @param MilestoneObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Milestones/Standards/Rules/CanUpdateMilestone.php b/app/Classes/Modules/Milestones/Standards/Rules/CanUpdateMilestone.php new file mode 100644 index 00000000..9f7db714 --- /dev/null +++ b/app/Classes/Modules/Milestones/Standards/Rules/CanUpdateMilestone.php @@ -0,0 +1,54 @@ +milestoneValidation = $milestoneValidation; + } + + /** + * @return bool + */ + protected function authorized(): bool + { + if (!Auth::user()->can('edit milestone')) { + return false; + } + return true; + } + + /** + * @param MilestoneObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return $this->milestoneValidation->validate($object, 'PUT'); + } + + /** + * @param MilestoneObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } +} diff --git a/app/Classes/Modules/Milestones/Standards/Validators/MilestoneRewardValidation.php b/app/Classes/Modules/Milestones/Standards/Validators/MilestoneRewardValidation.php new file mode 100644 index 00000000..a282b010 --- /dev/null +++ b/app/Classes/Modules/Milestones/Standards/Validators/MilestoneRewardValidation.php @@ -0,0 +1,40 @@ + $object->getMilestone()->id, + 'reward_ids' => $object->getRewardIds() + ]; + } + + /** + * @return array + */ + protected function rules(): array + { + return [ + 'milestone_id' => 'required', + 'reward_ids' => 'required', + ]; + } + + /** + * @return array + */ + protected function messages(): array + { + return []; + } +} diff --git a/app/Classes/Modules/Milestones/Standards/Validators/MilestoneValidation.php b/app/Classes/Modules/Milestones/Standards/Validators/MilestoneValidation.php new file mode 100644 index 00000000..81ffbced --- /dev/null +++ b/app/Classes/Modules/Milestones/Standards/Validators/MilestoneValidation.php @@ -0,0 +1,68 @@ + $object->getName(), + 'description' => $object->getDescription(), + ]; + + return $data; + } + + /** + * @param null|string $type + * @return array + */ + protected function rules(?string $type = 'POST'): array { + if ($type == 'POST') { //crete + return [ + 'name' => [ + 'required', + function ($attribute, $value, $fail) { + // Check if milestone name already exists in the database + $existingMilestone = Milestone::where('name', $value)->first(); + if ($existingMilestone) { + $fail("The {$attribute} milestone name already exists in the database."); + } + }, + ], + 'description' => [ + 'required', + ] + ]; + + } + elseif($type == 'PUT') { //update + return [ + 'name' => [ + 'required', + ], + 'description' => [ + 'required', + ] + ]; + } + } + + /** + * @return array + */ + protected function messages(): array { + return []; + } + +} diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php index acdf1a89..78b61bd6 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php @@ -39,8 +39,7 @@ class FetchesPerfexCRMTask return (object) $data; }else{ - // Log::error($response); - Helper::debugLoggerForPerfexCRM($response); + Helper::debugLogger($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 27ff3165..6d91c081 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php @@ -38,8 +38,7 @@ class UpdatesPerfexCRMCustomer $data = $response->json(); return (object) $data; }else{ - // Log::error($response); - Helper::debugLoggerForPerfexCRM($response); + Helper::debugLogger($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/Rewards/ControllersLogic/CreateRewardLogic.php b/app/Classes/Modules/Rewards/ControllersLogic/CreateRewardLogic.php new file mode 100644 index 00000000..dc6fecf2 --- /dev/null +++ b/app/Classes/Modules/Rewards/ControllersLogic/CreateRewardLogic.php @@ -0,0 +1,67 @@ + 'Create/Update Reward', + 'message' => 'You have successfully created/updated a reward' + ]; + } + + /** @var CreatesReward */ + private $createsReward; + + /** @var CanCreateReward */ + private $canCreateReward; + + /** + * CreateRewardLogic constructor. + */ + public function __construct(CreatesReward $createsMilestone, CanCreateReward $canCreateReward) + { + $this->createsReward = $createsMilestone; + $this->canCreateReward = $canCreateReward; + } + + /** + * @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 + { + $userRewardObject = new RewardObject( + $request->input('id'), + $request->input('name'), + $request->input('description'), + $request->input('value'), + $request->input('type'), + $request->input('is_active'), + $request->input('order'), + ); + + $this->canCreateReward->passes($userRewardObject); + + $result = $this->createsReward->execute($userRewardObject); + + return $this->response(['data' => $result]); + } + + +} diff --git a/app/Classes/Modules/Rewards/ControllersLogic/DeleteRewardLogic.php b/app/Classes/Modules/Rewards/ControllersLogic/DeleteRewardLogic.php new file mode 100644 index 00000000..6b2c306c --- /dev/null +++ b/app/Classes/Modules/Rewards/ControllersLogic/DeleteRewardLogic.php @@ -0,0 +1,74 @@ + 'Delete Reward', + 'message' => 'You have successfully deleted the Reward' + ]; + } + + /** @var CanDeleteReward */ + private $canDeleteReward; + + /** @var DeletesReward */ + private $deletesReward; + + /** @var FetchesReward */ + private $fetchesReward; + + + /** + * DeleteRewardLogic constructor. + * @param CanDeleteReward $canDeleteReward + * @param DeletesReward $deletesReward + * @param FetchesReward $fetchesReward + */ + public function __construct( + CanDeleteReward $canDeleteReward, + DeletesReward $deletesReward, + FetchesReward $fetchesReward + ) + { + $this->canDeleteReward = $canDeleteReward; + $this->deletesReward = $deletesReward; + $this->fetchesReward = $fetchesReward; + } + + /** + * @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->fetchesReward->execute(['id' => $request->route('id')]); + $this->canDeleteReward->passes(); + $this->deletesReward->execute($query); + + return $this->resourceResponse(new RewardResource($query)); + } + +} diff --git a/app/Classes/Modules/Rewards/ControllersLogic/ListRewardsDetailsLogic.php b/app/Classes/Modules/Rewards/ControllersLogic/ListRewardsDetailsLogic.php new file mode 100644 index 00000000..0f3cfda8 --- /dev/null +++ b/app/Classes/Modules/Rewards/ControllersLogic/ListRewardsDetailsLogic.php @@ -0,0 +1,49 @@ + 'Retrieved Rewards Details', + 'message' => 'You have successfully retrieved a list of Rewards Details' + ]; + } + + /** @var ListsRewards */ + private $listsRewards; + + /** + * ListRewardsDetailsLogic constructor. + * @param ListsRewards $listsRewards + */ + public function __construct(ListsRewards $listsRewards) + { + $this->listsRewards = $listsRewards; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $query = $this->listsRewards->execute($this->listsRewards->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(RewardDetailsResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Rewards/ControllersLogic/ListRewardsLogic.php b/app/Classes/Modules/Rewards/ControllersLogic/ListRewardsLogic.php new file mode 100644 index 00000000..593947e6 --- /dev/null +++ b/app/Classes/Modules/Rewards/ControllersLogic/ListRewardsLogic.php @@ -0,0 +1,50 @@ + 'Retrieved Rewards', + 'message' => 'You have successfully retrieved a list of Rewards' + ]; + } + + + /** @var ListsRewards */ + private $listsRewards; + + /** + * ListRewardsLogic constructor. + * @param ListsRewards $listsRewards + */ + public function __construct(ListsRewards $listsRewards) + { + $this->listsRewards = $listsRewards; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $query = $this->listsRewards->execute($this->listsRewards->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(RewardResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Rewards/DataTransferObjects/RewardObject.php b/app/Classes/Modules/Rewards/DataTransferObjects/RewardObject.php new file mode 100644 index 00000000..45092222 --- /dev/null +++ b/app/Classes/Modules/Rewards/DataTransferObjects/RewardObject.php @@ -0,0 +1,106 @@ +id = $id; + $this->name = $name; + $this->description = $description; + $this->value = $value; + $this->type = $type; + $this->isActive = $isActive; + $this->order = $order; + } + + /** + * @return int + */ + public function getId(): int + { + return $this->id; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return string + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * @return string + */ + public function getValue(): string + { + return $this->value; + } + + /** + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * @return bool + */ + public function getIsActive(): bool + { + return $this->isActive; + } + + /** + * @return int + */ + public function getOrder(): int + { + return $this->order ?? 9999; + } +} diff --git a/app/Classes/Modules/Rewards/Services/CreatesReward.php b/app/Classes/Modules/Rewards/Services/CreatesReward.php new file mode 100644 index 00000000..c9a16fdc --- /dev/null +++ b/app/Classes/Modules/Rewards/Services/CreatesReward.php @@ -0,0 +1,45 @@ +name = $object->getName(); + // $model->description = $object->getDescription(); + // $model->value = $object->getValue(); + // $model->type = $object->getType(); + // $model->is_active = $object->getIsActive(); + // return $this->handler($model); + + try{ + $data = [ + 'id' => $object->getId(), + 'name' => $object->getName(), + 'description' => $object->getDescription(), + 'value' => $object->getValue(), + 'type' => $object->getType(), + 'is_active' => $object->getIsActive(), + 'order' => $object->getOrder(), + ]; + + return Reward::upsert([$data], ['id'], ['name', 'description', 'value', 'type', 'is_active', 'order']); + + } catch (QueryException $exception){ + throw new MalformedRequestException($exception); + } + } +} diff --git a/app/Classes/Modules/Rewards/Services/CreatesUserReward.php b/app/Classes/Modules/Rewards/Services/CreatesUserReward.php new file mode 100644 index 00000000..8a7f5d29 --- /dev/null +++ b/app/Classes/Modules/Rewards/Services/CreatesUserReward.php @@ -0,0 +1,32 @@ +user_id = $user->id; + $model->voucher_id = $voucherId; + return $this->handler($reward->users(), $model); + } + else{ + $model = new UserReward(); + $model->voucher_id = $voucherId; + return $this->handler($user->rewards(), $model); + } + } +} diff --git a/app/Classes/Modules/Rewards/Services/DeletesReward.php b/app/Classes/Modules/Rewards/Services/DeletesReward.php new file mode 100644 index 00000000..5d3d9133 --- /dev/null +++ b/app/Classes/Modules/Rewards/Services/DeletesReward.php @@ -0,0 +1,19 @@ +handler($model); + } +} diff --git a/app/Classes/Modules/Rewards/Services/FetchesReward.php b/app/Classes/Modules/Rewards/Services/FetchesReward.php new file mode 100644 index 00000000..ab336092 --- /dev/null +++ b/app/Classes/Modules/Rewards/Services/FetchesReward.php @@ -0,0 +1,34 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Rewards/Services/ListsRewards.php b/app/Classes/Modules/Rewards/Services/ListsRewards.php new file mode 100644 index 00000000..79d0d1d4 --- /dev/null +++ b/app/Classes/Modules/Rewards/Services/ListsRewards.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Rewards/Services/ListsUserRewards.php b/app/Classes/Modules/Rewards/Services/ListsUserRewards.php new file mode 100644 index 00000000..d81761cd --- /dev/null +++ b/app/Classes/Modules/Rewards/Services/ListsUserRewards.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Rewards/Standards/Rules/CanCreateReward.php b/app/Classes/Modules/Rewards/Standards/Rules/CanCreateReward.php new file mode 100644 index 00000000..5249b35c --- /dev/null +++ b/app/Classes/Modules/Rewards/Standards/Rules/CanCreateReward.php @@ -0,0 +1,55 @@ +rewardValidation = $rewardValidation; + } + + /** + * @return bool + */ + protected function authorized(): bool + { + if (!Auth::user()->can('add reward')) { + return false; + } + + return true; + } + + /** + * @param RewardObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return true; // $this->rewardValidation->validate($object, 'POST'); + } + + /** + * @param RewardObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } +} diff --git a/app/Classes/Modules/Rewards/Standards/Rules/CanDeleteReward.php b/app/Classes/Modules/Rewards/Standards/Rules/CanDeleteReward.php new file mode 100644 index 00000000..888b0d1e --- /dev/null +++ b/app/Classes/Modules/Rewards/Standards/Rules/CanDeleteReward.php @@ -0,0 +1,44 @@ +can('delete reward')) { + return false; + } + + return true; + + } + + /** + * @param RewardObject $object + * @return bool + */ + protected function validators($object): bool + { + return true; + + } + + + /** + * @param RewardObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Rewards/Standards/Validators/RewardValidation.php b/app/Classes/Modules/Rewards/Standards/Validators/RewardValidation.php new file mode 100644 index 00000000..18d875dc --- /dev/null +++ b/app/Classes/Modules/Rewards/Standards/Validators/RewardValidation.php @@ -0,0 +1,55 @@ + $object->getName(), + 'description' => $object->getDescription(), + ]; + + return $data; + } + + /** + * @param null|string $type + * @return array + */ + protected function rules(): array { + return [ + 'name' => [ + 'required', + function ($attribute, $value, $fail) { + // Check if reward name already exists in the database + $existingMilestone = Reward::where('name', $value)->first(); + if ($existingMilestone) { + $fail("The {$attribute} reward name already exists in the database."); + } + }, + ], + 'description' => [ + 'required', + ] + ]; + } + + /** + * @return array + */ + protected function messages(): array { + return []; + } + +} diff --git a/app/Classes/Modules/Transactions/Services/UpdatesTransactionStatus.php b/app/Classes/Modules/Transactions/Services/UpdatesTransactionStatus.php index 9d6b9fe4..d92e3e9a 100644 --- a/app/Classes/Modules/Transactions/Services/UpdatesTransactionStatus.php +++ b/app/Classes/Modules/Transactions/Services/UpdatesTransactionStatus.php @@ -5,19 +5,27 @@ namespace App\Classes\Modules\Transactions\Services; use App\Classes\General\Eloquent\AbstractUpdateRecord; use App\Classes\Modules\PerfexCRM\Processors\TransactionToPerfexCRMProcessorV2; use App\Models\Transaction; -use App\Classes\Modules\PerfexCRM\Processors\TransactionToPerfexCRMProcessor; +use App\Classes\Modules\Vouchers\Processors\Voucherify\TransactionToVoucherifyProcessor; +use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\ValueObjects\Constants\TransactionType; class UpdatesTransactionStatus extends AbstractUpdateRecord { /** @var TransactionToPerfexCRMProcessorV2 */ private $transactionToPerfexCRMProcessor; + /** @var TransactionToVoucherifyProcessor */ + private $transactionToVoucherifyProcessor; + /** + * UpdatesTransactionStatus constructor. * @param TransactionToPerfexCRMProcessorV2 $transactionToPerfexCRMProcessor + * @param TransactionToVoucherifyProcessor $transactionToVoucherifyProcessor */ - public function __construct(TransactionToPerfexCRMProcessorV2 $transactionToPerfexCRMProcessor) + public function __construct(TransactionToPerfexCRMProcessorV2 $transactionToPerfexCRMProcessor, TransactionToVoucherifyProcessor $transactionToVoucherifyProcessor) { $this->transactionToPerfexCRMProcessor = $transactionToPerfexCRMProcessor; + $this->transactionToVoucherifyProcessor = $transactionToVoucherifyProcessor; } @@ -35,6 +43,11 @@ class UpdatesTransactionStatus extends AbstractUpdateRecord if(config('perfexcrm.is_enabled') == 'true'){ $this->transactionToPerfexCRMProcessor->execute($transaction, $status); } + + if($status == ApprovalStatus::APPROVED && ($transaction->type == TransactionType::PAYMENT || $transaction->type == TransactionType::TOP_UP)){ + $this->transactionToVoucherifyProcessor->execute($transaction, "PAID"); + } + return $result; } } diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php new file mode 100644 index 00000000..a5d65544 --- /dev/null +++ b/app/Classes/Modules/Vouchers/ControllersLogic/CreateVoucherLogic.php @@ -0,0 +1,49 @@ + 'Create Voucher', + 'message' => 'You have successfully created a voucher' + ]; + } + + /** @var CreateVoucherProcessor */ + private $createVoucherProcessor; + + /** + * CreateVoucherLogic constructor. + * @param CreateVoucherProcessor $createVoucherProcessor + */ + public function __construct(CreateVoucherProcessor $createVoucherProcessor) + { + $this->createVoucherProcessor = $createVoucherProcessor; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $user = User::where('id', $request->input('userId'))->first(); + $result = $this->createVoucherProcessor->execute($user, $request->input('voucherCode'), null); + return $this->response(['data' => $result]); + } +} diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php new file mode 100644 index 00000000..16356f0f --- /dev/null +++ b/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php @@ -0,0 +1,46 @@ +listsUserRewards = $listsUserRewards; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Retrieved User Vouchers', + 'message' => 'You have successfully retrieved a list of user vouchers' + ]; + } + + /** @var ListsUserRewards */ + private $listsUserRewards; + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $query = $this->listsUserRewards->execute($this->listsUserRewards->deserializeFilters($request->input('filters'))); + return $this->collectionResponse(UserRewardResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/RedeemVoucherLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/RedeemVoucherLogic.php deleted file mode 100644 index 58980b64..00000000 --- a/app/Classes/Modules/Vouchers/ControllersLogic/RedeemVoucherLogic.php +++ /dev/null @@ -1,48 +0,0 @@ - 'Redeem Voucher', - 'message' => 'You have successfully redeemed a voucher' - ]; - } - - /** @var RedeemsVoucher */ - private $redeemsVoucher; - - /** - * RedeemVoucherLogic constructor. - */ - public function __construct(RedeemsVoucher $redeemVoucher) - { - $this->redeemsVoucher = $redeemVoucher; - } - - /** - * @param Request $request - * @return JsonResponse - * @throws MalformedRequestException - */ - public function logic(Request $request) : JsonResponse - { - $result = $this->redeemsVoucher->execute($request->input('promoCode'), $request->input('amount')); - return $this->response(['data' => $result]); - } - - -} diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php index b3e1ff7d..4b820eb1 100644 --- a/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php +++ b/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php @@ -5,10 +5,11 @@ namespace App\Classes\Modules\Vouchers\ControllersLogic; use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Vouchers\Services\ValidatesVoucher; +use App\Classes\Modules\Vouchers\Services\Voucherify\ValidatesVoucherifyVoucher; +use App\Classes\Modules\Vouchers\DataTransferObjects\ValidateVoucherifyVoucherObject; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use ErrorException; +use App\Models\Booking; class ValidateVoucherLogic extends AbstractControllerLogic { @@ -22,15 +23,16 @@ class ValidateVoucherLogic extends AbstractControllerLogic ]; } - /** @var ValidatesVoucher */ - private $validatesVoucher; + /** @var ValidatesVoucherifyVoucher */ + private $validatesVoucherifyVoucher; /** * ValidateVoucherLogic constructor. + * @param ValidatesVoucherifyVoucher $validatesVoucherifyVoucher */ - public function __construct(ValidatesVoucher $validatesVoucher) + public function __construct(ValidatesVoucherifyVoucher $validatesVoucherifyVoucher) { - $this->validatesVoucher = $validatesVoucher; + $this->validatesVoucherifyVoucher = $validatesVoucherifyVoucher; } /** @@ -40,9 +42,12 @@ class ValidateVoucherLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $result = $this->validatesVoucher->execute($request->input('voucherCode'), null, null); + $booking = Booking::find($request->input('itemId')); + $employee = $booking->company->employees()->first(); + + $validateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject($booking->company_id, $request->input('voucherCode'), $request->input('amount'), $employee); + $result = $this->validatesVoucherifyVoucher->execute($validateVoucherifyVoucherObject); return $this->response(['data' => $result]); } - } diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyCustomerObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyCustomerObject.php new file mode 100644 index 00000000..b92f0e05 --- /dev/null +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyCustomerObject.php @@ -0,0 +1,71 @@ +companyId = $companyId; + $this->user = $user; + $this->isNew = $isNew; + $this->acquisitionChannel = $acquisitionChannel; + } + + /** + * @return int + */ + public function getCompanyId(): int + { + return $this->companyId; + } + + + /** + * @return User + */ + public function getUser(): User + { + return $this->user; + } + + + /** + * @return bool + */ + public function getIsNew(): bool + { + return $this->isNew; + } + + /** + * @return string + */ + public function getAcquisitionChannel(): string + { + return $this->acquisitionChannel; + } + +} diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyOrderObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyOrderObject.php new file mode 100644 index 00000000..e1fa189a --- /dev/null +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/CreateVoucherifyOrderObject.php @@ -0,0 +1,82 @@ +employee = $employee; + $this->companyId = $companyId; + $this->amount = $amount; + $this->isNoVoucher = $isNoVoucher; + $this->isTopUpWallet = $isTopUpWallet; + } + + /** + * @return int + */ + public function getCompanyId(): string + { + return $this->companyId; + } + + /** + * @return float + */ + public function getAmount(): float + { + return $this->amount; + } + + /** + * @return User + */ + public function getEmployee(): User + { + return $this->employee; + } + + /** + * @return bool + */ + public function getIsNoVoucher(): bool + { + return $this->isNoVoucher; + } + + /** + * @return bool + */ + public function getIsTopUpWallet(): bool + { + return $this->isTopUpWallet; + } +} diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/RedeemVoucherifyVoucherObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/RedeemVoucherifyVoucherObject.php new file mode 100644 index 00000000..01f5431c --- /dev/null +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/RedeemVoucherifyVoucherObject.php @@ -0,0 +1,69 @@ +companyId = $companyId; + $this->promoCode = $promoCode; + $this->amount = $amount; + $this->employee = $employee; + } + + /** + * @return int + */ + public function getCompanyId(): int + { + return $this->companyId; + } + + + /** + * @return string + */ + public function getPromoCode(): string + { + return $this->promoCode; + } + + /** + * @return string + */ + public function getAmount(): string + { + return $this->amount; + } + + /** + * @return object + */ + public function getEmployee(): object + { + return $this->employee; + } + +} diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/UpdateVoucherifyOrderObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/UpdateVoucherifyOrderObject.php new file mode 100644 index 00000000..bc49ee86 --- /dev/null +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/UpdateVoucherifyOrderObject.php @@ -0,0 +1,42 @@ +id = $id; + $this->status = $status; + } + + /** + * @return string + */ + public function getId(): string + { + return $this->id; + } + + /** + * @return string + */ + public function getStatus(): string + { + return $this->status; + } +} diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/ValidateVoucherifyVoucherObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/ValidateVoucherifyVoucherObject.php new file mode 100644 index 00000000..b48bee16 --- /dev/null +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/ValidateVoucherifyVoucherObject.php @@ -0,0 +1,70 @@ +companyId = $companyId; + $this->voucherCode = $voucherCode; + $this->amount = $amount; + $this->user = $user; + } + + /** + * @return int + */ + public function getCompanyId(): int + { + return $this->companyId; + } + + /** + * @return string + */ + public function getVoucherCode(): string + { + return $this->voucherCode; + } + + /** + * @return float + */ + public function getAmount(): float + { + return $this->amount; + } + + /** + * @return User + */ + public function getUser(): User + { + return $this->user; + } + +} diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherEntityObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherEntityObject.php new file mode 100644 index 00000000..692b221b --- /dev/null +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherEntityObject.php @@ -0,0 +1,41 @@ +id = $id; + $this->type = $type; + } + + /** + * @return string + */ + public function getId(): string + { + return $this->id; + } + + /** + * @return string + */ + public function getType(): string + { + return $this->type; + } +} diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php index 24b01612..f624b3cc 100644 --- a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php @@ -3,6 +3,8 @@ namespace App\Classes\Modules\Vouchers\DataTransferObjects; use App\Classes\General\Interfaces\DataTransferObject; +use DateTime; +use Illuminate\Support\Facades\Log; class VoucherObject implements DataTransferObject { @@ -18,19 +20,29 @@ class VoucherObject implements DataTransferObject /** @var float|null */ private $value; + /** @var string|null */ + private $startDate; + + /** @var string|null */ + private $endDate; + /** * VoucherObject constructor. * @param string $code * @param string $name * @param string $type * @param float $value + * @param string $startDate + * @param string $endDate */ - public function __construct(string $code, ?string $name, ?string $type, ?float $value) + public function __construct(string $code, ?string $name, ?string $type, ?float $value, ?string $startDate = '', ?string $endDate = '') { $this->code = $code; $this->name = $name; $this->type = $type; $this->value = $value; + $this->startDate = $startDate; + $this->endDate = $endDate; } /** @@ -67,4 +79,33 @@ class VoucherObject implements DataTransferObject return $this->value; } + /** + * @return DateTime + */ + public function getStartDate(): ?DateTime + { + try { + if(!$this->startDate) return null; + $dateTime = new DateTime($this->startDate); + return $dateTime; + } catch (\Exception $e) { + Log::error($e); + return null; + } + } + + /** + * @return DateTime + */ + public function getEndDate(): ?DateTime + { + try { + if(!$this->endDate) return null; + $dateTime = new DateTime($this->endDate); + return $dateTime; + } catch (\Exception $e) { + Log::error($e); + return null; + } + } } diff --git a/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php b/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php new file mode 100644 index 00000000..690ad59f --- /dev/null +++ b/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php @@ -0,0 +1,114 @@ +fetchesVoucherifyVoucher = $fetchesVoucherifyVoucher; + $this->createsVoucher = $createsVoucher; + $this->createsUserReward = $createsUserReward; + $this->fetchesVoucher = $fetchesVoucher; + $this->validatesVoucherifyVoucher = $validatesVoucherifyVoucher; + } + + + /** + * @param ?User $userParam + * @param string $voucherCodeInput + * @return array + * @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 + $voucherifyVoucherFetched = $this->fetchesVoucherifyVoucher->execute($user, $voucherCodeInput); + + $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); + $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 new file mode 100644 index 00000000..3df08a4c --- /dev/null +++ b/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php @@ -0,0 +1,163 @@ +createsVoucher = $createsVoucher; + $this->fetchesVoucher = $fetchesVoucher; + $this->createsVoucherRedemption = $createsVoucherRedemption; + $this->redeemsVoucherifyVoucher = $redeemsVoucherifyVoucher; + $this->createsVoucherifyOrder = $createsVoucherifyOrder; + $this->createsVoucherEntityMapping = $createsVoucherEntityMapping; + $this->createsUserReward = $createsUserReward; + } + + + /** + * @param User $user + * @param Transaction $transaction + * @param int $companyId + * @param float $amount + * @param float $voucherDiscountAmount + * @param string $voucherCode + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \Voucherify\ClientException + */ + public function execute(User $user, Transaction $transaction, int $companyId, float $amount, float $voucherDiscountAmount, ?string $voucherCode = "") + { + try{ + $voucherify_customer_id = ""; + $voucherify_order_id = ""; + if($voucherCode){ + $redeemVoucherifyVoucherObject = new RedeemVoucherifyVoucherObject($companyId, $voucherCode, $amount, $user); + $redeemVoucherResult = $this->redeemsVoucherifyVoucher->execute($redeemVoucherifyVoucherObject); + $redeemedVoucher = $redeemVoucherResult->voucher; + $redemptionId = $redeemVoucherResult->id; + + if($redeemVoucherResult && isset($redeemVoucherResult->order)){ + $voucherify_order_id = $redeemVoucherResult->order->id; + } + + if($redeemVoucherResult && isset($redeemVoucherResult->customer)){ + $voucherify_customer_id = $redeemVoucherResult->customer->id; + } + + $voucher = $this->recordVoucherInfo($redeemedVoucher, $transaction); + $this->createsVoucherRedemption->execute($transaction, $voucher, $redemptionId, $voucherDiscountAmount); + $this->recordVoucherForUserInfo($user, $voucher); + } + else{ + $createVoucherifyOrderObject = new CreateVoucherifyOrderObject($user, $companyId, $amount, true, $transaction->type == TransactionType::TOP_UP); + $createVoucherufyOrderResult = $this->createsVoucherifyOrder->execute($createVoucherifyOrderObject); + + if($createVoucherufyOrderResult && isset($createVoucherufyOrderResult->id)){ + $voucherify_order_id = $createVoucherufyOrderResult->id; + if(isset($createVoucherufyOrderResult->customer)){ + $voucherify_customer_id = $createVoucherufyOrderResult->customer->id; + } + } + } + + $this->recordVoucherifyOrderInfo($voucherify_order_id, $transaction); + $this->recordVoucherifyCustomerInfo($voucherify_customer_id, $user); + + } catch (\Exception $e) { + Log::error($e); + } + } + + private function recordVoucherInfo(object $redeemedVoucher){ + //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; + + $voucherObject= new VoucherObject($redeemedVoucher->code, isset($redeemedVoucher->metadata->name) ? $redeemedVoucher->metadata->name : "", $voucherType, $voucherValue); + $voucher = $this->createsVoucher->execute($voucherObject); + if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); + + return $voucher; + } + + private function recordVoucherForUserInfo(User $user, Voucher $voucher){ + //create reward to user (user_reward) + $voucherCount = $user->rewards->where('voucher_id', $voucher->id)->count(); + if($voucherCount == 0){ + $this->createsUserReward->execute(null, $user, $voucher->id); + } + } + + private function recordVoucherifyOrderInfo(string $voucherify_order_id, Transaction $transaction){ + //Update Database - 1 table + if($voucherify_order_id){ + $voucherify_entity = $transaction->voucherifyEntities()->first(); + if(!$voucherify_entity){ + $voucherEntityObject = new VoucherEntityObject($voucherify_order_id, VoucherifyEntityType::ORDER); + $this->createsVoucherEntityMapping->execute($transaction, $voucherEntityObject); + } + } + } + + private function recordVoucherifyCustomerInfo(string $voucherify_customer_id, User $user){ + //Update Database - 1 table + if($voucherify_customer_id){ + $voucherify_entity = $user->voucherifyEntities()->first(); + if(!$voucherify_entity){ + $voucherEntityObject = new VoucherEntityObject($voucherify_customer_id, VoucherifyEntityType::CUSTOMER); + $this->createsVoucherEntityMapping->execute($user, $voucherEntityObject); + } + } + } +} diff --git a/app/Classes/Modules/Vouchers/Processors/Voucherify/NewCustomerToVoucherifyProcessor.php b/app/Classes/Modules/Vouchers/Processors/Voucherify/NewCustomerToVoucherifyProcessor.php new file mode 100644 index 00000000..006bcd94 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Processors/Voucherify/NewCustomerToVoucherifyProcessor.php @@ -0,0 +1,55 @@ +createsVoucherEntityMapping = $createsVoucherEntityMapping; + $this->createsVoucherifyCustomer = $createsVoucherifyCustomer; + } + + + /** + * @param int $companyId + * @param User $user + * @param bool $isNew + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(int $companyId, User $user, bool $isNew) + { + try + { + $createVoucherifyCustomerObject = new CreateVoucherifyCustomerObject($companyId, $user, $isNew); + $result = $this->createsVoucherifyCustomer->execute($createVoucherifyCustomerObject); + + if($result && isset($result->id)){ + $voucherEntityObject = new VoucherEntityObject($result->id, VoucherifyEntityType::CUSTOMER); + $this->createsVoucherEntityMapping->execute($createVoucherifyCustomerObject->getUser(), $voucherEntityObject); + } + } catch (\Exception $e) { + Log::error($e); + } + } +} diff --git a/app/Classes/Modules/Vouchers/Processors/Voucherify/TransactionToVoucherifyProcessor.php b/app/Classes/Modules/Vouchers/Processors/Voucherify/TransactionToVoucherifyProcessor.php new file mode 100644 index 00000000..46dbf7a1 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Processors/Voucherify/TransactionToVoucherifyProcessor.php @@ -0,0 +1,44 @@ +updatesVoucherifyOrder = $updatesVoucherifyOrder; + } + + + /** + * @param Transaction $transaction + * @param string $status + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \Voucherify\ClientException + */ + public function execute(Transaction $transaction, string $status) + { + try{ + $voucherify_entity = $transaction->voucherifyEntities()->first(); + if($voucherify_entity){ + $updateVoucherifyOrderObject = new UpdateVoucherifyOrderObject($voucherify_entity->voucherify_entity_id, $status); + $this->updatesVoucherifyOrder->execute($updateVoucherifyOrderObject); + } + } catch (\Exception $e) { + Log::error($e); + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php b/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php index 26fb8bfa..9162dda8 100644 --- a/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php +++ b/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php @@ -33,6 +33,8 @@ class CreatesVoucher extends AbstractUpdateRecord $model->name = $object->getName(); $model->type = $object->getType(); $model->value = $object->getValue(); + $model->start_date = $object->getStartDate(); + $model->end_date = $object->getEndDate(); return $this->handler($model); } return null; diff --git a/app/Classes/Modules/Vouchers/Services/CreatesVoucherEntityMapping.php b/app/Classes/Modules/Vouchers/Services/CreatesVoucherEntityMapping.php new file mode 100644 index 00000000..1a1edb28 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/CreatesVoucherEntityMapping.php @@ -0,0 +1,24 @@ +voucherify_entity_id = $object->getId(); + $model->voucherify_entity_type = $object->getType(); + return $this->handler($voucherifable->voucherifyEntities(), $model); + } +} diff --git a/app/Classes/Modules/Vouchers/Services/RedeemsVoucher.php b/app/Classes/Modules/Vouchers/Services/RedeemsVoucher.php deleted file mode 100644 index aaf4d39a..00000000 --- a/app/Classes/Modules/Vouchers/Services/RedeemsVoucher.php +++ /dev/null @@ -1,48 +0,0 @@ -voucherifyClient = createVoucherifyClient(); - } - - /** - * @param string $promoCode - * @param string $amount - * @param object $employee - * @return null|object - * @throws ErrorException - */ - public function execute(string $promoCode, string $amount, object $employee) - { - try { - $result = $this->voucherifyClient->redemptions->redeem($promoCode, [ - "customer" => [ - // "id" => $employee->id, - "name" => $employee->name, - "email" => $employee->email, - ], - "order" => [ - "amount" => $amount * 100 //converting it to cents - ] - ]); - return $result; - } catch (\Voucherify\ClientException $e) { - throw $e; - } - } -} diff --git a/app/Classes/Modules/Vouchers/Services/RollbacksRedemption.php b/app/Classes/Modules/Vouchers/Services/RollbacksRedemption.php index bd8f6bb2..6bc3bf23 100644 --- a/app/Classes/Modules/Vouchers/Services/RollbacksRedemption.php +++ b/app/Classes/Modules/Vouchers/Services/RollbacksRedemption.php @@ -2,7 +2,6 @@ namespace App\Classes\Modules\Vouchers\Services; -use ErrorException; use Illuminate\Support\Facades\Log; class RollbacksRedemption @@ -24,7 +23,7 @@ class RollbacksRedemption /** * @param string $redemptionId * @return null|object - * @throws ErrorException + * @throws \Voucherify\ClientException */ public function execute(string $redemptionId) { diff --git a/app/Classes/Modules/Vouchers/Services/ValidatesVoucher.php b/app/Classes/Modules/Vouchers/Services/ValidatesVoucher.php deleted file mode 100644 index 7705e22e..00000000 --- a/app/Classes/Modules/Vouchers/Services/ValidatesVoucher.php +++ /dev/null @@ -1,64 +0,0 @@ -voucherifyClient = createVoucherifyClient(); - } - - /** - * @param string $voucherCode - * @param float $amount - * @param object $employee - * @return null|object - * @throws ErrorException - */ - public function execute(string $voucherCode, ?float $amount, ?object $employee) - { - try { - if($amount){ - $result = $this->voucherifyClient->validations->validateVoucher($voucherCode, [ - "customer" => [ - // "id" => $employee->id, - "name" => $employee->name, - "email" => $employee->email, - ], - "order" => [ - "amount" => $amount * 100 //converting it to cents - ] - ]); - } - else{ - $res = $this->voucherifyClient->validations->validateVoucher($voucherCode); - $result = [ - "valid" => $res->valid, - "code" => $res->code - ]; - if (isset($res->reason)) { - $result["reason"] = $res->reason; - } - } - - return $result; - } catch (\Voucherify\ClientException $e) { - // throw $e; - Log::error('ValidatesVoucher error:' . $e); - return null; - } - } -} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyCustomer.php b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyCustomer.php new file mode 100644 index 00000000..a15fe9c3 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyCustomer.php @@ -0,0 +1,66 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param CreateVoucherifyCustomerObject $object + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(CreateVoucherifyCustomerObject $object) + { + try { + + $customerObj = [ + "source_id" => $object->getUser()->id, + "name" => $object->getUser()->name, + "email" => $object->getUser()->email, + "address" => [ + "city" => '', + "country" => '', + "line_1" => '', + "line_2" => '', + "postal_code" => '', + "state" => '', + ], + ]; + + if ($object->getIsNew()) { + $customerObj['metadata']["new_customer"] = date('Y-m-d H:i:s'); + } + if ($object->getCompanyId()) { + $customerObj['metadata']["exchange_company_id"] = $object->getCompanyId(); + $customerObj['metadata']["exchange_user_id"] = $object->getUser()->id; + } + if ($object->getAcquisitionChannel()) { + $customerObj['metadata']["acquisition"] = $object->getAcquisitionChannel(); + } + + $result = $this->voucherifyClient->customers->create($customerObj); + return $result; + } catch (\Voucherify\ClientException $e) { + // throw $e; + Log::error($e); + return null; + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyOrder.php b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyOrder.php new file mode 100644 index 00000000..e5e6d404 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyOrder.php @@ -0,0 +1,61 @@ +voucherifyClient = createVoucherifyClient(); + } + + + /** + * @param CreateVoucherifyOrderObject $obj + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(CreateVoucherifyOrderObject $obj) + { + try { + $orderObj = [ + "customer" => [ + "source_id" => $obj->getEmployee()->id, + "name" => $obj->getEmployee()->name, + "email" => $obj->getEmployee()->email, + "metadata" => [ + "exchange_company_id" => $obj->getCompanyId(), + "exchange_user_id" => $obj->getEmployee()->id + ] + ], + "amount" => $obj->getAmount() * 100, //converting it to cents + ]; + + if ($obj->getIsNoVoucher()) { + $orderObj['metadata']["no_voucher"] = true; + } + + if ($obj->getIsTopUpWallet()) { + $orderObj['metadata']["is_wallet_top_up"] = true; + } + + $result = $this->voucherifyClient->orders->create($orderObj); + return $result; + } catch (\Voucherify\ClientException $e) { + Log::error($e); + return null; + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucher.php b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucher.php new file mode 100644 index 00000000..f3d14bb7 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/CreatesVoucherifyVoucher.php @@ -0,0 +1,59 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param User $user + * @param int $amount + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(User $user, int $amount) + { + $startDate = Carbon::now(); + $expirationDate = $startDate->copy()->addMonths(12)->endOfDay(); + try { + $result = $this->voucherifyClient->vouchers->create([ + "code" => Str::random(10), + "type" => "DISCOUNT_VOUCHER", + "discount" => [ + "type" => "AMOUNT", + "amount_off" => $amount * 100, + ], + "redemption" => [ + "quantity" => 1 + ], + "metadata" => [ + "email" => $user->email + ], + "start_date" => $startDate->format('Y-m-d H:i:s'), + "expiration_date" => $expirationDate->format('Y-m-d H:i:s') + ]); + return $result; + } catch (\Voucherify\ClientException $e) { + Log::error($e); + return null; + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyVoucher.php b/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyVoucher.php new file mode 100644 index 00000000..8c4d33b7 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/FetchesVoucherifyVoucher.php @@ -0,0 +1,47 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param User $user + * @param string $voucherifyVoucherCode + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(User $user, string $voucherifyVoucherCode) + { + try { + $result = $this->voucherifyClient->vouchers->get($voucherifyVoucherCode); + + if (isset($result->metadata) && isset($result->metadata->email)) { + if($user->email != $result->metadata->email){ + $result->reason = 'Invalid Code'; + } + } + + return $result; + } catch (\Voucherify\ClientException $e) { + Log::error($e); + return null; + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/RedeemsVoucherifyVoucher.php b/app/Classes/Modules/Vouchers/Services/Voucherify/RedeemsVoucherifyVoucher.php new file mode 100644 index 00000000..bd12e27f --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/RedeemsVoucherifyVoucher.php @@ -0,0 +1,50 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param RedeemVoucherifyVoucherObject $redeemVoucherifyVoucherObject + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(RedeemVoucherifyVoucherObject $redeemVoucherifyVoucherObject) + { + try { + $result = $this->voucherifyClient->redemptions->redeem($redeemVoucherifyVoucherObject->getPromoCode(), [ + "customer" => [ + "source_id" => $redeemVoucherifyVoucherObject->getEmployee()->id, + "name" => $redeemVoucherifyVoucherObject->getEmployee()->name, + "email" => $redeemVoucherifyVoucherObject->getEmployee()->email, + "metadata" => [ + "exchange_company_id" => $redeemVoucherifyVoucherObject->getCompanyId(), + "exchange_user_id" => $redeemVoucherifyVoucherObject->getEmployee()->id + ] + ], + "order" => [ + "amount" => $redeemVoucherifyVoucherObject->getAmount() * 100 //converting it to cents + ] + ]); + return $result; + } catch (\Voucherify\ClientException $e) { + throw $e; + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/UpdatesVoucherifyOrder.php b/app/Classes/Modules/Vouchers/Services/Voucherify/UpdatesVoucherifyOrder.php new file mode 100644 index 00000000..80aae605 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/UpdatesVoucherifyOrder.php @@ -0,0 +1,43 @@ +voucherifyClient = createVoucherifyClient(); + } + + + /** + * @param UpdateVoucherifyOrderObject $obj + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(UpdateVoucherifyOrderObject $obj) + { + try { + $result = $this->voucherifyClient->orders->update([ + "id" => $obj->getId(), + "status" => $obj->getStatus(), + ]); + return $result; + } catch (\Voucherify\ClientException $e) { + Log::error($e); + return null; + } + } +} diff --git a/app/Classes/Modules/Vouchers/Services/Voucherify/ValidatesVoucherifyVoucher.php b/app/Classes/Modules/Vouchers/Services/Voucherify/ValidatesVoucherifyVoucher.php new file mode 100644 index 00000000..3fa322d5 --- /dev/null +++ b/app/Classes/Modules/Vouchers/Services/Voucherify/ValidatesVoucherifyVoucher.php @@ -0,0 +1,70 @@ +voucherifyClient = createVoucherifyClient(); + } + + /** + * @param ValidateVoucherifyVoucherObject $validateVoucherifyVoucherObject + * @return null|object + * @throws \Voucherify\ClientException + */ + public function execute(ValidateVoucherifyVoucherObject $validateVoucherifyVoucherObject) + { + try { + $validateVoucherObj = [ + "customer" => [ + "source_id" => $validateVoucherifyVoucherObject->getUser()->id, + "name" => $validateVoucherifyVoucherObject->getUser()->name, + "email" => $validateVoucherifyVoucherObject->getUser()->email, + "metadata" => [ + "exchange_company_id" => $validateVoucherifyVoucherObject->getCompanyId(), + "exchange_user_id" => $validateVoucherifyVoucherObject->getUser()->id + ] + ] + ]; + if ($validateVoucherifyVoucherObject->getAmount()) { + $validateVoucherObj['order'] = [ + "amount" => $validateVoucherifyVoucherObject->getAmount() * 100 //converting it to cents + ]; + } + + $result = $this->voucherifyClient->validations->validateVoucher($validateVoucherifyVoucherObject->getVoucherCode(), $validateVoucherObj); + + if (isset($result->metadata) && isset($result->metadata->email)) { + if($validateVoucherifyVoucherObject->getUser()->email != $result->metadata->email){ + $result->reason = 'Invalid Code'; + } + } + + if (isset($result->reason)) { + Helper::debugLogger('ValidatesVoucherifyVoucher error: '. $result->reason); + $result->reason = 'Invalid Code'; + } + + return $result; + } catch (\Voucherify\ClientException $e) { + // throw $e; + Log::error($e); + return null; + } + } +} diff --git a/app/Classes/Modules/Wallets/ControllersLogic/TopUpWalletLogic.php b/app/Classes/Modules/Wallets/ControllersLogic/TopUpWalletLogic.php index c60cbf54..86e344ec 100644 --- a/app/Classes/Modules/Wallets/ControllersLogic/TopUpWalletLogic.php +++ b/app/Classes/Modules/Wallets/ControllersLogic/TopUpWalletLogic.php @@ -13,6 +13,7 @@ use App\Classes\Modules\Wallets\Services\GeneratesWalletCode; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill; use App\Classes\Modules\Transactions\Services\CreatesTransaction; +use App\Classes\Modules\Vouchers\Processors\Voucherify\BookingToVoucherifyProcessor; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\ApprovalStatus; @@ -56,6 +57,8 @@ class TopUpWalletLogic extends AbstractControllerLogic /** @var CreatesTransaction */ private $createsTransaction; + /** @var BookingToVoucherifyProcessor */ + private $bookingToVoucherifyProcessor; /** * TopUpWalletLogic constructor. @@ -65,8 +68,9 @@ class TopUpWalletLogic extends AbstractControllerLogic * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber * @param CreatesBillplzBill $createsBillplzBill * @param CreatesTransaction $createsTransaction + * @param BookingToVoucherifyProcessor $bookingToVoucherifyProcessor */ - public function __construct(FetchesCompany $fetchesCompany, GeneratesWalletCode $generatesWalletCode, CreatesWallet $createsWallet, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesBillplzBill $createsBillplzBill, CreatesTransaction $createsTransaction) + public function __construct(FetchesCompany $fetchesCompany, GeneratesWalletCode $generatesWalletCode, CreatesWallet $createsWallet, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesBillplzBill $createsBillplzBill, CreatesTransaction $createsTransaction, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor) { $this->fetchesCompany = $fetchesCompany; $this->generatesWalletCode = $generatesWalletCode; @@ -74,6 +78,7 @@ class TopUpWalletLogic extends AbstractControllerLogic $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createsBillplzBill = $createsBillplzBill; $this->createsTransaction = $createsTransaction; + $this->bookingToVoucherifyProcessor = $bookingToVoucherifyProcessor; } /** @@ -108,6 +113,8 @@ class TopUpWalletLogic extends AbstractControllerLogic $transaction = $this->createsTransaction->execute($wallet, $transaction_object); + $this->bookingToVoucherifyProcessor->execute($company->employees()->first(), $transaction, $company->id, $amount, 0); + return $this->resourceResponse(new WalletTransactionResource($transaction)); } } diff --git a/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php b/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php new file mode 100644 index 00000000..4631b25b --- /dev/null +++ b/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php @@ -0,0 +1,19 @@ + 'MILESTONE 1', 'id' => Milestones::MILESTONE_1], + ['text' => 'MILESTONE 2', 'id' => Milestones::MILESTONE_2], + ['text' => 'MILESTONE 3', 'id' => Milestones::MILESTONE_3], + // ['text' => 'MILESTONE 4', 'id' => Milestones::MILESTONE_4], + // ['text' => 'MILESTONE 5', 'id' => Milestones::MILESTONE_5], + // ['text' => 'MILESTONE 6', 'id' => Milestones::MILESTONE_6], + // ['text' => 'MILESTONE 7', 'id' => Milestones::MILESTONE_7], + // ['text' => 'MILESTONE 8', 'id' => Milestones::MILESTONE_8], + // ['text' => 'MILESTONE 9', 'id' => Milestones::MILESTONE_9], + // ['text' => 'MILESTONE 10', 'id' => Milestones::MILESTONE_10], + ]; +} diff --git a/app/Classes/ValueObjects/Constants/Milestones.php b/app/Classes/ValueObjects/Constants/Milestones.php new file mode 100644 index 00000000..19961d68 --- /dev/null +++ b/app/Classes/ValueObjects/Constants/Milestones.php @@ -0,0 +1,17 @@ + 'No', 'id' => 0], + ['text' => 'Yes', 'id' => 1], + ]; + + const OPTIONS_TYPE = [ + ['text' => 'User Specific', 'id' => RewardType::REWARD_INDIVIDUAL], + ['text' => 'Amount', 'id' => RewardType::REWARD_AMOUNT], + ['text' => 'Code', 'id' => RewardType::REWARD_CODE], + ]; +} diff --git a/app/Classes/ValueObjects/Constants/RewardType.php b/app/Classes/ValueObjects/Constants/RewardType.php new file mode 100644 index 00000000..1add2ecd --- /dev/null +++ b/app/Classes/ValueObjects/Constants/RewardType.php @@ -0,0 +1,10 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Milestones/DeleteMilestoneController.php b/app/Http/Controllers/Milestones/DeleteMilestoneController.php new file mode 100644 index 00000000..084ff35e --- /dev/null +++ b/app/Http/Controllers/Milestones/DeleteMilestoneController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Milestones/ListMilestoneProgressController.php b/app/Http/Controllers/Milestones/ListMilestoneProgressController.php new file mode 100644 index 00000000..03e2aa10 --- /dev/null +++ b/app/Http/Controllers/Milestones/ListMilestoneProgressController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Milestones/ListMilestonesController.php b/app/Http/Controllers/Milestones/ListMilestonesController.php new file mode 100644 index 00000000..b592c0d4 --- /dev/null +++ b/app/Http/Controllers/Milestones/ListMilestonesController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Milestones/UpdateMilestoneController.php b/app/Http/Controllers/Milestones/UpdateMilestoneController.php new file mode 100644 index 00000000..e3dce17d --- /dev/null +++ b/app/Http/Controllers/Milestones/UpdateMilestoneController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Rewards/CreateRewardController.php b/app/Http/Controllers/Rewards/CreateRewardController.php new file mode 100644 index 00000000..55ea98c9 --- /dev/null +++ b/app/Http/Controllers/Rewards/CreateRewardController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Rewards/DeleteRewardController.php b/app/Http/Controllers/Rewards/DeleteRewardController.php new file mode 100644 index 00000000..bc8e90e9 --- /dev/null +++ b/app/Http/Controllers/Rewards/DeleteRewardController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Rewards/ListRewardsController.php b/app/Http/Controllers/Rewards/ListRewardsController.php new file mode 100644 index 00000000..2d02d898 --- /dev/null +++ b/app/Http/Controllers/Rewards/ListRewardsController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Rewards/ListRewardsDetailsController.php b/app/Http/Controllers/Rewards/ListRewardsDetailsController.php new file mode 100644 index 00000000..bd853b00 --- /dev/null +++ b/app/Http/Controllers/Rewards/ListRewardsDetailsController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Vouchers/RedeemVoucherController.php b/app/Http/Controllers/Vouchers/CreateVoucherController.php similarity index 57% rename from app/Http/Controllers/Vouchers/RedeemVoucherController.php rename to app/Http/Controllers/Vouchers/CreateVoucherController.php index 8657846f..f89c93ac 100644 --- a/app/Http/Controllers/Vouchers/RedeemVoucherController.php +++ b/app/Http/Controllers/Vouchers/CreateVoucherController.php @@ -2,18 +2,18 @@ namespace App\Http\Controllers\Vouchers; -use App\Classes\Modules\Vouchers\ControllersLogic\RedeemVoucherLogic; +use App\Classes\Modules\Vouchers\ControllersLogic\CreateVoucherLogic; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -class RedeemVoucherController +class CreateVoucherController { /** * @param Request $request - * @param RedeemVoucherLogic $logic + * @param CreateVoucherLogic $logic * @return JsonResponse */ - public function redeem(Request $request, RedeemVoucherLogic $logic): JsonResponse { + public function create(Request $request, CreateVoucherLogic $logic): JsonResponse { return $logic->execute($request); } diff --git a/app/Http/Controllers/Vouchers/ListUserVouchersController.php b/app/Http/Controllers/Vouchers/ListUserVouchersController.php new file mode 100644 index 00000000..df8cb610 --- /dev/null +++ b/app/Http/Controllers/Vouchers/ListUserVouchersController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Resources/MilestoneProgressResource.php b/app/Http/Resources/MilestoneProgressResource.php new file mode 100644 index 00000000..ed4c465f --- /dev/null +++ b/app/Http/Resources/MilestoneProgressResource.php @@ -0,0 +1,23 @@ + $this->id, + 'milestone_id' => $this->milestone_id, + 'created_at' => $this->created_at + ]; + } +} diff --git a/app/Http/Resources/MilestoneResource.php b/app/Http/Resources/MilestoneResource.php new file mode 100644 index 00000000..f336f937 --- /dev/null +++ b/app/Http/Resources/MilestoneResource.php @@ -0,0 +1,28 @@ +rewards->pluck('id')->map(function ($id) { + return (int) $id; + })->toArray(); + + return [ + 'id' => $this->id, + 'name' => $this->name, + 'description' => $this->description, + 'reward_ids' => $rewardIds + ]; + } +} diff --git a/app/Http/Resources/MilestoneWIthMiltestoneProgressResource.php b/app/Http/Resources/MilestoneWIthMiltestoneProgressResource.php new file mode 100644 index 00000000..4b4176b6 --- /dev/null +++ b/app/Http/Resources/MilestoneWIthMiltestoneProgressResource.php @@ -0,0 +1,30 @@ +route('user_id'); + if(!$userId){ + $userId = Auth::user()->id; + } + + return [ + 'id' => $this->id, + 'name' => $this->name, + 'description' => $this->description, + 'milestone_progress' => new MilestoneProgressResource($this->progress->where('user_id', $userId)->first()), + ]; + } +} diff --git a/app/Http/Resources/RewardDetailsResource.php b/app/Http/Resources/RewardDetailsResource.php new file mode 100644 index 00000000..211ee4da --- /dev/null +++ b/app/Http/Resources/RewardDetailsResource.php @@ -0,0 +1,35 @@ +route('user_id'); + if(!$userId){ + $userId = Auth::user()->id; + } + + $userReward = $this->users->where('user_id', $userId)->first(); + + return [ + 'id' => $this->id, + 'name' => $this->name, + 'description' => $this->description, + 'milestones' => $this->milestones, + 'milestones_progress' => MilestoneWIthMiltestoneProgressResource::collection($this->milestones), + 'user_rewards' => new UserRewardResource($userReward), + 'voucher' => $userReward ? $userReward->voucher : null + ]; + } +} diff --git a/app/Http/Resources/RewardResource.php b/app/Http/Resources/RewardResource.php new file mode 100644 index 00000000..e400fc6a --- /dev/null +++ b/app/Http/Resources/RewardResource.php @@ -0,0 +1,28 @@ + $this->id, + 'name' => $this->name, + 'description' => $this->description, + 'is_active' => $this->is_active, + 'type' => $this->type, + 'value' => $this->value, + 'order' => $this->order, + 'milestones' => MilestoneResource::collection($this->milestones) + ]; + } +} diff --git a/app/Http/Resources/UserRewardResource.php b/app/Http/Resources/UserRewardResource.php new file mode 100644 index 00000000..ed693b4c --- /dev/null +++ b/app/Http/Resources/UserRewardResource.php @@ -0,0 +1,25 @@ + $this->id, + 'user_id' => $this->user_id, + 'reward' => new RewardResource($this->reward), + 'voucher' => new VoucherResource($this->voucher), + 'created_at' => $this->created_at + ]; + } +} diff --git a/app/Http/Resources/VoucherResource.php b/app/Http/Resources/VoucherResource.php new file mode 100644 index 00000000..54193eeb --- /dev/null +++ b/app/Http/Resources/VoucherResource.php @@ -0,0 +1,31 @@ +redemptions->filter(function ($redemption) { + return $redemption->transaction && $redemption->transaction->owner; + }); + return [ + 'id' => $this->id, + 'name' => $this->name, + '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 + ]; + } +} diff --git a/app/Models/Employee.php b/app/Models/Employee.php index 65dab67d..6d133186 100644 --- a/app/Models/Employee.php +++ b/app/Models/Employee.php @@ -31,4 +31,13 @@ class Employee extends AbstractModel { return $this->hasOne(User::class, 'user_id', 'id'); } + + /** + * @return belongsToMany + */ + public function milestones() + { + return $this->belongsToMany(Milestone::class, 'milestone_progress', 'user_id', 'milestone_id') + ->withPivot('created_at'); + } } diff --git a/app/Models/Milestone.php b/app/Models/Milestone.php new file mode 100644 index 00000000..391410cc --- /dev/null +++ b/app/Models/Milestone.php @@ -0,0 +1,22 @@ +hasMany(MilestoneProgress::class, 'milestone_id'); + } + + public function rewards() + { + return $this->belongsToMany(Reward::class, MilestoneReward::class); + } +} diff --git a/app/Models/MilestoneProgress.php b/app/Models/MilestoneProgress.php new file mode 100644 index 00000000..7e03cba0 --- /dev/null +++ b/app/Models/MilestoneProgress.php @@ -0,0 +1,23 @@ +belongsTo(Milestone::class, 'milestone_id'); + } + + public function user() + { + return $this->belongsTo(User::class, 'user_id'); + } +} diff --git a/app/Models/MilestoneReward.php b/app/Models/MilestoneReward.php new file mode 100644 index 00000000..1d5f04e3 --- /dev/null +++ b/app/Models/MilestoneReward.php @@ -0,0 +1,8 @@ +belongsToMany(Milestone::class, MilestoneReward::class); + } + + /** + * @return HasMany + */ + public function users(): HasMany + { + return $this->HasMany(UserReward::class, 'reward_id', 'id'); + } +} diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index eba18ee5..05fbfde7 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -4,6 +4,7 @@ namespace App\Models; use App\Classes\General\Interfaces\Documentable; use App\Classes\General\Interfaces\Transactionable; +use App\Classes\General\Interfaces\Voucherifiable; use App\Classes\General\Traits\LogData; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; @@ -19,7 +20,7 @@ use Illuminate\Database\Eloquent\Relations\MorphTo; use Staudenmeir\EloquentHasManyDeep\HasTableAlias; -class Transaction extends AbstractModel implements Documentable, Transactionable +class Transaction extends AbstractModel implements Documentable, Transactionable, Voucherifiable { use HasTableAlias; use SoftDeletes; @@ -200,4 +201,13 @@ class Transaction extends AbstractModel implements Documentable, Transactionable { return $query->whereIn('status', [ApprovalStatus::APPROVED]); } + + /** + * @return MorphMany + */ + public function voucherifyEntities(): MorphMany + { + return $this->morphMany(VoucherEntityMapping::class, 'owner'); + } + } diff --git a/app/Models/User.php b/app/Models/User.php index 6f33fac5..4bc7ec17 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,8 +2,10 @@ namespace App\Models; +use App\Classes\General\Interfaces\Voucherifiable; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\SoftDeletes; @@ -23,7 +25,8 @@ class User extends AbstractModel implements JWTSubject, AuthenticatableContract, AuthorizableContract, - CanResetPasswordContract + CanResetPasswordContract, + Voucherifiable { use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes; @@ -67,11 +70,35 @@ class User extends AbstractModel implements return $this->belongsToMany(Company::class, (new Employee())->getTable(), 'user_id', 'company_id'); } + // /** + // * @return HasMany + // */ + // public function redemptions(): HasMany + // { + // return $this->HasMany(VoucherRedemption::class, 'user_id', 'id'); + // } + /** * @return HasMany */ - public function redemptions(): HasMany + public function milestoneProgress(): HasMany { - return $this->HasMany(VoucherRedemption::class, 'user_id', 'id'); + return $this->HasMany(MilestoneProgress::class, 'user_id', 'id'); + } + + /** + * @return MorphMany + */ + public function voucherifyEntities(): MorphMany + { + return $this->morphMany(VoucherEntityMapping::class, 'owner'); + } + + /** + * @return HasMany + */ + public function rewards(): HasMany + { + return $this->HasMany(UserReward::class, 'user_id', 'id'); } } diff --git a/app/Models/UserReward.php b/app/Models/UserReward.php new file mode 100644 index 00000000..40309447 --- /dev/null +++ b/app/Models/UserReward.php @@ -0,0 +1,28 @@ +belongsTo(Reward::class, 'reward_id'); + } + + public function user() + { + return $this->belongsTo(User::class, 'user_id'); + } + + public function voucher() + { + return $this->belongsTo(Voucher::class, 'voucher_id'); + } +} diff --git a/app/Models/VoucherEntityMapping.php b/app/Models/VoucherEntityMapping.php new file mode 100644 index 00000000..2df0eacd --- /dev/null +++ b/app/Models/VoucherEntityMapping.php @@ -0,0 +1,23 @@ +morphTo(); + } + +} diff --git a/database/migrations/2023_06_12_191228_create_rewards_table.php b/database/migrations/2023_06_12_191228_create_rewards_table.php new file mode 100644 index 00000000..04ea1133 --- /dev/null +++ b/database/migrations/2023_06_12_191228_create_rewards_table.php @@ -0,0 +1,38 @@ +id(); + $table->string('name'); + $table->text('description')->nullable(); + $table->boolean('is_active')->default(true); + $table->integer('type')->default(0); + $table->string('value'); + $table->integer('order')->default(9999); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('rewards'); + } +} diff --git a/database/migrations/2023_06_13_062800_create_milestones_table.php b/database/migrations/2023_06_13_062800_create_milestones_table.php new file mode 100644 index 00000000..8785e734 --- /dev/null +++ b/database/migrations/2023_06_13_062800_create_milestones_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('name'); + $table->string('description'); + // $table->unsignedBigInteger('reward_id'); + $table->softDeletes(); + $table->timestamps(); + + // $table->foreign('reward_id')->references('id')->on('rewards')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('milestones'); + } +} diff --git a/database/migrations/2023_06_13_213411_create_milestone_progress_table.php b/database/migrations/2023_06_13_213411_create_milestone_progress_table.php new file mode 100644 index 00000000..3476eb5a --- /dev/null +++ b/database/migrations/2023_06_13_213411_create_milestone_progress_table.php @@ -0,0 +1,39 @@ +id(); + // $table->unsignedBigInteger('company_id'); + $table->unsignedBigInteger('user_id'); + $table->unsignedBigInteger('milestone_id'); + $table->softDeletes(); + $table->timestamps(); + + // $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->foreign('milestone_id')->references('id')->on('milestones')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('milestone_progress'); + } +} diff --git a/database/migrations/2023_06_20_192419_create_user_rewards_table.php b/database/migrations/2023_06_20_192419_create_user_rewards_table.php new file mode 100644 index 00000000..42288a87 --- /dev/null +++ b/database/migrations/2023_06_20_192419_create_user_rewards_table.php @@ -0,0 +1,39 @@ +id(); + $table->unsignedBigInteger('user_id'); + $table->unsignedBigInteger('reward_id'); + $table->unsignedBigInteger('voucher_id'); + $table->softDeletes(); + $table->timestamps(); + + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + // $table->foreign('reward_id')->references('id')->on('rewards')->onDelete('cascade'); + $table->foreign('voucher_id')->references('id')->on('vouchers')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('user_rewards'); + } +} diff --git a/database/migrations/2023_07_02_210132_create_milestone_reward.php b/database/migrations/2023_07_02_210132_create_milestone_reward.php new file mode 100644 index 00000000..2a00d7df --- /dev/null +++ b/database/migrations/2023_07_02_210132_create_milestone_reward.php @@ -0,0 +1,35 @@ +unsignedBigInteger('milestone_id'); + $table->unsignedBigInteger('reward_id'); + // $table->timestamps(); + + $table->foreign('milestone_id')->references('id')->on('milestones')->onDelete('cascade'); + $table->foreign('reward_id')->references('id')->on('rewards')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('milestone_reward'); + } +} diff --git a/database/migrations/2023_07_05_081135_create_voucher_entity_mappings.php b/database/migrations/2023_07_05_081135_create_voucher_entity_mappings.php new file mode 100644 index 00000000..5bae07b0 --- /dev/null +++ b/database/migrations/2023_07_05_081135_create_voucher_entity_mappings.php @@ -0,0 +1,36 @@ +id(); + $table->string('owner_type'); + $table->unsignedBigInteger('owner_id'); + $table->string('voucherify_entity_type'); + $table->string('voucherify_entity_id'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('voucher_entity_mappings'); + } +} diff --git a/database/migrations/2023_07_08_155628_add_start_date_and_end_date_to_vouchers_table.php b/database/migrations/2023_07_08_155628_add_start_date_and_end_date_to_vouchers_table.php new file mode 100644 index 00000000..a88e8e0d --- /dev/null +++ b/database/migrations/2023_07_08_155628_add_start_date_and_end_date_to_vouchers_table.php @@ -0,0 +1,33 @@ +timestamp('start_date')->nullable(); + $table->timestamp('end_date')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('vouchers', function (Blueprint $table) { + $table->dropColumn(['start_date', 'end_date']); + }); + } +} diff --git a/database/seeds/AdminUserPermissionsTableSeeder.php b/database/seeds/AdminUserPermissionsTableSeeder.php index 132184d7..0c3d5acf 100644 --- a/database/seeds/AdminUserPermissionsTableSeeder.php +++ b/database/seeds/AdminUserPermissionsTableSeeder.php @@ -19,7 +19,7 @@ class AdminUserPermissionsTableSeeder extends Seeder app()['cache']->forget('spatie.permission.cache'); // admin permissions - $permissions = [ + $permissions = [ ['name' => 'view document', 'guard_name' => 'web'], ['name' => 'add document', 'guard_name' => 'web'], ['name' => 'edit document', 'guard_name' => 'web'], @@ -63,7 +63,14 @@ class AdminUserPermissionsTableSeeder extends Seeder ['name' => 'view booking', 'guard_name' => 'web'], ['name' => 'add booking', 'guard_name' => 'web'], ['name' => 'edit booking', 'guard_name' => 'web'], - ['name' => 'delete booking', 'guard_name' => 'web'] + ['name' => 'delete booking', 'guard_name' => 'web'], + + ['name' => 'add milestone', 'guard_name' => 'web'], + ['name' => 'add reward', 'guard_name' => 'web'], + ['name' => 'edit milestone', 'guard_name' => 'web'], + ['name' => 'delete milestone', 'guard_name' => 'web'], + ['name' => 'delete reward', 'guard_name' => 'web'], + ]; foreach ($permissions as $permission){ diff --git a/docker-setup/Dockerfile b/docker-setup/Dockerfile index 13ce0249..71255f30 100644 --- a/docker-setup/Dockerfile +++ b/docker-setup/Dockerfile @@ -2,6 +2,8 @@ FROM php:7.4-fpm WORKDIR /var/www/html +RUN pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug + RUN docker-php-ext-install pdo pdo_mysql RUN apt-get update && apt-get install -y \ @@ -25,4 +27,15 @@ RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - RUN apt-get -y install nodejs RUN chown -R www-data:www-data /var/www -RUN chmod 755 /var/www \ No newline at end of file +RUN chmod 755 /var/www + +# Configure xdebug +RUN echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN echo "xdebug.remote_autostart=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN echo "xdebug.remote_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN echo "xdebug.remote_port=9002" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN echo "xdebug.idekey=VSCODE" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini + +# Moved to docker-setup folder +# RUN echo 'pm.max_children = 15' >> /usr/local/etc/php-fpm.d/zz-docker.conf && \ +# echo 'pm.max_requests = 500' >> /usr/local/etc/php-fpm.d/zz-docker.conf diff --git a/docker-setup/docker-compose.yml b/docker-setup/docker-compose.yml index deb02207..4dcfa8c2 100644 --- a/docker-setup/docker-compose.yml +++ b/docker-setup/docker-compose.yml @@ -44,8 +44,7 @@ services: container_name: exchange-php volumes: - ../:/var/www/html - ports: - - "9002:9000" + - ./php/default.conf:/usr/local/etc/php-fpm.d/zz-docker.conf networks: - exchange-staging ################################################################# diff --git a/docker-setup/nginx/default.conf b/docker-setup/nginx/default.conf index b594e701..c1811261 100644 --- a/docker-setup/nginx/default.conf +++ b/docker-setup/nginx/default.conf @@ -23,6 +23,13 @@ server { fastcgi_intercept_errors on; fastcgi_keep_conn on; fastcgi_param PHP_VALUE "auto_prepend_file= \n allow_url_include=Off"; + + # Xdebug configuration + # fastcgi_param XDEBUG_MODE debug; + # fastcgi_param XDEBUG_CLIENT_HOST host.docker.internal; + # fastcgi_param XDEBUG_CLIENT_PORT 9002; + # fastcgi_param XDEBUG_IDE_KEY VSCODE; + proxy_send_timeout 3600; proxy_read_timeout 3600; fastcgi_send_timeout 3600; diff --git a/docker-setup/php/default.conf b/docker-setup/php/default.conf new file mode 100644 index 00000000..dced3233 --- /dev/null +++ b/docker-setup/php/default.conf @@ -0,0 +1,8 @@ +[global] +daemonize = no + +[www] +listen = 9000 + +pm.max_children = 15 +pm.max_requests = 500 diff --git a/resources/assets/vue/components/bookings/elements/ListVouchers.vue b/resources/assets/vue/components/bookings/elements/ListVouchers.vue new file mode 100644 index 00000000..e59ff653 --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/ListVouchers.vue @@ -0,0 +1,81 @@ + + + diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index c9ababa4..71bf53d9 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -244,9 +244,17 @@ +
+ +
+ + + Apply a voucher
@@ -592,6 +600,7 @@ voucherValidated: false, voucherIsChecking: false, showApplyVoucher: false, + voucherListDropDownStatus: false, } }, validations () { @@ -677,7 +686,8 @@ this.voucherValidated = false; this.parameters = { voucherCode: this.voucherCode, - amount: this.amount + amount: this.amount, + itemId: this.item.id }; if(this.voucherCode.trim() !== ''){ this.submit(route('api.voucher.validate'), 'post', '', false, false); @@ -691,6 +701,13 @@ this.voucherCodeFailedReason = ''; this.voucherValidated = false; this.voucherCode = event.target.value; + }, + toggleDropdown() { + this.voucherListDropDownStatus = !this.voucherListDropDownStatus; + }, + handleSelectedVoucher(value){ + this.voucherCode = value; + this.voucherListDropDownStatus = !this.voucherListDropDownStatus; } }, mixins: [componentHandler], diff --git a/resources/assets/vue/components/companies/elements/SingleRewardDetailsItemComponent.vue b/resources/assets/vue/components/companies/elements/SingleRewardDetailsItemComponent.vue new file mode 100644 index 00000000..739cc262 --- /dev/null +++ b/resources/assets/vue/components/companies/elements/SingleRewardDetailsItemComponent.vue @@ -0,0 +1,29 @@ + + diff --git a/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue b/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue new file mode 100644 index 00000000..8f25ab60 --- /dev/null +++ b/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue @@ -0,0 +1,30 @@ + + diff --git a/resources/assets/vue/components/companies/sections/AddVoucherSectionComponent.vue b/resources/assets/vue/components/companies/sections/AddVoucherSectionComponent.vue new file mode 100644 index 00000000..65b0c2ed --- /dev/null +++ b/resources/assets/vue/components/companies/sections/AddVoucherSectionComponent.vue @@ -0,0 +1,106 @@ + + + diff --git a/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue new file mode 100644 index 00000000..7ba9b13d --- /dev/null +++ b/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue @@ -0,0 +1,119 @@ + + + diff --git a/resources/assets/vue/components/companies/sections/CustomerRewardsSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerRewardsSectionComponent.vue new file mode 100644 index 00000000..28ed76cd --- /dev/null +++ b/resources/assets/vue/components/companies/sections/CustomerRewardsSectionComponent.vue @@ -0,0 +1,112 @@ + + + diff --git a/resources/assets/vue/components/general/forms/SelectComponent.vue b/resources/assets/vue/components/general/forms/SelectComponent.vue index 394ec13b..1f902903 100644 --- a/resources/assets/vue/components/general/forms/SelectComponent.vue +++ b/resources/assets/vue/components/general/forms/SelectComponent.vue @@ -33,7 +33,11 @@ $(this.$el).val(value).trigger('change'); }, options: function(options){ - $(this.$el).select2({ data: options }); + $(this.$el).select2({ + data: options, + minimumResultsForSearch: 6, + theme: 'bootstrap', + containerCssClass: 'form-control'}); this.value ? $(this.$el).val(this.value).trigger('change'):null; } }, diff --git a/resources/assets/vue/components/general/forms/SelectableHardCodedComponent.vue b/resources/assets/vue/components/general/forms/SelectableHardCodedComponent.vue new file mode 100644 index 00000000..05a4e007 --- /dev/null +++ b/resources/assets/vue/components/general/forms/SelectableHardCodedComponent.vue @@ -0,0 +1,22 @@ + + + diff --git a/resources/assets/vue/components/settings/elements/MilestoneSingleItemComponent.vue b/resources/assets/vue/components/settings/elements/MilestoneSingleItemComponent.vue new file mode 100644 index 00000000..ab4f013e --- /dev/null +++ b/resources/assets/vue/components/settings/elements/MilestoneSingleItemComponent.vue @@ -0,0 +1,89 @@ + + diff --git a/resources/assets/vue/components/settings/elements/RewardChecklistComponent.vue b/resources/assets/vue/components/settings/elements/RewardChecklistComponent.vue new file mode 100644 index 00000000..453bdbe5 --- /dev/null +++ b/resources/assets/vue/components/settings/elements/RewardChecklistComponent.vue @@ -0,0 +1,34 @@ + + + diff --git a/resources/assets/vue/components/settings/elements/RewardSingleItemComponent.vue b/resources/assets/vue/components/settings/elements/RewardSingleItemComponent.vue new file mode 100644 index 00000000..a8510027 --- /dev/null +++ b/resources/assets/vue/components/settings/elements/RewardSingleItemComponent.vue @@ -0,0 +1,93 @@ + + + diff --git a/resources/assets/vue/components/settings/forms/AddMilestoneFormComponent.vue b/resources/assets/vue/components/settings/forms/AddMilestoneFormComponent.vue new file mode 100644 index 00000000..461a447b --- /dev/null +++ b/resources/assets/vue/components/settings/forms/AddMilestoneFormComponent.vue @@ -0,0 +1,112 @@ + + diff --git a/resources/assets/vue/components/settings/forms/AddRewardFormComponent.vue b/resources/assets/vue/components/settings/forms/AddRewardFormComponent.vue new file mode 100644 index 00000000..b00be4b0 --- /dev/null +++ b/resources/assets/vue/components/settings/forms/AddRewardFormComponent.vue @@ -0,0 +1,158 @@ + + diff --git a/resources/assets/vue/components/settings/forms/DeleteMilestoneFormComponent.vue b/resources/assets/vue/components/settings/forms/DeleteMilestoneFormComponent.vue new file mode 100644 index 00000000..63e0980c --- /dev/null +++ b/resources/assets/vue/components/settings/forms/DeleteMilestoneFormComponent.vue @@ -0,0 +1,33 @@ + + diff --git a/resources/assets/vue/components/settings/forms/DeleteRewardFormComponent.vue b/resources/assets/vue/components/settings/forms/DeleteRewardFormComponent.vue new file mode 100644 index 00000000..ecde176a --- /dev/null +++ b/resources/assets/vue/components/settings/forms/DeleteRewardFormComponent.vue @@ -0,0 +1,33 @@ + + diff --git a/resources/assets/vue/components/settings/sections/MilestoneListComponent.vue b/resources/assets/vue/components/settings/sections/MilestoneListComponent.vue new file mode 100644 index 00000000..def19717 --- /dev/null +++ b/resources/assets/vue/components/settings/sections/MilestoneListComponent.vue @@ -0,0 +1,79 @@ + + + + diff --git a/resources/views/pages/customers/reward.blade.php b/resources/views/pages/customers/reward.blade.php new file mode 100644 index 00000000..6332f664 --- /dev/null +++ b/resources/views/pages/customers/reward.blade.php @@ -0,0 +1,27 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+ +
+
+
+ Vouchers +
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+@endsection diff --git a/resources/views/pages/rewards/customers.blade.php b/resources/views/pages/rewards/customers.blade.php new file mode 100644 index 00000000..edbabb74 --- /dev/null +++ b/resources/views/pages/rewards/customers.blade.php @@ -0,0 +1,23 @@ +
+
+
+
+
+ Vouchers +
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
diff --git a/resources/views/pages/rewards/index.blade.php b/resources/views/pages/rewards/index.blade.php new file mode 100644 index 00000000..2a1daa8b --- /dev/null +++ b/resources/views/pages/rewards/index.blade.php @@ -0,0 +1,4 @@ +@extends('layouts.base_portal') +@section('inner_content') + @include('pages.rewards.customers') +@endsection diff --git a/resources/views/pages/settings.blade.php b/resources/views/pages/settings.blade.php index 100fb380..f79ddcd2 100644 --- a/resources/views/pages/settings.blade.php +++ b/resources/views/pages/settings.blade.php @@ -5,6 +5,7 @@
+
@@ -46,7 +47,7 @@
Labels
-
+
@@ -69,7 +70,7 @@
Seasonal Segment
-
+
@@ -208,7 +209,7 @@
Custom Segments
-
+ @@ -216,7 +217,7 @@ -
+
@@ -240,9 +241,57 @@
+
+
+
+
+
+
+
+
+ +
+
+
Milestones
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
Rewards
+
+
+
+
+
+
+
+
+ +
@@ -294,7 +343,7 @@
- +
+
+ +
+
+
+
+
+ Milestones +
+
+
+ + + + +
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+ Rewards +
+
+
+ + + + +
+
+
+
+ + + +
+
+
+
+
+
@@ -621,4 +738,4 @@
-@endsection \ No newline at end of file +@endsection diff --git a/resources/views/partials/header.blade.php b/resources/views/partials/header.blade.php index e5031575..37bdcd9a 100644 --- a/resources/views/partials/header.blade.php +++ b/resources/views/partials/header.blade.php @@ -61,6 +61,9 @@
Bank Accounts
+
+
Vouchers
+
@@ -114,4 +117,4 @@ @endif - \ No newline at end of file + diff --git a/routes/api.php b/routes/api.php index 2d820ed2..08673517 100644 --- a/routes/api.php +++ b/routes/api.php @@ -61,6 +61,10 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/accounting.php'; + require __DIR__ . '/reward.php'; + + require __DIR__ . '/milestone.php'; + // require __DIR__ . '/rate.php'; // require __DIR__ . '/receipt.php'; diff --git a/routes/milestone.php b/routes/milestone.php new file mode 100644 index 00000000..4777e8c8 --- /dev/null +++ b/routes/milestone.php @@ -0,0 +1,11 @@ + 'milestone', 'as' => 'milestone.', 'namespace' => 'Milestones'], function () { + Route::post('/create', 'CreateMilestoneController@create')->name('create'); + Route::put('/update/{id}', 'UpdateMilestoneController@update')->name('update'); + Route::get('/list', 'ListMilestonesController@list')->name('list'); + Route::get('/user/{id}/progress/list', 'ListMilestoneProgressController@list')->name('progress.list'); + Route::delete('/delete/{id}', 'DeleteMilestoneController@delete')->name('delete'); +}); diff --git a/routes/reward.php b/routes/reward.php new file mode 100644 index 00000000..c58b19f5 --- /dev/null +++ b/routes/reward.php @@ -0,0 +1,11 @@ + 'reward', 'as' => 'reward.', 'namespace' => 'Rewards'], function () { + Route::post('/create', 'CreateRewardController@create')->name('create'); + Route::get('/list', 'ListRewardsController@list')->name('list'); + Route::get('/list/details', 'ListRewardsDetailsController@list')->name('list.details'); + Route::get('/list/details/{user_id}', 'ListRewardsDetailsController@list')->name('list.details.admin'); + Route::delete('/delete/{id}', 'DeleteRewardController@delete')->name('delete'); +}); diff --git a/routes/voucher.php b/routes/voucher.php index 5b0f3b29..17c980f5 100644 --- a/routes/voucher.php +++ b/routes/voucher.php @@ -4,5 +4,7 @@ use Illuminate\Support\Facades\Route; Route::group(['prefix' => 'voucher', 'as' => 'voucher.', 'namespace' => 'Vouchers'], function () { Route::post('fetch', 'ValidateVoucherController@validate')->name('validate'); - Route::post('redeem', 'RedeemVoucherController@redeem')->name('redeem'); + Route::post('create', 'CreateVoucherController@create')->name('create'); + // Route::post('redeem', 'RedeemVoucherController@redeem')->name('redeem'); + Route::get('/user/list', 'ListUserVouchersController@list')->name('user.list'); }); diff --git a/routes/web.php b/routes/web.php index 7042b498..609b06ea 100644 --- a/routes/web.php +++ b/routes/web.php @@ -638,23 +638,32 @@ Route::get('/open-purchase-order/{marking}/{from_date}/{to_date}', function ($ma foreach ($bookings as $booking) { $booking->status = ApprovalStatus::APPROVED; $booking->save(); - + $transaction = $booking->transactions()->whereIn('type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->get(); foreach ($transaction as $key => $row) { $deletesTransaction->execute($row); } - + $document = $booking->documents()->whereIn('document_type', [DocumentType::PURCHASE_ORDER, DocumentType::INVOICE, DocumentType::DELIVER_ORDER, DocumentType::SUPPLIER_DELIVER_ORDER])->get(); foreach ($document as $key => $row) { $deletesDocument->execute($row); } - + $puchase_order = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); if($puchase_order) { $puchase_order->status = ApprovalStatus::PENDING_SUBMISSION; $puchase_order->save(); } - + dump('done - ' . $booking->marking); } -}); \ No newline at end of file +}); + +Route::get('/vouchers', function () { + return view('pages.rewards.index'); +})->name('rewards'); + +Route::get('/customer/vouchers/{marking}', function ($marking) { + $id = \App\Models\Company::where('reference', '=', $marking)->first()->employees->first()->id; + return view('pages.customers.reward', ['id' => $id]); +})->name('customer.reward');