Last active
February 1, 2022 14:13
-
-
Save Ensive/cdc46f7a941689fe9ae0eff6328e6f1d to your computer and use it in GitHub Desktop.
BuyTradingSchoolCourseCommand.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| declare(strict_types=1); | |
| namespace Fndx\Application\UseCase\TradingSchoolCourse; | |
| use Fndx\Application\UseCase\AbstractCommand; | |
| use Fndx\Domain\Permission\AggregateRoot\Permission; | |
| use Fndx\Infrastructure\Core\Exception\AccessNotAllowedException; | |
| use Fndx\Domain\Permission\Contract\PermissionServiceInterface; | |
| use Fndx\Infrastructure\Transaction\DTO\Response\TransactionResponseDTO; | |
| use Fndx\Infrastructure\Transaction\Transformer\TransactionResponseDTOTransformer; | |
| use Fndx\Domain\Identity\Exception\IdentityNotFoundException; | |
| use Fndx\Domain\TradingSchoolCourse\Contract\TradingSchoolCourseServiceInterface; | |
| use Fndx\Infrastructure\TradingSchoolCourse\DTO\Request\BuyTradingSchoolCourseRequestDTO; | |
| use Fndx\Infrastructure\Transaction\DTO\Request\CreateTransactionRequestDTO; | |
| use Fndx\Domain\Client\Contract\ClientServiceInterface; | |
| use Fndx\Domain\PersonalAccount\Contract\PersonalAccountServiceInterface; | |
| use Fndx\Domain\SystemAccount\Contract\SystemAccountServiceInterface; | |
| use Fndx\Domain\Transaction\Contract\TransactionServiceInterface; | |
| use Fndx\Domain\Transaction\AggregateRoot\Transaction; | |
| use Fndx\Domain\PaymentMethod\AggregateRoot\PaymentMethod; | |
| use Fndx\Domain\Permission\Exception\PermissionNotFoundException; | |
| use Fndx\Domain\Client\Exception\ClientNotFoundException; | |
| use Fndx\Domain\Money\Exception\AmountCannotBeZeroException; | |
| use Fndx\Domain\Money\Exception\NegativeAmountException; | |
| use Fndx\Domain\Money\Exception\NotEnoughBalanceException; | |
| use Fndx\Domain\PaymentMethod\Exception\InvalidPaymentMethodException; | |
| use Fndx\Domain\PersonalAccount\Exception\PersonalAccountNotFoundException; | |
| use Fndx\Domain\Transaction\Exception\InvalidTransactionCreationTypeException; | |
| use Fndx\Domain\Transaction\Exception\InvalidTransactionStatusException; | |
| use Fndx\Domain\Transaction\Exception\InvalidTransactionTypeException; | |
| use Fndx\Domain\TradingSchoolCourse\Exception\TradingSchoolCourseAlreadyPurchasedException; | |
| use Fndx\Infrastructure\SystemAccount\Repository\SystemAccountPostgresqlRepository; | |
| use Fndx\Domain\Transaction\ValueObject\TransactionCreationType; | |
| use Fndx\Domain\Transaction\ValueObject\TransactionStatus; | |
| use Fndx\Domain\Transaction\ValueObject\TransactionType; | |
| use function Fndx\Infrastructure\Helpers\map; | |
| class BuyTradingSchoolCourseCommand extends AbstractCommand | |
| { | |
| protected const TARGET_PERMISSION = Permission::TRADING_SCHOOL_COURSE_BUY; | |
| protected TradingSchoolCourseServiceInterface $courseService; | |
| protected ClientServiceInterface $clientService; | |
| protected PersonalAccountServiceInterface $personalAccountService; | |
| protected SystemAccountServiceInterface $systemAccountService; | |
| protected TransactionServiceInterface $transactionService; | |
| protected PermissionServiceInterface $permissionService; | |
| /** | |
| * @param TradingSchoolCourseServiceInterface $courseService | |
| * @param ClientServiceInterface $clientService | |
| * @param PersonalAccountServiceInterface $personalAccountService | |
| * @param SystemAccountServiceInterface $systemAccountService | |
| * @param TransactionServiceInterface $transactionService | |
| * @param PermissionServiceInterface $permissionService | |
| */ | |
| public function __construct( | |
| ClientServiceInterface $clientService, | |
| TradingSchoolCourseServiceInterface $courseService, | |
| PersonalAccountServiceInterface $personalAccountService, | |
| SystemAccountServiceInterface $systemAccountService, | |
| TransactionServiceInterface $transactionService, | |
| PermissionServiceInterface $permissionService | |
| ) { | |
| parent::__construct(); | |
| $this->clientService = $clientService; | |
| $this->courseService = $courseService; | |
| $this->personalAccountService = $personalAccountService; | |
| $this->systemAccountService = $systemAccountService; | |
| $this->transactionService = $transactionService; | |
| $this->permissionService = $permissionService; | |
| } | |
| /** | |
| * @param string $tradingSchoolCourseWpId | |
| * @param BuyTradingSchoolCourseRequestDTO $payload | |
| * | |
| * @return TransactionResponseDTO | |
| * @throws IdentityNotFoundException | |
| * @throws AmountCannotBeZeroException | |
| * @throws ClientNotFoundException | |
| * @throws InvalidPaymentMethodException | |
| * @throws InvalidTransactionCreationTypeException | |
| * @throws InvalidTransactionStatusException | |
| * @throws InvalidTransactionTypeException | |
| * @throws NegativeAmountException | |
| * @throws NotEnoughBalanceException | |
| * @throws PersonalAccountNotFoundException | |
| * @throws PermissionNotFoundException | |
| * @throws TradingSchoolCourseAlreadyPurchasedException | |
| * @throws AccessNotAllowedException | |
| */ | |
| // TODO: this doesn't work, fixes required | |
| // TODO: what is better name for tradingSchoolCourseWpId ? | |
| public function run( | |
| string $tradingSchoolCourseWpId, | |
| BuyTradingSchoolCourseRequestDTO $payload | |
| ): TransactionResponseDTO { | |
| $this->checkPermission(); | |
| $performerIdentity = $this->getPerformerIdentity(); | |
| if ($performerIdentity->can($payload->permissionKey, $performerIdentity->id())) { | |
| throw new TradingSchoolCourseAlreadyPurchasedException(); | |
| } | |
| $client = $this->clientService->getByIdentityId($performerIdentity->id()); | |
| $course = $this->courseService->getByWpId($tradingSchoolCourseWpId); | |
| $personalAccount = $this->personalAccountService->getByClientId($client->id()); | |
| $systemAccount = $this->systemAccountService->getSystemAccount(); | |
| // TODO: wrap the following code into database SQL transaction | |
| // update personal account balance | |
| $personalAccount->withdraw($course->price()->amount()); | |
| $this->personalAccountService->save($personalAccount); | |
| // update system account balance | |
| $systemAccount->topUp($course->price()->amount()); | |
| $this->systemAccountService->save($systemAccount); | |
| // todo: do we add "description" ? | |
| $transactionDto = map(CreateTransactionRequestDTO::class)->from( | |
| [ | |
| 'clientId' => $client->id(), | |
| 'type' => TransactionType::PURCHASE, | |
| 'status' => TransactionStatus::COMPLETED, | |
| 'amount' => $course->price()->amount(), | |
| 'creationType' => TransactionCreationType::AUTO, | |
| 'productId' => $course->productId(), | |
| 'fromPaymentMethodId' => PaymentMethod::PERSONAL_ACCOUNT, | |
| 'fromSourceId' => $client->id(), | |
| 'toPaymentMethodId' => PaymentMethod::SYSTEM_ACCOUNT, | |
| 'toSourceId' => SystemAccountPostgresqlRepository::SYSTEM_ACCOUNT_ID, | |
| ] | |
| ); | |
| // TODO: test | |
| $transaction = $this->transactionService->create($transactionDto, $performerIdentity->id()); | |
| $this->transactionService->save($transaction); | |
| // set permission after everything is successful | |
| $permission = $this->permissionService->getByKey($payload->permissionKey); | |
| // TODO: shall we rework this to identityService->addPermission or $this->getPerformerIdentity()->addPermission() | |
| $this->permissionService->setPermission($performerIdentity->id(), $permission->id()); | |
| return map(TransactionResponseDTO::class)->from( | |
| $transaction, | |
| fn(Transaction $transaction) => TransactionResponseDTOTransformer::transform($transaction) | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment