<?php
namespace App\Controller;
use App\Entity\CurrencyPair;
use App\Entity\Customer;
use App\Entity\User;
use Bundles\Portfolios\Controller\PortfolioOptionController;
use Bundles\Settings\Entity\Settings;
use App\Service\Helper;
use App\Service\Messenger;
use App\Service\Sender;
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;
use EasyCorp\Bundle\EasyAdminBundle\Event\EasyAdminEvents;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use App\Service\HedgingCalcs;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use App\Service\Excel;
use App\Service\GoogleApi;
use App\Models\ForwardPoints;
use Bundles\Settings\Controller\SettingsController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Bundles\Messenger\Controller\ActionController;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Component\Cache\CacheItem;
use Bundles\Instruments\Base\Model\Calculations;
class ParentController extends EasyAdminController {
protected $systemName = 'CorpHedge';
protected $systemUrl = ''; //is sistemos nustatymo
protected $systemPhone = ''; //is sistemos nustatymo
protected $logger;
protected $cronLogger;
protected $cache;
protected $rootPath;
protected $settings;
protected $sysConfig;
protected $systemCustomer;
protected $session;
protected $connection;
protected $redirect;
protected $data = [];
protected $mailSender = '';
public function initialize(Request $request) {
parent::initialize($request);
if (empty($this->em)) {
$this->em = $this->getDoctrine()->getManagerForClass(Settings::class);
}
$this->getSysConfig();
if (empty($this->systemCustomer)) {
$this->systemCustomer = $this->em->getRepository(Customer::class)->find($this->getSysConfig('systemCustomer'));
}
if (!empty($this->getUser()) && $this->getUser()->getId()) {
if ($this->getCustomer()->getLicence() == 'Trial' && date_create($this->getCustomer()->getTrialExpiresAt()) < date_create()) {
$this->addFlash('warning', 'Your trial period has ended. Please contact your administrator.');
$this->getCustomer()->setLicence('Basic');
$this->updateEntity($this->getCustomer());
}
$this->data['user'] = $this->getUser();
$this->data['licence'] = $this->getCustomer()->getLicence();
}
$this->mailSender = $_ENV['MAIL_SENDER'];
}
protected function listAction() {
$this->initialize($this->request);
$this->dispatch(EasyAdminEvents::PRE_LIST);
$fields = $this->entity['list']['fields'];
$paginator = $this->findAll($this->entity['class'], $this->request->query->get('page', 1), $this->entity['list']['max_results'], $this->request->query->get('sortField'), $this->request->query->get('sortDirection'), $this->entity['list']['dql_filter']);
$this->dispatch(EasyAdminEvents::POST_LIST, ['paginator' => $paginator]);
$parameters = [
'paginator' => $paginator,
'fields' => $fields,
'batch_form' => $this->createBatchForm($this->entity['name'])->createView(),
'delete_form_template' => $this->createDeleteForm($this->entity['name'], '__id__')->createView(),
'user' => $this->getUser(),
];
return $this->executeDynamicMethod('render<EntityName>Template', [
'list',
$this->entity['templates']['list'],
$parameters,
]);
}
protected function editAction() {
$this->dispatch(EasyAdminEvents::PRE_EDIT);
$id = $this->request->query->get('id');
$easyadmin = $this->request->attributes->get('easyadmin');
$entity = $easyadmin['item'];
if ($this->request->isXmlHttpRequest() && $property = $this->request->query->get('property')) {
$newValue = 'true' === mb_strtolower($this->request->query->get('newValue'));
$fieldsMetadata = $this->entity['list']['fields'];
if (!isset($fieldsMetadata[$property]) || 'toggle' !== $fieldsMetadata[$property]['dataType']) {
throw new \RuntimeException(sprintf('The type of the "%s" property is not "toggle".', $property));
}
$this->updateEntityProperty($entity, $property, $newValue);
// cast to integer instead of string to avoid sending empty responses for 'false'
return new Response((int)$newValue);
}
$fields = $this->entity['edit']['fields'];
$editForm = $this->executeDynamicMethod('create<EntityName>EditForm', [$entity, $fields]);
$deleteForm = $this->createDeleteForm($this->entity['name'], $id);
$editForm->handleRequest($this->request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->processUploadedFiles($editForm);
$this->dispatch(EasyAdminEvents::PRE_UPDATE, ['entity' => $entity]);
$this->executeDynamicMethod('update<EntityName>Entity', [$entity, $editForm]);
$this->dispatch(EasyAdminEvents::POST_UPDATE, ['entity' => $entity]);
return $this->redirectToReferrer();
}
$this->dispatch(EasyAdminEvents::POST_EDIT);
$parameters = [
'form' => $editForm->createView(),
'entity_fields' => $fields,
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
'user' => $this->getUser(),
];
return $this->executeDynamicMethod('render<EntityName>Template', [
'edit',
$this->entity['templates']['edit'],
$parameters,
]);
}
/**
* mano inicijuoti ir aktyvuoti servisai
* @return array
*/
public static function getSubscribedServices(): array {
return array_merge(parent::getSubscribedServices(), [
'messenger' => Messenger::class,
'sender' => Sender::class,
'helper' => Helper::class,
'settings' => SettingsController::class,
'user' => UserController::class,
'HedgingCalcs' => HedgingCalcs::class,
'Excel' => Excel::class,
'GoogleApi' => GoogleApi::class,
'messenger_actions' => ActionController::class,
'optionPortfolio' => PortfolioOptionController::class,
]);
}
protected function getCurrencyList() {
$list = [];
/**
* @var CurrencyPair[] $pairs
*/
$pairs = $this->getDoctrine()->getRepository(CurrencyPair::class)->findBy(['status' => 1]);
if (empty($pairs)) {
return $list;
}
foreach ($pairs as $item) {
$list[$item->getName()] = $item->getId();
}
return $list;
}
protected function getCompanyList() {
$list = [];
/**
* @var Customer[] $customers
*/
$customers = $this->getAdminCustomers(false);
if (empty($customers)) {
return $list;
}
foreach ($customers as $item) {
$list[$item->getCompanyName()] = $item->getId();
}
return $list;
}
public function createFilterForm($filters, $requestFilters, $route, $formName = 'filter', $errors = []) {
/** @var FormBuilder $formBuilder */
$formBuilder = $this->get('form.factory')->createNamedBuilder($formName)->setMethod('POST')->setAction($route);
foreach ($filters as $filter) {
if (!empty($filter['roles']['ROLE_ADMIN']) && !$this->getUser()->isAdmin()) {
continue;
}
switch ($filter['type']) {
case 'date':
$formBuilder->add($filter['property'], TextType::class, [
'translation_domain' => 'messages',
'required' => false,
'label' => $filter['label'],
'attr' => [
'class' => 'form-control datepicker '.($filter['class'] ?? ''),
'type' => 'date',
'widget' => 'single_text',
'format' => 'yyyy-mm-dd',
'placeholder' => $filter['placeholder'] ?? '',
'roles' => $filter['roles'] ?? '',
],
'data' => $requestFilters[$filter['property']] ?? $filter['default'] ?? '',
]);
break;
case 'text':
$formBuilder->add($filter['property'], TextType::class, [
'translation_domain' => 'messages',
'required' => false,
'label' => $filter['label'],
'label_attr' => ['class' => 'col-sm-2 control-label'],
'attr' => [
'class' => 'form-control '.($filter['class'] ?? ''),
'placeholder' => $filter['placeholder'] ?? '',
'roles' => $filter['roles'] ?? '',
],
'data' => $requestFilters[$filter['property']] ?? $filter['default'] ?? '',
]);
break;
case 'number':
$formBuilder->add($filter['property'], NumberType::class, [
'translation_domain' => 'messages',
'required' => false,
'label' => $filter['label'],
'label_attr' => ['class' => 'control-label'],
'attr' => [
'class' => 'form-control '.($filter['class'] ?? ''),
'placeholder' => $filter['placeholder'] ?? '',
'roles' => $filter['roles'] ?? '',
'title' => $filter['title'] ?? '',
'onKeyUp' => 'numberCheck(this)',
],
'data' => (!empty($requestFilters[$filter['property']]) ? $requestFilters[$filter['property']] : $filter['default'] ?? 0),
'help' => $filter['help'] ?? '',
]);
break;
case 'select':
$formBuilder->add($filter['property'], ChoiceType::class, [
'translation_domain' => 'messages',
'required' => false,
'choices' => $filter['choices'],
'label' => $filter['label'] ?? '',
'placeholder' => $filter['placeholder'] ?? '',
'label_attr' => ['class' => 'col-sm-2 control-label'],
'attr' => [
'class' => 'form-control '.($filter['class'] ?? ''),
'roles' => $filter['roles'] ?? '',
'onchange' => $filter['onchange'] ?? '',
],
'data' => $requestFilters[$filter['property']] ?? $filter['default'] ?? '',
]);
break;
case 'checkbox':
$formBuilder->add($filter['property'], CheckboxType::class, [
'translation_domain' => 'messages',
'required' => false,
'label' => $filter['label'],
'label_attr' => ['class' => 'col-sm-2 control-label'],
'attr' => [
'class' => 'form-control '.($filter['class'] ?? ''),
'roles' => $filter['roles'] ?? '',
'style' => 'width: 20px; box-shadow: none',
],
'data' => !empty($requestFilters[$filter['property']]) ? true : false,
]);
// dump($requestFilters);
// dump($filter);
break;
case 'textarea':
$formBuilder->add($filter['property'], TextareaType::class, [
'translation_domain' => 'messages',
'required' => false,
'label' => $filter['label'],
'label_attr' => ['class' => 'col-sm-2 control-label'],
'attr' => [
'class' => 'form-control '.($filter['class'] ?? ''),
'roles' => $filter['roles'] ?? '',
],
'data' => $requestFilters[$filter['property']] ?? $filter['default'] ?? '',
]);
break;
case 'hidden':
$formBuilder->add($filter['property'], HiddenType::class, [
'data' => $filter['default'] ?? '',
]);
break;
case 'submit':
$formBuilder->add($filter['property'], SubmitType::class, [
'label' => $filter['label'],
'attr' => $filter['attributes'] ?? '',
]);
break;
}
}
return $formBuilder->getForm();
}
public function getEntityConfig($name) {
$backendConfig = $this->get('easyadmin.config.manager')->getBackendConfig();
foreach ($backendConfig['entities'] as $entityName => $entityConfig) {
if ($entityName === $name) {
return $entityConfig;
}
}
return null;
}
public function getConfigValue($name, $type = 'system') {
return $this->getSysConfig($name, $type, 0);
}
public function getCustomer() {
if (!empty($this->getUser()) && !empty($this->getUser()->getCustomer())) {
return $this->getUser()->getCustomer();
}
// Kai prisijungia konsultantas, galima keisti klienta
if (empty($this->session)) {
$this->session = $this->get('session');
}
if (!empty($this->session->get('currentCustomer'))) {
$currentCustomerId = (int)$this->session->get('currentCustomer');
foreach ($this->getUser()->getConsultants() as $consultant) {
if ($consultant->getId() == $currentCustomerId) {
return $consultant;
}
}
$this->session->remove('currentCustomer');
return null;
} elseif (!empty($this->getUser()) && !empty($this->getUser()->getConsultants())) {
$consultants = $this->getUser()->getConsultants();
$this->session->set('currentCustomer', $consultants[0]->getId());
return $consultants[0];
}
return null;
}
protected function updateUserLogin($tokenStorage) {
/** @var User $user */
$user = $this->getUser();
$token = $tokenStorage->getToken();
if ($token && $user && !in_array('ROLE_PREVIOUS_ADMIN', $token->getRoleNames())) {
$user->setLastLoginAt(new \DateTime());
$this->updateEntity($user);
}
}
/**
* @return array
*/
protected function getAdmins($all = false, $superAdminsOnly = false) {
$repository = $this->em->getRepository(User::class);
if ($all) {
$admins = $repository->findAllAdmins()->getQuery()->getResult();
$admins = array_merge($admins, $repository->findAllSuperAdmins());
} elseif ($superAdminsOnly) {
$admins = $repository->findAllSuperAdmins();
} else {
$admins = $repository->findAllAdmins()->getQuery()->getResult();
}
$list = [0];
if (!empty($admins)) {
foreach ($admins as $object) {
$list[] = $object->getId();
}
return implode(',', $list);
}
return $list;
}
protected function getAdminCustomers($returnList = true) {
$objects = [];
if ($this->getUser()->isSuperAdmin()) {
$objects = $this->getDoctrine()->getRepository(Customer::class)->findAll();
} elseif ($this->getUser()->isAdmin()) {
$customerRepository = $this->getDoctrine()->getRepository(Customer::class);
$queryBuilder = $customerRepository->createQueryBuilder('c');
$query = $queryBuilder
->where('c.id = :id')
->setParameter('id', $this->getCustomer()->getId())
->getQuery();
$objects = $query->getResult();
} elseif (!empty($this->getUser()->isManager())) {
$objects = $this->getDoctrine()->getRepository(Customer::class)->findBy(['id' => $this->getCustomer()->getId()]);
}
if (!empty($returnList)) {
$list = [0];
foreach ($objects as $object) {
$list[] = $object->getId();
}
return implode(',', $list);
}
return $objects;
}
/**
* @param string $type
* @param int $customerId
* @param string $param
* @return mixed
*/
public function getSysConfig($param = '', $type = 'system', $customerId = 0) {
if (empty($this->setting)) {
$settings = $this->getEntityConfig('Settings');
$this->em = $this->getDoctrine()->getManagerForClass($settings['class']);
}
if (empty($this->sysConfig)) {
/**
* @var Settings[] $settingsRecords
*/
$settingsRecords = $this->em->getRepository(Settings::class)->findBy([
'active' => true,
]);
foreach ($settingsRecords as $item) {
$itemCustomerId = 0;
if (!empty($item->getCustomer())) {
$itemCustomerId = $item->getCustomer()->getId();
}
$this->sysConfig[$item->getType()][$itemCustomerId][$item->getName()] = $item->getValue();
}
}
//dump($this->sysConfig);
//dump($type);
if (!empty($this->sysConfig[$type])) {
$settingConfig = $this->sysConfig[$type];
$this->data['settings'] = $settingConfig[0];
}
if (!empty($settingConfig[$customerId])) {
$settingConfig = $settingConfig[$customerId];
} elseif (!empty($settingConfig[0])) {
$settingConfig = $settingConfig[0];
}
if (!empty($param)) {
if (isset($settingConfig[$param])) {
$settingConfig = $settingConfig[$param];
} else {
$settingConfig = null;
//dump('Setting '.$param.' not found');
}
}
return $settingConfig;
}
protected function getCustomers() {
return $this->getDoctrine()->getRepository(Customer::class)->findAll();
}
protected function getPairs() {
$pairs = $this->getDoctrine()->getRepository(CurrencyPair::class)->findBy(['status' => 1]);
return count($pairs);
}
/**
* @param CurrencyPair $currencyPair
* @param string $date
* @return float
*/
protected function getRate($currencyPair, $date = 'now') {
return $this->getModel()->getRate($currencyPair, $date);
}
public function getForwardRate($pair, $period = 30, $action = 'points') {
if (empty($pair)) {
return 0;
}
if (empty($this->forwardRates[$pair->getId()])) {
$this->forwardRates[$pair->getId()] = (new ForwardPoints())->get($pair);
}
if (!empty($this->forwardRates[$pair->getId()][$period][$action])) {
$rate = $this->forwardRates[$pair->getId()][$period][$action];
if ($action == 'points') {
$rate = str_replace(',', '', $rate);
return (int)$rate;
}
return $rate;
}
return 0;
}
protected function getForwardPoints($pairName = '') {
$this->customerId = $this->getCustomer()->getId();
$nextUpdate = $this->session->get('nextUpdate');
$forwards = $this->getCache('forwards_'.$this->customerId);
if (!empty($nextUpdate) && $nextUpdate > date_create() && !empty($forwards)) {
$this->data['forwardPoints'] = $forwards;
$this->data['forwardPointsUpdated'] = $nextUpdate->format('H:i');
if (!empty($pairName) && !empty($this->data['forwardPoints'][$pairName])) {
return $this->data['forwardPoints'][$pairName];
}
return false;
}
$repo = $this->getDoctrine()->getRepository(CurrencyPair::class);
$listNeeded = [];
if (empty($pairName)) {
$list = $this->connection->fetchAllAssociative('
SELECT cp.name
FROM currency_pair cp
LEFT JOIN customer_currency_pair ccp ON(ccp.currency_pair_id = cp.id)
WHERE ccp.customer_id = '.$this->getCustomer()->getId());
foreach ($list as $pair) {
$listNeeded[] = $pair['name'];
}
} else {
$listNeeded = [$pairName];
}
$pairs = $repo->findListByName($listNeeded);
$forwards = [];
$forward = new ForwardPoints();
$needAddEmptyValues = false;
$periodCount = 0;
foreach ($pairs as $pair) {
$forward->setPairSpots([$pair->getName() => $this->getRate($pair)]);
$values = $forward->get($pair->getName());
if (empty($values)) {
//jeigu nerandam reikiamos poros forwardo, sukeiciam valiutas ir bandom rasti atvirkscia
$pairList = explode('/', $pair->getName());
$pairInverted = $pairList[1].'/'.$pairList[0];
$values = $forward->get($pairInverted);
if (!empty($values)) {
//jeigu yra atvirkscias forwardas, tai pakeiciam reiksmes
foreach ($values as $key => $value) {
$values[$key]['bid'] = round(1 / $value['bid'], 4);
$values[$key]['ask'] = round(1 / $value['ask'], 4);
$values[$key]['mid'] = round(1 / $value['mid'], 4);
$values[$key]['points'] = $value['points'];
}
}
}
if (!empty($values)) {
$forwards[$pair->getName()] = $values;
}
if (empty($periodCount) && !empty($values)) {
$periodCount = count($values);
}
if (!empty($values) && count($values) != $periodCount) {
$needAddEmptyValues = true;
}
}
if ($needAddEmptyValues) {
$periods = [30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360];
foreach ($forwards as $pairName => $values) {
foreach ($periods as $period) {
if ($period == 30) {
$oneMonthDiff = floatval(($values[90]['bid'] - $values[30]['bid']) / 2);
}
if (empty($values[$period])) {
$forwards[$pairName][$period] = [
'name' => $period,
'ask' => '-',
'bid' => $lastMonth + $oneMonthDiff,
];
}
$lastMonth = floatval($forwards[$pairName][$period]['bid']);
}
ksort($forwards[$pairName]);
}
}
$updateInMinutes = 10;
$updated = date_create('+ '.$updateInMinutes.' min'); //todo: padaryti per nustatyma
$this->session->set('nextUpdate', $updated);
$this->setCache('forwards_'.$this->customerId, $forwards, $updateInMinutes * 60);
$this->data['forwardPoints'] = $forwards;
$this->data['forwardPointsUpdated'] = $updated->format('H:i');
if (!empty($pairName) && !empty($this->data['forwardPoints'][$pairName])) {
return $this->data['forwardPoints'][$pairName];
}
}
/**
* @return Calculations
*/
protected function getModel($renew = false) {
if (empty($this->model) || $renew) {
$this->model = new Calculations($this->getDoctrine(), $this->logger);
}
return $this->model;
}
public function getCache($name) {
$item = $this->cache->getItem($name);
if ($item->isHit()) {
return $item->get();
}
return false;
}
protected function setCache($name, $value, $expiresAfterSeconds = 3000) {
/** @var CacheItem $item */
$item = $this->cache->getItem($name);
$item->set($value);
if (!empty($expiresAfterSeconds)) {
$item->expiresAfter($expiresAfterSeconds);
}
$this->cache->save($item);
}
public function deleteCache($name) {
$this->cache->deleteItem($name);
}
public function getFunctionalCurrency() {
$this->functionalCurrency = $this->session->get('functionalCurr');
if (empty($this->functionalCurrency)) {
$this->functionalCurrency = $this->getCustomer()->getFunctionalCurrency();
}
return $this->functionalCurrency;
}
public function getCustomerLicence() {
$customer = $this->getCustomer() ?? null;
if (empty($customer)) {
return 'Basic';
}
return $customer->getLicence();
}
}