diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php
index 696145827b..1a5895b2a3 100644
--- a/app/Http/Controllers/CategoryController.php
+++ b/app/Http/Controllers/CategoryController.php
@@ -162,7 +162,6 @@ class CategoryController extends Controller
// list of ranges for list of periods:
// oldest transaction in category:
- //$start = $repository->getFirstActivityDate($category);
$start = $repository->firstUseDate($category, new Collection);
$range = Preferences::get('viewRange', '1M')->data;
$start = Navigation::startOfPeriod($start, $range);
diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php
index 162ca52394..ce5132628b 100644
--- a/app/Http/Controllers/Chart/BudgetController.php
+++ b/app/Http/Controllers/Chart/BudgetController.php
@@ -150,7 +150,7 @@ class BudgetController extends Controller
$cache->addProperty('budget');
$cache->addProperty('all');
if ($cache->has()) {
- return Response::json($cache->get());
+ //return Response::json($cache->get());
}
$budgets = $repository->getActiveBudgets();
$repetitions = $repository->getAllBudgetLimitRepetitions($start, $end);
@@ -203,6 +203,8 @@ class BudgetController extends Controller
$data = $this->generator->frontpage($allEntries);
$cache->store($data);
+ return ' ' . json_encode($data);
+
return Response::json($data);
}
diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php
index 15bd8c0405..5e432520fe 100644
--- a/app/Http/Controllers/Chart/CategoryController.php
+++ b/app/Http/Controllers/Chart/CategoryController.php
@@ -9,7 +9,6 @@ use FireflyIII\Generator\Chart\Category\CategoryChartGeneratorInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
-use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Log;
@@ -148,10 +147,10 @@ class CategoryController extends Controller
}
/**
- * @param Carbon $start
- * @param Carbon $end
- * @param Collection $accounts
- * @param Collection $categories
+ * @param Carbon $start
+ * @param Carbon $end
+ * @param Collection $accounts
+ * @param Collection $categories
*
* @return \Illuminate\Http\JsonResponse
*/
@@ -241,8 +240,8 @@ class CategoryController extends Controller
// return Response::json($cache->get());
}
- /** @var CategoryRepositoryInterface $repository */
- $repository = app(CategoryRepositoryInterface::class);
+ /** @var CRI $repository */
+ $repository = app(CRI::class);
$categoryCollection = new Collection([$category]);
// loop over period, add by users range:
$current = clone $start;
diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php
index 9e17c3c244..1d7997e4ba 100644
--- a/app/Repositories/Budget/BudgetRepository.php
+++ b/app/Repositories/Budget/BudgetRepository.php
@@ -15,7 +15,6 @@ use FireflyIII\User;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
-use Log;
/**
* Class BudgetRepository
@@ -78,7 +77,7 @@ class BudgetRepository implements BudgetRepositoryInterface
{
$oldest = Carbon::create()->startOfYear();
$journal = $budget->transactionjournals()->orderBy('date', 'ASC')->first();
- if ($journal) {
+ if (!is_null($journal)) {
$oldest = $journal->date < $oldest ? $journal->date : $oldest;
}
@@ -86,8 +85,9 @@ class BudgetRepository implements BudgetRepositoryInterface
->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.id')
->orderBy('transaction_journals.date', 'ASC')->first(['transactions.*', 'transaction_journals.date']);
- if ($transaction) {
- $oldest = $transaction->date < $oldest ? $transaction->date : $oldest;
+ if (!is_null($transaction)) {
+ $carbon = new Carbon($transaction->date);
+ $oldest = $carbon < $oldest ? $carbon : $oldest;
}
return $oldest;
@@ -187,8 +187,8 @@ class BudgetRepository implements BudgetRepositoryInterface
// first get all journals for all budget(s):
$journalQuery = $this->user->transactionjournals()
->expanded()
- ->before($end)
->sortCorrectly()
+ ->before($end)
->after($start)
->leftJoin(
'transactions as source',
@@ -204,6 +204,7 @@ class BudgetRepository implements BudgetRepositoryInterface
}
// get them:
$journals = $journalQuery->get(TransactionJournal::queryFields());
+
//Log::debug('journalsInPeriod journal count is ' . $journals->count());
// then get transactions themselves.
@@ -302,15 +303,80 @@ class BudgetRepository implements BudgetRepositoryInterface
*/
public function spentInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) : string
{
- $set = $this->journalsInPeriod($budgets, $accounts, $start, $end);
- //Log::debug('spentInPeriod set count is ' . $set->count());
- $sum = '0';
- /** @var TransactionJournal $journal */
- foreach ($set as $journal) {
- $sum = bcadd($sum, TransactionJournal::amount($journal));
+ // first collect actual transaction journals (fairly easy)
+ $query = $this->user
+ ->transactionjournals()
+ ->distinct()
+ ->leftJoin(
+ 'transactions as t', function (JoinClause $join) {
+ $join->on('t.transaction_journal_id', '=', 'transaction_journals.id')->where('amount', '<', 0);
+ }
+ );
+
+ if ($end >= $start) {
+ $query->before($end)->after($start);
+ }
+ if ($accounts->count() > 0) {
+ $accountIds = $accounts->pluck('id')->toArray();
+ $query->whereIn('t.account_id', $accountIds);
+ }
+ if ($budgets->count() > 0) {
+ $budgetIds = $budgets->pluck('id')->toArray();
+ $query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
+ $query->whereIn('budget_transaction_journal.budget_id', $budgetIds);
}
- Log::debug('spentInPeriod between ' . $start->format('Y-m-d') . ' and ' . $end->format('Y-m-d') . ' is ' . $sum);
+ // that should do it:
+ $first = strval($query->sum('t.amount'));
+
+ // then collection transactions (harder)
+ $query = $this->user->transactions()
+ ->where('transactions.amount', '<', 0)
+ ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
+ ->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'));
+ if ($accounts->count() > 0) {
+ $accountIds = $accounts->pluck('id')->toArray();
+ $query->whereIn('transactions.account_id', $accountIds);
+ }
+ if ($budgets->count() > 0) {
+ $budgetIds = $budgets->pluck('id')->toArray();
+ $query->leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id');
+ $query->whereIn('budget_transaction.budget_id', $budgetIds);
+ }
+ $second = strval($query->sum('transactions.amount'));
+
+ return bcadd($first, $second);
+ }
+
+ /**
+ * @param Collection $accounts
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return string
+ */
+ public function spentInPeriodWithoutBudget(Collection $accounts, Carbon $start, Carbon $end): string
+ {
+ $query = $this->user->transactionjournals()
+ ->distinct()
+ ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
+ ->leftJoin(
+ 'transactions as t', function (JoinClause $join) {
+ $join->on('t.transaction_journal_id', '=', 'transaction_journals.id')->where('amount', '<', 0);
+ }
+ )
+ ->leftJoin('budget_transaction', 't.id', '=', 'budget_transaction.transaction_id')
+ ->whereNull('budget_transaction_journal.id')
+ ->whereNull('budget_transaction.id')
+ ->before($end)
+ ->after($start);
+
+ if ($accounts->count() > 0) {
+ $accountIds = $accounts->pluck('id')->toArray();
+
+ $query->whereIn('t.account_id', $accountIds);
+ }
+ $sum = strval($query->sum('t.amount'));
return $sum;
}
@@ -402,25 +468,4 @@ class BudgetRepository implements BudgetRepositoryInterface
return $limit;
}
- /**
- * @param Collection $accounts
- * @param Carbon $start
- * @param Carbon $end
- *
- * @return string
- */
- public function spentInPeriodWithoutBudget(Collection $accounts, Carbon $start, Carbon $end): string
- {
- $set = $this->journalsInPeriodWithoutBudget($accounts, $start, $end);
- //Log::debug('spentInPeriod set count is ' . $set->count());
- $sum = '0';
- /** @var TransactionJournal $journal */
- foreach ($set as $journal) {
- $sum = bcadd($sum, TransactionJournal::amount($journal));
- }
-
- Log::debug('spentInPeriodWithoutBudget between ' . $start->format('Y-m-d') . ' and ' . $end->format('Y-m-d') . ' is ' . $sum);
-
- return $sum;
- }
}
diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php
index 7c1eff2d91..c02a8ad1a1 100644
--- a/app/Repositories/Category/CategoryRepository.php
+++ b/app/Repositories/Category/CategoryRepository.php
@@ -8,8 +8,10 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\User;
+use Illuminate\Database\Query\JoinClause;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
+use Log;
/**
* Class CategoryRepository
@@ -53,12 +55,24 @@ class CategoryRepository implements CategoryRepositoryInterface
*/
public function earnedInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string
{
- $types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
- $journals = $this->journalsInPeriod($categories, $accounts, $types, $start, $end);
- $sum = '0';
- foreach ($journals as $journal) {
- $sum = bcadd(TransactionJournal::amount($journal), $sum);
- }
+ $types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
+ $sum = bcmul($this->sumInPeriod($categories, $accounts, $types, $start, $end), '-1');
+
+ return $sum;
+
+ }
+
+ /**
+ * @param Collection $accounts
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return string
+ */
+ public function earnedInPeriodWithoutCategory(Collection $accounts, Carbon $start, Carbon $end) :string
+ {
+ $types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
+ $sum = $this->sumInPeriodWithoutCategory($accounts, $types, $start, $end);
return $sum;
}
@@ -80,7 +94,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return $category;
}
-
/**
* @param Category $category
* @param Collection $accounts
@@ -118,10 +131,13 @@ class CategoryRepository implements CategoryRepositoryInterface
$firstTransactionQuery->whereIn('transactions.account_id', $ids);
}
- $firstTransaction = $firstJournalQuery->first(['transaction_journals.*']);
+ $firstTransaction = $firstTransactionQuery->first(['transaction_journals.*']);
- if (!is_null($firstTransaction) && !is_null($first) && $firstTransaction->date < $first) {
- $first = $firstTransaction->date;
+ if (!is_null($firstTransaction) && ((!is_null($first) && $firstTransaction->date < $first) || is_null($first))) {
+ $first = new Carbon($firstTransaction->date);
+ }
+ if (is_null($first)) {
+ return new Carbon('1900-01-01');
}
return $first;
@@ -162,25 +178,30 @@ class CategoryRepository implements CategoryRepositoryInterface
$first = $query->get(TransactionJournal::queryFields());
// then collection transactions (harder)
- $query = $this->user->transactions();
- $query->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id');
- $query->where('category_transaction.category_id', $category->id);
+ $query = $this->user->transactionjournals()->distinct()
+ ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
+ ->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id')
+ ->where('category_transaction.category_id', $category->id);
$second = $query->get(['transaction_journals.*']);
-
$complete = $complete->merge($first);
$complete = $complete->merge($second);
// sort:
+ /** @var Collection $complete */
$complete = $complete->sortByDesc(
- function (TransactionJournal $journal) {
- return $journal->date->format('Ymd');
+ function ($model) {
+ $date = new Carbon($model->date);
+
+ return intval($date->format('U'));
}
);
-
// create paginator
- $offset = ($page - 1) * $pageSize;
- $subSet = $complete->slice($offset, $pageSize);
+ $offset = ($page - 1) * $pageSize;
+ Log::debug('Page is ' . $page);
+ Log::debug('Offset is ' . $offset);
+ Log::debug('pagesize is ' . $pageSize);
+ $subSet = $complete->slice($offset, $pageSize)->all();
$paginator = new LengthAwarePaginator($subSet, $complete->count(), $pageSize, $page);
return $paginator;
@@ -322,6 +343,7 @@ class CategoryRepository implements CategoryRepositoryInterface
/** @var TransactionJournal $first */
$lastJournalQuery = $category->transactionjournals()->orderBy('date', 'DESC');
+ Log::debug('lastUseDate ' . $category->name . ' (' . $category->id . ')');
if ($accounts->count() > 0) {
// filter journals:
@@ -334,6 +356,7 @@ class CategoryRepository implements CategoryRepositoryInterface
if ($lastJournal) {
$last = $lastJournal->date;
+ Log::debug('last is now ' . $last);
}
// check transactions:
@@ -347,10 +370,15 @@ class CategoryRepository implements CategoryRepositoryInterface
$lastTransactionQuery->whereIn('transactions.account_id', $ids);
}
- $lastTransaction = $lastJournalQuery->first(['transaction_journals.*']);
+ $lastTransaction = $lastTransactionQuery->first(['transaction_journals.*']);
+ if (!is_null($lastTransaction)) {
+ }
+ if (!is_null($lastTransaction) && ((!is_null($last) && $lastTransaction->date < $last) || is_null($last))) {
+ $last = new Carbon($lastTransaction->date);
+ }
- if (!is_null($lastTransaction) && !is_null($last) && $lastTransaction->date < $last) {
- $last = $lastTransaction->date;
+ if (is_null($last)) {
+ return new Carbon('1900-01-01');
}
return $last;
@@ -366,12 +394,8 @@ class CategoryRepository implements CategoryRepositoryInterface
*/
public function spentInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string
{
- $types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
- $journals = $this->journalsInPeriod($categories, $accounts, $types, $start, $end);
- $sum = '0';
- foreach ($journals as $journal) {
- $sum = bcadd(TransactionJournal::amount($journal), $sum);
- }
+ $types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
+ $sum = $this->sumInPeriod($categories, $accounts, $types, $start, $end);
return $sum;
}
@@ -385,12 +409,8 @@ class CategoryRepository implements CategoryRepositoryInterface
*/
public function spentInPeriodWithoutCategory(Collection $accounts, Carbon $start, Carbon $end) : string
{
- $types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
- $journals = $this->journalsInPeriodWithoutCategory($accounts, $types, $start, $end);
- $sum = '0';
- foreach ($journals as $journal) {
- $sum = bcadd(TransactionJournal::amount($journal), $sum);
- }
+ $types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
+ $sum = $this->sumInPeriodWithoutCategory($accounts, $types, $start, $end);
return $sum;
}
@@ -429,21 +449,100 @@ class CategoryRepository implements CategoryRepositoryInterface
}
/**
+ * @param Collection $categories
* @param Collection $accounts
+ * @param array $types
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
- public function earnedInPeriodWithoutCategory(Collection $accounts, Carbon $start, Carbon $end) :string
+ private function sumInPeriod(Collection $categories, Collection $accounts, array $types, Carbon $start, Carbon $end): string
{
- $types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
- $journals = $this->journalsInPeriodWithoutCategory($accounts, $types, $start, $end);
- $sum = '0';
- foreach ($journals as $journal) {
- $sum = bcadd(TransactionJournal::amount($journal), $sum);
+ // first collect actual transaction journals (fairly easy)
+ $query = $this->user
+ ->transactionjournals()
+ ->distinct()
+ ->transactionTypes($types)
+ ->leftJoin(
+ 'transactions as t', function (JoinClause $join) {
+ $join->on('t.transaction_journal_id', '=', 'transaction_journals.id')->where('amount', '<', 0);
+ }
+ );
+
+ if ($end >= $start) {
+ $query->before($end)->after($start);
+ }
+ if ($accounts->count() > 0) {
+ $accountIds = $accounts->pluck('id')->toArray();
+ $query->whereIn('t.account_id', $accountIds);
+ }
+ if ($categories->count() > 0) {
+ $categoryIds = $categories->pluck('id')->toArray();
+ $query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
+ $query->whereIn('category_transaction_journal.category_id', $categoryIds);
}
+ // that should do it:
+ $first = strval($query->sum('t.amount'));
+
+ // then collection transactions (harder)
+ $query = $this->user->transactions()
+ ->where('transactions.amount', '<', 0)
+ ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
+ ->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'));
+ if (count($types) > 0) {
+ $query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
+ $query->whereIn('transaction_types.type', $types);
+ }
+ if ($accounts->count() > 0) {
+ $accountIds = $accounts->pluck('id')->toArray();
+ $query->whereIn('transactions.account_id', $accountIds);
+ }
+ if ($categories->count() > 0) {
+ $categoryIds = $categories->pluck('id')->toArray();
+ $query->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id');
+ $query->whereIn('category_transaction.category_id', $categoryIds);
+ }
+ $second = strval($query->sum('transactions.amount'));
+
+ return bcadd($first, $second);
+
+ }
+
+ /**
+ * @param Collection $accounts
+ * @param array $types
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return string
+ */
+ private function sumInPeriodWithoutCategory(Collection $accounts, array $types, Carbon $start, Carbon $end): string
+ {
+ $query = $this->user->transactionjournals()
+ ->distinct()
+ ->transactionTypes($types)
+ ->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
+ ->leftJoin(
+ 'transactions as t', function (JoinClause $join) {
+ $join->on('t.transaction_journal_id', '=', 'transaction_journals.id')->where('amount', '<', 0);
+ }
+ )
+ ->leftJoin('category_transaction', 't.id', '=', 'category_transaction.transaction_id')
+ ->whereNull('category_transaction_journal.id')
+ ->whereNull('category_transaction.id')
+ ->before($end)
+ ->after($start);
+
+ if ($accounts->count() > 0) {
+ $accountIds = $accounts->pluck('id')->toArray();
+
+ $query->whereIn('t.account_id', $accountIds);
+ }
+ $sum = strval($query->sum('t.amount'));
+
return $sum;
+
}
}
diff --git a/app/Support/Twig/Journal.php b/app/Support/Twig/Journal.php
index 18fd9ab2bc..ff505f0e12 100644
--- a/app/Support/Twig/Journal.php
+++ b/app/Support/Twig/Journal.php
@@ -43,6 +43,7 @@ class Journal extends Twig_Extension
}
$array[] = '' . e($entry->name) . '';
}
+ $array = array_unique($array);
$result = join(', ', $array);
$cache->store($result);
@@ -111,6 +112,7 @@ class Journal extends Twig_Extension
}
$array[] = '' . e($entry->name) . '';
}
+ $array = array_unique($array);
$result = join(', ', $array);
$cache->store($result);