diff --git a/src/ApiResource/AccountingApiResource.php b/src/ApiResource/Accounting/Accounting.php similarity index 85% rename from src/ApiResource/AccountingApiResource.php rename to src/ApiResource/Accounting/Accounting.php index 44d4f90..127decb 100644 --- a/src/ApiResource/AccountingApiResource.php +++ b/src/ApiResource/Accounting/Accounting.php @@ -1,14 +1,14 @@ + * @var Collection */ #[API\ApiProperty(readableLink: false, writable: false)] - #[ORM\ManyToMany(targetEntity: AccountingTransaction::class, cascade: ['persist'])] + #[ORM\ManyToMany(targetEntity: Transaction::class, cascade: ['persist'])] private Collection $transactions; public function __construct() @@ -78,24 +81,24 @@ class GatewayCharge return $this->id; } - public function getCheckout(): ?GatewayCheckout + public function getCheckout(): ?Checkout { return $this->checkout; } - public function setCheckout(?GatewayCheckout $checkout): static + public function setCheckout(?Checkout $checkout): static { $this->checkout = $checkout; return $this; } - public function getType(): ?GatewayChargeType + public function getType(): ?ChargeType { return $this->type; } - public function setType(GatewayChargeType $type): static + public function setType(ChargeType $type): static { $this->type = $type; @@ -151,14 +154,14 @@ class GatewayCharge } /** - * @return Collection + * @return Collection */ public function getTransactions(): Collection { return $this->transactions; } - public function addTransaction(AccountingTransaction $transaction): static + public function addTransaction(Transaction $transaction): static { if (!$this->transactions->contains($transaction)) { $this->transactions->add($transaction); @@ -167,7 +170,7 @@ class GatewayCharge return $this; } - public function removeTransaction(AccountingTransaction $transaction): static + public function removeTransaction(Transaction $transaction): static { $this->transactions->removeElement($transaction); diff --git a/src/Entity/GatewayChargeType.php b/src/Entity/Gateway/ChargeType.php similarity index 78% rename from src/Entity/GatewayChargeType.php rename to src/Entity/Gateway/ChargeType.php index 84c7ba1..da30858 100644 --- a/src/Entity/GatewayChargeType.php +++ b/src/Entity/Gateway/ChargeType.php @@ -1,8 +1,8 @@ 'exact', 'charges.target' => 'exact'])] -#[ORM\Entity(repositoryClass: GatewayCheckoutRepository::class)] +#[ORM\Entity(repositoryClass: CheckoutRepository::class)] #[ORM\Index(fields: ['migratedId'])] -class GatewayCheckout +class Checkout { use TimestampableCreationEntity; use TimestampableUpdationEntity; @@ -54,18 +55,18 @@ class GatewayCheckout #[API\ApiProperty(writable: false)] #[API\ApiFilter(SearchFilter::class)] #[ORM\Column()] - private ?GatewayCheckoutStatus $status = null; + private ?CheckoutStatus $status = null; /** * The GatewayCharges to be charged at checkout with the gateway. * - * @var Collection + * @var Collection */ #[API\ApiProperty(readableLink: true, writableLink: true)] #[Assert\NotBlank()] #[Assert\Count(min: 1)] #[SupportedChargeTypes()] - #[ORM\OneToMany(mappedBy: 'checkout', targetEntity: GatewayCharge::class, cascade: ['persist'])] + #[ORM\OneToMany(mappedBy: 'checkout', targetEntity: Charge::class, cascade: ['persist'])] private Collection $charges; /** @@ -81,7 +82,7 @@ class GatewayCheckout * A list of URLs provided by the Gateway for this checkout.\ * e.g: Fulfill payment, API resource address. * - * @var GatewayLink[] + * @var Link[] */ #[API\ApiProperty(writable: false)] #[ORM\Column] @@ -91,7 +92,7 @@ class GatewayCheckout * A list of tracking codes provided by the Gateway for this checkout.\ * e.g: Order ID, Payment Capture ID, Checkout Session Token. * - * @var GatewayTracking[] + * @var Tracking[] */ #[API\ApiProperty(writable: false)] #[ORM\Column] @@ -119,7 +120,7 @@ class GatewayCheckout public function __construct() { - $this->status = GatewayCheckoutStatus::Pending; + $this->status = CheckoutStatus::Pending; $this->charges = new ArrayCollection(); } @@ -140,12 +141,12 @@ class GatewayCheckout return $this; } - public function getStatus(): ?GatewayCheckoutStatus + public function getStatus(): ?CheckoutStatus { return $this->status; } - public function setStatus(GatewayCheckoutStatus $status): static + public function setStatus(CheckoutStatus $status): static { $this->status = $status; @@ -153,14 +154,14 @@ class GatewayCheckout } /** - * @return Collection + * @return Collection */ public function getCharges(): Collection { return $this->charges; } - public function addCharge(GatewayCharge $charge): static + public function addCharge(Charge $charge): static { if (!$this->charges->contains($charge)) { $this->charges->add($charge); @@ -170,7 +171,7 @@ class GatewayCheckout return $this; } - public function removeCharge(GatewayCharge $charge): static + public function removeCharge(Charge $charge): static { if ($this->charges->removeElement($charge)) { // set the owning side to null (unless already changed) @@ -195,25 +196,25 @@ class GatewayCheckout } /** - * @return GatewayLink[] + * @return Link[] */ public function getGatewayLinks(): array { return $this->gatewayLinks; } - public function addGatewayLink(GatewayLink $link): static + public function addGatewayLink(Link $link): static { $this->gatewayLinks = [...$this->gatewayLinks, $link]; return $this; } - public function removeGatewayLink(GatewayLink $link): static + public function removeGatewayLink(Link $link): static { $this->gatewayLinks = \array_filter( $this->gatewayLinks, - function (GatewayLink $existingLink) use ($link) { + function (Link $existingLink) use ($link) { return $existingLink->href !== $link->href; } ); @@ -222,25 +223,25 @@ class GatewayCheckout } /** - * @return GatewayTracking[] + * @return Tracking[] */ public function getGatewayTrackings(): array { return $this->gatewayTrackings; } - public function addGatewayTracking(GatewayTracking $tracking): static + public function addGatewayTracking(Tracking $tracking): static { $this->gatewayTrackings = [...$this->gatewayTrackings, $tracking]; return $this; } - public function removeGatewayTracking(GatewayTracking $tracking): static + public function removeGatewayTracking(Tracking $tracking): static { $this->gatewayTrackings = \array_filter( $this->gatewayTrackings, - function (GatewayTracking $existingTracking) use ($tracking) { + function (Tracking $existingTracking) use ($tracking) { return $existingTracking->title !== $tracking->title && $existingTracking->value !== $tracking->value; } diff --git a/src/Entity/GatewayCheckoutStatus.php b/src/Entity/Gateway/CheckoutStatus.php similarity index 55% rename from src/Entity/GatewayCheckoutStatus.php rename to src/Entity/Gateway/CheckoutStatus.php index 4e8bc86..a05394e 100644 --- a/src/Entity/GatewayCheckoutStatus.php +++ b/src/Entity/Gateway/CheckoutStatus.php @@ -1,8 +1,8 @@ id; } - public function getTransaction(): ?AccountingTransaction + public function getTransaction(): ?Transaction { return $this->transaction; } - public function setTransaction(AccountingTransaction $transaction): static + public function setTransaction(Transaction $transaction): static { $this->transaction = $transaction; diff --git a/src/EventListener/AccountingOwnerListener.php b/src/EventListener/AccountingOwnerListener.php index 8800aa5..eeae8a5 100644 --- a/src/EventListener/AccountingOwnerListener.php +++ b/src/EventListener/AccountingOwnerListener.php @@ -2,7 +2,7 @@ namespace App\EventListener; -use App\Entity\Accounting; +use App\Entity\Accounting\Accounting; use App\Entity\Interface\AccountingOwnerInterface; use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener; use Doctrine\ORM\EntityManagerInterface; diff --git a/src/EventListener/WalletTransactionsListener.php b/src/EventListener/WalletTransactionsListener.php index 7d7402b..3d9c4ef 100644 --- a/src/EventListener/WalletTransactionsListener.php +++ b/src/EventListener/WalletTransactionsListener.php @@ -2,7 +2,7 @@ namespace App\EventListener; -use App\Entity\AccountingTransaction; +use App\Entity\Accounting\Transaction; use App\Entity\User; use App\Library\Economy\Payment\WalletGatewayService; use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener; @@ -13,7 +13,7 @@ use Doctrine\ORM\Events; #[AsEntityListener( event: Events::postPersist, method: 'processTransaction', - entity: AccountingTransaction::class + entity: Transaction::class )] final class WalletTransactionsListener { @@ -26,7 +26,7 @@ final class WalletTransactionsListener * Generates a WalletStatement for User-received Transactions. */ public function processTransaction( - AccountingTransaction $transaction, + Transaction $transaction, PostPersistEventArgs $event, ) { $target = $transaction->getTarget(); diff --git a/src/Library/Benzina/Pump/CheckoutsPump.php b/src/Library/Benzina/Pump/CheckoutsPump.php index d56e9c6..5994973 100644 --- a/src/Library/Benzina/Pump/CheckoutsPump.php +++ b/src/Library/Benzina/Pump/CheckoutsPump.php @@ -2,11 +2,11 @@ namespace App\Library\Benzina\Pump; -use App\Entity\GatewayCharge; -use App\Entity\GatewayChargeType; -use App\Entity\GatewayCheckout; -use App\Entity\GatewayCheckoutStatus; -use App\Entity\GatewayTracking; +use App\Entity\Gateway\Charge; +use App\Entity\Gateway\ChargeType; +use App\Entity\Gateway\Checkout; +use App\Entity\Gateway\CheckoutStatus; +use App\Entity\Gateway\Tracking; use App\Entity\Money; use App\Entity\Tipjar; use App\Library\Benzina\Pump\Trait\ArrayPumpTrait; @@ -20,7 +20,7 @@ use App\Library\Economy\Payment\WalletGateway; use App\Repository\ProjectRepository; use App\Repository\TipjarRepository; use App\Repository\UserRepository; -use App\Service\GatewayCheckoutService; +use App\Service\Gateway\CheckoutService; use Doctrine\ORM\EntityManagerInterface; class CheckoutsPump extends AbstractPump implements PumpInterface @@ -78,7 +78,7 @@ class CheckoutsPump extends AbstractPump implements PumpInterface private ProjectRepository $projectRepository, private TipjarRepository $tipjarRepository, private EntityManagerInterface $entityManager, - private GatewayCheckoutService $checkoutService, + private CheckoutService $checkoutService, ) {} public function supports(mixed $batch): bool @@ -92,7 +92,7 @@ class CheckoutsPump extends AbstractPump implements PumpInterface public function pump(mixed $batch): void { - $batch = $this->skipPumped($batch, 'id', GatewayCheckout::class, 'migratedId'); + $batch = $this->skipPumped($batch, 'id', Checkout::class, 'migratedId'); $tipjar = $this->getPlatformTipjar(); @@ -114,7 +114,7 @@ class CheckoutsPump extends AbstractPump implements PumpInterface $user = $users[$record['user']]; - $checkout = new GatewayCheckout(); + $checkout = new Checkout(); $checkout->setOrigin($user->getAccounting()); $checkout->setStatus($this->getCheckoutStatus($record)); $checkout->setGateway($this->getCheckoutGateway($record)); @@ -129,7 +129,7 @@ class CheckoutsPump extends AbstractPump implements PumpInterface $checkout->setDateCreated(new \DateTime($record['invested'])); $checkout->setDateUpdated(new \DateTime()); - $charge = new GatewayCharge(); + $charge = new Charge(); $charge->setType($this->getChargeType($record)); $charge->setMoney($this->getChargeMoney($record['amount'], $record['currency'])); @@ -148,8 +148,8 @@ class CheckoutsPump extends AbstractPump implements PumpInterface $checkout->addCharge($charge); if ($record['donate_amount'] > 0) { - $tip = new GatewayCharge(); - $tip->setType(GatewayChargeType::Single); + $tip = new Charge(); + $tip->setType(ChargeType::Single); $tip->setTitle(self::CHARGE_TITLE_TIP); $tip->setMoney($this->getChargeMoney($record['donate_amount'], $record['currency'])); $tip->setTarget($tipjar->getAccounting()); @@ -157,7 +157,7 @@ class CheckoutsPump extends AbstractPump implements PumpInterface $checkout->addCharge($tip); } - if ($checkout->getStatus() === GatewayCheckoutStatus::Charged) { + if ($checkout->getStatus() === CheckoutStatus::Charged) { $checkout = $this->checkoutService->chargeCheckout($checkout); } @@ -219,13 +219,13 @@ class CheckoutsPump extends AbstractPump implements PumpInterface return $tipjar; } - private function getChargeType(array $record): GatewayChargeType + private function getChargeType(array $record): ChargeType { if (\in_array($record['method'], ['stripe_subscription'])) { - return GatewayChargeType::Recurring; + return ChargeType::Recurring; } - return GatewayChargeType::Single; + return ChargeType::Single; } private function getChargeMoney(int $amount, string $currency): Money @@ -239,13 +239,13 @@ class CheckoutsPump extends AbstractPump implements PumpInterface return new Money($amount, $currency); } - private function getCheckoutStatus(array $record): GatewayCheckoutStatus + private function getCheckoutStatus(array $record): CheckoutStatus { if ($record['status'] < 1) { - return GatewayCheckoutStatus::Pending; + return CheckoutStatus::Pending; } - return GatewayCheckoutStatus::Charged; + return CheckoutStatus::Charged; } private function getCheckoutGateway(array $record): string @@ -269,18 +269,18 @@ class CheckoutsPump extends AbstractPump implements PumpInterface } /** - * @return GatewayTracking[] + * @return Tracking[] */ private function getCheckoutTrackings(array $record): array { - $v3Tracking = new GatewayTracking(); + $v3Tracking = new Tracking(); $v3Tracking->title = self::TRACKING_TITLE_V3; $v3Tracking->value = $record['id']; $trackings = [$v3Tracking]; if (!empty($record['payment'])) { - $payment = new GatewayTracking(); + $payment = new Tracking(); $payment->title = self::TRACKING_TITLE_PAYMENT; $payment->value = $record['payment']; @@ -288,7 +288,7 @@ class CheckoutsPump extends AbstractPump implements PumpInterface } if (!empty($record['transaction'])) { - $transaction = new GatewayTracking(); + $transaction = new Tracking(); $transaction->title = self::TRACKING_TITLE_TRANSACTION; $transaction->value = $record['transaction']; @@ -296,7 +296,7 @@ class CheckoutsPump extends AbstractPump implements PumpInterface } if (!empty($record['preapproval'])) { - $preapproval = new GatewayTracking(); + $preapproval = new Tracking(); $preapproval->title = self::TRACKING_TITLE_PREAPPROVAL; $preapproval->value = $record['preapproval']; diff --git a/src/Library/Benzina/Pump/ProjectsPump.php b/src/Library/Benzina/Pump/ProjectsPump.php index b2ccf1c..dd0edb9 100644 --- a/src/Library/Benzina/Pump/ProjectsPump.php +++ b/src/Library/Benzina/Pump/ProjectsPump.php @@ -2,7 +2,7 @@ namespace App\Library\Benzina\Pump; -use App\Entity\Accounting; +use App\Entity\Accounting\Accounting; use App\Entity\Project; use App\Entity\ProjectStatus; use App\Entity\User; diff --git a/src/Library/Economy/Payment/GatewayInterface.php b/src/Library/Economy/Payment/GatewayInterface.php index 0f41ffc..29c028a 100644 --- a/src/Library/Economy/Payment/GatewayInterface.php +++ b/src/Library/Economy/Payment/GatewayInterface.php @@ -2,19 +2,19 @@ namespace App\Library\Economy\Payment; -use App\Entity\GatewayCheckout; +use App\Entity\Gateway\Checkout; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** - * Gateway interfaces are in charge of connecting with payment gateways to send them the data in `GatewayCheckout` instances.\ + * Gateway interfaces are in charge of connecting with payment gateways to send them the data in `Checkout` instances.\ * \ * The flow is: - * 1. A client app creates a `GatewayCheckout` record - * 2. `App\State\GatewayCheckoutProcessor` calls the `sendData` method of the respective interface for the new `GatewayCheckout` - * 3. The interface connects with the gateway and sends the data for the `GatewayCheckout` - * 4. The interface updates the `GatewayCheckout` with the checkout url and reference given by the gateway for the checkout session + * 1. A client app creates a `Checkout` record + * 2. `App\State\GatewayCheckoutProcessor` calls the `sendData` method of the respective interface for the new `Checkout` + * 3. The interface connects with the gateway and sends the data for the `Checkout` + * 4. The interface updates the `Checkout` with the checkout url and reference given by the gateway for the checkout session * 5. `App\State\GatewayCheckoutProcessor` returns the response data to the client app * 6. The client app redirects the user to the payment with the gateway * 7. The gateway processes the payment and redirects the user back to v4 @@ -29,18 +29,18 @@ interface GatewayInterface public static function getName(): string; /** - * @return \App\Entity\GatewayChargeType[] The charge types that can be processed by this Gateway + * @return \App\Entity\Gateway\ChargeType[] The charge types that can be processed by this Gateway */ public static function getSupportedChargeTypes(): array; /** * Connects with the payment gateway and creates a checkout session so the gateway can process the payment. * - * @param GatewayCheckout $checkout The GatewayCheckout with the data for the payment to be charged + * @param Checkout $checkout The Checkout with the data for the payment to be charged * - * @return GatewayCheckout The GatewayCheckout updated with the data given by the gateway + * @return Checkout The Checkout updated with the data given by the gateway */ - public function process(GatewayCheckout $checkout): GatewayCheckout; + public function process(Checkout $checkout): Checkout; /** * When a user is redirected by the gateway we must handle the redirection diff --git a/src/Library/Economy/Payment/PaypalGateway.php b/src/Library/Economy/Payment/PaypalGateway.php index 1f9f542..7269f1e 100644 --- a/src/Library/Economy/Payment/PaypalGateway.php +++ b/src/Library/Economy/Payment/PaypalGateway.php @@ -3,15 +3,15 @@ namespace App\Library\Economy\Payment; use ApiPlatform\Api\IriConverterInterface; -use App\Entity\GatewayCharge; -use App\Entity\GatewayChargeType; -use App\Entity\GatewayCheckout; -use App\Entity\GatewayCheckoutStatus; -use App\Entity\GatewayLink; -use App\Entity\GatewayLinkType; -use App\Entity\GatewayTracking; -use App\Repository\GatewayCheckoutRepository; -use App\Service\GatewayCheckoutService; +use App\Entity\Gateway\Charge; +use App\Entity\Gateway\ChargeType; +use App\Entity\Gateway\Checkout; +use App\Entity\Gateway\CheckoutStatus; +use App\Entity\Gateway\Link; +use App\Entity\Gateway\LinkType; +use App\Entity\Gateway\Tracking; +use App\Repository\Gateway\CheckoutRepository; +use App\Service\Gateway\CheckoutService; use Brick\Money\Money as BrickMoney; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\JsonResponse; @@ -48,8 +48,8 @@ class PaypalGateway implements GatewayInterface private RouterInterface $router, private EntityManagerInterface $entityManager, private IriConverterInterface $iriConverter, - private GatewayCheckoutService $checkoutService, - private GatewayCheckoutRepository $checkoutRepository, + private CheckoutService $checkoutService, + private CheckoutRepository $checkoutRepository, ) {} public static function getName(): string @@ -60,11 +60,11 @@ class PaypalGateway implements GatewayInterface public static function getSupportedChargeTypes(): array { return [ - GatewayChargeType::Single, + ChargeType::Single, ]; } - public function process(GatewayCheckout $checkout): GatewayCheckout + public function process(Checkout $checkout): Checkout { $order = $this->paypal->postOrder([ 'intent' => self::PAYPAL_ORDER_INTENT, @@ -72,7 +72,7 @@ class PaypalGateway implements GatewayInterface 'payment_source' => $this->getPaypalPaymentSource($checkout), ]); - $tracking = new GatewayTracking(); + $tracking = new Tracking(); $tracking->title = self::TRACKING_TITLE_ORDER; $tracking->value = $order['id']; @@ -80,10 +80,10 @@ class PaypalGateway implements GatewayInterface foreach ($order['links'] as $linkData) { $linkType = \in_array($linkData['rel'], ['approve', 'payer-action']) - ? GatewayLinkType::Payment - : GatewayLinkType::Debug; + ? LinkType::Payment + : LinkType::Debug; - $link = new GatewayLink(); + $link = new Link(); $link->href = $linkData['href']; $link->rel = $linkData['rel']; $link->method = $linkData['method']; @@ -97,7 +97,7 @@ class PaypalGateway implements GatewayInterface public function handleRedirect(Request $request): RedirectResponse { - if ($request->query->get('type') !== GatewayCheckoutService::RESPONSE_TYPE_SUCCESS) { + if ($request->query->get('type') !== CheckoutService::RESPONSE_TYPE_SUCCESS) { throw new \Exception(sprintf('Checkout was not completed successfully.')); } @@ -105,10 +105,10 @@ class PaypalGateway implements GatewayInterface $checkout = $this->checkoutRepository->find($checkoutId); if ($checkout === null) { - throw new \Exception(sprintf("GatewayCheckout '%s' could not be found.", $checkoutId)); + throw new \Exception(sprintf("Checkout '%s' could not be found.", $checkoutId)); } - if ($checkout->getStatus() === GatewayCheckoutStatus::Charged) { + if ($checkout->getStatus() === CheckoutStatus::Charged) { return new RedirectResponse($this->iriConverter->getIriFromResource($checkout)); } @@ -128,7 +128,7 @@ class PaypalGateway implements GatewayInterface } foreach ($capture['purchase_units'] as $purchaseUnit) { - $tracking = new GatewayTracking(); + $tracking = new Tracking(); $tracking->title = self::TRACKING_TITLE_TRANSACTION; $tracking->value = $purchaseUnit['payments']['captures'][0]['id']; @@ -174,11 +174,11 @@ class PaypalGateway implements GatewayInterface $checkout = $this->checkoutRepository->findOneByTracking(self::TRACKING_TITLE_ORDER, $orderId); if ($checkout === null) { - throw new \Exception(sprintf("Could not find any GatewayCheckout by the GatewayTracking '%s'", $orderId), 1); + throw new \Exception(sprintf("Could not find any Checkout by the Tracking '%s'", $orderId), 1); } foreach ($event['resource']['purchase_units'] as $purchaseUnit) { - $tracking = new GatewayTracking(); + $tracking = new Tracking(); $tracking->title = self::TRACKING_TITLE_TRANSACTION; $tracking->value = $purchaseUnit['payments']['captures'][0]['id']; @@ -188,7 +188,7 @@ class PaypalGateway implements GatewayInterface $checkout = $this->checkoutService->chargeCheckout($checkout); } - private function getPaypalMoney(GatewayCharge $charge): array + private function getPaypalMoney(Charge $charge): array { $brick = BrickMoney::ofMinor( $charge->getMoney()->amount, @@ -201,7 +201,7 @@ class PaypalGateway implements GatewayInterface ]; } - private function getPaypalPurchaseUnits(GatewayCheckout $checkout): array + private function getPaypalPurchaseUnits(Checkout $checkout): array { $units = []; @@ -236,7 +236,7 @@ class PaypalGateway implements GatewayInterface return $units; } - private function getPaypalPaymentSource(GatewayCheckout $checkout): array + private function getPaypalPaymentSource(Checkout $checkout): array { return [ 'paypal' => [ diff --git a/src/Library/Economy/Payment/StripeGateway.php b/src/Library/Economy/Payment/StripeGateway.php index 5060537..4a79510 100644 --- a/src/Library/Economy/Payment/StripeGateway.php +++ b/src/Library/Economy/Payment/StripeGateway.php @@ -3,14 +3,16 @@ namespace App\Library\Economy\Payment; use ApiPlatform\Api\IriConverterInterface; -use App\Entity\GatewayChargeType; -use App\Entity\GatewayCheckout; -use App\Entity\GatewayCheckoutStatus; -use App\Entity\GatewayLink; -use App\Entity\GatewayLinkType; -use App\Entity\GatewayTracking; -use App\Repository\GatewayCheckoutRepository; -use App\Service\GatewayCheckoutService; +use App\Entity\Gateway\ChargeType; +use App\Entity\Gateway\Checkout; +use App\Entity\Gateway\CheckoutStatus; +use App\Entity\Gateway\Link; +use App\Entity\Gateway\LinkType; +use App\Entity\Gateway\Tracking; +use App\Entity\User; +use App\Repository\Gateway\CheckoutRepository; +use App\Repository\UserRepository; +use App\Service\Gateway\CheckoutService; use Doctrine\ORM\EntityManagerInterface; use Stripe\Checkout\Session as StripeSession; use Stripe\StripeClient; @@ -31,8 +33,9 @@ class StripeGateway implements GatewayInterface private string $stripeApiKey, private string $stripeWebhookSecret, private RouterInterface $router, - private GatewayCheckoutService $checkoutService, - private GatewayCheckoutRepository $checkoutRepository, + private CheckoutService $checkoutService, + private CheckoutRepository $checkoutRepository, + private UserRepository $userRepository, private EntityManagerInterface $entityManager, private IriConverterInterface $iriConverter, ) { @@ -47,15 +50,15 @@ class StripeGateway implements GatewayInterface public static function getSupportedChargeTypes(): array { return [ - GatewayChargeType::Single, - GatewayChargeType::Recurring, + ChargeType::Single, + ChargeType::Recurring, ]; } - public function process(GatewayCheckout $checkout): GatewayCheckout + public function process(Checkout $checkout): Checkout { $session = $this->stripe->checkout->sessions->create([ - 'customer_email' => $checkout->getOrigin()->getUser()->getEmail(), + 'customer_email' => $this->getStripeCustomer($checkout), 'mode' => $this->getStripeMode($checkout), 'line_items' => $this->getStripeLineItems($checkout), // Because Symfony's Router encodes query parameters, the value {CHECKOUT_SESSION_ID} @@ -65,16 +68,16 @@ class StripeGateway implements GatewayInterface 'success_url' => sprintf('%s&session_id={CHECKOUT_SESSION_ID}', $this->checkoutService->generateRedirectUrl($checkout)), ]); - $link = new GatewayLink(); + $link = new Link(); $link->href = $session->url; $link->rel = 'approve'; $link->method = Request::METHOD_GET; - $link->type = GatewayLinkType::Payment; + $link->type = LinkType::Payment; $checkout->addGatewayLink($link); - $tracking = new GatewayTracking(); + $tracking = new Tracking(); $tracking->title = self::TRACKING_TITLE_CHECKOUT; $tracking->value = $session->id; @@ -91,14 +94,14 @@ class StripeGateway implements GatewayInterface $checkout = $this->checkoutRepository->find($request->query->get('checkoutId')); if ($checkout === null) { - throw new \Exception(sprintf("Stripe checkout '%s' exists but no GatewayCheckout with that reference was found.", $sessionId)); + throw new \Exception(sprintf("Stripe checkout '%s' exists but no Checkout with that reference was found.", $sessionId)); } - if ($checkout->getStatus() === GatewayCheckoutStatus::Charged) { + if ($checkout->getStatus() === CheckoutStatus::Charged) { return $checkout; } - if ($request->query->get('type') !== GatewayCheckoutService::RESPONSE_TYPE_SUCCESS) { + if ($request->query->get('type') !== CheckoutService::RESPONSE_TYPE_SUCCESS) { return $checkout; } @@ -132,10 +135,21 @@ class StripeGateway implements GatewayInterface } } - private function getStripeMode(GatewayCheckout $checkout): string + private function getStripeCustomer(Checkout $checkout): string + { + if ($checkout->getOrigin()->getOwnerClass() !== User::class) { + return ''; + } + + $user = $this->userRepository->find($checkout->getOrigin()->getOwnerId()); + + return $user->getEmail(); + } + + private function getStripeMode(Checkout $checkout): string { foreach ($checkout->getCharges() as $charge) { - if ($charge->getType() === GatewayChargeType::Recurring) { + if ($charge->getType() === ChargeType::Recurring) { return StripeSession::MODE_SUBSCRIPTION; } } @@ -143,7 +157,7 @@ class StripeGateway implements GatewayInterface return StripeSession::MODE_PAYMENT; } - private function getStripeLineItems(GatewayCheckout $checkout): array + private function getStripeLineItems(Checkout $checkout): array { $items = []; @@ -157,7 +171,7 @@ class StripeGateway implements GatewayInterface ], ]; - if ($charge->getType() === GatewayChargeType::Recurring) { + if ($charge->getType() === ChargeType::Recurring) { $price['recurring'] = ['interval' => 'month']; } diff --git a/src/Library/Economy/Payment/WalletGateway.php b/src/Library/Economy/Payment/WalletGateway.php index 4167a77..7dc363f 100644 --- a/src/Library/Economy/Payment/WalletGateway.php +++ b/src/Library/Economy/Payment/WalletGateway.php @@ -2,9 +2,9 @@ namespace App\Library\Economy\Payment; -use App\Entity\AccountingTransaction; -use App\Entity\GatewayChargeType; -use App\Entity\GatewayCheckout; +use App\Entity\Accounting\Transaction; +use App\Entity\Gateway\ChargeType; +use App\Entity\Gateway\Checkout; use App\Entity\Money; use App\Entity\WalletStatement; use App\Entity\WalletStatementDirection; @@ -23,7 +23,7 @@ class WalletGateway implements GatewayInterface public static function getSupportedChargeTypes(): array { return [ - GatewayChargeType::Single, + ChargeType::Single, ]; } @@ -32,7 +32,7 @@ class WalletGateway implements GatewayInterface private MoneyService $money, ) {} - public function process(GatewayCheckout $checkout): GatewayCheckout + public function process(Checkout $checkout): Checkout { $origin = $checkout->getOrigin(); $available = $this->wallet->getBalance($origin); @@ -44,7 +44,7 @@ class WalletGateway implements GatewayInterface $charges = $checkout->getCharges(); foreach ($charges as $charge) { - $transaction = new AccountingTransaction(); + $transaction = new Transaction(); $transaction->setMoney($charge->getMoney()); $transaction->setOrigin($origin); $transaction->setTarget($charge->getTarget()); @@ -69,7 +69,7 @@ class WalletGateway implements GatewayInterface return new Response(); } - private function getChargeTotal(GatewayCheckout $checkout): Money + private function getChargeTotal(Checkout $checkout): Money { $total = new Money(0, $checkout->getOrigin()->getCurrency()); diff --git a/src/Library/Economy/Payment/WalletGatewayService.php b/src/Library/Economy/Payment/WalletGatewayService.php index 4cec990..ffc7ddd 100644 --- a/src/Library/Economy/Payment/WalletGatewayService.php +++ b/src/Library/Economy/Payment/WalletGatewayService.php @@ -2,8 +2,8 @@ namespace App\Library\Economy\Payment; -use App\Entity\Accounting; -use App\Entity\AccountingTransaction; +use App\Entity\Accounting\Accounting; +use App\Entity\Accounting\Transaction; use App\Entity\Money; use App\Entity\WalletStatement; use App\Entity\WalletStatementDirection; @@ -52,11 +52,11 @@ class WalletGatewayService /** * Puts the money of a Transaction into the target wallet. * - * @param AccountingTransaction $transaction The Transaction targetting a wallet + * @param Transaction $transaction The Transaction targetting a wallet * * @return WalletStatement An incoming statement for the target wallet */ - public function save(AccountingTransaction $transaction): WalletStatement + public function save(Transaction $transaction): WalletStatement { $statement = new WalletStatement(); $statement->setTransaction($transaction); @@ -72,11 +72,11 @@ class WalletGatewayService /** * Takes the money of a Transaction from the origin wallet. * - * @param AccountingTransaction $transaction The Transaction originating from a wallet + * @param Transaction $transaction The Transaction originating from a wallet * * @return WalletStatement An outgoing statement financed by previous incoming statements */ - public function spend(AccountingTransaction $transaction): WalletStatement + public function spend(Transaction $transaction): WalletStatement { $origin = $transaction->getOrigin(); diff --git a/src/Repository/AccountingRepository.php b/src/Repository/Accounting/AccountingRepository.php similarity index 95% rename from src/Repository/AccountingRepository.php rename to src/Repository/Accounting/AccountingRepository.php index c32c81e..d871046 100644 --- a/src/Repository/AccountingRepository.php +++ b/src/Repository/Accounting/AccountingRepository.php @@ -1,8 +1,8 @@ + * @extends ServiceEntityRepository * - * @method AccountingTransaction|null find($id, $lockMode = null, $lockVersion = null) - * @method AccountingTransaction|null findOneBy(array $criteria, array $orderBy = null) - * @method AccountingTransaction[] findAll() - * @method AccountingTransaction[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @method Transaction|null find($id, $lockMode = null, $lockVersion = null) + * @method Transaction|null findOneBy(array $criteria, array $orderBy = null) + * @method Transaction[] findAll() + * @method Transaction[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class AccountingTransactionRepository extends ServiceEntityRepository +class TransactionRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { - parent::__construct($registry, AccountingTransaction::class); + parent::__construct($registry, Transaction::class); } // /** - // * @return AccountingTransaction[] Returns an array of AccountingTransaction objects + // * @return Transaction[] Returns an array of Transaction objects // */ // public function findByExampleField($value): array // { @@ -36,7 +36,7 @@ class AccountingTransactionRepository extends ServiceEntityRepository // ; // } - // public function findOneBySomeField($value): ?AccountingTransaction + // public function findOneBySomeField($value): ?Transaction // { // return $this->createQueryBuilder('t') // ->andWhere('t.exampleField = :val') diff --git a/src/Repository/GatewayChargeRepository.php b/src/Repository/Gateway/ChargeRepository.php similarity index 56% rename from src/Repository/GatewayChargeRepository.php rename to src/Repository/Gateway/ChargeRepository.php index 9748d28..c8a196c 100644 --- a/src/Repository/GatewayChargeRepository.php +++ b/src/Repository/Gateway/ChargeRepository.php @@ -1,28 +1,28 @@ + * @extends ServiceEntityRepository * - * @method GatewayCharge|null find($id, $lockMode = null, $lockVersion = null) - * @method GatewayCharge|null findOneBy(array $criteria, array $orderBy = null) - * @method GatewayCharge[] findAll() - * @method GatewayCharge[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @method Charge|null find($id, $lockMode = null, $lockVersion = null) + * @method Charge|null findOneBy(array $criteria, array $orderBy = null) + * @method Charge[] findAll() + * @method Charge[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class GatewayChargeRepository extends ServiceEntityRepository +class ChargeRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { - parent::__construct($registry, GatewayCharge::class); + parent::__construct($registry, Charge::class); } // /** - // * @return GatewayCharge[] Returns an array of GatewayCharge objects + // * @return Charge[] Returns an array of Charge objects // */ // public function findByExampleField($value): array // { @@ -36,7 +36,7 @@ class GatewayChargeRepository extends ServiceEntityRepository // ; // } - // public function findOneBySomeField($value): ?GatewayCharge + // public function findOneBySomeField($value): ?Charge // { // return $this->createQueryBuilder('g') // ->andWhere('g.exampleField = :val') diff --git a/src/Repository/GatewayCheckoutRepository.php b/src/Repository/Gateway/CheckoutRepository.php similarity index 65% rename from src/Repository/GatewayCheckoutRepository.php rename to src/Repository/Gateway/CheckoutRepository.php index 9d8ee48..ad73efa 100644 --- a/src/Repository/GatewayCheckoutRepository.php +++ b/src/Repository/Gateway/CheckoutRepository.php @@ -1,29 +1,29 @@ + * @extends ServiceEntityRepository * - * @method GatewayCheckout|null find($id, $lockMode = null, $lockVersion = null) - * @method GatewayCheckout|null findOneBy(array $criteria, array $orderBy = null) - * @method GatewayCheckout[] findAll() - * @method GatewayCheckout[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + * @method Checkout|null find($id, $lockMode = null, $lockVersion = null) + * @method Checkout|null findOneBy(array $criteria, array $orderBy = null) + * @method Checkout[] findAll() + * @method Checkout[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class GatewayCheckoutRepository extends ServiceEntityRepository +class CheckoutRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { - parent::__construct($registry, GatewayCheckout::class); + parent::__construct($registry, Checkout::class); } /** - * @return GatewayCheckout|null + * @return Checkout|null */ public function findOneByTracking(string $title, string $value): array { @@ -39,7 +39,7 @@ class GatewayCheckoutRepository extends ServiceEntityRepository } // /** - // * @return GatewayCheckout[] Returns an array of GatewayCheckout objects + // * @return Checkout[] Returns an array of Checkout objects // */ // public function findByExampleField($value): array // { @@ -53,7 +53,7 @@ class GatewayCheckoutRepository extends ServiceEntityRepository // ; // } - // public function findOneBySomeField($value): ?GatewayCheckout + // public function findOneBySomeField($value): ?Checkout // { // return $this->createQueryBuilder('g') // ->andWhere('g.exampleField = :val') diff --git a/src/Repository/ProjectRepository.php b/src/Repository/ProjectRepository.php index a1a9495..ffd8d5e 100644 --- a/src/Repository/ProjectRepository.php +++ b/src/Repository/ProjectRepository.php @@ -2,7 +2,7 @@ namespace App\Repository; -use App\Entity\Accounting; +use App\Entity\Accounting\Accounting; use App\Entity\Project; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index bc4abf3..31bb5e7 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -2,7 +2,7 @@ namespace App\Repository; -use App\Entity\Accounting; +use App\Entity\Accounting\Accounting; use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; diff --git a/src/Repository/WalletStatementRepository.php b/src/Repository/WalletStatementRepository.php index 5277a5e..8987513 100644 --- a/src/Repository/WalletStatementRepository.php +++ b/src/Repository/WalletStatementRepository.php @@ -2,7 +2,7 @@ namespace App\Repository; -use App\Entity\Accounting; +use App\Entity\Accounting\Accounting; use App\Entity\WalletStatement; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\Query\Expr\Join; diff --git a/src/Security/Voter/AccountingVoter.php b/src/Security/Voter/AccountingVoter.php index 77ce9c8..eccd006 100644 --- a/src/Security/Voter/AccountingVoter.php +++ b/src/Security/Voter/AccountingVoter.php @@ -14,7 +14,7 @@ class AccountingVoter extends Voter protected function supports(string $attribute, mixed $subject): bool { return in_array($attribute, [self::EDIT]) - && $subject instanceof \App\Entity\Accounting; + && $subject instanceof \App\Entity\Accounting\Accounting; } protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool diff --git a/src/Service/GatewayCheckoutService.php b/src/Service/Gateway/CheckoutService.php similarity index 70% rename from src/Service/GatewayCheckoutService.php rename to src/Service/Gateway/CheckoutService.php index 0d5efaa..2ad5ac7 100644 --- a/src/Service/GatewayCheckoutService.php +++ b/src/Service/Gateway/CheckoutService.php @@ -1,15 +1,15 @@ setStatus(GatewayCheckoutStatus::Charged); + $checkout->setStatus(CheckoutStatus::Charged); foreach ($checkout->getCharges() as $charge) { - $transaction = new AccountingTransaction(); + $transaction = new Transaction(); $transaction->setMoney($charge->getMoney()); $transaction->setOrigin($checkout->getOrigin()); $transaction->setTarget($charge->getTarget()); diff --git a/src/State/AccountingStateProcessor.php b/src/State/Accounting/AccountingStateProcessor.php similarity index 93% rename from src/State/AccountingStateProcessor.php rename to src/State/Accounting/AccountingStateProcessor.php index f2e65c7..1645b65 100644 --- a/src/State/AccountingStateProcessor.php +++ b/src/State/Accounting/AccountingStateProcessor.php @@ -1,11 +1,11 @@ */ + /** @var Collection */ $charges = $value; $checkout = $charges->toArray()[0]->getCheckout(); diff --git a/tests/Entity/AccountingTest.php b/tests/Entity/Accounting/AccountingTest.php similarity index 95% rename from tests/Entity/AccountingTest.php rename to tests/Entity/Accounting/AccountingTest.php index 89aa398..4946e70 100644 --- a/tests/Entity/AccountingTest.php +++ b/tests/Entity/Accounting/AccountingTest.php @@ -1,8 +1,8 @@ assertEquals(0, $balance->amount); $this->assertEquals($user->getCurrency(), $balance->currency); - $incoming = new AccountingTransaction(); + $incoming = new Transaction(); $incoming->setMoney(new Money(100, 'EUR')); $incoming->setOrigin($tipjar); $incoming->setTarget($user); @@ -101,7 +101,7 @@ class WalletGatewayServiceTest extends KernelTestCase $tipjar = $this->getTipjar()->getAccounting(); $user = $this->getUser()->getAccounting(); - $incoming = new AccountingTransaction(); + $incoming = new Transaction(); $incoming->setMoney(new Money(100, 'EUR')); $incoming->setOrigin($tipjar); $incoming->setTarget($user); @@ -109,7 +109,7 @@ class WalletGatewayServiceTest extends KernelTestCase $this->entityManager->persist($incoming); $this->entityManager->flush(); - $outgoing = new AccountingTransaction(); + $outgoing = new Transaction(); $outgoing->setMoney(new Money(20, 'EUR')); $outgoing->setOrigin($user); $outgoing->setTarget($tipjar); @@ -139,7 +139,7 @@ class WalletGatewayServiceTest extends KernelTestCase $this->assertCount(0, $statement->getFinancesTo()); $this->assertCount(1, $statement->getFinancedBy()); - $outgoing = new AccountingTransaction(); + $outgoing = new Transaction(); $outgoing->setMoney(new Money(30, 'EUR')); $outgoing->setOrigin($user); $outgoing->setTarget($tipjar); @@ -182,7 +182,7 @@ class WalletGatewayServiceTest extends KernelTestCase $tipjar = $this->getTipjar()->getAccounting(); $user = $this->getUser()->getAccounting(); - $incoming = new AccountingTransaction(); + $incoming = new Transaction(); $incoming->setMoney(new Money(10, 'EUR')); $incoming->setOrigin($tipjar); $incoming->setTarget($user); @@ -190,7 +190,7 @@ class WalletGatewayServiceTest extends KernelTestCase $this->entityManager->persist($incoming); $this->entityManager->flush(); - $incoming = new AccountingTransaction(); + $incoming = new Transaction(); $incoming->setMoney(new Money(10, 'EUR')); $incoming->setOrigin($tipjar); $incoming->setTarget($user); @@ -198,14 +198,14 @@ class WalletGatewayServiceTest extends KernelTestCase $this->entityManager->persist($incoming); $this->entityManager->flush(); - $outgoing = new AccountingTransaction(); + $outgoing = new Transaction(); $outgoing->setMoney(new Money(15, 'EUR')); $outgoing->setOrigin($user); $outgoing->setTarget($tipjar); $this->walletService->spend($outgoing); - $incoming = new AccountingTransaction(); + $incoming = new Transaction(); $incoming->setMoney(new Money(5, 'EUR')); $incoming->setOrigin($tipjar); $incoming->setTarget($user);