<?php
namespace Bundles\Portfolios\Controller;
use App\Entity\CurrencyHistory;
use Bundles\Instruments\CashflowForward\Entity\HedgingPolitics;
use Bundles\Portfolios\Repository\PortfolioRepository;
use Bundles\RemoteSystems\Controller\CorpayController;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\Request;
use Psr\Log\LoggerInterface;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use App\Controller\ParentController;
use Bundles\Portfolios\Entity\Portfolio;
use Bundles\Portfolios\Form\PortfolioType;
use Bundles\Instruments\Base\Entity\Forward;
use Bundles\Instruments\Base\Entity\ForwardOperations;
use Bundles\Instruments\Base\Entity\CashFlows;
use App\Entity\Customer;
use Bundles\Instruments\Base\Model\Report;
use Bundles\Instruments\Swap\Entity\Swap;
use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\JsonResponse;
use App\Entity\CurrencyPair;
use Bundles\Instruments\CashflowForward\Entity\BudgetRates;
use Bundles\Messenger\Model\Actions;
use Bundles\Messenger\Entity\Event;
use Bundles\Messenger\Entity\Notification;
use Psr\Cache\CacheItemPoolInterface;
class PortfolioController extends ParentController {
const STEP_PORTFOLIO = 2;
const STEP_POLICY = 3;
const STEP_BUDGET_RATES = 4;
const STEP_CASH_FLOWS = 5;
const STEP_TRADES = 6;
const STEP_SUMMARY = 7;
const STEP_ANALYSIS = 8;
const STEP_REPORT = 9;
protected $importValidatorModel;
protected $currrentHedgingPolicy = null;
protected $tradeTypes = [
'Cashflow committed' => 'committed_forward',
'Cashflow forecast' => 'cashflow_forward',
'Swap' => 'swap',
'Option' => 'option',
];
protected $customerId = 0;
protected $url = '/portfolios?action=list&menuIndex=1';
protected $request;
private ForwardOperations $tradeOperationRecord;
protected bool $needFlush = false;
private CorpayController $corpayController;
public function __construct(CorpayController $corpayController) {
$this->corpayController = $corpayController;
}
public function init(LoggerInterface $analyticsLogger, CacheItemPoolInterface $cache, Request $request, Connection $connection) {
parent::initialize($request);
$this->session = $this->get('session');
$this->cache = $cache;
$this->redirect = false;
$this->connection = $connection;
$this->step = $request->get('step') ?? self::STEP_PORTFOLIO;
$this->show = $request->get('show') ?? ($this->session->get('show') ?? 'current');
$this->sumGroup = $request->get('group');
$this->tradeOperation = $request->get('operation');
$this->tradeOperationId = $request->get('operationId');
$this->analysisMethod = $request->get('analysisMethod');
$this->cvarMethod = $request->get('cvarMethod');
$this->edit = $request->get('edit') ?? '';
$this->tradeFilter = [
'from' => ($request->get('customPeriodFrom') ?? ''),
'to' => ($request->get('customPeriodTo') ?? ''),
];
$this->request = $request;
$this->logger = $analyticsLogger;
$this->portfolioId = $request->get('portfolioId') ?? 0;
$oldPortfolioId = $this->session->get('portfolioId');
if (!empty($this->portfolioId) && $this->portfolioId != $oldPortfolioId) {
$this->session->set('portfolioId', $this->portfolioId);
} elseif (!empty($oldPortfolioId) && empty($this->portfolioId)) {
$this->portfolioId = $oldPortfolioId;
}
//licence restrictions
$licence = $this->getCustomer()->getLicence();
if ($this->step == self::STEP_PORTFOLIO) {
$this->portfolioId = 0;
$this->session->set('portfolioId', $this->portfolioId);
$this->session->remove('analysisMethod');
$this->session->remove('cvarMethod');
$this->session->remove('sumGroup');
$this->session->remove('sensitivity');
$this->session->remove('show');
$this->session->remove('tradeFilter');
}
if (!empty($this->analysisMethod)) {
$this->session->set('analysisMethod', $this->analysisMethod);
} else {
$this->analysisMethod = $this->session->get('analysisMethod');
}
if (!empty($this->cvarMethod)) {
$this->session->set('cvarMethod', $this->analysisMethod);
} else {
$this->cvarMethod = $this->session->get('cvarMethod') ?? 'full';
}
if (!empty($this->sumGroup)) {
$this->session->set('sumGroup', $this->sumGroup);
} else {
$this->sumGroup = $this->session->get('sumGroup');
}
if (empty($this->sumGroup)) {
$this->sumGroup = 'month';
}
$this->sensitivity = $request->get('sensitivity') ?? '';
if (!empty($this->sensitivity)) {
$this->session->set('sensitivity', $this->sensitivity);
} else {
$this->sensitivity = $this->session->get('sensitivity');
}
if (!empty($this->show)) {
$this->session->set('show', $this->show);
if ($this->show == 'custom' && (!empty($this->tradeFilter['from']) || !empty($this->tradeFilter['to']))) {
$this->session->set('tradeFilter', $this->tradeFilter);
}
}
$this->show = $this->session->get('show');
$this->tradeFilter = $this->session->get('tradeFilter');
$this->policyId = $request->get('policyId') ?? 0;
$this->budgetRateId = $request->get('budgetRateId') ?? 0;
$this->cashFlowId = $request->get('cashFlowId') ?? 0;
$this->tradeId = $request->get('tradeId') ?? 0;
}
public function index(LoggerInterface $analyticsLogger, CacheItemPoolInterface $cache, Request $request, Connection $connection) {
$this->init($analyticsLogger, $cache, $request, $connection);
$this->portfolioId = $request->get('portfolioId') ?? (int)$this->session->get('portfolioId');
if (!empty($this->portfolioId)) {
$this->session->set('portfolioId', $this->portfolioId);
$portfolio = $this->em->getRepository(Portfolio::class)->find($this->portfolioId);
if (!empty($portfolio->getType()) && empty($this->edit)) {
return $this->redirectToRoute('portfolio_'.$portfolio->getType(), [
'step' => $this->step,
'portfolioId' => $this->portfolioId,
]);
}
$this->data['portfolio'] = $portfolio;
}
$this->getPortfolios($request);
$instrument = '@cashflowForward';
$this->data['title'] = 'Portfolios';
$this->data['url'] = $this->url;
$this->data['show'] = 'current';
$this->data['operation'] = $this->tradeOperation ?? null;
$this->data['sumGroup'] = 'month';
$this->data['edit'] = $this->edit;
$this->data['tradeTypes'] = array_flip($this->tradeTypes);
$this->data['portfolioId'] = $this->portfolioId;
$this->data['functionalCurrency'] = $this->session->get('functionalCurr') ?? $this->getCustomer()->getFunctionalCurrency();
// dump($this->data);
return $this->render($instrument.'/index.html.twig', $this->data);
}
protected function getPortfolios($request) {
$customer = $this->getCustomer();
$this->customerId = $customer->getId();
$customerPairs = $this->em->getRepository(Customer::class)->getCurrencyPairsByCustomer($this->customerId);
$step = self::STEP_PORTFOLIO;
$options = [
'tradeTypes' => $this->tradeTypes,
'customerPairs' => $customerPairs,
'licence' => $this->getCustomer()->getLicence(),
];
$form = $this->getForm($step, null, $options);
$form->handleRequest($request);
if ($form->isSubmitted()) {
$this->actionsPortfolio($form);
}
//Jeigu reikia patikrinti, ar useris yra prileidziamas prie visu portfelių
$userPortfolios = $this->getUser()->getUserPortfolios();
// dump($userPortfolios);
if ($this->getUser()->isUser() && !$userPortfolios->isEmpty()) {
$filtered = $userPortfolios->filter(function ($portfolio) {
return $portfolio->getStatus() == 1;
});
// Rūšiuojam kolekciją, bet reikia konvertuoti į masyvą, kad galėtume naudoti usort
$portfolios = $filtered->toArray();
usort($portfolios, function ($a, $b) {
return $b->getId() <=> $a->getId();
});
} else {
$portfolios = $this->em->getRepository(Portfolio::class)->findBy([
'status' => 1,
'customer' => $this->customerId,
], ['id' => 'DESC']);
}
$this->data['portfolios'] = $portfolios;
$this->data['portfolioValues'] = $this->getModel()->getPortfolioValues($this->data['portfolios'], $customer->getFunctionalCurrency());
$this->data['form2'] = $this->getForm($step, ($this->data['portfolio'] ?? null), $options)->createView();
$this->data['portfolioId'] = $this->session->get('portfolioId');
$this->functionalCurrencyRate = $this->getModel()->getFunctionalCurrencyRate($customer->getFunctionalCurrency());
if (!empty($this->data['portfolio'])) {
$this->data['pair'] = $this->data['portfolio']->getCurrencyPair();
$rateRecord = $this->em->getRepository(CurrencyHistory::class)->findLastRecord($this->data['pair']->getId());
if (!empty($rateRecord)) {
$this->data['rate'] = $rateRecord->getRate();
$this->data['rateLastUpdate'] = $rateRecord->getUpdated();
}
$this->data['majorCurrency'] = $this->data['portfolio']->getCurrencyPair()->getCurrencyNameByNumber(1);
$this->data['minorCurrency'] = $this->data['portfolio']->getCurrencyPair()->getCurrencyNameByNumber(2);
$this->data['functionalCurrency'] = $this->data['majorCurrency'];
$this->data['major'] = substr($this->data['majorCurrency'], 0, 2);
$this->data['minor'] = substr($this->data['minorCurrency'], 0, 2);
}
}
protected function actionsPortfolio($form = null) {
$action = $form->get('delete')->isClicked() ? 'delete' : 'add';
$formData = $form->getData();
if ($action == 'delete') {
if (empty($this->portfolioId)) {
$this->addFlash('warning', 'No portfolio found');
return false;
}
if (!empty($this->portfolioId)) {
$portfolio = $this->em->getRepository(Portfolio::class)->findOneBy([
'status' => 1,
'id' => $this->portfolioId,
'customer' => $this->customerId,
]);
}
if (empty($this->portfolioId)) {
$this->addFlash('warning', 'No portfolio found');
return false;
}
$portfolio->setStatus(false);
$this->em->persist($portfolio);
$this->em->flush();
$this->addFlash('success', 'Portfolio was deleted successfully');
$this->portfolioId = 0;
$this->redirect = true;
} elseif ($action == 'add') {
if (empty($this->portfolioId) || empty($formData->getId())) {
$portfolio = new Portfolio();
$portfolio->setCustomer($this->getCustomer());
$portfolio->setStatus(true);
} else {
$portfolio = $this->em->getRepository(Portfolio::class)->findOneBy([
'status' => 1,
'id' => $this->portfolioId,
'customer' => $this->customerId,
]);
}
$currPair = $formData->getCurrencyPair();
if (empty($currPair)) {
$currPair = $this->em->getRepository(CurrencyPair::class)->find(1);
}
$portfolio->setCurrencyPair($currPair);
$portfolio->setName($formData->getName());
$portfolio->setDescription($formData->getDescription());
$portfolio->setDirection($formData->getDirection());
$portfolio->setType($formData->getType());
$this->em->persist($portfolio);
$this->em->flush();
$this->session->set('portfolioId', $portfolio->getId());
$this->addFlash('success', 'new portfolio was created/updated successfully');
$this->redirect = true;
}
}
protected function getForm($step, $object = null, $options = []) {
switch ($step) {
case self::STEP_PORTFOLIO:
if (empty($object)) {
$object = new Portfolio();
}
$objetType = PortfolioType::class;
break;
}
$options['portfolioId'] = $this->portfolioId;
$options['url'] = $this->url.'&step='.$step;
return $this->createForm($objetType, $object, $options);
}
protected function getTradesOperations($request) {
if (empty($this->data['trade'])) {
return false;
}
$step = self::STEP_TRADES;
/** @var Forward $trade */
$trade = $this->data['trade'];
$object = new ForwardOperations();
$object->setRate($trade->getStrike());
// $object->setDateMaturity($trade->getDateDelivery());
$object->setAmount($trade->getAmountMinor());
$object->setTradeNumber($trade->getTradeNumber());
$object->setRate($trade->getStrike());
$form = $this->getForm('tradesOperations', $object);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->actionsTradesOperations($form);
}
$this->data['tradeOperations'] = $this->em->getRepository(ForwardOperations::class)->findBy(['Trade' => $this->tradeId]);
$this->data['formTradesOperations'] = $form->createView();
if ($form->isSubmitted()) {
return $this->redirect($this->url.'&step='.$step);
}
if (!empty($this->tradeOperationId) && $this->edit == 'delete') {
//todo: ideti tikrinama ar turi teise useris
/** @var ForwardOperations $operationRecord */
$operationRecord = $this->em->getRepository(ForwardOperations::class)->find($this->tradeOperationId);
if (empty($operationRecord)) {
$this->addFlash('warning', 'No trade operation record was found');
return false;
}
$tradeInfo = json_decode($operationRecord->getTradeOldData(), true);
if (!empty($tradeInfo)) {
//atstatome trado info
/** @var Forward $tradeRecord */
$tradeRecord = $this->em->getRepository(Forward::class)->find($operationRecord->getTrade());
if (empty($tradeRecord)) {
$this->addFlash('warning', 'No trade was found');
return false;
}
$tradeRecord->setDateDelivery($tradeInfo['dateDelivery']);
$tradeRecord->setAmount($tradeInfo['amount']);
$tradeRecord->setAmountMinor($tradeInfo['amountMinor']);
$this->em->persist($tradeRecord);
}
$cashflowInfo = json_decode($operationRecord->getCashflowOldData(), true);
if (!empty($cashflowInfo)) {
//atstatome cashflow info
/** @var CashFlows $cashflowRecord */
$cashflowRecord = $this->em->getRepository(CashFlows::class)->find($cashflowInfo['id']);
if (empty($cashflowRecord)) {
$this->addFlash('warning', 'No cashflow was found');
return false;
}
$cashflowRecord->setCashAmount($cashflowInfo['cashAmount']);
$cashflowRecord->setCashAmountMinor($cashflowInfo['cashAmountMinor']);
$this->em->persist($cashflowRecord);
}
if ($operationRecord->getAction() == 'extension' && !empty($operationRecord->getExtensionTradeId())) {
$forwardId = $operationRecord->getExtensionTradeId();
$extensionTradeRecord = $this->em->getRepository(Forward::class)->find($forwardId);
if (!empty($extensionTradeRecord)) {
$swapRecord = $this->em->getRepository(Swap::class)->findOneBy(['Forward' => $forwardId]);
if (!empty($swapRecord)) {
$this->em->remove($swapRecord);
}
if (!empty($extensionTradeRecord->getCommittedCashflows())) {
foreach ($extensionTradeRecord->getCommittedCashflows() as $cashflow) {
$this->em->remove($cashflow);
}
}
$this->em->remove($extensionTradeRecord);
}
}
$this->em->remove($operationRecord);
$this->em->flush();
$this->addFlash('success', 'Trade operation was deleted and trade info was restored successfully ');
$this->redirect = true;
}
}
/**
* @param $form
* @return false|void
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
protected function actionsTradesOperations($form) {
if (empty($this->tradeId)) {
return false;
}
$formData = $form->getData();
$trade = $this->data['trade'];
$this->fillTradeOperationRecord($formData, $trade);
/** @var Forward $tradeParent */
$tradeParent = $this->data['trade'];
$amount = $tradeParent->getAmountMinor() - $formData->getAmount();
$newDate = $formData->getDateMaturity();
if ($this->tradeOperation == 'extension') {
if ($amount < 0) {
$this->addFlash('warning', 'Amount cannot be greater than the original trade amount');
return false;
}
if ($newDate < $tradeParent->getDateDelivery()) {
$this->addFlash('warning', 'New date cannot be earlier than the original trade date');
return false;
}
if ($amount == 0) { //koreguojam tik trade ir flowso datas
$newTrade = new Forward();
$newTrade->setPortfolio($this->data['portfolio']);
$newTrade->setAmountMinor($formData->getAmount());
$newTrade->setDateDelivery($formData->getDateMaturity());
//reik sukurti ir cashflowsa nauja siai sumai
$this->updateCashflows($tradeParent, $newTrade, $action = 'update');
$tradeParent->setDateDelivery($newDate);
$this->em->persist($tradeParent);
$this->em->flush();
return;
}
if ($amount > 0) {
//mazinam seno trado amounta ir sukurti nauja trade
//mazinam senam flowsui amounta ir sukurti nauja flowsa pagal nauja data ir amounta
$newTrade = $this->createTradeExtension($tradeParent, $this->tradeOperationRecord);
$this->updateCashflows($tradeParent, $newTrade, $action = 'extension');
}
} elseif ($this->tradeOperation == 'drawdown') {
//koreguojam seno trade suma
//dump($formData);
$tradeParent->setStrike($formData->getRate());
$tradeParent->setAmountMinor($amount);
$tradeParent->setAmount($amount / $tradeParent->getStrike());
//dump($tradeParent);
$this->em->persist($tradeParent);
$this->em->flush();
// mazinam cashflowso amount
$this->updateCashflows($tradeParent, null, $this->tradeOperation);
$this->em->flush();
}
if (!empty($newTrade)) {
$this->tradeOperationRecord->setExtensionTradeId($newTrade->getId());
}
$this->em->persist($this->tradeOperationRecord);
$this->em->flush();
$this->addFlash('success', 'Trade operation was created successfully');
$this->redirect = true;
}
/**
* @param Forward $trade
* @param $cashflows
* @return mixed
*/
protected function setRelatedCashFlows($trade) {
if (empty($trade->getCommittedCashflows())) {
return null;
}
$relatedCashFlows = [];
foreach ($trade->getCommittedCashflows() as $item) {
$relatedCashFlows[] = $item->getId();
}
return $relatedCashFlows;
}
protected function fillTradeOperationRecord($formData, $trade) {
$this->tradeOperationRecord = new ForwardOperations();
$this->tradeOperationRecord->setAmount($formData->getAmount());
$this->tradeOperationRecord->setDateMaturity($formData->getDateMaturity());
$this->tradeOperationRecord->setRate($formData->getRate());
$this->tradeOperationRecord->setComment($formData->getComment());
$this->tradeOperationRecord->setTradeNumber($formData->getTradeNumber());
$this->tradeOperationRecord->setAction($this->tradeOperation);
$this->tradeOperationRecord->setTrade($trade);
$tradeOldData = [
'tradeNumber' => $trade->getTradeNumber(),
'dateDelivery' => $trade->getDateDelivery(),
'amount' => (int)$trade->getAmount(),
'amountMinor' => (int)$trade->getAmountMinor(),
'strike' => $trade->getStrike(),
'policyRatio' => $trade->getPolicyRatio(),
'relatedCashFlows' => $this->setRelatedCashFlows($trade),
];
$this->tradeOperationRecord->setTradeOldData(json_encode($tradeOldData));
$this->em->persist($this->tradeOperationRecord);
}
/**
* @param CashFlows $cashflow
* @return void
*/
protected function collectOldDataForRestore($cashflow) {
$cashflowOldData = [
'id' => $cashflow->getId(),
'cashAmount' => (int)$cashflow->getCashAmount(),
'cashAmountMinor' => (int)$cashflow->getCashAmountMinor(),
'flowDate' => (int)$cashflow->getFlowDate(),
];
$this->setTradeOperationByParam('cashflowOldData', json_encode($cashflowOldData));
}
protected function setTradeOperationByParam($param, $value) {
$methodName = 'set'.ucfirst($param);
if (method_exists($this->tradeOperationRecord, $methodName)) {
$this->tradeOperationRecord->$methodName($value);
}
$this->em->persist($this->tradeOperationRecord);
}
protected function createTradeExtension($tradeParent, $formData) {
/** @var Forward $tradeParent */
$tradeParent = $this->data['trade'];
/// naujas trade
$tradeRecord = new Forward();
$tradeRecord->setPortfolio($this->data['portfolio']);
$tradeRecord->setParentId($tradeParent->getId());
$tradeRecord->setCurrencyPair($tradeParent->getCurrencyPair());
$tradeRecord->setAmount($formData->getAmount() / $formData->getRate());
$tradeRecord->setAmountMinor($formData->getAmount());
$tradeRecord->setDateExpire($tradeParent->getDateExpire());
$tradeRecord->setDateDelivery($formData->getDateMaturity());
$tradeRecord->setExposureDirection($tradeParent->getExposureDirection());
$tradeRecord->setStatus(true);
$tradeRecord->setStrike($formData->getRate());
$tradeRecord->setCounterparty($tradeParent->getCounterparty());
$tradeRecord->setComment($formData->getComment());
$tradeRecord->setTradeNumber($formData->getTradeNumber());
$dateExpire = date_create($tradeRecord->getDateExpire());
$tradeRecord->setRate($this->getRate($tradeRecord->getCurrencyPair(), $dateExpire->format('Y-m-d')));
$hedgePolicyRatio = $this->getHedgePolicy($this->currrentHedgingPolicy, $dateExpire->format('Y'), $dateExpire->format('W'));
$tradeRecord->setPolicyRatio($hedgePolicyRatio);
if (!empty($tradeParent->getCommittedCashflows())) {
foreach ($tradeParent->getCommittedCashflows() as $cashflow) {
$tradeRecord->addCommittedCashflows($cashflow);
}
}
$this->em->persist($tradeRecord);
$this->em->flush();
//$tradeOperationRecord->setExtensionTradeId($tradeRecord->getId());
return $tradeRecord;
}
protected function updateCashflows($tradeParent, $newTrade, $action) {
return; //specifika priklauso pagal tipa, ziureti child klases
}
/**
* naudoja ajax route /analysis/{portfolioId}/{rate}
* @param $portfolioId
* @param $rate
* @return JsonResponse
*/
public function analysisAjax(CacheItemPoolInterface $cache, Request $request, Connection $connection) {
parent::initialize($request);
$this->cache = $cache;
$this->connection = $connection;
$this->session = $this->container->get('session');
$portfolioId = $request->get('portfolioId') ?? '';
$this->portfolioId = $portfolioId;
$rate = $request->get('rate') ?? '';
$method = $request->get('analysisMethod') ?? '';
if (empty((int)$portfolioId) || empty((float)$rate)) {
return new JsonResponse('error data', 400);
}
$portfolio = $this->em->getRepository(Portfolio::class)->findOneBy([
'id' => $portfolioId,
'customer' => $this->getCustomer()->getId(),
], ['id' => 'DESC']);
if (empty($portfolio)) {
return new JsonResponse('unauthorized access', 400);
}
$trades = $this->em->getRepository(Forward::class)->findByDates([
'Portfolio' => (int)$portfolioId,
'show' => 'current',
'type_not' => 'spot',
]);
$cashflows = $this->em->getRepository(CashFlows::class)->findByDates([
'Portfolio' => (int)$portfolioId,
'show' => 'current',
]);
$budgetRates = $this->em->getRepository(BudgetRates::class)->findByDates(['Portfolio' => (int)$this->portfolioId]);
$data = [
'cashFlows' => $cashflows,
'trades' => $trades,
'budgetRates' => $budgetRates,
];
$budgetRates = $method == 'budget' ? $this->getBudgetRateList($data) : [];
$this->getModel()->getFunctionalCurrencyRate($this->getFunctionalCurrency());
$analysis['trades'] = $this->getModel()->tradeValuation($trades, (float)$rate, $budgetRates, $cashflows);
$forwardPoints = [0 => ['bid' => $rate]];
$forwardPointsByPair = $this->getForwardPoints($portfolio->getCurrencyPair()->getName());
if (!empty($forwardPointsByPair)) {
$forwardPoints += $forwardPointsByPair;
}
$analysis['totalValuation'] = 0;
$periods = [];
if (!empty($analysis['trades']['diffByMonth'])) {
$analysis['totalValuation'] = round(array_sum($analysis['trades']['diffByMonth']));
$periods = array_keys($analysis['trades']['diffByMonth']);
}
//vykdomas vertinimas trade ir cashflows
$analysis['cashflows']['diffByMonth'] = [];
$portfolioDirection = $portfolio->getDirection();
try {
$analysis['cashflows'] = $this->getModel()->cashflowValuation($cashflows, $budgetRates, $portfolioDirection, (float)$rate, $analysis['trades'] ?? []);
} catch (\Exception $e) {
return new JsonResponse('error on cashflows valuation calcs', 200);
}
if ($method == 'budget') {
if (!empty($analysis['cashflows']['diffByMonth'])) {
$analysis['totalValuation'] += round(array_sum($analysis['cashflows']['diffByMonth']));
}
}
// $spot = $this->getRate($portfolio->getCurrencyPair());
foreach ($forwardPoints as $days => $points) {
$period = date_create(' + '.$days.' days')->format('Y-m');
// $pointDiff = (float)$points['bid'] - $spot;
// $pointDiff = 1 + $pointDiff / $spot;
// $analysis['forwards'][$period] = round((float)$rate * $pointDiff, 5);
if (empty($days)) {
$analysis['forwards'][$period] = (float)$rate;
}
if (!empty($analysis['cashflows']) && empty($analysis['cashflows']['diffByMonth'][$period])) {
$analysis['cashflows']['diffByMonth'][$period] = 0;
ksort($analysis['cashflows']['diffByMonth']);
}
if (!empty($analysis['trades']) && empty($analysis['trades']['diffByMonth'][$period])) {
$analysis['trades']['diffByMonth'][$period] = 0;
ksort($analysis['trades']['diffByMonth']);
}
}
foreach ($periods as $period) {
if (empty($analysis['forwards'][$period])) {
$analysis['forwards'][$period] = 'null';
}
}
$analysis['minValue'][1] = $this->getModel()->getMin($analysis['trades']['hedgeRates'] ?? [], $analysis['cashflows']['budgetRateByMonth'] ?? []);
$analysis['maxValue'][1] = $this->getModel()->getMax($analysis['trades']['hedgeRates'] ?? [], $analysis['cashflows']['budgetRateByMonth'] ?? []);
return new JsonResponse($analysis, 200);
}
/**
* @return Report
*/
protected function getReportModel($renew = false) {
if (empty($this->reportModel) || $renew) {
$excel = $this->get('Excel');
$this->reportModel = new Report($this->em, $excel);
}
return $this->reportModel;
}
protected function getEventAlertStatuses() {
$this->marginCalls = []; //pagal gauta final kursa, patikrinama, ar spotas nevirsyja budget Rate
$statuses = [];
$actionModel = new Actions($this->connection, $this->data['cashFlows']);
foreach ($this->data['cashFlows'] as $item) {
$flowId = $item->getId();
$finalRate = $actionModel->getFinalPointsCashflow($item);
$this->marginCalls[$flowId] = $finalRate != '-' ? round($finalRate, 5) : $finalRate;
$statuses[$flowId] = $actionModel::ALERT_STATUS_DISABLED;
if (!empty($finalRate) && $finalRate !== '-') {
$statuses[$flowId] = $actionModel::ALERT_STATUS_READY;
if ($this->hasAlert($flowId)) {
$statuses[$flowId] = $actionModel::ALERT_STATUS_ACTIVE;
}
}
}
return $statuses;
}
protected function hasAlert($flowId) {
if (empty($this->eventAlerts)) {
$eventAlerts = $this->em->getRepository(Event::class)->findBy([
'User' => $this->getUser(),
'objectType' => 'flow',
'active' => true,
]);
foreach ($eventAlerts as $item) {
$this->eventAlerts[$item->getFlowId()] = $item;
}
}
return !empty($this->eventAlerts[$flowId]);
}
protected function notificationsAsSeen() {
$user = $this->getUser();
$portfolioId = $this->portfolioId;
$seenMessages = $this->em->getRepository(Notification::class)->unseenMessagesBy($user, $portfolioId);
if (empty($seenMessages)) {
return true;
}
foreach ($seenMessages as $item) {
$item->setSeen(true);
$this->em->persist($item);
$this->em->flush();
}
return true;
}
protected function getHedgePolicy(HedgingPolitics $currentPolicy = null, $years, $week) {
return 1;
}
/**
* @param $flowId
* @param $type
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function callAlert($flowId, $type) {
return $this->forward('Bundles\Messenger\Controller\EventController::index', [
'flowId' => $flowId,
'type' => $type,
]);
}
public function getPortfoliosByCompany($companyId, PortfolioRepository $portfolioRepository): JsonResponse {
if (empty($companyId)) {
return new JsonResponse(['error' => 'Company ID is required'], 400);
}
$portfolios = $portfolioRepository->findBy(['status' => 1, 'customer' => $companyId]);
$data = array_map(function ($p) {
return ['id' => $p->getId(), 'name' => $p->getName()];
}, $portfolios);
return new JsonResponse($data);
}
}