Merge branch 'release/3.6.0'

This commit is contained in:
James Cole 2016-01-07 10:22:17 +01:00
commit 5f299b895b
96 changed files with 2706 additions and 2607 deletions

View File

@ -27,7 +27,4 @@ ANALYTICS_ID=
RUNCLEANUP=true RUNCLEANUP=true
SITE_OWNER=mail@example.com SITE_OWNER=mail@example.com
SENDGRID_USERNAME=
SENDGRID_PASSWORD=
BLOCKED_DOMAINS= BLOCKED_DOMAINS=

View File

@ -11,8 +11,6 @@
"Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared "Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared
household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money. household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money.
_Firefly is a system you'll have install yourself on webhosting of your choosing._
Personal financial management is pretty difficult, and everybody has their own approach to it. Some people Personal financial management is pretty difficult, and everybody has their own approach to it. Some people
make budgets, other people limit their cashflow by throwing away their credit cards, others try to increase make budgets, other people limit their cashflow by throwing away their credit cards, others try to increase
their current cashflow. There are tons of ways to save and earn money. their current cashflow. There are tons of ways to save and earn money.
@ -26,6 +24,11 @@ To get to know Firefly, and to see if it fits you, check out these resources:
- The [full description](https://github.com/JC5/firefly-iii/wiki/full-description), which will tell you how Firefly works, - The [full description](https://github.com/JC5/firefly-iii/wiki/full-description), which will tell you how Firefly works,
and the philosophy behind it. and the philosophy behind it.
#### A quick technical overview
Firefly is a system you'll have install yourself on webhosting of your choosing. It needs PHP and MySQL. The current version of Firefly III requires PHP 5.6.4 or
higher. Soon, this will be PHP 7.0.0 or higher.
#### About the name (should you care) #### About the name (should you care)
@ -92,7 +95,7 @@ is open source software under active development, and it is in no way guaranteed
## Translations ## Translations
Firefly III is currently available in Dutch and English. Support for other languages is being worked on. I can use Firefly III is currently available in Dutch and English. Support for other languages is being worked on. I could use
your help. Checkout [Crowdin](https://crowdin.com/project/firefly-iii) for more information. your help. Checkout [Crowdin](https://crowdin.com/project/firefly-iii) for more information.
## Credits ## Credits

View File

@ -49,19 +49,12 @@ class ChartJsBillChartGenerator implements BillChartGenerator
*/ */
public function single(Bill $bill, Collection $entries) public function single(Bill $bill, Collection $entries)
{ {
// language: $format = trans('config.month');
$format = trans('config.month'); $data = [
$data = [
'count' => 3, 'count' => 3,
'labels' => [], 'labels' => [],
'datasets' => [], 'datasets' => [],
]; ];
// dataset: max amount
// dataset: min amount
// dataset: actual amount
$minAmount = []; $minAmount = [];
$maxAmount = []; $maxAmount = [];
$actualAmount = []; $actualAmount = [];

View File

@ -68,24 +68,24 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator
*/ */
public function frontpage(Collection $entries) public function frontpage(Collection $entries)
{ {
$data = [ $data = [
'count' => 0, 'count' => 0,
'labels' => [], 'labels' => [],
'datasets' => [], 'datasets' => [],
]; ];
// dataset: left
// dataset: spent
// dataset: overspent
$left = []; $left = [];
$spent = []; $spent = [];
$overspent = []; $overspent = [];
foreach ($entries as $entry) { $filtered = $entries->filter(
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) { function ($entry) {
$data['labels'][] = $entry[0]; return ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0);
$left[] = round($entry[1], 2);
$spent[] = round($entry[2] * -1, 2); // spent is coming in negative, must be positive
$overspent[] = round($entry[3] * -1, 2); // same
} }
);
foreach ($filtered as $entry) {
$data['labels'][] = $entry[0];
$left[] = round($entry[1], 2);
$spent[] = round($entry[2] * -1, 2); // spent is coming in negative, must be positive
$overspent[] = round($entry[3] * -1, 2); // same
} }
$data['datasets'][] = [ $data['datasets'][] = [

View File

@ -100,9 +100,9 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
], ],
]; ];
foreach ($entries as $entry) { foreach ($entries as $entry) {
if ($entry['sum'] != 0) { if ($entry->spent != 0) {
$data['labels'][] = $entry['name']; $data['labels'][] = $entry->name;
$data['datasets'][0]['data'][] = round(($entry['sum'] * -1), 2); $data['datasets'][0]['data'][] = round(($entry->spent * -1), 2);
} }
} }

View File

@ -28,8 +28,6 @@ class ConnectJournalToPiggyBank
/** /**
* Handle the event when journal is saved. * Handle the event when journal is saved.
* *
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @param JournalCreated $event * @param JournalCreated $event
* *
* @return boolean * @return boolean

View File

@ -3,7 +3,6 @@
namespace FireflyIII\Helpers\Collection; namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Budget as BudgetModel; use FireflyIII\Models\Budget as BudgetModel;
use FireflyIII\Models\LimitRepetition;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@ -26,9 +25,6 @@ class BalanceLine
/** @var BudgetModel */ /** @var BudgetModel */
protected $budget; protected $budget;
/** @var LimitRepetition */
protected $repetition;
protected $role = self::ROLE_DEFAULTROLE; protected $role = self::ROLE_DEFAULTROLE;
/** /**
@ -48,24 +44,19 @@ class BalanceLine
} }
/** /**
* @return string * @return Collection
*/ */
public function getTitle() public function getBalanceEntries()
{ {
if ($this->getBudget() instanceof BudgetModel) { return $this->balanceEntries;
return $this->getBudget()->name; }
}
if ($this->getRole() == self::ROLE_DEFAULTROLE) {
return trans('firefly.noBudget');
}
if ($this->getRole() == self::ROLE_TAGROLE) {
return trans('firefly.coveredWithTags');
}
if ($this->getRole() == self::ROLE_DIFFROLE) {
return trans('firefly.leftUnbalanced');
}
return ''; /**
* @param Collection $balanceEntries
*/
public function setBalanceEntries($balanceEntries)
{
$this->balanceEntries = $balanceEntries;
} }
/** /**
@ -100,6 +91,27 @@ class BalanceLine
$this->role = $role; $this->role = $role;
} }
/**
* @return string
*/
public function getTitle()
{
if ($this->getBudget() instanceof BudgetModel) {
return $this->getBudget()->name;
}
if ($this->getRole() == self::ROLE_DEFAULTROLE) {
return trans('firefly.noBudget');
}
if ($this->getRole() == self::ROLE_TAGROLE) {
return trans('firefly.coveredWithTags');
}
if ($this->getRole() == self::ROLE_DIFFROLE) {
return trans('firefly.leftUnbalanced');
}
return '';
}
/** /**
* If a BalanceLine has a budget/repetition, each BalanceEntry in this BalanceLine * If a BalanceLine has a budget/repetition, each BalanceEntry in this BalanceLine
* should have a "spent" value, which is the amount of money that has been spent * should have a "spent" value, which is the amount of money that has been spent
@ -110,7 +122,7 @@ class BalanceLine
*/ */
public function leftOfRepetition() public function leftOfRepetition()
{ {
$start = $this->getRepetition() ? $this->getRepetition()->amount : 0; $start = isset($this->budget->amount) ? $this->budget->amount : 0;
/** @var BalanceEntry $balanceEntry */ /** @var BalanceEntry $balanceEntry */
foreach ($this->getBalanceEntries() as $balanceEntry) { foreach ($this->getBalanceEntries() as $balanceEntry) {
$start += $balanceEntry->getSpent(); $start += $balanceEntry->getSpent();
@ -118,36 +130,4 @@ class BalanceLine
return $start; return $start;
} }
/**
* @return LimitRepetition
*/
public function getRepetition()
{
return $this->repetition;
}
/**
* @param LimitRepetition $repetition
*/
public function setRepetition($repetition)
{
$this->repetition = $repetition;
}
/**
* @return Collection
*/
public function getBalanceEntries()
{
return $this->balanceEntries;
}
/**
* @param Collection $balanceEntries
*/
public function setBalanceEntries($balanceEntries)
{
$this->balanceEntries = $balanceEntries;
}
} }

View File

@ -2,6 +2,7 @@
namespace FireflyIII\Helpers\Collection; namespace FireflyIII\Helpers\Collection;
use Crypt;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use stdClass; use stdClass;
@ -36,7 +37,7 @@ class Expense
bcscale(2); bcscale(2);
$accountId = $entry->account_id; $accountId = $entry->account_id;
$amount = strval(round($entry->amount, 2)); $amount = strval(round($entry->journalAmount, 2));
if (bccomp('0', $amount) === -1) { if (bccomp('0', $amount) === -1) {
$amount = bcmul($amount, '-1'); $amount = bcmul($amount, '-1');
} }
@ -44,7 +45,7 @@ class Expense
if (!$this->expenses->has($accountId)) { if (!$this->expenses->has($accountId)) {
$newObject = new stdClass; $newObject = new stdClass;
$newObject->amount = $amount; $newObject->amount = $amount;
$newObject->name = $entry->name; $newObject->name = Crypt::decrypt($entry->account_name);
$newObject->count = 1; $newObject->count = 1;
$newObject->id = $accountId; $newObject->id = $accountId;
$this->expenses->put($accountId, $newObject); $this->expenses->put($accountId, $newObject);

View File

@ -2,6 +2,7 @@
namespace FireflyIII\Helpers\Collection; namespace FireflyIII\Helpers\Collection;
use Crypt;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use stdClass; use stdClass;
@ -38,15 +39,15 @@ class Income
$accountId = $entry->account_id; $accountId = $entry->account_id;
if (!$this->incomes->has($accountId)) { if (!$this->incomes->has($accountId)) {
$newObject = new stdClass; $newObject = new stdClass;
$newObject->amount = strval(round($entry->amount_positive, 2)); $newObject->amount = strval(round($entry->journalAmount, 2));
$newObject->name = $entry->name; $newObject->name = Crypt::decrypt($entry->account_name);
$newObject->count = 1; $newObject->count = 1;
$newObject->id = $accountId; $newObject->id = $accountId;
$this->incomes->put($accountId, $newObject); $this->incomes->put($accountId, $newObject);
} else { } else {
bcscale(2); bcscale(2);
$existing = $this->incomes->get($accountId); $existing = $this->incomes->get($accountId);
$existing->amount = bcadd($existing->amount, $entry->amount_positive); $existing->amount = bcadd($existing->amount, $entry->journalAmount);
$existing->count++; $existing->count++;
$this->incomes->put($accountId, $existing); $this->incomes->put($accountId, $existing);
} }

View File

@ -29,6 +29,22 @@ class RabobankDescription
} }
/**
* @param array $data
*/
public function setData($data)
{
$this->data = $data;
}
/**
* @param array $row
*/
public function setRow($row)
{
$this->row = $row;
}
/** /**
* Fixes Rabobank specific thing. * Fixes Rabobank specific thing.
*/ */
@ -46,21 +62,5 @@ class RabobankDescription
} }
/**
* @param array $data
*/
public function setData($data)
{
$this->data = $data;
}
/**
* @param array $row
*/
public function setRow($row)
{
$this->row = $row;
}
} }

View File

@ -3,6 +3,7 @@
namespace FireflyIII\Helpers\Report; namespace FireflyIII\Helpers\Report;
use Carbon\Carbon; use Carbon\Carbon;
use DB;
use FireflyIII\Helpers\Collection\Account as AccountCollection; use FireflyIII\Helpers\Collection\Account as AccountCollection;
use FireflyIII\Helpers\Collection\Balance; use FireflyIII\Helpers\Collection\Balance;
use FireflyIII\Helpers\Collection\BalanceEntry; use FireflyIII\Helpers\Collection\BalanceEntry;
@ -19,8 +20,9 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget as BudgetModel; use FireflyIII\Models\Budget as BudgetModel;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Steam;
/** /**
* Class ReportHelper * Class ReportHelper
@ -61,10 +63,9 @@ class ReportHelper implements ReportHelperInterface
*/ */
/** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */ /** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); $repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface');
$set = $repository->getCategories();
$set = $repository->spentForAccountsPerMonth($accounts, $start, $end);
foreach ($set as $category) { foreach ($set as $category) {
$spent = $repository->balanceInPeriod($category, $start, $end, $accounts);
$category->spent = $spent;
$object->addCategory($category); $object->addCategory($category);
} }
@ -123,21 +124,59 @@ class ReportHelper implements ReportHelperInterface
$startAmount = '0'; $startAmount = '0';
$endAmount = '0'; $endAmount = '0';
$diff = '0'; $diff = '0';
$ids = $accounts->pluck('id')->toArray();
$yesterday = clone $start;
$yesterday->subDay();
bcscale(2); bcscale(2);
// get balances for start.
$startSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereIn('accounts.id', $ids)
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->where('transaction_journals.date', '<=', $yesterday->format('Y-m-d'))
->groupBy('accounts.id')
->get(['accounts.id', DB::Raw('SUM(`transactions`.`amount`) as `balance`')]);
// and for end:
$endSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereIn('accounts.id', $ids)
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->groupBy('accounts.id')
->get(['accounts.id', DB::Raw('SUM(`transactions`.`amount`) as `balance`')]);
$accounts->each( $accounts->each(
function (Account $account) use ($start, $end) { function (Account $account) use ($startSet, $endSet) {
/** /**
* The balance for today always incorporates transactions * The balance for today always incorporates transactions
* made on today. So to get todays "start" balance, we sub one * made on today. So to get todays "start" balance, we sub one
* day. * day.
*/ */
$yesterday = clone $start; //
$yesterday->subDay(); $currentStart = $startSet->filter(
function (Account $entry) use ($account) {
return $account->id == $entry->id;
}
);
if ($currentStart->first()) {
$account->startBalance = $currentStart->first()->balance;
}
/** @noinspection PhpParamsInspection */ $currentEnd = $endSet->filter(
$account->startBalance = Steam::balance($account, $yesterday); function (Account $entry) use ($account) {
$account->endBalance = Steam::balance($account, $end); return $account->id == $entry->id;
}
);
if ($currentEnd->first()) {
$account->endBalance = $currentEnd->first()->balance;
}
} }
); );
@ -170,9 +209,10 @@ class ReportHelper implements ReportHelperInterface
public function getIncomeReport($start, $end, Collection $accounts) public function getIncomeReport($start, $end, Collection $accounts)
{ {
$object = new Income; $object = new Income;
$set = $this->query->incomeInPeriod($start, $end, $accounts); $set = $this->query->income($accounts, $start, $end);
foreach ($set as $entry) { foreach ($set as $entry) {
$object->addToTotal($entry->amount_positive); $object->addToTotal($entry->journalAmount);
$object->addOrCreateIncome($entry); $object->addOrCreateIncome($entry);
} }
@ -191,9 +231,10 @@ class ReportHelper implements ReportHelperInterface
public function getExpenseReport($start, $end, Collection $accounts) public function getExpenseReport($start, $end, Collection $accounts)
{ {
$object = new Expense; $object = new Expense;
$set = $this->query->expenseInPeriod($start, $end, $accounts); $set = $this->query->expense($accounts, $start, $end);
foreach ($set as $entry) { foreach ($set as $entry) {
$object->addToTotal($entry->amount); // can be positive, if it's a transfer $object->addToTotal($entry->journalAmount); // can be positive, if it's a transfer
$object->addOrCreateExpense($entry); $object->addOrCreateExpense($entry);
} }
@ -211,18 +252,24 @@ class ReportHelper implements ReportHelperInterface
{ {
$object = new BudgetCollection; $object = new BudgetCollection;
/** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$set = $repository->getBudgets(); $set = $repository->getBudgets();
$allRepetitions = $repository->getAllBudgetLimitRepetitions($start, $end);
$allTotalSpent = $repository->spentAllPerDayForAccounts($accounts, $start, $end);
bcscale(2); bcscale(2);
foreach ($set as $budget) { foreach ($set as $budget) {
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end); $repetitions = $allRepetitions->filter(
function (LimitRepetition $rep) use ($budget) {
return $rep->budget_id == $budget->id;
}
);
$totalSpent = isset($allTotalSpent[$budget->id]) ? $allTotalSpent[$budget->id] : [];
// no repetition(s) for this budget: // no repetition(s) for this budget:
if ($repetitions->count() == 0) { if ($repetitions->count() == 0) {
$spent = $repository->balanceInPeriod($budget, $start, $end, $accounts); $spent = array_sum($totalSpent);
$budgetLine = new BudgetLine; $budgetLine = new BudgetLine;
$budgetLine->setBudget($budget); $budgetLine->setBudget($budget);
$budgetLine->setOverspent($spent); $budgetLine->setOverspent($spent);
@ -237,7 +284,7 @@ class ReportHelper implements ReportHelperInterface
$budgetLine = new BudgetLine; $budgetLine = new BudgetLine;
$budgetLine->setBudget($budget); $budgetLine->setBudget($budget);
$budgetLine->setRepetition($repetition); $budgetLine->setRepetition($repetition);
$expenses = $repository->balanceInPeriod($budget, $start, $end, $accounts); $expenses = $this->getSumOfRange($start, $end, $totalSpent);
// 200 en -100 is 100, vergeleken met 0 === 1 // 200 en -100 is 100, vergeleken met 0 === 1
// 200 en -200 is 0, vergeleken met 0 === 0 // 200 en -200 is 0, vergeleken met 0 === 0
@ -282,13 +329,18 @@ class ReportHelper implements ReportHelperInterface
*/ */
public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts) public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts)
{ {
$repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
/** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */
$tagRepository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface'); $tagRepository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface');
$balance = new Balance;
$balance = new Balance;
// build a balance header: // build a balance header:
$header = new BalanceHeader; $header = new BalanceHeader;
$budgets = $repository->getBudgets(); $budgets = $repository->getBudgetsAndLimitsInRange($start, $end);
$spentData = $repository->spentPerBudgetPerAccount($budgets, $accounts, $start, $end);
foreach ($accounts as $account) { foreach ($accounts as $account) {
$header->addAccount($account); $header->addAccount($account);
} }
@ -298,19 +350,21 @@ class ReportHelper implements ReportHelperInterface
$line = new BalanceLine; $line = new BalanceLine;
$line->setBudget($budget); $line->setBudget($budget);
// get budget amount for current period:
$rep = $repository->getCurrentRepetition($budget, $start, $end);
// could be null?
$line->setRepetition($rep);
// loop accounts: // loop accounts:
foreach ($accounts as $account) { foreach ($accounts as $account) {
$balanceEntry = new BalanceEntry; $balanceEntry = new BalanceEntry;
$balanceEntry->setAccount($account); $balanceEntry->setAccount($account);
// get spent: // get spent:
$spent = $this->query->spentInBudget($account, $budget, $start, $end); // I think shared is irrelevant. $entry = $spentData->filter(
function (TransactionJournal $model) use ($budget, $account) {
return $model->account_id == $account->id && $model->budget_id == $budget->id;
}
);
$spent = 0;
if (!is_null($entry->first())) {
$spent = $entry->first()->spent;
}
$balanceEntry->setSpent($spent); $balanceEntry->setSpent($spent);
$line->addBalanceEntry($balanceEntry); $line->addBalanceEntry($balanceEntry);
} }
@ -324,13 +378,30 @@ class ReportHelper implements ReportHelperInterface
$empty = new BalanceLine; $empty = new BalanceLine;
$tags = new BalanceLine; $tags = new BalanceLine;
$diffLine = new BalanceLine; $diffLine = new BalanceLine;
$tagsLeft = $tagRepository->allCoveredByBalancingActs($accounts, $start, $end);
$tags->setRole(BalanceLine::ROLE_TAGROLE); $tags->setRole(BalanceLine::ROLE_TAGROLE);
$diffLine->setRole(BalanceLine::ROLE_DIFFROLE); $diffLine->setRole(BalanceLine::ROLE_DIFFROLE);
foreach ($accounts as $account) { foreach ($accounts as $account) {
$spent = $this->query->spentNoBudget($account, $start, $end); $entry = $spentData->filter(
$left = $tagRepository->coveredByBalancingActs($account, $start, $end); function (TransactionJournal $model) use ($budget, $account) {
return $model->account_id == $account->id && is_null($model->budget_id);
}
);
$spent = 0;
if (!is_null($entry->first())) {
$spent = $entry->first()->spent;
}
$leftEntry = $tagsLeft->filter(
function (Tag $tag) use ($account) {
return $tag->account_id == $account->id;
}
);
$left = 0;
if (!is_null($leftEntry->first())) {
$left = $leftEntry->first()->sum;
}
bcscale(2); bcscale(2);
$diff = bcadd($spent, $left); $diff = bcadd($spent, $left);
@ -380,6 +451,7 @@ class ReportHelper implements ReportHelperInterface
/** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */ /** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface'); $repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface');
$bills = $repository->getBillsForAccounts($accounts); $bills = $repository->getBillsForAccounts($accounts);
$journals = $repository->getAllJournalsInRange($bills, $start, $end);
$collection = new BillCollection; $collection = new BillCollection;
/** @var Bill $bill */ /** @var Bill $bill */
@ -392,16 +464,17 @@ class ReportHelper implements ReportHelperInterface
// is hit in period? // is hit in period?
bcscale(2); bcscale(2);
$set = $repository->getJournalsInRange($bill, $start, $end);
if ($set->count() == 0) { $entry = $journals->filter(
$billLine->setHit(false); function (TransactionJournal $journal) use ($bill) {
} else { return $journal->bill_id == $bill->id;
$billLine->setHit(true);
$amount = '0';
foreach ($set as $entry) {
$amount = bcadd($amount, $entry->amount);
} }
$billLine->setAmount($amount); );
if (!is_null($entry->first())) {
$billLine->setAmount($entry->first()->journalAmount);
$billLine->setHit(true);
} else {
$billLine->setHit(false);
} }
$collection->addBill($billLine); $collection->addBill($billLine);
@ -410,4 +483,32 @@ class ReportHelper implements ReportHelperInterface
return $collection; return $collection;
} }
}
/**
* Take the array as returned by SingleCategoryRepositoryInterface::spentPerDay and SingleCategoryRepositoryInterface::earnedByDay
* and sum up everything in the array in the given range.
*
* @param Carbon $start
* @param Carbon $end
* @param array $array
*
* @return string
*/
protected function getSumOfRange(Carbon $start, Carbon $end, array $array)
{
bcscale(2);
$sum = '0';
$currentStart = clone $start; // to not mess with the original one
$currentEnd = clone $end; // to not mess with the original one
while ($currentStart <= $currentEnd) {
$date = $currentStart->format('Y-m-d');
if (isset($array[$date])) {
$sum = bcadd($sum, $array[$date]);
}
$currentStart->addDay();
}
return $sum;
}
}

View File

@ -4,12 +4,8 @@ namespace FireflyIII\Helpers\Report;
use Auth; use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use Crypt; use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -20,215 +16,163 @@ use Illuminate\Support\Collection;
*/ */
class ReportQuery implements ReportQueryInterface class ReportQuery implements ReportQueryInterface
{ {
/**
* Covers tags
*
* @param Account $account
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function spentInBudget(Account $account, Budget $budget, Carbon $start, Carbon $end)
{
return Auth::user()->transactionjournals() /**
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') * Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers)
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') * grouped by month like so: "2015-01" => '123.45'
->transactionTypes([TransactionType::WITHDRAWAL]) *
->where('transactions.account_id', $account->id) * @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function spentPerMonth(Collection $accounts, Carbon $start, Carbon $end)
{
$ids = $accounts->pluck('id')->toArray();
$query = Auth::user()->transactionjournals()
->leftJoin(
'transactions AS t_from', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0);
}
)
->leftJoin(
'transactions AS t_to', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0);
}
)
->whereIn('t_from.account_id', $ids)
->whereNotIn('t_to.account_id', $ids)
->after($start)
->before($end)
->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE])
->groupBy('dateFormatted')
->get(
[
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") AS `dateFormatted`'),
DB::Raw('SUM(`t_from`.`amount`) AS `sum`')
]
);
$array = [];
foreach ($query as $result) {
$array[$result->dateFormatted] = $result->sum;
}
return $array;
}
/**
* Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers)
* grouped by month like so: "2015-01" => '123.45'
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function earnedPerMonth(Collection $accounts, Carbon $start, Carbon $end)
{
$ids = $accounts->pluck('id')->toArray();
$query = Auth::user()->transactionjournals()
->leftJoin(
'transactions AS t_from', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0);
}
)
->leftJoin(
'transactions AS t_to', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0);
}
)
->whereIn('t_to.account_id', $ids)
->whereNotIn('t_from.account_id', $ids)
->after($start)
->before($end)
->transactionTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE])
->groupBy('dateFormatted')
->get(
[
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") AS `dateFormatted`'),
DB::Raw('SUM(`t_to`.`amount`) AS `sum`')
]
);
$array = [];
foreach ($query as $result) {
$array[$result->dateFormatted] = $result->sum;
}
return $array;
}
/**
* This method returns all the "in" transaction journals for the given account and given period. The amount
* is stored in "journalAmount".
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function income(Collection $accounts, Carbon $start, Carbon $end)
{
$ids = $accounts->pluck('id')->toArray();
$set = Auth::user()->transactionjournals()
->leftJoin(
'transactions as t_from', function (JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts', 't_from.account_id', '=', 'accounts.id')
->transactionTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE])
->before($end) ->before($end)
->after($start) ->after($start)
->where('budget_transaction_journal.budget_id', $budget->id) ->whereIn('t_to.account_id', $ids)
->get(['transaction_journals.*'])->sum('amount'); ->whereNotIn('t_from.account_id', $ids)
->get(['transaction_journals.*', 't_to.amount as journalAmount', 'accounts.id as account_id', 'accounts.name as account_name']);
return $set;
} }
/** /**
* @param Account $account * This method returns all the "out" transaction journals for the given account and given period. The amount
* @param Carbon $start * is stored in "journalAmount".
* @param Carbon $end
*
* @return string
*/
public function spentNoBudget(Account $account, Carbon $start, Carbon $end)
{
return
Auth::user()->transactionjournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->transactionTypes([TransactionType::WITHDRAWAL])
->where('transactions.account_id', $account->id)
->before($end)
->after($start)
->whereNull('budget_transaction_journal.budget_id')->get(['transaction_journals.*'])->sum('amount');
}
/**
* @param Carbon $start
* @param Carbon $end
*
* @return Builder
*/
protected function queryJournalsWithTransactions(Carbon $start, Carbon $end)
{
$query = TransactionJournal::
leftJoin(
'transactions as t_from', function (JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
->leftJoin(
'account_meta as acm_from', function (JoinClause $join) {
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
->leftJoin(
'account_meta as acm_to', function (JoinClause $join) {
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
}
)
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
$query->before($end)->after($start)->where('transaction_journals.user_id', Auth::user()->id);
return $query;
}
/**
* This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results
* will simply list the transaction journals only. This should allow any follow up counting to be accurate with
* regards to tags. It will only get the incomes to the specified accounts.
* *
* @param Collection $accounts
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts
* *
* @return Collection * @return Collection
*/ */
public function incomeInPeriod(Carbon $start, Carbon $end, Collection $accounts) public function expense(Collection $accounts, Carbon $start, Carbon $end)
{ {
$query = $this->queryJournalsWithTransactions($start, $end); $ids = $accounts->pluck('id')->toArray();
$set = Auth::user()->transactionjournals()
->leftJoin(
'transactions as t_from', function (JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts', 't_to.account_id', '=', 'accounts.id')
->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE])
->before($end)
->after($start)
->whereIn('t_from.account_id', $ids)
->whereNotIn('t_to.account_id', $ids)
->get(['transaction_journals.*', 't_from.amount as journalAmount', 'accounts.id as account_id', 'accounts.name as account_name']);
$ids = []; return $set;
/** @var Account $account */
foreach ($accounts as $account) {
$ids[] = $account->id;
}
// OR is a deposit
// OR any transfer TO the accounts in $accounts, not FROM any of the accounts in $accounts.
$query->where(
function (Builder $query) use ($ids) {
$query->where(
function (Builder $q) {
$q->where('transaction_types.type', TransactionType::DEPOSIT);
}
);
$query->orWhere(
function (Builder $q) use ($ids) {
$q->where('transaction_types.type', TransactionType::TRANSFER);
$q->whereNotIn('ac_from.id', $ids);
$q->whereIn('ac_to.id', $ids);
}
);
}
);
// only include selected accounts.
$query->whereIn('ac_to.id', $ids);
$query->orderBy('transaction_journals.date');
// get everything
$data = $query->get(
['transaction_journals.*',
'transaction_types.type', 'ac_from.name as name',
't_from.amount as from_amount',
't_to.amount as to_amount',
'ac_from.id as account_id', 'ac_from.encrypted as account_encrypted']
);
$data->each(
function (TransactionJournal $journal) {
if (intval($journal->account_encrypted) == 1) {
$journal->name = Crypt::decrypt($journal->name);
}
}
);
return $data;
}
/**
* See ReportQueryInterface::incomeInPeriod
*
* This method returns all "expense" journals in a certain period, which are both transfers to a shared account
* and "ordinary" withdrawals. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does
* not group and returns different fields.
*
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return Collection
*
*/
public function expenseInPeriod(Carbon $start, Carbon $end, Collection $accounts)
{
$ids = [];
/** @var Account $account */
foreach ($accounts as $account) {
$ids[] = $account->id;
}
$query = $this->queryJournalsWithTransactions($start, $end);
// withdrawals from any account are an expense.
// transfers away, from an account in the list, to an account not in the list, are an expense.
$query->where(
function (Builder $query) use ($ids) {
$query->where(
function (Builder $q) {
$q->where('transaction_types.type', TransactionType::WITHDRAWAL);
}
);
$query->orWhere(
function (Builder $q) use ($ids) {
$q->where('transaction_types.type', TransactionType::TRANSFER);
$q->whereIn('ac_from.id', $ids);
$q->whereNotIn('ac_to.id', $ids);
}
);
}
);
// expense goes from the selected accounts:
$query->whereIn('ac_from.id', $ids);
$query->orderBy('transaction_journals.date');
$data = $query->get( // get everything
['transaction_journals.*', 'transaction_types.type',
't_from.amount as from_amount',
't_to.amount as to_amount',
'ac_to.name as name', 'ac_to.id as account_id', 'ac_to.encrypted as account_encrypted']
);
$data->each(
function (TransactionJournal $journal) {
if (intval($journal->account_encrypted) == 1) {
$journal->name = Crypt::decrypt($journal->name);
}
}
);
return $data;
} }
} }

View File

@ -3,8 +3,6 @@
namespace FireflyIII\Helpers\Report; namespace FireflyIII\Helpers\Report;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@ -16,54 +14,52 @@ interface ReportQueryInterface
{ {
/** /**
* See ReportQueryInterface::incomeInPeriod * Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers)
* * grouped by month like so: "2015-01" => '123.45'
* This method returns all "expense" journals in a certain period, which are both transfers to a shared account
* and "ordinary" withdrawals. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does
* not group and returns different fields.
* *
* @param Collection $accounts
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts
*
* @return Collection
* *
* @return array
*/ */
public function expenseInPeriod(Carbon $start, Carbon $end, Collection $accounts); public function earnedPerMonth(Collection $accounts, Carbon $start, Carbon $end);
/** /**
* This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results * This method returns all the "out" transaction journals for the given account and given period. The amount
* will simply list the transaction journals only. This should allow any follow up counting to be accurate with * is stored in "journalAmount".
* regards to tags. It will only get the incomes to the specified accounts.
* *
* @param Collection $accounts
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts
* *
* @return Collection * @return Collection
*/ */
public function incomeInPeriod(Carbon $start, Carbon $end, Collection $accounts); public function expense(Collection $accounts, Carbon $start, Carbon $end);
/** /**
* Covers tags as well. * This method returns all the "in" transaction journals for the given account and given period. The amount
* is stored in "journalAmount".
* *
* @param Account $account * @param Collection $accounts
* @param Budget $budget * @param Carbon $start
* @param Carbon $start * @param Carbon $end
* @param Carbon $end
* *
* @return float * @return Collection
*/ */
public function spentInBudget(Account $account, Budget $budget, Carbon $start, Carbon $end); public function income(Collection $accounts, Carbon $start, Carbon $end);
/** /**
* @param Account $account * Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers)
* @param Carbon $start * grouped by month like so: "2015-01" => '123.45'
* @param Carbon $end
* *
* @return string * @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/ */
public function spentNoBudget(Account $account, Carbon $start, Carbon $end); public function spentPerMonth(Collection $accounts, Carbon $start, Carbon $end);
} }

View File

@ -6,7 +6,7 @@ use Config;
use ExpandedForm; use ExpandedForm;
use FireflyIII\Http\Requests\AccountFormRequest; use FireflyIII\Http\Requests\AccountFormRequest;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use Input; use Input;
use Preferences; use Preferences;
use Session; use Session;
@ -56,12 +56,12 @@ class AccountController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param Account $account * @param Account $account
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function delete(AccountRepositoryInterface $repository, Account $account) public function delete(ARI $repository, Account $account)
{ {
$typeName = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); $typeName = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]); $subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]);
@ -77,12 +77,12 @@ class AccountController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param Account $account * @param Account $account
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function destroy(AccountRepositoryInterface $repository, Account $account) public function destroy(ARI $repository, Account $account)
{ {
$type = $account->accountType->type; $type = $account->accountType->type;
$typeName = Config::get('firefly.shortNamesByFullName.' . $type); $typeName = Config::get('firefly.shortNamesByFullName.' . $type);
@ -98,12 +98,12 @@ class AccountController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param Account $account * @param Account $account
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function edit(AccountRepositoryInterface $repository, Account $account) public function edit(ARI $repository, Account $account)
{ {
$what = Config::get('firefly.shortNamesByFullName')[$account->accountType->type]; $what = Config::get('firefly.shortNamesByFullName')[$account->accountType->type];
@ -143,40 +143,31 @@ class AccountController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param $what * @param $what
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function index(AccountRepositoryInterface $repository, $what) public function index(ARI $repository, $what)
{ {
$subTitle = trans('firefly.' . $what . '_accounts'); $subTitle = trans('firefly.' . $what . '_accounts');
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$types = Config::get('firefly.accountTypesByIdentifier.' . $what); $types = Config::get('firefly.accountTypesByIdentifier.' . $what);
$accounts = $repository->getAccounts($types); $accounts = $repository->getAccounts($types);
// last activity: $start = clone Session::get('start', Carbon::now()->startOfMonth());
/** $end = clone Session::get('end', Carbon::now()->endOfMonth());
* HERE WE ARE
*/
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = clone Session::get('end', Carbon::now()->endOfMonth());
$start->subDay(); $start->subDay();
// start balances: $ids = $accounts->pluck('id')->toArray();
$ids = [];
foreach ($accounts as $account) {
$ids[] = $account->id;
}
$startBalances = Steam::balancesById($ids, $start); $startBalances = Steam::balancesById($ids, $start);
$endBalances = Steam::balancesById($ids, $end); $endBalances = Steam::balancesById($ids, $end);
$activities = Steam::getLastActivities($ids); $activities = Steam::getLastActivities($ids);
$accounts->each( $accounts->each(
function (Account $account) use ($activities, $startBalances, $endBalances) { function (Account $account) use ($activities, $startBalances, $endBalances) {
$account->lastActivityDate = isset($activities[$account->id]) ? $activities[$account->id] : null; $account->lastActivityDate = $this->isInArray($activities, $account->id);
$account->startBalance = isset($startBalances[$account->id]) ? $startBalances[$account->id] : null; $account->startBalance = $this->isInArray($startBalances, $account->id);
$account->endBalance = isset($endBalances[$account->id]) ? $endBalances[$account->id] : null; $account->endBalance = $this->isInArray($endBalances, $account->id);
} }
); );
@ -184,12 +175,12 @@ class AccountController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param Account $account * @param Account $account
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function show(AccountRepositoryInterface $repository, Account $account) public function show(ARI $repository, Account $account)
{ {
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); $page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type); $subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type);
@ -203,12 +194,12 @@ class AccountController extends Controller
} }
/** /**
* @param AccountFormRequest $request * @param AccountFormRequest $request
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function store(AccountFormRequest $request, AccountRepositoryInterface $repository) public function store(AccountFormRequest $request, ARI $repository)
{ {
$accountData = [ $accountData = [
'name' => $request->input('name'), 'name' => $request->input('name'),
@ -242,13 +233,13 @@ class AccountController extends Controller
} }
/** /**
* @param AccountFormRequest $request * @param AccountFormRequest $request
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param Account $account * @param Account $account
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function update(AccountFormRequest $request, AccountRepositoryInterface $repository, Account $account) public function update(AccountFormRequest $request, ARI $repository, Account $account)
{ {
$accountData = [ $accountData = [
@ -283,4 +274,20 @@ class AccountController extends Controller
} }
/**
* @param array $array
* @param $entryId
*
* @return null|mixed
*/
protected function isInArray(array $array, $entryId)
{
if (isset($array[$entryId])) {
return $array[$entryId];
}
return null;
}
} }

View File

@ -58,15 +58,7 @@ class AuthController extends Controller
*/ */
public function postLogin(Request $request) public function postLogin(Request $request)
{ {
$this->validate( $this->validate($request, [$this->loginUsername() => 'required', 'password' => 'required',]);
$request, [
$this->loginUsername() => 'required', 'password' => 'required',
]
);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
$throttles = $this->isUsingThrottlesLoginsTrait(); $throttles = $this->isUsingThrottlesLoginsTrait();
if ($throttles && $this->hasTooManyLoginAttempts($request)) { if ($throttles && $this->hasTooManyLoginAttempts($request)) {
@ -80,10 +72,7 @@ class AuthController extends Controller
return $this->handleUserWasAuthenticated($request, $throttles); return $this->handleUserWasAuthenticated($request, $throttles);
} }
// default error message:
$message = $this->getFailedLoginMessage(); $message = $this->getFailedLoginMessage();
// try to find a blocked user with this email address.
/** @var User $foundUser */ /** @var User $foundUser */
$foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first(); $foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first();
if (!is_null($foundUser)) { if (!is_null($foundUser)) {
@ -95,22 +84,13 @@ class AuthController extends Controller
$message = trans('firefly.' . $code . '_error', ['email' => $credentials['email']]); $message = trans('firefly.' . $code . '_error', ['email' => $credentials['email']]);
} }
// try
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
if ($throttles) { if ($throttles) {
$this->incrementLoginAttempts($request); $this->incrementLoginAttempts($request);
} }
return redirect($this->loginPath()) return redirect($this->loginPath())
->withInput($request->only($this->loginUsername(), 'remember')) ->withInput($request->only($this->loginUsername(), 'remember'))
->withErrors( ->withErrors([$this->loginUsername() => $message,]);
[
$this->loginUsername() => $message,
]
);
} }

View File

@ -78,6 +78,7 @@ class PasswordController extends Controller
} }
abort(404); abort(404);
return ''; return '';
} }

View File

@ -6,8 +6,9 @@ use Carbon\Carbon;
use FireflyIII\Http\Requests\BudgetFormRequest; use FireflyIII\Http\Requests\BudgetFormRequest;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Support\Collection;
use Input; use Input;
use Navigation; use Navigation;
use Preferences; use Preferences;
@ -20,7 +21,6 @@ use View;
* Class BudgetController * Class BudgetController
* *
* @package FireflyIII\Http\Controllers * @package FireflyIII\Http\Controllers
* @SuppressWarnings(PHPMD.TooManyMethods)
*/ */
class BudgetController extends Controller class BudgetController extends Controller
{ {
@ -132,13 +132,13 @@ class BudgetController extends Controller
} }
/** /**
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* *
* @param AccountRepositoryInterface $accountRepository * @param ARI $accountRepository
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function index(BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) public function index(BudgetRepositoryInterface $repository, ARI $accountRepository)
{ {
$budgets = $repository->getActiveBudgets(); $budgets = $repository->getActiveBudgets();
$inactive = $repository->getInactiveBudgets(); $inactive = $repository->getInactiveBudgets();
@ -232,13 +232,26 @@ class BudgetController extends Controller
$journals = $repository->getJournals($budget, $repetition); $journals = $repository->getJournals($budget, $repetition);
if (is_null($repetition->id)) { if (is_null($repetition->id)) {
$limits = $repository->getBudgetLimits($budget); $start = $repository->firstActivity($budget);
$end = new Carbon;
$set = $budget->limitrepetitions()->orderBy('startdate', 'DESC')->get();
$subTitle = e($budget->name); $subTitle = e($budget->name);
} else { } else {
$limits = [$repetition->budgetLimit]; $start = $repetition->startdate;
$end = $repetition->enddate;
$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)]);
} }
$spentArray = $repository->spentPerDay($budget, $start, $end);
$limits = new Collection();
/** @var LimitRepetition $entry */
foreach ($set as $entry) {
$entry->spent = $this->getSumOfRange($entry->startdate, $entry->enddate, $spentArray);
$limits->push($entry);
}
$journals->setPath('/budgets/show/' . $budget->id); $journals->setPath('/budgets/show/' . $budget->id);
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle')); return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));

View File

@ -4,7 +4,8 @@ use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Requests\CategoryFormRequest; use FireflyIII\Http\Requests\CategoryFormRequest;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
use FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface as SCRI;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -68,12 +69,12 @@ class CategoryController extends Controller
} }
/** /**
* @param CategoryRepositoryInterface $repository * @param SCRI $repository
* @param Category $category * @param Category $category
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function destroy(CategoryRepositoryInterface $repository, Category $category) public function destroy(SCRI $repository, Category $category)
{ {
$name = $category->name; $name = $category->name;
@ -107,17 +108,18 @@ class CategoryController extends Controller
} }
/** /**
* @param CategoryRepositoryInterface $repository * @param CRI $repository
* @param SCRI $singleRepository
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function index(CategoryRepositoryInterface $repository) public function index(CRI $repository, SCRI $singleRepository)
{ {
$categories = $repository->getCategories(); $categories = $repository->listCategories();
$categories->each( $categories->each(
function (Category $category) use ($repository) { function (Category $category) use ($singleRepository) {
$category->lastActivity = $repository->getLatestActivity($category); $category->lastActivity = $singleRepository->getLatestActivity($category);
} }
); );
@ -125,15 +127,15 @@ class CategoryController extends Controller
} }
/** /**
* @param CategoryRepositoryInterface $repository * @param CRI $repository
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function noCategory(CategoryRepositoryInterface $repository) public function noCategory(CRI $repository)
{ {
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->startOfMonth()); $end = Session::get('end', Carbon::now()->startOfMonth());
$list = $repository->getWithoutCategory($start, $end); $list = $repository->listNoCategory($start, $end);
$subTitle = trans( $subTitle = trans(
'firefly.without_category_between', 'firefly.without_category_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
@ -143,14 +145,14 @@ class CategoryController extends Controller
} }
/** /**
* @param CategoryRepositoryInterface $repository * @param SCRI $repository
* @param Category $category * @param Category $category
* *
* @param $date * @param $date
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function showWithDate(CategoryRepositoryInterface $repository, Category $category, $date) public function showWithDate(SCRI $repository, Category $category, $date)
{ {
$carbon = new Carbon($date); $carbon = new Carbon($date);
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
@ -170,12 +172,12 @@ class CategoryController extends Controller
} }
/** /**
* @param CategoryRepositoryInterface $repository * @param SCRI $repository
* @param Category $category * @param Category $category
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function show(CategoryRepositoryInterface $repository, Category $category) public function show(SCRI $repository, Category $category)
{ {
$hideCategory = true; // used in list. $hideCategory = true; // used in list.
$page = intval(Input::get('page')); $page = intval(Input::get('page'));
@ -200,6 +202,12 @@ class CategoryController extends Controller
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty('category-show'); $cache->addProperty('category-show');
$cache->addProperty($category->id); $cache->addProperty($category->id);
// get all spent and earned data:
// get amount earned in period, grouped by day.
$spentArray = $repository->spentPerDay($category, $start, $end);
$earnedArray = $repository->earnedPerDay($category, $start, $end);
if ($cache->has()) { if ($cache->has()) {
$entries = $cache->get(); $entries = $cache->get();
} else { } else {
@ -208,9 +216,9 @@ class CategoryController extends Controller
$end = Navigation::startOfPeriod($end, $range); $end = Navigation::startOfPeriod($end, $range);
$currentEnd = Navigation::endOfPeriod($end, $range); $currentEnd = Navigation::endOfPeriod($end, $range);
// here do something. // get data from spentArray:
$spent = $repository->spentInPeriod($category, $end, $currentEnd); $spent = $this->getSumOfRange($end, $currentEnd, $spentArray);
$earned = $repository->earnedInPeriod($category, $end, $currentEnd); $earned = $this->getSumOfRange($end, $currentEnd, $earnedArray);
$dateStr = $end->format('Y-m-d'); $dateStr = $end->format('Y-m-d');
$dateName = Navigation::periodShow($end, $range); $dateName = Navigation::periodShow($end, $range);
$entries->push([$dateStr, $dateName, $spent, $earned]); $entries->push([$dateStr, $dateName, $spent, $earned]);
@ -225,12 +233,12 @@ class CategoryController extends Controller
} }
/** /**
* @param CategoryFormRequest $request * @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository * @param SCRI $repository
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function store(CategoryFormRequest $request, CategoryRepositoryInterface $repository) public function store(CategoryFormRequest $request, SCRI $repository)
{ {
$categoryData = [ $categoryData = [
'name' => $request->input('name'), 'name' => $request->input('name'),
@ -252,13 +260,13 @@ class CategoryController extends Controller
/** /**
* @param CategoryFormRequest $request * @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository * @param SCRI $repository
* @param Category $category * @param Category $category
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function update(CategoryFormRequest $request, CategoryRepositoryInterface $repository, Category $category) public function update(CategoryFormRequest $request, SCRI $repository, Category $category)
{ {
$categoryData = [ $categoryData = [
'name' => $request->input('name'), 'name' => $request->input('name'),

View File

@ -5,7 +5,7 @@ namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Preferences; use Preferences;
@ -37,14 +37,14 @@ class AccountController extends Controller
/** /**
* Shows the balances for a given set of dates and accounts. * Shows the balances for a given set of dates and accounts.
* *
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function report($report_type, Carbon $start, Carbon $end, Collection $accounts) public function report($reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
// chart properties for cache: // chart properties for cache:
$cache = new CacheProperties(); $cache = new CacheProperties();
@ -53,6 +53,7 @@ class AccountController extends Controller
$cache->addProperty('all'); $cache->addProperty('all');
$cache->addProperty('accounts'); $cache->addProperty('accounts');
$cache->addProperty('default'); $cache->addProperty('default');
$cache->addProperty($reportType);
$cache->addProperty($accounts); $cache->addProperty($accounts);
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
@ -68,11 +69,11 @@ class AccountController extends Controller
/** /**
* Shows the balances for all the user's expense accounts. * Shows the balances for all the user's expense accounts.
* *
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function expenseAccounts(AccountRepositoryInterface $repository) public function expenseAccounts(ARI $repository)
{ {
$start = clone Session::get('start', Carbon::now()->startOfMonth()); $start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = clone Session::get('end', Carbon::now()->endOfMonth()); $end = clone Session::get('end', Carbon::now()->endOfMonth());
@ -98,11 +99,11 @@ class AccountController extends Controller
/** /**
* Shows the balances for all the user's frontpage accounts. * Shows the balances for all the user's frontpage accounts.
* *
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function frontpage(AccountRepositoryInterface $repository) public function frontpage(ARI $repository)
{ {
$frontPage = Preferences::get('frontPageAccounts', []); $frontPage = Preferences::get('frontPageAccounts', []);
$start = clone Session::get('start', Carbon::now()->startOfMonth()); $start = clone Session::get('start', Carbon::now()->startOfMonth());

View File

@ -6,7 +6,7 @@ use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -37,8 +37,10 @@ class BudgetController extends Controller
} }
/** /**
* TODO expand with no budget chart.
*
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
@ -46,11 +48,11 @@ class BudgetController extends Controller
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function multiYear(BudgetRepositoryInterface $repository, $report_type, Carbon $start, Carbon $end, Collection $accounts, Collection $budgets) public function multiYear(BudgetRepositoryInterface $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts, Collection $budgets)
{ {
// chart properties for cache: // chart properties for cache:
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($report_type); $cache->addProperty($reportType);
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty($accounts); $cache->addProperty($accounts);
@ -61,41 +63,43 @@ class BudgetController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
/** /*
* budget * Get the budgeted amounts for each budgets in each year.
* year:
* spent: x
* budgeted: x
* year
* spent: x
* budgeted: x
*/ */
$budgetedSet = $repository->getBudgetedPerYear($budgets, $start, $end);
$budgetedArray = [];
/** @var Budget $entry */
foreach ($budgetedSet as $entry) {
$budgetedArray[$entry->id][$entry->dateFormatted] = $entry->budgeted;
}
$set = $repository->getBudgetsAndExpensesPerYear($budgets, $accounts, $start, $end);
$entries = new Collection; $entries = new Collection;
// go by budget, not by year. // go by budget, not by year.
/** @var Budget $budget */
foreach ($budgets as $budget) { foreach ($budgets as $budget) {
$entry = ['name' => '', 'spent' => [], 'budgeted' => []]; $entry = ['name' => '', 'spent' => [], 'budgeted' => []];
$id = $budget->id;
$currentStart = clone $start; $currentStart = clone $start;
while ($currentStart < $end) { while ($currentStart < $end) {
// fix the date: // fix the date:
$currentEnd = clone $currentStart; $currentEnd = clone $currentStart;
$currentEnd->endOfYear(); $currentEnd->endOfYear();
// get data: // save to array:
if (is_null($budget->id)) { $year = $currentStart->year;
$name = trans('firefly.noBudget'); $entry['name'] = $budget->name;
$sum = $repository->getWithoutBudgetSum($currentStart, $currentEnd); $spent = 0;
$budgeted = 0; $budgeted = 0;
} else { if (isset($set[$id]['entries'][$year])) {
$name = $budget->name; $spent = $set[$id]['entries'][$year] * -1;
$sum = $repository->balanceInPeriod($budget, $currentStart, $currentEnd, $accounts);
$budgeted = $repository->getBudgetLimitRepetitions($budget, $currentStart, $currentEnd)->sum('amount');
} }
// save to array: if (isset($budgetedArray[$id][$year])) {
$year = $currentStart->year; $budgeted = round($budgetedArray[$id][$year], 2);
$entry['name'] = $name; }
$entry['spent'][$year] = ($sum * -1);
$entry['spent'][$year] = $spent;
$entry['budgeted'][$year] = $budgeted; $entry['budgeted'][$year] = $budgeted;
// jump to next year. // jump to next year.
@ -106,30 +110,25 @@ class BudgetController extends Controller
} }
// generate chart with data: // generate chart with data:
$data = $this->generator->multiYear($entries); $data = $this->generator->multiYear($entries);
$cache->store($data);
return Response::json($data); return Response::json($data);
} }
/** /**
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* @param AccountRepositoryInterface $accountRepository * @param Budget $budget
* @param Budget $budget
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function budget(BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository, Budget $budget) public function budget(BudgetRepositoryInterface $repository, Budget $budget)
{ {
// dates and times // dates and times
$first = $repository->getFirstBudgetLimitDate($budget); $first = $repository->getFirstBudgetLimitDate($budget);
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
$last = Session::get('end', new Carbon); $last = Session::get('end', new Carbon);
$final = clone $last;
$final->addYears(2);
$last = Navigation::endOfX($last, $range, $final);
$accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']);
// chart properties for cache: // chart properties for cache:
$cache = new CacheProperties(); $cache = new CacheProperties();
@ -137,18 +136,29 @@ class BudgetController extends Controller
$cache->addProperty($last); $cache->addProperty($last);
$cache->addProperty('budget'); $cache->addProperty('budget');
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$final = clone $last;
$final->addYears(2);
$last = Navigation::endOfX($last, $range, $final);
$entries = new Collection; $entries = new Collection;
// get all expenses:
$set = $repository->getExpensesPerMonth($budget, $first, $last); // TODO
while ($first < $last) { while ($first < $last) {
$end = Navigation::addPeriod($first, $range, 0); $monthFormatted = $first->format('Y-m');
$end->subDay();
$chartDate = clone $end; $filtered = $set->filter(
$chartDate->startOfMonth(); function (Budget $obj) use ($monthFormatted) {
$spent = $repository->balanceInPeriod($budget, $first, $end, $accounts) * -1; return $obj->dateFormatted == $monthFormatted;
$entries->push([$chartDate, $spent]); }
);
$spent = is_null($filtered->first()) ? '0' : $filtered->first()->monthlyAmount;
$entries->push([$first, round(($spent * -1), 2)]);
$first = Navigation::addPeriod($first, $range, 0); $first = Navigation::addPeriod($first, $range, 0);
} }
@ -185,15 +195,24 @@ class BudgetController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$set = $repository->getExpensesPerDay($budget, $start, $end);
$entries = new Collection; $entries = new Collection;
$amount = $repetition->amount; $amount = $repetition->amount;
// get sum (har har)!
while ($start <= $end) { while ($start <= $end) {
$formatted = $start->format('Y-m-d');
$filtered = $set->filter(
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:
*/ */
$sum = $repository->expensesOnDay($budget, $start); $amount = round(bcadd($amount, $sum), 2);
$amount = bcadd($amount, $sum);
$entries->push([clone $start, $amount]); $entries->push([clone $start, $amount]);
$start->addDay(); $start->addDay();
} }
@ -208,13 +227,13 @@ class BudgetController extends Controller
/** /**
* Shows a budget list with spent/left/overspent. * Shows a budget list with spent/left/overspent.
* *
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* *
* @param AccountRepositoryInterface $accountRepository * @param ARI $accountRepository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function frontpage(BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) public function frontpage(BudgetRepositoryInterface $repository, ARI $accountRepository)
{ {
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
@ -273,24 +292,23 @@ class BudgetController extends Controller
} }
/** /**
* TODO expand with no budget chart.
*
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function year(BudgetRepositoryInterface $repository, $report_type, Carbon $start, Carbon $end, Collection $accounts) public function year(BudgetRepositoryInterface $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
$allBudgets = $repository->getBudgets();
$budgets = new Collection;
// chart properties for cache: // chart properties for cache:
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty($report_type); $cache->addProperty($reportType);
$cache->addProperty($accounts); $cache->addProperty($accounts);
$cache->addProperty('budget'); $cache->addProperty('budget');
$cache->addProperty('year'); $cache->addProperty('year');
@ -298,26 +316,30 @@ class BudgetController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
// filter empty budgets: $budgetInformation = $repository->getBudgetsAndExpensesPerMonth($accounts, $start, $end);
foreach ($allBudgets as $budget) { $budgets = new Collection;
$spent = $repository->balanceInPeriod($budget, $start, $end, $accounts); $entries = new Collection;
if ($spent != 0) {
$budgets->push($budget);
}
}
$entries = new Collection; /** @var array $row */
foreach ($budgetInformation as $row) {
$budgets->push($row['budget']);
}
while ($start < $end) { while ($start < $end) {
// month is the current end of the period: // month is the current end of the period:
$month = clone $start; $month = clone $start;
$month->endOfMonth(); $month->endOfMonth();
$row = [clone $start]; $row = [clone $start];
$dateFormatted = $start->format('Y-m');
// each budget, fill the row: // each budget, check if there is an entry for this month:
foreach ($budgets as $budget) { /** @var array $row */
$spent = $repository->balanceInPeriod($budget, $start, $month, $accounts); foreach ($budgetInformation as $budgetRow) {
$row[] = $spent * -1; $spent = 0; // nothing spent.
if (isset($budgetRow['entries'][$dateFormatted])) {
$spent = $budgetRow['entries'][$dateFormatted] * -1; // to fit array
}
$row[] = $spent;
} }
$entries->push($row); $entries->push($row);
$start->endOfMonth()->addDay(); $start->endOfMonth()->addDay();

View File

@ -6,13 +6,15 @@ namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
use FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface as SCRI;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Navigation; use Navigation;
use Preferences; use Preferences;
use Response; use Response;
use Session; use Session;
use stdClass;
/** /**
* Class CategoryController * Class CategoryController
@ -38,12 +40,12 @@ class CategoryController extends Controller
/** /**
* Show an overview for a category for all time, per month/week/year. * Show an overview for a category for all time, per month/week/year.
* *
* @param CategoryRepositoryInterface $repository * @param SCRI $repository
* @param Category $category * @param Category $category
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function all(CategoryRepositoryInterface $repository, Category $category) public function all(SCRI $repository, Category $category)
{ {
// oldest transaction in category: // oldest transaction in category:
$start = $repository->getFirstActivityDate($category); $start = $repository->getFirstActivityDate($category);
@ -62,12 +64,18 @@ class CategoryController extends Controller
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$spentArray = $repository->spentPerDay($category, $start, $end);
$earnedArray = $repository->earnedPerDay($category, $start, $end);
while ($start <= $end) { while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range); $currentEnd = Navigation::endOfPeriod($start, $range);
$spent = $repository->spentInPeriod($category, $start, $currentEnd);
$earned = $repository->earnedInPeriod($category, $start, $currentEnd); // get the sum from $spentArray and $earnedArray:
$date = Navigation::periodShow($start, $range); $spent = $this->getSumOfRange($start, $currentEnd, $spentArray);
$earned = $this->getSumOfRange($start, $currentEnd, $earnedArray);
$date = Navigation::periodShow($start, $range);
$entries->push([clone $start, $date, $spent, $earned]); $entries->push([clone $start, $date, $spent, $earned]);
$start = Navigation::addPeriod($start, $range, 0); $start = Navigation::addPeriod($start, $range, 0);
} }
@ -84,14 +92,15 @@ class CategoryController extends Controller
} }
/** /**
* Show this month's category overview. * Show this month's category overview.
* *
* @param CategoryRepositoryInterface $repository * @param CRI $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function frontpage(CategoryRepositoryInterface $repository) public function frontpage(CRI $repository)
{ {
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
@ -107,30 +116,26 @@ class CategoryController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$array = $repository->getCategoriesAndExpenses($start, $end); // get data for categories (and "no category"):
// sort by callback: $set = $repository->spentForAccountsPerMonth(new Collection, $start, $end);
uasort( $outside = $repository->sumSpentNoCategory(new Collection, $start, $end);
$array,
function ($left, $right) {
if ($left['sum'] == $right['sum']) {
return 0;
}
return ($left['sum'] < $right['sum']) ? -1 : 1; // this is a "fake" entry for the "no category" entry.
} $entry = new stdClass();
); $entry->name = trans('firefly.no_category');
$set = new Collection($array); $entry->spent = $outside;
$set->push($entry);
$set = $set->sortBy('spent');
$data = $this->generator->frontpage($set); $data = $this->generator->frontpage($set);
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);
} }
/** /**
* @param CategoryRepositoryInterface $repository * @param $reportType
* @param $report_type
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
@ -138,11 +143,14 @@ class CategoryController extends Controller
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function multiYear(CategoryRepositoryInterface $repository, $report_type, Carbon $start, Carbon $end, Collection $accounts, Collection $categories) public function multiYear($reportType, Carbon $start, Carbon $end, Collection $accounts, Collection $categories)
{ {
/** @var CRI $repository */
$repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface');
// chart properties for cache: // chart properties for cache:
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($report_type); $cache->addProperty($reportType);
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty($accounts); $cache->addProperty($accounts);
@ -163,7 +171,14 @@ class CategoryController extends Controller
* earned: x * earned: x
*/ */
$entries = new Collection; $entries = new Collection;
// go by budget, not by year. // go by category, not by year.
// given a set of categories and accounts, it should not be difficult to get
// the exact array of data we need.
// then get the data for "no category".
$set = $repository->listMultiYear($categories, $accounts, $start, $end);
/** @var Category $category */ /** @var Category $category */
foreach ($categories as $category) { foreach ($categories as $category) {
$entry = ['name' => '', 'spent' => [], 'earned' => []]; $entry = ['name' => '', 'spent' => [], 'earned' => []];
@ -171,22 +186,35 @@ class CategoryController extends Controller
$currentStart = clone $start; $currentStart = clone $start;
while ($currentStart < $end) { while ($currentStart < $end) {
// fix the date: // fix the date:
$year = $currentStart->year;
$currentEnd = clone $currentStart; $currentEnd = clone $currentStart;
$currentEnd->endOfYear(); $currentEnd->endOfYear();
// get data: // get data:
if (is_null($category->id)) { if (is_null($category->id)) {
$name = trans('firefly.noCategory'); $name = trans('firefly.noCategory');
$spent = $repository->spentNoCategoryForAccounts($accounts, $currentStart, $currentEnd); $spent = $repository->sumSpentNoCategory($accounts, $currentStart, $currentEnd);
$earned = $repository->earnedNoCategoryForAccounts($accounts, $currentStart, $currentEnd); $earned = $repository->sumEarnedNoCategory($accounts, $currentStart, $currentEnd);
} else { } else {
// get from set:
$entrySpent = $set->filter(
function (Category $cat) use ($year, $category) {
return ($cat->type == 'Withdrawal' && $cat->dateFormatted == $year && $cat->id == $category->id);
}
)->first();
$entryEarned = $set->filter(
function (Category $cat) use ($year, $category) {
return ($cat->type == 'Deposit' && $cat->dateFormatted == $year && $cat->id == $category->id);
}
)->first();
$name = $category->name; $name = $category->name;
$spent = $repository->spentInPeriodForAccounts($category, $accounts, $currentStart, $currentEnd); $spent = !is_null($entrySpent) ? $entrySpent->sum : 0;
$earned = $repository->earnedInPeriodForAccounts($category, $accounts, $currentStart, $currentEnd); $earned = !is_null($entryEarned) ? $entryEarned->sum : 0;
} }
// save to array: // save to array:
$year = $currentStart->year;
$entry['name'] = $name; $entry['name'] = $name;
$entry['spent'][$year] = ($spent * -1); $entry['spent'][$year] = ($spent * -1);
$entry['earned'][$year] = $earned; $entry['earned'][$year] = $earned;
@ -201,18 +229,17 @@ class CategoryController extends Controller
$data = $this->generator->multiYear($entries); $data = $this->generator->multiYear($entries);
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);
} }
/** /**
* @param CategoryRepositoryInterface $repository * @param SCRI $repository
* @param Category $category * @param Category $category
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function currentPeriod(CategoryRepositoryInterface $repository, Category $category) public function currentPeriod(SCRI $repository, Category $category)
{ {
$start = clone Session::get('start', Carbon::now()->startOfMonth()); $start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
@ -223,16 +250,21 @@ class CategoryController extends Controller
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty($category->id); $cache->addProperty($category->id);
$cache->addProperty('category'); $cache->addProperty('category');
$cache->addProperty('currentPeriod'); $cache->addProperty('current-period');
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$entries = new Collection; $entries = new Collection;
// get amount earned in period, grouped by day.
// get amount spent in period, grouped by day.
$spentArray = $repository->spentPerDay($category, $start, $end);
$earnedArray = $repository->earnedPerDay($category, $start, $end);
while ($start <= $end) { while ($start <= $end) {
$spent = $repository->spentOnDaySum($category, $start); $str = $start->format('Y-m-d');
$earned = $repository->earnedOnDaySum($category, $start); $spent = isset($spentArray[$str]) ? $spentArray[$str] : 0;
$earned = isset($earnedArray[$str]) ? $earnedArray[$str] : 0;
$date = Navigation::periodShow($start, '1D'); $date = Navigation::periodShow($start, '1D');
$entries->push([clone $start, $date, $spent, $earned]); $entries->push([clone $start, $date, $spent, $earned]);
$start->addDay(); $start->addDay();
@ -242,19 +274,17 @@ class CategoryController extends Controller
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);
} }
/** /**
* @param CategoryRepositoryInterface $repository * @param SCRI $repository
* @param Category $category * @param Category $category
* *
* @param $date * @param $date
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function specificPeriod(CategoryRepositoryInterface $repository, Category $category, $date) public function specificPeriod(SCRI $repository, Category $category, $date)
{ {
$carbon = new Carbon($date); $carbon = new Carbon($date);
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
@ -274,12 +304,17 @@ class CategoryController extends Controller
} }
$entries = new Collection; $entries = new Collection;
// get amount earned in period, grouped by day.
$spentArray = $repository->spentPerDay($category, $start, $end);
$earnedArray = $repository->earnedPerDay($category, $start, $end);
// get amount spent in period, grouped by day.
while ($start <= $end) { while ($start <= $end) {
$spent = $repository->spentOnDaySum($category, $start); $str = $start->format('Y-m-d');
$earned = $repository->earnedOnDaySum($category, $start); $spent = isset($spentArray[$str]) ? $spentArray[$str] : 0;
$theDate = Navigation::periodShow($start, '1D'); $earned = isset($earnedArray[$str]) ? $earnedArray[$str] : 0;
$entries->push([clone $start, $theDate, $spent, $earned]); $date = Navigation::periodShow($start, '1D');
$entries->push([clone $start, $date, $spent, $earned]);
$start->addDay(); $start->addDay();
} }
@ -295,99 +330,62 @@ class CategoryController extends Controller
* Returns a chart of what has been earned in this period in each category * Returns a chart of what has been earned in this period in each category
* grouped by month. * grouped by month.
* *
* @param CategoryRepositoryInterface $repository * @param CRI $repository
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function earnedInPeriod(CategoryRepositoryInterface $repository, $report_type, Carbon $start, Carbon $end, Collection $accounts) public function earnedInPeriod(CRI $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
$original = clone $start; $cache = new CacheProperties; // chart properties for cache:
$cache = new CacheProperties; // chart properties for cache:
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty($report_type); $cache->addProperty($reportType);
$cache->addProperty($accounts); $cache->addProperty($accounts);
$cache->addProperty('category'); $cache->addProperty('category');
$cache->addProperty('earned-in-period'); $cache->addProperty('earned-in-period');
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$categories = new Collection;
$sets = new Collection;
$entries = new Collection;
// run a very special query each month: $set = $repository->earnedForAccountsPerMonth($accounts, $start, $end);
$start = clone $original; $categories = $set->unique('id')->sortBy(
while ($start < $end) {
$currentEnd = clone $start;
$currentStart = clone $start;
$currentStart->startOfMonth();
$currentEnd->endOfMonth();
// get a list of categories, and what the user has earned for that category
// (if the user has earned anything)
$set = $repository->earnedForAccounts($accounts, $currentStart, $currentEnd);
$categories = $categories->merge($set);
// save the set combined with the data that is in it:
// for example:
// december 2015, salary:1000, bonus:200
$sets->push([$currentStart, $set]);
$start->addMonth();
}
// filter categories into a single bunch. Useful later on.
// $categories contains all the categories the user has earned money
// in in this period.
$categories = $categories->unique('id');
$categories = $categories->sortBy(
function (Category $category) { function (Category $category) {
return $category->name; return $category->name;
} }
); );
$entries = new Collection;
// start looping the time again, this time processing the while ($start < $end) { // filter the set:
// data for each month. $row = [clone $start];
$start = clone $original; // get possibly relevant entries from the big $set
while ($start < $end) { $currentSet = $set->filter(
$currentEnd = clone $start; function (Category $category) use ($start) {
$currentStart = clone $start; return $category->dateFormatted == $start->format("Y-m");
$currentStart->startOfMonth();
$currentEnd->endOfMonth();
// in $sets we have saved all the sets of data for each month
// so now we need to retrieve the corrent one.
// match is on date of course.
$currentSet = $sets->first(
function ($key, $value) use ($currentStart) {
// set for this date.
return ($value[0] == $currentStart);
} }
); );
// create a row used later on. // check for each category if its in the current set.
$row = [clone $currentStart];
// loop all categories:
/** @var Category $category */ /** @var Category $category */
foreach ($categories as $category) { foreach ($categories as $category) {
// if entry is not null, we've earned money in this period for this category. // if its in there, use the value.
$entry = $currentSet[1]->first( $entry = $currentSet->filter(
function ($key, $value) use ($category) { function (Category $cat) use ($category) {
return $value->id == $category->id; return ($cat->id == $category->id);
} }
); )->first();
// save amount
if (!is_null($entry)) { if (!is_null($entry)) {
$row[] = $entry->earned; $row[] = round($entry->earned, 2);
} else { } else {
$row[] = 0; $row[] = 0;
} }
} }
$entries->push($row); $entries->push($row);
$start->addMonth(); $start->addMonth();
} }
$data = $this->generator->earnedInPeriod($categories, $entries); $data = $this->generator->earnedInPeriod($categories, $entries);
$cache->store($data); $cache->store($data);
@ -399,87 +397,67 @@ class CategoryController extends Controller
* Returns a chart of what has been spent in this period in each category * Returns a chart of what has been spent in this period in each category
* grouped by month. * grouped by month.
* *
* @param CategoryRepositoryInterface $repository * @param CRI $repository
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function spentInPeriod(CategoryRepositoryInterface $repository, $report_type, Carbon $start, Carbon $end, Collection $accounts) public function spentInPeriod(CRI $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
$original = clone $start; $cache = new CacheProperties; // chart properties for cache:
$cache = new CacheProperties; // chart properties for cache:
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty($report_type); $cache->addProperty($reportType);
$cache->addProperty($accounts); $cache->addProperty($accounts);
$cache->addProperty('category'); $cache->addProperty('category');
$cache->addProperty('spent-in-period'); $cache->addProperty('spent-in-period');
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$categories = new Collection;
$sets = new Collection;
$entries = new Collection;
// run a very special query each month: $set = $repository->spentForAccountsPerMonth($accounts, $start, $end);
$start = clone $original; $categories = $set->unique('id')->sortBy(
while ($start < $end) {
$currentEnd = clone $start;
$currentStart = clone $start;
$currentStart->startOfMonth();
$currentEnd->endOfMonth();
$set = $repository->spentForAccounts($accounts, $currentStart, $currentEnd);
$categories = $categories->merge($set);
$sets->push([$currentStart, $set]);
$start->addMonth();
}
$categories = $categories->unique('id');
$categories = $categories->sortBy(
function (Category $category) { function (Category $category) {
return $category->name; return $category->name;
} }
); );
$entries = new Collection;
$start = clone $original; while ($start < $end) { // filter the set:
while ($start < $end) { $row = [clone $start];
$currentEnd = clone $start; // get possibly relevant entries from the big $set
$currentStart = clone $start; $currentSet = $set->filter(
$currentStart->startOfMonth(); function (Category $category) use ($start) {
$currentEnd->endOfMonth(); return $category->dateFormatted == $start->format("Y-m");
$currentSet = $sets->first(
function ($key, $value) use ($currentStart) {
// set for this date.
return ($value[0] == $currentStart);
} }
); );
$row = [clone $currentStart]; // check for each category if its in the current set.
/** @var Category $category */ /** @var Category $category */
foreach ($categories as $category) { foreach ($categories as $category) {
/** @var Category $entry */ // if its in there, use the value.
$entry = $currentSet[1]->first( $entry = $currentSet->filter(
function ($key, $value) use ($category) { function (Category $cat) use ($category) {
return $value->id == $category->id; return ($cat->id == $category->id);
} }
); )->first();
if (!is_null($entry)) { if (!is_null($entry)) {
$row[] = $entry->spent; $row[] = round(($entry->spent * -1), 2);
} else { } else {
$row[] = 0; $row[] = 0;
} }
} }
$entries->push($row); $entries->push($row);
$start->addMonth(); $start->addMonth();
} }
$data = $this->generator->spentInPeriod($categories, $entries); $data = $this->generator->spentInPeriod($categories, $entries);
$cache->store($data); $cache->store($data);
return $data; return $data;
} }
} }

View File

@ -36,66 +36,40 @@ class ReportController extends Controller
* Summarizes all income and expenses, per month, for a given year. * Summarizes all income and expenses, per month, for a given year.
* *
* @param ReportQueryInterface $query * @param ReportQueryInterface $query
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function yearInOut(ReportQueryInterface $query, $report_type, Carbon $start, Carbon $end, Collection $accounts) public function yearInOut(ReportQueryInterface $query, $reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
// chart properties for cache: // chart properties for cache:
$cache = new CacheProperties; $cache = new CacheProperties;
$cache->addProperty('yearInOut'); $cache->addProperty('yearInOut');
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($reportType);
$cache->addProperty($accounts); $cache->addProperty($accounts);
$cache->addProperty($end); $cache->addProperty($end);
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
// spent per month, and earned per month. For a specific set of accounts
// grouped by month
$spentArray = $query->spentPerMonth($accounts, $start, $end);
$earnedArray = $query->earnedPerMonth($accounts, $start, $end);
// per year?
if ($start->diffInMonths($end) > 12) { if ($start->diffInMonths($end) > 12) {
// data = method X
$entries = new Collection; $data = $this->multiYearInOut($earnedArray, $spentArray, $start, $end);
while ($start < $end) {
$startOfYear = clone $start;
$startOfYear->startOfYear();
$endOfYear = clone $startOfYear;
$endOfYear->endOfYear();
// total income and total expenses:
$incomeSum = $query->incomeInPeriod($startOfYear, $endOfYear, $accounts)->sum('amount_positive');
$expenseSum = $query->expenseInPeriod($startOfYear, $endOfYear, $accounts)->sum('amount_positive');
$entries->push([clone $start, $incomeSum, $expenseSum]);
$start->addYear();
}
$data = $this->generator->multiYearInOut($entries);
$cache->store($data);
} else { } else {
// per month: // data = method Y
$data = $this->singleYearInOut($earnedArray, $spentArray, $start, $end);
$entries = new Collection;
while ($start < $end) {
$month = clone $start;
$month->endOfMonth();
// total income and total expenses:
$incomeSum = $query->incomeInPeriod($start, $month, $accounts)->sum('amount_positive');
$expenseSum = $query->expenseInPeriod($start, $month, $accounts)->sum('amount_positive');
$entries->push([clone $start, $incomeSum, $expenseSum]);
$start->addMonth();
}
$data = $this->generator->yearInOut($entries);
$cache->store($data);
} }
$cache->store($data);
return Response::json($data); return Response::json($data);
@ -105,14 +79,14 @@ class ReportController extends Controller
* Summarizes all income and expenses for a given year. Gives a total and an average. * Summarizes all income and expenses for a given year. Gives a total and an average.
* *
* @param ReportQueryInterface $query * @param ReportQueryInterface $query
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function yearInOutSummarized(ReportQueryInterface $query, $report_type, Carbon $start, Carbon $end, Collection $accounts) public function yearInOutSummarized(ReportQueryInterface $query, $reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
// chart properties for cache: // chart properties for cache:
@ -120,58 +94,155 @@ class ReportController extends Controller
$cache->addProperty('yearInOutSummarized'); $cache->addProperty('yearInOutSummarized');
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty($reportType);
$cache->addProperty($accounts); $cache->addProperty($accounts);
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
// spent per month, and earned per month. For a specific set of accounts
// grouped by month
$spentArray = $query->spentPerMonth($accounts, $start, $end);
$earnedArray = $query->earnedPerMonth($accounts, $start, $end);
if ($start->diffInMonths($end) > 12) {
// per year
$data = $this->multiYearInOutSummarized($earnedArray, $spentArray, $start, $end);
} else {
// per month!
$data = $this->singleYearInOutSummarized($earnedArray, $spentArray, $start, $end);
}
$cache->store($data);
return Response::json($data);
}
/**
* @param array $earned
* @param array $spent
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
protected function singleYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end)
{
$income = '0'; $income = '0';
$expense = '0'; $expense = '0';
$count = 0; $count = 0;
while ($start < $end) {
$date = $start->format('Y-m');
$currentIncome = isset($earned[$date]) ? $earned[$date] : 0;
$currentExpense = isset($spent[$date]) ? ($spent[$date] * -1) : 0;
$income = bcadd($income, $currentIncome);
$expense = bcadd($expense, $currentExpense);
bcscale(2); $count++;
$start->addMonth();
if ($start->diffInMonths($end) > 12) {
// per year
while ($start < $end) {
$startOfYear = clone $start;
$startOfYear->startOfYear();
$endOfYear = clone $startOfYear;
$endOfYear->endOfYear();
// total income and total expenses:
$currentIncome = $query->incomeInPeriod($startOfYear, $endOfYear, $accounts)->sum('amount_positive');
$currentExpense = $query->expenseInPeriod($startOfYear, $endOfYear, $accounts)->sum('amount_positive');
$income = bcadd($income, $currentIncome);
$expense = bcadd($expense, $currentExpense);
$count++;
$start->addYear();
}
$data = $this->generator->multiYearInOutSummarized($income, $expense, $count);
$cache->store($data);
} else {
// per month!
while ($start < $end) {
$month = clone $start;
$month->endOfMonth();
// total income and total expenses:
$currentIncome = $query->incomeInPeriod($start, $month, $accounts)->sum('amount_positive');
$currentExpense = $query->expenseInPeriod($start, $month, $accounts)->sum('amount_positive');
$income = bcadd($income, $currentIncome);
$expense = bcadd($expense, $currentExpense);
$count++;
$start->addMonth();
}
$data = $this->generator->yearInOutSummarized($income, $expense, $count);
$cache->store($data);
} }
$data = $this->generator->yearInOutSummarized($income, $expense, $count);
return Response::json($data); return $data;
}
/**
* @param array $earned
* @param array $spent
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
protected function multiYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end)
{
$income = '0';
$expense = '0';
$count = 0;
while ($start < $end) {
$currentIncome = $this->pluckFromArray($start->year, $earned);
$currentExpense = $this->pluckFromArray($start->year, $spent) * -1;
$income = bcadd($income, $currentIncome);
$expense = bcadd($expense, $currentExpense);
$count++;
$start->addYear();
}
$data = $this->generator->multiYearInOutSummarized($income, $expense, $count);
return $data;
}
/**
* @param array $earned
* @param array $spent
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
protected function multiYearInOut(array $earned, array $spent, Carbon $start, Carbon $end)
{
$entries = new Collection;
while ($start < $end) {
$incomeSum = $this->pluckFromArray($start->year, $earned);
$expenseSum = $this->pluckFromArray($start->year, $spent) * -1;
$entries->push([clone $start, $incomeSum, $expenseSum]);
$start->addYear();
}
$data = $this->generator->multiYearInOut($entries);
return $data;
}
/**
* @param array $earned
* @param array $spent
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
protected function singleYearInOut(array $earned, array $spent, Carbon $start, Carbon $end)
{
// per month? simply use each month.
$entries = new Collection;
while ($start < $end) {
// total income and total expenses:
$date = $start->format('Y-m');
$incomeSum = isset($earned[$date]) ? $earned[$date] : 0;
$expenseSum = isset($spent[$date]) ? ($spent[$date] * -1) : 0;
$entries->push([clone $start, $incomeSum, $expenseSum]);
$start->addMonth();
}
$data = $this->generator->yearInOut($entries);
return $data;
}
/**
* @param int $year
* @param array $set
*
* @return string
*/
protected function pluckFromArray($year, array $set)
{
bcscale(2);
$sum = '0';
foreach ($set as $date => $amount) {
if (substr($date, 0, 4) == $year) {
$sum = bcadd($sum, $amount);
}
}
return $sum;
} }
} }

View File

@ -1,6 +1,7 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Auth; use Auth;
use Carbon\Carbon;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController; use Illuminate\Routing\Controller as BaseController;
@ -44,4 +45,32 @@ abstract class Controller extends BaseController
View::share('localeconv', localeconv()); View::share('localeconv', localeconv());
} }
} }
/**
* Take the array as returned by SingleCategoryRepositoryInterface::spentPerDay and SingleCategoryRepositoryInterface::earnedByDay
* and sum up everything in the array in the given range.
*
* @param Carbon $start
* @param Carbon $end
* @param array $array
*
* @return string
*/
protected function getSumOfRange(Carbon $start, Carbon $end, array $array)
{
bcscale(2);
$sum = '0';
$currentStart = clone $start; // to not mess with the original one
$currentEnd = clone $end; // to not mess with the original one
while ($currentStart <= $currentEnd) {
$date = $currentStart->format('Y-m-d');
if (isset($array[$date])) {
$sum = bcadd($sum, $array[$date]);
}
$currentStart->addDay();
}
return $sum;
}
} }

View File

@ -1,74 +0,0 @@
<?php
namespace FireflyIII\Http\Controllers;
use FireflyIII\User;
/**
* Class WebhookController
*
* @package FireflyIII\Http\Controllers
*/
class CronController extends Controller
{
/**
* Firefly doesn't have anything that should be in the a cron job, except maybe this one, and it's fairly exceptional.
*
* If you use SendGrid like I do, you can detect bounces and thereby check if users gave an invalid address. If they did,
* it's easy to block them and change their password. Optionally, you could notify yourself about it and send them a message.
*
* But thats something not supported right now.
*/
public function sendgrid()
{
if (strlen(env('SENDGRID_USERNAME')) > 0 && strlen(env('SENDGRID_PASSWORD')) > 0) {
$set = [
'blocks' => 'https://api.sendgrid.com/api/blocks.get.json',
'bounces' => 'https://api.sendgrid.com/api/bounces.get.json',
'invalids' => 'https://api.sendgrid.com/api/invalidemails.get.json',
];
echo '<pre>';
foreach ($set as $name => $URL) {
$parameters = [
'api_user' => env('SENDGRID_USERNAME'),
'api_key' => env('SENDGRID_PASSWORD'),
'date' => 1,
'days' => 7
];
$fullURL = $URL . '?' . http_build_query($parameters);
$data = json_decode(file_get_contents($fullURL));
/*
* Loop the result, if any.
*/
if (is_array($data)) {
echo 'Found ' . count($data) . ' entries in the SendGrid ' . $name . ' list.' . "\n";
foreach ($data as $entry) {
$address = $entry->email;
$user = User::where('email', $address)->where('blocked', 0)->first();
if (!is_null($user)) {
echo 'Found a user: ' . $address . ', who is now blocked.' . "\n";
$user->blocked = 1;
$user->blocked_code = 'bounced';
$user->password = 'bounced';
$user->save();
} else {
echo 'Found no user: ' . $address . ', did nothing.' . "\n";
}
}
}
}
echo 'Done!' . "\n";
} else {
echo 'Please fill in SendGrid details.';
}
}
}

View File

@ -8,7 +8,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Csv\Data; use FireflyIII\Helpers\Csv\Data;
use FireflyIII\Helpers\Csv\Importer; use FireflyIII\Helpers\Csv\Importer;
use FireflyIII\Helpers\Csv\WizardInterface; use FireflyIII\Helpers\Csv\WizardInterface;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Input; use Input;
use Log; use Log;
@ -146,11 +146,11 @@ class CsvController extends Controller
* *
* STEP ONE * STEP ONE
* *
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function index(AccountRepositoryInterface $repository) public function index(ARI $repository)
{ {
$subTitle = trans('firefly.csv_import'); $subTitle = trans('firefly.csv_import');

View File

@ -4,7 +4,7 @@ use Artisan;
use Carbon\Carbon; use Carbon\Carbon;
use Config; use Config;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use Input; use Input;
use Preferences; use Preferences;
use Session; use Session;
@ -62,11 +62,11 @@ class HomeController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/ */
public function index(AccountRepositoryInterface $repository) public function index(ARI $repository)
{ {
$types = Config::get('firefly.accountTypesByIdentifier.asset'); $types = Config::get('firefly.accountTypesByIdentifier.asset');
$count = $repository->countAccounts($types); $count = $repository->countAccounts($types);

View File

@ -3,9 +3,9 @@
use Amount; use Amount;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
@ -60,7 +60,7 @@ class JsonController extends Controller
} }
/** /**
* @param BillRepositoryInterface $repository * @param BillRepositoryInterface $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
@ -111,13 +111,13 @@ class JsonController extends Controller
} }
/** /**
* @param ReportQueryInterface $reportQuery * @param ReportQueryInterface $reportQuery
* *
* @param AccountRepositoryInterface $accountRepository * @param ARI $accountRepository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function boxIn(ReportQueryInterface $reportQuery, AccountRepositoryInterface $accountRepository) public function boxIn(ReportQueryInterface $reportQuery, ARI $accountRepository)
{ {
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
@ -131,7 +131,7 @@ class JsonController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); $accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']);
$amount = $reportQuery->incomeInPeriod($start, $end, $accounts)->sum('to_amount'); $amount = $reportQuery->income($accounts, $start, $end)->sum('journalAmount');
$data = ['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]; $data = ['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$cache->store($data); $cache->store($data);
@ -140,13 +140,13 @@ class JsonController extends Controller
} }
/** /**
* @param ReportQueryInterface $reportQuery * @param ReportQueryInterface $reportQuery
* *
* @param AccountRepositoryInterface $accountRepository * @param ARI $accountRepository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function boxOut(ReportQueryInterface $reportQuery, AccountRepositoryInterface $accountRepository) public function boxOut(ReportQueryInterface $reportQuery, ARI $accountRepository)
{ {
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
@ -162,7 +162,7 @@ class JsonController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$amount = $reportQuery->expenseInPeriod($start, $end, $accounts)->sum('to_amount'); $amount = $reportQuery->expense($accounts, $start, $end)->sum('journalAmount');
$data = ['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]; $data = ['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$cache->store($data); $cache->store($data);
@ -173,13 +173,13 @@ class JsonController extends Controller
/** /**
* Returns a list of categories. * Returns a list of categories.
* *
* @param CategoryRepositoryInterface $repository * @param CRI $repository
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function categories(CategoryRepositoryInterface $repository) public function categories(CRI $repository)
{ {
$list = $repository->getCategories(); $list = $repository->listCategories();
$return = []; $return = [];
foreach ($list as $entry) { foreach ($list as $entry) {
$return[] = $entry->name; $return[] = $entry->name;
@ -191,11 +191,11 @@ class JsonController extends Controller
/** /**
* Returns a JSON list of all beneficiaries. * Returns a JSON list of all beneficiaries.
* *
* @param AccountRepositoryInterface $accountRepository * @param ARI $accountRepository
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function expenseAccounts(AccountRepositoryInterface $accountRepository) public function expenseAccounts(ARI $accountRepository)
{ {
$list = $accountRepository->getAccounts(['Expense account', 'Beneficiary account']); $list = $accountRepository->getAccounts(['Expense account', 'Beneficiary account']);
$return = []; $return = [];
@ -208,11 +208,11 @@ class JsonController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $accountRepository * @param ARI $accountRepository
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function revenueAccounts(AccountRepositoryInterface $accountRepository) public function revenueAccounts(ARI $accountRepository)
{ {
$list = $accountRepository->getAccounts(['Revenue account']); $list = $accountRepository->getAccounts(['Revenue account']);
$return = []; $return = [];

View File

@ -5,7 +5,7 @@ use Carbon\Carbon;
use Config; use Config;
use FireflyIII\Http\Requests\NewUserFormRequest; use FireflyIII\Http\Requests\NewUserFormRequest;
use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountMeta;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use Preferences; use Preferences;
use Session; use Session;
use View; use View;
@ -20,11 +20,11 @@ class NewUserController extends Controller
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @@return \Illuminate\Http\RedirectResponse|\Illuminate\View\View * @@return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/ */
public function index(AccountRepositoryInterface $repository) public function index(ARI $repository)
{ {
View::share('title', 'Welcome to Firefly!'); View::share('title', 'Welcome to Firefly!');
View::share('mainTitleIcon', 'fa-fire'); View::share('mainTitleIcon', 'fa-fire');
@ -42,12 +42,12 @@ class NewUserController extends Controller
} }
/** /**
* @param NewUserFormRequest $request * @param NewUserFormRequest $request
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function submit(NewUserFormRequest $request, AccountRepositoryInterface $repository) public function submit(NewUserFormRequest $request, ARI $repository)
{ {
// create normal asset account: // create normal asset account:
$assetAccount = [ $assetAccount = [

View File

@ -6,7 +6,7 @@ use Config;
use ExpandedForm; use ExpandedForm;
use FireflyIII\Http\Requests\PiggyBankFormRequest; use FireflyIII\Http\Requests\PiggyBankFormRequest;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Input; use Input;
@ -18,7 +18,6 @@ use View;
/** /**
* *
* @SuppressWarnings(PHPMD.TooManyMethods)
* *
* Class PiggyBankController * Class PiggyBankController
* *
@ -40,12 +39,12 @@ class PiggyBankController extends Controller
/** /**
* Add money to piggy bank * Add money to piggy bank
* *
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
* @return $this * @return $this
*/ */
public function add(AccountRepositoryInterface $repository, PiggyBank $piggyBank) public function add(ARI $repository, PiggyBank $piggyBank)
{ {
bcscale(2); bcscale(2);
$date = Session::get('end', Carbon::now()->endOfMonth()); $date = Session::get('end', Carbon::now()->endOfMonth());
@ -58,11 +57,11 @@ class PiggyBankController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return mixed * @return mixed
*/ */
public function create(AccountRepositoryInterface $repository) public function create(ARI $repository)
{ {
$periods = Config::get('firefly.piggy_bank_periods'); $periods = Config::get('firefly.piggy_bank_periods');
@ -116,12 +115,12 @@ class PiggyBankController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
* @return View * @return View
*/ */
public function edit(AccountRepositoryInterface $repository, PiggyBank $piggyBank) public function edit(ARI $repository, PiggyBank $piggyBank)
{ {
$periods = Config::get('firefly.piggy_bank_periods'); $periods = Config::get('firefly.piggy_bank_periods');
@ -157,12 +156,12 @@ class PiggyBankController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param PiggyBankRepositoryInterface $piggyRepository * @param PiggyBankRepositoryInterface $piggyRepository
* *
* @return View * @return View
*/ */
public function index(AccountRepositoryInterface $repository, PiggyBankRepositoryInterface $piggyRepository) public function index(ARI $repository, PiggyBankRepositoryInterface $piggyRepository)
{ {
/** @var Collection $piggyBanks */ /** @var Collection $piggyBanks */
$piggyBanks = $piggyRepository->getPiggyBanks(); $piggyBanks = $piggyRepository->getPiggyBanks();
@ -219,12 +218,12 @@ class PiggyBankController extends Controller
/** /**
* @param PiggyBankRepositoryInterface $repository * @param PiggyBankRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts * @param ARI $accounts
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function postAdd(PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts, PiggyBank $piggyBank) public function postAdd(PiggyBankRepositoryInterface $repository, ARI $accounts, PiggyBank $piggyBank)
{ {
bcscale(2); bcscale(2);
$amount = round(Input::get('amount'), 2); $amount = round(Input::get('amount'), 2);

View File

@ -1,7 +1,7 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Config; use Config;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use Input; use Input;
use Preferences; use Preferences;
use Session; use Session;
@ -26,11 +26,11 @@ class PreferencesController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return $this|\Illuminate\View\View * @return $this|\Illuminate\View\View
*/ */
public function index(AccountRepositoryInterface $repository) public function index(ARI $repository)
{ {
$accounts = $repository->getAccounts(['Default account', 'Asset account']); $accounts = $repository->getAccounts(['Default account', 'Asset account']);
$viewRangePref = Preferences::get('viewRange', '1M'); $viewRangePref = Preferences::get('viewRange', '1M');

View File

@ -3,7 +3,7 @@
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportHelperInterface; use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Session; use Session;
use View; use View;
@ -35,12 +35,12 @@ class ReportController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* *
* @return View * @return View
* @internal param ReportHelperInterface $helper * @internal param ReportHelperInterface $helper
*/ */
public function index(AccountRepositoryInterface $repository) public function index(ARI $repository)
{ {
$start = Session::get('first'); $start = Session::get('first');
$months = $this->helper->listOfMonths($start); $months = $this->helper->listOfMonths($start);
@ -66,21 +66,21 @@ class ReportController extends Controller
return view( return view(
'reports.index', compact( 'reports.index', compact(
'months', 'accounts', 'start', 'accountList', 'months', 'accounts', 'start', 'accountList',
'startOfMonth', 'endOfMonth', 'startOfYear', 'endOfYear' 'startOfMonth', 'endOfMonth', 'startOfYear', 'endOfYear'
) )
); );
} }
/** /**
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return View * @return View
*/ */
public function defaultYear($report_type, Carbon $start, Carbon $end, Collection $accounts) public function defaultYear($reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
$incomeTopLength = 8; $incomeTopLength = 8;
$expenseTopLength = 8; $expenseTopLength = 8;
@ -104,7 +104,7 @@ class ReportController extends Controller
return view( return view(
'reports.default.year', 'reports.default.year',
compact( compact(
'start', 'accountReport', 'incomes', 'report_type', 'accountIds', 'end', 'start', 'accountReport', 'incomes', 'reportType', 'accountIds', 'end',
'expenses', 'incomeTopLength', 'expenseTopLength' 'expenses', 'incomeTopLength', 'expenseTopLength'
) )
); );
@ -112,66 +112,65 @@ class ReportController extends Controller
/** /**
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return View * @return View
*/ */
public function defaultMonth($report_type, Carbon $start, Carbon $end, Collection $accounts) public function defaultMonth($reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
$incomeTopLength = 8; $incomeTopLength = 8;
$expenseTopLength = 8; $expenseTopLength = 8;
// get report stuff! // get report stuff!
$accountReport = $this->helper->getAccountReport($start, $end, $accounts); $accountReport = $this->helper->getAccountReport($start, $end, $accounts); // done (+2)
$incomes = $this->helper->getIncomeReport($start, $end, $accounts); $incomes = $this->helper->getIncomeReport($start, $end, $accounts); // done (+3)
$expenses = $this->helper->getExpenseReport($start, $end, $accounts); $expenses = $this->helper->getExpenseReport($start, $end, $accounts); // done (+1)
$budgets = $this->helper->getBudgetReport($start, $end, $accounts); $budgets = $this->helper->getBudgetReport($start, $end, $accounts); // done (+5)
$categories = $this->helper->getCategoryReport($start, $end, $accounts); $categories = $this->helper->getCategoryReport($start, $end, $accounts); // done (+1) (20)
$balance = $this->helper->getBalanceReport($start, $end, $accounts); $balance = $this->helper->getBalanceReport($start, $end, $accounts); // +566
$bills = $this->helper->getBillReport($start, $end, $accounts); $bills = $this->helper->getBillReport($start, $end, $accounts);
// and some id's, joined: // and some id's, joined:
$accountIds = []; $accountIds = join(',', $accounts->pluck('id')->toArray());
/** @var Account $account */
foreach ($accounts as $account) {
$accountIds[] = $account->id;
}
$accountIds = join(',', $accountIds);
// continue! // continue!
return view( return view(
'reports.default.month', 'reports.default.month',
compact( compact(
'start', 'end', 'report_type', 'start', 'end', 'reportType',
'accountReport', 'accountReport',
'incomes', 'incomeTopLength', 'incomes', 'incomeTopLength',
'expenses', 'expenseTopLength', 'expenses', 'expenseTopLength',
'budgets', 'balance', 'budgets', 'balance',
'categories', 'categories',
'bills', 'bills',
'accountIds', 'report_type' 'accountIds', 'reportType'
) )
); );
} }
/** /**
* @param $report_type * @param $reportType
* @param $start * @param $start
* @param $end * @param $end
* @param $accounts * @param $accounts
* *
* @return View * @return View
*/ */
public function defaultMultiYear($report_type, $start, $end, $accounts) public function defaultMultiYear($reportType, $start, $end, $accounts)
{ {
$incomeTopLength = 8;
$expenseTopLength = 8;
// list of users stuff: // list of users stuff:
$budgets = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface')->getActiveBudgets(); $budgets = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface')->getActiveBudgets();
$categories = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface')->getCategories(); $categories = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface')->listCategories();
$accountReport = $this->helper->getAccountReport($start, $end, $accounts); // done (+2)
$incomes = $this->helper->getIncomeReport($start, $end, $accounts); // done (+3)
$expenses = $this->helper->getExpenseReport($start, $end, $accounts); // done (+1)
// and some id's, joined: // and some id's, joined:
$accountIds = []; $accountIds = [];
@ -182,19 +181,23 @@ class ReportController extends Controller
$accountIds = join(',', $accountIds); $accountIds = join(',', $accountIds);
return view( return view(
'reports.default.multi-year', compact('budgets', 'accounts', 'categories', 'start', 'end', 'accountIds', 'report_type') 'reports.default.multi-year',
compact(
'budgets', 'accounts', 'categories', 'start', 'end', 'accountIds', 'reportType', 'accountReport', 'incomes', 'expenses',
'incomeTopLength', 'expenseTopLength'
)
); );
} }
/** /**
* @param $report_type * @param $reportType
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param Collection $accounts * @param Collection $accounts
* *
* @return View * @return View
*/ */
public function report($report_type, Carbon $start, Carbon $end, Collection $accounts) public function report($reportType, Carbon $start, Carbon $end, Collection $accounts)
{ {
// throw an error if necessary. // throw an error if necessary.
if ($end < $start) { if ($end < $start) {
@ -206,7 +209,7 @@ class ReportController extends Controller
$start = Session::get('first'); $start = Session::get('first');
} }
switch ($report_type) { switch ($reportType) {
default: default:
case 'default': case 'default':
@ -223,14 +226,14 @@ class ReportController extends Controller
// more than one year date difference means year report. // more than one year date difference means year report.
if ($start->diffInMonths($end) > 12) { if ($start->diffInMonths($end) > 12) {
return $this->defaultMultiYear($report_type, $start, $end, $accounts); return $this->defaultMultiYear($reportType, $start, $end, $accounts);
} }
// more than two months date difference means year report. // more than two months date difference means year report.
if ($start->diffInMonths($end) > 1) { if ($start->diffInMonths($end) > 1) {
return $this->defaultYear($report_type, $start, $end, $accounts); return $this->defaultYear($reportType, $start, $end, $accounts);
} }
return $this->defaultMonth($report_type, $start, $end, $accounts); return $this->defaultMonth($reportType, $start, $end, $accounts);
} }

View File

@ -14,7 +14,7 @@ use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Input; use Input;
@ -43,12 +43,12 @@ class TransactionController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param string $what * @param string $what
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function create(AccountRepositoryInterface $repository, $what = TransactionType::DEPOSIT) public function create(ARI $repository, $what = TransactionType::DEPOSIT)
{ {
$what = strtolower($what); $what = strtolower($what);
$maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize')); $maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize'));
@ -133,12 +133,12 @@ class TransactionController extends Controller
/** /**
* Shows the view to edit a transaction. * Shows the view to edit a transaction.
* *
* @param AccountRepositoryInterface $repository * @param ARI $repository
* @param TransactionJournal $journal * @param TransactionJournal $journal
* *
* @return $this * @return $this
*/ */
public function edit(AccountRepositoryInterface $repository, TransactionJournal $journal) public function edit(ARI $repository, TransactionJournal $journal)
{ {
// cannot edit opening balance // cannot edit opening balance
if ($journal->isOpeningBalance()) { if ($journal->isOpeningBalance()) {
@ -163,11 +163,7 @@ class TransactionController extends Controller
'piggy_bank_id' => 0 'piggy_bank_id' => 0
]; ];
// get tags: // get tags:
$tags = []; $preFilled['tags'] = join(',', $journal->tags->pluck('tag')->toArray());
foreach ($journal->tags as $tag) {
$tags[] = $tag->tag;
}
$preFilled['tags'] = join(',', $tags);
$category = $journal->categories()->first(); $category = $journal->categories()->first();
if (!is_null($category)) { if (!is_null($category)) {
@ -285,7 +281,7 @@ class TransactionController extends Controller
$what = strtolower($journal->getTransactionType()); $what = strtolower($journal->getTransactionType());
$subTitle = trans('firefly.' . $journal->getTransactionType()) . ' "' . e($journal->description) . '"'; $subTitle = trans('firefly.' . $journal->getTransactionType()) . ' "' . e($journal->description) . '"';
return view('transactions.show', compact('journal','events', 'subTitle', 'what')); return view('transactions.show', compact('journal', 'events', 'subTitle', 'what'));
} }
/** /**
@ -354,7 +350,6 @@ class TransactionController extends Controller
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att, TransactionJournal $journal) public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att, TransactionJournal $journal)
{ {
// cannot edit opening balance
if ($journal->isOpeningBalance()) { if ($journal->isOpeningBalance()) {
return view('error')->with('message', 'Cannot edit this transaction. Edit the account instead!'); return view('error')->with('message', 'Cannot edit this transaction. Edit the account instead!');
} }

View File

@ -54,8 +54,9 @@ class Authenticate
return redirect()->guest('auth/login'); return redirect()->guest('auth/login');
} }
} }
/** @var User $user */
if ($this->auth->user() instanceof User && intval($this->auth->user()->blocked) == 1) { $user = $this->auth->user();
if ($user instanceof User && intval($user->blocked) == 1) {
Auth::logout(); Auth::logout();
return redirect()->route('index'); return redirect()->route('index');

View File

@ -42,7 +42,6 @@ class Range
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $theNext * @param \Closure $theNext
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* *
* @return mixed * @return mixed
*/ */

View File

@ -51,7 +51,6 @@ class JournalFormRequest extends Request
/** /**
* @return array * @return array
* @throws Exception * @throws Exception
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/ */
public function rules() public function rules()
{ {

View File

@ -355,9 +355,9 @@ Breadcrumbs::register(
$breadcrumbs->parent('reports.index'); $breadcrumbs->parent('reports.index');
$monthFormat = trans('config.month_and_day'); $monthFormat = trans('config.month_and_day');
$title = trans('firefly.report_default', ['start' => $start->formatLocalized($monthFormat), 'end' => $end->formatLocalized($monthFormat)]); $title = trans('firefly.report_' . $reportType, ['start' => $start->formatLocalized($monthFormat), 'end' => $end->formatLocalized($monthFormat)]);
$breadcrumbs->push($title, route('reports.report', ['url' => 'abcde'])); $breadcrumbs->push($title, route('reports.report', [$reportType, $start->format('Ymd'), $end->format('Ymd'), $accountIds]));
} }
); );

View File

@ -264,7 +264,6 @@ Route::bind(
* Auth\AuthController * Auth\AuthController
*/ */
Route::get('/register', ['uses' => 'Auth\AuthController@getRegister', 'as' => 'register']); Route::get('/register', ['uses' => 'Auth\AuthController@getRegister', 'as' => 'register']);
Route::get('/cron/sendgrid', ['uses' => 'CronController@sendgrid']);
Route::controllers( Route::controllers(
[ [
@ -389,7 +388,7 @@ Route::group(
// accounts: // accounts:
Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']); Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']);
Route::get('/chart/account/expense', ['uses' => 'Chart\AccountController@expenseAccounts']); Route::get('/chart/account/expense', ['uses' => 'Chart\AccountController@expenseAccounts']);
Route::get('/chart/account/report/{report_type}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\AccountController@report']); Route::get('/chart/account/report/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\AccountController@report']);
Route::get('/chart/account/{account}', ['uses' => 'Chart\AccountController@single']); Route::get('/chart/account/{account}', ['uses' => 'Chart\AccountController@single']);
@ -401,8 +400,8 @@ Route::group(
Route::get('/chart/budget/frontpage', ['uses' => 'Chart\BudgetController@frontpage']); Route::get('/chart/budget/frontpage', ['uses' => 'Chart\BudgetController@frontpage']);
// this chart is used in reports: // this chart is used in reports:
Route::get('/chart/budget/year/{report_type}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\BudgetController@year']); Route::get('/chart/budget/year/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\BudgetController@year']);
Route::get('/chart/budget/multi-year/{report_type}/{start_date}/{end_date}/{accountList}/{budgetList}', ['uses' => 'Chart\BudgetController@multiYear']); Route::get('/chart/budget/multi-year/{reportType}/{start_date}/{end_date}/{accountList}/{budgetList}', ['uses' => 'Chart\BudgetController@multiYear']);
Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'Chart\BudgetController@budgetLimit']); Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'Chart\BudgetController@budgetLimit']);
Route::get('/chart/budget/{budget}', ['uses' => 'Chart\BudgetController@budget']); Route::get('/chart/budget/{budget}', ['uses' => 'Chart\BudgetController@budget']);
@ -411,10 +410,10 @@ Route::group(
Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']); Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']);
// these three charts are for reports: // these three charts are for reports:
Route::get('/chart/category/earned-in-period/{report_type}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\CategoryController@earnedInPeriod']); Route::get('/chart/category/earned-in-period/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\CategoryController@earnedInPeriod']);
Route::get('/chart/category/spent-in-period/{report_type}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\CategoryController@spentInPeriod']); Route::get('/chart/category/spent-in-period/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\CategoryController@spentInPeriod']);
Route::get( Route::get(
'/chart/category/multi-year/{report_type}/{start_date}/{end_date}/{accountList}/{categoryList}', ['uses' => 'Chart\CategoryController@multiYear'] '/chart/category/multi-year/{reportType}/{start_date}/{end_date}/{accountList}/{categoryList}', ['uses' => 'Chart\CategoryController@multiYear']
); );
Route::get('/chart/category/{category}/period', ['uses' => 'Chart\CategoryController@currentPeriod']); Route::get('/chart/category/{category}/period', ['uses' => 'Chart\CategoryController@currentPeriod']);
@ -422,11 +421,11 @@ Route::group(
Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']); Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']);
// piggy banks: // piggy banks:
Route::get('/chart/piggyBank/{piggyBank}', ['uses' => 'Chart\PiggyBankController@history']); Route::get('/chart/piggy-bank/{piggyBank}', ['uses' => 'Chart\PiggyBankController@history']);
// reports: // reports:
Route::get('/chart/report/in-out/{report_type}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\ReportController@yearInOut']); Route::get('/chart/report/in-out/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\ReportController@yearInOut']);
Route::get('/chart/report/in-out-sum/{report_type}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\ReportController@yearInOutSummarized']); Route::get('/chart/report/in-out-sum/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\ReportController@yearInOutSummarized']);
/** /**
@ -492,7 +491,7 @@ Route::group(
* Report Controller * Report Controller
*/ */
Route::get('/reports', ['uses' => 'ReportController@index', 'as' => 'reports.index']); Route::get('/reports', ['uses' => 'ReportController@index', 'as' => 'reports.index']);
Route::get('/reports/report/{report_type}/{start_date}/{end_date}/{accountList}', ['uses' => 'ReportController@report', 'as' => 'reports.report']); Route::get('/reports/report/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'ReportController@report', 'as' => 'reports.report']);
/** /**
* Search Controller * Search Controller

View File

@ -1,53 +1,38 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt; use Crypt;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Watson\Validating\ValidatingTrait; use Watson\Validating\ValidatingTrait;
/** /**
* Class Account * FireflyIII\Models\Account
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property integer $user_id
* @property integer $user_id * @property integer $account_type_id
* @property integer $account_type_id * @property string $name
* @property string $name * @property boolean $active
* @property boolean $active * @property boolean $encrypted
* @property boolean $encrypted * @property float $virtual_balance
* @property float $virtual_balance * @property string $iban
* @property string $iban * @property-read Collection|AccountMeta[] $accountMeta
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\AccountMeta[] $accountMeta * @property-read AccountType $accountType
* @property-read \FireflyIII\Models\AccountType $accountType * @property-read mixed $name_for_editform
* @property-read mixed $name_for_editform * @property-read Collection|PiggyBank[] $piggyBanks
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBank[] $piggyBanks * @property-read Collection|Transaction[] $transactions
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions * @property-read User $user
* @property-read \FireflyIII\User $user * @method static Builder|Account accountTypeIn($types)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereId($value) * @method static Builder|Account hasMetaValue($name, $value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereAccountTypeId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereActive($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereVirtualBalance($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereIban($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account accountTypeIn($types)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account hasMetaValue($name, $value)
* @property-read bool $joinedAccountTypes
* @property float $startBalance
* @property float $endBalance
* @property float $piggyBalance
* @property float $percentage
* @property float $difference
* @property \Carbon\Carbon $lastActivityDate
*/ */
class Account extends Model class Account extends Model
{ {
@ -65,7 +50,6 @@ class Account extends Model
/** /**
* @param array $fields * @param array $fields
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* *
* @return Account|null * @return Account|null
*/ */

View File

@ -1,25 +1,19 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait; use Watson\Validating\ValidatingTrait;
/** /**
* Class AccountMeta * FireflyIII\Models\AccountMeta
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property integer $account_id
* @property integer $account_id * @property string $name
* @property string $name * @property string $data
* @property string $data * @property-read Account $account
* @property-read \FireflyIII\Models\Account $account
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereAccountId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereData($value)
*/ */
class AccountMeta extends Model class AccountMeta extends Model
{ {

View File

@ -1,22 +1,18 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
* Class AccountType * FireflyIII\Models\AccountType
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property string $type
* @property string $type * @property boolean $editable
* @property boolean $editable * @property-read Collection|Account[] $accounts
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Account[] $accounts
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereType($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereEditable($value)
*/ */
class AccountType extends Model class AccountType extends Model
{ {
@ -33,6 +29,7 @@ class AccountType extends Model
/** /**
* @return array * @return array
*/ */
/** @noinspection PhpMissingParentCallCommonInspection */
public function getDates() public function getDates()
{ {
return ['created_at', 'updated_at']; return ['created_at', 'updated_at'];

View File

@ -2,46 +2,32 @@
namespace FireflyIII\Models; namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt; use Crypt;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class Attachment * FireflyIII\Models\Attachment
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property string $deleted_at
* @property string $deleted_at * @property integer $attachable_id
* @property integer $attachable_id * @property string $attachable_type
* @property string $attachable_type * @property integer $user_id
* @property integer $user_id * @property string $md5
* @property string $md5 * @property string $filename
* @property string $filename * @property string $title
* @property string $mime * @property string $description
* @property integer $size * @property string $notes
* @property boolean $uploaded * @property string $mime
* @property-read \ $attachable * @property integer $size
* @property-read \FireflyIII\User $user * @property boolean $uploaded
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereId($value) * @property-read Attachment $attachable
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereCreatedAt($value) * @property-read User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereAttachableId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereAttachableType($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereMd5($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereFilename($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereMime($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereSize($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUploaded($value)
* @property string $title
* @property string $description
* @property string $notes
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereTitle($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereNotes($value)
*/ */
class Attachment extends Model class Attachment extends Model
{ {

View File

@ -1,47 +1,31 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt; use Crypt;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
* Class Bill * FireflyIII\Models\Bill
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property integer $user_id
* @property integer $user_id * @property string $name
* @property string $name * @property string $match
* @property string $match * @property float $amount_min
* @property float $amount_min * @property float $amount_max
* @property float $amount_max * @property Carbon $date
* @property \Carbon\Carbon $date * @property boolean $active
* @property boolean $active * @property boolean $automatch
* @property boolean $automatch * @property string $repeat_freq
* @property string $repeat_freq * @property integer $skip
* @property integer $skip * @property boolean $name_encrypted
* @property boolean $name_encrypted * @property boolean $match_encrypted
* @property boolean $match_encrypted * @property-read Collection|TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals * @property-read User $user
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereMatch($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMin($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMax($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereDate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereActive($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAutomatch($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereRepeatFreq($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereSkip($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereNameEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereMatchEncrypted($value)
* @property \Carbon\Carbon $nextExpectedMatch
* @property \Carbon\Carbon $lastFoundMatch
* @property-read string $expectedAmount
*/ */
class Bill extends Model class Bill extends Model
{ {

View File

@ -1,32 +1,26 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt; use Crypt;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class Budget * FireflyIII\Models\Budget
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property string $name
* @property string $name * @property integer $user_id
* @property integer $user_id * @property boolean $active
* @property boolean $active * @property boolean $encrypted
* @property boolean $encrypted * @property-read Collection|BudgetLimit[] $budgetlimits
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\BudgetLimit[] $budgetlimits * @property-read Collection|TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals * @property-read User $user
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereActive($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereEncrypted($value)
*/ */
class Budget extends Model class Budget extends Model
{ {

View File

@ -1,29 +1,22 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
* Class BudgetLimit * FireflyIII\Models\BudgetLimit
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property integer $budget_id
* @property integer $budget_id * @property Carbon $startdate
* @property \Carbon\Carbon $startdate * @property float $amount
* @property float $amount * @property boolean $repeats
* @property boolean $repeats * @property string $repeat_freq
* @property string $repeat_freq * @property-read Budget $budget
* @property-read \FireflyIII\Models\Budget $budget * @property-read Collection|LimitRepetition[] $limitrepetitions
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\LimitRepetition[] $limitrepetitions
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereBudgetId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereAmount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereRepeats($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereRepeatFreq($value)
*/ */
class BudgetLimit extends Model class BudgetLimit extends Model
{ {

View File

@ -1,31 +1,24 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt; use Crypt;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class Category * FireflyIII\Models\Category
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property string $name
* @property string $name * @property integer $user_id
* @property integer $user_id * @property boolean $encrypted
* @property boolean $encrypted * @property-read Collection|TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals * @property-read User $user
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereEncrypted($value)
* @property-read float $spent
* @property \Carbon\Carbon $lastActivity
*/ */
class Category extends Model class Category extends Model
{ {
@ -36,7 +29,6 @@ class Category extends Model
/** /**
* @param array $fields * @param array $fields
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* *
* @return Category * @return Category
*/ */

View File

@ -1,26 +1,19 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class Component * FireflyIII\Models\Component
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property string $name
* @property string $name * @property integer $user_id
* @property integer $user_id * @property string $class
* @property string $class
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereClass($value)
*/ */
class Component extends Model class Component extends Model
{ {

View File

@ -1,26 +1,19 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
* Class LimitRepetition * FireflyIII\Models\LimitRepetition
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property integer $budget_limit_id
* @property integer $budget_limit_id * @property Carbon $startdate
* @property \Carbon\Carbon $startdate * @property Carbon $enddate
* @property \Carbon\Carbon $enddate * @property float $amount
* @property float $amount * @property-read BudgetLimit $budgetLimit
* @property-read \FireflyIII\Models\BudgetLimit $budgetLimit
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereBudgetLimitId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereAmount($value)
*/ */
class LimitRepetition extends Model class LimitRepetition extends Model
{ {

View File

@ -2,25 +2,20 @@
namespace FireflyIII\Models; namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Zizaco\Entrust\EntrustPermission; use Zizaco\Entrust\EntrustPermission;
/** /**
* Class Permission * FireflyIII\Models\Permission
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property string $name
* @property string $name * @property string $display_name
* @property string $display_name * @property string $description
* @property string $description * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property-read Collection|Role[] $roles
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.role[] $roles
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereDisplayName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereUpdatedAt($value)
*/ */
class Permission extends EntrustPermission class Permission extends EntrustPermission
{ {

View File

@ -1,45 +1,30 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt; use Crypt;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class PiggyBank * FireflyIII\Models\PiggyBank
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property integer $account_id
* @property integer $account_id * @property string $name
* @property string $name * @property float $targetamount
* @property float $targetamount * @property Carbon $startdate
* @property \Carbon\Carbon $startdate * @property Carbon $targetdate
* @property \Carbon\Carbon $targetdate * @property integer $order
* @property integer $order * @property boolean $encrypted
* @property boolean $encrypted * @property boolean $remind_me
* @property boolean $remind_me * @property integer $reminder_skip
* @property integer $reminder_skip * @property-read Account $account
* @property-read \FireflyIII\Models\Account $account * @property-read Collection|PiggyBankRepetition[] $piggyBankRepetitions
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankRepetition[] $piggyBankRepetitions * @property-read Collection|PiggyBankEvent[] $piggyBankEvents
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereAccountId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereOrder($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereRemindMe($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminderSkip($value)
* @property-read \FireflyIII\Models\PiggyBankRepetition $currentRep
* @property string $reminder
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminder($value)
*/ */
class PiggyBank extends Model class PiggyBank extends Model
{ {

View File

@ -1,27 +1,20 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
* Class PiggyBankEvent * FireflyIII\Models\PiggyBankEvent
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property integer $piggy_bank_id
* @property integer $piggy_bank_id * @property integer $transaction_journal_id
* @property integer $transaction_journal_id * @property Carbon $date
* @property \Carbon\Carbon $date * @property float $amount
* @property float $amount * @property PiggyBank $piggyBank
* @property \FireflyIII\Models\PiggyBank $piggyBank * @property-read TransactionJournal $transactionJournal
* @property-read \FireflyIII\Models\TransactionJournal $transactionJournal
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent wherePiggyBankId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereTransactionJournalId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereDate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereAmount($value)
*/ */
class PiggyBankEvent extends Model class PiggyBankEvent extends Model
{ {
@ -32,6 +25,7 @@ class PiggyBankEvent extends Model
/** /**
* @return array * @return array
*/ */
/** @noinspection PhpMissingParentCallCommonInspection */
public function getDates() public function getDates()
{ {
return ['created_at', 'updated_at', 'date']; return ['created_at', 'updated_at', 'date'];

View File

@ -3,28 +3,21 @@
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Query\Builder;
/** /**
* Class PiggyBankRepetition * FireflyIII\Models\PiggyBankRepetition
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property integer $piggy_bank_id
* @property integer $piggy_bank_id * @property Carbon $startdate
* @property \Carbon\Carbon $startdate * @property Carbon $targetdate
* @property \Carbon\Carbon $targetdate * @property float $currentamount
* @property float $currentamount * @property-read PiggyBank $piggyBank
* @property-read \FireflyIII\Models\PiggyBank $piggyBank * @method static Builder|PiggyBankRepetition onDates($start, $target)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereId($value) * @method static Builder|PiggyBankRepetition relevantOnDate($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition wherePiggyBankId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereTargetdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCurrentamount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition onDates($start, $target)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition relevantOnDate($date)
*/ */
class PiggyBankRepetition extends Model class PiggyBankRepetition extends Model
{ {

View File

@ -1,29 +1,22 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt; use Crypt;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
* Class Preference * FireflyIII\Models\Preference
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property integer $user_id
* @property integer $user_id * @property string $name
* @property string $name * @property string $name_encrypted
* @property string $name_encrypted * @property string $data
* @property string $data * @property string $data_encrypted
* @property string $data_encrypted * @property-read User $user
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereNameEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereData($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereDataEncrypted($value)
*/ */
class Preference extends Model class Preference extends Model
{ {

View File

@ -2,26 +2,21 @@
namespace FireflyIII\Models; namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Zizaco\Entrust\EntrustRole; use Zizaco\Entrust\EntrustRole;
/** /**
* Class Role * FireflyIII\Models\Role
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property string $name
* @property string $name * @property string $display_name
* @property string $display_name * @property string $description
* @property string $description * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property-read Collection|\FireflyIII\User[] $users
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('auth.model[] $users * @property-read Collection|Permission[] $perms
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.permission[] $perms
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereDisplayName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereUpdatedAt($value)
*/ */
class Role extends EntrustRole class Role extends EntrustRole
{ {

View File

@ -2,40 +2,30 @@
namespace FireflyIII\Models; namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt; use Crypt;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait; use Watson\Validating\ValidatingTrait;
/** /**
* Class Tag * FireflyIII\Models\Tag
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property string $deleted_at
* @property string $deleted_at * @property integer $user_id
* @property integer $user_id * @property string $tag
* @property string $tag * @property string $tagMode
* @property string $tagMode * @property Carbon $date
* @property \Carbon\Carbon $date * @property string $description
* @property string $description * @property float $latitude
* @property float $latitude * @property float $longitude
* @property float $longitude * @property integer $zoomLevel
* @property integer $zoomLevel * @property-read Collection|TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals * @property-read User $user
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereTag($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereTagMode($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereLatitude($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereLongitude($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereZoomLevel($value)
*/ */
class Tag extends Model class Tag extends Model
{ {
@ -54,8 +44,6 @@ class Tag extends Model
/** /**
* @param array $fields * @param array $fields
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* *
* @return Tag|null * @return Tag|null
*/ */

View File

@ -4,34 +4,24 @@ use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder;
use Watson\Validating\ValidatingTrait; use Watson\Validating\ValidatingTrait;
/** /**
* Class Transaction * FireflyIII\Models\Transaction
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property integer $account_id
* @property integer $account_id * @property integer $transaction_journal_id
* @property integer $transaction_journal_id * @property string $description
* @property string $description * @property float $amount
* @property float $amount * @property-read Account $account
* @property-read \FireflyIII\Models\Account $account * @property-read TransactionJournal $transactionJournal
* @property-read \FireflyIII\Models\TransactionJournal $transactionJournal * @method static Builder|Transaction after($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereId($value) * @method static Builder|Transaction before($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAccountId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereTransactionJournalId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAmount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction after($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction before($date)
* @property float $before
* @property float $after
*/ */
class Transaction extends Model class Transaction extends Model
{ {

View File

@ -1,27 +1,21 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class TransactionCurrency * FireflyIII\Models\TransactionCurrency
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property string $code
* @property string $code * @property string $name
* @property string $name * @property string $symbol
* @property string $symbol * @property-read Collection|TransactionJournal[] $transactionJournals
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionJournals
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereCode($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereName($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereSymbol($value)
*/ */
class TransactionCurrency extends Model class TransactionCurrency extends Model
{ {

View File

@ -1,26 +1,22 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class TransactionGroup * FireflyIII\Models\TransactionGroup
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property integer $user_id
* @property integer $user_id * @property string $relation
* @property string $relation * @property-read Collection|TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals * @property-read User $user
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereRelation($value)
*/ */
class TransactionGroup extends Model class TransactionGroup extends Model
{ {

View File

@ -3,74 +3,53 @@
use Carbon\Carbon; use Carbon\Carbon;
use Crypt; use Crypt;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder;
use Watson\Validating\ValidatingTrait; use Watson\Validating\ValidatingTrait;
/** /**
* Class TransactionJournal * FireflyIII\Models\TransactionJournal
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property integer $user_id
* @property integer $user_id * @property integer $transaction_type_id
* @property integer $transaction_type_id * @property integer $bill_id
* @property integer $bill_id * @property integer $transaction_currency_id
* @property integer $transaction_currency_id * @property string $description
* @property string $description * @property boolean $completed
* @property boolean $completed * @property Carbon $date
* @property \Carbon\Carbon $date * @property boolean $encrypted
* @property boolean $encrypted * @property integer $order
* @property integer $order * @property integer $tag_count
* @property integer $tag_count * @property-read Bill $bill
* @property-read \FireflyIII\Models\Bill $bill * @property-read Collection|Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets * @property-read Collection|Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $categories * @property-read mixed $amount_positive
* @property-read mixed $actual_amount * @property-read mixed $amount
* @property-read mixed $amount * @property-read Collection|Tag[] $tags
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Tag[] $tags * @property-read Collection|Transaction[] $transactions
* @property-read mixed $correct_amount * @property-read mixed $destination_account
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions * @property-read mixed $source_account
* @property-read mixed $destination_account * @property-read Collection|PiggyBankEvent[] $piggyBankEvents
* @property-read mixed $source_account * @property-read Collection|Attachment[] $attachments
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents * @property-read TransactionCurrency $transactionCurrency
* @property-read \FireflyIII\Models\TransactionCurrency $transactionCurrency * @property-read TransactionType $transactionType
* @property-read \FireflyIII\Models\TransactionType $transactionType * @property-read Collection|TransactionGroup[] $transactiongroups
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionGroup[] $transactiongroups * @property-read User $user
* @property-read \FireflyIII\User $user * @method static Builder|TransactionJournal accountIs($account)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereId($value) * @method static Builder|TransactionJournal after($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereCreatedAt($value) * @method static Builder|TransactionJournal before($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereUpdatedAt($value) * @method static Builder|TransactionJournal onDate($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDeletedAt($value) * @method static Builder|TransactionJournal transactionTypes($types)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereUserId($value) * @method static Builder|TransactionJournal withRelevantData()
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTransactionTypeId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereBillId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTransactionCurrencyId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereCompleted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereOrder($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTagCount($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal accountIs($account)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal after($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal before($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal onDate($date)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal transactionTypes($types)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal withRelevantData()
* @property-read bool $account_encrypted
* @property-read bool $joinedTransactions
* @property-read bool $joinedTransactionTypes
* @property-read int $account_id
* @property string $name
* @property-read string $symbol
* @property-read string $type
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Attachment[] $attachments
* @property-read mixed $amount_positive
*/ */
class TransactionJournal extends Model class TransactionJournal extends Model
{ {

View File

@ -1,21 +0,0 @@
<?php namespace FireflyIII\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Class TransactionRelation
*
* @package FireflyIII\Models
*/
class TransactionRelation extends Model
{
/**
* @return array
*/
public function getDates()
{
return ['created_at', 'updated_at'];
}
}

View File

@ -1,23 +1,19 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class TransactionType * FireflyIII\Models\TransactionType
* *
* @package FireflyIII\Models * @property integer $id
* @property integer $id * @property Carbon $created_at
* @property \Carbon\Carbon $created_at * @property Carbon $updated_at
* @property \Carbon\Carbon $updated_at * @property Carbon $deleted_at
* @property \Carbon\Carbon $deleted_at * @property string $type
* @property string $type * @property-read Collection|TransactionJournal[] $transactionJournals
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionJournals
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereType($value)
*/ */
class TransactionType extends Model class TransactionType extends Model
{ {

View File

@ -19,7 +19,6 @@ class ConfigServiceProvider extends ServiceProvider
* to overwrite any "vendor" or package configuration that you may want to * to overwrite any "vendor" or package configuration that you may want to
* modify before the application handles the incoming request / command. * modify before the application handles the incoming request / command.
* *
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* *
* @return void * @return void
*/ */

View File

@ -47,7 +47,7 @@ class FireflyServiceProvider extends ServiceProvider
} }
/** /**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) *
*/ */
public function register() public function register()
{ {
@ -83,6 +83,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind('FireflyIII\Repositories\Account\AccountRepositoryInterface', 'FireflyIII\Repositories\Account\AccountRepository'); $this->app->bind('FireflyIII\Repositories\Account\AccountRepositoryInterface', 'FireflyIII\Repositories\Account\AccountRepository');
$this->app->bind('FireflyIII\Repositories\Budget\BudgetRepositoryInterface', 'FireflyIII\Repositories\Budget\BudgetRepository'); $this->app->bind('FireflyIII\Repositories\Budget\BudgetRepositoryInterface', 'FireflyIII\Repositories\Budget\BudgetRepository');
$this->app->bind('FireflyIII\Repositories\Category\CategoryRepositoryInterface', 'FireflyIII\Repositories\Category\CategoryRepository'); $this->app->bind('FireflyIII\Repositories\Category\CategoryRepositoryInterface', 'FireflyIII\Repositories\Category\CategoryRepository');
$this->app->bind('FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface', 'FireflyIII\Repositories\Category\SingleCategoryRepository');
$this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository'); $this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository');
$this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository'); $this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository');
$this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository'); $this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository');

View File

@ -39,6 +39,8 @@ class RouteServiceProvider extends ServiceProvider
* *
* @param \Illuminate\Routing\Router $router * @param \Illuminate\Routing\Router $router
* *
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return void * @return void
*/ */
public function map(Router $router) public function map(Router $router)

View File

@ -14,7 +14,6 @@ use FireflyIII\Models\Preference;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Support\CacheProperties;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -24,7 +23,6 @@ use Steam;
/** /**
* @SuppressWarnings(PHPMD.TooManyMethods)
* *
* Class AccountRepository * Class AccountRepository
* *
@ -40,14 +38,7 @@ class AccountRepository implements AccountRepositoryInterface
*/ */
public function countAccounts(array $types) public function countAccounts(array $types)
{ {
$cache = new CacheProperties;
$cache->addProperty('user-count-accounts');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$count = Auth::user()->accounts()->accountTypeIn($types)->count(); $count = Auth::user()->accounts()->accountTypeIn($types)->count();
$cache->store($count);
return $count; return $count;
} }
@ -77,14 +68,6 @@ class AccountRepository implements AccountRepositoryInterface
*/ */
public function getAccounts(array $types) public function getAccounts(array $types)
{ {
$cache = new CacheProperties();
$cache->addProperty('get-accounts');
$cache->addProperty($types);
if ($cache->has()) {
return $cache->get();
}
/** @var Collection $result */ /** @var Collection $result */
$result = Auth::user()->accounts()->with( $result = Auth::user()->accounts()->with(
['accountmeta' => function (HasMany $query) { ['accountmeta' => function (HasMany $query) {
@ -97,9 +80,6 @@ class AccountRepository implements AccountRepositoryInterface
return strtolower($account->name); return strtolower($account->name);
} }
); );
$cache->store($result);
return $result; return $result;
} }
@ -117,12 +97,6 @@ class AccountRepository implements AccountRepositoryInterface
*/ */
public function getCreditCards(Carbon $date) public function getCreditCards(Carbon $date)
{ {
$cache = new CacheProperties();
$cache->addProperty('user-credit-cards');
if ($cache->has()) {
return $cache->get();
}
$set = Auth::user()->accounts() $set = Auth::user()->accounts()
->hasMetaValue('accountRole', 'ccAsset') ->hasMetaValue('accountRole', 'ccAsset')
->hasMetaValue('ccType', 'monthlyFull') ->hasMetaValue('ccType', 'monthlyFull')
@ -139,8 +113,6 @@ class AccountRepository implements AccountRepositoryInterface
DB::Raw('SUM(`transactions`.`amount`) AS `balance`') DB::Raw('SUM(`transactions`.`amount`) AS `balance`')
] ]
); );
$cache->store($set);
return $set; return $set;
} }
@ -152,16 +124,7 @@ class AccountRepository implements AccountRepositoryInterface
*/ */
public function getFirstTransaction(TransactionJournal $journal, Account $account) public function getFirstTransaction(TransactionJournal $journal, Account $account)
{ {
$cache = new CacheProperties();
$cache->addProperty('first-transaction');
$cache->addProperty($journal->id);
$cache->addProperty($account->id);
if ($cache->has()) {
return $cache->get();
}
$transaction = $journal->transactions()->where('account_id', $account->id)->first(); $transaction = $journal->transactions()->where('account_id', $account->id)->first();
$cache->store($transaction);
return $transaction; return $transaction;
} }
@ -173,11 +136,6 @@ class AccountRepository implements AccountRepositoryInterface
*/ */
public function getFrontpageAccounts(Preference $preference) public function getFrontpageAccounts(Preference $preference)
{ {
$cache = new CacheProperties();
$cache->addProperty('user-frontpage-accounts');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$query = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account']); $query = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account']);
if (count($preference->data) > 0) { if (count($preference->data) > 0) {
@ -185,9 +143,6 @@ class AccountRepository implements AccountRepositoryInterface
} }
$result = $query->get(['accounts.*']); $result = $query->get(['accounts.*']);
$cache->store($result);
return $result; return $result;
} }
@ -204,15 +159,6 @@ class AccountRepository implements AccountRepositoryInterface
*/ */
public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end) public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end)
{ {
$cache = new CacheProperties();
$cache->addProperty($account->id);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('frontpage-transactions');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$set = Auth::user() $set = Auth::user()
->transactionjournals() ->transactionjournals()
->with(['transactions']) ->with(['transactions'])
@ -227,8 +173,6 @@ class AccountRepository implements AccountRepositoryInterface
->orderBy('transaction_journals.id', 'DESC') ->orderBy('transaction_journals.id', 'DESC')
->take(10) ->take(10)
->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']); ->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']);
$cache->store($set);
return $set; return $set;
} }
@ -266,24 +210,12 @@ class AccountRepository implements AccountRepositoryInterface
*/ */
public function getPiggyBankAccounts() public function getPiggyBankAccounts()
{ {
$ids = [];
$start = clone Session::get('start', new Carbon); $start = clone Session::get('start', new Carbon);
$end = clone Session::get('end', new Carbon); $end = clone Session::get('end', new Carbon);
$accountIds = DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']); $collection = new Collection(DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']));
$ids = $collection->pluck('account_id')->toArray();
$accounts = new Collection; $accounts = new Collection;
/** @var PiggyBank $id */
foreach ($accountIds as $id) {
$ids[] = intval($id->account_id);
}
$cache = new CacheProperties;
$cache->addProperty($ids);
$cache->addProperty('user-piggy-bank-accounts');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$ids = array_unique($ids); $ids = array_unique($ids);
if (count($ids) > 0) { if (count($ids) > 0) {
$accounts = Auth::user()->accounts()->whereIn('id', $ids)->where('accounts.active', 1)->get(); $accounts = Auth::user()->accounts()->whereIn('id', $ids)->where('accounts.active', 1)->get();
@ -309,8 +241,6 @@ class AccountRepository implements AccountRepositoryInterface
} }
); );
$cache->store($accounts);
return $accounts; return $accounts;
} }
@ -387,21 +317,12 @@ class AccountRepository implements AccountRepositoryInterface
*/ */
public function openingBalanceTransaction(Account $account) public function openingBalanceTransaction(Account $account)
{ {
$cache = new CacheProperties;
$cache->addProperty($account->id);
$cache->addProperty('opening-balance-journal');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$journal = TransactionJournal $journal = TransactionJournal
::orderBy('transaction_journals.date', 'ASC') ::orderBy('transaction_journals.date', 'ASC')
->accountIs($account) ->accountIs($account)
->transactionTypes([TransactionType::OPENING_BALANCE]) ->transactionTypes([TransactionType::OPENING_BALANCE])
->orderBy('created_at', 'ASC') ->orderBy('created_at', 'ASC')
->first(['transaction_journals.*']); ->first(['transaction_journals.*']);
$cache->store($journal);
return $journal; return $journal;
} }
@ -614,7 +535,6 @@ class AccountRepository implements AccountRepositoryInterface
* @param Account $account * @param Account $account
* @param array $data * @param array $data
* *
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/ */
protected function updateMetadata(Account $account, array $data) protected function updateMetadata(Account $account, array $data)
{ {

View File

@ -44,7 +44,7 @@ interface AccountRepositoryInterface
/** /**
* @param array $types * @param array $types
* *
* @return mixed * @return Collection
*/ */
public function getAccounts(array $types); public function getAccounts(array $types);

View File

@ -7,11 +7,9 @@ use Carbon\Carbon;
use DB; use DB;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Database\Query\Builder; use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -36,6 +34,40 @@ class BillRepository implements BillRepositoryInterface
return $bill->delete(); return $bill->delete();
} }
/**
* Returns all journals connected to these bills in the given range. Amount paid
* is stored in "journalAmount" as a negative number.
*
* @param Collection $bills
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getAllJournalsInRange(Collection $bills, Carbon $start, Carbon $end)
{
$ids = $bills->pluck('id')->toArray();
$set = Auth::user()->transactionjournals()
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
}
)
->whereIn('bill_id', $ids)
->before($end)
->after($start)
->groupBy('transaction_journals.bill_id')
->get(
[
'transaction_journals.bill_id',
DB::Raw('SUM(`transactions`.`amount`) as `journalAmount`')
]
);
return $set;
}
/** /**
* @return Collection * @return Collection
@ -64,26 +96,22 @@ class BillRepository implements BillRepositoryInterface
*/ */
public function getBillsForAccounts(Collection $accounts) public function getBillsForAccounts(Collection $accounts)
{ {
/** @var Collection $set */ $ids = $accounts->pluck('id')->toArray();
$set = Auth::user()->bills()->orderBy('name', 'ASC')->get(); $set = Auth::user()->bills()
->leftJoin(
$ids = []; 'transaction_journals', function (JoinClause $join) {
/** @var Account $account */ $join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at');
foreach ($accounts as $account) { }
$ids[] = $account->id; )
} ->leftJoin(
'transactions', function (JoinClause $join) {
$set = $set->filter( $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
function (Bill $bill) use ($ids) { }
// get transaction journals from or to any of the mentioned accounts. )
// when zero, return null. ->whereIn('transactions.account_id', $ids)
$journals = $bill->transactionjournals()->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->whereNull('transaction_journals.deleted_at')
->whereIn('transactions.account_id', $ids)->count(); ->groupBy('bills.id')
->get(['bills.*']);
return ($journals > 0);
}
);
$set = $set->sortBy( $set = $set->sortBy(
function (Bill $bill) { function (Bill $bill) {
@ -107,13 +135,6 @@ class BillRepository implements BillRepositoryInterface
*/ */
public function getJournals(Bill $bill) public function getJournals(Bill $bill)
{ {
$cache = new CacheProperties;
$cache->addProperty($bill->id);
$cache->addProperty('journals-for-bill');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$set = $bill->transactionjournals() $set = $bill->transactionjournals()
->leftJoin( ->leftJoin(
'transactions', function (JoinClause $join) { 'transactions', function (JoinClause $join) {
@ -125,8 +146,6 @@ class BillRepository implements BillRepositoryInterface
->orderBy('transaction_journals.order', 'ASC') ->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC') ->orderBy('transaction_journals.id', 'DESC')
->get(['transaction_journals.*', 'transactions.amount as journalAmount']); ->get(['transaction_journals.*', 'transactions.amount as journalAmount']);
$cache->store($set);
return $set; return $set;
} }
@ -156,12 +175,8 @@ class BillRepository implements BillRepositoryInterface
$set = DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get( $set = DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get(
['transaction_journal_id'] ['transaction_journal_id']
); );
$ids = []; $ids = $set->pluck('transaction_journal_id')->toArray();
/** @var Transaction $entry */
foreach ($set as $entry) {
$ids[] = intval($entry->transaction_journal_id);
}
$journals = new Collection; $journals = new Collection;
if (count($ids) > 0) { if (count($ids) > 0) {
$journals = Auth::user()->transactionjournals()->transactionTypes([TransactionType::WITHDRAWAL])->whereIn('transaction_journals.id', $ids)->get( $journals = Auth::user()->transactionjournals()->transactionTypes([TransactionType::WITHDRAWAL])->whereIn('transaction_journals.id', $ids)->get(
@ -425,13 +440,6 @@ class BillRepository implements BillRepositoryInterface
*/ */
public function getBillsPaidInRange(Carbon $start, Carbon $end) public function getBillsPaidInRange(Carbon $start, Carbon $end)
{ {
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('bills-paid-in-range');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$amount = '0'; $amount = '0';
$bills = $this->getActiveBills(); $bills = $this->getActiveBills();
@ -452,8 +460,6 @@ class BillRepository implements BillRepositoryInterface
$amount = bcadd($amount, $paid->sum_amount); $amount = bcadd($amount, $paid->sum_amount);
} }
} }
$cache->store($amount);
return $amount; return $amount;
} }
@ -486,13 +492,6 @@ class BillRepository implements BillRepositoryInterface
*/ */
public function getBillsUnpaidInRange(Carbon $start, Carbon $end) public function getBillsUnpaidInRange(Carbon $start, Carbon $end)
{ {
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('bills-unpaid-in-range');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$amount = '0'; $amount = '0';
$bills = $this->getActiveBills(); $bills = $this->getActiveBills();
@ -516,8 +515,6 @@ class BillRepository implements BillRepositoryInterface
$amount = bcadd($amount, $bill->expectedAmount); $amount = bcadd($amount, $bill->expectedAmount);
} }
} }
$cache->store($amount);
return $amount; return $amount;
} }
@ -533,13 +530,6 @@ class BillRepository implements BillRepositoryInterface
public function getCreditCardBill(Carbon $start, Carbon $end) public function getCreditCardBill(Carbon $start, Carbon $end)
{ {
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('credit-card-bill');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
/** @var AccountRepositoryInterface $accountRepository */ /** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); $accountRepository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
$amount = '0'; $amount = '0';

View File

@ -59,6 +59,19 @@ interface BillRepositoryInterface
*/ */
public function destroy(Bill $bill); public function destroy(Bill $bill);
/**
* Returns all journals connected to these bills in the given range. Amount paid
* is stored in "journalAmount" as a negative number.
*
* @param Collection $bills
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getAllJournalsInRange(Collection $bills, Carbon $start, Carbon $end);
/** /**
* @return Collection * @return Collection
*/ */

View File

@ -10,7 +10,6 @@ use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Shared\ComponentRepository; use FireflyIII\Repositories\Shared\ComponentRepository;
use FireflyIII\Support\CacheProperties;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
@ -36,6 +35,67 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
} }
/**
* 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
*
* @return Collection
*/
public function getExpensesPerDay(Budget $budget, Carbon $start, Carbon $end)
{
$set = Auth::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')
->get(['transaction_journals.date', DB::Raw('SUM(`transactions`.`amount`) as `dailyAmount`')]);
return $set;
}
/**
* Returns the expenses for this budget grouped per month, with the date
* in "dateFormatted" (a string, not a Carbon) and the amount in "dailyAmount".
*
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getExpensesPerMonth(Budget $budget, Carbon $start, Carbon $end)
{
$set = Auth::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'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->whereNull('transaction_journals.deleted_at')
->where('budgets.id', $budget->id)
->where('transactions.amount', '<', 0)
->groupBy('dateFormatted')
->orderBy('transaction_journals.date')
->get(
[
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y-%m") AS `dateFormatted`'),
DB::Raw('SUM(`transactions`.`amount`) as `monthlyAmount`')
]
);
return $set;
}
/** /**
* @param Budget $budget * @param Budget $budget
* *
@ -48,20 +108,6 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
return true; return true;
} }
/**
* @param Budget $budget
* @param Carbon $date
*
* @return float
*/
public function expensesOnDay(Budget $budget, Carbon $date)
{
bcscale(2);
$sum = $budget->transactionjournals()->transactionTypes([TransactionType::WITHDRAWAL])->onDate($date)->get(['transaction_journals.*'])->sum('amount');
return $sum;
}
/** /**
* @return Collection * @return Collection
*/ */
@ -125,30 +171,68 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
/** /**
* @param Budget $budget * @param Budget $budget
*
* @return Carbon
*/
public function firstActivity(Budget $budget)
{
$first = $budget->transactionjournals()->orderBy('date', 'ASC')->first();
if ($first) {
return $first->date;
}
return new Carbon;
}
/**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* *
* @return Collection * @return Collection
*/ */
public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end) public function getAllBudgetLimitRepetitions(Carbon $start, Carbon $end)
{ {
/** @var Collection $repetitions */ /** @var Collection $repetitions */
return LimitRepetition:: return LimitRepetition::
leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00')) ->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00'))
->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00')) ->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00'))
->where('budget_limits.budget_id', $budget->id) ->where('budgets.user_id', Auth::user()->id)
->get(['limit_repetitions.*']); ->get(['limit_repetitions.*', 'budget_limits.budget_id']);
} }
/** /**
* @param Budget $budget * Returns an array with the following key:value pairs:
* *
* @return Collection * yyyy-mm-dd:<amount>
*
* Where yyyy-mm-dd is the date and <amount> is the money spent using DEPOSITS in the $budget
* from all the users accounts.
*
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/ */
public function getBudgetLimits(Budget $budget) public function spentPerDay(Budget $budget, Carbon $start, Carbon $end)
{ {
return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get(); /** @var Collection $query */
$query = $budget->transactionJournals()
->transactionTypes([TransactionType::WITHDRAWAL])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.amount', '<', 0)
->before($end)
->after($start)
->groupBy('dateFormatted')->get(['transaction_journals.date as dateFormatted', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
$return = [];
foreach ($query->toArray() as $entry) {
$return[$entry['dateFormatted']] = $entry['sum'];
}
return $return;
} }
/** /**
@ -177,21 +261,10 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
*/ */
public function getCurrentRepetition(Budget $budget, Carbon $start, Carbon $end) public function getCurrentRepetition(Budget $budget, Carbon $start, Carbon $end)
{ {
$cache = new CacheProperties;
$cache->addProperty($budget->id);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('getCurrentRepetition');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$data = $budget->limitrepetitions() $data = $budget->limitrepetitions()
->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00')) ->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00'))
->where('limit_repetitions.enddate', $end->format('Y-m-d 00:00:00')) ->where('limit_repetitions.enddate', $end->format('Y-m-d 00:00:00'))
->first(['limit_repetitions.*']); ->first(['limit_repetitions.*']);
$cache->store($data);
return $data; return $data;
} }
@ -210,6 +283,64 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
return Carbon::now()->startOfYear(); return Carbon::now()->startOfYear();
} }
/**
* Returns an array with every budget in it and the expenses for each budget
* per month.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function getBudgetsAndExpensesPerMonth(Collection $accounts, Carbon $start, Carbon $end)
{
$ids = $accounts->pluck('id')->toArray();
/** @var Collection $set */
$set = Auth::user()->budgets()
->leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.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)
->get(
[
'budgets.*',
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y-%m") AS `dateFormatted`'),
DB::Raw('SUM(`transactions`.`amount`) AS `sumAmount`')
]
);
$set = $set->sortBy(
function (Budget $budget) {
return strtolower($budget->name);
}
);
$return = [];
foreach ($set as $budget) {
$id = $budget->id;
if (!isset($return[$id])) {
$return[$id] = [
'budget' => $budget,
'entries' => [],
];
}
// store each entry:
$return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount;
}
return $return;
}
/** /**
* @return Collection * @return Collection
*/ */
@ -238,17 +369,6 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
*/ */
public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50) public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50)
{ {
$cache = new CacheProperties;
$cache->addProperty($budget->id);
if ($repetition) {
$cache->addProperty($repetition->id);
}
$cache->addProperty($take);
$cache->addProperty('getJournals');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$offset = intval(Input::get('page')) > 0 ? intval(Input::get('page')) * $take : 0; $offset = intval(Input::get('page')) > 0 ? intval(Input::get('page')) * $take : 0;
$setQuery = $budget->transactionJournals()->withRelevantData()->take($take)->offset($offset) $setQuery = $budget->transactionJournals()->withRelevantData()->take($take)->offset($offset)
->orderBy('transaction_journals.date', 'DESC') ->orderBy('transaction_journals.date', 'DESC')
@ -268,50 +388,10 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
$paginator = new LengthAwarePaginator($set, $count, $take, $offset); $paginator = new LengthAwarePaginator($set, $count, $take, $offset);
$cache->store($paginator);
return $paginator; return $paginator;
} }
/**
* @deprecated
*
* @param Budget $budget
*
* @return Carbon
*/
public function getLastBudgetLimitDate(Budget $budget)
{
$limit = $budget->budgetlimits()->orderBy('startdate', 'DESC')->first();
if ($limit) {
return $limit->startdate;
}
return Carbon::now()->startOfYear();
}
/**
* @deprecated
*
* @param Budget $budget
* @param Carbon $date
*
* @return float|null
*/
public function getLimitAmountOnDate(Budget $budget, Carbon $date)
{
$repetition = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('limit_repetitions.startdate', $date->format('Y-m-d 00:00:00'))
->where('budget_limits.budget_id', $budget->id)
->first(['limit_repetitions.*']);
if ($repetition) {
return $repetition->amount;
}
return null;
}
/** /**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
@ -450,7 +530,197 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
} }
return $limit; return $limit;
}
/**
* Get the budgeted amounts for each budgets in each year.
*
* @param Collection $budgets
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getBudgetedPerYear(Collection $budgets, Carbon $start, Carbon $end)
{
$budgetIds = $budgets->pluck('id')->toArray();
$set = Auth::user()->budgets()
->leftJoin('budget_limits', 'budgets.id', '=', 'budget_limits.budget_id')
->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d'))
->where('limit_repetitions.enddate', '<=', $end->format('Y-m-d'))
->groupBy('budgets.id')
->groupBy('dateFormatted')
->whereIn('budgets.id', $budgetIds)
->get(
[
'budgets.*',
DB::Raw('DATE_FORMAT(`limit_repetitions`.`startdate`,"%Y") as `dateFormatted`'),
DB::Raw('SUM(`limit_repetitions`.`amount`) as `budgeted`')
]
);
return $set;
}
/**
* Returns an array with every budget in it and the expenses for each budget
* per year for.
*
* @param Collection $budgets
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end)
{
$ids = $accounts->pluck('id')->toArray();
$budgetIds = $budgets->pluck('id')->toArray();
/** @var Collection $set */
$set = Auth::user()->budgets()
->leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.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(
function (Budget $budget) {
return strtolower($budget->name);
}
);
$return = [];
foreach ($set as $budget) {
$id = $budget->id;
if (!isset($return[$id])) {
$return[$id] = [
'budget' => $budget,
'entries' => [],
];
}
// store each entry:
$return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount;
}
return $return;
}
/**
* Returns an array with the following key:value pairs:
*
* yyyy-mm-dd:<array>
*
* That array contains:
*
* budgetid:<amount>
*
* Where yyyy-mm-dd is the date and <amount> is the money spent using WITHDRAWALS in the $budget
* from the given users accounts..
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function spentAllPerDayForAccounts(Collection $accounts, Carbon $start, Carbon $end)
{
$ids = $accounts->pluck('id')->toArray();
/** @var Collection $query */
$query = Auth::user()->transactionJournals()
->transactionTypes([TransactionType::WITHDRAWAL])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
->whereIn('transactions.account_id', $ids)
->where('transactions.amount', '<', 0)
->before($end)
->after($start)
->groupBy('budget_id')
->groupBy('dateFormatted')
->get(
['transaction_journals.date as dateFormatted', 'budget_transaction_journal.budget_id',
DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]
);
$return = [];
foreach ($query->toArray() as $entry) {
$budgetId = $entry['budget_id'];
if (!isset($return[$budgetId])) {
$return[$budgetId] = [];
}
$return[$budgetId][$entry['dateFormatted']] = $entry['sum'];
}
return $return;
}
/**
* Returns a list of expenses (in the field "spent", grouped per budget per account.
*
* @param Collection $budgets
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function spentPerBudgetPerAccount(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end)
{
$accountIds = $accounts->pluck('id')->toArray();
$budgetIds = $budgets->pluck('id')->toArray();
$set = Auth::user()->transactionjournals()
->leftJoin(
'transactions AS t_from', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0);
}
)
->leftJoin(
'transactions AS t_to', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
->whereIn('t_from.account_id', $accountIds)
->whereNotIn('t_to.account_id', $accountIds)
->where(
function (Builder $q) use ($budgetIds) {
$q->whereIn('budget_transaction_journal.budget_id', $budgetIds);
$q->orWhereNull('budget_transaction_journal.budget_id');
}
)
->after($start)
->before($end)
->groupBy('t_from.account_id')
->groupBy('budget_transaction_journal.budget_id')
->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE])
->get(
[
't_from.account_id', 'budget_transaction_journal.budget_id',
DB::Raw('SUM(`t_from`.`amount`) AS `spent`')
]
);
return $set;
} }
} }

View File

@ -15,11 +15,93 @@ use Illuminate\Support\Collection;
*/ */
interface BudgetRepositoryInterface interface BudgetRepositoryInterface
{ {
/** /**
* @return void * @return void
*/ */
public function cleanupBudgets(); public function cleanupBudgets();
/**
* 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
*
* @return Collection
*/
public function getExpensesPerDay(Budget $budget, Carbon $start, Carbon $end);
/**
* @param Budget $budget
*
* @return Carbon
*/
public function firstActivity(Budget $budget);
/**
* Returns the expenses for this budget grouped per month, with the date
* in "date" (a string, not a Carbon) and the amount in "dailyAmount".
*
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getExpensesPerMonth(Budget $budget, Carbon $start, Carbon $end);
/**
* Returns a list of expenses (in the field "spent", grouped per budget per account.
*
* @param Collection $budgets
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function spentPerBudgetPerAccount(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end);
/**
* Returns an array with the following key:value pairs:
*
* yyyy-mm-dd:<amount>
*
* Where yyyy-mm-dd is the date and <amount> is the money spent using WITHDRAWALS in the $budget
* from all the users accounts.
*
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function spentPerDay(Budget $budget, Carbon $start, Carbon $end);
/**
* Returns an array with the following key:value pairs:
*
* yyyy-mm-dd:<array>
*
* That array contains:
*
* budgetid:<amount>
*
* Where yyyy-mm-dd is the date and <amount> is the money spent using WITHDRAWALS in the $budget
* from the given users accounts..
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function spentAllPerDayForAccounts(Collection $accounts, Carbon $start, Carbon $end);
/** /**
* @param Budget $budget * @param Budget $budget
* *
@ -28,14 +110,29 @@ interface BudgetRepositoryInterface
public function destroy(Budget $budget); public function destroy(Budget $budget);
/** /**
* Takes tags into account. * Returns an array with every budget in it and the expenses for each budget
* per month.
* *
* @param Budget $budget * @param Collection $accounts
* @param Carbon $date * @param Carbon $start
* @param Carbon $end
* *
* @return float * @return array
*/ */
public function expensesOnDay(Budget $budget, Carbon $date); public function getBudgetsAndExpensesPerMonth(Collection $accounts, Carbon $start, Carbon $end);
/**
* Returns an array with every budget in it and the expenses for each budget
* per year for.
*
* @param Collection $budgets
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end);
/** /**
* @return Collection * @return Collection
@ -43,20 +140,23 @@ interface BudgetRepositoryInterface
public function getActiveBudgets(); public function getActiveBudgets();
/** /**
* @param Budget $budget * Get the budgeted amounts for each budgets in each year.
*
* @param Collection $budgets
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getBudgetedPerYear(Collection $budgets, Carbon $start, Carbon $end);
/**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* *
* @return Collection * @return Collection
*/ */
public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end); public function getAllBudgetLimitRepetitions(Carbon $start, Carbon $end);
/**
* @param Budget $budget
*
* @return Collection
*/
public function getBudgetLimits(Budget $budget);
/** /**
* @return Collection * @return Collection
@ -106,25 +206,6 @@ interface BudgetRepositoryInterface
*/ */
public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50); public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50);
/**
* @deprecated
*
* @param Budget $budget
*
* @return Carbon
*/
public function getLastBudgetLimitDate(Budget $budget);
/**
* @deprecated
*
* @param Budget $budget
* @param Carbon $date
*
* @return float
*/
public function getLimitAmountOnDate(Budget $budget, Carbon $date);
/** /**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end

View File

@ -4,13 +4,10 @@ namespace FireflyIII\Repositories\Category;
use Auth; use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use Crypt;
use DB; use DB;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Shared\ComponentRepository; use FireflyIII\Sql\Query;
use FireflyIII\Support\CacheProperties;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -19,44 +16,16 @@ use Illuminate\Support\Collection;
* *
* @package FireflyIII\Repositories\Category * @package FireflyIII\Repositories\Category
*/ */
class CategoryRepository extends ComponentRepository implements CategoryRepositoryInterface class CategoryRepository implements CategoryRepositoryInterface
{ {
/** /**
* @param Category $category * Returns a list of all the categories belonging to a user.
* *
* @return int
*/
public function countJournals(Category $category)
{
return $category->transactionJournals()->count();
}
/**
* @param Category $category
*
* @return boolean
*/
public function destroy(Category $category)
{
$category->delete();
return true;
}
/**
* @return Collection * @return Collection
*/ */
public function getCategories() public function listCategories()
{ {
$cache = new CacheProperties;
$cache->addProperty('category-list');
if ($cache->has()) {
return $cache->get();
}
/** @var Collection $set */ /** @var Collection $set */
$set = Auth::user()->categories()->orderBy('name', 'ASC')->get(); $set = Auth::user()->categories()->orderBy('name', 'ASC')->get();
$set = $set->sortBy( $set = $set->sortBy(
@ -65,181 +34,19 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
} }
); );
$cache->store($set);
return $set; return $set;
} }
/** /**
* Returns the amount earned without category by accounts in period. * Returns a list of transaction journals in the range (all types, all accounts) that have no category
* associated to them.
* *
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function earnedNoCategoryForAccounts(Collection $accounts, Carbon $start, Carbon $end)
{
$accountIds = [];
foreach ($accounts as $account) {
$accountIds[] = $account->id;
}
// is deposit AND account_from is in the list of $accounts
// not from any of the accounts in the list?
return Auth::user()
->transactionjournals()
->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('category_transaction_journal.id')
->before($end)
->after($start)
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereIn('transactions.account_id', $accountIds)
->transactionTypes([TransactionType::DEPOSIT])
->get(['transaction_journals.*'])->sum('amount');
}
/**
* Returns the amount spent without category by accounts in period.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function spentNoCategoryForAccounts(Collection $accounts, Carbon $start, Carbon $end)
{
$accountIds = [];
foreach ($accounts as $account) {
$accountIds[] = $account->id;
}
// is withdrawal or transfer AND account_from is in the list of $accounts
return Auth::user()
->transactionjournals()
->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('category_transaction_journal.id')
->before($end)
->after($start)
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereIn('transactions.account_id', $accountIds)
->transactionTypes([TransactionType::WITHDRAWAL])
->get(['transaction_journals.*'])->sum('amount');
}
/**
*
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function getCategoriesAndExpenses(Carbon $start, Carbon $end)
{
$set = Auth::user()->transactionjournals()
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
->before($end)
->where('categories.user_id', Auth::user()->id)
->after($start)
->transactionTypes([TransactionType::WITHDRAWAL])
->get(['categories.id as category_id', 'categories.encrypted as category_encrypted', 'categories.name', 'transaction_journals.*']);
bcscale(2);
$result = [];
foreach ($set as $entry) {
$categoryId = intval($entry->category_id);
if (isset($result[$categoryId])) {
$result[$categoryId]['sum'] = bcadd($result[$categoryId]['sum'], $entry->amount);
} else {
$isEncrypted = intval($entry->category_encrypted) === 1 ? true : false;
$name = strlen($entry->name) === 0 ? trans('firefly.no_category') : $entry->name;
$name = $isEncrypted ? Crypt::decrypt($name) : $name;
$result[$categoryId] = [
'name' => $name,
'sum' => $entry->amount,
];
}
}
return $result;
}
/**
* @param Category $category
*
* @return Carbon
*/
public function getFirstActivityDate(Category $category)
{
/** @var TransactionJournal $first */
$first = $category->transactionjournals()->orderBy('date', 'ASC')->first();
if ($first) {
return $first->date;
}
return new Carbon;
}
/**
* @param Category $category
* @param int $page
*
* @return Collection
*/
public function getJournals(Category $category, $page)
{
$offset = $page > 0 ? $page * 50 : 0;
return $category->transactionJournals()->withRelevantData()->take(50)->offset($offset)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->get(
['transaction_journals.*']
);
}
/**
* @param Category $category
*
* @return Carbon|null
*/
public function getLatestActivity(Category $category)
{
$latest = $category->transactionjournals()
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->first();
if ($latest) {
return $latest->date;
}
return null;
}
/**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* *
* @return Collection * @return Collection
*/ */
public function getWithoutCategory(Carbon $start, Carbon $end) public function listNoCategory(Carbon $start, Carbon $end)
{ {
return Auth::user() return Auth::user()
->transactionjournals() ->transactionjournals()
@ -254,269 +61,65 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
} }
/** /**
* @param Category $category * This method returns a very special collection for each category:
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
* *
* @return string * category, year, expense/earned, amount
*/
public function balanceInPeriod(Category $category, Carbon $start, Carbon $end, Collection $accounts)
{
return $this->commonBalanceInPeriod($category, $start, $end, $accounts);
}
/**
* Corrected for tags
* *
* @param Category $category * categories can be duplicated.
* @param Carbon $date
* *
* @return string * @param Collection $categories
*/
public function spentOnDaySum(Category $category, Carbon $date)
{
return $category->transactionjournals()->transactionTypes([TransactionType::WITHDRAWAL])->onDate($date)->get(['transaction_journals.*'])->sum('amount');
}
/**
* @param array $data
*
* @return Category
*/
public function store(array $data)
{
$newCategory = new Category(
[
'user_id' => $data['user'],
'name' => $data['name'],
]
);
$newCategory->save();
return $newCategory;
}
/**
* @param Category $category
* @param array $data
*
* @return Category
*/
public function update(Category $category, array $data)
{
// update the account:
$category->name = $data['name'];
$category->save();
return $category;
}
/**
* @deprecated
* This method returns the sum of the journals in the category, optionally
* limited by a start or end date.
*
* @param Category $category
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function journalsSum(Category $category, Carbon $start = null, Carbon $end = null)
{
$query = $category->transactionJournals()
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC');
if (!is_null($start)) {
$query->after($start);
}
if (!is_null($end)) {
$query->before($end);
}
return $query->get(['transaction_journals.*'])->sum('amount');
}
/**
* @param Category $category
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
*
* @return string
*/
public function spentInPeriod(Category $category, Carbon $start, Carbon $end)
{
$cache = new CacheProperties; // we must cache this.
$cache->addProperty($category->id);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('spentInPeriod');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$sum = $category->transactionjournals()->transactionTypes([TransactionType::WITHDRAWAL])->before($end)->after($start)->get(['transaction_journals.*'])
->sum(
'amount'
);
$cache->store($sum);
return $sum;
}
/**
* @param Category $category
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
*
* @return string
*/
public function earnedInPeriod(Category $category, Carbon $start, Carbon $end)
{
$cache = new CacheProperties; // we must cache this.
$cache->addProperty($category->id);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('earnedInPeriod');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$sum = $category->transactionjournals()->transactionTypes([TransactionType::DEPOSIT])->before($end)->after($start)->get(['transaction_journals.*'])
->sum(
'amount'
);
$cache->store($sum);
return $sum;
}
/**
* @param Category $category
* @param int $page
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end)
{
$offset = $page > 0 ? $page * 50 : 0;
return $category->transactionJournals()
->after($start)
->before($end)
->withRelevantData()->take(50)->offset($offset)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->get(
['transaction_journals.*']
);
}
/**
* @param Category $category
*
* @param Carbon $start
* @param Carbon $end
*
* @return int
*/
public function countJournalsInRange(Category $category, Carbon $start, Carbon $end)
{
return $category->transactionJournals()->before($end)->after($start)->count();
}
/**
*
* Corrected for tags.
*
* @param Category $category
* @param Carbon $date
*
* @return float
*/
public function earnedOnDaySum(Category $category, Carbon $date)
{
return $category->transactionjournals()->transactionTypes([TransactionType::DEPOSIT])->onDate($date)->get(['transaction_journals.*'])->sum('amount');
}
/**
* Calculates how much is spent in this period.
*
* @param Category $category
* @param Collection $accounts * @param Collection $accounts
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* *
* @return string * @return Collection
*/ */
public function spentInPeriodForAccounts(Category $category, Collection $accounts, Carbon $start, Carbon $end) public function listMultiYear(Collection $categories, Collection $accounts, Carbon $start, Carbon $end)
{ {
$accountIds = []; /*
foreach ($accounts as $account) { * select categories.id, DATE_FORMAT(transaction_journals.date,"%Y") as dateFormatted, transaction_types.type, SUM(amount) as sum from categories
$accountIds[] = $account->id;
}
$sum left join category_transaction_journal ON category_transaction_journal.category_id = categories.id
= $category left join transaction_journals ON transaction_journals.id = category_transaction_journal.transaction_journal_id
->transactionjournals() left join transaction_types ON transaction_types.id = transaction_journals.transaction_type_id
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') left join transactions ON transactions.transaction_journal_id = transaction_journals.id
->after($start)
->before($end)
->whereIn('transactions.account_id', $accountIds)
->transactionTypes([TransactionType::WITHDRAWAL])
->get(['transaction_journals.*'])
->sum('amount');
return $sum;
where
categories.user_id =1
and transaction_types.type in ("Withdrawal","Deposit")
and transactions.account_id IN (2,4,6,10,11,610,725,879,1248)
group by categories.id, transaction_types.type, dateFormatted
*/
$set = Auth::user()->categories()
->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'category_transaction_journal.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereIn('transaction_types.type', [TransactionType::DEPOSIT, TransactionType::WITHDRAWAL])
->whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
->whereIn('categories.id', $categories->pluck('id')->toArray())
->groupBy('categories.id')
->groupBy('transaction_types.type')
->groupBy('dateFormatted')
->get(
[
'categories.*',
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y") as `dateFormatted`'),
'transaction_types.type',
DB::Raw('SUM(`amount`) as `sum`')
]
);
return $set;
} }
/**
* Calculate how much is earned in this period.
*
* @param Category $category
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function earnedInPeriodForAccounts(Category $category, Collection $accounts, Carbon $start, Carbon $end)
{
$accountIds = [];
foreach ($accounts as $account) {
$accountIds[] = $account->id;
}
$sum
= $category
->transactionjournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->before($end)
->whereIn('transactions.account_id', $accountIds)
->transactionTypes([TransactionType::DEPOSIT])
->after($start)
->get(['transaction_journals.*'])
->sum('amount');
return $sum;
}
/** /**
* Returns a collection of Categories appended with the amount of money that has been earned * Returns a collection of Categories appended with the amount of money that has been earned
* in these categories, based on the $accounts involved, in period X. * in these categories, based on the $accounts involved, in period X, grouped per month.
* The amount earned in category X in period X is saved in field "earned". * The amount earned in category X in period X is saved in field "earned".
* *
* @param $accounts * @param $accounts
@ -525,13 +128,8 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
* *
* @return Collection * @return Collection
*/ */
public function earnedForAccounts(Collection $accounts, Carbon $start, Carbon $end) public function earnedForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end)
{ {
$accountIds = [];
foreach ($accounts as $account) {
$accountIds[] = $account->id;
}
$collection = Auth::user()->categories() $collection = Auth::user()->categories()
->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id') ->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id')
@ -547,15 +145,22 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
$join->on('t_dest.transaction_journal_id', '=', 'transaction_journals.id')->where('t_dest.amount', '>', 0); $join->on('t_dest.transaction_journal_id', '=', 'transaction_journals.id')->where('t_dest.amount', '>', 0);
} }
) )
->whereIn('t_dest.account_id', $accountIds)// to these accounts (earned) ->whereIn('t_dest.account_id', $accounts->pluck('id')->toArray())// to these accounts (earned)
->whereNotIn('t_src.account_id', $accountIds)//-- but not from these accounts ->whereNotIn('t_src.account_id', $accounts->pluck('id')->toArray())//-- but not from these accounts
->whereIn( ->whereIn(
'transaction_types.type', [TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE] 'transaction_types.type', [TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]
)// earned from these things. )
->where('transaction_journals.date', '>=', $start->format('Y-m-d')) ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->groupBy('categories.id') ->groupBy('categories.id')
->get(['categories.*', DB::Raw('SUM(`t_dest`.`amount`) AS `earned`')]); ->groupBy('dateFormatted')
->get(
[
'categories.*',
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") as `dateFormatted`'),
DB::Raw('SUM(`t_dest`.`amount`) AS `earned`')
]
);
return $collection; return $collection;
@ -564,8 +169,8 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
/** /**
* Returns a collection of Categories appended with the amount of money that has been spent * Returns a collection of Categories appended with the amount of money that has been spent
* in these categories, based on the $accounts involved, in period X. * in these categories, based on the $accounts involved, in period X, grouped per month.
* The amount earned in category X in period X is saved in field "spent". * The amount spent in category X in period X is saved in field "spent".
* *
* @param $accounts * @param $accounts
* @param $start * @param $start
@ -573,15 +178,10 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
* *
* @return Collection * @return Collection
*/ */
public function spentForAccounts(Collection $accounts, Carbon $start, Carbon $end) public function spentForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end)
{ {
$accountIds = []; $accountIds = $accounts->pluck('id')->toArray();
foreach ($accounts as $account) { $query = Auth::user()->categories()
$accountIds[] = $account->id;
}
$collection = Auth::user()->categories()
->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id') ->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id')
->leftJoin('transaction_journals', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') ->leftJoin('transaction_journals', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
@ -595,16 +195,105 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
$join->on('t_dest.transaction_journal_id', '=', 'transaction_journals.id')->where('t_dest.amount', '>', 0); $join->on('t_dest.transaction_journal_id', '=', 'transaction_journals.id')->where('t_dest.amount', '>', 0);
} }
) )
->whereIn('t_src.account_id', $accountIds)// from these accounts (spent)
->whereNotIn('t_dest.account_id', $accountIds)//-- but not from these accounts (spent internally)
->whereIn( ->whereIn(
'transaction_types.type', [TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE] 'transaction_types.type', [TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]
)// spent on these things. )// spent on these things.
->where('transaction_journals.date', '>=', $start->format('Y-m-d')) ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->groupBy('categories.id') ->groupBy('categories.id')
->get(['categories.*', DB::Raw('SUM(`t_dest`.`amount`) AS `spent`')]); ->groupBy('dateFormatted');
if (count($accountIds) > 0) {
$query->whereIn('t_src.account_id', $accountIds)// from these accounts (spent)
->whereNotIn('t_dest.account_id', $accountIds);//-- but not from these accounts (spent internally)
}
$collection = $query->get(
[
'categories.*',
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") as `dateFormatted`'),
DB::Raw('SUM(`t_src`.`amount`) AS `spent`')
]
);
return $collection; return $collection;
} }
/**
* Returns the total amount of money related to transactions without any category connected to
* it. Returns either the spent amount.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function sumSpentNoCategory(Collection $accounts, Carbon $start, Carbon $end)
{
return $this->sumNoCategory($accounts, $start, $end, Query::SPENT);
}
/**
* Returns the total amount of money related to transactions without any category connected to
* it. Returns either the earned amount.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function sumEarnedNoCategory(Collection $accounts, Carbon $start, Carbon $end)
{
return $this->sumNoCategory($accounts, $start, $end, Query::EARNED);
}
/**
* Returns the total amount of money related to transactions without any category connected to
* it. Returns either the earned or the spent amount.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
* @param int $group
*
* @return string
*/
protected function sumNoCategory(Collection $accounts, Carbon $start, Carbon $end, $group = Query::EARNED)
{
$accountIds = $accounts->pluck('id')->toArray();
if ($group == Query::EARNED) {
$types = [TransactionType::DEPOSIT];
} else {
$types = [TransactionType::WITHDRAWAL];
}
// is withdrawal or transfer AND account_from is in the list of $accounts
$query = Auth::user()
->transactionjournals()
->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('category_transaction_journal.id')
->before($end)
->after($start)
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->transactionTypes($types);
if (count($accountIds) > 0) {
$query->whereIn('transactions.account_id', $accountIds);
}
$single = $query->first(
[
DB::Raw('SUM(`transactions`.`amount`) as `sum`')
]
);
if (!is_null($single)) {
return $single->sum;
}
return '0';
}
} }

View File

@ -3,7 +3,6 @@
namespace FireflyIII\Repositories\Category; namespace FireflyIII\Repositories\Category;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Models\Category;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@ -13,33 +12,11 @@ use Illuminate\Support\Collection;
*/ */
interface CategoryRepositoryInterface interface CategoryRepositoryInterface
{ {
/**
* @param Category $category
*
* @return int
*/
public function countJournals(Category $category);
/**
* @param Category $category
*
* @param Carbon $start
* @param Carbon $end
*
* @return int
*/
public function countJournalsInRange(Category $category, Carbon $start, Carbon $end);
/**
* @param Category $category
*
* @return boolean
*/
public function destroy(Category $category);
/** /**
* Returns a collection of Categories appended with the amount of money that has been earned * Returns a collection of Categories appended with the amount of money that has been earned
* in these categories, based on the $accounts involved, in period X. * in these categories, based on the $accounts involved, in period X, grouped per month.
* The amount earned in category X in period X is saved in field "earned". * The amount earned in category X in period X is saved in field "earned".
* *
* @param $accounts * @param $accounts
@ -48,11 +25,45 @@ interface CategoryRepositoryInterface
* *
* @return Collection * @return Collection
*/ */
public function earnedForAccounts(Collection $accounts, Carbon $start, Carbon $end); public function earnedForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end);
/**
* Returns a list of all the categories belonging to a user.
*
* @return Collection
*/
public function listCategories();
/**
* This method returns a very special collection for each category:
*
* category, year, expense/earned, amount
*
* categories can be duplicated.
*
* @param Collection $categories
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function listMultiYear(Collection $categories, Collection $accounts, Carbon $start, Carbon $end);
/**
* Returns a list of transaction journals in the range (all types, all accounts) that have no category
* associated to them.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function listNoCategory(Carbon $start, Carbon $end);
/** /**
* Returns a collection of Categories appended with the amount of money that has been spent * Returns a collection of Categories appended with the amount of money that has been spent
* in these categories, based on the $accounts involved, in period X. * in these categories, based on the $accounts involved, in period X, grouped per month.
* The amount earned in category X in period X is saved in field "spent". * The amount earned in category X in period X is saved in field "spent".
* *
* @param $accounts * @param $accounts
@ -61,40 +72,11 @@ interface CategoryRepositoryInterface
* *
* @return Collection * @return Collection
*/ */
public function spentForAccounts(Collection $accounts, Carbon $start, Carbon $end); public function spentForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end);
/** /**
* @return Collection * Returns the total amount of money related to transactions without any category connected to
*/ * it. Returns either the earned amount.
public function getCategories();
/**
* Calculates how much is spent in this period.
*
* @param Category $category
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function spentInPeriodForAccounts(Category $category, Collection $accounts, Carbon $start, Carbon $end);
/**
* Calculate how much is earned in this period.
*
* @param Category $category
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function earnedInPeriodForAccounts(Category $category, Collection $accounts, Carbon $start, Carbon $end);
/**
* Returns the amount spent without category by accounts in period.
* *
* @param Collection $accounts * @param Collection $accounts
* @param Carbon $start * @param Carbon $start
@ -102,10 +84,11 @@ interface CategoryRepositoryInterface
* *
* @return string * @return string
*/ */
public function spentNoCategoryForAccounts(Collection $accounts, Carbon $start, Carbon $end); public function sumEarnedNoCategory(Collection $accounts, Carbon $start, Carbon $end);
/** /**
* Returns the amount earned without category by accounts in period. * Returns the total amount of money related to transactions without any category connected to
* it. Returns either the spent amount.
* *
* @param Collection $accounts * @param Collection $accounts
* @param Carbon $start * @param Carbon $start
@ -113,137 +96,6 @@ interface CategoryRepositoryInterface
* *
* @return string * @return string
*/ */
public function earnedNoCategoryForAccounts(Collection $accounts, Carbon $start, Carbon $end); public function sumSpentNoCategory(Collection $accounts, Carbon $start, Carbon $end);
/**
* Corrected for tags.
*
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function getCategoriesAndExpenses(Carbon $start, Carbon $end);
/**
* @param Category $category
*
* @return Carbon
*/
public function getFirstActivityDate(Category $category);
/**
* @param Category $category
* @param int $page
*
* @return Collection
*/
public function getJournals(Category $category, $page);
/**
* @param Category $category
* @param int $page
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end);
/**
* @deprecated
* This method returns the sum of the journals in the category, optionally
* limited by a start or end date.
*
* @param Category $category
* @param Carbon $start
* @param Carbon $end
*
* @return string
*/
public function journalsSum(Category $category, Carbon $start = null, Carbon $end = null);
/**
* @param Category $category
*
* @return Carbon|null
*/
public function getLatestActivity(Category $category);
/**
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getWithoutCategory(Carbon $start, Carbon $end);
/**
* Corrected for tags and list of accounts.
*
* @param Category $category
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* @param Collection $accounts
*
* @return string
*/
public function balanceInPeriod(Category $category, Carbon $start, Carbon $end, Collection $accounts);
/**
* @param Category $category
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
*
* @return string
*/
public function spentInPeriod(Category $category, Carbon $start, Carbon $end);
/**
* @param Category $category
* @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
*
* @return string
*/
public function earnedInPeriod(Category $category, Carbon $start, Carbon $end);
/**
*
* Corrected for tags.
*
* @param Category $category
* @param Carbon $date
*
* @return float
*/
public function spentOnDaySum(Category $category, Carbon $date);
/**
*
* Corrected for tags.
*
* @param Category $category
* @param Carbon $date
*
* @return float
*/
public function earnedOnDaySum(Category $category, Carbon $date);
/**
* @param array $data
*
* @return Category
*/
public function store(array $data);
/**
* @param Category $category
* @param array $data
*
* @return Category
*/
public function update(Category $category, array $data);
} }

View File

@ -0,0 +1,238 @@
<?php
namespace FireflyIII\Repositories\Category;
use Carbon\Carbon;
use DB;
use FireflyIII\Models\Category;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Shared\ComponentRepository;
use Illuminate\Support\Collection;
/**
* Class SingleCategoryRepository
*
* @package FireflyIII\Repositories\Category
*/
class SingleCategoryRepository extends ComponentRepository implements SingleCategoryRepositoryInterface
{
/**
* @param Category $category
*
* @return int
*/
public function countJournals(Category $category)
{
return $category->transactionJournals()->count();
}
/**
* @param Category $category
*
* @param Carbon $start
* @param Carbon $end
*
* @return int
*/
public function countJournalsInRange(Category $category, Carbon $start, Carbon $end)
{
return $category->transactionJournals()->before($end)->after($start)->count();
}
/**
* @param Category $category
*
* @return boolean
*/
public function destroy(Category $category)
{
$category->delete();
return true;
}
/**
* Returns an array with the following key:value pairs:
*
* yyyy-mm-dd:<amount>
*
* Where yyyy-mm-dd is the date and <amount> is the money earned using DEPOSITS in the $category
* from all the users $accounts.
*
* @param Category $category
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function earnedPerDay(Category $category, Carbon $start, Carbon $end)
{
/** @var Collection $query */
$query = $category->transactionJournals()
->transactionTypes([TransactionType::DEPOSIT])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.amount', '>', 0)
->before($end)
->after($start)
->groupBy('date')->get(['transaction_journals.date as dateFormatted', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
$return = [];
foreach ($query->toArray() as $entry) {
$return[$entry['dateFormatted']] = $entry['sum'];
}
return $return;
}
/**
* @param Category $category
*
* @return Carbon
*/
public function getFirstActivityDate(Category $category)
{
/** @var TransactionJournal $first */
$first = $category->transactionjournals()->orderBy('date', 'ASC')->first();
if ($first) {
return $first->date;
}
return new Carbon;
}
/**
* @param Category $category
* @param int $page
*
* @return Collection
*/
public function getJournals(Category $category, $page)
{
$offset = $page > 0 ? $page * 50 : 0;
return $category->transactionJournals()->withRelevantData()->take(50)->offset($offset)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->get(
['transaction_journals.*']
);
}
/**
* @param Category $category
* @param int $page
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end)
{
$offset = $page > 0 ? $page * 50 : 0;
return $category->transactionJournals()
->after($start)
->before($end)
->withRelevantData()->take(50)->offset($offset)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->get(
['transaction_journals.*']
);
}
/**
* @param Category $category
*
* @return Carbon|null
*/
public function getLatestActivity(Category $category)
{
$latest = $category->transactionjournals()
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->first();
if ($latest) {
return $latest->date;
}
return null;
}
/**
* Returns an array with the following key:value pairs:
*
* yyyy-mm-dd:<amount>
*
* Where yyyy-mm-dd is the date and <amount> is the money spent using DEPOSITS in the $category
* from all the users accounts.
*
* @param Category $category
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function spentPerDay(Category $category, Carbon $start, Carbon $end)
{
/** @var Collection $query */
$query = $category->transactionJournals()
->transactionTypes([TransactionType::WITHDRAWAL])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.amount', '<', 0)
->before($end)
->after($start)
->groupBy('date')->get(['transaction_journals.date as dateFormatted', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
$return = [];
foreach ($query->toArray() as $entry) {
$return[$entry['dateFormatted']] = $entry['sum'];
}
return $return;
}
/**
* @param array $data
*
* @return Category
*/
public function store(array $data)
{
$newCategory = new Category(
[
'user_id' => $data['user'],
'name' => $data['name'],
]
);
$newCategory->save();
return $newCategory;
}
/**
* @param Category $category
* @param array $data
*
* @return Category
*/
public function update(Category $category, array $data)
{
// update the account:
$category->name = $data['name'];
$category->save();
return $category;
}
}

View File

@ -0,0 +1,122 @@
<?php
namespace FireflyIII\Repositories\Category;
use Carbon\Carbon;
use FireflyIII\Models\Category;
use Illuminate\Support\Collection;
/**
* Interface SingleCategoryRepositoryInterface
*
* @package FireflyIII\Repositories\Category
*/
interface SingleCategoryRepositoryInterface
{
/**
* @param Category $category
*
* @return int
*/
public function countJournals(Category $category);
/**
* @param Category $category
*
* @param Carbon $start
* @param Carbon $end
*
* @return int
*/
public function countJournalsInRange(Category $category, Carbon $start, Carbon $end);
/**
* @param Category $category
*
* @return boolean
*/
public function destroy(Category $category);
/**
* Returns an array with the following key:value pairs:
*
* yyyy-mm-dd:<amount>
*
* Where yyyy-mm-dd is the date and <amount> is the money earned using DEPOSITS in the $category
* from all the users accounts.
*
* @param Category $category
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function earnedPerDay(Category $category, Carbon $start, Carbon $end);
/**
* @param Category $category
*
* @return Carbon
*/
public function getFirstActivityDate(Category $category);
/**
* @param Category $category
* @param int $page
*
* @return Collection
*/
public function getJournals(Category $category, $page);
/**
* @param Category $category
* @param int $page
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end);
/**
* @param Category $category
*
* @return Carbon|null
*/
public function getLatestActivity(Category $category);
/**
* Returns an array with the following key:value pairs:
*
* yyyy-mm-dd:<amount>
*
* Where yyyy-mm-dd is the date and <amount> is the money spent using WITHDRAWALS in the $category
* from all the users accounts.
*
* @param Category $category
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function spentPerDay(Category $category, Carbon $start, Carbon $end);
/**
* @param array $data
*
* @return Category
*/
public function store(array $data);
/**
* @param Category $category
* @param array $data
*
* @return Category
*/
public function update(Category $category, array $data);
}

View File

@ -13,7 +13,6 @@ use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Support\CacheProperties;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Log; use Log;
@ -45,14 +44,7 @@ class JournalRepository implements JournalRepositoryInterface
*/ */
public function first() public function first()
{ {
$cache = new CacheProperties;
$cache->addProperty('user-first-journal');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$entry = Auth::user()->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']); $entry = Auth::user()->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
$cache->store($entry);
return $entry; return $entry;
} }

View File

@ -4,9 +4,7 @@ namespace FireflyIII\Repositories\Shared;
use Carbon\Carbon; use Carbon\Carbon;
use DB; use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@ -27,23 +25,7 @@ class ComponentRepository
*/ */
protected function commonBalanceInPeriod($object, Carbon $start, Carbon $end, Collection $accounts) protected function commonBalanceInPeriod($object, Carbon $start, Carbon $end, Collection $accounts)
{ {
$cache = new CacheProperties; // we must cache this. $ids = $accounts->pluck('id')->toArray();
$cache->addProperty($object->id);
$cache->addProperty(get_class($object));
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($accounts);
$cache->addProperty('balanceInPeriodList');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$ids = [];
/** @var Account $account */
foreach ($accounts as $account) {
$ids[] = $account->id;
}
$entry = $object->transactionjournals() $entry = $object->transactionjournals()
@ -56,8 +38,6 @@ class ComponentRepository
->first([DB::Raw('SUM(`transactions`.`amount`) as `journalAmount`')]); ->first([DB::Raw('SUM(`transactions`.`amount`) as `journalAmount`')]);
$amount = $entry->journalAmount; $amount = $entry->journalAmount;
$cache->store($amount);
return $amount; return $amount;
} }
} }

View File

@ -5,11 +5,12 @@ namespace FireflyIII\Repositories\Tag;
use Auth; use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use DB;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Support\CacheProperties; use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@ -22,7 +23,6 @@ class TagRepository implements TagRepositoryInterface
/** /**
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five.
* *
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param Tag $tag * @param Tag $tag
@ -31,7 +31,6 @@ class TagRepository implements TagRepositoryInterface
*/ */
public function connect(TransactionJournal $journal, Tag $tag) public function connect(TransactionJournal $journal, Tag $tag)
{ {
/* /*
* Already connected: * Already connected:
*/ */
@ -94,6 +93,49 @@ class TagRepository implements TagRepositoryInterface
return $amount; return $amount;
} }
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function allCoveredByBalancingActs(Collection $accounts, Carbon $start, Carbon $end)
{
$ids = $accounts->pluck('id')->toArray();
$set = Auth::user()->tags()
->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id')
->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
->leftJoin(
'transactions AS t_from', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0);
}
)
->leftJoin(
'transactions AS t_to', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0);
}
)
->where('tags.tagMode', 'balancingAct')
->where('transaction_types.type', TransactionType::TRANSFER)
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->whereNull('transaction_journals.deleted_at')
->whereIn('t_from.account_id', $ids)
->whereIn('t_to.account_id', $ids)
->groupBy('t_to.account_id')
->get(
[
't_to.account_id',
DB::Raw('SUM(`t_to`.`amount`) as `sum`')
]
);
return $set;
}
/** /**
* @param Tag $tag * @param Tag $tag
* *
@ -112,13 +154,6 @@ class TagRepository implements TagRepositoryInterface
*/ */
public function get() public function get()
{ {
$cache = new CacheProperties;
$cache->addProperty('tags-list');
if ($cache->has()) {
return $cache->get();
}
/** @var Collection $tags */ /** @var Collection $tags */
$tags = Auth::user()->tags()->get(); $tags = Auth::user()->tags()->get();
$tags = $tags->sortBy( $tags = $tags->sortBy(
@ -127,8 +162,6 @@ class TagRepository implements TagRepositoryInterface
} }
); );
$cache->store($tags);
return $tags; return $tags;
} }

View File

@ -16,7 +16,14 @@ use Illuminate\Support\Collection;
*/ */
interface TagRepositoryInterface interface TagRepositoryInterface
{ {
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function allCoveredByBalancingActs(Collection $accounts, Carbon $start, Carbon $end);
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal

17
app/Sql/Query.php Normal file
View File

@ -0,0 +1,17 @@
<?php
namespace FireflyIII\Sql;
/**
* Class Query
*
* This class holds some useful static constants.
*
* @package FireflyIII\Sql
*/
class Query
{
const SPENT = 1;
const EARNED = 2;
}

View File

@ -15,7 +15,6 @@ use Session;
* *
* @package FireflyIII\Support * @package FireflyIII\Support
* *
* @SuppressWarnings(PHPMD.TooManyMethods)
*/ */
class ExpandedForm class ExpandedForm
{ {

View File

@ -100,11 +100,11 @@ class Navigation
/** /**
* *
* @param Carbon $theCurrentEnd * @param \Carbon\Carbon $theCurrentEnd
* @param $repeatFreq * @param $repeatFreq
* @param Carbon $maxDate * @param \Carbon\Carbon $maxDate
* *
* @return Carbon * @return \Carbon\Carbon
*/ */
public function endOfX(Carbon $theCurrentEnd, $repeatFreq, Carbon $maxDate = null) public function endOfX(Carbon $theCurrentEnd, $repeatFreq, Carbon $maxDate = null)
{ {
@ -218,11 +218,11 @@ class Navigation
} }
/** /**
* @param Carbon $theDate * @param \Carbon\Carbon $theDate
* @param $repeatFreq * @param $repeatFreq
* @param int $subtract * @param int $subtract
* *
* @return Carbon * @return \Carbon\Carbon
* @throws FireflyException * @throws FireflyException
*/ */
public function subtractPeriod(Carbon $theDate, $repeatFreq, $subtract = 1) public function subtractPeriod(Carbon $theDate, $repeatFreq, $subtract = 1)

View File

@ -76,9 +76,10 @@ class Steam
* Gets the balance for the given account during the whole range, using this format: * Gets the balance for the given account during the whole range, using this format:
* *
* [yyyy-mm-dd] => 123,2 * [yyyy-mm-dd] => 123,2
* @param Account $account *
* @param Carbon $start * @param \FireflyIII\Models\Account $account
* @param Carbon $end * @param \Carbon\Carbon $start
* @param \Carbon\Carbon $end
* *
* @return array * @return array
*/ */
@ -126,7 +127,7 @@ class Steam
* @param array $ids * @param array $ids
* @param \Carbon\Carbon $date * @param \Carbon\Carbon $date
* *
* @return float * @return array
*/ */
public function balancesById(array $ids, Carbon $date) public function balancesById(array $ids, Carbon $date)
{ {

View File

@ -24,7 +24,6 @@ class General extends Twig_Extension
/** /**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @return array * @return array
*/ */
public function getFilters() public function getFilters()

View File

@ -1,43 +1,55 @@
<?php namespace FireflyIII; <?php namespace FireflyIII;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Role;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Collection;
use Zizaco\Entrust\Traits\EntrustUserTrait; use Zizaco\Entrust\Traits\EntrustUserTrait;
/** /**
* Class User * Class User
* *
* @package FireflyIII * @package FireflyIII
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property Carbon $updated_at
* @property string $email * @property string $email
* @property string $password * @property string $password
* @property string $reset * @property string $reset
* @property string $remember_token * @property string $remember_token
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Account[] $accounts * @property-read Collection|Account[] $accounts
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Tag[] $tags * @property-read Collection|Tag[] $tags
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Bill[] $bills * @property-read Collection|Bill[] $bills
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets * @property-read Collection|Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $categories * @property-read Collection|Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Preference[] $preferences * @property-read Collection|Preference[] $preferences
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals * @property-read Collection|TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.role[] $roles * @property-read Collection|Role $roles
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereId($value) * @method static Builder|User whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereCreatedAt($value) * @method static Builder|User whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereUpdatedAt($value) * @method static Builder|User whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereEmail($value) * @method static Builder|User whereEmail($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User wherePassword($value) * @method static Builder|User wherePassword($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereReset($value) * @method static Builder|User whereReset($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereRememberToken($value) * @method static Builder|User whereRememberToken($value)
* @property boolean $blocked * @property boolean $blocked
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Attachment[] $attachments * @property-read Collection|Attachment[] $attachments
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereBlocked($value) * @method static Builder|User whereBlocked($value)
* @property string $blocked_code * @property string $blocked_code
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereBlockedCode($value) * @method static Builder|User whereBlockedCode($value)
*/ */
class User extends Model implements AuthenticatableContract, CanResetPasswordContract class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{ {

View File

@ -28,7 +28,6 @@ class FireflyValidator extends Validator
* @param array $rules * @param array $rules
* @param array $messages * @param array $messages
* @param array $customAttributes * @param array $customAttributes
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/ */
public function __construct(TranslatorInterface $translator, array $data, array $rules, array $messages = [], array $customAttributes = []) public function __construct(TranslatorInterface $translator, array $data, array $rules, array $messages = [], array $customAttributes = [])
{ {
@ -40,6 +39,8 @@ class FireflyValidator extends Validator
* @param $value * @param $value
* @param $parameters * @param $parameters
* *
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return bool * @return bool
*/ */
public function validateBelongsToUser($attribute, $value, $parameters) public function validateBelongsToUser($attribute, $value, $parameters)
@ -58,6 +59,8 @@ class FireflyValidator extends Validator
* @param $attribute * @param $attribute
* @param $value * @param $value
* *
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return bool * @return bool
*/ */
public function validateIban($attribute, $value) public function validateIban($attribute, $value)
@ -87,6 +90,8 @@ class FireflyValidator extends Validator
* @param $value * @param $value
* @param $parameters * @param $parameters
* *
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return bool * @return bool
*/ */
public function validateUniqueAccountForUser($attribute, $value, $parameters) public function validateUniqueAccountForUser($attribute, $value, $parameters)
@ -232,6 +237,8 @@ class FireflyValidator extends Validator
* @param $value * @param $value
* @param $parameters * @param $parameters
* *
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return bool * @return bool
*/ */
public function validateUniqueForUser($attribute, $value, $parameters) public function validateUniqueForUser($attribute, $value, $parameters)
@ -261,6 +268,8 @@ class FireflyValidator extends Validator
* @param $value * @param $value
* @param $parameters * @param $parameters
* *
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return bool * @return bool
*/ */
public function validateUniqueObjectForUser($attribute, $value, $parameters) public function validateUniqueObjectForUser($attribute, $value, $parameters)
@ -291,6 +300,8 @@ class FireflyValidator extends Validator
* @param $value * @param $value
* @param $parameters * @param $parameters
* *
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return bool * @return bool
*/ */
public function validateUniquePiggyBankForUser($attribute, $value, $parameters) public function validateUniquePiggyBankForUser($attribute, $value, $parameters)

View File

@ -21,6 +21,7 @@
}, },
"require": { "require": {
"laravel/framework": "5.1.*", "laravel/framework": "5.1.*",
"php": ">=5.6.4",
"davejamesmiller/laravel-breadcrumbs": "~3.0", "davejamesmiller/laravel-breadcrumbs": "~3.0",
"watson/validating": "~1.0", "watson/validating": "~1.0",
"doctrine/dbal": "~2.5", "doctrine/dbal": "~2.5",

80
composer.lock generated
View File

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "4fc3975430321d76dd859916a9dcbfb0", "hash": "35ee47a928ca01f96176d94b1bdbd800",
"content-hash": "ad9d33604e0a88fabea148474769942d", "content-hash": "1d6d8db5b01d70aed4926680b5236331",
"packages": [ "packages": [
{ {
"name": "classpreloader/classpreloader", "name": "classpreloader/classpreloader",
@ -269,33 +269,33 @@
}, },
{ {
"name": "doctrine/cache", "name": "doctrine/cache",
"version": "v1.5.4", "version": "v1.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/cache.git", "url": "https://github.com/doctrine/cache.git",
"reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136" "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/47cdc76ceb95cc591d9c79a36dc3794975b5d136", "url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6",
"reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136", "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.2" "php": "~5.5|~7.0"
}, },
"conflict": { "conflict": {
"doctrine/common": ">2.2,<2.4" "doctrine/common": ">2.2,<2.4"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": ">=3.7", "phpunit/phpunit": "~4.8|~5.0",
"predis/predis": "~1.0", "predis/predis": "~1.0",
"satooshi/php-coveralls": "~0.6" "satooshi/php-coveralls": "~0.6"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.5.x-dev" "dev-master": "1.6.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -335,7 +335,7 @@
"cache", "cache",
"caching" "caching"
], ],
"time": "2015-12-19 05:03:47" "time": "2015-12-31 16:37:02"
}, },
{ {
"name": "doctrine/collections", "name": "doctrine/collections",
@ -478,16 +478,16 @@
}, },
{ {
"name": "doctrine/dbal", "name": "doctrine/dbal",
"version": "v2.5.3", "version": "v2.5.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/dbal.git", "url": "https://github.com/doctrine/dbal.git",
"reference": "2fbcea96eae34a53183377cdbb0b9bec33974648" "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/2fbcea96eae34a53183377cdbb0b9bec33974648", "url": "https://api.github.com/repos/doctrine/dbal/zipball/abbdfd1cff43a7b99d027af3be709bc8fc7d4769",
"reference": "2fbcea96eae34a53183377cdbb0b9bec33974648", "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -545,7 +545,7 @@
"persistence", "persistence",
"queryobject" "queryobject"
], ],
"time": "2015-12-25 16:28:24" "time": "2016-01-05 22:11:12"
}, },
{ {
"name": "doctrine/inflector", "name": "doctrine/inflector",
@ -668,42 +668,6 @@
], ],
"time": "2014-09-09 13:34:57" "time": "2014-09-09 13:34:57"
}, },
{
"name": "grumpydictator/gchart",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/JC5/gchart.git",
"reference": "0b1de3e045aaf19bb17658d3e81db706d6945e5d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/JC5/gchart/zipball/0b1de3e045aaf19bb17658d3e81db706d6945e5d",
"reference": "0b1de3e045aaf19bb17658d3e81db706d6945e5d",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"psr-0": {
"Grumpydictator\\Gchart": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "James Cole",
"email": "TheGrumpyDictator@gmail.com"
}
],
"description": "GChart is a small package that allows you to easily generate data for the Google Charts API.",
"time": "2015-12-15 21:07:33"
},
{ {
"name": "illuminate/html", "name": "illuminate/html",
"version": "v5.0.0", "version": "v5.0.0",
@ -897,16 +861,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v5.1.27", "version": "v5.1.28",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "b16f80878fd3603022d3c84593397cedd9af0bcf" "reference": "3f0fd27939dfdafb1e50058423cd24e640894ba2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/b16f80878fd3603022d3c84593397cedd9af0bcf", "url": "https://api.github.com/repos/laravel/framework/zipball/3f0fd27939dfdafb1e50058423cd24e640894ba2",
"reference": "b16f80878fd3603022d3c84593397cedd9af0bcf", "reference": "3f0fd27939dfdafb1e50058423cd24e640894ba2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1021,7 +985,7 @@
"framework", "framework",
"laravel" "laravel"
], ],
"time": "2015-12-17 20:35:38" "time": "2015-12-31 17:41:30"
}, },
{ {
"name": "league/commonmark", "name": "league/commonmark",
@ -3065,6 +3029,8 @@
}, },
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": [], "platform": {
"php": ">=5.6.4"
},
"platform-dev": [] "platform-dev": []
} }

View File

@ -2,7 +2,7 @@
return [ return [
'chart' => 'chartjs', 'chart' => 'chartjs',
'version' => '3.5.6.1', 'version' => '3.6.0',
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'], 'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'], 'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'csv_import_enabled' => true, 'csv_import_enabled' => true,

View File

@ -94,7 +94,7 @@ return [
'TwigBridge\Extension\Laravel\Dump', 'TwigBridge\Extension\Laravel\Dump',
'TwigBridge\Extension\Laravel\Input', 'TwigBridge\Extension\Laravel\Input',
'TwigBridge\Extension\Laravel\Session', 'TwigBridge\Extension\Laravel\Session',
'TwigBridge\Extension\Laravel\String', 'TwigBridge\Extension\Laravel\Str',
'TwigBridge\Extension\Laravel\Translator', 'TwigBridge\Extension\Laravel\Translator',
'TwigBridge\Extension\Laravel\Url', 'TwigBridge\Extension\Laravel\Url',

View File

@ -15,7 +15,7 @@ $(function () {
$('.removeMoney').on('click', removeMoney); $('.removeMoney').on('click', removeMoney);
if (typeof(lineChart) === 'function' && typeof(piggyBankID) !== 'undefined') { if (typeof(lineChart) === 'function' && typeof(piggyBankID) !== 'undefined') {
lineChart('chart/piggyBank/' + piggyBankID, 'piggy-bank-history'); lineChart('chart/piggy-bank/' + piggyBankID, 'piggy-bank-history');
} }
$('#sortable tbody').sortable( $('#sortable tbody').sortable(

View File

@ -5,6 +5,11 @@ $(function () {
"use strict"; "use strict";
drawChart(); drawChart();
// click open the top X income list:
$('#showIncomes').click(showIncomes);
// click open the top X expense list:
$('#showExpenses').click(showExpenses);
}); });
@ -152,4 +157,48 @@ function readCookie(name) {
function eraseCookie(name) { function eraseCookie(name) {
createCookie(name, "", -1); createCookie(name, "", -1);
}
function showIncomes() {
"use strict";
if (incomeRestShow) {
// hide everything, make button say "show"
$('#showIncomes').text(showTheRest);
$('.incomesCollapsed').removeClass('in').addClass('out');
// toggle:
incomeRestShow = false;
} else {
// show everything, make button say "hide".
$('#showIncomes').text(hideTheRest);
$('.incomesCollapsed').removeClass('out').addClass('in');
// toggle:
incomeRestShow = true;
}
return false;
}
function showExpenses() {
"use strict";
if (expenseRestShow) {
// hide everything, make button say "show"
$('#showExpenses').text(showTheRestExpense);
$('.expenseCollapsed').removeClass('in').addClass('out');
// toggle:
expenseRestShow = false;
} else {
// show everything, make button say "hide".
$('#showExpenses').text(hideTheRestExpense);
$('.expenseCollapsed').removeClass('out').addClass('in');
// toggle:
expenseRestShow = true;
}
return false;
} }

View File

@ -44,47 +44,43 @@
{% endif %} {% endif %}
{% for limit in limits %} {% for limit in limits %}
{% for rep in limit.limitRepetitions %} <div class="box">
{% set spentInRep = spentInRepetition(rep) %} <div class="box-header with-border">
<div class="box"> <h3 class="box-title"><a href="{{ route('budgets.show',[budget.id,limit.id]) }}">{{ limit.startdate.formatLocalized(monthFormat) }}</a>
<div class="box-header with-border"> </h3>
<h3 class="box-title"><a href="{{ route('budgets.show',[budget.id,rep.id]) }}">{{ rep.startdate.formatLocalized(monthFormat) }}</a> </div>
</h3> <div class="box-body">
</div> <div class="row">
<div class="box-body"> <div class="col-lg-6 col-md-6 col-sm-6">
<div class="row"> {{ 'amount'|_ }}: {{ limit.amount|formatAmount }}
<div class="col-lg-6 col-md-6 col-sm-6">
{{ 'amount'|_ }}: {{ rep.amount|formatAmount }}
</div>
<div class="col-lg-6 col-md-6 col-sm-6">
{{ 'spent'|_ }}: {{ spentInRep|formatAmount }}
</div>
</div> </div>
<div class="row"> <div class="col-lg-6 col-md-6 col-sm-6">
<div class="col-lg-12 col-md-12 col-sm-12"> {{ 'spent'|_ }}: {{ limit.spent|formatAmount }}
{% set overspent = rep.amount + spentInRep < 0 %} </div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
{% set overspent = limit.amount + limit.spent < 0 %}
{% if overspent %} {% if overspent %}
{% set pct = (spentInRep != 0 ? (rep.amount / (spentInRep*-1))*100 : 0) %} <!-- must have -1 here --> {% set pct = (limit.spent != 0 ? (limit.amount / (limit.spent*-1))*100 : 0) %} <!-- must have -1 here -->
<div class="progress progress-striped"> <div class="progress progress-striped">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{ pct|round }}" aria-valuemin="0" <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{ pct|round }}" aria-valuemin="0"
aria-valuemax="100" style="width: {{ pct|round }}%;"></div> aria-valuemax="100" style="width: {{ pct|round }}%;"></div>
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="{{ (100-pct)|round }}" <div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="{{ (100-pct)|round }}"
aria-valuemin="0" aria-valuemax="100" style="width: {{ (100-pct)|round }}%;"></div> aria-valuemin="0" aria-valuemax="100" style="width: {{ (100-pct)|round }}%;"></div>
</div> </div>
{% else %} {% else %}
{% set amount = rep.amount %} {% set pct = (limit.amount != 0 ? (((limit.spent*-1) / limit.amount)*100) : 0) %} <!-- must have -1 here -->
{% set pct = (amount != 0 ? (((spentInRep*-1) / amount)*100) : 0) %} <!-- must have -1 here --> <div class="progress progress-striped">
<div class="progress progress-striped"> <div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="{{ pct|round }}" aria-valuemin="0"
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="{{ pct|round }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ pct|round }}%;"></div>
aria-valuemax="100" style="width: {{ pct|round }}%;"></div> </div>
</div> {% endif %}
{% endif %}
</div>
</div> </div>
</div> </div>
</div> </div>
{% endfor %} </div>
{% endfor %} {% endfor %}
{% if limits|length == 1 %} {% if limits|length == 1 %}

View File

@ -61,6 +61,7 @@
</script> </script>
</body> </body>

View File

@ -1,7 +1,7 @@
<div class="list-group"> <div class="list-group">
{% for journal in transactions %} {% for journal in transactions %}
<a class="list-group-item" title="{{ journal.date.format('jS M Y') }}" href="{{ route('transactions.show',journal.id) }}"> <a class="list-group-item" title="{{ journal.date.formatLocalized(trans('config.month_and_day')) }}" href="{{ route('transactions.show',journal.id) }}">
{{ journal|typeIcon }} {{ journal|typeIcon }}

View File

@ -1,7 +1,7 @@
{% extends "./layout/default.twig" %} {% extends "./layout/default.twig" %}
{% block breadcrumbs %} {% block breadcrumbs %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, start, end, report_type, accountIds) }} {{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, start, end, reportType, accountIds) }}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -75,7 +75,7 @@
// to report another URL: // to report another URL:
var startDate = '{{ start.format('Ymd') }}'; var startDate = '{{ start.format('Ymd') }}';
var endDate = '{{ end.format('Ymd') }}'; var endDate = '{{ end.format('Ymd') }}';
var reportType = '{{ report_type }}'; var reportType = '{{ reportType }}';
var accountIds = '{{ accountIds }}'; var accountIds = '{{ accountIds }}';
var incomeTopLength = {{ incomeTopLength }}; var incomeTopLength = {{ incomeTopLength }};

View File

@ -1,7 +1,7 @@
{% extends "./layout/default.twig" %} {% extends "./layout/default.twig" %}
{% block breadcrumbs %} {% block breadcrumbs %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, start, end, report_type, accountIds) }} {{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, start, end, reportType, accountIds) }}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -29,6 +29,22 @@
</div> </div>
</div> </div>
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-6">
{% include 'reports/partials/accounts.twig' %}
{% include 'reports/partials/income-vs-expenses.twig' %}
</div>
<div class="col-lg-3 col-md-3 col-sm-3">
<!-- income -->
{% include 'reports/partials/income.twig' %}
</div>
<div class="col-lg-3 col-md-3 col-sm-3">
<!-- expenses -->
{% include 'reports/partials/expenses.twig' %}
</div>
</div>
{% for account in accounts %} {% for account in accounts %}
<div class="row" style="display:none;"> <div class="row" style="display:none;">
<div class="col-lg-12 col-md-12 col-sm-12"> <div class="col-lg-12 col-md-12 col-sm-12">
@ -125,8 +141,18 @@
// to report another URL: // to report another URL:
var startDate = '{{ start.format('Ymd') }}'; var startDate = '{{ start.format('Ymd') }}';
var endDate = '{{ end.format('Ymd') }}'; var endDate = '{{ end.format('Ymd') }}';
var reportType = '{{ report_type }}'; var reportType = '{{ reportType }}';
var accountIds = '{{ accountIds }}'; var accountIds = '{{ accountIds }}';
var incomeTopLength = {{ incomeTopLength }};
var expenseTopLength = {{ expenseTopLength }};
var incomeRestShow = false; // starts hidden.
var expenseRestShow = false; // starts hidden.
var showTheRest = '{{ trans('firefly.showTheRest',{number:incomeTopLength}) }}';
var hideTheRest = '{{ trans('firefly.hideTheRest',{number:incomeTopLength}) }}';
var showTheRestExpense = '{{ trans('firefly.showTheRest',{number:expenseTopLength}) }}';
var hideTheRestExpense = '{{ trans('firefly.hideTheRest',{number:expenseTopLength}) }}';
</script> </script>
<script type="text/javascript" src="js/reports/default/multi-year.js"></script> <script type="text/javascript" src="js/reports/default/multi-year.js"></script>
{% endblock %} {% endblock %}

View File

@ -1,7 +1,7 @@
{% extends "./layout/default.twig" %} {% extends "./layout/default.twig" %}
{% block breadcrumbs %} {% block breadcrumbs %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, start, end, report_type, accountIds) }} {{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, start, end, reportType, accountIds) }}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -92,7 +92,7 @@
// to report another URL: // to report another URL:
var startDate = '{{ start.format('Ymd') }}'; var startDate = '{{ start.format('Ymd') }}';
var endDate = '{{ end.format('Ymd') }}'; var endDate = '{{ end.format('Ymd') }}';
var reportType = '{{ report_type }}'; var reportType = '{{ reportType }}';
var accountIds = '{{ accountIds }}'; var accountIds = '{{ accountIds }}';