<?php
namespace Rawafed\CloudServicesBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Rawafed\CloudServicesBundle\Entity\BillingSettings;
use Rawafed\CloudServicesBundle\Entity\Client;
use Rawafed\CloudServicesBundle\Entity\Package;
use Rawafed\CloudServicesBundle\Entity\Subscription;
use Rawafed\CloudServicesBundle\Form\SubscriptionType;
use Rawafed\PaymentBundle\Entity\BillingPeriod;
use Rawafed\CloudServicesBundle\Exception\SubscriptionIsNotReadyException;
use Rawafed\CloudServicesBundle\Exception\SubscriptionNotFoundException;
use Rawafed\CloudServicesBundle\Exception\SubscriptionIsSuspenededException;
class SubscriptionController extends AbstractController
{
/**
* @Route("/subscriptions", name="cloud_subscription_list")
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
* @Template
*/
public function subscriptionsAction(Request $request)
{
$user = $this->getUser();
if($this->container->has('navigation')) {
$breadcrumbBuilder = $this->get('navigation')->getBreadcrumbBuilder();
$breadcrumbBuilder
->moveTo('homepage')
->add('cloud_services.titles.subscriptions', 'cloud_subscription_list')
;
}
$entityManager = $this->getDoctrine()->getManager();
$subscriptionRepo = $entityManager->getRepository(Subscription::class);
$subscriptions = $subscriptionRepo->getUserSubscriptions($user);
return [
'subscriptions' => $subscriptions,
'cloudManager' => $this->get('cloud_manager')
];
}
/**
* @Route("/subscription/new", name="cloud_subscription_new")
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
* @Template
*/
public function newSubscriptionAction(Request $request)
{
$entityManager = $this->getDoctrine()->getManager();
$user = $this->getUser();
$packageId = $this->get('session')->get('packageId');
$package = null;
if($packageId) {
$packageRepo = $entityManager->getRepository(Package::class);
$package = $packageRepo->find($packageId);
}
if(!$package) {
return $this->redirectToRoute('cloud_package_pricing');
}
if($this->container->has('navigation')) {
$breadcrumbBuilder = $this->get('navigation')->getBreadcrumbBuilder();
$breadcrumbBuilder
->moveTo('homepage')
->add('cloud_services.titles.subscriptions', 'cloud_subscription_list')
->add('cloud_services.titles.new_subscription', 'cloud_subscription_new')
;
}
$subscription = new Subscription();
$subscription->setPackage($package);
$clientRepo = $entityManager->getRepository(Client::class);
$clients = $clientRepo->getUserClients($user);
if(!$clients || !count($clients)) {
return $this->redirectToRoute('cloud_client_new');
}
$billingPeriod = $this->get('session')->get('billing_period');
$billingSettings = new BillingSettings();
if(strcasecmp($billingPeriod, BillingPeriod::YEAR) === 0) {
$billingSettings->setBillingPeriod(BillingPeriod::YEAR);
} else {
$billingSettings->setBillingPeriod(BillingPeriod::MONTH);
}
$subscription->setBillingSettings($billingSettings);
if(count($clients) == 1) {
$subscription->setClient($clients[0]);
}
$subscriptionForm = $this->createForm(SubscriptionType::class, $subscription, ['clients' => $clients]);
$subscriptionForm->handleRequest($request);
if($subscriptionForm->isSubmitted() && $subscriptionForm->isValid()) {
$subscription = $subscriptionForm->getData();
$billingSettings = $subscription->getBillingSettings();
if(!$billingSettings->getBillingName()) {
$billingName = $subscription->getClient()->getContacts()[0]->getRealName();
$billingSettings->setBillingName($billingName);
}
if(!$billingSettings->getBillingEmail()) {
$billingEmail = $subscription->getClient()->getContacts()[0]->getEmail();
$billingSettings->setBillingEmail($billingEmail);
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($subscription);
$entityManager->flush();
$translator = $this->get('translator');
$freePeriod = $package->getFreePeriod();
if($freePeriod == 0) {
///////////
// TODO: move logic in this action & SubscriptionsMonitoringCommand to a service
$paymentPeriodStart = new \DateTime();
$paymentPeriodStart->setTime(0, 0);
$invoiceItems = new \Doctrine\Common\Collections\ArrayCollection();
$setupFees = $package->getSetupFees();
if($setupFees > 0) {
$invoiceItem = new \Rawafed\PaymentBundle\Entity\InvoiceItem();
$invoiceItem->setAmount($setupFees * (1 - $package->getSetupFeesDiscount() / 100));
$invoiceItem->setDescription($translator->trans('cloud_services.fields.setup_fees'));
$invoiceItems->add($invoiceItem);
}
$billingSettings = $subscription->getBillingSettings();
$billingPeriod = $billingSettings->getBillingPeriod();
$paymentPeriodEnd = new \DateTime();
$paymentPeriodEnd->add(new \DateInterval($billingPeriod == BillingPeriod::YEAR ? 'P1Y' : 'P1M'));
$invoiceItem = new \Rawafed\PaymentBundle\Entity\InvoiceItem();
if($billingPeriod == BillingPeriod::YEAR) {
$yearlyFees = $package->getYearlyFees();
$invoiceItem->setAmount($yearlyFees * (1 - $package->getYearlyFeesDiscount() / 100));
$invoiceItem->setDescription($translator->trans('cloud_services.fields.yearly_fees'));
} else {
$monthlyFees = $package->getMonthlyFees();
$invoiceItem->setAmount($monthlyFees * (1 - $package->getMonthlyFeesDiscount() / 100));
$invoiceItem->setDescription($translator->trans('cloud_services.fields.monthly_fees'));
}
$invoiceItems->add($invoiceItem);
$invoiceSubmissionPeriod = $this->getParameter('cloud_services.invoice_submission_period');
$invoiceIssueDate = new \DateTime();
$invoiceIssueDate->sub(new \DateInterval('P' . $invoiceSubmissionPeriod .'D'));
$invoiceRepo = $entityManager->getRepository(\Rawafed\PaymentBundle\Entity\Invoice::class);
$invoiceNumber = $invoiceRepo->getNextInvoiceNumber();
$invoice = new \Rawafed\PaymentBundle\Entity\Invoice();
$invoice->setInvoiceNumber($invoiceNumber);
$invoice->setIssueDate(new \DateTime());
$invoice->setDueDate(new \DateTime());
$invoice->setCurrency($billingSettings->getCurrency());
foreach($invoiceItems as $invoiceItem) {
if($billingSettings->getCountry()->getId() == 'SA') {
$invoiceItem->setVat(0.05 * $invoiceItem->getAmount());
}
$invoice->addItem($invoiceItem);
}
$subscriptionPayment = new \Rawafed\CloudServicesBundle\Entity\SubscriptionPayment();
$subscriptionPayment->setSubscription($subscription);
$subscriptionPayment->setInvoice($invoice);
$subscriptionPayment->setPeriodStart(new \DateTime());
$subscriptionPayment->setPeriodEnd($paymentPeriodEnd);
$entityManager->persist($invoice);
$entityManager->persist($subscriptionPayment);
$entityManager->flush();
//return $this->redirectToRoute('cloud_billing_checkout', ['number' => $invoiceNumber]);
return $this->redirectToRoute('cloud_billing_invoice', ['number' => $invoiceNumber]);
///////////
} else {
$this->get('session')->getFlashBag()->add(
'success', $translator->trans('cloud_services.messages.subscription_created')
);
return $this->redirectToRoute('cloud_subscription_list');
}
}
return [
'subscription' => $subscription,
'form' => $subscriptionForm->createView(),
];
}
/**
* @Route("/subscription/check-name", name="cloud_subscription_check_name")
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
*/
public function checkNameAction(Request $request)
{
$name = $request->request->get('name');
$cloudManager = $this->get('cloud_manager');
$result = $cloudManager->checkAppNameValidity($name);
$message = '';
if($result !== true) {
$message = 'cloud_services.messages.invalid_app_name';
$result = false;
} else {
$result = $cloudManager->checkAppNameAvailability($name);
if(!$result) {
$message = 'cloud_services.messages.app_name_not_available';
}
}
$translator = $this->get('translator');
$response = [
'result' => $result,
'message' => $translator->trans($message)
];
return new JsonResponse($response);
}
/**
* @Route("/subscription/{name}", name="cloud_subscription_view")
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
* @Template
*/
public function viewSubscriptionAction(Request $request, $name)
{
$entityManager = $this->getDoctrine()->getManager();
$subscriptionRepo = $entityManager->getRepository(Subscription::class);
$subscription = $subscriptionRepo->findByName($name);
$status = $subscription->getStatus();
if(!$subscription) {
throw new NotFoundHttpException('There is no subscription with name: ' . $name);
}
$user = $this->getUser();
if(!$subscription->getClient()->getContacts()->contains($user)) {
throw $this->createAccessDeniedException();
}
if($this->container->has('navigation')) {
$breadcrumbBuilder = $this->get('navigation')->getBreadcrumbBuilder();
$breadcrumbBuilder
->moveTo('homepage')
->add('cloud_services.titles.subscriptions', 'cloud_subscription_list')
->add($name, 'cloud_subscription_view')
;
}
$subscriptionForm = $this->createForm(SubscriptionType::class, $subscription);
$subscriptionForm->handleRequest($request);
if($subscriptionForm->isSubmitted() && $subscriptionForm->isValid()) {
$subscription->setStatus($status);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($subscription);
$entityManager->flush();
return $this->redirectToRoute('cloud_subscription_view', ['name' => $name]);
}
return [
'subscription' => $subscription,
'form' => $subscriptionForm->createView(),
];
}
/**
* @Route("/subscription/{name}/status", name="cloud_subscription_status")
* @Template
*/
public function subscriptionStatusAction(Request $request, $name)
{
if($this->container->has('navigation')) {
$breadcrumbBuilder = $this->get('navigation')->getBreadcrumbBuilder();
$breadcrumbBuilder
->moveTo('homepage')
->add('cloud_services.titles.subscription_status', 'cloud_subscription_status')
;
}
$cloudManager = $this->get('cloud_manager');
$status = null;
$url = null;
try {
$subscription = $cloudManager->getApp($name);
$status = 'ok';
$url = $cloudManager->getAppUrl($name);
$message = sprintf('App %s is up and running', $name);
} catch(SubscriptionNotFoundException $ex) {
$status = 'not_found';
$message = 'cloud_services.messages.subscription_is_not_found';
} catch(SubscriptionIsNotReadyException $ex) {
$status = 'not_ready';
$message = 'cloud_services.messages.subscription_is_not_ready';
} catch(SubscriptionIsSuspenededException $ex) {
$status = 'suspeneded';
$message = 'cloud_services.messages.subscription_is_not_active';
} catch(\Exception $ex) {
$message = $ex->getMessage();
}
if($request->isXmlHttpRequest()) {
$response = [
'name' => $name,
'status' => $status,
'message' => $message,
];
if($url) {
$response['url'] = $url;
}
return new JsonResponse($response);
} else {
return [
'message' => $message,
'name' => $name,
];
}
}
}