Fixes for transactions.

This commit is contained in:
James Cole 2016-05-11 17:17:43 +02:00
parent 529bf50c85
commit 037d84b810
6 changed files with 228 additions and 82 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
@ -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;

View File

@ -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;
}
}

View File

@ -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
@ -54,12 +56,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);
$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);
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;
@ -367,11 +395,7 @@ 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);
}
$sum = $this->sumInPeriod($categories, $accounts, $types, $start, $end);
return $sum;
}
@ -386,11 +410,7 @@ 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);
}
$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;
}
}

View File

@ -43,6 +43,7 @@ class Journal extends Twig_Extension
}
$array[] = '<a title="' . e($entry->name) . '" href="' . route('accounts.show', $entry->id) . '">' . e($entry->name) . '</a>';
}
$array = array_unique($array);
$result = join(', ', $array);
$cache->store($result);
@ -111,6 +112,7 @@ class Journal extends Twig_Extension
}
$array[] = '<a title="' . e($entry->name) . '" href="' . route('accounts.show', $entry->id) . '">' . e($entry->name) . '</a>';
}
$array = array_unique($array);
$result = join(', ', $array);
$cache->store($result);