<?php
namespace App\EventSubscriber\Package;
use App\DTO\MMPZ\PaymentMethod\PaymentGatewayAuthorizationDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\PaypalCurrencyDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\PaypalProductDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PaypalPlanBillingCyclesDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PaypalPlanDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PaypalPlanFrequencyDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PaypalPlanPaymentPreferenceDTO;
use App\DTO\MMPZ\PaymentMethod\Paypal\Plan\PayPalPlanPricingSchemeDTO;
use App\DTO\Request\UserPayloadMMAZ;
use App\Entity\Logs\EventLog;
use App\Entity\Package\Invoice;
use App\Entity\Package\Package;
use App\Entity\Package\PackageSongWriter;
use App\Entity\Package\PackageTransaction;
use App\Entity\Package\ReactivationAttempts;
use App\Entity\Profile\Profile;
use App\Entity\Profile\ProfileRBAC;
use App\Entity\User\User;
use App\Enums\Constants;
use App\Enums\PackageSongwriterStatus;
use App\Enums\PackageType;
use App\Enums\TransactionPlatform;
use App\Event\LogEvent;
use App\Event\Package\PackageCreatedEvent;
use App\Event\Package\PackageDeletedEvent;
use App\Event\Package\PackagePurchasedEvent;
use App\Event\Package\PackageTransactionApprovedEvent;
use App\Event\Package\PackageTransactionSubscriptionCanceledEvent;
use App\Event\Package\PackageTransactionSubscriptionInactivatedEvent;
use App\Event\Package\PackageTransactionSubscriptionReactivatedEvent;
use App\Event\Package\PackageUpdatedEvent;
use App\Repository\Package\InvoiceRepository;
use App\Repository\Package\PackageRepository;
use App\Repository\Package\PackageSongwriterRepository;
use App\Repository\Profile\InvitationRepository;
use App\Service\AuthenticationService;
use App\Service\Mailer\PackageMailer;
use App\Service\PackageService;
use App\Service\PaymentMethod\Paypal\PaypalService;
use App\Service\PaymentMethod\Stripe\StripeService;
use App\Service\ProfileService;
use Stripe\Subscription;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Serializer\SerializerInterface;
class PackageSubscriber implements EventSubscriberInterface
{
/** @var SerializerInterface */
private $serializer;
/**
* @var AuthenticationService
*/
private $authenticationService;
/** @var EventDispatcherInterface */
private $eventDispatcher;
/** @var PackageSongwriterRepository */
private $packageSongwriterRepository;
/** @var ProfileService */
private $profileService;
/** @var PackageMailer */
private $packageMailer;
/** @var PackageService */
private $packageService;
public function __construct(
SerializerInterface $serializer,
AuthenticationService $authenticationService,
EventDispatcherInterface $eventDispatcher,
PackageSongwriterRepository $packageSongwriterRepository,
ProfileService $profileService,
PackageMailer $packageMailer,
PackageService $packageService
)
{
$this->serializer = $serializer;
$this->authenticationService = $authenticationService;
$this->eventDispatcher = $eventDispatcher;
$this->packageSongwriterRepository = $packageSongwriterRepository;
$this->profileService = $profileService;
$this->packageMailer = $packageMailer;
$this->packageService = $packageService;
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents(): array
{
return [
PackageCreatedEvent::class => 'onPackageCreatedEvent',
PackageUpdatedEvent::class => 'onPackageUpdatedEvent',
PackageDeletedEvent::class => 'onPackageDeletedEvent',
PackagePurchasedEvent::class => 'onPackagePurchasedEvent',
PackageTransactionApprovedEvent::class => 'onPackageTransactionApprovedEvent',
PackageTransactionSubscriptionCanceledEvent::class => 'onPackageTransactionSubscriptionCanceledEvent',
PackageTransactionSubscriptionInactivatedEvent::class => 'onPackageTransactionSubscriptionInactivatedEvent',
PackageTransactionSubscriptionReactivatedEvent::class => 'onPackageTransactionSubscriptionReactivatedEvent',
];
}
/**
* @param PackageCreatedEvent $event
* @return void
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Stripe\Exception\ApiErrorException
*/
public function onPackageCreatedEvent(PackageCreatedEvent $event): void
{
$type = "";
if($event->getPackage()->getType() === PackageType::PRIMARY){
$type = EventLog::TYPE_PACKAGE_CREATED;
}else if($event->getPackage()->getType() === PackageType::SUBSCRIPTION){
$type = EventLog::TYPE_SUBSCRIPTION_CREATED;
}
$this->eventDispatcher->dispatch(new LogEvent($event->getPackage(), $this->authenticationService->getUser(), $type));
}
/**
* @param PackageUpdatedEvent $event
*/
public function onPackageUpdatedEvent(PackageUpdatedEvent $event): void
{
$type = "";
if($event->getPackage()->getType() === PackageType::PRIMARY){
$type = EventLog::TYPE_PACKAGE_UPDATED;
}else if($event->getPackage()->getType() === PackageType::SUBSCRIPTION){
$type = EventLog::TYPE_SUBSCRIPTION_UPDATED;
}
$this->eventDispatcher->dispatch(new LogEvent($event->getPackage(), $this->authenticationService->getUser(), $type));
}
/**
* @param PackageDeletedEvent $event
*/
public function onPackageDeletedEvent(PackageDeletedEvent $event): void
{
$type = "";
if($event->getPackage()->getType() === PackageType::PRIMARY){
$type = EventLog::TYPE_PACKAGE_DELETED;
}else if($event->getPackage()->getType() === PackageType::SUBSCRIPTION){
$type = EventLog::TYPE_SUBSCRIPTION_DELETED;
}
$this->eventDispatcher->dispatch(new LogEvent($event->getPackage(), $this->authenticationService->getUser(), $type));
}
/**
* @param PackagePurchasedEvent $event
*/
public function onPackagePurchasedEvent(PackagePurchasedEvent $event): void
{
$type = "";
if($event->getPackage()->getType() === PackageType::PRIMARY){
$type = EventLog::TYPE_PACKAGE_PURCHASED;
}else if($event->getPackage()->getType() === PackageType::SUBSCRIPTION){
$type = EventLog::TYPE_SUBSCRIPTION_PURCHASED;
}
$this->packageMailer->sendPackageSubcriptionPurchasedEmails($this->authenticationService->getUser(), $event->getMessage());
$this->eventDispatcher->dispatch(new LogEvent($event->getPackage(), $this->authenticationService->getUser(), $type));
}
/**
* @param PackageTransactionApprovedEvent $packageTransactionApprovedEvent
* @return void
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Stripe\Exception\ApiErrorException
*/
public function onPackageTransactionApprovedEvent(PackageTransactionApprovedEvent $packageTransactionApprovedEvent)
{
$packageTransaction = $packageTransactionApprovedEvent->getPackageTransaction();
/** @var PackageSongWriter $packageSongwriter */
$packageSongwriter = $this->packageSongwriterRepository->findOneBy(['packageTransaction' => $packageTransaction]);
if(is_null($packageSongwriter)){
throw new BadRequestHttpException("Package transaction {$packageTransaction->getId()} does not have a Songwriter");
}
$type = "";
$invoiceType = "";
if($packageTransaction->getPackage()->getType() === PackageType::PRIMARY){
$type = EventLog::TYPE_PACKAGE_PURCHASED_CONFIRM;
$invoiceType = "PAC";
}else if($packageTransaction->getPackage()->getType() === PackageType::SUBSCRIPTION){
$type = EventLog::TYPE_SUBSCRIPTION_PURCHASED_CONFIRM;
$invoiceType = "SUB";
}
$dataUser = [];
if($packageTransactionApprovedEvent->getFrom() === "web"){
$dataUser[] = $this->authenticationService->getUser();
}else{
/** @var ProfileRBAC $rbac */
foreach ($this->profileService->findAllUserForAProfile($packageTransaction->getProfile()) as $rbac){
$dataUser[] = $rbac->getUser();
}
}
$messeges = $this->buildMessages(
$type,
$packageTransaction,
$packageSongwriter,
$dataUser[0]
);
$this->packageMailer->sendPackageSubcriptionPurchasedEmails($dataUser,$messeges);
$this->eventDispatcher->dispatch(new LogEvent($packageTransaction, $dataUser[0], $type));
}
/**
* @param PackageTransactionSubscriptionCanceledEvent $event
* @return void
*/
public function onPackageTransactionSubscriptionCanceledEvent(PackageTransactionSubscriptionCanceledEvent $event)
{
$packageTransaction = $event->getPackageTransaction();
$dataUser = [];
if($event->getFrom() === "web"){
$dataUser[] = $this->authenticationService->getUser();
}else{
/** @var ProfileRBAC $rbac */
foreach ($this->profileService->findAllUserForAProfile($packageTransaction->getProfile()) as $rbac){
if(!in_array($rbac->getUser(), $dataUser)){
$dataUser[] = $rbac->getUser();
}
}
}
$this->eventDispatcher->dispatch(new LogEvent(
$packageTransaction,
$dataUser[0],
EventLog::TYPE_SUBSCRIPTION_PURCHASED_CANCEL
));
/** @var PackageSongWriter $packageSongWriter */
$packageSongWriter = $this->packageSongwriterRepository->findOneBy(['packageTransaction' => $packageTransaction]);
$messeges = $this->buildMessages(
EventLog::TYPE_SUBSCRIPTION_PURCHASED_CANCEL,
$packageTransaction,
$packageSongWriter,
$dataUser[0]
);
$this->packageMailer->sendPackageSubscriptionCancelledEmails($dataUser,$messeges);
}
/**
* @param PackageTransactionSubscriptionInactivatedEvent $event
* @return void
* @throws \Symfony\Component\Mailer\Exception\TransportExceptionInterface
*/
public function onPackageTransactionSubscriptionInactivatedEvent(PackageTransactionSubscriptionInactivatedEvent $event)
{
$packageTransaction = $event->getPackageTransaction();
$dataUser = [];
if($event->getFrom() === "web"){
$dataUser[] = $this->authenticationService->getUser();
}else{
/** @var ProfileRBAC $rbac */
foreach ($this->profileService->findAllUserForAProfile($packageTransaction->getProfile()) as $rbac){
$dataUser[] = $rbac->getUser();
}
}
$this->eventDispatcher->dispatch(new LogEvent(
$packageTransaction,
$dataUser[0],
EventLog::TYPE_SUBSCRIPTION_PURCHASED_INACTIVE
));
/** @var PackageSongWriter $packageSongWriter */
$packageSongWriter = $this->packageSongwriterRepository->findOneBy(['packageTransaction' => $packageTransaction]);
$messeges = $this->buildMessages(
EventLog::TYPE_SUBSCRIPTION_PURCHASED_INACTIVE,
$packageTransaction,
$packageSongWriter,
$dataUser[0]
);
$this->packageMailer->sendPackageSubscriptionInactivatedEmails($dataUser,$messeges);
}
public function onPackageTransactionSubscriptionReactivatedEvent(PackageTransactionSubscriptionReactivatedEvent $event)
{
$packageTransaction = $event->getPackageTransaction();
$dataUser = [];
if($event->getFrom() === "web"){
$dataUser[] = $this->authenticationService->getUser();
}else{
/** @var ProfileRBAC $rbac */
foreach ($this->profileService->findAllUserForAProfile($packageTransaction->getProfile()) as $rbac){
$dataUser[] = $rbac->getUser();
}
}
$this->eventDispatcher->dispatch(new LogEvent(
$packageTransaction,
$dataUser[0],
EventLog::TYPE_SUBSCRIPTION_PURCHASED_REACTIVE
));
/** @var PackageSongWriter $packageSongWriter */
$packageSongWriter = $this->packageSongwriterRepository->findOneBy(['packageTransaction' => $packageTransaction]);
$message = $this->buildMessages(
EventLog::TYPE_SUBSCRIPTION_PURCHASED_REACTIVE,
$packageTransaction,
$packageSongWriter,
$dataUser[0]
);
$this->packageMailer->sendPackageSubscriptionInactivatedEmails($dataUser, $message);
}
/**
* @param Profile $profile
* @return array|mixed
*/
private function getCredentialFOrPaymentGateway(Profile $profile)
{
$credentials = [];
if($profile->getProfileType()->getName() === Constants::PROFILE_TYPE_PUBLISHER_ADMINISTRATOR){
$credentials = $this->profileService->getParentPaymentGateways($profile);
}else if($profile->getProfileType()->getName() === Constants::PROFILE_TYPE_PUBLISHER
|| $profile->getProfileType()->getName() === Constants::PROFILE_TYPE_SONGWRITER){
$publisherAdministrator = $this->profileService->findPublisherAdministratorForProfile($profile);
$credentials = $this->profileService->getParentPaymentGateways($publisherAdministrator);
}
return $credentials;
}
/**
* @param string $event
* @param PackageTransaction $packageTransaction
* @param PackageSongWriter $packageSongWriter
* @param User $user
* @return array
*/
private function buildMessages(
string $event,
PackageTransaction $packageTransaction,
PackageSongWriter $packageSongWriter,
User $user = null
)
{
$invoiceType = "";
if($packageTransaction->getPackage()->getType() === PackageType::PRIMARY){
$invoiceType = "PAC";
}else if($packageTransaction->getPackage()->getType() === PackageType::SUBSCRIPTION){
$invoiceType = "SUB";
}
/** @var User $user */
$user = (is_null($user)) ? $this->authenticationService->getUser() : $user;
$date = date("Y-m-d");
$time = date("H:i:s");
$message = "";
$title = "";
$dataForEmail = [];
$nameInTheEmail = "";
if($packageSongWriter->getProfile()->getProfileType()->getName() === Constants::PROFILE_TYPE_PUBLISHER){
$nameInTheEmail = $packageSongWriter->getProfile()->getProfileInformation()->getName();
}else if($packageSongWriter->getProfile()->getProfileType()->getName() === Constants::PROFILE_TYPE_SONGWRITER){
$nameInTheEmail = $user->getUserProfile()->getFirstName()." ".$user->getUserProfile()->getLastName();
}
switch($event){
case EventLog::TYPE_SUBSCRIPTION_PURCHASED_CANCEL:
$dataForEmail['title'] = "Subscription Cancelled - ".$packageSongWriter->getProfile()->getProfileInformation()->getName();
$dataForEmail['message'] = "The subscription of {$packageTransaction->getPackage()->getName()} has been cancelled for
{$user->getUserProfile()->getFirstName()} {$user->getUserProfile()->getLastName()} on {$date} at {$time}";
$dataForEmail['message2'] = "";
$dataForEmail['message3'] = "";
$dataForEmail['username'] = $nameInTheEmail;
breaK;
case EventLog::TYPE_SUBSCRIPTION_PURCHASED_INACTIVE:
$dateBegin = $packageSongWriter->getAvialableOn()->format("Y/m/d");
$dateEnd = $packageSongWriter->getAvialableOff()->format("Y/m/d");
$nextAttemptDate = $this->packageService->getReactivationAttempts($packageTransaction)
->getNextAttemptDate()->format("Y/m/d");
$dataForEmail['title'] = $packageSongWriter->getProfile()->getProfileInformation()->getName();
$dataForEmail['title'] .= " Your renewal for subscription ".$packageTransaction->getPackage()->getName()." failed";
$dataForEmail['message'] = "Your payment for subscription {$packageTransaction->getPackage()->getName()} -
Date {$dateBegin} to {$dateEnd} of {$packageSongWriter->getProfile()->getProfileInformation()->getName()}";
$dataForEmail['message'] .= " at {$packageSongWriter->getPackage()->getProfile()->getParent()->getProfileInformation()->getName()}";
$dataForEmail['message'] .= " failed using {$packageTransaction->getPaymentGateway()->getPaymentType()->getName()}";
$dataForEmail['message2'] = "Your subscription has been suspended and its renewal will be tried again on";
$dataForEmail['message2'] .= " {$nextAttemptDate}. Make sure that there are enough funds in your";
$dataForEmail['message2'] .= " {$packageTransaction->getPaymentGateway()->getPaymentType()->getName()} account so";
$dataForEmail['message2'] .= " the renewal can be completed and your subscription re-activated";
$dataForEmail['message3'] = "Please note that until your subscription has been successfully renewed ";
$dataForEmail['message3'] .= "your compositions will not be processed and you will not be able to submit compositions";
$dataForEmail['username'] = $nameInTheEmail;
break;
case EventLog::TYPE_SUBSCRIPTION_PURCHASED_REACTIVE:
$dataForEmail['title'] = "Subscription Reactivated - ".$packageSongWriter->getProfile()->getProfileInformation()->getName();
$dataForEmail['message'] = "The subscription of {$packageTransaction->getPackage()->getName()} has been reactivated
on {$date} at {$time} for more information please contact with publishing@horusmusic.global";
$dataForEmail['message2'] = "";
$dataForEmail['message3'] = "";
$dataForEmail['username'] = $nameInTheEmail;
break;
case EventLog::TYPE_SUBSCRIPTION_PURCHASED_CONFIRM:
$duration = "";
if($packageTransaction->getPackage()->isMonthly()){
$duration = "1 month";
}else if($packageTransaction->getPackage()->isAnnual()){
$duration = "1 year";
}
$invoicesCounter = $this->packageService->invoiceCounter($packageSongWriter, "query");
$dateBegin = $packageSongWriter->getAvialableOn()->format("Y/m/d");
$dateEnd = $packageSongWriter->getAvialableOff()->format("Y/m/d");
$dataForEmail['title'] = "New Subscription";
$dataForEmail['message'] = "your payment for subscription {$packageTransaction->getPackage()->getName()} ({$duration})
Date - {$dateBegin} - {$dateEnd} of {$packageTransaction->getProfile()->getProfileInformation()->getName()}
at {$packageTransaction->getProfile()->getParent()->getProfileInformation()->getName()} was processed successfully using {$packageTransaction->getPaymentGateway()->getPaymentType()->getName()}.
Please click below to view the invoice for the transaction.";
$dataForEmail['invoiceUrl'] = $_ENV['MMPZ_API_DOMAIN']."/invoice?invoice_number={$packageTransaction->getId()}{$packageSongWriter->getId()}-{$invoicesCounter}";
$dataForEmail['message2'] = "In case of issues, please mention the following transaction reference number #
{$packageTransaction->getPaymentGatewayExternalId()} to the customer support team";
$dataForEmail['username'] = $nameInTheEmail;
break;
case EventLog::TYPE_PACKAGE_PURCHASED_CONFIRM:
$invoicesCounter = $this->packageService->invoiceCounter($packageSongWriter, "query");
$dataForEmail['title'] = "New Package";
$dataForEmail['message'] = "your payment for Package {$packageTransaction->getPackage()->getName()}
of {$packageTransaction->getProfile()->getProfileInformation()->getName()}
at {$packageTransaction->getProfile()->getParent()->getProfileInformation()->getName()} was processed successfully using {$packageTransaction->getPaymentGateway()->getPaymentType()->getName()}.
Please click below to view the invoice for the transaction";
$dataForEmail['invoiceUrl'] = $_ENV['MMPZ_API_DOMAIN']."/invoice?invoice_number={$packageTransaction->getId()}{$packageSongWriter->getId()}-{$invoicesCounter}";
$dataForEmail['message2'] = "In case of issues, please mention the following transaction reference number #
{$packageTransaction->getPaymentGatewayExternalId()} to the customer support team";
$dataForEmail['username'] = $nameInTheEmail;
break;
}
$dataForEmail['profile'] = $packageSongWriter->getProfile();
return $dataForEmail;
}
}