mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-11-26 02:40:43 -06:00
Fixes for transactions.
This commit is contained in:
parent
529bf50c85
commit
037d84b810
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user