<?php
namespace Bundles\RemoteSystems\Controller;
use Bundles\Instruments\Base\Entity\Forward;
use Bundles\RemoteSystems\Form\DrawdownType;
use Bundles\RemoteSystems\Form\OrderForwardType;
use Bundles\RemoteSystems\Form\OrderSpotType;
use Bundles\RemoteSystems\Entity\Trade;
use App\Controller\ParentController;
use App\Entity\Customer;
use App\Models\systems\broker\Corpay;
use App\Models\systems\broker\CorpayDemo;
use Bundles\Portfolios\Entity\Portfolio;
use Bundles\RemoteSystems\Form\ForwardType;
use Bundles\RemoteSystems\Form\SpotType;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Contracts\Cache\CacheInterface;
use function Amp\Promise\wait;
class CorpayController extends ParentController {
protected Customer $customer;
protected Corpay|CorpayDemo $corpay;
protected $useRemoteSystems = false;
protected $useRemoteSystemsDemo = false;
protected $session;
protected $request;
protected $url = '';
protected $contractTypes = ['O' => 'Open', 'C' => 'Closed'];
public function initialize($request, $logger = null) {
parent::initialize($request);
$this->request = $request;
$this->session = $request->getSession();
$this->customer = $this->getCustomer();
$partnerId = $_ENV['CORPAY_PartnerId'] ?: '';
$partnerKey = $_ENV['CORPAY_PartnerKey'] ?: '';
$appSecret = $_ENV['APP_SECRET'] ?: '';
$env = $_ENV['APP_ENV'] ?: '';
if (!empty($logger)) {
$this->logger = $logger;
}
if ($this->useRemoteSystemsDemo) { //fake data
$this->corpay = new CorpayDemo($this->logger, $this->session);
$this->useRemoteSystems = true;
} elseif (!empty($this->customer->getRemoteUserCode()) && $this->getUser()->isAccessRemoteSystems()) { //production, sandbox
$this->corpay = new Corpay($this->logger, $this->session, $env);
$validCredentials = $this->corpay->setCredentionals($partnerId, $partnerKey, $this->customer->getRemoteUserCode(), $this->customer->getRemoteUserId(), $this->customer->getDecryptedKey($appSecret));
if ($validCredentials) {
$checkConnection = $this->corpay->clientCall('0/');
$this->useRemoteSystems = !empty($checkConnection['clientCode']);
}
}
return $this;
}
public function dashboard(Request $request, LoggerInterface $dbLogger) {
$this->logger = $dbLogger;
$this->initialize($request);
$this->data['title'] = 'Corpay Dashboard';
$this->data['useRemoteSystems'] = $this->useRemoteSystems;
if (!$this->useRemoteSystems) {
$this->data['apiErrors'] = 'No access to remote system management. Please contact support';
return $this->render('@remoteSystems/corpay/index.html.twig', $this->data);
}
$statusColors = [1 => 'secondary', 2 => 'mustard', 3 => 'primary'];
$statusOrders = ['F' => 'Filled', 'P' => 'Pending', 'E' => 'Expired', 'X' => 'Deleted'];
$statusOrderColors = ['F' => 'primary', 'P' => 'orchid', 'E' => 'gray', 'X' => 'salmon'];
$this->data['statusColors'] = $statusColors;
$step = $request->query->get('step') ?? 1;
if ($this->useRemoteSystems) {
if ($step == 1) {
$this->data['forwards'] = $this->corpay->getForwards();
$this->data['spots'] = $this->corpay->getSpots();
} elseif ($step == 2) {
$this->data['orders'] = $this->corpay->getOrders();
$this->data['statusOrders'] = $statusOrders;
$this->data['statusOrderColors'] = $statusOrderColors;
} elseif ($step == 3) {
$this->data['accounts'] = $this->corpay->getAccounts();
$this->data['accountHistory'] = $this->corpay->getBalanceHistory('610324866000031001', '2024-01-01', date('Y-m-d'));
} elseif ($step == 4) {
$this->data['payments'] = $this->corpay->getPayments();
$this->data['tracking'] = $this->corpay->getPaymentTracking();
} elseif ($step == 5) {
$this->data['news'] = $this->corpay->getMarketNews(10);
} elseif ($step == 6) { //tests
// $this->data['forwardsInfo'] = $this->corpay->getForwardGuideline();
// $this->data['BusinessTypes'] = $this->corpay->call('clientonboarding/onboardingpicklists?pickListType=BusinessType');
$data = [
'amount' => $request->request->get('amount') ?? 1000,
'buyCurrency' => $request->request->get('buyCurrency') ?? 'USD',
// 'forwardType' => $request->request->get('forwardType') ?? 'C',
'lockSide' => $request->request->get('lockSide') ?? 'Settlement', //Payment/Settlement
// 'maturityDate' => $request->request->get('maturityDate') ?? date_create('+ 35 days')->format('Y-m-d'),
'expiryDate' => $request->request->get('expiryDate') ?? date_create('+ 35 days')->format('Y-m-d'),
// 'openDateFrom' => $request->request->get('openDateFrom') ?? date_create('+ 1 day')->format('Y-m-d'),
'sellCurrency' => $request->request->get('sellCurrency') ?? 'EUR',
// 'settlementCurrency' => $request->request->get('sellCurrency') ?? 'EUR',
// 'paymentCurrency' => $request->request->get('sellCurrency') ?? 'USD',
'rate' => $request->request->get('rate') ?? '1.11',
'limitOrderType' => $request->request->get('limitOrderType') ?? 'Spot', //Spot/Forward
];
// $forwardPost = $this->corpay->postForward($data);
// $quotId = $this->corpay->postSpot($data);
// $orderResponse = $this->corpay->postOrder($data);
if (!empty($quotId)) {
$quotDetails = $this->corpay->rateResource($quotId);
$spotOrderData = $this->corpay->spotBook($quotId);
}
$this->data['tests']['forwardPost'] = $forwardPost ?? [];
$this->data['tests']['quotDetails'] = $quotDetails ?? [];
$this->data['tests']['spotOrderData'] = $spotOrderData ?? [];
$this->data['tests']['orderResponse'] = $orderResponse ?? [];
}
} else {
$this->data['apiErrors'] = 'No access to Corpay remote system';
}
$this->data['step'] = $step;
$this->data['apiErrors'] = $this->corpay->getErrors();
//dump($this->data);
return $this->render('@remoteSystems/corpay/index.html.twig', $this->data);
}
public function getForwards($portfolioId, Request|null $request, LoggerInterface|null $dbLogger, CacheInterface|null $cache) {
$this->logger = $dbLogger;
$this->initialize($request);
if (!$this->useRemoteSystems) {
return $this->json(['error' => 'No access to remote system'], 403);
}
if (empty($portfolioId)) {
return $this->json(['error' => 'No portfolioId'], 403);
}
$portfolio = $this->em->getRepository(Portfolio::class)->findOneBy(['id' => $portfolioId,
'customer' => $this->customer,
]);
if (empty($portfolio)) {
return $this->json(['error' => 'No portfolio found'], 403);
}
$currPairName = $portfolio->getCurrencyPair()->getName();
$minorCurr = $portfolio->getCurrencyPair()->getCurrencyNameByNumber(2);
$forwards = $this->corpay->getForwards();
$spots = [];// siai dienai istoriniu spotu dealu paimti negalime, nes API neturi reikiamo endpointo tam
$list = [];
$forwardCount = 0;
if (!empty($forwards['data']['rows'])) {
$forwards = $forwards['data']['rows'];
$forwardNumbers = [];
foreach ($forwards as $key => $item) {
$forwardNumbers[] = $item['ordNum'];
}
$existingForwards = $this->em->getRepository(Forward::class)->findBy(['tradeNumber' => $forwardNumbers, 'Portfolio' => $portfolioId]);
foreach ($existingForwards as $item) {
$existingForwardList[$item->getTradeNumber()] = $item->getId();
}
foreach ($forwards as $item) {
$tradePairName1 = $item['currency'].'/'.$item['costCurrency'];
$tradePairName2 = $item['costCurrency'].'/'.$item['currency'];
if ($currPairName == $tradePairName1 || $currPairName == $tradePairName2) {
$item['currencyPair'] = $currPairName;
$item['createdBy'] = 'forward';
if ($item['currency'] != $minorCurr) { //kartais buna, kai valiutu pora atvirkstine, todel reikia patikrinti ir isvesti pagal poras vistiek minor valiutos amounta
$item['amount'] = $item['costAmount'];
}
$item['exist'] = $existingForwardList[$item['ordNum']] ?? 0;
$list[] = $item;
$forwardCount++;
}
}
}
if (!empty($spots)) {
$spotCount = 0;
foreach ($spots as $item) {
$tradePairName1 = substr($item['rateType'], 0, 3).'/'.substr($item['rateType'], 3);
$tradePairName2 = substr($item['rateType'], 3).'/'.substr($item['rateType'], 0, 3);
if ($currPairName == $tradePairName1 || $currPairName == $tradePairName2) {
$list[] = [
'maturityDate' => $item['quoteTimestamp'],
'token' => $item['id'],
'ordNum' => '',
'currencyPair' => $currPairName,
'costAmount' => $item['paymentAmount'],
'rate' => $item['rate'],
'createdBy' => 'spot',
];
$spotCount++;
}
}
}
$error = '';
if (count($list) != (count($spots) + count($forwards))) {
if (!empty($forwards) && count($forwards) != $forwardCount) {
$error .= 'Forwards received '.count($forwards).', but fit for this portfolio '.$forwardCount.'<br>';
}
if (!empty($spots) && count($spots) != $spotCount) {
$error .= 'Spots received '.count($spots).', but fit for this portfolio '.$spotCount;
}
}
$data = [
'list' => $list,
];
if (!empty($cache)) {
// Generate a unique key for this session
$cacheKey = 'broker_forwards_'.$this->getUser()->getId();
// Save big array in cache for 1 hour
$cache->delete($cacheKey); // optional, clear previous
$cache->get($cacheKey, function () use ($list) {
return $list;
});
$data['count'] = count($cache->getItem($cacheKey)->get());
}
return new JsonResponse($data, 200);
}
public function getForms(?int $portfolioId, Request $request, LoggerInterface $dbLogger) {
$this->logger = $dbLogger;
$this->initialize($request);
$portfolio = $this->em->getRepository(Portfolio::class)->findOneBy([
'id' => $portfolioId,
'customer' => $this->getCustomer()->getId(),
]);
if (empty($portfolio) || !$this->useRemoteSystems) {
return new JsonResponse(['error' => 'Unauthorized access or lack of rights. Please reach the support for more information.']);
}
$this->url = $portfolio->getId();
$majorCurr = $portfolio->getCurrencyPair()->getCurrencyNameByNumber(1);
$minorCurr = $portfolio->getCurrencyPair()->getCurrencyNameByNumber(2);
$sellCurr = $majorCurr;
$buyCurr = $minorCurr;
$currencies = [
'buy' => [$minorCurr => $minorCurr],
'sell' => [$majorCurr => $majorCurr],
];
if ($portfolio->getDirection() == 'receive') {
$currencies['buy'] = [$majorCurr => $majorCurr];
$currencies['sell'] = [$minorCurr => $minorCurr];
$sellCurr = $minorCurr;
$buyCurr = $majorCurr;
}
$accounts = $this->corpay->getAccounts($sellCurr);
$options = [
'currencies' => $currencies,
'currentCurr' => $buyCurr,
'accounts' => $accounts['accounts'],
];
$spotForm = $this->getForm('spot', null, $options);
$forwardForm = $this->getForm('forward', null, $options);
// $orderSpotForm = $this->getForm('orderSpot', null, $options);
// $orderForwardForm = $this->getForm('orderForward', null, $options);
$data = [
'spotForm' => $spotForm->createView(),
'forwardForm' => $forwardForm->createView(),
// 'orderSpotForm' => $orderSpotForm->createView(),
// 'orderForwardForm' => $orderForwardForm->createView(),
'accountDetails' => $accounts['details'],
'sellCurr' => $sellCurr,
'buyCurr' => $buyCurr,
];
$operatinForm = $this->render('@remoteSystems/corpay/forms.html.twig', $data)->getContent();
return new JsonResponse($operatinForm, 200);
}
protected function getForm($type, $object = null, $options = []) {
switch ($type) {
case 'forward':
if (empty($object)) {
$object = new Trade();
}
$objetType = ForwardType::class;
$vars = '&type='.$type;
break;
case 'spot':
if (empty($object)) {
$object = new Trade();
}
$objetType = SpotType::class;
$vars = '&type='.$type;
break;
case 'orderSpot':
if (empty($object)) {
$object = new Trade();
}
$objetType = OrderSpotType::class;
$vars = '&type='.$type;
break;
case 'orderForward':
if (empty($object)) {
$object = new Trade();
}
$objetType = OrderForwardType::class;
$vars = '&type='.$type;
break;
case 'drawdown':
if (empty($object)) {
$object = new Trade();
}
$objetType = DrawdownType::class;
$vars = '&type='.$type;
break;
}
$options['url'] = $this->url.'&step=6'.$vars;
return $this->createForm($objetType, $object, $options);
}
protected function getErrors($errors) {
$errorList = null;
if (!empty($errors)) {
$errorList = 'Errors: <br><ul>';
foreach ($errors as $error) {
if (!empty($error['message'])) {
$errorList .= '<li>'.$error['message'].'</li>';
}
}
$errorList .= '</ul>';
}
return $errorList;
}
}