mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-10 23:45:48 -06:00
Another chart optimised
This commit is contained in:
parent
0fd0d7d080
commit
35154dc7a3
@ -304,8 +304,7 @@ class CategoryController extends Controller
|
||||
*/
|
||||
public function earnedInPeriod(CategoryRepositoryInterface $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
$original = clone $start;
|
||||
$cache = new CacheProperties; // chart properties for cache:
|
||||
$cache = new CacheProperties; // chart properties for cache:
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($reportType);
|
||||
@ -315,78 +314,42 @@ class CategoryController extends Controller
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$categories = new Collection;
|
||||
$sets = new Collection;
|
||||
$entries = new Collection;
|
||||
|
||||
// run a very special query each month:
|
||||
$start = clone $original;
|
||||
while ($start < $end) {
|
||||
$currentEnd = clone $start;
|
||||
$currentStart = clone $start;
|
||||
$currentStart->startOfMonth();
|
||||
$currentEnd->endOfMonth();
|
||||
// get a list of categories, and what the user has earned for that category
|
||||
// (if the user has earned anything)
|
||||
$set = $repository->earnedForAccounts($accounts, $currentStart, $currentEnd);
|
||||
$categories = $categories->merge($set);
|
||||
// save the set combined with the data that is in it:
|
||||
// for example:
|
||||
// december 2015, salary:1000, bonus:200
|
||||
$sets->push([$currentStart, $set]);
|
||||
$start->addMonth();
|
||||
}
|
||||
// filter categories into a single bunch. Useful later on.
|
||||
// $categories contains all the categories the user has earned money
|
||||
// in in this period.
|
||||
$categories = $categories->unique('id');
|
||||
$categories = $categories->sortBy(
|
||||
$set = $repository->earnedForAccountsPerMonth($accounts, $start, $end);
|
||||
$categories = $set->unique('id')->sortBy(
|
||||
function (Category $category) {
|
||||
return $category->name;
|
||||
}
|
||||
);
|
||||
$entries = new Collection;
|
||||
|
||||
// start looping the time again, this time processing the
|
||||
// data for each month.
|
||||
$start = clone $original;
|
||||
while ($start < $end) {
|
||||
$currentEnd = clone $start;
|
||||
$currentStart = clone $start;
|
||||
$currentStart->startOfMonth();
|
||||
$currentEnd->endOfMonth();
|
||||
|
||||
// in $sets we have saved all the sets of data for each month
|
||||
// so now we need to retrieve the corrent one.
|
||||
// match is on date of course.
|
||||
$currentSet = $sets->first(
|
||||
function ($key, $value) use ($currentStart) {
|
||||
// set for this date.
|
||||
return ($value[0] == $currentStart);
|
||||
while ($start < $end) { // filter the set:
|
||||
$row = [clone $start];
|
||||
// get possibly relevant entries from the big $set
|
||||
$currentSet = $set->filter(
|
||||
function (Category $category) use ($start) {
|
||||
return $category->dateFormatted == $start->format("Y-m");
|
||||
}
|
||||
);
|
||||
// create a row used later on.
|
||||
$row = [clone $currentStart];
|
||||
|
||||
// loop all categories:
|
||||
// check for each category if its in the current set.
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
// if entry is not null, we've earned money in this period for this category.
|
||||
$entry = $currentSet[1]->first(
|
||||
function ($key, $value) use ($category) {
|
||||
return $value->id == $category->id;
|
||||
// if its in there, use the value.
|
||||
$entry = $currentSet->filter(
|
||||
function (Category $cat) use ($category) {
|
||||
return ($cat->id == $category->id);
|
||||
}
|
||||
);
|
||||
// save amount
|
||||
)->first();
|
||||
if (!is_null($entry)) {
|
||||
$row[] = $entry->earned;
|
||||
$row[] = round($entry->earned, 2);
|
||||
} else {
|
||||
$row[] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$entries->push($row);
|
||||
$start->addMonth();
|
||||
}
|
||||
|
||||
$data = $this->generator->earnedInPeriod($categories, $entries);
|
||||
$cache->store($data);
|
||||
|
||||
@ -408,8 +371,7 @@ class CategoryController extends Controller
|
||||
*/
|
||||
public function spentInPeriod(CategoryRepositoryInterface $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
$original = clone $start;
|
||||
$cache = new CacheProperties; // chart properties for cache:
|
||||
$cache = new CacheProperties; // chart properties for cache:
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($reportType);
|
||||
@ -419,66 +381,46 @@ class CategoryController extends Controller
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$categories = new Collection;
|
||||
$sets = new Collection;
|
||||
$entries = new Collection;
|
||||
|
||||
// run a very special query each month:
|
||||
$start = clone $original;
|
||||
while ($start < $end) {
|
||||
$currentEnd = clone $start;
|
||||
$currentStart = clone $start;
|
||||
$currentStart->startOfMonth();
|
||||
$currentEnd->endOfMonth();
|
||||
$set = $repository->spentForAccounts($accounts, $currentStart, $currentEnd);
|
||||
$categories = $categories->merge($set);
|
||||
$sets->push([$currentStart, $set]);
|
||||
$start->addMonth();
|
||||
}
|
||||
$categories = $categories->unique('id');
|
||||
$categories = $categories->sortBy(
|
||||
$set = $repository->spentForAccountsPerMonth($accounts, $start, $end);
|
||||
$categories = $set->unique('id')->sortBy(
|
||||
function (Category $category) {
|
||||
return $category->name;
|
||||
}
|
||||
);
|
||||
$entries = new Collection;
|
||||
|
||||
$start = clone $original;
|
||||
while ($start < $end) {
|
||||
$currentEnd = clone $start;
|
||||
$currentStart = clone $start;
|
||||
$currentStart->startOfMonth();
|
||||
$currentEnd->endOfMonth();
|
||||
$currentSet = $sets->first(
|
||||
function ($key, $value) use ($currentStart) {
|
||||
// set for this date.
|
||||
return ($value[0] == $currentStart);
|
||||
while ($start < $end) { // filter the set:
|
||||
$row = [clone $start];
|
||||
// get possibly relevant entries from the big $set
|
||||
$currentSet = $set->filter(
|
||||
function (Category $category) use ($start) {
|
||||
return $category->dateFormatted == $start->format("Y-m");
|
||||
}
|
||||
);
|
||||
$row = [clone $currentStart];
|
||||
|
||||
// check for each category if its in the current set.
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
/** @var Category $entry */
|
||||
$entry = $currentSet[1]->first(
|
||||
function ($key, $value) use ($category) {
|
||||
return $value->id == $category->id;
|
||||
// if its in there, use the value.
|
||||
$entry = $currentSet->filter(
|
||||
function (Category $cat) use ($category) {
|
||||
return ($cat->id == $category->id);
|
||||
}
|
||||
);
|
||||
)->first();
|
||||
if (!is_null($entry)) {
|
||||
$row[] = $entry->spent;
|
||||
$row[] = round(($entry->spent * -1), 2);
|
||||
} else {
|
||||
$row[] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$entries->push($row);
|
||||
$start->addMonth();
|
||||
}
|
||||
|
||||
$data = $this->generator->spentInPeriod($categories, $entries);
|
||||
$cache->store($data);
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -531,6 +531,61 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of Categories appended with the amount of money that has been earned
|
||||
* in these categories, based on the $accounts involved, in period X, grouped per month.
|
||||
* The amount earned in category X in period X is saved in field "earned".
|
||||
*
|
||||
* @param $accounts
|
||||
* @param $start
|
||||
* @param $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function earnedForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$accountIds = [];
|
||||
foreach ($accounts as $account) {
|
||||
$accountIds[] = $account->id;
|
||||
}
|
||||
|
||||
|
||||
$collection = Auth::user()->categories()
|
||||
->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id')
|
||||
->leftJoin('transaction_journals', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin(
|
||||
'transactions AS t_src', function (JoinClause $join) {
|
||||
$join->on('t_src.transaction_journal_id', '=', 'transaction_journals.id')->where('t_src.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions AS t_dest', function (JoinClause $join) {
|
||||
$join->on('t_dest.transaction_journal_id', '=', 'transaction_journals.id')->where('t_dest.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->whereIn('t_dest.account_id', $accountIds)// to these accounts (earned)
|
||||
->whereNotIn('t_src.account_id', $accountIds)//-- but not from these accounts
|
||||
->whereIn(
|
||||
'transaction_types.type', [TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]
|
||||
)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->groupBy('categories.id')
|
||||
->groupBy('dateFormatted')
|
||||
->get(
|
||||
[
|
||||
'categories.*',
|
||||
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") as `dateFormatted`'),
|
||||
DB::Raw('SUM(`t_dest`.`amount`) AS `earned`')
|
||||
]
|
||||
);
|
||||
|
||||
return $collection;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of Categories appended with the amount of money that has been earned
|
||||
* in these categories, based on the $accounts involved, in period X.
|
||||
@ -568,7 +623,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
->whereNotIn('t_src.account_id', $accountIds)//-- but not from these accounts
|
||||
->whereIn(
|
||||
'transaction_types.type', [TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]
|
||||
)// earned from these things.
|
||||
)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->groupBy('categories.id')
|
||||
@ -624,4 +679,58 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of Categories appended with the amount of money that has been spent
|
||||
* in these categories, based on the $accounts involved, in period X, grouped per month.
|
||||
* The amount earned in category X in period X is saved in field "spent".
|
||||
*
|
||||
* @param $accounts
|
||||
* @param $start
|
||||
* @param $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function spentForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$accountIds = [];
|
||||
foreach ($accounts as $account) {
|
||||
$accountIds[] = $account->id;
|
||||
}
|
||||
|
||||
|
||||
$collection = Auth::user()->categories()
|
||||
->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id')
|
||||
->leftJoin('transaction_journals', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin(
|
||||
'transactions AS t_src', function (JoinClause $join) {
|
||||
$join->on('t_src.transaction_journal_id', '=', 'transaction_journals.id')->where('t_src.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions AS t_dest', function (JoinClause $join) {
|
||||
$join->on('t_dest.transaction_journal_id', '=', 'transaction_journals.id')->where('t_dest.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->whereIn('t_src.account_id', $accountIds)// from these accounts (spent)
|
||||
->whereNotIn('t_dest.account_id', $accountIds)//-- but not from these accounts (spent internally)
|
||||
->whereIn(
|
||||
'transaction_types.type', [TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]
|
||||
)// spent on these things.
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->groupBy('categories.id')
|
||||
->groupBy('dateFormatted')
|
||||
->get(
|
||||
[
|
||||
'categories.*',
|
||||
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") as `dateFormatted`'),
|
||||
DB::Raw('SUM(`t_src`.`amount`) AS `spent`')
|
||||
]
|
||||
);
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,6 +63,32 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function spentForAccounts(Collection $accounts, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Returns a collection of Categories appended with the amount of money that has been spent
|
||||
* in these categories, based on the $accounts involved, in period X, grouped per month.
|
||||
* The amount earned in category X in period X is saved in field "spent".
|
||||
*
|
||||
* @param $accounts
|
||||
* @param $start
|
||||
* @param $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function spentForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Returns a collection of Categories appended with the amount of money that has been earned
|
||||
* in these categories, based on the $accounts involved, in period X, grouped per month.
|
||||
* The amount earned in category X in period X is saved in field "earned".
|
||||
*
|
||||
* @param $accounts
|
||||
* @param $start
|
||||
* @param $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function earnedForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user