mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-02 02:18:20 +00:00
These budget charts are the worst, I'm telling you.
This commit is contained in:
@@ -124,8 +124,8 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
|||||||
$set = new Collection;
|
$set = new Collection;
|
||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
$expenses = $repository->getExpensesPerDay($budget, $start, $end, $accounts);
|
$expenses = $repository->spentPerDay($budget, $start, $end, $accounts);
|
||||||
$total = strval($expenses->sum('dailyAmount'));
|
$total = strval(array_sum($expenses));
|
||||||
if (bccomp($total, '0') === -1) {
|
if (bccomp($total, '0') === -1) {
|
||||||
$set->push($budget);
|
$set->push($budget);
|
||||||
}
|
}
|
||||||
|
@@ -264,7 +264,7 @@ class BudgetController extends Controller
|
|||||||
$set = $budget->limitrepetitions()->orderBy('startdate', 'DESC')->get();
|
$set = $budget->limitrepetitions()->orderBy('startdate', 'DESC')->get();
|
||||||
$subTitle = e($budget->name);
|
$subTitle = e($budget->name);
|
||||||
$journals->setPath('/budgets/show/' . $budget->id);
|
$journals->setPath('/budgets/show/' . $budget->id);
|
||||||
$spentArray = $repository->spentPerDay($budget, $start, $end);
|
$spentArray = $repository->spentPerDay($budget, $start, $end, new Collection);
|
||||||
$limits = new Collection();
|
$limits = new Collection();
|
||||||
|
|
||||||
/** @var LimitRepetition $entry */
|
/** @var LimitRepetition $entry */
|
||||||
@@ -298,7 +298,7 @@ class BudgetController extends Controller
|
|||||||
$set = new Collection([$repetition]);
|
$set = new Collection([$repetition]);
|
||||||
$subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]);
|
$subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]);
|
||||||
$journals->setPath('/budgets/show/' . $budget->id . '/' . $repetition->id);
|
$journals->setPath('/budgets/show/' . $budget->id . '/' . $repetition->id);
|
||||||
$spentArray = $repository->spentPerDay($budget, $start, $end);
|
$spentArray = $repository->spentPerDay($budget, $start, $end, new Collection);
|
||||||
$limits = new Collection();
|
$limits = new Collection();
|
||||||
|
|
||||||
/** @var LimitRepetition $entry */
|
/** @var LimitRepetition $entry */
|
||||||
|
@@ -13,7 +13,7 @@ use Illuminate\Support\Collection;
|
|||||||
use Preferences;
|
use Preferences;
|
||||||
use Response;
|
use Response;
|
||||||
|
|
||||||
/**
|
/** checked
|
||||||
* Class AccountController
|
* Class AccountController
|
||||||
*
|
*
|
||||||
* @package FireflyIII\Http\Controllers\Chart
|
* @package FireflyIII\Http\Controllers\Chart
|
||||||
|
@@ -24,7 +24,7 @@ class BillController extends Controller
|
|||||||
protected $generator;
|
protected $generator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* checked
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@@ -39,6 +39,8 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* checked
|
||||||
|
*
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @param BudgetRepositoryInterface $repository
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
@@ -59,7 +61,7 @@ class BudgetController extends Controller
|
|||||||
$cache->addProperty('budget');
|
$cache->addProperty('budget');
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
|
|
||||||
return Response::json($cache->get());
|
//return Response::json($cache->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
$final = clone $last;
|
$final = clone $last;
|
||||||
@@ -67,7 +69,7 @@ class BudgetController extends Controller
|
|||||||
$last = Navigation::endOfX($last, $range, $final);
|
$last = Navigation::endOfX($last, $range, $final);
|
||||||
$entries = new Collection;
|
$entries = new Collection;
|
||||||
// get all expenses:
|
// get all expenses:
|
||||||
$spentArray = $repository->spentPerDay($budget, $first, $last);
|
$spentArray = $repository->spentPerDay($budget, $first, $last, new Collection);
|
||||||
|
|
||||||
while ($first < $last) {
|
while ($first < $last) {
|
||||||
|
|
||||||
@@ -113,19 +115,14 @@ class BudgetController extends Controller
|
|||||||
return Response::json($cache->get());
|
return Response::json($cache->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
$set = $repository->getExpensesPerDay($budget, $start, $end);
|
$set = $repository->spentPerDay($budget, $start, $end, new Collection);
|
||||||
$entries = new Collection;
|
$entries = new Collection;
|
||||||
$amount = $repetition->amount;
|
$amount = $repetition->amount;
|
||||||
|
|
||||||
// get sum (har har)!
|
// get sum (har har)!
|
||||||
while ($start <= $end) {
|
while ($start <= $end) {
|
||||||
$formatted = $start->format('Y-m-d');
|
$formatted = $start->format('Y-m-d');
|
||||||
$filtered = $set->filter(
|
$sum = $set[$formatted] ?? '0';
|
||||||
function (Budget $obj) use ($formatted) {
|
|
||||||
return $obj->date == $formatted;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
$sum = is_null($filtered->first()) ? '0' : $filtered->first()->dailyAmount;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sum of expenses on this day:
|
* Sum of expenses on this day:
|
||||||
@@ -135,7 +132,7 @@ class BudgetController extends Controller
|
|||||||
$start->addDay();
|
$start->addDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->generator->budgetLimit($entries);
|
$data = $this->generator->budgetLimit($entries, 'monthAndDay');
|
||||||
$cache->store($data);
|
$cache->store($data);
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<?php namespace FireflyIII\Models;
|
<?php namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Watson\Validating\ValidatingTrait;
|
use Watson\Validating\ValidatingTrait;
|
||||||
@@ -38,6 +38,7 @@ use Watson\Validating\ValidatingTrait;
|
|||||||
class Transaction extends Model
|
class Transaction extends Model
|
||||||
{
|
{
|
||||||
|
|
||||||
|
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount'];
|
protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount'];
|
||||||
protected $hidden = ['encrypted'];
|
protected $hidden = ['encrypted'];
|
||||||
protected $rules
|
protected $rules
|
||||||
@@ -47,10 +48,30 @@ class Transaction extends Model
|
|||||||
'description' => 'between:1,255',
|
'description' => 'between:1,255',
|
||||||
'amount' => 'required|numeric',
|
'amount' => 'required|numeric',
|
||||||
];
|
];
|
||||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
|
||||||
|
|
||||||
use SoftDeletes, ValidatingTrait;
|
use SoftDeletes, ValidatingTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Builder $query
|
||||||
|
* @param string $table
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isJoined(Builder $query, string $table):bool
|
||||||
|
{
|
||||||
|
$joins = $query->getQuery()->joins;
|
||||||
|
if (is_null($joins)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach ($joins as $join) {
|
||||||
|
if ($join->table === $table) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
*/
|
*/
|
||||||
@@ -59,54 +80,6 @@ class Transaction extends Model
|
|||||||
return $this->belongsTo('FireflyIII\Models\Account');
|
return $this->belongsTo('FireflyIII\Models\Account');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $value
|
|
||||||
*
|
|
||||||
* @return float|int
|
|
||||||
*/
|
|
||||||
public function getAmountAttribute($value)
|
|
||||||
{
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param EloquentBuilder $query
|
|
||||||
* @param Carbon $date
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function scopeAfter(EloquentBuilder $query, Carbon $date)
|
|
||||||
{
|
|
||||||
return $query->where('transaction_journals.date', '>=', $date->format('Y-m-d 00:00:00'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param EloquentBuilder $query
|
|
||||||
* @param Carbon $date
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function scopeBefore(EloquentBuilder $query, Carbon $date)
|
|
||||||
{
|
|
||||||
return $query->where('transaction_journals.date', '<=', $date->format('Y-m-d 00:00:00'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $value
|
|
||||||
*/
|
|
||||||
public function setAmountAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['amount'] = strval(round($value, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
||||||
*/
|
|
||||||
public function transactionJournal()
|
|
||||||
{
|
|
||||||
return $this->belongsTo('FireflyIII\Models\TransactionJournal');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||||
*/
|
*/
|
||||||
@@ -122,4 +95,74 @@ class Transaction extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsToMany('FireflyIII\Models\Category');
|
return $this->belongsToMany('FireflyIII\Models\Category');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $value
|
||||||
|
*
|
||||||
|
* @return float|int
|
||||||
|
*/
|
||||||
|
public function getAmountAttribute($value)
|
||||||
|
{
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param Builder $query
|
||||||
|
* @param Carbon $date
|
||||||
|
*/
|
||||||
|
public function scopeAfter(Builder $query, Carbon $date)
|
||||||
|
{
|
||||||
|
if (!self::isJoined($query, 'transaction_journals')) {
|
||||||
|
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
|
||||||
|
}
|
||||||
|
$query->where('transaction_journals.date', '>=', $date->format('Y-m-d 00:00:00'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param Builder $query
|
||||||
|
* @param Carbon $date
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function scopeBefore(Builder $query, Carbon $date)
|
||||||
|
{
|
||||||
|
if (!self::isJoined($query, 'transaction_journals')) {
|
||||||
|
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
|
||||||
|
}
|
||||||
|
$query->where('transaction_journals.date', '<=', $date->format('Y-m-d 00:00:00'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param Builder $query
|
||||||
|
* @param array $types
|
||||||
|
*/
|
||||||
|
public function scopeTransactionTypes(Builder $query, array $types)
|
||||||
|
{
|
||||||
|
if (!self::isJoined($query, 'transaction_journals')) {
|
||||||
|
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self::isJoined($query, 'transaction_types')) {
|
||||||
|
$query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
|
||||||
|
}
|
||||||
|
$query->whereIn('transaction_types.type', $types);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $value
|
||||||
|
*/
|
||||||
|
public function setAmountAttribute($value)
|
||||||
|
{
|
||||||
|
$this->attributes['amount'] = strval(round($value, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
|
*/
|
||||||
|
public function transactionJournal()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('FireflyIII\Models\TransactionJournal');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ use Illuminate\Database\Query\JoinClause;
|
|||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
use Input;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetRepository
|
* Class BudgetRepository
|
||||||
@@ -310,16 +311,19 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
|
* @deprecated
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
|
public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
|
// get budgets,
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
$budgetIds = $budgets->pluck('id')->toArray();
|
$budgetIds = $budgets->pluck('id')->toArray();
|
||||||
|
|
||||||
/** @var Collection $set */
|
/** @var Collection $set */
|
||||||
$set = $this->user->budgets()
|
$set = $this->user->budgets()
|
||||||
->leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
->join('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
||||||
->leftJoin(
|
->leftJoin(
|
||||||
'transactions', function (JoinClause $join) {
|
'transactions', function (JoinClause $join) {
|
||||||
@@ -340,6 +344,27 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// run it again, for transactions this time.
|
||||||
|
/** @var Collection $secondSet */
|
||||||
|
$secondSet = $this->user->budgets()
|
||||||
|
->join('budget_transaction', 'budgets.id', '=', 'budget_transaction.budget_id')
|
||||||
|
->leftJoin('transactions', 'transactions.id', '=', 'budget_transaction.transaction_id')
|
||||||
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->where('transactions.amount', '<', 0)
|
||||||
|
->groupBy('budgets.id')
|
||||||
|
->groupBy('dateFormatted')
|
||||||
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||||
|
->whereIn('transactions.account_id', $ids)
|
||||||
|
->whereIn('budgets.id', $budgetIds)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'budgets.*',
|
||||||
|
DB::raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y") AS `dateFormatted`'),
|
||||||
|
DB::raw('SUM(`transactions`.`amount`) AS `sumAmount`'),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
$set = $set->sortBy(
|
$set = $set->sortBy(
|
||||||
function (Budget $budget) {
|
function (Budget $budget) {
|
||||||
return strtolower($budget->name);
|
return strtolower($budget->name);
|
||||||
@@ -348,16 +373,36 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
|
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($set as $budget) {
|
foreach ($set as $budget) {
|
||||||
|
Log::debug('First set, budget #' . $budget->id . ' (' . $budget->name . ')');
|
||||||
$id = $budget->id;
|
$id = $budget->id;
|
||||||
if (!isset($return[$id])) {
|
if (!isset($return[$id])) {
|
||||||
|
Log::debug('$return[$id] is not set, now created.');
|
||||||
$return[$id] = [
|
$return[$id] = [
|
||||||
'budget' => $budget,
|
'budget' => $budget,
|
||||||
'entries' => [],
|
'entries' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
Log::debug('Add new entry to entries, for ' . $budget->dateFormatted . ' and amount ' . $budget->sumAmount);
|
||||||
// store each entry:
|
// store each entry:
|
||||||
$return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount;
|
$return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount;
|
||||||
}
|
}
|
||||||
|
unset($budget);
|
||||||
|
|
||||||
|
// run the second set:
|
||||||
|
foreach ($secondSet as $entry) {
|
||||||
|
$id = $entry->id;
|
||||||
|
// create it if it still does not exist (not really likely)
|
||||||
|
if (!isset($return[$id])) {
|
||||||
|
$return[$id] = [
|
||||||
|
'budget' => $entry,
|
||||||
|
'entries' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// this one might be filled too:
|
||||||
|
$startAmount = $return[$id]['entries'][$entry->dateFormatted] ?? '0';
|
||||||
|
// store each entry:
|
||||||
|
$return[$id]['entries'][$entry->dateFormatted] = bcadd($startAmount, $entry->sumAmount);
|
||||||
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@@ -453,40 +498,6 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
return $set;
|
return $set;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the expenses for this budget grouped per day, with the date
|
|
||||||
* in "date" (a string, not a Carbon) and the amount in "dailyAmount".
|
|
||||||
*
|
|
||||||
* @param Budget $budget
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
* @param Collection $accounts
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function getExpensesPerDay(Budget $budget, Carbon $start, Carbon $end, Collection $accounts = null): Collection
|
|
||||||
{
|
|
||||||
$query = $this->user->budgets()
|
|
||||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.budget_id', '=', 'budgets.id')
|
|
||||||
->leftJoin('transaction_journals', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
|
||||||
->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
|
||||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
|
||||||
->whereNull('transaction_journals.deleted_at')
|
|
||||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
|
||||||
->where('budgets.id', $budget->id)
|
|
||||||
->where('transactions.amount', '<', 0)
|
|
||||||
->groupBy('transaction_journals.date')
|
|
||||||
->orderBy('transaction_journals.date');
|
|
||||||
if (!is_null($accounts) && $accounts->count() > 0) {
|
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
|
||||||
$query->whereIn('transactions.account_id', $ids);
|
|
||||||
}
|
|
||||||
$set
|
|
||||||
= $query->get(['transaction_journals.date', DB::raw('SUM(`transactions`.`amount`) as `dailyAmount`')]);
|
|
||||||
|
|
||||||
return $set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
@@ -788,10 +799,11 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
|
* @param Collection $accounts
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function spentPerDay(Budget $budget, Carbon $start, Carbon $end): array
|
public function spentPerDay(Budget $budget, Carbon $start, Carbon $end, Collection $accounts): array
|
||||||
{
|
{
|
||||||
/** @var Collection $query */
|
/** @var Collection $query */
|
||||||
$query = $budget->transactionjournals()
|
$query = $budget->transactionjournals()
|
||||||
@@ -807,6 +819,24 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
$return[$entry['dateFormatted']] = $entry['sum'];
|
$return[$entry['dateFormatted']] = $entry['sum'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// also search transactions:
|
||||||
|
$query = $budget->transactions()
|
||||||
|
->transactionTypes([TransactionType::WITHDRAWAL])
|
||||||
|
->where('transactions.amount', '<', 0)
|
||||||
|
->before($end)
|
||||||
|
->after($start)
|
||||||
|
->groupBy('dateFormatted')->get(['transaction_journals.date as dateFormatted', DB::raw('SUM(`transactions`.`amount`) AS `sum`')]);
|
||||||
|
foreach ($query as $newEntry) {
|
||||||
|
// add to return array.
|
||||||
|
$date = $newEntry['dateFormatted'];
|
||||||
|
if (isset($return[$date])) {
|
||||||
|
$return[$date] = bcadd($newEntry['sum'], $return[$date]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$return[$date] = $newEntry['sum'];
|
||||||
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -131,6 +131,8 @@ interface BudgetRepositoryInterface
|
|||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
|
* @deprecated
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array;
|
public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array;
|
||||||
@@ -180,19 +182,6 @@ interface BudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function getExpenses(Budget $budget, Collection $accounts, Carbon $start, Carbon $end):Collection;
|
public function getExpenses(Budget $budget, Collection $accounts, Carbon $start, Carbon $end):Collection;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the expenses for this budget grouped per day, with the date
|
|
||||||
* in "date" (a string, not a Carbon) and the amount in "dailyAmount".
|
|
||||||
*
|
|
||||||
* @param Budget $budget
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
* @param Collection $accounts
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function getExpensesPerDay(Budget $budget, Carbon $start, Carbon $end, Collection $accounts = null) : Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
@@ -287,10 +276,11 @@ interface BudgetRepositoryInterface
|
|||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
|
* @param Collection $accounts
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function spentPerDay(Budget $budget, Carbon $start, Carbon $end): array;
|
public function spentPerDay(Budget $budget, Carbon $start, Carbon $end, Collection $accounts): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $data
|
* @param array $data
|
||||||
|
@@ -81,9 +81,13 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
public function first(): TransactionJournal
|
public function first(): TransactionJournal
|
||||||
{
|
{
|
||||||
$entry = $this->user->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
|
$entry = $this->user->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
|
||||||
|
|
||||||
if (is_null($entry)) {
|
if (is_null($entry)) {
|
||||||
|
Log::debug('Could not find first transaction journal.');
|
||||||
|
|
||||||
return new TransactionJournal;
|
return new TransactionJournal;
|
||||||
}
|
}
|
||||||
|
Log::debug('Found first journal: ', ['date' => $entry->date->format('Y-m-d')]);
|
||||||
|
|
||||||
return $entry;
|
return $entry;
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ use Carbon\Carbon;
|
|||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Support\Migration\TestData;
|
use FireflyIII\Support\Migration\TestData;
|
||||||
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,154 +50,48 @@ class SplitDataSeeder extends Seeder
|
|||||||
$user = TestData::createUsers();
|
$user = TestData::createUsers();
|
||||||
|
|
||||||
// create all kinds of static data:
|
// create all kinds of static data:
|
||||||
$assets = [
|
$assets = [['name' => 'Checking Account', 'iban' => 'NL11XOLA6707795988', 'meta' => ['accountRole' => 'defaultAsset']],
|
||||||
[
|
['name' => 'Alternate Checking Account', 'iban' => 'NL40UKBK3619908726', 'meta' => ['accountRole' => 'defaultAsset']],
|
||||||
'name' => 'Checking Account',
|
['name' => 'Savings Account', 'iban' => 'NL96DZCO4665940223', 'meta' => ['accountRole' => 'savingAsset']],
|
||||||
'iban' => 'NL11XOLA6707795988',
|
['name' => 'Shared Checking Account', 'iban' => 'NL81RCQZ7160379858', 'meta' => ['accountRole' => 'sharedAsset']]];
|
||||||
'meta' => [
|
|
||||||
'accountRole' => 'defaultAsset',
|
// some asset accounts
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Alternate Checking Account',
|
|
||||||
'iban' => 'NL40UKBK3619908726',
|
|
||||||
'meta' => [
|
|
||||||
'accountRole' => 'defaultAsset',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Savings Account',
|
|
||||||
'iban' => 'NL96DZCO4665940223',
|
|
||||||
'meta' => [
|
|
||||||
'accountRole' => 'savingAsset',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'name' => 'Shared Checking Account',
|
|
||||||
'iban' => 'NL81RCQZ7160379858',
|
|
||||||
'meta' => [
|
|
||||||
'accountRole' => 'sharedAsset',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
TestData::createAssetAccounts($user, $assets);
|
TestData::createAssetAccounts($user, $assets);
|
||||||
|
|
||||||
|
// budgets, categories and others:
|
||||||
TestData::createBudgets($user);
|
TestData::createBudgets($user);
|
||||||
TestData::createCategories($user);
|
TestData::createCategories($user);
|
||||||
TestData::createExpenseAccounts($user);
|
TestData::createExpenseAccounts($user);
|
||||||
TestData::createRevenueAccounts($user);
|
TestData::createRevenueAccounts($user);
|
||||||
TestData::createPiggybanks($user, 'Savings Account');
|
TestData::createPiggybanks($user, 'Savings Account');
|
||||||
|
TestData::createBills($user);
|
||||||
|
// some bills
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create splitted expense of 66,-
|
* Create splitted expense of 66,-
|
||||||
*/
|
*/
|
||||||
$today = new Carbon;
|
$today = new Carbon('2012-03-14');
|
||||||
$today->subDays(2);
|
|
||||||
|
|
||||||
if (!$skipWithdrawal) {
|
if (!$skipWithdrawal) {
|
||||||
$journal = TransactionJournal::create(
|
$this->generateWithdrawals($user);
|
||||||
[
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'transaction_type_id' => 1, // withdrawal
|
|
||||||
'transaction_currency_id' => 1,
|
|
||||||
'description' => 'Split Even Expense (journal (50/50))',
|
|
||||||
'completed' => 1,
|
|
||||||
'date' => $today->format('Y-m-d'),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// split in 6 transactions (multiple destinations). 22,- each
|
|
||||||
// source is TestData Checking Account.
|
|
||||||
// also attach some budgets and stuff.
|
|
||||||
$destinations = ['SixtyFive', 'EightyFour'];
|
|
||||||
$budgets = ['Groceries', 'Car'];
|
|
||||||
$categories = ['Bills', 'Bills'];
|
|
||||||
$amounts = [50, 50];
|
|
||||||
$source = TestData::findAccount($user, 'Alternate Checking Account');
|
|
||||||
foreach ($destinations as $index => $dest) {
|
|
||||||
$bud = $budgets[$index];
|
|
||||||
$cat = $categories[$index];
|
|
||||||
$destination = TestData::findAccount($user, $dest);
|
|
||||||
|
|
||||||
$one = Transaction::create(
|
|
||||||
[
|
|
||||||
'account_id' => $source->id,
|
|
||||||
'transaction_journal_id' => $journal->id,
|
|
||||||
'amount' => $amounts[$index] * -1,
|
|
||||||
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$two = Transaction::create(
|
|
||||||
[
|
|
||||||
'account_id' => $destination->id,
|
|
||||||
'transaction_journal_id' => $journal->id,
|
|
||||||
'amount' => $amounts[$index],
|
|
||||||
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$one->budgets()->save(TestData::findBudget($user, $bud));
|
|
||||||
$two->budgets()->save(TestData::findBudget($user, $bud));
|
|
||||||
|
|
||||||
$one->categories()->save(TestData::findCategory($user, $cat));
|
|
||||||
$two->categories()->save(TestData::findCategory($user, $cat));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// AND ANOTHER ONE
|
|
||||||
$today->addDay();
|
|
||||||
$journal = TransactionJournal::create(
|
|
||||||
[
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'transaction_type_id' => 1, // withdrawal
|
|
||||||
'transaction_currency_id' => 1,
|
|
||||||
'description' => 'Split Uneven Expense (journal (15/34/51=100))',
|
|
||||||
'completed' => 1,
|
|
||||||
'date' => $today->format('Y-m-d'),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// split in 6 transactions (multiple destinations). 22,- each
|
|
||||||
// source is TestData Checking Account.
|
|
||||||
// also attach some budgets and stuff.
|
|
||||||
$destinations = ['SixtyFive', 'EightyFour', 'Fiftyone'];
|
|
||||||
$budgets = ['Groceries', 'Groceries', 'Car'];
|
|
||||||
$categories = ['Bills', 'Bills', 'Car'];
|
|
||||||
$amounts = [15, 34, 51];
|
|
||||||
$source = TestData::findAccount($user, 'Checking Account');
|
|
||||||
foreach ($destinations as $index => $dest) {
|
|
||||||
$bud = $budgets[$index];
|
|
||||||
$cat = $categories[$index];
|
|
||||||
$destination = TestData::findAccount($user, $dest);
|
|
||||||
|
|
||||||
$one = Transaction::create(
|
|
||||||
[
|
|
||||||
'account_id' => $source->id,
|
|
||||||
'transaction_journal_id' => $journal->id,
|
|
||||||
'amount' => $amounts[$index] * -1,
|
|
||||||
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$two = Transaction::create(
|
|
||||||
[
|
|
||||||
'account_id' => $destination->id,
|
|
||||||
'transaction_journal_id' => $journal->id,
|
|
||||||
'amount' => $amounts[$index],
|
|
||||||
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$one->budgets()->save(TestData::findBudget($user, $bud));
|
|
||||||
$two->budgets()->save(TestData::findBudget($user, $bud));
|
|
||||||
|
|
||||||
$one->categories()->save(TestData::findCategory($user, $cat));
|
|
||||||
$two->categories()->save(TestData::findCategory($user, $cat));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create splitted income of 99,-
|
// create splitted income of 99,-
|
||||||
$today->addDay();
|
$today->addDay();
|
||||||
|
|
||||||
if (!$skipDeposit) {
|
if (!$skipDeposit) {
|
||||||
|
$this->generateDeposits();
|
||||||
|
}
|
||||||
|
// create a splitted transfer of 57,- (19)
|
||||||
|
// $today->addDay();
|
||||||
|
|
||||||
|
if (!$skipTransfer) {
|
||||||
|
$this->generateTransfers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateDeposits()
|
||||||
|
{
|
||||||
$journal = TransactionJournal::create(
|
$journal = TransactionJournal::create(
|
||||||
[
|
[
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
@@ -245,10 +140,9 @@ class SplitDataSeeder extends Seeder
|
|||||||
$two->categories()->save(TestData::findCategory($user, $cat));
|
$two->categories()->save(TestData::findCategory($user, $cat));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create a splitted transfer of 57,- (19)
|
|
||||||
$today->addDay();
|
|
||||||
|
|
||||||
if (!$skipTransfer) {
|
private function generateTransfers()
|
||||||
|
{
|
||||||
$journal = TransactionJournal::create(
|
$journal = TransactionJournal::create(
|
||||||
[
|
[
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
@@ -295,5 +189,114 @@ class SplitDataSeeder extends Seeder
|
|||||||
$two->categories()->save(TestData::findCategory($user, $cat));
|
$two->categories()->save(TestData::findCategory($user, $cat));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function generateWithdrawals(User $user)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* TRANSACTION ONE
|
||||||
|
*/
|
||||||
|
$date = new Carbon('2012-03-15');
|
||||||
|
$journal = TransactionJournal::create(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'transaction_type_id' => 1, // withdrawal
|
||||||
|
'transaction_currency_id' => 1,
|
||||||
|
'description' => 'Split Even Expense (journal (50/50))',
|
||||||
|
'completed' => 1,
|
||||||
|
'date' => $date->format('Y-m-d'),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// split in 6 transactions (multiple destinations). 22,- each
|
||||||
|
// source is TestData Checking Account.
|
||||||
|
// also attach some budgets and stuff.
|
||||||
|
$destinations = ['SixtyFive', 'EightyFour'];
|
||||||
|
$budgets = ['Groceries', 'Car'];
|
||||||
|
$categories = ['Bills', 'Bills'];
|
||||||
|
$amounts = [50, 50];
|
||||||
|
$source = TestData::findAccount($user, 'Alternate Checking Account');
|
||||||
|
foreach ($destinations as $index => $dest) {
|
||||||
|
$bud = $budgets[$index];
|
||||||
|
$cat = $categories[$index];
|
||||||
|
$destination = TestData::findAccount($user, $dest);
|
||||||
|
|
||||||
|
$one = Transaction::create(
|
||||||
|
[
|
||||||
|
'account_id' => $source->id,
|
||||||
|
'transaction_journal_id' => $journal->id,
|
||||||
|
'amount' => $amounts[$index] * -1,
|
||||||
|
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$two = Transaction::create(
|
||||||
|
[
|
||||||
|
'account_id' => $destination->id,
|
||||||
|
'transaction_journal_id' => $journal->id,
|
||||||
|
'amount' => $amounts[$index],
|
||||||
|
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$one->budgets()->save(TestData::findBudget($user, $bud));
|
||||||
|
$two->budgets()->save(TestData::findBudget($user, $bud));
|
||||||
|
|
||||||
|
$one->categories()->save(TestData::findCategory($user, $cat));
|
||||||
|
$two->categories()->save(TestData::findCategory($user, $cat));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GENERATE TRANSACTION TWO.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$date = new Carbon;
|
||||||
|
$journal = TransactionJournal::create(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'transaction_type_id' => 1, // withdrawal
|
||||||
|
'transaction_currency_id' => 1,
|
||||||
|
'description' => 'Split Uneven Expense (journal (15/34/51=100))',
|
||||||
|
'completed' => 1,
|
||||||
|
'date' => $date->format('Y-m-d'),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// split in 6 transactions (multiple destinations). 22,- each
|
||||||
|
// source is TestData Checking Account.
|
||||||
|
// also attach some budgets and stuff.
|
||||||
|
$destinations = ['SixtyFive', 'EightyFour', 'Fiftyone'];
|
||||||
|
$budgets = ['Groceries', 'Groceries', 'Car'];
|
||||||
|
$categories = ['Bills', 'Bills', 'Car'];
|
||||||
|
$amounts = [15, 34, 51];
|
||||||
|
$source = TestData::findAccount($user, 'Checking Account');
|
||||||
|
foreach ($destinations as $index => $dest) {
|
||||||
|
$bud = $budgets[$index];
|
||||||
|
$cat = $categories[$index];
|
||||||
|
$destination = TestData::findAccount($user, $dest);
|
||||||
|
|
||||||
|
$one = Transaction::create(
|
||||||
|
[
|
||||||
|
'account_id' => $source->id,
|
||||||
|
'transaction_journal_id' => $journal->id,
|
||||||
|
'amount' => $amounts[$index] * -1,
|
||||||
|
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$two = Transaction::create(
|
||||||
|
[
|
||||||
|
'account_id' => $destination->id,
|
||||||
|
'transaction_journal_id' => $journal->id,
|
||||||
|
'amount' => $amounts[$index],
|
||||||
|
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$one->budgets()->save(TestData::findBudget($user, $bud));
|
||||||
|
$two->budgets()->save(TestData::findBudget($user, $bud));
|
||||||
|
|
||||||
|
$one->categories()->save(TestData::findCategory($user, $cat));
|
||||||
|
$two->categories()->save(TestData::findCategory($user, $cat));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user