Initial commit
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Helper\Currency;
|
||||
use App\Helper\MyReader;
|
||||
use App\Helper\ReaderSheet;
|
||||
use App\Helper\SheetData;
|
||||
use App\Helper\DividendsSummary;
|
||||
use App\Services\CryptoService;
|
||||
use App\Services\DividendsService;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Validator\Constraints\All;
|
||||
use Symfony\Component\Validator\Constraints\File;
|
||||
|
||||
class TaxesController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route("/taxes", name="app_taxes")
|
||||
*/
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$a=[];
|
||||
$form = $this->createFormBuilder([])
|
||||
->add("uploads",FileType::class, [
|
||||
'data_class' => null,
|
||||
'multiple' => true,
|
||||
'attr'=>[
|
||||
'multiple' => 'multiple',
|
||||
],
|
||||
// 'constraints' => [
|
||||
// new All([
|
||||
// 'constraints' => [
|
||||
// new File([
|
||||
// 'maxSize' => '2048k',
|
||||
// 'mimeTypes' => [
|
||||
// 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
// 'application/atom+xml',
|
||||
// 'application/xml',
|
||||
// 'text/xml',
|
||||
// 'text/xml-external-parsed-entity',
|
||||
//// 'application/x-pdf',
|
||||
// ],
|
||||
// 'mimeTypesMessage' => 'Please upload a valid XLSX or XML document',
|
||||
// ])
|
||||
// ]
|
||||
// ])
|
||||
// ],
|
||||
])
|
||||
->add("upload",SubmitType::class)
|
||||
->getForm();
|
||||
$form->handleRequest($request);
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$files = $form->get('uploads')->getData();
|
||||
$hash = substr(md5(rand()),0,16);
|
||||
if ($files) {
|
||||
$i=1;
|
||||
/** @var UploadedFile $file */
|
||||
foreach ($files as $file) {
|
||||
$file->move(
|
||||
$this->getParameter("uploads_path")."/".$hash,
|
||||
$i.".".$file->getClientOriginalExtension()
|
||||
);
|
||||
$i++;
|
||||
}
|
||||
return $this->redirectToRoute("app_taxes_show",["hash" => $hash]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderForm('taxes/index.html.twig', [
|
||||
'controller_name' => 'TaxesController',
|
||||
'form' => $form,
|
||||
'sheet' => $a
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/taxes/{hash}", name="app_taxes_show")
|
||||
*/
|
||||
public function show(CryptoService $tax) : Response
|
||||
{
|
||||
if ($tax->readFiles()) {
|
||||
$gen = $tax->generate();
|
||||
return $this->render("taxes/show.html.twig", [
|
||||
"taxes" => $gen->getSummaryByCountry(),
|
||||
"error" => $gen->error
|
||||
]);
|
||||
}
|
||||
return new Response("error");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\ExchangeRatesRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\ORM\Mapping\Index;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass=ExchangeRatesRepository::class)
|
||||
* @ORM\Table(indexes={@Index(name="currency", columns={"date_date","str_currency"})})
|
||||
*/
|
||||
class ExchangeRates
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=3)
|
||||
*/
|
||||
private $strCurrency;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="float")
|
||||
*/
|
||||
private $intRate;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date")
|
||||
*/
|
||||
private $dateDate;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getStrCurrency(): ?string
|
||||
{
|
||||
return $this->strCurrency;
|
||||
}
|
||||
|
||||
public function setStrCurrency(string $strCurrency): self
|
||||
{
|
||||
$this->strCurrency = $strCurrency;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIntRate(): ?float
|
||||
{
|
||||
return $this->intRate;
|
||||
}
|
||||
|
||||
public function setIntRate(float $intRate): self
|
||||
{
|
||||
$this->intRate = $intRate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->dateDate;
|
||||
}
|
||||
|
||||
public function setDateDate(\DateTimeInterface $dateDate): self
|
||||
{
|
||||
$this->dateDate = $dateDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Entity\ExchangeRates;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
class Currency
|
||||
{
|
||||
public static array $currencies = ["USD","GBP","PLN"];
|
||||
private static string $apiUrl = "https://api.nbp.pl/api/exchangerates/rates/a/:code/:date/?format=json";
|
||||
private EntityManager $manager;
|
||||
private array $ratesPerDate;
|
||||
|
||||
public function __construct(EntityManager $manager)
|
||||
{
|
||||
$this->manager = $manager;
|
||||
$this->takeRates();
|
||||
}
|
||||
|
||||
public function getRate(string $currency, \DateTime $dateTime, &$err) : float
|
||||
{
|
||||
$dayOfWeek = $dateTime->format("N");
|
||||
$minusDay = 1;
|
||||
if ($dayOfWeek == 7){
|
||||
$minusDay = 2;
|
||||
} elseif ($dayOfWeek == 1) {
|
||||
$minusDay = 3;
|
||||
}
|
||||
$dateTime->modify("-$minusDay days");
|
||||
$dateStr = $dateTime->format("Ymd");
|
||||
|
||||
if (isset($this->ratesPerDate[$currency]) && isset($this->ratesPerDate[$currency][$dateStr])) {
|
||||
return $this->ratesPerDate[$currency][$dateStr];
|
||||
}
|
||||
$dateCopy = clone $dateTime;
|
||||
|
||||
do {
|
||||
$rate = $this->takePLNOnDate($currency, $dateCopy->format("Y-m-d"));
|
||||
if (!$rate) {
|
||||
$dateCopy->modify("-1 day");
|
||||
}
|
||||
}while($rate == 0);
|
||||
|
||||
if ($rate) {
|
||||
$ratesEntity = new ExchangeRates();
|
||||
$ratesEntity->setIntRate(intval($rate * 10000));
|
||||
$ratesEntity->setStrCurrency($currency);
|
||||
$ratesEntity->setDateDate($dateTime);
|
||||
|
||||
$this->manager->persist($ratesEntity);
|
||||
$this->manager->flush();
|
||||
$this->ratesPerDate[$currency][$dateStr] = $rate;
|
||||
return $rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private function takePLNOnDate(string $currency, string $dateStr) : float
|
||||
{
|
||||
if (!in_array($currency, self::$currencies)) {
|
||||
return 0;
|
||||
}
|
||||
$url = strtr(self::$apiUrl,[
|
||||
":code" => mb_strtolower($currency),
|
||||
":date" => str_replace(".","-",$dateStr)
|
||||
]);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$result=curl_exec($ch);
|
||||
curl_close($ch);
|
||||
$data = json_decode($result, true);
|
||||
if (!isset($data['rates']) || !isset($data['rates'][0]) || !isset($data['rates'][0]['mid'])) {
|
||||
return 0;
|
||||
}
|
||||
return $data['rates'][0]['mid'];
|
||||
}
|
||||
|
||||
private function takeRates()
|
||||
{
|
||||
$rates = $this->manager->getRepository(ExchangeRates::class);
|
||||
$rates = $rates->findAll();
|
||||
|
||||
if ($rates) {
|
||||
/** @var ExchangeRates $rate */
|
||||
foreach ($rates as $rate) {
|
||||
if (!isset($this->ratesPerDate[$rate->getStrCurrency()])) {
|
||||
$this->ratesPerDate[$rate->getStrCurrency()] = [];
|
||||
}
|
||||
$this->ratesPerDate[$rate->getStrCurrency()][$rate->getDateDate()->format("Ymd")] = $rate->getIntRate()/10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Helper\DataNeed;
|
||||
|
||||
use App\Logic\Crypto\MainObject;
|
||||
|
||||
final class CryptoValues
|
||||
{
|
||||
private static array $values = [
|
||||
"values" => ["Wartość","Values"],
|
||||
"currency" => ["Currency", "Waluta"],
|
||||
"date" => ["Data operacji"],
|
||||
"desc" => ["Rodzaj"]
|
||||
];
|
||||
|
||||
public static function isValue(string $type, string $text) : bool
|
||||
{
|
||||
if (!isset(self::$values[$type])) {
|
||||
return false;
|
||||
}
|
||||
$ret = false;
|
||||
foreach (self::$values[$type] as $value) {
|
||||
if (strpos($text,$value) !== false) {
|
||||
$ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function isInOut(MainObject $mainObject) : bool
|
||||
{
|
||||
$arr = [
|
||||
"Wypłata środków","Blokada środków","Wpłata na rachunek"
|
||||
];
|
||||
$ret = false;
|
||||
foreach ($arr as $item) {
|
||||
if ($mainObject->getDesc() === $item) {
|
||||
$ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper\FIFO;
|
||||
|
||||
use App\Helper\Currency;
|
||||
use App\Helper\DataNeed\CryptoValues;
|
||||
use App\Logic\Crypto\MainObject;
|
||||
|
||||
class Crypto extends Main
|
||||
{
|
||||
public function takeSumTransactions() : array
|
||||
{
|
||||
$all = $this->takeAllRealTransactions(CryptoValues::class);
|
||||
if (!$all || count($all) < 1) {
|
||||
return [];
|
||||
}
|
||||
$sum = [
|
||||
];
|
||||
|
||||
/** @var MainObject $item */
|
||||
foreach ($all as $item) {
|
||||
if (!in_array($item->getCurrency(), Currency::$currencies)) {
|
||||
if ($item->getValue() == 0) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($sum[$item->getCurrency()])) {
|
||||
$sum[$item->getCurrency()] = [];
|
||||
if (!isset($sum[$item->getCurrency()][$item->getDateTime()->format("Y-m-d")])){
|
||||
$sum[$item->getCurrency()][$item->getDateTime()->format("Y-m-d")] = [];
|
||||
}
|
||||
}
|
||||
$sum[$item->getCurrency()][$item->getDateTime()->format("Y-m-d")][] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Helper\FIFO;
|
||||
|
||||
use App\Helper\Currency;
|
||||
use App\Helper\DataNeed\CryptoValues;
|
||||
use App\Logic\Crypto\MainObject;
|
||||
|
||||
class Main
|
||||
{
|
||||
protected array $data;
|
||||
|
||||
public function __construct(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
protected function takeAllRealTransactions(string $abstract): array
|
||||
{
|
||||
$tmp = [];
|
||||
$keys = array_shift($this->data);
|
||||
$names = [];
|
||||
|
||||
foreach ($keys as $keyId => $key) {
|
||||
/** @var CryptoValues $abstract */
|
||||
if ($abstract::isValue("values",$key)) {
|
||||
$names[$keyId] = "setValue";
|
||||
}
|
||||
if ($abstract::isValue("date",$key)) {
|
||||
$names[$keyId] = "setDateTime";
|
||||
}
|
||||
if ($abstract::isValue("currency",$key)) {
|
||||
$names[$keyId] = "setCurrency";
|
||||
}
|
||||
if ($abstract::isValue("desc",$key)) {
|
||||
$names[$keyId] = "setDesc";
|
||||
}
|
||||
}
|
||||
foreach ($this->data as $datum) {
|
||||
$obj = new MainObject();
|
||||
foreach ($names as $key => $name) {
|
||||
if ($name === "setValue") {
|
||||
$datum[$key] = floatval($datum[$key]);
|
||||
}
|
||||
if ($name === "setDateTime") {
|
||||
$datum[$key] = new \DateTime($datum[$key]);
|
||||
}
|
||||
$obj->$name($datum[$key]);
|
||||
}
|
||||
$tmp[] = $obj;
|
||||
}
|
||||
return $tmp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Helper\Sheets;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
||||
class ReadSheet
|
||||
{
|
||||
private string $filePath;
|
||||
private array $arr=[];
|
||||
|
||||
public function __construct(string $file)
|
||||
{
|
||||
if (file_exists($file)){
|
||||
$this->filePath = $file;
|
||||
}
|
||||
}
|
||||
|
||||
public function getAll() : array
|
||||
{
|
||||
return $this->arr;
|
||||
}
|
||||
|
||||
public function takeFile() : bool
|
||||
{
|
||||
if (!$this->filePath) {
|
||||
return false;
|
||||
}
|
||||
$fileType = explode(".", $this->filePath);
|
||||
|
||||
$reader = IOFactory::createReader(ucfirst($fileType[1]));
|
||||
$reader->setLoadAllSheets();
|
||||
$reader->setReadDataOnly(true);
|
||||
$spreadsheet = $reader->load($this->filePath);
|
||||
foreach ($spreadsheet->getAllSheets() as $sheetName) {
|
||||
$this->arr[] = $sheetName->toArray();
|
||||
}
|
||||
|
||||
return count($this->arr) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
|
||||
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||
|
||||
class Kernel extends BaseKernel
|
||||
{
|
||||
use MicroKernelTrait;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Logic\Crypto;
|
||||
|
||||
class MainObject
|
||||
{
|
||||
private \DateTime $dateTime;
|
||||
private string $desc;
|
||||
private float $value;
|
||||
private string $currency;
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getDateTime(): \DateTime
|
||||
{
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $dateTime
|
||||
*/
|
||||
public function setDateTime(\DateTime $dateTime): void
|
||||
{
|
||||
$this->dateTime = $dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDesc(): string
|
||||
{
|
||||
return $this->desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $desc
|
||||
*/
|
||||
public function setDesc(string $desc): void
|
||||
{
|
||||
$this->desc = $desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getValue(): float
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $value
|
||||
*/
|
||||
public function setValue(float $value): void
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrency(): string
|
||||
{
|
||||
return $this->currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $currency
|
||||
*/
|
||||
public function setCurrency(string $currency): void
|
||||
{
|
||||
$this->currency = $currency;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
final class DividendsData
|
||||
{
|
||||
private int $tax;
|
||||
private int $count;
|
||||
private float $value;
|
||||
private string $currency;
|
||||
private string $isin;
|
||||
private \DateTime $dateTime;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIsin(): string
|
||||
{
|
||||
return $this->isin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $isin
|
||||
*/
|
||||
public function setIsin(string $isin): void
|
||||
{
|
||||
$this->isin = $isin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getDateTime(): \DateTime
|
||||
{
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $dateTime
|
||||
*/
|
||||
public function setDateTime(\DateTime $dateTime): void
|
||||
{
|
||||
$this->dateTime = $dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTax(): int
|
||||
{
|
||||
return $this->tax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $tax
|
||||
*/
|
||||
public function setTax(int $tax): void
|
||||
{
|
||||
$this->tax = $tax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCount(): int
|
||||
{
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
*/
|
||||
public function setCount(int $count): void
|
||||
{
|
||||
$this->count = $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getValue(): float
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $value
|
||||
*/
|
||||
public function setValue(float $value): void
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrency(): string
|
||||
{
|
||||
return $this->currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $currency
|
||||
*/
|
||||
public function setCurrency(string $currency): void
|
||||
{
|
||||
$this->currency = $currency;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
use App\Helper\Currency;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
class DividendsSummary
|
||||
{
|
||||
/** @var SheetData|array $sheetData */
|
||||
private array $sheetData=[];
|
||||
/** @var XMLReader|array $sheetData */
|
||||
private array $xmlData=[];
|
||||
private Currency $currencyObj;
|
||||
public array $error=[];
|
||||
private array $allData=[];
|
||||
private array $countryToCurrency=[];
|
||||
|
||||
public function __construct(EntityManager $manager)
|
||||
{
|
||||
$this->currencyObj = new Currency($manager);
|
||||
}
|
||||
|
||||
public function getSummaryByCountry() : array
|
||||
{
|
||||
$return=[];
|
||||
$this->countFromSheets();
|
||||
|
||||
if (count($this->allData) > 0) {
|
||||
$sum = 0;
|
||||
foreach ($this->allData as $key => $item) {
|
||||
$val = round($item, 2);
|
||||
$sum += $val;
|
||||
$return[$key] = [
|
||||
"country" => \Locale::getDisplayRegion("-".$key),
|
||||
"value" => $val,
|
||||
"currency" => $this->countryToCurrency[$key]
|
||||
];
|
||||
}
|
||||
$return['sum'] = intval(ceil($sum));
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function countFromSheets() : void
|
||||
{
|
||||
if (!count($this->sheetData)) {
|
||||
return;
|
||||
}
|
||||
$test=[];
|
||||
$countryToCurrency=[];
|
||||
/** @var SheetData $sheetDatum */
|
||||
foreach ($this->sheetData as $sheetDatum) {
|
||||
$all = $sheetDatum->getByCountry();
|
||||
foreach ($all as $country => $item) {
|
||||
/** @var DividendsData $val */
|
||||
foreach ($item as $val) {
|
||||
if (!isset($test[$country])) $test[$country] = 0;
|
||||
$test[$country] += $this->count($val);
|
||||
if (!isset($countryToCurrency[$country])) {
|
||||
$countryToCurrency[$country] = $val->getCurrency();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->allData = array_merge($this->allData,$test);
|
||||
$this->countryToCurrency = array_merge($this->countryToCurrency,$countryToCurrency);
|
||||
}
|
||||
|
||||
private function getRate(DividendsData $data) : float
|
||||
{
|
||||
return $this->currencyObj->getRate($data->getCurrency(),$data->getDateTime(),$this->error);
|
||||
}
|
||||
|
||||
private function count(DividendsData $data) : float
|
||||
{
|
||||
$value = round($data->getCount()*$data->getValue(),2);
|
||||
$tax = 19;
|
||||
if ($data->getTax() > 0) {
|
||||
$tax = 4;
|
||||
}
|
||||
$valueTax = round($value * $tax / 100);
|
||||
$rate = $this->getRate($data);
|
||||
if ($rate > 0) {
|
||||
return $valueTax * $rate;
|
||||
}
|
||||
$this->error[]=$data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SheetData $sheetData
|
||||
*/
|
||||
public function addSheetData(SheetData $sheetData): void
|
||||
{
|
||||
$this->sheetData[] = $sheetData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param XMLReader $reader
|
||||
*/
|
||||
public function addXml(XMLReader $reader)
|
||||
{
|
||||
$this->xmlData[] = $reader;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
use App\Helper\Currency;
|
||||
|
||||
class SheetData
|
||||
{
|
||||
private array $rawData;
|
||||
// eg. 0 -> name, 1 -> ISIN
|
||||
private array $dataIndex;
|
||||
private array $data;
|
||||
|
||||
public function __construct(array $data)
|
||||
{
|
||||
$this->rawData = $data;
|
||||
}
|
||||
|
||||
public function get() : array
|
||||
{
|
||||
if (isset($this->data)) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$needIndex = [];
|
||||
foreach ($this->rawData as $index => $rawDatum) {
|
||||
if ($index === 0) {
|
||||
$this->dataIndex = $rawDatum;
|
||||
continue;
|
||||
}
|
||||
$setDatas=[];
|
||||
foreach ($rawDatum as $i => $data) {
|
||||
$dataType = $this->getDataType($data,$setDatas);
|
||||
if ($dataType){
|
||||
$needIndex[$i] = $dataType;
|
||||
}
|
||||
}
|
||||
unset($setDatas);
|
||||
break;
|
||||
}
|
||||
$ret = [];
|
||||
foreach ($this->rawData as $index => $datum) {
|
||||
if ($index === 0) {
|
||||
continue;
|
||||
}
|
||||
$row=[];
|
||||
foreach ($datum as $i => $d) {
|
||||
if (isset($needIndex[$i])) {
|
||||
$row[$needIndex[$i]] = $d;
|
||||
}
|
||||
}
|
||||
$dividendObj = new DividendsData();
|
||||
$dividendObj->setCount($row['count']);
|
||||
$dividendObj->setIsin($row['isin']);
|
||||
$dividendObj->setCurrency($row['currency']);
|
||||
$dividendObj->setTax($row['tax']);
|
||||
$dividendObj->setValue($row['value']);
|
||||
$dividendObj->setDateTime(new \DateTime(str_replace(".","-",$row['date'])));
|
||||
$ret[] = $dividendObj;
|
||||
}
|
||||
$this->data = $ret;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function getByCountry() : array
|
||||
{
|
||||
$data = $this->get();
|
||||
if (!$data) {
|
||||
return [];
|
||||
}
|
||||
$newArr = [];
|
||||
/** @var DividendsData $datum */
|
||||
foreach ($data as $datum) {
|
||||
$key = mb_substr($datum->getIsin(), 0, 2);
|
||||
$newArr[$key][] = $datum;
|
||||
}
|
||||
|
||||
return $newArr;
|
||||
}
|
||||
|
||||
public function takeColumnNames() : array
|
||||
{
|
||||
return $this->dataIndex;
|
||||
}
|
||||
|
||||
private function getDataType($data,&$setDatas) : ?string
|
||||
{
|
||||
if (is_int($data)){
|
||||
$ret = "count";
|
||||
$count = &$setDatas['int'];
|
||||
if ($count===1){
|
||||
$ret = "tax";
|
||||
}
|
||||
if ($count > 1) {
|
||||
$ret = null;
|
||||
}
|
||||
$count++;
|
||||
return $ret;
|
||||
}
|
||||
if (is_float($data)) {
|
||||
$ret = "value";
|
||||
$count = &$setDatas['float'];
|
||||
if ($count > 0) {
|
||||
$ret = null;
|
||||
}
|
||||
$count++;
|
||||
return $ret;
|
||||
}
|
||||
if (in_array(mb_substr($data, 0, 2), ['CA', 'US', 'IE', 'GB']) && intval(mb_substr($data, 2, 1))>0) {
|
||||
$count = &$setDatas['data'];
|
||||
$ret = "isin";
|
||||
if ($count > 0) {
|
||||
$ret = null;
|
||||
}
|
||||
$count++;
|
||||
return $ret;
|
||||
}
|
||||
if (in_array($data, Currency::$currencies)) {
|
||||
return "currency";
|
||||
}
|
||||
if (count(explode(".", $data)) === 3) {
|
||||
return "date";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
|
||||
class XMLReader
|
||||
{
|
||||
private string $filePath;
|
||||
private array $datas=[];
|
||||
|
||||
public function __construct(string $file)
|
||||
{
|
||||
if (file_exists($file)){
|
||||
$this->filePath = $file;
|
||||
}
|
||||
}
|
||||
|
||||
public function readFile()
|
||||
{
|
||||
if (!is_file($this->filePath)) {
|
||||
return;
|
||||
}
|
||||
$a = $this->tryCashTransaction();
|
||||
$xml = simplexml_load_file($this->filePath, null, LIBXML_NOCDATA);
|
||||
$json = json_encode($xml);
|
||||
$arr = json_decode($json, true);
|
||||
$this->findValues($arr);
|
||||
}
|
||||
|
||||
private function tryCashTransaction()
|
||||
{
|
||||
$obj = new \DOMDocument();
|
||||
$obj->load($this->filePath);
|
||||
$node = $obj->getElementsByTagName("CashTransaction");
|
||||
if (count($node) < 1) {
|
||||
return;
|
||||
}
|
||||
foreach ($node as $item) {
|
||||
$values = explode(" ", $item->getAttribute('description'));
|
||||
dd($values);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function findValues(array $arr)
|
||||
{
|
||||
$obj = new DividendsData();
|
||||
$isset=false;
|
||||
foreach ($arr as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$this->findValues($value);
|
||||
} else {
|
||||
$isset=true;
|
||||
if ($key === "currency") {
|
||||
$obj->setCurrency($value);
|
||||
}
|
||||
if ($key === "payDate") {
|
||||
$tmp = str_split($value, 4);
|
||||
$y=$tmp[0];
|
||||
$tmp = str_split($tmp[1],2);
|
||||
$d = $tmp[1];
|
||||
$m = $tmp[0];
|
||||
|
||||
// $a = implode("-", array_merge(str_split($tmp[1],2),$tmp[0]));
|
||||
// print_r($a);
|
||||
$obj->setDateTime(new \DateTime("$y-$m-$d"));
|
||||
}
|
||||
if ($key === "quantity") {
|
||||
$obj->setCount(intval($value));
|
||||
}
|
||||
if ($key === "isin") {
|
||||
$obj->setIsin($value);
|
||||
}
|
||||
if ($key === "grossRate") {
|
||||
$obj->setValue(floatval($value));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
if ($isset) {
|
||||
$this->datas[] = $obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\ExchangeRates;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\OptimisticLockException;
|
||||
use Doctrine\ORM\ORMException;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method ExchangeRates|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method ExchangeRates|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method ExchangeRates[] findAll()
|
||||
* @method ExchangeRates[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ExchangeRatesRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ExchangeRates::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ORMException
|
||||
* @throws OptimisticLockException
|
||||
*/
|
||||
public function add(ExchangeRates $entity, bool $flush = true): void
|
||||
{
|
||||
$this->_em->persist($entity);
|
||||
if ($flush) {
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ORMException
|
||||
* @throws OptimisticLockException
|
||||
*/
|
||||
public function remove(ExchangeRates $entity, bool $flush = true): void
|
||||
{
|
||||
$this->_em->remove($entity);
|
||||
if ($flush) {
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return ExchangeRates[] Returns an array of ExchangeRates objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('e')
|
||||
->andWhere('e.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('e.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?ExchangeRates
|
||||
{
|
||||
return $this->createQueryBuilder('e')
|
||||
->andWhere('e.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Services;
|
||||
|
||||
use App\Helper\FIFO\Crypto;
|
||||
use App\Helper\Sheets\ReadSheet;
|
||||
use App\Logic\Dividends\DividendsSummary;
|
||||
use App\Logic\Dividends\SheetData;
|
||||
use App\Logic\Dividends\XMLReader;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
class CryptoService extends MasterServices
|
||||
{
|
||||
public function generate() : DividendsSummary
|
||||
{
|
||||
$summaryObj = new DividendsSummary($this->manager);
|
||||
|
||||
foreach ($this->allFiles as $file) {
|
||||
$extension = pathinfo($file)['extension'];
|
||||
$tmp = new ReadSheet($file);
|
||||
$tmp->takeFile();
|
||||
$a = new Crypto($tmp->getAll()[0]);
|
||||
dd($a->takeSumTransactions());
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $summaryObj;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Services;
|
||||
|
||||
use App\Helper\Sheets\ReadSheet;
|
||||
use App\Logic\Dividends\DividendsSummary;
|
||||
use App\Logic\Dividends\SheetData;
|
||||
use App\Logic\Dividends\XMLReader;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
class DividendsService extends MasterServices
|
||||
{
|
||||
public function generate() : DividendsSummary
|
||||
{
|
||||
$summaryObj = new DividendsSummary($this->manager);
|
||||
|
||||
foreach ($this->allFiles as $file) {
|
||||
$extension = pathinfo($file)['extension'];
|
||||
if (in_array($extension, ['xlsx','csv'])) {
|
||||
$reader = new ReadSheet($file);
|
||||
if ($reader->takeFile()) {
|
||||
/** @var SheetData $item */
|
||||
foreach ($reader->getAll() as $val) {
|
||||
$item = new SheetData($val);
|
||||
$summaryObj->addSheetData($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($extension === "xml") {
|
||||
$obj = new XMLReader($file);
|
||||
$obj->readFile();
|
||||
$summaryObj->addXml($obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $summaryObj;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Services;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
class MasterServices
|
||||
{
|
||||
protected EntityManager $manager;
|
||||
protected string $hashParam;
|
||||
protected string $uploadPath;
|
||||
protected array $allFiles;
|
||||
|
||||
public function __construct(EntityManager $entity,string $hash)
|
||||
{
|
||||
$this->manager = $entity;
|
||||
$this->hashParam = $hash;
|
||||
}
|
||||
|
||||
public function setUploadsPath(string $path)
|
||||
{
|
||||
$this->uploadPath = $path;
|
||||
}
|
||||
|
||||
public function readFiles() : bool
|
||||
{
|
||||
$fileNames = [];
|
||||
$dir=$this->uploadPath . "/" . $this->hashParam;
|
||||
$handle = opendir($dir);
|
||||
while (($inDir = readdir($handle)) !== false) {
|
||||
if ($inDir !== "." && $inDir !== "..") {
|
||||
$fileNames[] = $dir."/".$inDir;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
$this->allFiles=$fileNames;
|
||||
|
||||
return count($fileNames) > 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user