Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop

# Conflicts:
#	app/JsonApi/V2/Accounts/AccountRepository.php
#	app/JsonApi/V2/Accounts/AccountRequest.php
#	app/JsonApi/V2/Accounts/Capabilities/CrudAccount.php
#	app/Support/Steam.php
This commit is contained in:
James Cole
2024-08-05 19:48:46 +02:00
32 changed files with 570 additions and 563 deletions

View File

@@ -170,7 +170,6 @@ class UpdateController extends Controller
/** @var User $user */
$user = auth()->user();
// safety catch on currency disablement.
$set = $this->repository->get();
if (array_key_exists('enabled', $data) && false === $data['enabled'] && 1 === count($set) && $set->first()->id === $currency->id) {

View File

@@ -102,6 +102,7 @@ class PreferencesController extends Controller
* TODO This endpoint is not documented.
*
* Return a single preference by name.
*
* @param Collection<int, Preference> $collection
*/
public function showList(Collection $collection): JsonResponse

View File

@@ -46,7 +46,7 @@ class AccountController extends Controller
use Actions\Destroy;
use Actions\DetachRelationship;
use Actions\FetchMany;
use Actions\FetchMany;
// use Actions\FetchOne;
use Actions\FetchRelated;
use Actions\FetchRelationship;
@@ -66,7 +66,8 @@ class AccountController extends Controller
->repository()
->queryAll()
->withRequest($request)
->get();
->get()
;
// do something custom...

View File

@@ -43,8 +43,8 @@ class OtherCurrenciesCorrections extends Command
use ShowsFriendlyMessages;
public const string CONFIG_NAME = '480_other_currencies';
protected $description = 'Update all journal currency information.';
protected $signature = 'firefly-iii:other-currencies {--F|force : Force the execution of this command.}';
protected $description = 'Update all journal currency information.';
protected $signature = 'firefly-iii:other-currencies {--F|force : Force the execution of this command.}';
private array $accountCurrencies;
private AccountRepositoryInterface $accountRepos;
private JournalCLIRepositoryInterface $cliRepos;
@@ -220,14 +220,14 @@ class OtherCurrenciesCorrections extends Command
private function getCurrency(Account $account): ?TransactionCurrency
{
$accountId = $account->id;
$accountId = $account->id;
if (array_key_exists($accountId, $this->accountCurrencies) && 0 === $this->accountCurrencies[$accountId]) {
return null;
}
if (array_key_exists($accountId, $this->accountCurrencies) && $this->accountCurrencies[$accountId] instanceof TransactionCurrency) {
return $this->accountCurrencies[$accountId];
}
$currency = $this->accountRepos->getAccountCurrency($account);
$currency = $this->accountRepos->getAccountCurrency($account);
if (null === $currency) {
$this->accountCurrencies[$accountId] = 0;
@@ -249,6 +249,7 @@ class OtherCurrenciesCorrections extends Command
if (false === $value || null === $value) {
return false;
}
return '1' === $value;
}
}

View File

@@ -29,28 +29,28 @@ class AccountCollectionQuery extends ResourceQuery
'array',
JsonApiRule::fieldSets(),
],
'userGroupId' => [
'userGroupId' => [
'nullable',
'integer',
new IsAllowedGroupAction(Account::class, request()->method()),
],
'startPeriod' => [
'startPeriod' => [
'nullable',
'date',
new IsDateOrTime(),
new isValidDateRange(),
new IsValidDateRange(),
],
'endPeriod' => [
'endPeriod' => [
'nullable',
'date',
new IsDateOrTime(),
new isValidDateRange(),
new IsValidDateRange(),
],
'filter' => [
'nullable',
'array',
JsonApiRule::filter($validFilters),
new IsValidAccountType()
new IsValidAccountType(),
],
'include' => [
'nullable',

View File

@@ -29,10 +29,8 @@ use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use Illuminate\Support\Facades\Log;
use LaravelJsonApi\Contracts\Store\CreatesResources;
use LaravelJsonApi\Contracts\Store\QueriesAll;
use LaravelJsonApi\Contracts\Store\QueryOneBuilder;
use LaravelJsonApi\NonEloquent\AbstractRepository;
use LaravelJsonApi\NonEloquent\Capabilities\CrudRelations;
use LaravelJsonApi\NonEloquent\Capabilities\CrudResource;
use LaravelJsonApi\NonEloquent\Concerns\HasCrudCapability;
use LaravelJsonApi\NonEloquent\Concerns\HasRelationsCapability;
@@ -52,27 +50,25 @@ class AccountRepository extends AbstractRepository implements QueriesAll, Create
use HasRelationsCapability;
use UsergroupAware;
/**
* SiteRepository constructor.
*/
public function __construct() {
public function __construct()
{
Log::debug(__METHOD__);
}
public function exists(string $resourceId): bool
{
$result = null !== Account::find((int) $resourceId);
Log::debug(sprintf('%s: %s',__METHOD__, var_export($result, true)));
Log::debug(sprintf('%s: %s', __METHOD__, var_export($result, true)));
return $result;
}
public function find(string $resourceId): ?object
{
die(__METHOD__);
exit(__METHOD__);
Log::debug(__METHOD__);
// throw new \RuntimeException('trace me');
$account = Account::find((int) $resourceId);
@@ -99,6 +95,7 @@ class AccountRepository extends AbstractRepository implements QueriesAll, Create
protected function crud(): Capabilities\CrudAccount
{
Log::debug(__METHOD__);
return Capabilities\CrudAccount::make();
}
@@ -111,6 +108,7 @@ class AccountRepository extends AbstractRepository implements QueriesAll, Create
protected function relations(): CrudRelations
{
Log::debug(__METHOD__);
return Capabilities\CrudAccountRelations::make();
}
}

View File

@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V2\Accounts;
use FireflyIII\Rules\Account\IsUniqueAccount;
@@ -13,11 +15,8 @@ use LaravelJsonApi\Laravel\Http\Requests\ResourceRequest;
class AccountRequest extends ResourceRequest
{
use ConvertsDataTypes;
/**
* Get the validation rules for the resource.
*
* @return array
*/
public function rules(): array
{
@@ -52,7 +51,7 @@ class AccountRequest extends ResourceRequest
// 'interest' => 'min:0|max:100|numeric',
// 'interest_period' => sprintf('nullable|in:%s', implode(',', config('firefly.interest_periods'))),
// 'notes' => 'min:0|max:32768',
];
}
}

View File

@@ -28,7 +28,7 @@ class AccountResource extends JsonApiResource
*/
public function attributes($request): iterable
{
//Log::debug(__METHOD__);
// Log::debug(__METHOD__);
return [
'created_at' => $this->resource->created_at,
@@ -62,7 +62,6 @@ class AccountResource extends JsonApiResource
// other things
'last_activity' => $this->resource->last_activity,
// object group
'object_group_id' => $this->resource->object_group_id,
'object_group_title' => $this->resource->object_group_title,

View File

@@ -28,7 +28,7 @@ class AccountSchema extends Schema
*/
public function fields(): array
{
Log::debug(__METHOD__);
Log::debug(__METHOD__);
return [
ID::make(),
@@ -89,6 +89,7 @@ class AccountSchema extends Schema
foreach ($config as $entry) {
$array[] = Filter::make($entry);
}
return $array;
}
@@ -96,18 +97,18 @@ class AccountSchema extends Schema
{
Log::debug(__METHOD__);
$this->setUserGroup($this->server->getUsergroup());
return AccountRepository::make()
->withServer($this->server)
->withSchema($this)
->withUserGroup($this->userGroup);
->withServer($this->server)
->withSchema($this)
->withUserGroup($this->userGroup)
;
}
/**
* @inheritDoc
*/
public function pagination(): EnumerablePagination
{
Log::debug(__METHOD__);
return EnumerablePagination::make();
}
}

View File

@@ -41,16 +41,16 @@ use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
class AccountQuery extends QueryAll implements HasPagination
{
use AccountFilter;
use CollectsCustomParameters;
use ExpandsQuery;
use FiltersPagination;
use SortsCollection;
use SortsQueryResults;
use UsergroupAware;
use ValidateSortParameters;
use CollectsCustomParameters;
use AccountFilter;
use SortsQueryResults;
//use PaginatesEnumerables;
// use PaginatesEnumerables;
#[\Override]
/**
@@ -62,49 +62,46 @@ class AccountQuery extends QueryAll implements HasPagination
{
Log::debug(__METHOD__);
// collect sort options
$sort = $this->queryParameters->sortFields();
$sort = $this->queryParameters->sortFields();
// collect pagination based on the page
$pagination = $this->filtersPagination($this->queryParameters->page());
$pagination = $this->filtersPagination($this->queryParameters->page());
// check if we need all accounts, regardless of pagination
// This is necessary when the user wants to sort on specific params.
$needsAll = $this->needsFullDataset(Account::class, $sort);
$needsAll = $this->needsFullDataset(Account::class, $sort);
// params that were not recognised, may be my own custom stuff.
$otherParams = $this->getOtherParams($this->queryParameters->unrecognisedParameters());
// start the query
$query = $this->userGroup->accounts();
$query = $this->userGroup->accounts();
// add sort and filter parameters to the query.
$query = $this->addSortParams(Account::class, $query, $sort);
$query = $this->addFilterParams(Account::class, $query, $this->queryParameters->filter());
$query = $this->addSortParams(Account::class, $query, $sort);
$query = $this->addFilterParams(Account::class, $query, $this->queryParameters->filter());
// collect the result.
$collection = $query->get(['accounts.*']);
$collection = $query->get(['accounts.*']);
// sort the data after the query, and return it right away.
$collection = $this->sortCollection(Account::class, $collection, $sort);
$collection = $this->sortCollection(Account::class, $collection, $sort);
// if the entire collection needs to be enriched and sorted, do so now:
$totalCount = $collection->count();
$totalCount = $collection->count();
Log::debug(sprintf('Total is %d', $totalCount));
if ($needsAll) {
Log::debug('Needs the entire collection');
// enrich the entire collection
$enrichment = new AccountEnrichment();
$enrichment = new AccountEnrichment();
$enrichment->setStart($otherParams['start'] ?? null);
$enrichment->setEnd($otherParams['end'] ?? null);
$collection = $enrichment->enrich($collection);
$collection = $enrichment->enrich($collection);
// TODO sort the set based on post-query sort options:
$collection = $this->postQuerySort(Account::class, $collection, $sort);
$collection = $this->postQuerySort(Account::class, $collection, $sort);
// take the current page from the enriched set.
$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
}
if (!$needsAll) {
Log::debug('Needs only partial collection');
@@ -112,38 +109,33 @@ class AccountQuery extends QueryAll implements HasPagination
$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
// enrich only the current page.
$enrichment = new AccountEnrichment();
$enrichment = new AccountEnrichment();
$enrichment->setStart($otherParams['start'] ?? null);
$enrichment->setEnd($otherParams['end'] ?? null);
$currentPage = $enrichment->enrich($currentPage);
}
// get current page?
Log::debug(sprintf('Skip %d, take %d', ($pagination['number'] - 1) * $pagination['size'], $pagination['size']));
//$currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
// $currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
Log::debug(sprintf('New collection size: %d', $currentPage->count()));
// TODO add filters after the query, if there are filters that cannot be applied to the database
// TODO same for sort things.
return new LengthAwarePaginator($currentPage, $totalCount, $pagination['size'], $pagination['number']);
}
/**
* @inheritDoc
*/
#[\Override] public function paginate(array $page): Page
#[\Override]
public function paginate(array $page): Page
{
die('here weare');
exit('here weare');
// TODO: Implement paginate() method.
}
/**
* @inheritDoc
*/
#[\Override] public function getOrPaginate(?array $page): iterable
#[\Override]
public function getOrPaginate(?array $page): iterable
{
die('here weare');
exit('here weare');
// TODO: Implement getOrPaginate() method.
}
}

View File

@@ -42,18 +42,16 @@ class CrudAccount extends CrudResource
Log::debug(__METHOD__);
// enrich the collected data
$enrichment = new AccountEnrichment();
$enrichment = new AccountEnrichment();
// set start and date, if present.
$enrichment->setStart($otherParams['start'] ?? null);
$enrichment->setEnd($otherParams['end'] ?? null);
return $enrichment->enrichSingle($account);
}
public function create(array $validatedData): Account {
var_dump($validatedData);exit;
die('in create method.');
}
}

View File

@@ -49,6 +49,7 @@ class AccountPolicy
public function viewAny(): bool
{
Log::debug(__METHOD__);
return auth()->check();
}

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Rules\Account;
use Closure;
use FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Contracts\Validation\ValidationRule;
@@ -31,12 +30,9 @@ class IsValidAccountType implements ValidationRule
{
use AccountFilter;
/**
* @inheritDoc
*/
#[\Override] public function validate(string $attribute, mixed $value, Closure $fail): void
#[\Override]
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
// only check the type.
if (array_key_exists('type', $value)) {
$value = $value['type'];
@@ -44,13 +40,13 @@ class IsValidAccountType implements ValidationRule
$value = [$value];
}
$filtered = [];
$keys = array_keys($this->types);
/** @var mixed $entry */
foreach ($value as $entry) {
$entry = (string) $entry;
if (!in_array($entry, $keys)) {
if (!in_array($entry, $keys, true)) {
$fail('something');
}
}

View File

@@ -35,17 +35,18 @@ class IsValidDateRange implements ValidationRule
*/
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
$value = (string) $value;
$value = (string) $value;
if ('' === $value) {
$fail('validation.date_or_time')->translate();
return;
}
$other = 'startPeriod';
$other = 'startPeriod';
if ('startPeriod' === $attribute) {
$other = 'endPeriod';
}
$otherValue = request()->get($other);
// parse date, twice.
try {
$left = Carbon::parse($value);
@@ -68,6 +69,7 @@ class IsValidDateRange implements ValidationRule
if ($left->gt($right)) {
$fail('validation.date_after')->translate();
}
return;
}
// end must be after start
@@ -76,4 +78,3 @@ class IsValidDateRange implements ValidationRule
}
}
}

View File

@@ -45,8 +45,10 @@ class Amount
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
}
public function formatByCurrencyId(int $currencyId, string $amount, ?bool $coloured = null): string {
public function formatByCurrencyId(int $currencyId, string $amount, ?bool $coloured = null): string
{
$format = TransactionCurrency::find($currencyId);
return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured);
}

View File

@@ -31,14 +31,8 @@ use Illuminate\Support\Facades\Log;
class Balance
{
/**
* Returns the accounts balances as an array, on the account ID.
*
* @param Collection $accounts
* @param Carbon $date
*
* @return array
*/
public function getAccountBalances(Collection $accounts, Carbon $date): array
{
@@ -53,19 +47,19 @@ class Balance
return $cache->get();
}
$query = Transaction::
whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->orderBy('transaction_journals.date', 'desc')
->orderBy('transaction_journals.order', 'asc')
->orderBy('transaction_journals.description', 'desc')
->orderBy('transactions.amount', 'desc')
->where('transaction_journals.date', '<=', $date);
$query = Transaction::whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->orderBy('transaction_journals.date', 'desc')
->orderBy('transaction_journals.order', 'asc')
->orderBy('transaction_journals.description', 'desc')
->orderBy('transactions.amount', 'desc')
->where('transaction_journals.date', '<=', $date)
;
$result = $query->get(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.balance_after']);
$result = $query->get(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.balance_after']);
foreach ($result as $entry) {
$accountId = (int) $entry->account_id;
$currencyId = (int) $entry->transaction_currency_id;
$accountId = (int) $entry->account_id;
$currencyId = (int) $entry->transaction_currency_id;
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
$return[$accountId] ??= [];
if (array_key_exists($currencyId, $return[$accountId])) {
@@ -73,7 +67,7 @@ class Balance
}
$return[$accountId][$currencyId] = ['currency' => $currencies[$currencyId], 'balance' => $entry->balance_after, 'date' => clone $date];
}
return $return;
return $return;
}
}

View File

@@ -81,6 +81,7 @@ trait AccountFilter
'creditcard' => [AccountType::CREDITCARD],
'cc' => [AccountType::CREDITCARD],
];
/**
* All the available types.
*/

View File

@@ -44,7 +44,6 @@ class ExchangeRateConverter
private array $prepared = [];
private int $queryCount = 0;
public function enabled(): bool
{
return false !== config('cer.enabled');
@@ -85,8 +84,8 @@ class ExchangeRateConverter
*/
private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
{
$key = $this->getCacheKey($from, $to, $date);
$res = Cache::get($key, null);
$key = $this->getCacheKey($from, $to, $date);
$res = Cache::get($key, null);
// find in cache
if (null !== $res) {
@@ -96,7 +95,7 @@ class ExchangeRateConverter
}
// find in database
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
$rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d'));
if (null !== $rate) {
Cache::forever($key, $rate);
Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d')));
@@ -105,7 +104,7 @@ class ExchangeRateConverter
}
// find reverse in database
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
$rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d'));
if (null !== $rate) {
$rate = bcdiv('1', $rate);
Cache::forever($key, $rate);
@@ -138,7 +137,7 @@ class ExchangeRateConverter
if ($from === $to) {
return '1';
}
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
$key = sprintf('cer-%d-%d-%s', $from, $to, $date);
// perhaps the rate has been cached during this particular run
$preparedRate = $this->prepared[$date][$from][$to] ?? null;
@@ -148,7 +147,7 @@ class ExchangeRateConverter
return $preparedRate;
}
$cache = new CacheProperties();
$cache = new CacheProperties();
$cache->addProperty($key);
if ($cache->has()) {
$rate = $cache->get();
@@ -161,15 +160,16 @@ class ExchangeRateConverter
}
/** @var null|CurrencyExchangeRate $result */
$result = auth()->user()
->currencyExchangeRates()
->where('from_currency_id', $from)
->where('to_currency_id', $to)
->where('date', '<=', $date)
->orderBy('date', 'DESC')
->first();
$result = auth()->user()
->currencyExchangeRates()
->where('from_currency_id', $from)
->where('to_currency_id', $to)
->where('date', '<=', $date)
->orderBy('date', 'DESC')
->first()
;
++$this->queryCount;
$rate = (string) $result?->rate;
$rate = (string) $result?->rate;
if ('' === $rate) {
app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date));
@@ -209,13 +209,13 @@ class ExchangeRateConverter
if ($euroId === $currency->id) {
return '1';
}
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
$rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d'));
if (null !== $rate) {
// app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate));
return $rate;
}
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
$rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d'));
if (null !== $rate) {
return bcdiv('1', $rate);
// app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate));
@@ -244,7 +244,7 @@ class ExchangeRateConverter
if ($cache->has()) {
return (int) $cache->get();
}
$euro = TransactionCurrency::whereCode('EUR')->first();
$euro = TransactionCurrency::whereCode('EUR')->first();
++$this->queryCount;
if (null === $euro) {
throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.');
@@ -266,13 +266,14 @@ class ExchangeRateConverter
$start->startOfDay();
$end->endOfDay();
Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d')));
$set = auth()->user()
->currencyExchangeRates()
->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id)
->where('date', '<=', $end->format('Y-m-d'))
->where('date', '>=', $start->format('Y-m-d'))
->orderBy('date', 'DESC')->get();
$set = auth()->user()
->currencyExchangeRates()
->where('from_currency_id', $from->id)
->where('to_currency_id', $to->id)
->where('date', '<=', $end->format('Y-m-d'))
->where('date', '>=', $start->format('Y-m-d'))
->orderBy('date', 'DESC')->get()
;
++$this->queryCount;
if (0 === $set->count()) {
Log::debug('No prepared rates found in this period, use the fallback');
@@ -286,10 +287,10 @@ class ExchangeRateConverter
$this->isPrepared = true;
// so there is a fallback just in case. Now loop the set of rates we DO have.
$temp = [];
$count = 0;
$temp = [];
$count = 0;
foreach ($set as $rate) {
$date = $rate->date->format('Y-m-d');
$date = $rate->date->format('Y-m-d');
$temp[$date] ??= [
$from->id => [
$to->id => $rate->rate,
@@ -298,11 +299,11 @@ class ExchangeRateConverter
++$count;
}
Log::debug(sprintf('Found %d rates in this period.', $count));
$currentStart = clone $start;
$currentStart = clone $start;
while ($currentStart->lte($end)) {
$currentDate = $currentStart->format('Y-m-d');
$currentDate = $currentStart->format('Y-m-d');
$this->prepared[$currentDate] ??= [];
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
$fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0';
if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) {
// fill from temp or fallback or from temp (see before)
$this->prepared[$currentDate][$from->id][$to->id] = $fallback;

View File

@@ -441,7 +441,7 @@ trait PeriodOverview
$cache->addProperty('tag-period-entries');
$cache->addProperty($tag->id);
if ($cache->has()) {
return $cache->get();
return $cache->get();
}
/** @var array $dates */

View File

@@ -27,7 +27,6 @@ use Carbon\Carbon;
trait CollectsCustomParameters
{
protected function getOtherParams(array $params): array
{
$return = [];
@@ -37,7 +36,7 @@ trait CollectsCustomParameters
if (array_key_exists('endPeriod', $params)) {
$return['end'] = Carbon::parse($params['endPeriod']);
}
if(array_key_exists('currentMoment', $params)) {
if (array_key_exists('currentMoment', $params)) {
$return['today'] = Carbon::parse($params['currentMoment']);
}

View File

@@ -117,8 +117,8 @@ class AccountEnrichment implements EnrichmentInterface
$default = $this->default;
// get start and end, so the balance difference can be generated.
$start = null;
$end = null;
$start = null;
$end = null;
if (null !== $this->start) {
$start = Balance::getAccountBalances($this->collection, $this->start);
}
@@ -140,7 +140,7 @@ class AccountEnrichment implements EnrichmentInterface
'balance_difference' => null,
];
if (array_key_exists($account->id, $balances)) {
$set = [];
$set = [];
foreach ($balances[$account->id] as $currencyId => $entry) {
$left = $start[$account->id][$currencyId]['balance'] ?? null;
$right = $end[$account->id][$currencyId]['balance'] ?? null;
@@ -176,7 +176,6 @@ class AccountEnrichment implements EnrichmentInterface
}
}
return $account;
});
}
@@ -205,7 +204,7 @@ class AccountEnrichment implements EnrichmentInterface
$metaFields = $this->repository->getMetaValues($this->collection, ['is_multi_currency', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']);
$currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray();
$currencies = [];
$currencies = [];
foreach ($this->currencyRepository->getByIds($currencyIds) as $currency) {
$id = $currency->id;
$currencies[$id] = $currency;
@@ -250,31 +249,33 @@ class AccountEnrichment implements EnrichmentInterface
private function getObjectGroups(): void
{
$set = \DB::table('object_groupables')
->where('object_groupable_type', Account::class)
->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray())
->distinct()
->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id']);
$set = \DB::table('object_groupables')
->where('object_groupable_type', Account::class)
->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray())
->distinct()
->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id'])
;
// get the groups:
$groupIds = $set->pluck('object_group_id')->toArray();
$groups = ObjectGroup::whereIn('id', $groupIds)->get();
/** @var ObjectGroup $group */
foreach ($groups as $group) {
$this->objectGroups[$group->id] = $group;
}
/** @var \stdClass $entry */
foreach ($set as $entry) {
$this->grouped[(int) $entry->object_groupable_id] = (int) $entry->object_group_id;
}
$this->collection->transform(function (Account $account) {
$this->collection->transform(function (Account $account) {
$account->object_group_id = $this->grouped[$account->id] ?? null;
if(null !== $account->object_group_id) {
if (null !== $account->object_group_id) {
$account->object_group_title = $this->objectGroups[$account->object_group_id]->title;
$account->object_group_order = $this->objectGroups[$account->object_group_id]->order;
}
return $account;
});
}
}

View File

@@ -62,6 +62,7 @@ trait ExpandsQuery
foreach ($value as $entry) {
$return = array_merge($return, $this->mapAccountTypes($entry));
}
return array_unique($return);
}
@@ -70,7 +71,7 @@ trait ExpandsQuery
$config = config('api.valid_api_filters')[$class];
$parsed = [];
foreach ($filters->all() as $filter) {
$key = $filter->key();
$key = $filter->key();
if (!in_array($key, $config, true)) {
continue;
}
@@ -86,12 +87,16 @@ trait ExpandsQuery
switch ($filter->key()) {
case 'name':
$parsed['name'] = $value;
break;
case 'type':
$parsed['type'] = $this->parseAccountTypeFilter($value);
break;
}
}
return $parsed;
}
@@ -122,14 +127,13 @@ trait ExpandsQuery
});
// TODO this is special treatment, but alas, unavoidable right now.
if ($class === Account::class && array_key_exists('type', $parsed)) {
if (Account::class === $class && array_key_exists('type', $parsed)) {
if (count($parsed['type']) > 0) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
$query->whereIn('account_types.type', $parsed['type']);
}
}
return $query;
}
}

View File

@@ -31,24 +31,18 @@ use LaravelJsonApi\Core\Query\SortFields;
trait SortsQueryResults
{
final protected function postQuerySort(string $class, Collection $collection, SortFields $parameters): Collection
{
Log::debug(__METHOD__);
foreach ($parameters->all() as $field) {
$collection = $this->sortQueryCollection($class, $collection, $field);
}
return $collection;
}
/**
* TODO improve this.
*
* @param string $class
* @param Collection $collection
* @param SortField $field
*
* @return Collection
*/
private function sortQueryCollection(string $class, Collection $collection, SortField $field): Collection
{
@@ -59,6 +53,7 @@ trait SortsQueryResults
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftSum = $this->sumBalance($left->balance);
$rightSum = $this->sumBalance($right->balance);
return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum);
});
}
@@ -67,6 +62,7 @@ trait SortsQueryResults
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftSum = $this->sumBalanceDifference($left->balance);
$rightSum = $this->sumBalanceDifference($right->balance);
return $ascending ? bccomp($leftSum, $rightSum) : bccomp($rightSum, $leftSum);
});
}
@@ -76,6 +72,7 @@ trait SortsQueryResults
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftNr = sprintf('%s%s', $left->iban, $left->account_number);
$rightNr = sprintf('%s%s', $right->iban, $right->account_number);
return $ascending ? strcmp($leftNr, $rightNr) : strcmp($rightNr, $leftNr);
});
}
@@ -86,17 +83,17 @@ trait SortsQueryResults
$collection = $collection->sort(function (Account $left, Account $right) use ($ascending): int {
$leftNr = (int)$left->last_activity?->format('U');
$rightNr = (int)$right->last_activity?->format('U');
if($ascending){
if ($ascending) {
return $leftNr <=> $rightNr;
}
return $rightNr <=> $leftNr;
//return (int) ($ascending ? $rightNr < $leftNr : $leftNr < $rightNr );
// return (int) ($ascending ? $rightNr < $leftNr : $leftNr < $rightNr );
});
}
// sort by balance difference.
return $collection;
}
@@ -112,6 +109,7 @@ trait SortsQueryResults
foreach ($balance as $entry) {
$sum = bcadd($sum, $entry['balance']);
}
return $sum;
}
@@ -127,7 +125,7 @@ trait SortsQueryResults
foreach ($balance as $entry) {
$sum = bcadd($sum, $entry['balance_difference']);
}
return $sum;
}
}

View File

@@ -38,6 +38,7 @@ trait ValidateSortParameters
foreach ($params->all() as $field) {
if (in_array($field->name(), $config, true)) {
Log::debug('TRUE');
return true;
}
}

View File

@@ -46,24 +46,26 @@ class Steam
{
//Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$repository = app(AccountRepositoryInterface::class);
$repository->setUser($account->user);
$currencyId = (int) $repository->getMetaValue($account, 'currency_id');
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currencyId)
->get(['transactions.amount'])->toArray();
$nativeBalance = $this->sumTransactions($transactions, 'amount');
$currencyId = (int) $repository->getMetaValue($account, 'currency_id');
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currencyId)
->get(['transactions.amount'])->toArray()
;
$nativeBalance = $this->sumTransactions($transactions, 'amount');
// get all balances in foreign currency:
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $currencyId)
->where('transactions.transaction_currency_id', '!=', $currencyId)
->get(['transactions.foreign_amount'])->toArray();
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $currencyId)
->where('transactions.transaction_currency_id', '!=', $currencyId)
->get(['transactions.foreign_amount'])->toArray()
;
$foreignBalance = $this->sumTransactions($transactions, 'foreign_amount');
@@ -106,41 +108,42 @@ class Steam
$start->subDay();
$end->addDay();
$balances = [];
$formatted = $start->format('Y-m-d');
$startBalance = $this->balance($account, $start, $currency);
$balances = [];
$formatted = $start->format('Y-m-d');
$startBalance = $this->balance($account, $start, $currency);
$balances[$formatted] = $startBalance;
if (null === $currency) {
$repository = app(AccountRepositoryInterface::class);
$repository->setUser($account->user);
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
$currencyId = $currency->id;
$currencyId = $currency->id;
$start->addDay();
// query!
$set = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'))
->groupBy('transaction_journals.date')
->groupBy('transactions.transaction_currency_id')
->groupBy('transactions.foreign_currency_id')
->orderBy('transaction_journals.date', 'ASC')
->whereNull('transaction_journals.deleted_at')
->get(
[ // @phpstan-ignore-line
'transaction_journals.date',
'transactions.transaction_currency_id',
\DB::raw('SUM(transactions.amount) AS modified'),
'transactions.foreign_currency_id',
\DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
]
);
$set = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'))
->groupBy('transaction_journals.date')
->groupBy('transactions.transaction_currency_id')
->groupBy('transactions.foreign_currency_id')
->orderBy('transaction_journals.date', 'ASC')
->whereNull('transaction_journals.deleted_at')
->get(
[ // @phpstan-ignore-line
'transaction_journals.date',
'transactions.transaction_currency_id',
\DB::raw('SUM(transactions.amount) AS modified'),
'transactions.foreign_currency_id',
\DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
]
)
;
$currentBalance = $startBalance;
$currentBalance = $startBalance;
/** @var Transaction $entry */
foreach ($set as $entry) {
@@ -170,7 +173,7 @@ class Steam
public function balanceByTransactions(Account $account, Carbon $date, ?TransactionCurrency $currency): array
{
$cache = new CacheProperties();
$cache = new CacheProperties();
$cache->addProperty($account->id);
$cache->addProperty('balance-by-transactions');
$cache->addProperty($date);
@@ -179,12 +182,13 @@ class Steam
return $cache->get();
}
$query = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->orderBy('transaction_journals.date', 'desc')
->orderBy('transaction_journals.order', 'asc')
->orderBy('transaction_journals.description', 'desc')
->orderBy('transactions.amount', 'desc');
$query = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->orderBy('transaction_journals.date', 'desc')
->orderBy('transaction_journals.order', 'asc')
->orderBy('transaction_journals.description', 'desc')
->orderBy('transactions.amount', 'desc')
;
if (null !== $currency) {
$query->where('transactions.transaction_currency_id', $currency->id);
$query->limit(1);
@@ -192,18 +196,20 @@ class Steam
$key = (int) $result->transaction_currency_id;
$return = [$key => $result->balance_after];
$cache->store($return);
return $return;
}
$return = [];
$result = $query->get(['transactions.transaction_currency_id', 'transactions.balance_after']);
foreach ($result as $entry) {
$key = (int) $entry->transaction_currency_id;
$key = (int) $entry->transaction_currency_id;
if (array_key_exists($key, $return)) {
continue;
}
$return[$key] = $entry->balance_after;
}
return $return;
}
@@ -216,7 +222,7 @@ class Steam
{
// Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
// abuse chart properties:
$cache = new CacheProperties();
$cache = new CacheProperties();
$cache->addProperty($account->id);
$cache->addProperty('balance');
$cache->addProperty($date);
@@ -226,24 +232,26 @@ class Steam
}
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$repository = app(AccountRepositoryInterface::class);
if (null === $currency) {
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
// first part: get all balances in own currency:
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id)
->get(['transactions.amount'])->toArray();
$nativeBalance = $this->sumTransactions($transactions, 'amount');
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id)
->get(['transactions.amount'])->toArray()
;
$nativeBalance = $this->sumTransactions($transactions, 'amount');
// get all balances in foreign currency:
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $currency->id)
->where('transactions.transaction_currency_id', '!=', $currency->id)
->get(['transactions.foreign_amount'])->toArray();
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $currency->id)
->where('transactions.transaction_currency_id', '!=', $currency->id)
->get(['transactions.foreign_amount'])->toArray()
;
$foreignBalance = $this->sumTransactions($transactions, 'foreign_amount');
$balance = bcadd($nativeBalance, $foreignBalance);
$virtual = null === $account->virtual_balance ? '0' : $account->virtual_balance;
@@ -261,8 +269,8 @@ class Steam
*/
public function balanceInRangeConverted(Account $account, Carbon $start, Carbon $end, TransactionCurrency $native): array
{
// Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$cache = new CacheProperties();
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$cache = new CacheProperties();
$cache->addProperty($account->id);
$cache->addProperty('balance-in-range-converted');
$cache->addProperty($native->id);
@@ -282,34 +290,35 @@ class Steam
Log::debug(sprintf('Start balance on %s is %s', $formatted, $startBalance));
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$converter = new ExchangeRateConverter();
$converter = new ExchangeRateConverter();
// not sure why this is happening:
$start->addDay();
// grab all transactions between start and end:
$set = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'))
->orderBy('transaction_journals.date', 'ASC')
->whereNull('transaction_journals.deleted_at')
->get(
[
'transaction_journals.date',
'transactions.transaction_currency_id',
'transactions.amount',
'transactions.foreign_currency_id',
'transactions.foreign_amount',
]
)->toArray();
$set = $account->transactions()
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'))
->orderBy('transaction_journals.date', 'ASC')
->whereNull('transaction_journals.deleted_at')
->get(
[
'transaction_journals.date',
'transactions.transaction_currency_id',
'transactions.amount',
'transactions.foreign_currency_id',
'transactions.foreign_amount',
]
)->toArray()
;
// loop the set and convert if necessary:
$currentBalance = $startBalance;
$currentBalance = $startBalance;
/** @var Transaction $transaction */
foreach ($set as $transaction) {
$day = false;
$day = false;
try {
$day = Carbon::parse($transaction['date'], config('app.timezone'));
@@ -319,7 +328,7 @@ class Steam
if (false === $day) {
$day = today(config('app.timezone'));
}
$format = $day->format('Y-m-d');
$format = $day->format('Y-m-d');
// if the transaction is in the expected currency, change nothing.
if ((int) $transaction['transaction_currency_id'] === $native->id) {
// change the current balance, set it to today, continue the loop.
@@ -342,21 +351,21 @@ class Steam
$currency = $currencies[$currencyId] ?? TransactionCurrency::find($currencyId);
$currencies[$currencyId] = $currency;
$rate = $converter->getCurrencyRate($currency, $native, $day);
$convertedAmount = bcmul($transaction['amount'], $rate);
$currentBalance = bcadd($currentBalance, $convertedAmount);
$balances[$format] = $currentBalance;
$rate = $converter->getCurrencyRate($currency, $native, $day);
$convertedAmount = bcmul($transaction['amount'], $rate);
$currentBalance = bcadd($currentBalance, $convertedAmount);
$balances[$format] = $currentBalance;
Log::debug(sprintf(
'%s: transaction in %s(!). Conversion rate is %s. %s %s = %s %s',
$format,
$currency->code,
$rate,
$currency->code,
$transaction['amount'],
$native->code,
$convertedAmount
));
'%s: transaction in %s(!). Conversion rate is %s. %s %s = %s %s',
$format,
$currency->code,
$rate,
$currency->code,
$transaction['amount'],
$native->code,
$convertedAmount
));
}
$cache->store($balances);
@@ -388,7 +397,7 @@ class Steam
{
// Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
Log::debug(sprintf('Now in balanceConverted (%s) for account #%d, converting to %s', $date->format('Y-m-d'), $account->id, $native->code));
$cache = new CacheProperties();
$cache = new CacheProperties();
$cache->addProperty($account->id);
$cache->addProperty('balance');
$cache->addProperty($date);
@@ -396,7 +405,7 @@ class Steam
if ($cache->has()) {
Log::debug('Cached!');
return $cache->get();
return $cache->get();
}
/** @var AccountRepositoryInterface $repository */
@@ -409,66 +418,72 @@ class Steam
return $this->balance($account, $date);
}
$new = [];
$existing = [];
$new[] = $account->transactions() // 1
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id)
->whereNull('transactions.foreign_currency_id')
->get(['transaction_journals.date', 'transactions.amount'])->toArray();
$new = [];
$existing = [];
$new[] = $account->transactions() // 1
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id)
->whereNull('transactions.foreign_currency_id')
->get(['transaction_journals.date', 'transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transaction(s) in set #1', count($new[0])));
$existing[] = $account->transactions() // 2
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $native->id)
->whereNull('transactions.foreign_currency_id')
->get(['transactions.amount'])->toArray();
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $native->id)
->whereNull('transactions.foreign_currency_id')
->get(['transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transaction(s) in set #2', count($existing[0])));
$new[] = $account->transactions() // 3
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', '!=', $currency->id)
->where('transactions.transaction_currency_id', '!=', $native->id)
->whereNull('transactions.foreign_currency_id')
->get(['transaction_journals.date', 'transactions.amount'])->toArray();
$new[] = $account->transactions() // 3
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', '!=', $currency->id)
->where('transactions.transaction_currency_id', '!=', $native->id)
->whereNull('transactions.foreign_currency_id')
->get(['transaction_journals.date', 'transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transactions in set #3', count($new[1])));
$existing[] = $account->transactions() // 4
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $native->id)
->whereNotNull('transactions.foreign_amount')
->get(['transactions.foreign_amount'])->toArray();
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $native->id)
->whereNotNull('transactions.foreign_amount')
->get(['transactions.foreign_amount'])->toArray()
;
Log::debug(sprintf('%d transactions in set #4', count($existing[1])));
$new[] = $account->transactions()// 5
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id)
->where('transactions.foreign_currency_id', '!=', $native->id)
->whereNotNull('transactions.foreign_amount')
->get(['transaction_journals.date', 'transactions.amount'])->toArray();
$new[] = $account->transactions()// 5
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', $currency->id)
->where('transactions.foreign_currency_id', '!=', $native->id)
->whereNotNull('transactions.foreign_amount')
->get(['transaction_journals.date', 'transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transactions in set #5', count($new[2])));
$new[] = $account->transactions()// 6
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', '!=', $currency->id)
->where('transactions.foreign_currency_id', '!=', $native->id)
->whereNotNull('transactions.foreign_amount')
->get(['transaction_journals.date', 'transactions.amount'])->toArray();
$new[] = $account->transactions()// 6
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.transaction_currency_id', '!=', $currency->id)
->where('transactions.foreign_currency_id', '!=', $native->id)
->whereNotNull('transactions.foreign_amount')
->get(['transaction_journals.date', 'transactions.amount'])->toArray()
;
Log::debug(sprintf('%d transactions in set #6', count($new[3])));
// process both sets of transactions. Of course, no need to convert set "existing".
$balance = $this->sumTransactions($existing[0], 'amount');
$balance = bcadd($balance, $this->sumTransactions($existing[1], 'foreign_amount'));
$balance = $this->sumTransactions($existing[0], 'amount');
$balance = bcadd($balance, $this->sumTransactions($existing[1], 'foreign_amount'));
Log::debug(sprintf('Balance from set #2 and #4 is %f', $balance));
// need to convert the others. All sets use the "amount" value as their base (that's easy)
// but we need to convert each transaction separately because the date difference may
// incur huge currency changes.
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$start = clone $date;
$end = clone $date;
$converter = new ExchangeRateConverter();
$start = clone $date;
$end = clone $date;
$converter = new ExchangeRateConverter();
foreach ($new as $set) {
foreach ($set as $transaction) {
$currentDate = false;
@@ -491,7 +506,7 @@ class Steam
foreach ($new as $set) {
foreach ($set as $transaction) {
$currentDate = false;
$currentDate = false;
try {
$currentDate = Carbon::parse($transaction['date'], config('app.timezone'));
@@ -508,9 +523,9 @@ class Steam
}
// add virtual balance (also needs conversion)
$virtual = null === $account->virtual_balance ? '0' : $account->virtual_balance;
$virtual = $converter->convert($currency, $native, $account->created_at, $virtual);
$balance = bcadd($balance, $virtual);
$virtual = null === $account->virtual_balance ? '0' : $account->virtual_balance;
$virtual = $converter->convert($currency, $native, $account->created_at, $virtual);
$balance = bcadd($balance, $virtual);
$converter->summarize();
$cache->store($balance);
@@ -526,10 +541,10 @@ class Steam
*/
public function balancesByAccounts(Collection $accounts, Carbon $date): array
{
// Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray();
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray();
// cache this property.
$cache = new CacheProperties();
$cache = new CacheProperties();
$cache->addProperty($ids);
$cache->addProperty('balances');
$cache->addProperty($date);
@@ -557,15 +572,15 @@ class Steam
*/
public function balancesByAccountsConverted(Collection $accounts, Carbon $date): array
{
// Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray();
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray();
// cache this property.
$cache = new CacheProperties();
$cache = new CacheProperties();
$cache->addProperty($ids);
$cache->addProperty('balances-converted');
$cache->addProperty($date);
if ($cache->has()) {
return $cache->get();
return $cache->get();
}
// need to do this per account.
@@ -576,9 +591,9 @@ class Steam
$default = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
$result[$account->id]
= [
'balance' => $this->balance($account, $date),
'native_balance' => $this->balanceConverted($account, $date, $default),
];
'balance' => $this->balance($account, $date),
'native_balance' => $this->balanceConverted($account, $date, $default),
];
}
$cache->store($result);
@@ -591,10 +606,10 @@ class Steam
*/
public function balancesPerCurrencyByAccounts(Collection $accounts, Carbon $date): array
{
// Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray();
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
$ids = $accounts->pluck('id')->toArray();
// cache this property.
$cache = new CacheProperties();
$cache = new CacheProperties();
$cache->addProperty($ids);
$cache->addProperty('balances-per-currency');
$cache->addProperty($date);
@@ -619,7 +634,7 @@ class Steam
{
// Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
// abuse chart properties:
$cache = new CacheProperties();
$cache = new CacheProperties();
$cache->addProperty($account->id);
$cache->addProperty('balance-per-currency');
$cache->addProperty($date);
@@ -627,9 +642,10 @@ class Steam
return $cache->get();
}
$query = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->groupBy('transactions.transaction_currency_id');
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->groupBy('transactions.transaction_currency_id')
;
$balances = $query->get(['transactions.transaction_currency_id', \DB::raw('SUM(transactions.amount) as sum_for_currency')]); // @phpstan-ignore-line
$return = [];
@@ -661,10 +677,10 @@ class Steam
// Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
if (str_contains($number, '.')) {
if ('-' !== $number[0]) {
return bcadd($number, '0.' . str_repeat('0', $precision) . '5', $precision);
return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision);
}
return bcsub($number, '0.' . str_repeat('0', $precision) . '5', $precision);
return bcsub($number, '0.'.str_repeat('0', $precision).'5', $precision);
}
return $number;
@@ -747,15 +763,15 @@ class Steam
{
$list = [];
$set = auth()->user()->transactions()
->whereIn('transactions.account_id', $accounts)
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
->get(['transactions.account_id', \DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
$set = auth()->user()->transactions()
->whereIn('transactions.account_id', $accounts)
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
->get(['transactions.account_id', \DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
;
/** @var Transaction $entry */
foreach ($set as $entry) {
$date = new Carbon($entry->max_date, config('app.timezone'));
$date = new Carbon($entry->max_date, config('app.timezone'));
$date->setTimezone(config('app.timezone'));
$list[$entry->account_id] = $date;
}
@@ -830,9 +846,9 @@ class Steam
public function getSafeUrl(string $unknownUrl, string $safeUrl): string
{
// Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
$returnUrl = $safeUrl;
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
$safeHost = parse_url($safeUrl, PHP_URL_HOST);
$returnUrl = $safeUrl;
$unknownHost = parse_url($unknownUrl, PHP_URL_HOST);
$safeHost = parse_url($safeUrl, PHP_URL_HOST);
if (null !== $unknownHost && $unknownHost === $safeHost) {
$returnUrl = $unknownUrl;
@@ -869,7 +885,7 @@ class Steam
*/
public function floatalize(string $value): string
{
$value = strtoupper($value);
$value = strtoupper($value);
if (!str_contains($value, 'E')) {
return $value;
}

View File

@@ -63,15 +63,16 @@ class General extends AbstractExtension
}
/** @var Carbon $date */
$date = session('end', today(config('app.timezone'))->endOfMonth());
$info = app('steam')->balanceByTransactions($account, $date, null);
$date = session('end', today(config('app.timezone'))->endOfMonth());
$info = app('steam')->balanceByTransactions($account, $date, null);
$strings = [];
foreach($info as $currencyId => $balance) {
$strings[] = app('amount')->formatByCurrencyId($currencyId, $balance, false);
foreach ($info as $currencyId => $balance) {
$strings[] = app('amount')->formatByCurrencyId($currencyId, $balance, false);
}
return implode(', ', $strings);
//return app('steam')->balance($account, $date);
// return app('steam')->balance($account, $date);
}
);
}