Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af2ce4732b | |||
| 84ad29d0a0 | |||
| ce7fc07aa5 | |||
| aa52f216bd | |||
| fc1ef6f3ec | |||
| 90952d883e | |||
| 2c5a40eb28 | |||
| 7e55e5097f | |||
| 6b005cb5b6 | |||
| a29ee0d5b7 |
+41
-40
@@ -4,53 +4,53 @@
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=7.4",
|
||||
"php": ">=8.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-iconv": "*",
|
||||
"doctrine/annotations": "^1.0",
|
||||
"doctrine/doctrine-bundle": "^2.5",
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-simplexml": "*",
|
||||
"doctrine/deprecations": "*",
|
||||
"doctrine/doctrine-bundle": "^2.10",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.2",
|
||||
"doctrine/orm": "^2.11",
|
||||
"doctrine/orm": "^2.20",
|
||||
"phpdocumentor/reflection-docblock": "^5.3",
|
||||
"phpoffice/phpspreadsheet": "^1.22",
|
||||
"phpstan/phpdoc-parser": "^1.2",
|
||||
"sensio/framework-extra-bundle": "^6.1",
|
||||
"symfony/asset": "5.4.*",
|
||||
"symfony/console": "5.4.*",
|
||||
"symfony/doctrine-messenger": "5.4.*",
|
||||
"symfony/dotenv": "5.4.*",
|
||||
"symfony/expression-language": "5.4.*",
|
||||
"symfony/flex": "^1.17|^2",
|
||||
"symfony/form": "5.4.*",
|
||||
"symfony/framework-bundle": "5.4.*",
|
||||
"symfony/http-client": "5.4.*",
|
||||
"symfony/intl": "5.4.*",
|
||||
"symfony/mailer": "5.4.*",
|
||||
"symfony/mime": "5.4.*",
|
||||
"symfony/asset": "6.4.*",
|
||||
"symfony/console": "6.4.*",
|
||||
"symfony/doctrine-messenger": "6.4.*",
|
||||
"symfony/dotenv": "6.4.*",
|
||||
"symfony/expression-language": "6.4.*",
|
||||
"symfony/flex": "^1.21",
|
||||
"symfony/form": "6.4.*",
|
||||
"symfony/framework-bundle": "6.4.*",
|
||||
"symfony/http-client": "6.4.*",
|
||||
"symfony/intl": "6.4.*",
|
||||
"symfony/mailer": "6.4.*",
|
||||
"symfony/mime": "6.4.*",
|
||||
"symfony/monolog-bundle": "^3.0",
|
||||
"symfony/notifier": "5.4.*",
|
||||
"symfony/process": "5.4.*",
|
||||
"symfony/property-access": "5.4.*",
|
||||
"symfony/property-info": "5.4.*",
|
||||
"symfony/proxy-manager-bridge": "5.4.*",
|
||||
"symfony/runtime": "5.4.*",
|
||||
"symfony/security-bundle": "5.4.*",
|
||||
"symfony/serializer": "5.4.*",
|
||||
"symfony/string": "5.4.*",
|
||||
"symfony/translation": "5.4.*",
|
||||
"symfony/twig-bundle": "5.4.*",
|
||||
"symfony/validator": "5.4.*",
|
||||
"symfony/web-link": "5.4.*",
|
||||
"symfony/notifier": "6.4.*",
|
||||
"symfony/process": "6.4.*",
|
||||
"symfony/property-access": "6.4.*",
|
||||
"symfony/property-info": "6.4.*",
|
||||
"symfony/proxy-manager-bridge": "6.4.*",
|
||||
"symfony/runtime": "6.4.*",
|
||||
"symfony/security-bundle": "6.4.*",
|
||||
"symfony/serializer": "6.4.*",
|
||||
"symfony/string": "6.4.*",
|
||||
"symfony/translation": "6.4.*",
|
||||
"symfony/twig-bundle": "6.4.*",
|
||||
"symfony/validator": "6.4.*",
|
||||
"symfony/web-link": "6.4.*",
|
||||
"symfony/webapp-meta": "^1.0",
|
||||
"symfony/webpack-encore-bundle": "^1.14",
|
||||
"symfony/yaml": "5.4.*",
|
||||
"symfony/yaml": "6.4.*",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*"
|
||||
"twig/twig": "^2.12|^3.0"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
@@ -97,13 +97,14 @@
|
||||
"extra": {
|
||||
"symfony": {
|
||||
"allow-contrib": false,
|
||||
"require": "5.4.*"
|
||||
"require": "6.4.*"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/debug-bundle": "5.4.*",
|
||||
"rector/rector": "*",
|
||||
"symfony/debug-bundle": "6.4.*",
|
||||
"symfony/maker-bundle": "^1.0",
|
||||
"symfony/stopwatch": "5.4.*",
|
||||
"symfony/web-profiler-bundle": "5.4.*"
|
||||
"symfony/stopwatch": "6.4.*",
|
||||
"symfony/web-profiler-bundle": "6.4.*"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+2572
-2480
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@ doctrine:
|
||||
dir: '%kernel.project_dir%/src/Entity'
|
||||
prefix: 'App\Entity'
|
||||
alias: App
|
||||
type: attribute
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
framework:
|
||||
messenger:
|
||||
reset_on_message: true
|
||||
failure_transport: failed
|
||||
|
||||
transports:
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/', name: 'homepage')]
|
||||
public function index() : Response
|
||||
{
|
||||
return $this->render("index/index.html.twig");
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,9 @@
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Enum\MarketNames;
|
||||
use App\Helper\Currency;
|
||||
use App\Helper\MyReader;
|
||||
use App\Helper\ReaderSheet;
|
||||
use App\Helper\SheetData;
|
||||
use App\Helper\DividendsSummary;
|
||||
use App\Helper\DataNeed\NeedFileName;
|
||||
use App\Services\CryptoService;
|
||||
use App\Services\DividendsService;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
@@ -23,11 +21,13 @@ use Symfony\Component\Validator\Constraints\File;
|
||||
|
||||
class TaxesController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route("/taxes", name="app_taxes")
|
||||
*/
|
||||
public function index(Request $request): Response
|
||||
#[Route(path: '/taxes/{type}', name: 'app_taxes')]
|
||||
public function index(Request $request, string $type): Response
|
||||
{
|
||||
if (!in_array($type, ["crypto", "dividend"])) {
|
||||
return $this->redirectToRoute("homepage");
|
||||
}
|
||||
|
||||
$a=[];
|
||||
$form = $this->createFormBuilder([])
|
||||
->add("uploads",FileType::class, [
|
||||
@@ -36,42 +36,49 @@ class TaxesController extends AbstractController
|
||||
'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',
|
||||
// ])
|
||||
// ]
|
||||
// ])
|
||||
// ],
|
||||
'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',
|
||||
'text/csv',
|
||||
'text/plain',
|
||||
// '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);
|
||||
$hash = substr(md5(random_int(0, mt_getrandmax())),0,16);
|
||||
if ($files) {
|
||||
$i=1;
|
||||
/** @var UploadedFile $file */
|
||||
foreach ($files as $file) {
|
||||
$newName = $i;
|
||||
$checkName = NeedFileName::check($file->getClientOriginalName());
|
||||
if ($checkName !== null) {
|
||||
$newName .= "-".$checkName;
|
||||
}
|
||||
$file->move(
|
||||
$this->getParameter("uploads_path")."/".$hash,
|
||||
$i.".".$file->getClientOriginalExtension()
|
||||
$newName.".".$file->getClientOriginalExtension()
|
||||
);
|
||||
$i++;
|
||||
}
|
||||
return $this->redirectToRoute("app_taxes_show",["hash" => $hash]);
|
||||
return $this->redirectToRoute("app_taxes_{$type}_show",["hash" => $hash]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,20 +89,40 @@ class TaxesController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/taxes/{hash}", name="app_taxes_show")
|
||||
*/
|
||||
public function show(DividendsService $tax) : Response
|
||||
#[Route(path: '/taxes/dividend/{hash}/{market}', name: 'app_taxes_dividend_show', defaults: ['market' => null])]
|
||||
public function showDividend(DividendsService $tax, ?MarketNames $market) : Response
|
||||
{
|
||||
if ($tax->readFiles()) {
|
||||
if ($tax->readFiles($market)) {
|
||||
$gen = $tax->generate();
|
||||
// dd($gen);
|
||||
return $this->render("taxes/show.html.twig", [
|
||||
"taxes" => $gen->getSummaryByCountry(),
|
||||
"error" => $gen->error
|
||||
"errorDividend" => $gen->getErrorDividend(),
|
||||
"errorString" => $gen->getErrorString(),
|
||||
"rawCount" => $gen->takeCountRawData(),
|
||||
"markets" => $gen->getMarkets(),
|
||||
"markets_all" => MarketNames::cases(),
|
||||
"hash_param" => $tax->takeHash(),
|
||||
"current_market" => $market,
|
||||
]);
|
||||
|
||||
}
|
||||
return new Response("error");
|
||||
}
|
||||
#[Route(path: '/taxes/crypto/{hash}', name: 'app_taxes_crypto_show')]
|
||||
public function showCrypto(CryptoService $tax) : Response
|
||||
{
|
||||
if ($tax->readFiles(null)) {
|
||||
$gen = $tax->generate();
|
||||
if ($gen) {
|
||||
return $this->render("taxes/show.html.twig", [
|
||||
"taxes" => $tax->takeAllByCurrency(),
|
||||
"empty" => $tax->takeAllByCurrencyEmpty(),
|
||||
"error" => $tax->takeError()
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
return new Response("error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,32 +6,23 @@ 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"})})
|
||||
*/
|
||||
#[ORM\Table]
|
||||
#[Index(columns: ['date_date', 'str_currency'], name: 'currency')]
|
||||
#[ORM\Entity(repositoryClass: ExchangeRatesRepository::class)]
|
||||
class ExchangeRates
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=3)
|
||||
*/
|
||||
#[ORM\Column(type: 'string', length: 3)]
|
||||
private $strCurrency;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="float")
|
||||
*/
|
||||
#[ORM\Column(type: 'float')]
|
||||
private $intRate;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date")
|
||||
*/
|
||||
#[ORM\Column(type: 'date')]
|
||||
private $dateDate;
|
||||
|
||||
public function getId(): ?int
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
namespace App\Enum;
|
||||
|
||||
enum MarketNames: int
|
||||
{
|
||||
case IBKR = 1;
|
||||
case MBANK = 2;
|
||||
case EXANTE = 3;
|
||||
|
||||
public static function tryFromCase(string $value): ?MarketNames
|
||||
{
|
||||
$ret = null;
|
||||
foreach (self::cases() as $case) {
|
||||
if (str_contains($value, strtolower($case->name))) {
|
||||
$ret = $case;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
final class ClearTypes
|
||||
{
|
||||
public static function clearInt($input) : int
|
||||
{
|
||||
if (is_int($input)) {
|
||||
return $input;
|
||||
}
|
||||
return (int) $input;
|
||||
}
|
||||
|
||||
public static function clearFloat($input): float
|
||||
{
|
||||
if (is_float($input)) {
|
||||
return $input;
|
||||
}
|
||||
if (str_contains($input, '.')) {
|
||||
return floatval($input);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
@@ -7,18 +7,17 @@ use Doctrine\ORM\EntityManager;
|
||||
|
||||
class Currency
|
||||
{
|
||||
public static array $currencies = ["USD","GBP","PLN"];
|
||||
public static array $currencies = ["USD","GBP","PLN","EUR","CAD","AUD"];
|
||||
public static array $currenciesCrypto = ["USDT"];
|
||||
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)
|
||||
public function __construct(private readonly EntityManager $manager)
|
||||
{
|
||||
$this->manager = $manager;
|
||||
$this->takeRates();
|
||||
}
|
||||
|
||||
public function getRate(string $currency, \DateTime $dateTime, &$err) : float
|
||||
public function getRate(string $currency, \DateTime $dateTime) : float
|
||||
{
|
||||
$dayOfWeek = $dateTime->format("N");
|
||||
$minusDay = 1;
|
||||
@@ -29,17 +28,20 @@ class Currency
|
||||
}
|
||||
$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;
|
||||
|
||||
$limitLoop = 5;
|
||||
do {
|
||||
$rate = $this->takePLNOnDate($currency, $dateCopy->format("Y-m-d"));
|
||||
if (!$rate) {
|
||||
$dateCopy->modify("-1 day");
|
||||
}
|
||||
if ($limitLoop < 1) {
|
||||
break;
|
||||
}
|
||||
$limitLoop--;
|
||||
}while($rate == 0);
|
||||
|
||||
if ($rate) {
|
||||
@@ -60,7 +62,7 @@ class Currency
|
||||
|
||||
private function takePLNOnDate(string $currency, string $dateStr) : float
|
||||
{
|
||||
if (!in_array($currency, self::$currencies)) {
|
||||
if (!self::isCurrencyExists($currency)) {
|
||||
return 0;
|
||||
}
|
||||
$url = strtr(self::$apiUrl,[
|
||||
@@ -94,4 +96,10 @@ class Currency
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function isCurrencyExists(string $currency) : bool
|
||||
{
|
||||
return in_array($currency, self::$currencies);
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,14 @@ use App\Logic\Crypto\MainObject;
|
||||
final class CryptoValues
|
||||
{
|
||||
private static array $values = [
|
||||
"values" => ["Wartość","Values"],
|
||||
"values" => ["Wartość","Values","Amount"],
|
||||
"currency" => ["Currency", "Waluta"],
|
||||
"date" => ["Data operacji"],
|
||||
"desc" => ["Rodzaj"]
|
||||
"date" => ["Data operacji","Date(UTC)"],
|
||||
"desc" => ["Rodzaj"],
|
||||
"price" => ["Price"],
|
||||
"transactionType" => ["Type","Side"],
|
||||
"market" => ["Market","Pair"],
|
||||
"realValue" => ["Total"]
|
||||
];
|
||||
|
||||
public static function isValue(string $type, string $text) : bool
|
||||
@@ -20,7 +24,7 @@ final class CryptoValues
|
||||
}
|
||||
$ret = false;
|
||||
foreach (self::$values[$type] as $value) {
|
||||
if (strpos($text,$value) !== false) {
|
||||
if (str_contains($text,(string) $value)) {
|
||||
$ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Helper\DataNeed;
|
||||
|
||||
class DividendValues
|
||||
{
|
||||
private static array $samples = [
|
||||
'count' => ["LICZBA POSIADANYCH SZT"],
|
||||
'isin' => ["ISIN"],
|
||||
'currency' => ["WALUTA","CurrencyPrimary"],
|
||||
'tax' => ["PODATK"],
|
||||
'value' => ["DYWIDENDA BRUTTO"],
|
||||
'date' => ["DATA","Date"],
|
||||
'description' => ["Desc"],
|
||||
'amount' => ["Amount"],
|
||||
'groupId' => ["ActionID"],
|
||||
'type' => ["Type"]
|
||||
];
|
||||
|
||||
public static function searchForKeyName(string $val) : ?string
|
||||
{
|
||||
$ret=null;
|
||||
$val = trim($val);
|
||||
foreach (self::$samples as $key => $sample) {
|
||||
foreach ($sample as $item) {
|
||||
if (str_contains($val, (string) $item)) {
|
||||
$ret = $key;
|
||||
break;
|
||||
}
|
||||
if ($ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helper\DataNeed;
|
||||
|
||||
class NeedFileName
|
||||
{
|
||||
const NAMES = [
|
||||
"exante","ibkr", "mbank"
|
||||
];
|
||||
|
||||
public static function check(string $fileName) : ?string
|
||||
{
|
||||
$name = null;
|
||||
$fileName = strtolower($fileName);
|
||||
foreach (self::NAMES as $str) {
|
||||
if (str_contains($fileName, $str)) {
|
||||
$name = $str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,14 @@ class Crypto extends Main
|
||||
if (!$all || count($all) < 1) {
|
||||
return [];
|
||||
}
|
||||
$sum = [
|
||||
];
|
||||
|
||||
$sum = [];
|
||||
/** @var MainObject $item */
|
||||
foreach ($all as $item) {
|
||||
if ($item->getValue() == 0) {
|
||||
continue;
|
||||
}
|
||||
// if ($item->getCurrency() === "BTC")
|
||||
// dd($item,$item->getValueCrypto());
|
||||
// if (!isset($sum[$item->getCurrency()])) {
|
||||
// $sum[$item->getCurrency()] = [];
|
||||
// if (!isset($sum[$item->getCurrency()][$item->getDateTime()->format("Y-m-d")])){
|
||||
@@ -40,12 +40,25 @@ class Crypto extends Main
|
||||
$sum[$item->getCurrency()][$date] = [];
|
||||
}
|
||||
|
||||
$sum[$item->getCurrency()][$date] = $item;
|
||||
$sum[$item->getCurrency()][$date][] = $item;
|
||||
}
|
||||
$test=[];
|
||||
$realCurrency = [];
|
||||
|
||||
foreach ($sum as $currency => $itemsAll) {
|
||||
foreach ($itemsAll as $date => $i) {
|
||||
if (count($i) > 1) {
|
||||
$realObj = array_pop($i);
|
||||
foreach ($i as $item) {
|
||||
$realObj->setValue($item->getValue() + $realObj->getValue());
|
||||
}
|
||||
$sum[$currency][$date] = $realObj;
|
||||
} else {
|
||||
$sum[$currency][$date] = $i[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($sum as $currency => $items) {
|
||||
if (in_array($currency, Currency::$currencies)) {
|
||||
if (in_array($currency, Currency::$currencies) || in_array($currency,Currency::$currenciesCrypto)) {
|
||||
if (!isset($realCurrency[$currency])) {
|
||||
$realCurrency[$currency] = [];
|
||||
}
|
||||
@@ -56,7 +69,22 @@ class Crypto extends Main
|
||||
foreach ($keyToDel as $item) {
|
||||
unset($sum[$item]);
|
||||
}
|
||||
|
||||
foreach ($realCurrency as $currency => $i) {
|
||||
if (in_array($currency,Currency::$currenciesCrypto)) {
|
||||
$curr=null;
|
||||
foreach ($i as $item) {
|
||||
if (!isset($realCurrency[$item->getRealCurrency()])) {
|
||||
continue;
|
||||
}
|
||||
if (!($curr instanceof MainObject)) {
|
||||
$curr = $realCurrency[$item->getRealCurrency()][array_key_first($realCurrency[$item->getRealCurrency()])];
|
||||
}
|
||||
$item->setRealCurrency("PLN");
|
||||
$item->setPrice(round($curr->getPrice()/$item->getPrice(),4));
|
||||
$item->setRealValue(intval(round(($item->getValue()/100)*$item->getPrice()*100)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
"realCurrency" => $realCurrency,
|
||||
"transactions" => $sum
|
||||
@@ -70,20 +98,31 @@ class Crypto extends Main
|
||||
'in' => [],
|
||||
'out' =>[]
|
||||
];
|
||||
|
||||
/** @var MainObject $item */
|
||||
foreach ($transactions['transactions'] as $currency => $transaction) {
|
||||
foreach ($transaction as $date => $item) {
|
||||
$date = $item->getDateTime()->format("Y-m-d H:i");
|
||||
$yearTrans = intval($item->getDateTime()->format("Y"));
|
||||
if (isset($transactions['realCurrency']['PLN'][$date])) {
|
||||
$item->setRealValue($transactions['realCurrency']['PLN'][$date]->getValue());
|
||||
$obj = $transactions['realCurrency']['PLN'][$date];
|
||||
$item->setRealValue($obj->getValue());
|
||||
$item->setRealCurrency($obj->getCurrency());
|
||||
// unset($transactions['realCurrency']['PLN'][$date]);
|
||||
}
|
||||
if (in_array($item->getRealCurrency(), Currency::$currenciesCrypto) && isset($transactions['realCurrency'][$item->getRealCurrency()])) {
|
||||
$this->changeValue($item, $transactions['realCurrency'][$item->getRealCurrency()]);
|
||||
}
|
||||
if ($currency === "LML" && $yearTrans == "2020") {
|
||||
// dd($item,$transactions['realCurrency']['PLN']);
|
||||
}
|
||||
if ($item->getRealValue() != 0) {
|
||||
if (!isset($tmp['in'][$currency])) {
|
||||
$tmp['in'][$currency] = [];
|
||||
}
|
||||
if (!isset($tmp['out'][$currency])) {
|
||||
$tmp['out'][$currency] = [];
|
||||
}
|
||||
$date = $item->getDateTime()->format("Y-m-d H:i");
|
||||
if ($item->getRealValue() > 0) {
|
||||
if ($yearTrans === intval(date("Y"))-1 && ($item->getTransactionType() !== "" && $item->getTransactionType() !== "BUY") || $item->getRealValue()>0) {
|
||||
$tmp['in'][$currency][$date] = $item;
|
||||
} else {
|
||||
$tmp['out'][$currency][$date] = $item;
|
||||
@@ -91,23 +130,52 @@ class Crypto extends Main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dd($tmp['out']['LML']);
|
||||
foreach ($tmp as &$inout) {
|
||||
foreach ($inout as $currency => &$items) {
|
||||
if (count($items) > 0) {
|
||||
ksort($items,2);
|
||||
foreach ($items as $item) {
|
||||
$item->currencyConversion();
|
||||
$item->takePrice();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($items);
|
||||
unset($inout);
|
||||
if (count($tmp["in"]) === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var MainObject $i */
|
||||
foreach ($tmp as $type => $value) {
|
||||
foreach ($value as $cur => $item) {
|
||||
if (in_array($cur, Currency::$currenciesCrypto) && count($item) > 0) {
|
||||
foreach ($item as $i) {
|
||||
if ($i->getRealCurrency() === "PLN") {
|
||||
continue;
|
||||
}
|
||||
$real = $transactions['realCurrency'][$i->getRealCurrency()][array_key_first($transactions['realCurrency'][$i->getRealCurrency()])];
|
||||
$i->setRealCurrency($real->getRealCurrency());
|
||||
$newVal = $i->getRealValue()/100 * $real->getPrice();
|
||||
$newVal = intval(round($newVal * 100));
|
||||
$i->setRealValue($newVal);
|
||||
$newPrice = $i->getPrice() * $real->getPrice();
|
||||
$newPrice = intval(round($newPrice * 100));
|
||||
$i->setPrice($newPrice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$arr = [];
|
||||
foreach ($tmp["in"] as $currency => $items) {
|
||||
foreach ($items as $item) {
|
||||
$item->takePrice();
|
||||
$arr[$currency] = $this->countTax($item, $tmp['out'][$currency]);
|
||||
}
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
@@ -116,14 +184,19 @@ class Crypto extends Main
|
||||
return $this->notCount;
|
||||
}
|
||||
|
||||
private function countTax(MainObject $mainObject, array $buys)
|
||||
private function countTax(MainObject $mainObject, array $buys) : array
|
||||
{
|
||||
$needCount = abs($mainObject->getValue());
|
||||
$priceToTax = 0;
|
||||
$getedValue = 0;
|
||||
/** @var MainObject $buy */
|
||||
foreach ($buys as $buy) {
|
||||
if ($mainObject->getDateTime()->diff($buy->getDateTime())->invert == 0) {
|
||||
$this->notCount[] = $mainObject;
|
||||
$value = abs($mainObject->getValue())-$getedValue;
|
||||
if ($value > 1) {
|
||||
$value /= MainObject::_CRYPTO_DIVIDER;
|
||||
}
|
||||
$this->notCount[$mainObject->getCurrency()] = $value;
|
||||
break;
|
||||
}
|
||||
if ($needCount === 0) {
|
||||
@@ -132,16 +205,67 @@ class Crypto extends Main
|
||||
if ($buy->getValue() == 0) {
|
||||
continue;
|
||||
}
|
||||
if ($needCount > $buy->getValue()) {
|
||||
if ($mainObject->getCurrency() == "LML") {
|
||||
// dd($needCount - $buy->getValue());
|
||||
}
|
||||
if ($needCount - $buy->getValue() > 0) {
|
||||
$needCount -= $buy->getValue();
|
||||
$priceToTax += $buy->getRealValue();
|
||||
$getedValue += $buy->getValue();
|
||||
$priceToTax += abs($buy->getRealValue()/100);
|
||||
$buy->setValue(0);
|
||||
} else {
|
||||
$newVal = abs($buy->getValue())-$needCount;
|
||||
$priceToTax += $buy->getPrice() * $needCount;
|
||||
$newVal = $buy->getValue() - $needCount;
|
||||
$priceToTax += round(abs($buy->getPrice() * $needCount / MainObject::_CRYPTO_DIVIDER),4);
|
||||
$needCount = 0;
|
||||
$buy->setValue($newVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $mainObject->getRealValue()-$priceToTax;
|
||||
$return = [
|
||||
'income' => 0,
|
||||
'cost' => 0,
|
||||
];
|
||||
if ($needCount > 0) {
|
||||
if ($mainObject->getCurrency() == "GRT") {
|
||||
// dd($needCount,$getedValue,$mainObject, $buys);
|
||||
}
|
||||
$value = abs($mainObject->getValue())-$getedValue;
|
||||
if ($value > 1) {
|
||||
$value /= MainObject::_CRYPTO_DIVIDER;
|
||||
}
|
||||
$this->notCount[$mainObject->getCurrency()] = $value;
|
||||
return $return;
|
||||
}
|
||||
$return['income'] = $mainObject->getRealValue() / 100;
|
||||
$return['cost'] = round($priceToTax,2);
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function changeValue(MainObject $mainObject, array $buys)
|
||||
{
|
||||
$needCount = abs($mainObject->getRealValue());
|
||||
$newCount = 0;
|
||||
/** @var MainObject $buy */
|
||||
foreach ($buys as $buy) {
|
||||
if ($mainObject->getDateTime()->diff($buy->getDateTime())->invert == 0) {
|
||||
continue;
|
||||
}
|
||||
if ($buy->getValue() === 0) {
|
||||
continue;
|
||||
}
|
||||
if ($needCount - $buy->getValue() > 0) {
|
||||
$newCount += $buy->getValue()/100 * $buy->getPrice();
|
||||
$buy->setValue(0);
|
||||
} else {
|
||||
$newCount = $needCount/100 * $buy->getPrice();
|
||||
$buy->setValue(intval($buy->getValue()-$needCount));
|
||||
}
|
||||
}
|
||||
|
||||
if ($newCount > 0) {
|
||||
$mainObject->setRealValue(intval(round($newCount*100)));
|
||||
$mainObject->setRealCurrency("PLN");
|
||||
$mainObject->takePrice(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,17 +10,32 @@ class Main
|
||||
{
|
||||
protected array $data;
|
||||
|
||||
public function __construct(array $data)
|
||||
public function __construct()
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function addData(array $data)
|
||||
{
|
||||
if (isset($data[0]) && $data[0][0]==='Date(UTC)') {
|
||||
// $first = array_shift($data);
|
||||
// array_unshift($data, $first, [
|
||||
// "2021-04-14 13:00:00",
|
||||
// "EURPLN",
|
||||
// "BUY",
|
||||
// 4.5755,
|
||||
// 100,
|
||||
// 457.55
|
||||
// ]);
|
||||
}
|
||||
$this->data[] = $data;
|
||||
}
|
||||
|
||||
protected function takeAllRealTransactions(string $abstract): array
|
||||
{
|
||||
$tmp = [];
|
||||
$keys = array_shift($this->data);
|
||||
foreach ($this->data as $datum1) {
|
||||
$keys = array_shift($datum1);
|
||||
$names = [];
|
||||
|
||||
foreach ($keys as $keyId => $key) {
|
||||
/** @var CryptoValues $abstract */
|
||||
if ($abstract::isValue("values",$key)) {
|
||||
@@ -35,19 +50,60 @@ class Main
|
||||
if ($abstract::isValue("desc",$key)) {
|
||||
$names[$keyId] = "setDesc";
|
||||
}
|
||||
if ($abstract::isValue("price",$key)) {
|
||||
$names[$keyId] = "setPrice";
|
||||
}
|
||||
foreach ($this->data as $datum) {
|
||||
if ($abstract::isValue("transactionType",$key)) {
|
||||
$names[$keyId] = "setTransactionType";
|
||||
}
|
||||
if ($abstract::isValue("market",$key)) {
|
||||
$names[$keyId] = "setMarketName";
|
||||
}
|
||||
if ($abstract::isValue("realValue",$key)) {
|
||||
$names[$keyId] = "setRealValue";
|
||||
}
|
||||
}
|
||||
$i = 0;
|
||||
foreach ($datum1 as $key1 => $datum) {
|
||||
$obj = new MainObject();
|
||||
if ($datum[0] === $keys[0]) {
|
||||
continue;
|
||||
}
|
||||
foreach ($names as $key => $name) {
|
||||
if ($name === "setCurrency" && is_float($datum[$key])) {
|
||||
dd($names,$datum[$key]);
|
||||
}
|
||||
if ($name === "setValue") {
|
||||
$datum[$key] = floatval($datum[$key]);
|
||||
$data = "$datum[$key]";
|
||||
if (str_contains($data,",") || str_contains($data,".")) {
|
||||
$data = str_replace(",",".",$data);
|
||||
}
|
||||
$realInt = floatval($data)*MainObject::_CRYPTO_DIVIDER;
|
||||
$datum[$key] = intval($realInt);
|
||||
}
|
||||
if ($name === "setDateTime") {
|
||||
$datum[$key] = new \DateTime($datum[$key]);
|
||||
}
|
||||
if ($name === "setRealValue") {
|
||||
$datum[$key] = intval($datum[$key]*100);
|
||||
}
|
||||
if ($name === "setPrice" && is_string($datum[$key])) {
|
||||
$val = $datum[$key];
|
||||
if (str_contains($val, ".") && str_contains($val, ",")) {
|
||||
$val = str_replace(",", "", $val);
|
||||
$datum[$key] = intval(floatval($val)*100);
|
||||
}
|
||||
}
|
||||
$obj->$name($datum[$key]);
|
||||
}
|
||||
$obj->trySetCurrencies();
|
||||
$obj->checkCurrency();
|
||||
if ($i == 30) {
|
||||
// dd($obj);
|
||||
}
|
||||
$tmp[] = $obj;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
@@ -2,17 +2,20 @@
|
||||
declare(strict_types=1);
|
||||
namespace App\Helper\Sheets;
|
||||
|
||||
use App\Enum\MarketNames;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
||||
class ReadSheet
|
||||
{
|
||||
private string $filePath;
|
||||
private array $arr=[];
|
||||
private ?MarketNames $marketNames;
|
||||
|
||||
public function __construct(string $file)
|
||||
public function __construct(string $file, ?MarketNames $marketNames)
|
||||
{
|
||||
if (file_exists($file)){
|
||||
$this->filePath = $file;
|
||||
$this->marketNames = $marketNames;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,21 +24,26 @@ class ReadSheet
|
||||
return $this->arr;
|
||||
}
|
||||
|
||||
public function takeFile() : bool
|
||||
public function takeFile(?string $delimiter = null) : bool
|
||||
{
|
||||
if (!$this->filePath) {
|
||||
return false;
|
||||
}
|
||||
$fileType = explode(".", $this->filePath);
|
||||
|
||||
$reader = IOFactory::createReader(ucfirst($fileType[1]));
|
||||
$fileType = explode(".", $this->filePath)[1];
|
||||
$reader = IOFactory::createReader(ucfirst($fileType));
|
||||
$reader->setLoadAllSheets();
|
||||
$reader->setReadDataOnly(true);
|
||||
if ($this->marketNames && $this->marketNames === MarketNames::EXANTE) {
|
||||
$reader->setInputEncoding("UTF-16");
|
||||
}
|
||||
if ($delimiter) {
|
||||
$reader->setDelimiter($delimiter);
|
||||
}
|
||||
$spreadsheet = $reader->load($this->filePath);
|
||||
// $spreadsheet->getDefaultStyle()->getNumberFormat()->setFormatCode('@');
|
||||
foreach ($spreadsheet->getAllSheets() as $sheetName) {
|
||||
$this->arr[] = $sheetName->toArray();
|
||||
}
|
||||
|
||||
return count($this->arr) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,31 @@
|
||||
declare(strict_types=1);
|
||||
namespace App\Logic\Crypto;
|
||||
|
||||
use App\Helper\Currency;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
|
||||
class MainObject
|
||||
{
|
||||
const _CRYPTO_DIVIDER = 10000000;
|
||||
private \DateTime $dateTime;
|
||||
private string $desc;
|
||||
private float $value;
|
||||
private int $value;
|
||||
private string $currency;
|
||||
private ?string $realCurrency=null;
|
||||
private float $realValue=0;
|
||||
private int $realValue=0;
|
||||
private float $price=0;
|
||||
private bool $isCrypto = false;
|
||||
private string $transactionType="";
|
||||
private string $marketName="";
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTransactionType(): string
|
||||
{
|
||||
return $this->transactionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
@@ -23,17 +37,17 @@ class MainObject
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $realValue
|
||||
* @param int $realValue
|
||||
*/
|
||||
public function setRealValue(float $realValue): void
|
||||
public function setRealValue(int $realValue): void
|
||||
{
|
||||
$this->realValue = $realValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRealCurrency(): string
|
||||
public function getRealCurrency(): ?string
|
||||
{
|
||||
return $this->realCurrency;
|
||||
}
|
||||
@@ -79,17 +93,17 @@ class MainObject
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
* @return int
|
||||
*/
|
||||
public function getValue(): float
|
||||
public function getValue(): int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $value
|
||||
* @param int $value
|
||||
*/
|
||||
public function setValue(float $value): void
|
||||
public function setValue(int $value): void
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
@@ -107,10 +121,29 @@ class MainObject
|
||||
*/
|
||||
public function setCurrency(string $currency): void
|
||||
{
|
||||
if (!in_array($currency, Currency::$currencies) && !in_array($currency, Currency::$currenciesCrypto)) {
|
||||
$this->isCrypto = true;
|
||||
}
|
||||
$this->currency = $currency;
|
||||
}
|
||||
|
||||
public function addValue(float $val) : void
|
||||
/**
|
||||
* @param string $transactionType
|
||||
*/
|
||||
public function setTransactionType(string $transactionType): void
|
||||
{
|
||||
$this->transactionType = $transactionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $marketName
|
||||
*/
|
||||
public function setMarketName(string $marketName): void
|
||||
{
|
||||
$this->marketName = $marketName;
|
||||
}
|
||||
|
||||
public function addValue(int $val) : void
|
||||
{
|
||||
$this->value += $val;
|
||||
}
|
||||
@@ -123,13 +156,116 @@ class MainObject
|
||||
$this->realValue += $val;
|
||||
}
|
||||
|
||||
public function takePrice() : void
|
||||
public function takePrice(bool $force = false) : void
|
||||
{
|
||||
$this->price = abs(round($this->realValue / $this->getValue(),4));
|
||||
if ($this->price && !$force) {
|
||||
return;
|
||||
}
|
||||
$real = $this->getRealValue() / 100;
|
||||
$val = $this->getValue();
|
||||
if ($this->isCrypto) {
|
||||
$val = $this->getValueCrypto();
|
||||
}
|
||||
$price = round($real/$val,8);
|
||||
// if ($this->isCrypto) {
|
||||
// $price *= self::_CRYPTO_DIVIDER;
|
||||
// } else {
|
||||
// $price *= 100;
|
||||
// }
|
||||
$this->price = $price;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float|int $price
|
||||
*/
|
||||
public function setPrice($price): void
|
||||
{
|
||||
$this->price = $price;
|
||||
}
|
||||
|
||||
public function getPrice() : float
|
||||
{
|
||||
return $this->price;
|
||||
}
|
||||
|
||||
public function getValueCrypto() : float
|
||||
{
|
||||
return $this->value / self::_CRYPTO_DIVIDER;
|
||||
}
|
||||
|
||||
public function subtract(MainObject $mainObject)
|
||||
{
|
||||
$this->value = $this->getValue() - $mainObject->getValue();
|
||||
}
|
||||
|
||||
public function checkCurrency() : void
|
||||
{
|
||||
if (!$this->isCrypto) {
|
||||
$this->value = intval($this->value/self::_CRYPTO_DIVIDER*100);
|
||||
}
|
||||
}
|
||||
|
||||
public function trySetCurrencies() : void
|
||||
{
|
||||
if ($this->marketName) {
|
||||
$cryptoFiat = ["USDT","BUSD"];
|
||||
if (strlen($this->marketName) === 6) {
|
||||
$cur1 = substr($this->marketName,0,3);
|
||||
$cur2 = substr($this->marketName,3);
|
||||
if ($this->transactionType === "BUY") {
|
||||
$this->setCurrency($cur1);
|
||||
$this->setRealCurrency($cur2);
|
||||
// $this->setPrice(-$this->getPrice());
|
||||
} else {
|
||||
$this->setCurrency($cur2);
|
||||
$this->setRealCurrency($cur1);
|
||||
}
|
||||
} else {
|
||||
foreach ($cryptoFiat as $item) {
|
||||
$currReal = strpos($this->marketName, $item);
|
||||
if ($currReal === false) {
|
||||
continue;
|
||||
}
|
||||
if ($currReal > 0) {
|
||||
$cur1 = substr($this->marketName, 0,strlen($this->marketName) - strlen($item));
|
||||
$cur2 = $item;
|
||||
} else {
|
||||
$cur1 = $item;
|
||||
$cur2 = substr($this->marketName, 0, strlen($this->marketName) - strlen($item));
|
||||
}
|
||||
if ($this->transactionType === "BUY") {
|
||||
$this->setCurrency($cur1);
|
||||
$this->setRealCurrency($cur2);
|
||||
// $this->setPrice(-$this->getPrice());
|
||||
} else {
|
||||
$this->setCurrency($cur2);
|
||||
$this->setRealCurrency($cur1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->getRealCurrency() === "USDT") {
|
||||
$this->setRealValue(-intval($this->getRealValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function currencyConversion() : void
|
||||
{
|
||||
if ($this->realCurrency === "PLN" || (!in_array($this->realCurrency, Currency::$currencies) && !in_array($this->realCurrency, Currency::$currenciesCrypto))) {
|
||||
return;
|
||||
}
|
||||
$eur = 4.5755;
|
||||
if ($this->realCurrency === "EUR") {
|
||||
$this->setRealValue(intval(round($this->getRealValue() * $eur)));
|
||||
$this->setRealCurrency("PLN");
|
||||
$this->takePrice(true);
|
||||
}
|
||||
// if ($this->realCurrency === "USDT") {
|
||||
// dd($this);
|
||||
// $this->setRealValue(intval(round($this->getRealValue() * ($eur/$this->getPrice()))));
|
||||
// $this->setRealCurrency("PLN");
|
||||
// $this->takePrice(true);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,6 @@ final class DividendsData
|
||||
*/
|
||||
public function setCurrency(string $currency): void
|
||||
{
|
||||
$this->currency = $currency;
|
||||
$this->currency = trim($currency);
|
||||
}
|
||||
}
|
||||
@@ -2,25 +2,40 @@
|
||||
declare(strict_types=1);
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
use App\Enum\MarketNames;
|
||||
use App\Helper\Currency;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
class DividendsSummary
|
||||
{
|
||||
/** @var SheetData|array $sheetData */
|
||||
/** @var SheetDataAll|array $sheetData */
|
||||
private array $sheetData=[];
|
||||
/** @var XMLReader|array $sheetData */
|
||||
private array $xmlData=[];
|
||||
private Currency $currencyObj;
|
||||
public array $error=[];
|
||||
private readonly Currency $currencyObj;
|
||||
/** @var array|DividendsData $error */
|
||||
private ?array $errorDividend=null;
|
||||
private ?array $errorString=null;
|
||||
private array $allData=[];
|
||||
private array $countryToCurrency=[];
|
||||
private int $realCalculatedRows = 0;
|
||||
/** @var array|MarketNames $markets */
|
||||
private array $markets=[];
|
||||
|
||||
public function __construct(EntityManager $manager)
|
||||
{
|
||||
$this->currencyObj = new Currency($manager);
|
||||
}
|
||||
|
||||
public function addMarket(?MarketNames $names)
|
||||
{
|
||||
$this->markets[] = $names ?? MarketNames::MBANK;
|
||||
}
|
||||
|
||||
public function getMarkets(): array
|
||||
{
|
||||
return $this->markets;
|
||||
}
|
||||
public function getSummaryByCountry() : array
|
||||
{
|
||||
$return=[];
|
||||
@@ -28,16 +43,26 @@ class DividendsSummary
|
||||
|
||||
if (count($this->allData) > 0) {
|
||||
$sum = 0;
|
||||
$profitSum = 0;
|
||||
foreach ($this->allData as $key => $item) {
|
||||
$val = round($item, 2);
|
||||
$val = round($item['tax'], 2);
|
||||
$sum += $val;
|
||||
$profitSum += $item['incomeAll'];
|
||||
$return[$key] = [
|
||||
"country" => \Locale::getDisplayRegion("-".$key),
|
||||
"value" => $val,
|
||||
"currency" => $this->countryToCurrency[$key]
|
||||
"income" => $item['incomeAll'],
|
||||
"currency" => $this->countryToCurrency[$key],
|
||||
"tax" => $item['tax'],
|
||||
"destiny_tax" => $item['destiny_tax'],
|
||||
"tax_cost" => $item['tax_cost'],
|
||||
"incomesArray" => $item['incomes']
|
||||
];
|
||||
}
|
||||
$return['sum'] = intval(ceil($sum));
|
||||
// >
|
||||
$return['sum'] = [
|
||||
"tax" => intval(ceil($sum)),
|
||||
"profit" => $profitSum
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
@@ -56,44 +81,90 @@ class DividendsSummary
|
||||
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($test[$country])){
|
||||
$test[$country] = [
|
||||
"incomeAll" => 0,
|
||||
"tax" => 0,
|
||||
"destiny_tax" => 0,
|
||||
"tax_cost" => 0,
|
||||
"incomes" => []
|
||||
];
|
||||
}
|
||||
if (!isset($test[$country]['incomes'][$val->getTax()])) {
|
||||
$test[$country]['incomes'][$val->getTax()] = 0;
|
||||
}
|
||||
if ($this->getRate($val) < 1) {
|
||||
die("Rate for date: ".$val->getDateTime()->format("Y-m-d")." / ".$val->getCurrency() . " is 0");
|
||||
}
|
||||
$income = round($val->getCount()*$val->getValue()*$this->getRate($val),5);
|
||||
$test[$country]['incomeAll'] += $income;
|
||||
$test[$country]['tax'] += round($this->count($val),5);
|
||||
$test[$country]['destiny_tax'] += round($this->count($val,true),5);
|
||||
$test[$country]['tax_cost'] += round($this->countTaxPrice($val),5);
|
||||
$test[$country]['incomes'][$val->getTax()] += $income;
|
||||
if (!isset($countryToCurrency[$country])) {
|
||||
$countryToCurrency[$country] = $val->getCurrency();
|
||||
}
|
||||
$this->realCalculatedRows++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->allData = array_merge($this->allData,$test);
|
||||
foreach ($test as &$item) {
|
||||
ksort($item['incomes']);
|
||||
}
|
||||
unset($item);
|
||||
$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);
|
||||
if (!Currency::isCurrencyExists($data->getCurrency())) {
|
||||
$this->errorString[$data->getCurrency()] = "Currency: {$data->getCurrency()} is not supported! Please contact with administrator.";
|
||||
return 0;
|
||||
}
|
||||
return $this->currencyObj->getRate($data->getCurrency(),$data->getDateTime());
|
||||
}
|
||||
|
||||
private function count(DividendsData $data) : float
|
||||
private function count(DividendsData $data, bool $fromDestiny = false) : float
|
||||
{
|
||||
$value = round($data->getCount()*$data->getValue(),2);
|
||||
$value = round($data->getCount()*$data->getValue(),5);
|
||||
$tax = 19;
|
||||
if ($data->getTax() > 0) {
|
||||
$tax = 4;
|
||||
}
|
||||
$valueTax = round($value * $tax / 100);
|
||||
if ($fromDestiny) {
|
||||
$tax = $data->getTax();
|
||||
}
|
||||
|
||||
$valueTax = round($value * $tax / 100,5);
|
||||
$rate = $this->getRate($data);
|
||||
if ($rate > 0) {
|
||||
return $valueTax * $rate;
|
||||
}
|
||||
$this->errorDividend[]=$data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function countTaxPrice(DividendsData $data) : float
|
||||
{
|
||||
if ($data->getTax() == 0) {
|
||||
return 0;
|
||||
}
|
||||
$value = round($data->getCount()*$data->getValue(),5);
|
||||
$tax = min($data->getTax(),15);
|
||||
$valueTax = round($value * $tax / 100,5);
|
||||
$rate = $this->getRate($data);
|
||||
if ($rate > 0) {
|
||||
return $valueTax * $rate;
|
||||
}
|
||||
$this->error[]=$data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SheetData $sheetData
|
||||
* @param SheetDataAll $sheetData
|
||||
*/
|
||||
public function addSheetData(SheetData $sheetData): void
|
||||
public function addSheetData(SheetDataAll $sheetData): void
|
||||
{
|
||||
$this->sheetData[] = $sheetData;
|
||||
}
|
||||
@@ -106,4 +177,27 @@ class DividendsSummary
|
||||
$this->xmlData[] = $reader;
|
||||
}
|
||||
|
||||
public function takeCountRawData(): array
|
||||
{
|
||||
$rowCount = 0;
|
||||
/** @var SheetData $sheetDatum */
|
||||
foreach ($this->sheetData as $sheetDatum) {
|
||||
$rowCount += $sheetDatum->getCount();
|
||||
}
|
||||
return [
|
||||
'countSheet' => count($this->sheetData),
|
||||
'countRows' => $rowCount,
|
||||
'realCountRows' => $this->realCalculatedRows
|
||||
];
|
||||
}
|
||||
|
||||
public function getErrorDividend(): ?array
|
||||
{
|
||||
return $this->errorDividend;
|
||||
}
|
||||
public function getErrorString(): ?array
|
||||
{
|
||||
return $this->errorString;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
class ExanteSheet extends SheetDataAll
|
||||
{
|
||||
protected function takeData(): array
|
||||
{
|
||||
$commentKey = -1;
|
||||
$operationKey = -1;
|
||||
$ret = [];
|
||||
foreach ($this->getRawData() as $index => $rawDatum) {
|
||||
if (!isset($rawDatum[1])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($rawDatum as $key => $value) {
|
||||
$value = strtolower((string) $value);
|
||||
if (str_contains($value, "comment")) {
|
||||
$commentKey = $key;
|
||||
}
|
||||
if (str_contains($value, "operation type")) {
|
||||
$operationKey = $key;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
foreach ($this->getRawData() as $index => $rawDatum) {
|
||||
if ($index<2) {
|
||||
continue;
|
||||
}
|
||||
$operationType = strtolower((string) $rawDatum[$operationKey]);
|
||||
if (!str_contains($operationType,"dividend")) {
|
||||
continue;
|
||||
}
|
||||
$comment = $rawDatum[$commentKey];
|
||||
if (!str_contains((string) $comment, "dividend")) {
|
||||
continue;
|
||||
}
|
||||
$separate = explode(" ",(string) $comment);
|
||||
$tax = intval(str_replace(["(","-","%",")"],"",$separate[16]));
|
||||
$value = floatval(str_replace(["(",")"],"",$separate[10]));
|
||||
$date = new \DateTime($separate[3]);
|
||||
$dividendObj = new DividendsData();
|
||||
$dividendObj->setCount($separate[0]);
|
||||
$dividendObj->setCurrency($separate[9]);
|
||||
$dividendObj->setTax($tax);
|
||||
$dividendObj->setDateTime($date);
|
||||
$dividendObj->setIsin($separate[18]);
|
||||
$dividendObj->setValue($value);
|
||||
$ret[] = $dividendObj;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
use App\Helper\DataNeed\DividendValues;
|
||||
|
||||
class IbkrSheet extends SheetDataAll
|
||||
{
|
||||
protected function takeData(): array
|
||||
{
|
||||
$needIndex = [];
|
||||
foreach ($this->getRawData() as $index => $rawDatum) {
|
||||
if ($index === 0) {
|
||||
foreach ($rawDatum as $i => $item) {
|
||||
if (!$item) {
|
||||
continue;
|
||||
}
|
||||
$keyName = DividendValues::searchForKeyName($item);
|
||||
if ($keyName) {
|
||||
$needIndex[$i] = $keyName;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$ret = [];
|
||||
$dividendArr = [];
|
||||
$taxArr = [];
|
||||
$test = [];
|
||||
foreach ($this->getRawData() as $index => $rawDatum) {
|
||||
if ($index < 1) {
|
||||
continue;
|
||||
}
|
||||
$row=[];
|
||||
foreach ($rawDatum as $i => $d) {
|
||||
if (isset($needIndex[$i])) {
|
||||
$row[$needIndex[$i]] = $d;
|
||||
}
|
||||
}
|
||||
$test[$row['groupId']][] = $row['amount'];
|
||||
if (str_contains((string) $row['type'], "Dividend")) {
|
||||
$dividendArr[$row['groupId']] = $row;
|
||||
} else {
|
||||
if (!isset($taxArr[$row['groupId']])) {
|
||||
$taxArr[$row['groupId']] = $row;
|
||||
} else {
|
||||
$taxArr[$row['groupId']]['amount'] += $row['amount'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($dividendArr as $groupId => $dividend) {
|
||||
if (isset($taxArr[$groupId])) {
|
||||
$taxGet = $taxArr[$groupId]['amount'];
|
||||
$taxPercentage = intval(round(abs($taxGet) / $dividend['amount'], 2) * 100);
|
||||
if ($taxPercentage === 14) {
|
||||
$taxPercentage = 15;
|
||||
}
|
||||
} else {
|
||||
$taxPercentage = 19;
|
||||
}
|
||||
|
||||
$separate = explode(" ", (string) $dividend['description']);
|
||||
$perShare = floatval($separate[4]);
|
||||
if (!$perShare) {
|
||||
$perShare = floatval($separate[5]);
|
||||
}
|
||||
if (!$perShare) {
|
||||
continue;
|
||||
}
|
||||
$date = explode(";", (string) $dividend['date'])[0];
|
||||
if (substr_count($date, "-") !== 2) {
|
||||
$date = substr($date, 0, 4) . "-" . substr($date, 4, 2) . "-" . substr($date, 6, 2);
|
||||
}
|
||||
$dateObj = new \DateTime($date);
|
||||
if ($dateObj->format("Y") !== (new \DateTime())->modify("-1 year")->format("Y")) {
|
||||
continue;
|
||||
}
|
||||
// trigger_error(var_export($date,true));
|
||||
$dividendObj = new DividendsData();
|
||||
$dividendObj->setCount(intval($dividend['amount'] / $perShare));
|
||||
$dividendObj->setIsin($dividend['isin']);
|
||||
$dividendObj->setCurrency($dividend['currency']);
|
||||
$dividendObj->setTax($taxPercentage);
|
||||
$dividendObj->setValue($perShare);
|
||||
$dividendObj->setDateTime($dateObj);
|
||||
|
||||
$ret[] = $dividendObj;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -3,43 +3,37 @@ declare(strict_types=1);
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
use App\Helper\Currency;
|
||||
use App\Helper\DataNeed\DividendValues;
|
||||
use ClearTypes;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||
|
||||
class SheetData
|
||||
class SheetData extends SheetDataAll
|
||||
{
|
||||
private array $rawData;
|
||||
// eg. 0 -> name, 1 -> ISIN
|
||||
private array $dataIndex;
|
||||
private array $data;
|
||||
|
||||
public function __construct(array $data)
|
||||
public function takeData() : array
|
||||
{
|
||||
$this->rawData = $data;
|
||||
}
|
||||
|
||||
public function get() : array
|
||||
{
|
||||
if (isset($this->data)) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$needIndex = [];
|
||||
foreach ($this->rawData as $index => $rawDatum) {
|
||||
foreach ($this->getRawData() as $index => $rawDatum) {
|
||||
if ($index === 0) {
|
||||
$this->dataIndex = $rawDatum;
|
||||
foreach ($rawDatum as $i => $item) {
|
||||
if (!$item) {
|
||||
continue;
|
||||
}
|
||||
$setDatas=[];
|
||||
foreach ($rawDatum as $i => $data) {
|
||||
$dataType = $this->getDataType($data,$setDatas);
|
||||
if ($dataType){
|
||||
$needIndex[$i] = $dataType;
|
||||
$keyName = DividendValues::searchForKeyName($item);
|
||||
if ($keyName) {
|
||||
$needIndex[$i] = $keyName;
|
||||
}
|
||||
}
|
||||
unset($setDatas);
|
||||
break;
|
||||
// continue;
|
||||
}
|
||||
// trigger_error(var_export($rawDatum,true));
|
||||
}
|
||||
$ret = [];
|
||||
foreach ($this->rawData as $index => $datum) {
|
||||
foreach ($this->getRawData() as $index => $datum) {
|
||||
if ($index === 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -49,35 +43,36 @@ class SheetData
|
||||
$row[$needIndex[$i]] = $d;
|
||||
}
|
||||
}
|
||||
if (count($row) < 1) {
|
||||
continue;
|
||||
}
|
||||
$tmpDate = intval($row['date']);
|
||||
$date = &$row['date'];
|
||||
if ($tmpDate > 2100) {
|
||||
$date = Date::excelToDateTimeObject($date);
|
||||
} else {
|
||||
$date = new \DateTime(str_replace(".", "-", $date));
|
||||
}
|
||||
if (is_float($row['tax'])) {
|
||||
$row['tax'] = intval(round($row['tax']*100));
|
||||
}
|
||||
|
||||
$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'])));
|
||||
|
||||
|
||||
$dividendObj->setTax(ClearTypes::clearInt($row['tax']));
|
||||
$dividendObj->setCount(ClearTypes::clearInt($row['count']));
|
||||
$dividendObj->setValue(ClearTypes::clearFloat($row['value']));
|
||||
|
||||
|
||||
$dividendObj->setDateTime($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;
|
||||
@@ -106,7 +101,7 @@ class SheetData
|
||||
$count++;
|
||||
return $ret;
|
||||
}
|
||||
if (in_array(mb_substr($data, 0, 2), ['CA', 'US', 'IE', 'GB']) && intval(mb_substr($data, 2, 1))>0) {
|
||||
if (in_array(mb_substr((string) $data, 0, 2), ['CA', 'US', 'IE', 'GB']) && intval(mb_substr((string) $data, 2, 1))>0) {
|
||||
$count = &$setDatas['data'];
|
||||
$ret = "isin";
|
||||
if ($count > 0) {
|
||||
@@ -118,10 +113,24 @@ class SheetData
|
||||
if (in_array($data, Currency::$currencies)) {
|
||||
return "currency";
|
||||
}
|
||||
if (count(explode(".", $data)) === 3) {
|
||||
if (count(explode(".", (string) $data)) === 3 || count(explode("-", (string) $data)) === 3) {
|
||||
return "date";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function searchForDateIndex() : int
|
||||
{
|
||||
$ret = -1;
|
||||
|
||||
foreach ($this->takeColumnNames() as $index => $takeColumnName) {
|
||||
if (str_contains((string) $takeColumnName,"DATE") || str_contains((string) $takeColumnName,"DATA")) {
|
||||
$ret = $index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace App\Logic\Dividends;
|
||||
|
||||
use function Symfony\Component\Translation\t;
|
||||
|
||||
abstract class SheetDataAll
|
||||
{
|
||||
protected int $countData;
|
||||
/**
|
||||
* @var array|DividendsData $data
|
||||
*/
|
||||
protected array $data = [];
|
||||
protected array $dataNotCalculate = [];
|
||||
|
||||
/**
|
||||
* Assign raw data to field, then create array of DividendsData
|
||||
*
|
||||
* @param array $rawData
|
||||
*/
|
||||
public function __construct(private readonly array $rawData)
|
||||
{
|
||||
$this->countData = count($this->rawData) - 1;
|
||||
$this->data = $this->takeData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array grouped values by country
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getByCountry() : array
|
||||
{
|
||||
$data = $this->getData();
|
||||
if (!$data) {
|
||||
return [];
|
||||
}
|
||||
$newArr = [];
|
||||
/** @var DividendsData $datum */
|
||||
foreach ($data as $datum) {
|
||||
$key = mb_substr($datum->getIsin(), 0, 2);
|
||||
$newArr[$key][] = $datum;
|
||||
}
|
||||
|
||||
return $newArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count of rows
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCount(): int
|
||||
{
|
||||
return $this->countData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of DividendsData
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getData() : array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of raw data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getRawData() : array
|
||||
{
|
||||
return $this->rawData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate array of DividendsData from $rawData
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function takeData() : array;
|
||||
}
|
||||
@@ -55,7 +55,7 @@ class XMLReader
|
||||
$obj->setCurrency($value);
|
||||
}
|
||||
if ($key === "payDate") {
|
||||
$tmp = str_split($value, 4);
|
||||
$tmp = str_split((string) $value, 4);
|
||||
$y=$tmp[0];
|
||||
$tmp = str_split($tmp[1],2);
|
||||
$d = $tmp[1];
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Services;
|
||||
|
||||
use App\Helper\FIFO\Crypto;
|
||||
use App\Helper\Sheets\ReadSheet;
|
||||
use App\Logic\Crypto\MainObject;
|
||||
use App\Logic\Dividends\DividendsSummary;
|
||||
use App\Logic\Dividends\SheetData;
|
||||
use App\Logic\Dividends\XMLReader;
|
||||
@@ -11,25 +12,69 @@ use Doctrine\ORM\EntityManager;
|
||||
|
||||
class CryptoService extends MasterServices
|
||||
{
|
||||
public function generate() : array
|
||||
private array $transactions = [];
|
||||
private array $transactionsError = [];
|
||||
|
||||
public function generate() : bool
|
||||
{
|
||||
$summaryObj = new DividendsSummary($this->manager);
|
||||
$sum = 0;
|
||||
$errorArr = [];
|
||||
|
||||
$a = new Crypto();
|
||||
foreach ($this->allFiles as $file) {
|
||||
$extension = pathinfo($file)['extension'];
|
||||
$tmp = new ReadSheet($file);
|
||||
$tmp->takeFile();
|
||||
$a = new Crypto($tmp->getAll()[0]);
|
||||
$sum += array_sum($a->takeSumTransactions());
|
||||
$errorArr = array_merge($errorArr, $a->getNotCounted());
|
||||
if($tmp->takeFile()){
|
||||
$a->addData($tmp->getAll()[0]);
|
||||
}
|
||||
}
|
||||
$this->transactions = $a->takeSumTransactions();
|
||||
$this->transactionsError = $a->getNotCounted();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function takeAllByCurrency() : array
|
||||
{
|
||||
$return = [];
|
||||
$profitSum = 0;
|
||||
|
||||
|
||||
return [
|
||||
"sum" => $sum,
|
||||
"error" => $errorArr
|
||||
foreach ($this->transactions as $key => $transaction) {
|
||||
$tax = $transaction['income'] - $transaction['cost'];
|
||||
$profit = $tax;
|
||||
if ($tax < 0) {
|
||||
$tax = 0;
|
||||
} else {
|
||||
$tax = round($tax * 0.19,2);
|
||||
}
|
||||
$return[$key] = [
|
||||
"country" => $key,
|
||||
"currency" => "",
|
||||
"tax" => $tax,
|
||||
"profit" => $profit
|
||||
];
|
||||
$profitSum += $profit;
|
||||
$return[$key] = array_merge($return[$key], $transaction);
|
||||
}
|
||||
$return['sum'] = [
|
||||
'tax' => intval(ceil($profitSum*0.19)),
|
||||
'profit' => $profitSum
|
||||
];
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function takeAllByCurrencyEmpty() : array
|
||||
{
|
||||
$return = [];
|
||||
|
||||
foreach ($this->transactions as $key => $transaction) {
|
||||
if ($transaction['income'] === 0) {
|
||||
$return[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function takeError()
|
||||
{
|
||||
return $this->transactionsError;
|
||||
}
|
||||
}
|
||||
//LML, EXY, AMLT, XRP, XLM, OMG, ETH, LTC
|
||||
@@ -2,8 +2,11 @@
|
||||
declare(strict_types=1);
|
||||
namespace App\Services;
|
||||
|
||||
use App\Enum\MarketNames;
|
||||
use App\Helper\Sheets\ReadSheet;
|
||||
use App\Logic\Dividends\DividendsSummary;
|
||||
use App\Logic\Dividends\ExanteSheet;
|
||||
use App\Logic\Dividends\IbkrSheet;
|
||||
use App\Logic\Dividends\SheetData;
|
||||
use App\Logic\Dividends\XMLReader;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
@@ -15,16 +18,32 @@ class DividendsService extends MasterServices
|
||||
$summaryObj = new DividendsSummary($this->manager);
|
||||
|
||||
foreach ($this->allFiles as $file) {
|
||||
$extension = pathinfo($file)['extension'];
|
||||
$extension = pathinfo((string) $file)['extension'];
|
||||
$market = MarketNames::tryFromCase($file);
|
||||
|
||||
if (in_array($extension, ['xlsx','csv'])) {
|
||||
$reader = new ReadSheet($file);
|
||||
if ($reader->takeFile()) {
|
||||
if ($market === MarketNames::EXANTE) {
|
||||
$delimiter = ";";
|
||||
$delimiter = null;
|
||||
} else {
|
||||
$delimiter = null;
|
||||
}
|
||||
$reader = new ReadSheet($file, $market);
|
||||
if ($reader->takeFile($delimiter)) {
|
||||
/** @var SheetData $item */
|
||||
foreach ($reader->getAll() as $val) {
|
||||
if ($market === MarketNames::EXANTE) {
|
||||
$item = new ExanteSheet($val);
|
||||
} elseif ($market === MarketNames::IBKR) {
|
||||
$item = new IbkrSheet($val);
|
||||
}
|
||||
else {
|
||||
$item = new SheetData($val);
|
||||
}
|
||||
$summaryObj->addSheetData($item);
|
||||
}
|
||||
}
|
||||
$summaryObj->addMarket($market);
|
||||
}
|
||||
if ($extension === "xml") {
|
||||
$obj = new XMLReader($file);
|
||||
|
||||
@@ -2,19 +2,16 @@
|
||||
declare(strict_types=1);
|
||||
namespace App\Services;
|
||||
|
||||
use App\Enum\MarketNames;
|
||||
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)
|
||||
public function __construct(protected EntityManager $manager, protected string $hashParam)
|
||||
{
|
||||
$this->manager = $entity;
|
||||
$this->hashParam = $hash;
|
||||
}
|
||||
|
||||
public function setUploadsPath(string $path)
|
||||
@@ -22,7 +19,7 @@ class MasterServices
|
||||
$this->uploadPath = $path;
|
||||
}
|
||||
|
||||
public function readFiles() : bool
|
||||
public function readFiles(?MarketNames $market) : bool
|
||||
{
|
||||
$fileNames = [];
|
||||
$dir=$this->uploadPath . "/" . $this->hashParam;
|
||||
@@ -33,8 +30,20 @@ class MasterServices
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
if($market !== null) {
|
||||
foreach ($fileNames as $key => $fileName) {
|
||||
$fileMarket = MarketNames::tryFromCase($fileName);
|
||||
if ($fileMarket !== $market) {
|
||||
unset($fileNames[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->allFiles=$fileNames;
|
||||
|
||||
return count($fileNames) > 0;
|
||||
}
|
||||
|
||||
public function takeHash(): string
|
||||
{
|
||||
return $this->hashParam;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Twig;
|
||||
|
||||
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
|
||||
class AppExtension extends AbstractExtension
|
||||
{
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter("price", $this->formatPrice(...))
|
||||
];
|
||||
}
|
||||
|
||||
public function formatPrice(float $number, string $currency = "PLN", int $decimal = 2): string
|
||||
{
|
||||
return number_format($number, $decimal, ",", " ")." $currency";
|
||||
}
|
||||
}
|
||||
+9
-27
@@ -14,12 +14,6 @@
|
||||
"doctrine/cache": {
|
||||
"version": "2.1.1"
|
||||
},
|
||||
"doctrine/collections": {
|
||||
"version": "1.6.8"
|
||||
},
|
||||
"doctrine/common": {
|
||||
"version": "3.2.2"
|
||||
},
|
||||
"doctrine/dbal": {
|
||||
"version": "3.3.2"
|
||||
},
|
||||
@@ -59,18 +53,12 @@
|
||||
"doctrine/inflector": {
|
||||
"version": "2.0.4"
|
||||
},
|
||||
"doctrine/instantiator": {
|
||||
"version": "1.4.0"
|
||||
},
|
||||
"doctrine/lexer": {
|
||||
"version": "1.2.3"
|
||||
},
|
||||
"doctrine/migrations": {
|
||||
"version": "3.4.1"
|
||||
},
|
||||
"doctrine/orm": {
|
||||
"version": "2.11.1"
|
||||
},
|
||||
"doctrine/persistence": {
|
||||
"version": "2.3.0"
|
||||
},
|
||||
@@ -122,6 +110,15 @@
|
||||
"phpstan/phpdoc-parser": {
|
||||
"version": "1.2.0"
|
||||
},
|
||||
"phpstan/phpstan": {
|
||||
"version": "2.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes-contrib",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767"
|
||||
}
|
||||
},
|
||||
"psr/cache": {
|
||||
"version": "1.0.1"
|
||||
},
|
||||
@@ -161,9 +158,6 @@
|
||||
"config/packages/sensio_framework_extra.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/amqp-messenger": {
|
||||
"version": "v5.4.5"
|
||||
},
|
||||
"symfony/asset": {
|
||||
"version": "v5.4.3"
|
||||
},
|
||||
@@ -366,15 +360,9 @@
|
||||
"symfony/polyfill-mbstring": {
|
||||
"version": "v1.24.0"
|
||||
},
|
||||
"symfony/polyfill-php73": {
|
||||
"version": "v1.24.0"
|
||||
},
|
||||
"symfony/polyfill-php80": {
|
||||
"version": "v1.24.0"
|
||||
},
|
||||
"symfony/polyfill-php81": {
|
||||
"version": "v1.24.0"
|
||||
},
|
||||
"symfony/process": {
|
||||
"version": "v5.4.5"
|
||||
},
|
||||
@@ -387,9 +375,6 @@
|
||||
"symfony/proxy-manager-bridge": {
|
||||
"version": "v5.4.3"
|
||||
},
|
||||
"symfony/redis-messenger": {
|
||||
"version": "v5.4.5"
|
||||
},
|
||||
"symfony/routing": {
|
||||
"version": "5.4",
|
||||
"recipe": {
|
||||
@@ -424,9 +409,6 @@
|
||||
"symfony/security-csrf": {
|
||||
"version": "v5.4.3"
|
||||
},
|
||||
"symfony/security-guard": {
|
||||
"version": "v5.4.3"
|
||||
},
|
||||
"symfony/security-http": {
|
||||
"version": "v5.4.5"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Index{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="row justify-content-md-center" style="margin: 50px 0;">
|
||||
<div class="col-md-1">
|
||||
<a class="btn btn-primary" href="{{ path('app_taxes',{type:"dividend"}) }}">Dividends</a>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<a class="btn btn-primary" href="{{ path('app_taxes',{type:"crypto"}) }}">Cryptocurrency</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -3,33 +3,137 @@
|
||||
{% block title %}Tax summary{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="row justify-content-md-center" style="margin-top: 150px;">
|
||||
<div class="row justify-content-md-center" >
|
||||
<div class="col col-md-6">
|
||||
<ul class="nav nav-tabs">
|
||||
{% for market in markets_all %}
|
||||
{% set isHaveMarket = market.value in markets|keys %}
|
||||
{% set isCurrentMarket = market == current_market %}
|
||||
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link {% if isHaveMarket = 0 %}disabled{% endif %} {% if isCurrentMarket %}active{% endif %}" aria-current="page" href="{{ path("app_taxes_dividend_show",{hash:hash_param, market:market.value}) }}">{{ market.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if current_market is null %}active{% endif %}" aria-current="page" href="{{ path("app_taxes_dividend_show",{hash:hash_param, market:null}) }}">All</a>
|
||||
</li>
|
||||
|
||||
{# <li class="nav-item">#}
|
||||
{# <a class="nav-link active" aria-current="page" href="#">Active</a>#}
|
||||
{# </li>#}
|
||||
{# <li class="nav-item">#}
|
||||
{# <a class="nav-link" href="#">Link</a>#}
|
||||
{# </li>#}
|
||||
{# <li class="nav-item">#}
|
||||
{# <a class="nav-link" href="#">Link</a>#}
|
||||
{# </li>#}
|
||||
{# <li class="nav-item">#}
|
||||
{# <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>#}
|
||||
{# </li>#}
|
||||
</ul>
|
||||
{% if taxes %}
|
||||
<table class="table table-dark table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>L.p.</th>
|
||||
<th>Country</th>
|
||||
<th>Value</th>
|
||||
<th>Income</th>
|
||||
{% if taxes|first.cost is defined %}
|
||||
<th>Cost</th>
|
||||
{% endif %}
|
||||
{% if taxes|first.destiny_tax is defined %}
|
||||
<th>Origin tax</th>
|
||||
{% endif %}
|
||||
{% if taxes|first.tax_cost is defined %}
|
||||
<th>Deductable tax (15%)</th>
|
||||
{% endif %}
|
||||
{% if taxes|first.profit is defined %}
|
||||
<th>Profit/Loss</th>
|
||||
{% endif %}
|
||||
<th>Tax</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for tax in taxes %}
|
||||
<tr {% if tax.country is not defined %}class="table-success"{% endif %}>
|
||||
{% for key,tax in taxes %}
|
||||
{% if tax.country is defined %}
|
||||
{% set colspan = tax|length %}
|
||||
{% if tax.income > 0 %}
|
||||
<tr class="{% if tax.profit is defined and tax.profit < 0 %}table-danger{% else %}table-success{% endif %}">
|
||||
<td>{{ loop.index }}</td>
|
||||
<td>{{ tax.country }}</td>
|
||||
<td>{{ tax.value }}zł</td>
|
||||
{% else %}
|
||||
<td colspan="2">Summary:</td>
|
||||
<td>{{ tax }}zł</td>
|
||||
<td>{{ tax.income|price }}</td>
|
||||
{% if tax.cost is defined %}
|
||||
<td>{{ tax.cost|price }}</td>
|
||||
{% endif %}
|
||||
{% if tax.destiny_tax is defined %}
|
||||
<td>{{ tax.destiny_tax|price }}</td>
|
||||
{% endif %}
|
||||
{% if tax.tax_cost is defined %}
|
||||
<td>{{ tax.tax_cost|price }}</td>
|
||||
{% endif %}
|
||||
{% if tax.profit is defined %}
|
||||
<td>{{ tax.profit|price }}</td>
|
||||
{% endif %}
|
||||
<td>{{ tax.tax|price }}</td>
|
||||
</tr>
|
||||
{% if tax.incomesArray is defined and tax.incomesArray|length > 0 %}
|
||||
{% set colspan = colspan-1 %}
|
||||
{% for incomePerc,value in tax.incomesArray %}
|
||||
<tr>
|
||||
<td>#</td>
|
||||
<td></td>
|
||||
<td>{{ incomePerc }}% - {{ value|price }}</td>
|
||||
<td colspan="3"></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% elseif key == "sum" %}
|
||||
<tr class="">
|
||||
<td colspan="{{ colspan-2 }}">Summary:</td>
|
||||
<td>{{ tax.profit|price("PLN",0) }}</td>
|
||||
<td>{{ tax.tax|price("PLN",0) }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr class="">
|
||||
<td colspan="{{ colspan-1 }}">Summary:</td>
|
||||
<td>{{ tax|price("PLN",0) }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
Calculated <b>{{ rawCount.realCountRows }}</b> of <b>{{ rawCount.countRows }}</b> rows in <b>{{ rawCount.countSheet }}</b> sheets
|
||||
{% endif %}
|
||||
{% if errorDividend %}
|
||||
<table class="table table-dark table-striped">
|
||||
<tr>
|
||||
{% for row in errorDividend %}
|
||||
<td>{{ row.currency }}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
{% for row in errorDividend %}
|
||||
<td>{{ row.value }}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% if errorString %}
|
||||
{% for error in errorString %}
|
||||
<div class="alert alert-warning">
|
||||
<span>{{ error }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# {% if empty %}#}
|
||||
{# <div class="col col-md-6">#}
|
||||
{# {% for item in empty %}#}
|
||||
{# <div>{{ item }}</div>#}
|
||||
{# {% endfor %}#}
|
||||
{# </div>#}
|
||||
{# {% endif %}#}
|
||||
{% endblock %}
|
||||
Regular → Executable
@@ -45,15 +45,15 @@ Encore
|
||||
// enables hashed filenames (e.g. app.abc123.css)
|
||||
.enableVersioning(Encore.isProduction())
|
||||
|
||||
.configureBabel((config) => {
|
||||
config.plugins.push('@babel/plugin-proposal-class-properties');
|
||||
})
|
||||
|
||||
// enables @babel/preset-env polyfills
|
||||
.configureBabelPresetEnv((config) => {
|
||||
config.useBuiltIns = 'usage';
|
||||
config.corejs = 3;
|
||||
})
|
||||
// .configureBabel((config) => {
|
||||
// config.plugins.push('@babel/plugin-transform-class-properties');
|
||||
// })
|
||||
//
|
||||
// // enables @babel/preset-env polyfills
|
||||
// .configureBabelPresetEnv((config) => {
|
||||
// config.useBuiltIns = 'usage';
|
||||
// config.corejs = 3;
|
||||
// })
|
||||
|
||||
// enables Sass/SCSS support
|
||||
//.enableSassLoader()
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
|
||||
FROM php:7.4-fpm
|
||||
FROM php:8.1-fpm
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y nginx \
|
||||
&& apt-get install -y libpq-dev
|
||||
|
||||
|
||||
RUN pecl install redis-5.1.1 \
|
||||
&& pecl install xdebug-2.8.1 \
|
||||
&& docker-php-ext-enable redis xdebug
|
||||
RUN pecl install redis \
|
||||
&& docker-php-ext-enable redis
|
||||
|
||||
RUN apt-get update && apt-get -y install curl
|
||||
|
||||
@@ -61,9 +60,9 @@ COPY --chown=www-data:www-data ./project /var/www/html
|
||||
|
||||
#COPY --from=minimalise --chown=www-data /var/www/html/src/scripts_generated /var/www/html/src/scripts_generated
|
||||
WORKDIR /var/www/html
|
||||
RUN composer install
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
RUN apt-get purge --auto-remove -y npm
|
||||
#RUN composer install
|
||||
#RUN npm install
|
||||
#RUN npm run build
|
||||
#RUN apt-get purge --auto-remove -y npm
|
||||
|
||||
ENTRYPOINT ["/etc/entrypoint.sh"]
|
||||
Reference in New Issue
Block a user