mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-09 22:26:04 +00:00
Merge pull request #11024 from ctrl-f5/feat/improve-date-handling
improved balance range date handling
This commit is contained in:
@@ -84,7 +84,7 @@ class AccountController extends Controller
|
|||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
$types = $data['types'];
|
$types = $data['types'];
|
||||||
$query = $data['query'];
|
$query = $data['query'];
|
||||||
$date = $data['date'] ?? today(config('app.timezone'));
|
$date = $data['date'];
|
||||||
$return = [];
|
$return = [];
|
||||||
$timer = Timer::getInstance();
|
$timer = Timer::getInstance();
|
||||||
$timer->start(sprintf('AC accounts "%s"', $query));
|
$timer->start(sprintf('AC accounts "%s"', $query));
|
||||||
|
@@ -589,8 +589,6 @@ class BasicController extends Controller
|
|||||||
|
|
||||||
private function getNetWorthInfo(Carbon $end): array
|
private function getNetWorthInfo(Carbon $end): array
|
||||||
{
|
{
|
||||||
$end->endOfDay();
|
|
||||||
|
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
Log::debug(sprintf('getNetWorthInfo up until "%s".', $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('getNetWorthInfo up until "%s".', $end->format('Y-m-d H:i:s')));
|
||||||
|
@@ -48,10 +48,11 @@ class AutocompleteRequest extends FormRequest
|
|||||||
// remove 'initial balance' from allowed types. its internal
|
// remove 'initial balance' from allowed types. its internal
|
||||||
$array = array_diff($array, [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::RECONCILIATION->value]);
|
$array = array_diff($array, [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::RECONCILIATION->value]);
|
||||||
|
|
||||||
|
$date = $this->getCarbonDate('date') ?? today(config('app.timezone'));
|
||||||
return [
|
return [
|
||||||
'types' => $array,
|
'types' => $array,
|
||||||
'query' => $this->convertString('query'),
|
'query' => $this->convertString('query'),
|
||||||
'date' => $this->getCarbonDate('date'),
|
'date' => $date->endOfDay(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Exceptions\ValidationException;
|
|||||||
use FireflyIII\Support\Request\ChecksLogin;
|
use FireflyIII\Support\Request\ChecksLogin;
|
||||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request class for end points that require date parameters.
|
* Request class for end points that require date parameters.
|
||||||
@@ -55,7 +56,6 @@ class DateRequest extends FormRequest
|
|||||||
// sanity check on dates:
|
// sanity check on dates:
|
||||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||||
|
|
||||||
|
|
||||||
$start->startOfDay();
|
$start->startOfDay();
|
||||||
$end->endOfDay();
|
$end->endOfDay();
|
||||||
if ($start->diffInYears($end, true) > 5) {
|
if ($start->diffInYears($end, true) > 5) {
|
||||||
|
@@ -91,14 +91,12 @@ class IndexController extends Controller
|
|||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
||||||
|
|
||||||
// #10618 go to the end of the previous day.
|
|
||||||
$start->subSecond();
|
|
||||||
|
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
Log::debug(sprintf('inactive start: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('inactive start: accountsBalancesInRange("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('inactive end: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
[
|
||||||
$startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
$startBalances,
|
||||||
$endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
$endBalances,
|
||||||
|
] = Steam::accountsBalancesInRange($start, $end, $accounts, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$activities = Steam::getLastActivities($ids);
|
$activities = Steam::getLastActivities($ids);
|
||||||
|
|
||||||
|
|
||||||
@@ -169,14 +167,12 @@ class IndexController extends Controller
|
|||||||
/** @var Carbon $end */
|
/** @var Carbon $end */
|
||||||
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
||||||
|
|
||||||
// #10618 go to the end of the previous day.
|
|
||||||
$start->subSecond();
|
|
||||||
|
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
Log::debug(sprintf('index start: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('index: accountsBalancesInRange("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('index end: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
[
|
||||||
$startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
$startBalances,
|
||||||
$endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
$endBalances,
|
||||||
|
] = Steam::accountsBalancesInRange($start, $end, $accounts, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$activities = Steam::getLastActivities($ids);
|
$activities = Steam::getLastActivities($ids);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -116,10 +116,11 @@ class AccountController extends Controller
|
|||||||
$accountNames = $this->extractNames($accounts);
|
$accountNames = $this->extractNames($accounts);
|
||||||
|
|
||||||
// grab all balances
|
// grab all balances
|
||||||
Log::debug(sprintf('expenseAccounts: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('expenseAccounts: accountsBalancesInRange("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('expenseAccounts: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
[
|
||||||
$startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
$startBalances,
|
||||||
$endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
$endBalances,
|
||||||
|
] = Steam::accountsBalancesInRange($start, $end, $accounts, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
Log::debug('Done collecting balances');
|
Log::debug('Done collecting balances');
|
||||||
// loop the accounts, then check for balance and currency info.
|
// loop the accounts, then check for balance and currency info.
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
@@ -666,10 +667,11 @@ class AccountController extends Controller
|
|||||||
$accountNames = $this->extractNames($accounts);
|
$accountNames = $this->extractNames($accounts);
|
||||||
|
|
||||||
// grab all balances
|
// grab all balances
|
||||||
Log::debug(sprintf('revAccounts: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('revAccounts: accountsBalancesInRange("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('revAccounts: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
[
|
||||||
$startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
$startBalances,
|
||||||
$endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
$endBalances,
|
||||||
|
] = Steam::accountsBalancesInRange($start, $end, $accounts, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
|
|
||||||
|
|
||||||
// loop the accounts, then check for balance and currency info.
|
// loop the accounts, then check for balance and currency info.
|
||||||
|
@@ -50,10 +50,11 @@ class AccountTasker implements AccountTaskerInterface, UserGroupInterface
|
|||||||
$yesterday = clone $start;
|
$yesterday = clone $start;
|
||||||
$yesterday->subDay()->endOfDay(); // exactly up until $start but NOT including.
|
$yesterday->subDay()->endOfDay(); // exactly up until $start but NOT including.
|
||||||
$end->endOfDay(); // needs to be end of day to be correct.
|
$end->endOfDay(); // needs to be end of day to be correct.
|
||||||
Log::debug(sprintf('getAccountReport: accountsBalancesOptimized("%s")', $yesterday->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('getAccountReport: accountsBalancesInRange("%s", "%s")', $yesterday->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('getAccountReport: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
[
|
||||||
$startSet = Steam::accountsBalancesOptimized($accounts, $yesterday);
|
$startSet,
|
||||||
$endSet = Steam::accountsBalancesOptimized($accounts, $end);
|
$endSet,
|
||||||
|
] = Steam::accountsBalancesInRange($yesterday, $end, $accounts);
|
||||||
Log::debug('Start of accountreport');
|
Log::debug('Start of accountreport');
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
|
@@ -289,8 +289,10 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
{
|
{
|
||||||
$this->balances = Steam::accountsBalancesOptimized($this->collection, $this->getDate(), $this->primaryCurrency, $this->convertToPrimary);
|
$this->balances = Steam::accountsBalancesOptimized($this->collection, $this->getDate(), $this->primaryCurrency, $this->convertToPrimary);
|
||||||
if ($this->start instanceof Carbon && $this->end instanceof Carbon) {
|
if ($this->start instanceof Carbon && $this->end instanceof Carbon) {
|
||||||
$this->startBalances = Steam::accountsBalancesOptimized($this->collection, $this->start, $this->primaryCurrency, $this->convertToPrimary);
|
[
|
||||||
$this->endBalances = Steam::accountsBalancesOptimized($this->collection, $this->end, $this->primaryCurrency, $this->convertToPrimary);
|
$this->startBalances,
|
||||||
|
$this->endBalances,
|
||||||
|
] = Steam::accountsBalancesInRange($this->start, $this->end, $this->collection, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -402,21 +402,21 @@ trait ConvertsDataTypes
|
|||||||
*/
|
*/
|
||||||
protected function getCarbonDate(string $field): ?Carbon
|
protected function getCarbonDate(string $field): ?Carbon
|
||||||
{
|
{
|
||||||
$result = null;
|
$data = (string)$this->get($field);
|
||||||
|
Log::debug(sprintf('Date string is "%s"', $data));
|
||||||
|
|
||||||
Log::debug(sprintf('Date string is "%s"', (string)$this->get($field)));
|
if ('' === $data) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$result = '' !== (string)$this->get($field) ? new Carbon((string)$this->get($field), config('app.timezone')) : null;
|
return new Carbon($data, config('app.timezone'));
|
||||||
} catch (InvalidFormatException) {
|
} catch (InvalidFormatException) {
|
||||||
// @ignoreException
|
// @ignoreException
|
||||||
Log::debug(sprintf('Exception when parsing date "%s".', $this->get($field)));
|
Log::debug(sprintf('Exception when parsing date "%s".', $data));
|
||||||
}
|
|
||||||
if (!$result instanceof Carbon) {
|
|
||||||
Log::debug(sprintf('Exception when parsing date "%s".', $this->get($field)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -49,7 +49,7 @@ use function Safe\preg_replace;
|
|||||||
*/
|
*/
|
||||||
class Steam
|
class Steam
|
||||||
{
|
{
|
||||||
public function accountsBalancesOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
public function accountsBalancesOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null, bool $inclusive = true): array
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('accountsBalancesOptimized: Called for %d account(s) with date/time "%s"', $accounts->count(), $date->toIso8601String()));
|
Log::debug(sprintf('accountsBalancesOptimized: Called for %d account(s) with date/time "%s"', $accounts->count(), $date->toIso8601String()));
|
||||||
$result = [];
|
$result = [];
|
||||||
@@ -61,7 +61,7 @@ class Steam
|
|||||||
$arrayOfSums = Transaction::whereIn('account_id', $accounts->pluck('id')->toArray())
|
$arrayOfSums = Transaction::whereIn('account_id', $accounts->pluck('id')->toArray())
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
->where('transaction_journals.date', $inclusive ? '<=': '<', $date->format('Y-m-d H:i:s'))
|
||||||
->groupBy(['transactions.account_id', 'transaction_currencies.code'])
|
->groupBy(['transactions.account_id', 'transaction_currencies.code'])
|
||||||
->get(['transactions.account_id', 'transaction_currencies.code', DB::raw('SUM(transactions.amount) as sum_of_amount')])->toArray()
|
->get(['transactions.account_id', 'transaction_currencies.code', DB::raw('SUM(transactions.amount) as sum_of_amount')])->toArray()
|
||||||
;
|
;
|
||||||
@@ -125,6 +125,14 @@ class Steam
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function accountsBalancesInRange(Carbon $start, Carbon $end, Collection $accounts, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
$this->accountsBalancesOptimized($accounts, $start, $primary, $convertToPrimary, inclusive: false),
|
||||||
|
$this->accountsBalancesOptimized($accounts, $end, $primary, $convertToPrimary),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://stackoverflow.com/questions/1642614/how-to-ceil-floor-and-round-bcmath-numbers
|
* https://stackoverflow.com/questions/1642614/how-to-ceil-floor-and-round-bcmath-numbers
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user