mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/4.2.1'
This commit is contained in:
commit
529bab1112
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,6 +2,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [4.2.1] - 2015-05-25
|
||||
### Added
|
||||
- BIC support (see #430)
|
||||
- New category report section and chart (see the general financial report)
|
||||
|
||||
|
||||
### Changed
|
||||
- Date range picker now also available on mobile devices (see #435)
|
||||
- Extended range of amounts for issue #439
|
||||
- Rewrote all routes. Old bookmarks may break.
|
||||
|
||||
## [4.2.0] - 2016-11-27
|
||||
### Added
|
||||
- Lots of (empty) tests
|
||||
|
@ -72,8 +72,7 @@ class UpgradeDatabase extends Command
|
||||
}
|
||||
|
||||
|
||||
$subQuery = TransactionJournal
|
||||
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
$subQuery = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->groupBy(['transaction_journals.id'])
|
||||
@ -98,8 +97,7 @@ class UpgradeDatabase extends Command
|
||||
|
||||
try {
|
||||
/** @var Transaction $opposing */
|
||||
$opposing = Transaction
|
||||
::where('transaction_journal_id', $journalId)
|
||||
$opposing = Transaction::where('transaction_journal_id', $journalId)
|
||||
->where('amount', $amount)->where('identifier', '=', 0)
|
||||
->whereNotIn('id', $processed)
|
||||
->first();
|
||||
|
@ -102,8 +102,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function reportAccounts()
|
||||
{
|
||||
$set = Account
|
||||
::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
$set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
->leftJoin('users', 'accounts.user_id', '=', 'users.id')
|
||||
->groupBy(['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email'])
|
||||
->whereNull('transactions.account_id')
|
||||
@ -125,8 +124,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function reportBudgetLimits()
|
||||
{
|
||||
$set = Budget
|
||||
::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
|
||||
$set = Budget::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
|
||||
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
|
||||
->groupBy(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email'])
|
||||
->whereNull('budget_limits.id')
|
||||
@ -148,8 +146,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function reportDeletedAccounts()
|
||||
{
|
||||
$set = Account
|
||||
::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
$set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->whereNotNull('accounts.deleted_at')
|
||||
->whereNotNull('transactions.id')
|
||||
@ -187,8 +184,7 @@ class VerifyDatabase extends Command
|
||||
TransactionType::TRANSFER => [AccountType::EXPENSE, AccountType::REVENUE],
|
||||
];
|
||||
foreach ($configuration as $transactionType => $accountTypes) {
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
$set = TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin('account_types', 'account_types.id', 'accounts.account_type_id')
|
||||
@ -218,8 +214,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function reportJournals()
|
||||
{
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNotNull('transaction_journals.deleted_at')// USE THIS
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNotNull('transactions.id')
|
||||
@ -245,8 +240,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function reportNoTransactions()
|
||||
{
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->groupBy('transaction_journals.id')
|
||||
->whereNull('transactions.transaction_journal_id')
|
||||
->get(['transaction_journals.id']);
|
||||
@ -335,8 +329,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function reportTransfersBudgets()
|
||||
{
|
||||
$set = TransactionJournal
|
||||
::distinct()
|
||||
$set = TransactionJournal::distinct()
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
||||
->where('transaction_types.type', TransactionType::TRANSFER)
|
||||
|
@ -292,8 +292,7 @@ class JournalExportCollector extends BasicCollector implements CollectorInterfac
|
||||
private function getWorkSet()
|
||||
{
|
||||
$accountIds = $this->accounts->pluck('id')->toArray();
|
||||
$this->workSet = Transaction
|
||||
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
$this->workSet = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin(
|
||||
'transactions AS opposing', function (JoinClause $join) {
|
||||
$join->on('opposing.transaction_journal_id', '=', 'transactions.transaction_journal_id')
|
||||
|
@ -44,4 +44,11 @@ interface BudgetChartGeneratorInterface
|
||||
* @return array
|
||||
*/
|
||||
public function period(array $entries): array;
|
||||
|
||||
/**
|
||||
* @param array $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodNoBudget(array $entries): array;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function period(array $entries) : array
|
||||
public function period(array $entries): array
|
||||
{
|
||||
|
||||
$data = [
|
||||
@ -133,4 +133,32 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodNoBudget(array $entries): array
|
||||
{
|
||||
$data = [
|
||||
'labels' => array_keys($entries),
|
||||
'datasets' => [
|
||||
0 => [
|
||||
'label' => trans('firefly.spent'),
|
||||
'data' => [],
|
||||
],
|
||||
],
|
||||
'count' => 1,
|
||||
];
|
||||
|
||||
foreach ($entries as $label => $entry) {
|
||||
// data set 0 is budgeted
|
||||
// data set 1 is spent:
|
||||
$data['datasets'][0]['data'][] = round(($entry['spent'] * -1), 2);
|
||||
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface CategoryChartGeneratorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
@ -58,4 +57,11 @@ interface CategoryChartGeneratorInterface
|
||||
*/
|
||||
public function pieChart(array $data): array;
|
||||
|
||||
/**
|
||||
* @param array $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function reportPeriod(array $entries): array;
|
||||
|
||||
}
|
||||
|
@ -142,6 +142,41 @@ class ChartJsCategoryChartGenerator implements CategoryChartGeneratorInterface
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function reportPeriod(array $entries): array
|
||||
{
|
||||
|
||||
$data = [
|
||||
'labels' => array_keys($entries),
|
||||
'datasets' => [
|
||||
0 => [
|
||||
'label' => trans('firefly.earned'),
|
||||
'data' => [],
|
||||
],
|
||||
1 => [
|
||||
'label' => trans('firefly.spent'),
|
||||
'data' => [],
|
||||
],
|
||||
],
|
||||
'count' => 2,
|
||||
];
|
||||
|
||||
foreach ($entries as $label => $entry) {
|
||||
// data set 0 is budgeted
|
||||
// data set 1 is spent:
|
||||
$data['datasets'][0]['data'][] = round($entry['earned'], 2);
|
||||
$data['datasets'][1]['data'][] = round(bcmul($entry['spent'], '-1'), 2);
|
||||
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $entries
|
||||
*
|
||||
|
@ -29,7 +29,7 @@ class ChartJsReportChartGenerator implements ReportChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function multiYearInOut(Collection $entries): array
|
||||
public function multiYearOperations(Collection $entries): array
|
||||
{
|
||||
$data = [
|
||||
'count' => 2,
|
||||
@ -62,7 +62,7 @@ class ChartJsReportChartGenerator implements ReportChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function multiYearInOutSummarized(string $income, string $expense, int $count): array
|
||||
public function multiYearSum(string $income, string $expense, int $count): array
|
||||
{
|
||||
$data = [
|
||||
'count' => 2,
|
||||
@ -117,7 +117,7 @@ class ChartJsReportChartGenerator implements ReportChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOut(Collection $entries): array
|
||||
public function yearOperations(Collection $entries): array
|
||||
{
|
||||
// language:
|
||||
$format = (string)trans('config.month');
|
||||
@ -153,7 +153,7 @@ class ChartJsReportChartGenerator implements ReportChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOutSummarized(string $income, string $expense, int $count): array
|
||||
public function yearSum(string $income, string $expense, int $count): array
|
||||
{
|
||||
|
||||
$data = [
|
||||
|
@ -28,7 +28,7 @@ interface ReportChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function multiYearInOut(Collection $entries): array;
|
||||
public function multiYearOperations(Collection $entries): array;
|
||||
|
||||
/**
|
||||
* @param string $income
|
||||
@ -37,7 +37,7 @@ interface ReportChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function multiYearInOutSummarized(string $income, string $expense, int $count): array;
|
||||
public function multiYearSum(string $income, string $expense, int $count): array;
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
@ -51,7 +51,7 @@ interface ReportChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOut(Collection $entries): array;
|
||||
public function yearOperations(Collection $entries): array;
|
||||
|
||||
/**
|
||||
* @param string $income
|
||||
@ -60,6 +60,6 @@ interface ReportChartGeneratorInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOutSummarized(string $income, string $expense, int $count): array;
|
||||
public function yearSum(string $income, string $expense, int $count): array;
|
||||
|
||||
}
|
||||
|
@ -78,9 +78,9 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
$auditData[$id]['dayBeforeBalance'] = $dayBeforeBalance;
|
||||
}
|
||||
|
||||
$reportType = 'audit';
|
||||
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
|
||||
|
||||
$defaultShow = ['icon', 'description', 'balance_before', 'amount', 'balance_after', 'date', 'to'];
|
||||
$reportType = 'audit';
|
||||
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
|
||||
$hideable = ['buttons', 'icon', 'description', 'balance_before', 'amount', 'balance_after', 'date',
|
||||
'interest_date', 'book_date', 'process_date',
|
||||
// three new optional fields.
|
||||
@ -88,10 +88,9 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
'from', 'to', 'budget', 'category', 'bill',
|
||||
// more new optional fields
|
||||
'internal_reference', 'notes',
|
||||
|
||||
'create_date', 'update_date',
|
||||
];
|
||||
$defaultShow = ['icon', 'description', 'balance_before', 'amount', 'balance_after', 'date', 'to'];
|
||||
|
||||
|
||||
return view('reports.audit.report', compact('reportType', 'accountIds', 'auditData', 'hideable', 'defaultShow'))
|
||||
->with('start', $this->start)->with('end', $this->end)->with('accounts', $this->accounts)
|
||||
|
@ -148,8 +148,6 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
// is not set?
|
||||
if (!isset($result[$opposingId])) {
|
||||
$name = $transaction->opposing_account_name;
|
||||
$encrypted = intval($transaction->opposing_account_encrypted);
|
||||
$name = $encrypted === 1 ? Crypt::decrypt($name) : $name;
|
||||
$result[$opposingId] = [
|
||||
'name' => $name,
|
||||
'count' => 1,
|
||||
@ -267,14 +265,6 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
{
|
||||
$transactions = $this->getExpenses()->sortBy('transaction_amount');
|
||||
|
||||
$transactions = $transactions->each(
|
||||
function (Transaction $transaction) {
|
||||
if (intval($transaction->opposing_account_encrypted) === 1) {
|
||||
$transaction->opposing_account_name = Crypt::decrypt($transaction->opposing_account_name);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
@ -285,14 +275,6 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
{
|
||||
$transactions = $this->getIncome()->sortByDesc('transaction_amount');
|
||||
|
||||
$transactions = $transactions->each(
|
||||
function (Transaction $transaction) {
|
||||
if (intval($transaction->opposing_account_encrypted) === 1) {
|
||||
$transaction->opposing_account_name = Crypt::decrypt($transaction->opposing_account_name);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
|
@ -34,25 +34,25 @@ class BudgetEventHandler
|
||||
/**
|
||||
* This method creates a new budget limit repetition when a new budget limit has been created.
|
||||
*
|
||||
* @param StoredBudgetLimit $event
|
||||
* @param StoredBudgetLimit $budgetLimitEvent
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function storeRepetition(StoredBudgetLimit $event):bool
|
||||
public function storeRepetition(StoredBudgetLimit $budgetLimitEvent):bool
|
||||
{
|
||||
return $this->processRepetitionChange($event->budgetLimit, $event->end);
|
||||
return $this->processRepetitionChange($budgetLimitEvent->budgetLimit, $budgetLimitEvent->end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates, if present the budget limit repetition part of a budget limit.
|
||||
*
|
||||
* @param UpdatedBudgetLimit $event
|
||||
* @param UpdatedBudgetLimit $budgetLimitEvent
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function updateRepetition(UpdatedBudgetLimit $event): bool
|
||||
public function updateRepetition(UpdatedBudgetLimit $budgetLimitEvent): bool
|
||||
{
|
||||
return $this->processRepetitionChange($event->budgetLimit, $event->end);
|
||||
return $this->processRepetitionChange($budgetLimitEvent->budgetLimit, $budgetLimitEvent->end);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,15 +33,15 @@ class StoredJournalEventHandler
|
||||
/**
|
||||
* This method connects a new transfer to a piggy bank.
|
||||
*
|
||||
* @param StoredTransactionJournal $event
|
||||
* @param StoredTransactionJournal $storedJournalEvent
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function connectToPiggyBank(StoredTransactionJournal $event): bool
|
||||
public function connectToPiggyBank(StoredTransactionJournal $storedJournalEvent): bool
|
||||
{
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $event->journal;
|
||||
$piggyBankId = $event->piggyBankId;
|
||||
$journal = $storedJournalEvent->journal;
|
||||
$piggyBankId = $storedJournalEvent->piggyBankId;
|
||||
|
||||
Log::debug(sprintf('Trying to connect journal %d to piggy bank %d.', $journal->id, $piggyBankId));
|
||||
|
||||
@ -101,11 +101,11 @@ class StoredJournalEventHandler
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
/** @var PiggyBankEvent $event */
|
||||
$event = PiggyBankEvent::create(
|
||||
/** @var PiggyBankEvent $storedJournalEvent */
|
||||
$storedJournalEvent = PiggyBankEvent::create(
|
||||
['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]
|
||||
);
|
||||
Log::debug(sprintf('Created piggy bank event #%d', $event->id));
|
||||
Log::debug(sprintf('Created piggy bank event #%d', $storedJournalEvent->id));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -113,14 +113,14 @@ class StoredJournalEventHandler
|
||||
/**
|
||||
* This method grabs all the users rules and processes them.
|
||||
*
|
||||
* @param StoredTransactionJournal $event
|
||||
* @param StoredTransactionJournal $storedJournalEvent
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function processRules(StoredTransactionJournal $event): bool
|
||||
public function processRules(StoredTransactionJournal $storedJournalEvent): bool
|
||||
{
|
||||
// get all the user's rule groups, with the rules, order by 'order'.
|
||||
$journal = $event->journal;
|
||||
$journal = $storedJournalEvent->journal;
|
||||
$groups = $journal->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||
//
|
||||
/** @var RuleGroup $group */
|
||||
@ -150,13 +150,13 @@ class StoredJournalEventHandler
|
||||
/**
|
||||
* This method calls a special bill scanner that will check if the stored journal is part of a bill.
|
||||
*
|
||||
* @param StoredTransactionJournal $event
|
||||
* @param StoredTransactionJournal $storedJournalEvent
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function scanBills(StoredTransactionJournal $event): bool
|
||||
public function scanBills(StoredTransactionJournal $storedJournalEvent): bool
|
||||
{
|
||||
$journal = $event->journal;
|
||||
$journal = $storedJournalEvent->journal;
|
||||
BillScanner::scan($journal);
|
||||
|
||||
return true;
|
||||
|
@ -31,14 +31,14 @@ class UpdatedJournalEventHandler
|
||||
/**
|
||||
* This method will check all the rules when a journal is updated.
|
||||
*
|
||||
* @param UpdatedTransactionJournal $event
|
||||
* @param UpdatedTransactionJournal $updatedJournalEvent
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function processRules(UpdatedTransactionJournal $event):bool
|
||||
public function processRules(UpdatedTransactionJournal $updatedJournalEvent):bool
|
||||
{
|
||||
// get all the user's rule groups, with the rules, order by 'order'.
|
||||
$journal = $event->journal;
|
||||
$journal = $updatedJournalEvent->journal;
|
||||
$groups = $journal->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get();
|
||||
//
|
||||
/** @var RuleGroup $group */
|
||||
@ -67,13 +67,13 @@ class UpdatedJournalEventHandler
|
||||
/**
|
||||
* This method calls a special bill scanner that will check if the updated journal is part of a bill.
|
||||
*
|
||||
* @param UpdatedTransactionJournal $event
|
||||
* @param UpdatedTransactionJournal $updatedJournalEvent
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function scanBills(UpdatedTransactionJournal $event): bool
|
||||
public function scanBills(UpdatedTransactionJournal $updatedJournalEvent): bool
|
||||
{
|
||||
$journal = $event->journal;
|
||||
$journal = $updatedJournalEvent->journal;
|
||||
BillScanner::scan($journal);
|
||||
|
||||
return true;
|
||||
|
@ -1,85 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Expense.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class Expense
|
||||
*
|
||||
* @package FireflyIII\Helpers\Collection
|
||||
*/
|
||||
class Expense
|
||||
{
|
||||
/** @var Collection */
|
||||
protected $expenses;
|
||||
/** @var string */
|
||||
protected $total = '0';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->expenses = new Collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stdClass $entry
|
||||
*/
|
||||
public function addOrCreateExpense(stdClass $entry)
|
||||
{
|
||||
$this->expenses->put($entry->id, $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*/
|
||||
public function addToTotal(string $add)
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
if (bccomp('0', $add) === -1) {
|
||||
$add = bcmul($add, '-1');
|
||||
}
|
||||
|
||||
// if amount is positive, the original transaction
|
||||
// was a transfer. But since this is an expense report,
|
||||
// that amount must be negative.
|
||||
|
||||
$this->total = bcadd($this->total, $add);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getExpenses(): Collection
|
||||
{
|
||||
$set = $this->expenses->sortBy(
|
||||
function (stdClass $object) {
|
||||
return $object->amount;
|
||||
}
|
||||
);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTotal(): string
|
||||
{
|
||||
return strval(round($this->total, 2));
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Income.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class Income
|
||||
*
|
||||
* @package FireflyIII\Helpers\Collection
|
||||
*/
|
||||
class Income
|
||||
{
|
||||
|
||||
/** @var Collection */
|
||||
protected $incomes;
|
||||
/** @var string */
|
||||
protected $total = '0';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->incomes = new Collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stdClass $entry
|
||||
*/
|
||||
public function addOrCreateIncome(stdClass $entry)
|
||||
{
|
||||
$this->incomes->put($entry->id, $entry);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*/
|
||||
public function addToTotal(string $add)
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->total = bcadd($this->total, $add);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getIncomes(): Collection
|
||||
{
|
||||
$set = $this->incomes->sortByDesc(
|
||||
function (stdClass $object) {
|
||||
return $object->amount;
|
||||
}
|
||||
);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTotal(): string
|
||||
{
|
||||
return strval(round($this->total, 2));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,4 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* JournalCollector.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collector;
|
||||
@ -16,6 +26,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@ -60,6 +71,8 @@ class JournalCollector implements JournalCollectorInterface
|
||||
'account_types.type as account_type',
|
||||
];
|
||||
/** @var bool */
|
||||
private $filterInternalTransfers;
|
||||
/** @var bool */
|
||||
private $filterTransfers = false;
|
||||
/** @var bool */
|
||||
private $joinedBudget = false;
|
||||
@ -127,6 +140,26 @@ class JournalCollector implements JournalCollectorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function disableInternalFilter(): JournalCollectorInterface
|
||||
{
|
||||
$this->filterInternalTransfers = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function enableInternalFilter(): JournalCollectorInterface
|
||||
{
|
||||
$this->filterInternalTransfers = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
@ -138,12 +171,25 @@ class JournalCollector implements JournalCollectorInterface
|
||||
$set = $this->filterTransfers($set);
|
||||
Log::debug(sprintf('Count of set after filterTransfers() is %d', $set->count()));
|
||||
|
||||
// possibly filter "internal" transfers:
|
||||
$set = $this->filterInternalTransfers($set);
|
||||
Log::debug(sprintf('Count of set after filterInternalTransfers() is %d', $set->count()));
|
||||
|
||||
|
||||
// loop for decryption.
|
||||
$set->each(
|
||||
function (Transaction $transaction) {
|
||||
$transaction->date = new Carbon($transaction->date);
|
||||
$transaction->description = intval($transaction->encrypted) === 1 ? Crypt::decrypt($transaction->description) : $transaction->description;
|
||||
$transaction->bill_name = !is_null($transaction->bill_name) ? Crypt::decrypt($transaction->bill_name) : '';
|
||||
|
||||
// optionally decrypted:
|
||||
try {
|
||||
$transaction->opposing_account_name = Crypt::decrypt($transaction->opposing_account_name);
|
||||
} catch (DecryptException $e) {
|
||||
// if this fails its already decrypted.
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
@ -501,6 +547,47 @@ class JournalCollector implements JournalCollectorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function filterInternalTransfers(Collection $set): Collection
|
||||
{
|
||||
if ($this->filterInternalTransfers === false) {
|
||||
Log::debug('Did NO filtering for internal transfers on given set.');
|
||||
|
||||
return $set;
|
||||
}
|
||||
if ($this->joinedOpposing === false) {
|
||||
Log::error('Cannot filter internal transfers because no opposing information is present.');
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
$accountIds = $this->accountIds;
|
||||
$set = $set->filter(
|
||||
function (Transaction $transaction) use ($accountIds) {
|
||||
// both id's in $accountids?
|
||||
if (in_array($transaction->account_id, $accountIds) && in_array($transaction->opposing_account_id, $accountIds)) {
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Transaction #%d has #%d and #%d in set, so removed',
|
||||
$transaction->id, $transaction->account_id, $transaction->opposing_account_id
|
||||
), $accountIds
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $transaction;
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the set of accounts used by the collector includes more than one asset
|
||||
* account, chances are the set include double entries: transfers get selected
|
||||
@ -583,6 +670,7 @@ class JournalCollector implements JournalCollectorInterface
|
||||
private function joinOpposingTables()
|
||||
{
|
||||
if (!$this->joinedOpposing) {
|
||||
Log::debug('joinedOpposing is false');
|
||||
// join opposing transaction (hard):
|
||||
$this->query->leftJoin(
|
||||
'transactions as opposing', function (JoinClause $join) {
|
||||
@ -595,11 +683,12 @@ class JournalCollector implements JournalCollectorInterface
|
||||
$this->query->leftJoin('account_types as opposing_account_types', 'opposing_accounts.account_type_id', '=', 'opposing_account_types.id');
|
||||
$this->query->whereNull('opposing.deleted_at');
|
||||
|
||||
$this->fields[] = 'opposing.account_id as opposing_account_id';
|
||||
$this->fields[] = 'opposing_accounts.name as opposing_account_name';
|
||||
$this->fields[] = 'opposing_accounts.encrypted as opposing_account_encrypted';
|
||||
$this->fields[] = 'opposing_account_types.type as opposing_account_type';
|
||||
|
||||
$this->fields[] = 'opposing.account_id as opposing_account_id';
|
||||
$this->fields[] = 'opposing_accounts.name as opposing_account_name';
|
||||
$this->fields[] = 'opposing_accounts.encrypted as opposing_account_encrypted';
|
||||
$this->fields[] = 'opposing_account_types.type as opposing_account_type';
|
||||
$this->joinedOpposing = true;
|
||||
Log::debug('joinedOpposing is now true!');
|
||||
}
|
||||
}
|
||||
|
||||
@ -621,19 +710,18 @@ class JournalCollector implements JournalCollectorInterface
|
||||
private function startQuery(): EloquentBuilder
|
||||
{
|
||||
|
||||
$query = Transaction
|
||||
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', 'transaction_journals.transaction_currency_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('bills', 'bills.id', 'transaction_journals.bill_id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin('account_types', 'accounts.account_type_id', 'account_types.id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC');
|
||||
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', 'transaction_journals.transaction_currency_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('bills', 'bills.id', 'transaction_journals.bill_id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin('account_types', 'accounts.account_type_id', 'account_types.id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC');
|
||||
|
||||
return $query;
|
||||
|
||||
|
@ -38,6 +38,16 @@ interface JournalCollectorInterface
|
||||
*/
|
||||
public function disableFilter(): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function disableInternalFilter(): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function enableInternalFilter(): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
@ -46,7 +56,7 @@ interface JournalCollectorInterface
|
||||
/**
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function getPaginatedJournals():LengthAwarePaginator;
|
||||
public function getPaginatedJournals(): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
|
@ -120,7 +120,6 @@ class Help implements HelpInterface
|
||||
* @param string $language
|
||||
* @param string $content
|
||||
*
|
||||
* @internal param $title
|
||||
*/
|
||||
public function putInCache(string $route, string $language, string $content)
|
||||
{
|
||||
|
@ -51,13 +51,13 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return Balance
|
||||
*/
|
||||
public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts): Balance
|
||||
public function getBalanceReport(Collection $accounts, Carbon $start, Carbon $end): Balance
|
||||
{
|
||||
$balance = new Balance;
|
||||
$header = new BalanceHeader;
|
||||
|
@ -26,11 +26,11 @@ use Illuminate\Support\Collection;
|
||||
interface BalanceReportHelperInterface
|
||||
{
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return Balance
|
||||
*/
|
||||
public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts): Balance;
|
||||
public function getBalanceReport(Collection $accounts, Carbon $start, Carbon $end): Balance;
|
||||
}
|
||||
|
@ -42,22 +42,6 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBudgetPeriodReport(Carbon $start, Carbon $end, Collection $accounts): array
|
||||
{
|
||||
$budgets = $this->repository->getBudgets();
|
||||
$report = $this->repository->getBudgetPeriodReport($budgets, $accounts, $start, $end);
|
||||
$data = $this->filterBudgetPeriodReport($report);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
@ -162,31 +146,4 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
return $array;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters empty results from getBudgetPeriodReport
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function filterBudgetPeriodReport(array $data): array
|
||||
{
|
||||
/**
|
||||
* @var int $budgetId
|
||||
* @var array $set
|
||||
*/
|
||||
foreach ($data as $budgetId => $set) {
|
||||
$sum = '0';
|
||||
foreach ($set['entries'] as $amount) {
|
||||
$sum = bcadd($amount, $sum);
|
||||
}
|
||||
$data[$budgetId]['sum'] = $sum;
|
||||
if (bccomp('0', $sum) === 0) {
|
||||
unset($data[$budgetId]);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -26,15 +26,6 @@ use Illuminate\Support\Collection;
|
||||
interface BudgetReportHelperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBudgetPeriodReport(Carbon $start, Carbon $end, Collection $accounts): array;
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
|
@ -17,19 +17,15 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collection\Bill as BillCollection;
|
||||
use FireflyIII\Helpers\Collection\BillLine;
|
||||
use FireflyIII\Helpers\Collection\Category as CategoryCollection;
|
||||
use FireflyIII\Helpers\Collection\Expense;
|
||||
use FireflyIII\Helpers\Collection\Income;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Helpers\FiscalHelperInterface;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class ReportHelper
|
||||
@ -118,7 +114,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
*
|
||||
* @return CategoryCollection
|
||||
*/
|
||||
public function getCategoryReport(Carbon $start, Carbon $end, Collection $accounts): CategoryCollection
|
||||
public function getCategoryReport(Collection $accounts, Carbon $start, Carbon $end): CategoryCollection
|
||||
{
|
||||
$object = new CategoryCollection;
|
||||
/** @var CategoryRepositoryInterface $repository */
|
||||
@ -136,57 +132,6 @@ class ReportHelper implements ReportHelperInterface
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a full report on the users expenses during the period for a list of accounts.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return Expense
|
||||
*/
|
||||
public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): Expense
|
||||
{
|
||||
$object = new Expense;
|
||||
|
||||
/** @var AccountTaskerInterface $tasker */
|
||||
$tasker = app(AccountTaskerInterface::class);
|
||||
$collection = $tasker->expenseReport($accounts, $accounts, $start, $end);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($collection as $entry) {
|
||||
$object->addToTotal($entry->amount);
|
||||
$object->addOrCreateExpense($entry);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a full report on the users incomes during the period for the given accounts.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return Income
|
||||
*/
|
||||
public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): Income
|
||||
{
|
||||
$object = new Income;
|
||||
/** @var AccountTaskerInterface $tasker */
|
||||
$tasker = app(AccountTaskerInterface::class);
|
||||
$collection = $tasker->incomeReport($accounts, $accounts, $start, $end);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($collection as $entry) {
|
||||
$object->addToTotal($entry->amount);
|
||||
$object->addOrCreateIncome($entry);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -49,29 +49,7 @@ interface ReportHelperInterface
|
||||
*
|
||||
* @return CategoryCollection
|
||||
*/
|
||||
public function getCategoryReport(Carbon $start, Carbon $end, Collection $accounts): CategoryCollection;
|
||||
|
||||
/**
|
||||
* Get a full report on the users expenses during the period for a list of accounts.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return Expense
|
||||
*/
|
||||
public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): Expense;
|
||||
|
||||
/**
|
||||
* Get a full report on the users incomes during the period for the given accounts.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return Income
|
||||
*/
|
||||
public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): Income;
|
||||
public function getCategoryReport(Collection $accounts, Carbon $start, Carbon $end): CategoryCollection;
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
|
@ -171,6 +171,7 @@ class AccountController extends Controller
|
||||
'accountRole' => $account->getMeta('accountRole'),
|
||||
'ccType' => $account->getMeta('ccType'),
|
||||
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
|
||||
'BIC' => $account->getMeta('BIC'),
|
||||
'openingBalanceDate' => $openingBalanceDate,
|
||||
'openingBalance' => $openingBalanceAmount,
|
||||
'virtualBalance' => $account->virtual_balance,
|
||||
@ -281,7 +282,7 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function showWithDate(Account $account, string $date)
|
||||
public function showByDate(Account $account, string $date)
|
||||
{
|
||||
$carbon = new Carbon($date);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
@ -297,7 +298,7 @@ class AccountController extends Controller
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('accounts/show/' . $account->id . '/' . $date);
|
||||
|
||||
return view('accounts.show_with_date', compact('category', 'date', 'account', 'journals', 'subTitle', 'carbon', 'start', 'end'));
|
||||
return view('accounts.show-by-date', compact('category', 'date', 'account', 'journals', 'subTitle', 'carbon', 'start', 'end'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,7 +71,7 @@ class ConfigurationController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(ConfigurationRequest $request)
|
||||
public function postIndex(ConfigurationRequest $request)
|
||||
{
|
||||
// get config values:
|
||||
$data = $request->getConfigurationData();
|
||||
|
@ -38,10 +38,16 @@ class TwoFactorController extends Controller
|
||||
$user = auth()->user();
|
||||
|
||||
// to make sure the validator in the next step gets the secret, we push it in session
|
||||
$secret = Preferences::get('twoFactorAuthSecret', '')->data;
|
||||
$secret = Preferences::get('twoFactorAuthSecret', null)->data;
|
||||
$title = strval(trans('firefly.two_factor_title'));
|
||||
|
||||
if (strlen($secret) === 0) {
|
||||
// make sure the user has two factor configured:
|
||||
$has2FA = Preferences::get('twoFactorAuthEnabled', null)->data;
|
||||
if (is_null($has2FA) || $has2FA === false) {
|
||||
return redirect(route('index'));
|
||||
}
|
||||
|
||||
if (strlen(strval($secret)) === 0) {
|
||||
throw new FireflyException('Your two factor authentication secret is empty, which it cannot be at this point. Please check the log files.');
|
||||
}
|
||||
Session::flash('two-factor-secret', $secret);
|
||||
|
@ -332,7 +332,7 @@ class BudgetController extends Controller
|
||||
* @return View
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function showWithRepetition(Budget $budget, LimitRepetition $repetition)
|
||||
public function showByRepetition(Budget $budget, LimitRepetition $repetition)
|
||||
{
|
||||
if ($repetition->budgetLimit->budget->id != $budget->id) {
|
||||
throw new FireflyException('This budget limit is not part of this budget.');
|
||||
|
@ -245,7 +245,7 @@ class CategoryController extends Controller
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function showWithDate(Category $category, string $date)
|
||||
public function showByDate(Category $category, string $date)
|
||||
{
|
||||
$carbon = new Carbon($date);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
@ -263,7 +263,7 @@ class CategoryController extends Controller
|
||||
$journals->setPath('categories/show/' . $category->id . '/' . $date);
|
||||
|
||||
|
||||
return view('categories.show_with_date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon'));
|
||||
return view('categories.show-by-date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,7 +112,7 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function expenseByBudget(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
public function expenseBudget(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($account->id);
|
||||
@ -153,7 +153,7 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function expenseByCategory(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
public function expenseCategory(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($account->id);
|
||||
@ -199,7 +199,7 @@ class AccountController extends Controller
|
||||
$frontPage = Preferences::get('frontPageAccounts', $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray());
|
||||
$accounts = $repository->getAccountsById($frontPage->data);
|
||||
|
||||
return Response::json($this->accountBalanceChart($start, $end, $accounts));
|
||||
return Response::json($this->accountBalanceChart($accounts, $start, $end));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -210,7 +210,7 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function incomeByCategory(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
public function incomeCategory(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($account->id);
|
||||
@ -251,9 +251,9 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function report(Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function report(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
return Response::json($this->accountBalanceChart($start, $end, $accounts));
|
||||
return Response::json($this->accountBalanceChart($accounts, $start, $end));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -406,13 +406,13 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function accountBalanceChart(Carbon $start, Carbon $end, Collection $accounts): array
|
||||
private function accountBalanceChart(Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
|
@ -193,7 +193,7 @@ class BudgetController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function period(BudgetRepositoryInterface $repository, Budget $budget, Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function period(BudgetRepositoryInterface $repository, Budget $budget, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
@ -209,7 +209,7 @@ class BudgetController extends Controller
|
||||
|
||||
// the expenses:
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$entries = $repository->getBudgetPeriodReport(new Collection([$budget]), $accounts, $start, $end);
|
||||
$entries = $repository->getBudgetPeriodReport(new Collection([$budget]), $accounts, $start, $end, false);
|
||||
$budgeted = [];
|
||||
$key = Navigation::preferredCarbonFormat($start, $end);
|
||||
$range = Navigation::preferredRangeFormat($start, $end);
|
||||
@ -252,6 +252,47 @@ class BudgetController extends Controller
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function periodNoBudget(BudgetRepositoryInterface $repository, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($accounts);
|
||||
$cache->addProperty('no-budget');
|
||||
$cache->addProperty('period');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
|
||||
// the expenses:
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$entries = $repository->getNoBudgetPeriodReport($accounts, $start, $end);
|
||||
|
||||
// join them:
|
||||
$result = [];
|
||||
foreach (array_keys($periods) as $period) {
|
||||
$nice = $periods[$period];
|
||||
$result[$nice] = [
|
||||
'spent' => isset($entries['entries'][$period]) ? $entries['entries'][$period] : '0',
|
||||
];
|
||||
}
|
||||
|
||||
$data = $this->generator->periodNoBudget($result);
|
||||
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $repetitions
|
||||
* @param Budget $budget
|
||||
|
@ -152,6 +152,84 @@ class CategoryController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CRI $repository
|
||||
* @param Category $category
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse|mixed
|
||||
*/
|
||||
public function reportPeriod(CRI $repository, Category $category, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category-period-chart');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
$cache->addProperty($category);
|
||||
if ($cache->has()) {
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
$expenses = $repository->periodExpenses(new Collection([$category]), $accounts, $start, $end);
|
||||
$income = $repository->periodIncome(new Collection([$category]), $accounts, $start, $end);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
|
||||
|
||||
// join them:
|
||||
$result = [];
|
||||
foreach (array_keys($periods) as $period) {
|
||||
$nice = $periods[$period];
|
||||
$result[$nice] = [
|
||||
'earned' => $income[$category->id]['entries'][$period] ?? '0',
|
||||
'spent' => $expenses[$category->id]['entries'][$period] ?? '0',
|
||||
];
|
||||
}
|
||||
$data = $this->generator->reportPeriod($result);
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CRI $repository
|
||||
* @param Category $category
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse|mixed
|
||||
*/
|
||||
public function reportPeriodNoCategory(CRI $repository, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('no-category-period-chart');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
$expenses = $repository->periodExpensesNoCategory($accounts, $start, $end);
|
||||
$income = $repository->periodIncomeNoCategory($accounts, $start, $end);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
|
||||
// join them:
|
||||
$result = [];
|
||||
foreach (array_keys($periods) as $period) {
|
||||
$nice = $periods[$period];
|
||||
$result[$nice] = [
|
||||
'earned' => $income['entries'][$period] ?? '0',
|
||||
'spent' => $expenses['entries'][$period] ?? '0',
|
||||
];
|
||||
}
|
||||
$data = $this->generator->reportPeriod($result);
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CRI $repository
|
||||
* @param Category $category
|
||||
|
@ -49,13 +49,12 @@ class ReportController extends Controller
|
||||
* This chart, by default, is shown on the multi-year and year report pages,
|
||||
* which means that giving it a 2 week "period" should be enough granularity.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function netWorth(Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function netWorth(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
@ -90,13 +89,16 @@ class ReportController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Shows income and expense, debet/credit: operations
|
||||
*
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function yearInOut(Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function operations(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
@ -112,14 +114,14 @@ class ReportController extends Controller
|
||||
|
||||
if ($start->diffInMonths($end) > 12) {
|
||||
// data = method X
|
||||
$data = $this->multiYearInOut($chartSource['earned'], $chartSource['spent'], $start, $end);
|
||||
$data = $this->multiYearOperations($chartSource['earned'], $chartSource['spent'], $start, $end);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
// data = method Y
|
||||
$data = $this->singleYearInOut($chartSource['earned'], $chartSource['spent'], $start, $end);
|
||||
$data = $this->singleYearOperations($chartSource['earned'], $chartSource['spent'], $start, $end);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
@ -128,14 +130,14 @@ class ReportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows sum income and expense, debet/credit: operations
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @internal param AccountRepositoryInterface $repository
|
||||
*/
|
||||
public function yearInOutSummarized(Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function sum(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
||||
// chart properties for cache:
|
||||
@ -151,13 +153,13 @@ class ReportController extends Controller
|
||||
|
||||
if ($start->diffInMonths($end) > 12) {
|
||||
// per year
|
||||
$data = $this->multiYearInOutSummarized($chartSource['earned'], $chartSource['spent'], $start, $end);
|
||||
$data = $this->multiYearSum($chartSource['earned'], $chartSource['spent'], $start, $end);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
// per month!
|
||||
$data = $this->singleYearInOutSummarized($chartSource['earned'], $chartSource['spent'], $start, $end);
|
||||
$data = $this->singleYearSum($chartSource['earned'], $chartSource['spent'], $start, $end);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
@ -172,7 +174,7 @@ class ReportController extends Controller
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function multiYearInOut(array $earned, array $spent, Carbon $start, Carbon $end)
|
||||
protected function multiYearOperations(array $earned, array $spent, Carbon $start, Carbon $end)
|
||||
{
|
||||
$entries = new Collection;
|
||||
while ($start < $end) {
|
||||
@ -184,7 +186,7 @@ class ReportController extends Controller
|
||||
$start->addYear();
|
||||
}
|
||||
|
||||
$data = $this->generator->multiYearInOut($entries);
|
||||
$data = $this->generator->multiYearOperations($entries);
|
||||
|
||||
return $data;
|
||||
}
|
||||
@ -197,7 +199,7 @@ class ReportController extends Controller
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function multiYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end)
|
||||
protected function multiYearSum(array $earned, array $spent, Carbon $start, Carbon $end)
|
||||
{
|
||||
$income = '0';
|
||||
$expense = '0';
|
||||
@ -213,7 +215,7 @@ class ReportController extends Controller
|
||||
$start->addYear();
|
||||
}
|
||||
|
||||
$data = $this->generator->multiYearInOutSummarized($income, $expense, $count);
|
||||
$data = $this->generator->multiYearSum($income, $expense, $count);
|
||||
|
||||
return $data;
|
||||
}
|
||||
@ -245,7 +247,7 @@ class ReportController extends Controller
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function singleYearInOut(array $earned, array $spent, Carbon $start, Carbon $end)
|
||||
protected function singleYearOperations(array $earned, array $spent, Carbon $start, Carbon $end)
|
||||
{
|
||||
// per month? simply use each month.
|
||||
|
||||
@ -260,7 +262,7 @@ class ReportController extends Controller
|
||||
$start->addMonth();
|
||||
}
|
||||
|
||||
$data = $this->generator->yearInOut($entries);
|
||||
$data = $this->generator->yearOperations($entries);
|
||||
|
||||
return $data;
|
||||
}
|
||||
@ -273,7 +275,7 @@ class ReportController extends Controller
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function singleYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end)
|
||||
protected function singleYearSum(array $earned, array $spent, Carbon $start, Carbon $end)
|
||||
{
|
||||
$income = '0';
|
||||
$expense = '0';
|
||||
@ -289,7 +291,7 @@ class ReportController extends Controller
|
||||
$start->addMonth();
|
||||
}
|
||||
|
||||
$data = $this->generator->yearInOutSummarized($income, $expense, $count);
|
||||
$data = $this->generator->yearSum($income, $expense, $count);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
@ -60,14 +60,14 @@ class CurrencyController extends Controller
|
||||
$subTitle = trans('firefly.create_currency');
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (session('currency.create.fromStore') !== true) {
|
||||
Session::put('currency.create.url', URL::previous());
|
||||
if (session('currencies.create.fromStore') !== true) {
|
||||
Session::put('currencies.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('currency.create.fromStore');
|
||||
Session::forget('currencies.create.fromStore');
|
||||
Session::flash('gaEventCategory', 'currency');
|
||||
Session::flash('gaEventAction', 'create');
|
||||
|
||||
return view('currency.create', compact('subTitleIcon', 'subTitle'));
|
||||
return view('currencies.create', compact('subTitleIcon', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,7 +85,7 @@ class CurrencyController extends Controller
|
||||
Cache::forget('FFCURRENCYSYMBOL');
|
||||
Cache::forget('FFCURRENCYCODE');
|
||||
|
||||
return redirect(route('currency.index'));
|
||||
return redirect(route('currencies.index'));
|
||||
|
||||
}
|
||||
|
||||
@ -99,18 +99,18 @@ class CurrencyController extends Controller
|
||||
if (!$this->canDeleteCurrency($currency)) {
|
||||
Session::flash('error', trans('firefly.cannot_delete_currency', ['name' => $currency->name]));
|
||||
|
||||
return redirect(route('currency.index'));
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
|
||||
|
||||
// put previous url in session
|
||||
Session::put('currency.delete.url', URL::previous());
|
||||
Session::put('currencies.delete.url', URL::previous());
|
||||
Session::flash('gaEventCategory', 'currency');
|
||||
Session::flash('gaEventAction', 'delete');
|
||||
$subTitle = trans('form.delete_currency', ['name' => $currency->name]);
|
||||
|
||||
|
||||
return view('currency.delete', compact('currency', 'subTitle'));
|
||||
return view('currencies.delete', compact('currency', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,7 +124,7 @@ class CurrencyController extends Controller
|
||||
if (!$this->canDeleteCurrency($currency)) {
|
||||
Session::flash('error', trans('firefly.cannot_delete_currency', ['name' => $currency->name]));
|
||||
|
||||
return redirect(route('currency.index'));
|
||||
return redirect(route('currencies.index'));
|
||||
}
|
||||
|
||||
Session::flash('success', trans('firefly.deleted_currency', ['name' => $currency->name]));
|
||||
@ -132,7 +132,7 @@ class CurrencyController extends Controller
|
||||
$currency->forceDelete();
|
||||
}
|
||||
|
||||
return redirect(session('currency.delete.url'));
|
||||
return redirect(session('currencies.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,14 +147,14 @@ class CurrencyController extends Controller
|
||||
$currency->symbol = htmlentities($currency->symbol);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (session('currency.edit.fromUpdate') !== true) {
|
||||
Session::put('currency.edit.url', URL::previous());
|
||||
if (session('currencies.edit.fromUpdate') !== true) {
|
||||
Session::put('currencies.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('currency.edit.fromUpdate');
|
||||
Session::forget('currencies.edit.fromUpdate');
|
||||
Session::flash('gaEventCategory', 'currency');
|
||||
Session::flash('gaEventAction', 'edit');
|
||||
|
||||
return view('currency.edit', compact('currency', 'subTitle', 'subTitleIcon'));
|
||||
return view('currencies.edit', compact('currency', 'subTitle', 'subTitleIcon'));
|
||||
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ class CurrencyController extends Controller
|
||||
}
|
||||
|
||||
|
||||
return view('currency.index', compact('currencies', 'defaultCurrency'));
|
||||
return view('currencies.index', compact('currencies', 'defaultCurrency'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,7 +189,7 @@ class CurrencyController extends Controller
|
||||
if (!auth()->user()->hasRole('owner')) {
|
||||
Log::error('User ' . auth()->user()->id . ' is not admin, but tried to store a currency.');
|
||||
|
||||
return redirect(session('currency.create.url'));
|
||||
return redirect(session('currencies.create.url'));
|
||||
}
|
||||
|
||||
$data = $request->getCurrencyData();
|
||||
@ -197,13 +197,13 @@ class CurrencyController extends Controller
|
||||
Session::flash('success', trans('firefly.created_currency', ['name' => $currency->name]));
|
||||
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
Session::put('currency.create.fromStore', true);
|
||||
Session::put('currencies.create.fromStore', true);
|
||||
|
||||
return redirect(route('currency.create'))->withInput();
|
||||
return redirect(route('currencies.create'))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return redirect(session('currency.create.url'));
|
||||
return redirect(session('currencies.create.url'));
|
||||
|
||||
|
||||
}
|
||||
@ -226,13 +226,13 @@ class CurrencyController extends Controller
|
||||
|
||||
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
Session::put('currency.edit.fromUpdate', true);
|
||||
Session::put('currencies.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('currency.edit', [$currency->id]));
|
||||
return redirect(route('currencies.edit', [$currency->id]));
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return redirect(session('currency.edit.url'));
|
||||
return redirect(session('currencies.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,6 @@ class JsonController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @internal param ARI $accountRepository
|
||||
*/
|
||||
public function boxIn(AccountTaskerInterface $accountTasker, AccountRepositoryInterface $repository)
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ class ReportController extends Controller
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function info(Request $request)
|
||||
public function general(Request $request)
|
||||
{
|
||||
$attributes = $request->get('attributes') ?? [];
|
||||
$attributes = $this->parseAttributes($attributes);
|
||||
|
@ -74,7 +74,7 @@ class PreferencesController extends Controller
|
||||
Session::flash('success', strval(trans('firefly.pref_two_factor_auth_disabled')));
|
||||
Session::flash('info', strval(trans('firefly.pref_two_factor_auth_remove_it')));
|
||||
|
||||
return redirect(route('preferences'));
|
||||
return redirect(route('preferences.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,7 +122,7 @@ class PreferencesController extends Controller
|
||||
Session::flash('success', strval(trans('firefly.saved_preferences')));
|
||||
Preferences::mark();
|
||||
|
||||
return redirect(route('preferences'));
|
||||
return redirect(route('preferences.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -206,7 +206,7 @@ class PreferencesController extends Controller
|
||||
return redirect(route('preferences.code'));
|
||||
}
|
||||
|
||||
return redirect(route('preferences'));
|
||||
return redirect(route('preferences.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,7 +108,7 @@ class ProfileController extends Controller
|
||||
|
||||
Session::flash('success', strval(trans('firefly.password_changed')));
|
||||
|
||||
return redirect(route('profile'));
|
||||
return redirect(route('profile.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,13 +29,13 @@ class AccountController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function accountReport(Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function general(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
@ -47,9 +47,9 @@ class AccountController extends Controller
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
|
||||
/** @var AccountTaskerInterface $accountTasker */
|
||||
$accountTasker = app(AccountTaskerInterface::class);
|
||||
$accountReport = $accountTasker->getAccountReport($start, $end, $accounts);
|
||||
$accountReport = $accountTasker->getAccountReport($accounts, $start, $end);
|
||||
|
||||
$result = view('reports.partials.accounts', compact('accountReport'))->render();
|
||||
$cache->store($result);
|
||||
|
@ -30,13 +30,13 @@ class BalanceController extends Controller
|
||||
|
||||
/**
|
||||
* @param BalanceReportHelperInterface $helper
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function balanceReport(BalanceReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function general(BalanceReportHelperInterface $helper,Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ class BalanceController extends Controller
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$balance = $helper->getBalanceReport($start, $end, $accounts);
|
||||
$balance = $helper->getBalanceReport($accounts, $start, $end);
|
||||
|
||||
$result = view('reports.partials.balance', compact('balance'))->render();
|
||||
$cache->store($result);
|
||||
|
@ -17,6 +17,7 @@ namespace FireflyIII\Http\Controllers\Report;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Report\BudgetReportHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
@ -29,43 +30,16 @@ use Navigation;
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @param BudgetReportHelperInterface $helper
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function budgetPeriodReport(BudgetReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('budget-period-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$budgets = $helper->getBudgetPeriodReport($start, $end, $accounts);
|
||||
$result = view('reports.partials.budget-period', compact('budgets', 'periods'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BudgetReportHelperInterface $helper
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function budgetReport(BudgetReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function general(BudgetReportHelperInterface $helper, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
||||
// chart properties for cache:
|
||||
@ -86,4 +60,64 @@ class BudgetController extends Controller
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function period(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('budget-period-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
// generate budget report right here.
|
||||
/** @var BudgetRepositoryInterface $repository */
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
$budgets = $repository->getBudgets();
|
||||
$data = $repository->getBudgetPeriodReport($budgets, $accounts, $start, $end);
|
||||
$data[0] = $repository->getNoBudgetPeriodReport($accounts, $start, $end); // append report data for "no budget"
|
||||
$report = $this->filterBudgetPeriodReport($data);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
|
||||
$result = view('reports.partials.budget-period', compact('report', 'periods'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters empty results from getBudgetPeriodReport
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function filterBudgetPeriodReport(array $data): array
|
||||
{
|
||||
/**
|
||||
* @var int $budgetId
|
||||
* @var array $set
|
||||
*/
|
||||
foreach ($data as $budgetId => $set) {
|
||||
$sum = '0';
|
||||
foreach ($set['entries'] as $amount) {
|
||||
$sum = bcadd($amount, $sum);
|
||||
}
|
||||
$data[$budgetId]['sum'] = $sum;
|
||||
if (bccomp('0', $sum) === 0) {
|
||||
unset($data[$budgetId]);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -17,8 +17,12 @@ namespace FireflyIII\Http\Controllers\Report;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
|
||||
/**
|
||||
* Class CategoryController
|
||||
@ -27,16 +31,82 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function expenses(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category-period-expenses-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
Log::debug('Return report from cache');
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
/** @var CategoryRepositoryInterface $repository */
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
$categories = $repository->getCategories();
|
||||
$data = $repository->periodExpenses($categories, $accounts, $start, $end);
|
||||
$data[0] = $repository->periodExpensesNoCategory($accounts, $start, $end);
|
||||
$report = $this->filterReport($data);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$result = view('reports.partials.category-period', compact('report', 'periods'))->render();
|
||||
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function income(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category-period-income-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
Log::debug('Return report from cache');
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
/** @var CategoryRepositoryInterface $repository */
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
$categories = $repository->getCategories();
|
||||
$data = $repository->periodIncome($categories, $accounts, $start, $end);
|
||||
$data[0] = $repository->periodIncomeNoCategory($accounts, $start, $end);
|
||||
$report = $this->filterReport($data);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$result = view('reports.partials.category-period', compact('report', 'periods'))->render();
|
||||
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReportHelperInterface $helper
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function categoryReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function operations(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
@ -48,12 +118,56 @@ class CategoryController extends Controller
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$categories = $helper->getCategoryReport($start, $end, $accounts);
|
||||
/** @var CategoryRepositoryInterface $repository */
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
$categories = $repository->getCategories();
|
||||
$report = [];
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
$spent = $repository->spentInPeriod(new Collection([$category]), $accounts, $start, $end);
|
||||
if (bccomp($spent, '0') !== 0) {
|
||||
$report[$category->id] = ['name' => $category->name, 'spent' => $spent];
|
||||
}
|
||||
}
|
||||
|
||||
$result = view('reports.partials.categories', compact('categories'))->render();
|
||||
// sort the result
|
||||
// Obtain a list of columns
|
||||
$sum = [];
|
||||
foreach ($report as $categoryId => $row) {
|
||||
$sum[$categoryId] = floatval($row['spent']);
|
||||
}
|
||||
|
||||
array_multisort($sum, SORT_ASC, $report);
|
||||
|
||||
$result = view('reports.partials.categories', compact('report'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters empty results from category period report
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function filterReport(array $data): array
|
||||
{
|
||||
foreach ($data as $categoryId => $set) {
|
||||
$sum = '0';
|
||||
foreach ($set['entries'] as $amount) {
|
||||
$sum = bcadd($amount, $sum);
|
||||
}
|
||||
$data[$categoryId]['sum'] = $sum;
|
||||
if (bccomp('0', $sum) === 0) {
|
||||
unset($data[$categoryId]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* InOutController.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Report;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class InOutController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Report
|
||||
*/
|
||||
class InOutController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @param ReportHelperInterface $helper
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function expenseReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expense-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$expenses = $helper->getExpenseReport($start, $end, $accounts);
|
||||
|
||||
$result = view('reports.partials.expenses', compact('expenses'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReportHelperInterface $helper
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function incExpReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('inc-exp-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$incomes = $helper->getIncomeReport($start, $end, $accounts);
|
||||
$expenses = $helper->getExpenseReport($start, $end, $accounts);
|
||||
|
||||
$result = view('reports.partials.income-vs-expenses', compact('expenses', 'incomes'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReportHelperInterface $helper
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function incomeReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('income-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$incomes = $helper->getIncomeReport($start, $end, $accounts);
|
||||
|
||||
$result = view('reports.partials.income', compact('incomes'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
}
|
245
app/Http/Controllers/Report/OperationsController.php
Normal file
245
app/Http/Controllers/Report/OperationsController.php
Normal file
@ -0,0 +1,245 @@
|
||||
<?php
|
||||
/**
|
||||
* OperationsController.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Report;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class OperationsController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Report
|
||||
*/
|
||||
class OperationsController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function expenses(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expense-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
$expenses = $this->getExpenseReport($start, $end, $accounts);
|
||||
$result = view('reports.partials.expenses', compact('expenses'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function operations(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('inc-exp-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$incomes = $this->getIncomeReport($start, $end, $accounts);
|
||||
$expenses = $this->getExpenseReport($start, $end, $accounts);
|
||||
$incomeSum = array_sum(
|
||||
array_map(
|
||||
function ($item) {
|
||||
return $item['sum'];
|
||||
}, $incomes
|
||||
)
|
||||
);
|
||||
|
||||
$expensesSum = array_sum(
|
||||
array_map(
|
||||
function ($item) {
|
||||
return $item['sum'];
|
||||
}, $expenses
|
||||
)
|
||||
);
|
||||
|
||||
$result = view('reports.partials.operations', compact('incomeSum', 'expensesSum'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function income(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('income-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
//return $cache->get();
|
||||
}
|
||||
$income = $this->getIncomeReport($start, $end, $accounts);
|
||||
|
||||
$result = view('reports.partials.income', compact('income'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): array
|
||||
{
|
||||
// get all expenses for the given accounts in the given period!
|
||||
// also transfers!
|
||||
// get all transactions:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||
->withOpposingAccount()
|
||||
->enableInternalFilter();
|
||||
$transactions = $collector->getJournals();
|
||||
$transactions = $transactions->filter(
|
||||
function (Transaction $transaction) {
|
||||
// return negative amounts only.
|
||||
if (bccomp($transaction->transaction_amount, '0') === -1) {
|
||||
return $transaction;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
$expenses = $this->groupByOpposing($transactions);
|
||||
|
||||
// sort the result
|
||||
// Obtain a list of columns
|
||||
$sum = [];
|
||||
foreach ($expenses as $accountId => $row) {
|
||||
$sum[$accountId] = floatval($row['sum']);
|
||||
}
|
||||
|
||||
array_multisort($sum, SORT_ASC, $expenses);
|
||||
|
||||
return $expenses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): array
|
||||
{
|
||||
// get all expenses for the given accounts in the given period!
|
||||
// also transfers!
|
||||
// get all transactions:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||
->withOpposingAccount()
|
||||
->enableInternalFilter();
|
||||
$transactions = $collector->getJournals();
|
||||
$transactions = $transactions->filter(
|
||||
function (Transaction $transaction) {
|
||||
// return positive amounts only.
|
||||
if (bccomp($transaction->transaction_amount, '0') === 1) {
|
||||
return $transaction;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
$income = $this->groupByOpposing($transactions);
|
||||
|
||||
// sort the result
|
||||
// Obtain a list of columns
|
||||
$sum = [];
|
||||
foreach ($income as $accountId => $row) {
|
||||
$sum[$accountId] = floatval($row['sum']);
|
||||
}
|
||||
|
||||
array_multisort($sum, SORT_DESC, $income);
|
||||
|
||||
return $income;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $transactions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function groupByOpposing(Collection $transactions): array
|
||||
{
|
||||
$expenses = [];
|
||||
// join the result together:
|
||||
foreach ($transactions as $transaction) {
|
||||
$opposingId = $transaction->opposing_account_id;
|
||||
$name = $transaction->opposing_account_name;
|
||||
if (!isset($expenses[$opposingId])) {
|
||||
$expenses[$opposingId] = [
|
||||
'id' => $opposingId,
|
||||
'name' => $name,
|
||||
'sum' => '0',
|
||||
'count' => 0,
|
||||
];
|
||||
}
|
||||
$expenses[$opposingId]['sum'] = bcadd($expenses[$opposingId]['sum'], $transaction->transaction_amount);
|
||||
$expenses[$opposingId]['count']++;
|
||||
}
|
||||
|
||||
|
||||
return $expenses;
|
||||
}
|
||||
|
||||
}
|
@ -61,14 +61,13 @@ class ReportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function auditReport(Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function auditReport(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
if ($end < $start) {
|
||||
return view('error')->with('message', trans('firefly.end_after_start_date'));
|
||||
@ -97,15 +96,14 @@ class ReportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $categories
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function categoryReport(Carbon $start, Carbon $end, Collection $accounts, Collection $categories)
|
||||
public function categoryReport(Collection $accounts, Collection $categories, Carbon $start, Carbon $end)
|
||||
{
|
||||
if ($end < $start) {
|
||||
return view('error')->with('message', trans('firefly.end_after_start_date'));
|
||||
@ -134,14 +132,13 @@ class ReportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function defaultReport(Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function defaultReport(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
if ($end < $start) {
|
||||
return view('error')->with('message', trans('firefly.end_after_start_date'));
|
||||
@ -227,6 +224,12 @@ class ReportController extends Controller
|
||||
return redirect(route('reports.index'));
|
||||
}
|
||||
|
||||
if ($request->getCategoryList()->count() === 0 && $reportType === 'category') {
|
||||
Session::flash('error', trans('firefly.select_more_than_one_category'));
|
||||
|
||||
return redirect(route('reports.index'));
|
||||
}
|
||||
|
||||
if ($end < $start) {
|
||||
return view('error')->with('message', trans('firefly.end_after_start_date'));
|
||||
}
|
||||
@ -240,13 +243,13 @@ class ReportController extends Controller
|
||||
default:
|
||||
throw new FireflyException(sprintf('Firefly does not support the "%s"-report yet.', $reportType));
|
||||
case 'category':
|
||||
$uri = route('reports.report.category', [$start, $end, $accounts, $categories]);
|
||||
$uri = route('reports.report.category', [$accounts, $categories, $start, $end]);
|
||||
break;
|
||||
case 'default':
|
||||
$uri = route('reports.report.default', [$start, $end, $accounts]);
|
||||
$uri = route('reports.report.default', [$accounts, $start, $end]);
|
||||
break;
|
||||
case 'audit':
|
||||
$uri = route('reports.report.audit', [$start, $end, $accounts]);
|
||||
$uri = route('reports.report.audit', [$accounts, $start, $end]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,6 @@ class RuleController extends Controller
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return View
|
||||
* @internal param RuleRepositoryInterface $repository
|
||||
*/
|
||||
public function delete(Rule $rule)
|
||||
{
|
||||
|
@ -15,14 +15,12 @@ namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
||||
use FireflyIII\Http\Requests\TagFormRequest;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
@ -170,33 +168,14 @@ class TagController extends Controller
|
||||
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $state
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function hideTagHelp(string $state)
|
||||
{
|
||||
|
||||
$newState = $state == 'true' ? true : false;
|
||||
Preferences::set('hideTagHelp', $newState);
|
||||
|
||||
return Response::json([true]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
/** @var Preference $helpHiddenPref */
|
||||
$helpHiddenPref = Preferences::get('hideTagHelp', false);
|
||||
$title = 'Tags';
|
||||
$mainTitleIcon = 'fa-tags';
|
||||
$helpHidden = $helpHiddenPref->data;
|
||||
|
||||
// group years.
|
||||
$types = ['nothing', 'balancingAct', 'advancePayment'];
|
||||
$title = 'Tags';
|
||||
$mainTitleIcon = 'fa-tags';
|
||||
$types = ['nothing', 'balancingAct', 'advancePayment'];
|
||||
|
||||
// loop each types and get the tags, group them by year.
|
||||
$collection = [];
|
||||
@ -223,7 +202,7 @@ class TagController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
return view('tags.index', compact('title', 'mainTitleIcon', 'types', 'helpHidden', 'collection'));
|
||||
return view('tags.index', compact('title', 'mainTitleIcon', 'types', 'collection'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,7 +62,7 @@ class ConvertController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||
*/
|
||||
public function convert(TransactionType $destinationType, TransactionJournal $journal)
|
||||
public function index(TransactionType $destinationType, TransactionJournal $journal)
|
||||
{
|
||||
if ($this->isOpeningBalance($journal)) {
|
||||
return $this->redirectToAccount($journal);
|
||||
@ -115,7 +115,7 @@ class ConvertController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function submit(Request $request, JournalRepositoryInterface $repository, TransactionType $destinationType, TransactionJournal $journal)
|
||||
public function postIndex(Request $request, JournalRepositoryInterface $repository, TransactionType $destinationType, TransactionJournal $journal)
|
||||
{
|
||||
if ($this->isOpeningBalance($journal)) {
|
||||
return $this->redirectToAccount($journal);
|
||||
|
@ -179,7 +179,7 @@ class SingleController extends Controller
|
||||
$count = $journal->transactions()->count();
|
||||
|
||||
if ($count > 2) {
|
||||
return redirect(route('transactions.edit-split', [$journal->id]));
|
||||
return redirect(route('transactions.split.edit', [$journal->id]));
|
||||
}
|
||||
|
||||
$what = strtolower(TransactionJournal::transactionTypeStr($journal));
|
||||
@ -286,7 +286,7 @@ class SingleController extends Controller
|
||||
|
||||
if ($doSplit === true) {
|
||||
// redirect to edit screen:
|
||||
return redirect(route('transactions.edit-split', [$journal->id]));
|
||||
return redirect(route('transactions.split.edit', [$journal->id]));
|
||||
}
|
||||
|
||||
|
||||
|
@ -157,7 +157,7 @@ class SplitController extends Controller
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('transactions.edit-split.fromUpdate', true);
|
||||
|
||||
return redirect(route('transactions.edit-split', [$journal->id]))->withInput(['return_to_edit' => 1]);
|
||||
return redirect(route('transactions.split.edit', [$journal->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
@ -249,8 +249,8 @@ class SplitController extends Controller
|
||||
$transactions = $this->tasker->getTransactionsOverview($journal);
|
||||
$return = [];
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return[] = [
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$set = [
|
||||
'description' => $transaction['description'],
|
||||
'source_account_id' => $transaction['source_account_id'],
|
||||
'source_account_name' => $transaction['source_account_name'],
|
||||
@ -260,6 +260,15 @@ class SplitController extends Controller
|
||||
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
|
||||
'category' => $transaction['category'],
|
||||
];
|
||||
|
||||
// set initial category and/or budget:
|
||||
if (count($transactions) === 1 && $index === 0) {
|
||||
$set['budget_id'] = TransactionJournal::budgetId($journal);
|
||||
$set['category'] = TransactionJournal::categoryAsString($journal);
|
||||
}
|
||||
|
||||
$return[] = $set;
|
||||
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
@ -146,7 +146,7 @@ class TransactionController extends Controller
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function indexDate(Request $request, string $what, string $date)
|
||||
public function indexByDate(Request $request, string $what, string $date)
|
||||
{
|
||||
$carbon = new Carbon($date);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
|
@ -57,7 +57,7 @@ class AuthenticateTwoFactor
|
||||
$has2faSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
|
||||
$is2faAuthed = Session::get('twofactor-authenticated');
|
||||
if ($is2faEnabled && $has2faSecret && !$is2faAuthed) {
|
||||
return redirect(route('two-factor'));
|
||||
return redirect(route('two-factor.index'));
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
@ -46,7 +46,12 @@ class IsConfirmed
|
||||
return redirect()->guest('login');
|
||||
}
|
||||
// must the user be confirmed in the first place?
|
||||
$mustConfirmAccount = FireflyConfig::get('must_confirm_account', config('firefly.configuration.must_confirm_account'))->data;
|
||||
$confirmPreference = FireflyConfig::get('must_confirm_account', config('firefly.configuration.must_confirm_account'));
|
||||
$mustConfirmAccount = false;
|
||||
if (!is_null($confirmPreference)) {
|
||||
$mustConfirmAccount = $confirmPreference->data;
|
||||
}
|
||||
|
||||
// user must be logged in, then continue:
|
||||
$isConfirmed = Preferences::get('user_confirmed', false)->data;
|
||||
|
||||
|
@ -61,7 +61,6 @@ class Range
|
||||
* @param string|null $guard
|
||||
*
|
||||
* @return mixed
|
||||
* @internal param Closure $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, $guard = null)
|
||||
{
|
||||
|
@ -42,10 +42,11 @@ class AccountFormRequest extends Request
|
||||
'name' => trim($this->input('name')),
|
||||
'active' => intval($this->input('active')) === 1,
|
||||
'accountType' => $this->input('what'),
|
||||
'currency_id' => intval($this->input('currency_id')),
|
||||
'currency_id' => intval($this->input('currency_id')),
|
||||
'virtualBalance' => round($this->input('virtualBalance'), 2),
|
||||
'virtualBalanceCurrency' => intval($this->input('amount_currency_id_virtualBalance')),
|
||||
'iban' => trim($this->input('iban')),
|
||||
'BIC' => trim($this->input('BIC')),
|
||||
'accountNumber' => trim($this->input('accountNumber')),
|
||||
'accountRole' => $this->input('accountRole'),
|
||||
'openingBalance' => round($this->input('openingBalance'), 2),
|
||||
@ -79,6 +80,7 @@ class AccountFormRequest extends Request
|
||||
'name' => $nameRule,
|
||||
'openingBalance' => 'numeric',
|
||||
'iban' => 'iban',
|
||||
'BIC' => 'bic',
|
||||
'virtualBalance' => 'numeric',
|
||||
'openingBalanceDate' => 'date',
|
||||
'currency_id' => 'exists:transaction_currencies,id',
|
||||
|
@ -327,29 +327,29 @@ Breadcrumbs::register(
|
||||
* CURRENCIES
|
||||
*/
|
||||
Breadcrumbs::register(
|
||||
'currency.index', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
'currencies.index', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('firefly.currencies'), route('currency.index'));
|
||||
$breadcrumbs->push(trans('firefly.currencies'), route('currencies.index'));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'currency.create', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('currency.index');
|
||||
$breadcrumbs->push(trans('firefly.create_currency'), route('currency.create'));
|
||||
'currencies.create', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('currencies.index');
|
||||
$breadcrumbs->push(trans('firefly.create_currency'), route('currencies.create'));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'currency.edit', function (BreadCrumbGenerator $breadcrumbs, TransactionCurrency $currency) {
|
||||
$breadcrumbs->parent('currency.index');
|
||||
$breadcrumbs->push(trans('breadcrumbs.edit_currency', ['name' => e($currency->name)]), route('currency.edit', [$currency->id]));
|
||||
'currencies.edit', function (BreadCrumbGenerator $breadcrumbs, TransactionCurrency $currency) {
|
||||
$breadcrumbs->parent('currencies.index');
|
||||
$breadcrumbs->push(trans('breadcrumbs.edit_currency', ['name' => e($currency->name)]), route('currencies.edit', [$currency->id]));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'currency.delete', function (BreadCrumbGenerator $breadcrumbs, TransactionCurrency $currency) {
|
||||
$breadcrumbs->parent('currency.index');
|
||||
$breadcrumbs->push(trans('breadcrumbs.delete_currency', ['name' => e($currency->name)]), route('currency.delete', [$currency->id]));
|
||||
'currencies.delete', function (BreadCrumbGenerator $breadcrumbs, TransactionCurrency $currency) {
|
||||
$breadcrumbs->parent('currencies.index');
|
||||
$breadcrumbs->push(trans('breadcrumbs.delete_currency', ['name' => e($currency->name)]), route('currencies.delete', [$currency->id]));
|
||||
}
|
||||
);
|
||||
|
||||
@ -404,9 +404,9 @@ Breadcrumbs::register(
|
||||
* PREFERENCES
|
||||
*/
|
||||
Breadcrumbs::register(
|
||||
'preferences', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
'preferences.index', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('breadcrumbs.preferences'), route('preferences'));
|
||||
$breadcrumbs->push(trans('breadcrumbs.preferences'), route('preferences.index'));
|
||||
|
||||
}
|
||||
);
|
||||
@ -414,7 +414,7 @@ Breadcrumbs::register(
|
||||
Breadcrumbs::register(
|
||||
'preferences.code', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('breadcrumbs.preferences'), route('preferences'));
|
||||
$breadcrumbs->push(trans('breadcrumbs.preferences'), route('preferences.index'));
|
||||
|
||||
}
|
||||
);
|
||||
@ -423,22 +423,22 @@ Breadcrumbs::register(
|
||||
* PROFILE
|
||||
*/
|
||||
Breadcrumbs::register(
|
||||
'profile', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
'profile.index', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('breadcrumbs.profile'), route('profile'));
|
||||
$breadcrumbs->push(trans('breadcrumbs.profile'), route('profile.index'));
|
||||
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'profile.change-password', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('profile');
|
||||
$breadcrumbs->parent('profile.index');
|
||||
$breadcrumbs->push(trans('breadcrumbs.changePassword'), route('profile.change-password'));
|
||||
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'profile.delete-account', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('profile');
|
||||
$breadcrumbs->parent('profile.index');
|
||||
$breadcrumbs->push(trans('firefly.delete_account'), route('profile.delete-account'));
|
||||
|
||||
}
|
||||
@ -529,9 +529,9 @@ Breadcrumbs::register(
|
||||
* SEARCH
|
||||
*/
|
||||
Breadcrumbs::register(
|
||||
'search', function (BreadCrumbGenerator $breadcrumbs, $query) {
|
||||
'search.index', function (BreadCrumbGenerator $breadcrumbs, $query) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('breadcrumbs.searchResult', ['query' => e($query)]), route('search'));
|
||||
$breadcrumbs->push(trans('breadcrumbs.searchResult', ['query' => e($query)]), route('search.index'));
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -199,8 +199,7 @@ class Account extends Model
|
||||
*/
|
||||
public function getOpeningBalanceAmount(): string
|
||||
{
|
||||
$journal = TransactionJournal
|
||||
::sortCorrectly()
|
||||
$journal = TransactionJournal::sortCorrectly()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $this->id)
|
||||
->transactionTypes([TransactionType::OPENING_BALANCE])
|
||||
@ -230,8 +229,7 @@ class Account extends Model
|
||||
public function getOpeningBalanceDate(): Carbon
|
||||
{
|
||||
$date = new Carbon('1900-01-01');
|
||||
$journal = TransactionJournal
|
||||
::sortCorrectly()
|
||||
$journal = TransactionJournal::sortCorrectly()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $this->id)
|
||||
->transactionTypes([TransactionType::OPENING_BALANCE])
|
||||
|
@ -64,8 +64,7 @@ class TransactionJournal extends TransactionJournalSupport
|
||||
public static function routeBinder($value)
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$object = TransactionJournal
|
||||
::where('transaction_journals.id', $value)
|
||||
$object = TransactionJournal::where('transaction_journals.id', $value)
|
||||
->with('transactionType')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->where('user_id', auth()->user()->id)->first(['transaction_journals.*']);
|
||||
|
@ -41,7 +41,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
/** @var User */
|
||||
private $user;
|
||||
/** @var array */
|
||||
private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber','currency_id'];
|
||||
private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber', 'currency_id', 'BIC'];
|
||||
|
||||
/**
|
||||
* AttachmentRepository constructor.
|
||||
@ -60,7 +60,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(array $types):int
|
||||
public function count(array $types): int
|
||||
{
|
||||
$count = $this->user->accounts()->accountTypeIn($types)->count();
|
||||
|
||||
@ -367,12 +367,11 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
protected function openingBalanceTransaction(Account $account): TransactionJournal
|
||||
{
|
||||
$journal = TransactionJournal
|
||||
::sortCorrectly()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $account->id)
|
||||
->transactionTypes([TransactionType::OPENING_BALANCE])
|
||||
->first(['transaction_journals.*']);
|
||||
$journal = TransactionJournal::sortCorrectly()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $account->id)
|
||||
->transactionTypes([TransactionType::OPENING_BALANCE])
|
||||
->first(['transaction_journals.*']);
|
||||
if (is_null($journal)) {
|
||||
Log::debug('Could not find a opening balance journal, return empty one.');
|
||||
|
||||
@ -482,7 +481,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
protected function storeOpposingAccount(float $amount, string $name):Account
|
||||
protected function storeOpposingAccount(float $amount, string $name): Account
|
||||
{
|
||||
$type = $amount < 0 ? 'expense' : 'revenue';
|
||||
$opposingData = [
|
||||
|
@ -119,6 +119,6 @@ interface AccountRepositoryInterface
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
public function store(array $data) : Account;
|
||||
public function store(array $data): Account;
|
||||
|
||||
}
|
||||
|
@ -107,41 +107,12 @@ class AccountTasker implements AccountTaskerInterface
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $excluded
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
* @see self::financialReport
|
||||
*
|
||||
*/
|
||||
public function expenseReport(Collection $accounts, Collection $excluded, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
$idList = [
|
||||
'accounts' => $accounts->pluck('id')->toArray(),
|
||||
'exclude' => $excluded->pluck('id')->toArray(),
|
||||
];
|
||||
|
||||
Log::debug(
|
||||
'Now calling expenseReport.',
|
||||
['accounts' => $idList['accounts'], 'excluded' => $idList['exclude'],
|
||||
'start' => $start->format('Y-m-d'),
|
||||
'end' => $end->format('Y-m-d'),
|
||||
]
|
||||
);
|
||||
|
||||
return $this->financialReport($idList, $start, $end, false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return AccountCollection
|
||||
*/
|
||||
public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection
|
||||
public function getAccountReport(Collection $accounts, Carbon $start, Carbon $end): AccountCollection
|
||||
{
|
||||
$startAmount = '0';
|
||||
$endAmount = '0';
|
||||
@ -190,35 +161,6 @@ class AccountTasker implements AccountTaskerInterface
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $excluded
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @see AccountTasker::financialReport()
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
*/
|
||||
public function incomeReport(Collection $accounts, Collection $excluded, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
$idList = [
|
||||
'accounts' => $accounts->pluck('id')->toArray(),
|
||||
'exclude' => $excluded->pluck('id')->toArray(),
|
||||
];
|
||||
|
||||
Log::debug(
|
||||
'Now calling expenseReport.',
|
||||
['accounts' => $idList['accounts'], 'excluded' => $idList['exclude'],
|
||||
'start' => $start->format('Y-m-d'),
|
||||
'end' => $end->format('Y-m-d'),
|
||||
]
|
||||
);
|
||||
|
||||
return $this->financialReport($idList, $start, $end, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return how much money has been going out (ie. spent) by the given account(s).
|
||||
* Alternatively, will return how much money has been coming in (ie. earned) by the given accounts.
|
||||
@ -249,21 +191,20 @@ class AccountTasker implements AccountTaskerInterface
|
||||
$joinModifier = $incoming ? '<' : '>';
|
||||
$selection = $incoming ? '>' : '<';
|
||||
|
||||
$query = Transaction
|
||||
::distinct()
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin(
|
||||
'transactions as other_side', function (JoinClause $join) use ($joinModifier) {
|
||||
$join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0);
|
||||
}
|
||||
)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereIn('transactions.account_id', $accounts['accounts'])
|
||||
->where('transactions.amount', $selection, 0);
|
||||
$query = Transaction::distinct()
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin(
|
||||
'transactions as other_side', function (JoinClause $join) use ($joinModifier) {
|
||||
$join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0);
|
||||
}
|
||||
)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereIn('transactions.account_id', $accounts['accounts'])
|
||||
->where('transactions.amount', $selection, 0);
|
||||
if (count($accounts['exclude']) > 0) {
|
||||
$query->whereNotIn('other_side.account_id', $accounts['exclude']);
|
||||
}
|
||||
@ -279,91 +220,4 @@ class AccountTasker implements AccountTaskerInterface
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* This method will determin how much has flown (in the given period) from OR to $accounts to/from anywhere else,
|
||||
* except $excluded. This could be a list of incomes, or a list of expenses. This method shows
|
||||
* the name, the amount and the number of transactions. It is a summary, and only used in some reports.
|
||||
*
|
||||
* $incoming=true a list of incoming money (earnings)
|
||||
* $incoming=false a list of outgoing money (expenses).
|
||||
*
|
||||
* @param array $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $incoming
|
||||
*
|
||||
* Opening balances are ignored.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
protected function financialReport(array $accounts, Carbon $start, Carbon $end, bool $incoming): Collection
|
||||
{
|
||||
$collection = new Collection;
|
||||
$joinModifier = $incoming ? '<' : '>';
|
||||
$selection = $incoming ? '>' : '<';
|
||||
$query = Transaction
|
||||
::distinct()
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->leftJoin(
|
||||
'transactions as other_side', function (JoinClause $join) use ($joinModifier) {
|
||||
$join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as other_account', 'other_account.id', '=', 'other_side.account_id')
|
||||
->where('transaction_types.type', '!=', TransactionType::OPENING_BALANCE)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('other_side.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereIn('transactions.account_id', $accounts['accounts'])
|
||||
->where('other_side.amount', '=', DB::raw('transactions.amount * -1'))
|
||||
->where('transactions.amount', $selection, 0)
|
||||
->orderBy('transactions.amount');
|
||||
|
||||
if (count($accounts['exclude']) > 0) {
|
||||
$query->whereNotIn('other_side.account_id', $accounts['exclude']);
|
||||
}
|
||||
$set = $query->get(
|
||||
[
|
||||
'transaction_journals.id',
|
||||
'other_side.account_id',
|
||||
'other_account.name',
|
||||
'other_account.encrypted',
|
||||
'transactions.amount',
|
||||
]
|
||||
);
|
||||
// summarize ourselves:
|
||||
$temp = [];
|
||||
foreach ($set as $entry) {
|
||||
// save into $temp:
|
||||
$id = intval($entry->account_id);
|
||||
if (isset($temp[$id])) {
|
||||
$temp[$id]['count']++;
|
||||
$temp[$id]['amount'] = bcadd($temp[$id]['amount'], $entry->amount);
|
||||
}
|
||||
if (!isset($temp[$id])) {
|
||||
$temp[$id] = [
|
||||
'name' => intval($entry->encrypted) === 1 ? Crypt::decrypt($entry->name) : $entry->name,
|
||||
'amount' => $entry->amount,
|
||||
'count' => 1,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// loop $temp and create collection:
|
||||
foreach ($temp as $key => $entry) {
|
||||
$object = new stdClass();
|
||||
$object->id = $key;
|
||||
$object->name = $entry['name'];
|
||||
$object->count = $entry['count'];
|
||||
$object->amount = $entry['amount'];
|
||||
$collection->push($object);
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
}
|
||||
|
@ -51,37 +51,11 @@ interface AccountTaskerInterface
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $excluded
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @see AccountTasker::financialReport()
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
*/
|
||||
public function expenseReport(Collection $accounts, Collection $excluded, Carbon $start, Carbon $end): Collection;
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return AccountCollection
|
||||
*/
|
||||
public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $excluded
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @see AccountTasker::financialReport()
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
*/
|
||||
public function incomeReport(Collection $accounts, Collection $excluded, Carbon $start, Carbon $end): Collection;
|
||||
public function getAccountReport(Collection $accounts, Carbon $start, Carbon $end): AccountCollection;
|
||||
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
public function find(int $billId) : Bill
|
||||
public function find(int $billId): Bill
|
||||
{
|
||||
$bill = $this->user->bills()->find($billId);
|
||||
if (is_null($bill)) {
|
||||
@ -83,7 +83,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
public function findByName(string $name) : Bill
|
||||
public function findByName(string $name): Bill
|
||||
{
|
||||
$bills = $this->user->bills()->get(['bills.*']);
|
||||
|
||||
|
@ -40,7 +40,7 @@ interface BillRepositoryInterface
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
public function find(int $billId) : Bill;
|
||||
public function find(int $billId): Bill;
|
||||
|
||||
/**
|
||||
* Find a bill by name.
|
||||
@ -49,7 +49,7 @@ interface BillRepositoryInterface
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
public function findByName(string $name) : Bill;
|
||||
public function findByName(string $name): Bill;
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
|
@ -212,10 +212,8 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is being used to generate the budget overview in the year/multi-year report. More specifically, this
|
||||
* method runs the query and returns the result that is used for this report.
|
||||
*
|
||||
* The query is used in both the year/multi-year budget overview AND in the accompanying chart.
|
||||
* This method is being used to generate the budget overview in the year/multi-year report. Its used
|
||||
* in both the year/multi-year budget overview AND in the accompanying chart.
|
||||
*
|
||||
* @param Collection $budgets
|
||||
* @param Collection $accounts
|
||||
@ -226,54 +224,31 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
*/
|
||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
$data = [];
|
||||
// prep data array:
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
$data[$budget->id] = [
|
||||
'name' => $budget->name,
|
||||
'sum' => '0',
|
||||
'entries' => [],
|
||||
];
|
||||
}
|
||||
|
||||
// get all transactions:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($start, $end);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end);
|
||||
$collector->setBudgets($budgets);
|
||||
$transactions = $collector->getJournals();
|
||||
|
||||
// this is the date format we need:
|
||||
// define period to group on:
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
|
||||
// this is the set of transactions for this period
|
||||
// in these budgets. Now they must be grouped (manually)
|
||||
// id, period => amount
|
||||
$data = [];
|
||||
// loop transactions:
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$budgetId = max(intval($transaction->transaction_journal_budget_id), intval($transaction->transaction_budget_id));
|
||||
$date = $transaction->date->format($carbonFormat);
|
||||
|
||||
if (!isset($data[$budgetId])) {
|
||||
$data[$budgetId]['name'] = $this->getBudgetName($budgetId, $budgets);
|
||||
$data[$budgetId]['sum'] = '0';
|
||||
$data[$budgetId]['entries'] = [];
|
||||
}
|
||||
|
||||
if (!isset($data[$budgetId]['entries'][$date])) {
|
||||
$data[$budgetId]['entries'][$date] = '0';
|
||||
}
|
||||
$data[$budgetId]['entries'][$date] = bcadd($data[$budgetId]['entries'][$date], $transaction->transaction_amount);
|
||||
}
|
||||
// and now the same for stuff without a budget:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$collector->withoutBudget();
|
||||
$transactions = $collector->getJournals();
|
||||
|
||||
$data[0]['entries'] = [];
|
||||
$data[0]['name'] = strval(trans('firefly.no_budget'));
|
||||
$data[0]['sum'] = '0';
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
$date = $transaction->date->format($carbonFormat);
|
||||
|
||||
if (!isset($data[0]['entries'][$date])) {
|
||||
$data[0]['entries'][$date] = '0';
|
||||
}
|
||||
$data[0]['entries'][$date] = bcadd($data[0]['entries'][$date], $transaction->transaction_amount);
|
||||
$budgetId = max(intval($transaction->transaction_journal_budget_id), intval($transaction->transaction_budget_id));
|
||||
$date = $transaction->date->format($carbonFormat);
|
||||
$data[$budgetId]['entries'][$date] = bcadd($data[$budgetId]['entries'][$date] ?? '0', $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $data;
|
||||
@ -314,6 +289,40 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$collector->withoutBudget();
|
||||
$transactions = $collector->getJournals();
|
||||
$result = [
|
||||
'entries' => [],
|
||||
'name' => strval(trans('firefly.no_budget')),
|
||||
'sum' => '0',
|
||||
];
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
$date = $transaction->date->format($carbonFormat);
|
||||
|
||||
if (!isset($result['entries'][$date])) {
|
||||
$result['entries'][$date] = '0';
|
||||
}
|
||||
$result['entries'][$date] = bcadd($result['entries'][$date], $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Collection $accounts
|
||||
@ -332,20 +341,23 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
Log::debug('spentInPeriod: and these accounts: ', $accountIds);
|
||||
Log::debug(sprintf('spentInPeriod: Start date is "%s", end date is "%s"', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
|
||||
$fromJournalsQuery = TransactionJournal
|
||||
::leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->where('transaction_types.type', 'Withdrawal');
|
||||
$fromJournalsQuery = TransactionJournal::leftJoin(
|
||||
'budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
|
||||
'transactions.amount', '<', 0
|
||||
);
|
||||
}
|
||||
)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->where('transaction_types.type', 'Withdrawal');
|
||||
|
||||
// add budgets:
|
||||
if ($budgets->count() > 0) {
|
||||
@ -368,17 +380,16 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
* and budget_transaction.budget_id in (1,61)
|
||||
* and transactions.account_id in (2)
|
||||
*/
|
||||
$fromTransactionsQuery = Transaction
|
||||
::leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id')
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->where('transactions.amount', '<', 0)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->where('transaction_types.type', 'Withdrawal');
|
||||
$fromTransactionsQuery = Transaction::leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id')
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->where('transactions.amount', '<', 0)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('transaction_journals.user_id', $this->user->id)
|
||||
->where('transaction_types.type', 'Withdrawal');
|
||||
|
||||
// add budgets:
|
||||
if ($budgets->count() > 0) {
|
||||
@ -550,25 +561,4 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
|
||||
return $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $budgetId
|
||||
* @param Collection $budgets
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getBudgetName(int $budgetId, Collection $budgets): string
|
||||
{
|
||||
|
||||
$first = $budgets->filter(
|
||||
function (Budget $budget) use ($budgetId) {
|
||||
return $budgetId === $budget->id;
|
||||
}
|
||||
);
|
||||
if (!is_null($first->first())) {
|
||||
return $first->first()->name;
|
||||
}
|
||||
|
||||
return '(unknown)';
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +111,14 @@ interface BudgetRepositoryInterface
|
||||
*/
|
||||
public function getInactiveBudgets(): Collection;
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Collection $accounts
|
||||
@ -119,7 +127,7 @@ interface BudgetRepositoryInterface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) : string;
|
||||
public function spentInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): string;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
@ -143,7 +151,7 @@ interface BudgetRepositoryInterface
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function update(Budget $budget, array $data) : Budget;
|
||||
public function update(Budget $budget, array $data): Budget;
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
@ -154,6 +162,6 @@ interface BudgetRepositoryInterface
|
||||
*
|
||||
* @return BudgetLimit
|
||||
*/
|
||||
public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $range, int $amount) : BudgetLimit;
|
||||
public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $range, int $amount): BudgetLimit;
|
||||
|
||||
}
|
||||
|
@ -15,12 +15,16 @@ namespace FireflyIII\Repositories\Category;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
|
||||
/**
|
||||
* Class CategoryRepository
|
||||
@ -221,6 +225,178 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $last;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodExpenses(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
$data = [];
|
||||
// prep data array:
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
$data[$category->id] = [
|
||||
'name' => $category->name,
|
||||
'sum' => '0',
|
||||
'entries' => [],
|
||||
];
|
||||
}
|
||||
|
||||
// get all transactions:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end);
|
||||
$collector->setCategories($categories)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||
->withOpposingAccount()
|
||||
->enableInternalFilter();
|
||||
$transactions = $collector->getJournals();
|
||||
|
||||
// loop transactions:
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
// if positive, skip:
|
||||
if (bccomp($transaction->transaction_amount, '0') === 1) {
|
||||
continue;
|
||||
}
|
||||
$categoryId = max(intval($transaction->transaction_journal_category_id), intval($transaction->transaction_category_id));
|
||||
$date = $transaction->date->format($carbonFormat);
|
||||
$data[$categoryId]['entries'][$date] = bcadd($data[$categoryId]['entries'][$date] ?? '0', $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodExpensesNoCategory(Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->withOpposingAccount();
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])->enableInternalFilter();
|
||||
$collector->withoutCategory();
|
||||
$transactions = $collector->getJournals();
|
||||
$result = [
|
||||
'entries' => [],
|
||||
'name' => strval(trans('firefly.no_category')),
|
||||
'sum' => '0',
|
||||
];
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
// if positive, skip:
|
||||
if (bccomp($transaction->transaction_amount, '0') === 1) {
|
||||
continue;
|
||||
}
|
||||
$date = $transaction->date->format($carbonFormat);
|
||||
|
||||
if (!isset($result['entries'][$date])) {
|
||||
$result['entries'][$date] = '0';
|
||||
}
|
||||
$result['entries'][$date] = bcadd($result['entries'][$date], $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodIncome(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
$data = [];
|
||||
// prep data array:
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
$data[$category->id] = [
|
||||
'name' => $category->name,
|
||||
'sum' => '0',
|
||||
'entries' => [],
|
||||
];
|
||||
}
|
||||
|
||||
// get all transactions:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end);
|
||||
$collector->setCategories($categories)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||
->withOpposingAccount()
|
||||
->enableInternalFilter();
|
||||
$transactions = $collector->getJournals();
|
||||
|
||||
// loop transactions:
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
// if negative, skip:
|
||||
if (bccomp($transaction->transaction_amount, '0') === -1) {
|
||||
continue;
|
||||
}
|
||||
$categoryId = max(intval($transaction->transaction_journal_category_id), intval($transaction->transaction_category_id));
|
||||
$date = $transaction->date->format($carbonFormat);
|
||||
$data[$categoryId]['entries'][$date] = bcadd($data[$categoryId]['entries'][$date] ?? '0', $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodIncomeNoCategory(Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug('Now in periodIncomeNoCategory()');
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->withOpposingAccount();
|
||||
$collector->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])->enableInternalFilter();
|
||||
$collector->withoutCategory();
|
||||
$transactions = $collector->getJournals();
|
||||
$result = [
|
||||
'entries' => [],
|
||||
'name' => strval(trans('firefly.no_category')),
|
||||
'sum' => '0',
|
||||
];
|
||||
Log::debug('Looping transactions..');
|
||||
foreach ($transactions as $transaction) {
|
||||
|
||||
// if negative, skip:
|
||||
if (bccomp($transaction->transaction_amount, '0') === -1) {
|
||||
continue;
|
||||
}
|
||||
$date = $transaction->date->format($carbonFormat);
|
||||
|
||||
if (!isset($result['entries'][$date])) {
|
||||
$result['entries'][$date] = '0';
|
||||
}
|
||||
$result['entries'][$date] = bcadd($result['entries'][$date], $transaction->transaction_amount);
|
||||
}
|
||||
Log::debug('Done looping transactions..');
|
||||
Log::debug('Finished periodIncomeNoCategory()');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
@ -233,6 +409,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
{
|
||||
$sum = $this->sumInPeriod($categories, $accounts, TransactionType::WITHDRAWAL, $start, $end);
|
||||
$sum = bcmul($sum, '-1');
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
@ -404,5 +581,4 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $sum;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface CategoryRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
@ -49,7 +48,7 @@ interface CategoryRepositoryInterface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function earnedInPeriodWithoutCategory(Collection $accounts, Carbon $start, Carbon $end) :string;
|
||||
public function earnedInPeriodWithoutCategory(Collection $accounts, Carbon $start, Carbon $end): string;
|
||||
|
||||
/**
|
||||
* Find a category
|
||||
@ -58,7 +57,7 @@ interface CategoryRepositoryInterface
|
||||
*
|
||||
* @return Category
|
||||
*/
|
||||
public function find(int $categoryId) : Category;
|
||||
public function find(int $categoryId): Category;
|
||||
|
||||
/**
|
||||
* Find a category
|
||||
@ -67,7 +66,7 @@ interface CategoryRepositoryInterface
|
||||
*
|
||||
* @return Category
|
||||
*/
|
||||
public function findByName(string $name) : Category;
|
||||
public function findByName(string $name): Category;
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
@ -93,6 +92,44 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function lastUseDate(Category $category, Collection $accounts): Carbon;
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodExpenses(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodExpensesNoCategory(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodIncome(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function periodIncomeNoCategory(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
@ -110,7 +147,7 @@ interface CategoryRepositoryInterface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriodWithoutCategory(Collection $accounts, Carbon $start, Carbon $end) : string;
|
||||
public function spentInPeriodWithoutCategory(Collection $accounts, Carbon $start, Carbon $end): string;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
|
@ -43,7 +43,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function find(int $currencyId) : TransactionCurrency
|
||||
public function find(int $currencyId): TransactionCurrency
|
||||
{
|
||||
$currency = TransactionCurrency::find($currencyId);
|
||||
if (is_null($currency)) {
|
||||
@ -61,7 +61,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findByCode(string $currencyCode) : TransactionCurrency
|
||||
public function findByCode(string $currencyCode): TransactionCurrency
|
||||
{
|
||||
$currency = TransactionCurrency::whereCode($currencyCode)->first();
|
||||
if (is_null($currency)) {
|
||||
@ -78,7 +78,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findByName(string $currencyName) : TransactionCurrency
|
||||
public function findByName(string $currencyName): TransactionCurrency
|
||||
{
|
||||
$preferred = TransactionCurrency::whereName($currencyName)->first();
|
||||
if (is_null($preferred)) {
|
||||
@ -95,7 +95,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findBySymbol(string $currencySymbol) : TransactionCurrency
|
||||
public function findBySymbol(string $currencySymbol): TransactionCurrency
|
||||
{
|
||||
$currency = TransactionCurrency::whereSymbol($currencySymbol)->first();
|
||||
if (is_null($currency)) {
|
||||
|
@ -39,7 +39,7 @@ interface CurrencyRepositoryInterface
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function find(int $currencyId) : TransactionCurrency;
|
||||
public function find(int $currencyId): TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency code
|
||||
@ -48,7 +48,7 @@ interface CurrencyRepositoryInterface
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findByCode(string $currencyCode) : TransactionCurrency;
|
||||
public function findByCode(string $currencyCode): TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency name
|
||||
@ -57,7 +57,7 @@ interface CurrencyRepositoryInterface
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findByName(string $currencyName) : TransactionCurrency;
|
||||
public function findByName(string $currencyName): TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Find by currency symbol
|
||||
@ -66,7 +66,7 @@ interface CurrencyRepositoryInterface
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function findBySymbol(string $currencySymbol) : TransactionCurrency;
|
||||
public function findBySymbol(string $currencySymbol): TransactionCurrency;
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
|
@ -105,7 +105,7 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function find(int $journalId) : TransactionJournal
|
||||
public function find(int $journalId): TransactionJournal
|
||||
{
|
||||
$journal = $this->user->transactionJournals()->where('id', $journalId)->first();
|
||||
if (is_null($journal)) {
|
||||
|
@ -52,7 +52,7 @@ interface JournalRepositoryInterface
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function find(int $journalId) : TransactionJournal;
|
||||
public function find(int $journalId): TransactionJournal;
|
||||
|
||||
/**
|
||||
* Get users very first transaction journal
|
||||
|
@ -171,39 +171,37 @@ class JournalTasker implements JournalTaskerInterface
|
||||
$identifier = intval($transaction->identifier);
|
||||
|
||||
// go!
|
||||
$sum
|
||||
= Transaction
|
||||
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('account_id', $transaction->account_id)
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->where('transactions.id', '!=', $transactionId)
|
||||
->where(
|
||||
function (Builder $q1) use ($date, $order, $journalId, $identifier) {
|
||||
$q1->where('transaction_journals.date', '<', $date); // date
|
||||
$q1->orWhere(
|
||||
function (Builder $q2) use ($date, $order) { // function 1
|
||||
$q2->where('transaction_journals.date', $date);
|
||||
$q2->where('transaction_journals.order', '>', $order);
|
||||
}
|
||||
);
|
||||
$q1->orWhere(
|
||||
function (Builder $q3) use ($date, $order, $journalId) { // function 2
|
||||
$q3->where('transaction_journals.date', $date);
|
||||
$q3->where('transaction_journals.order', $order);
|
||||
$q3->where('transaction_journals.id', '<', $journalId);
|
||||
}
|
||||
);
|
||||
$q1->orWhere(
|
||||
function (Builder $q4) use ($date, $order, $journalId, $identifier) { // function 3
|
||||
$q4->where('transaction_journals.date', $date);
|
||||
$q4->where('transaction_journals.order', $order);
|
||||
$q4->where('transaction_journals.id', $journalId);
|
||||
$q4->where('transactions.identifier', '>', $identifier);
|
||||
}
|
||||
);
|
||||
}
|
||||
)->sum('transactions.amount');
|
||||
$sum = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('account_id', $transaction->account_id)
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->where('transactions.id', '!=', $transactionId)
|
||||
->where(
|
||||
function (Builder $q1) use ($date, $order, $journalId, $identifier) {
|
||||
$q1->where('transaction_journals.date', '<', $date); // date
|
||||
$q1->orWhere(
|
||||
function (Builder $q2) use ($date, $order) { // function 1
|
||||
$q2->where('transaction_journals.date', $date);
|
||||
$q2->where('transaction_journals.order', '>', $order);
|
||||
}
|
||||
);
|
||||
$q1->orWhere(
|
||||
function (Builder $q3) use ($date, $order, $journalId) { // function 2
|
||||
$q3->where('transaction_journals.date', $date);
|
||||
$q3->where('transaction_journals.order', $order);
|
||||
$q3->where('transaction_journals.id', '<', $journalId);
|
||||
}
|
||||
);
|
||||
$q1->orWhere(
|
||||
function (Builder $q4) use ($date, $order, $journalId, $identifier) { // function 3
|
||||
$q4->where('transaction_journals.date', $date);
|
||||
$q4->where('transaction_journals.order', $order);
|
||||
$q4->where('transaction_journals.id', $journalId);
|
||||
$q4->where('transactions.identifier', '>', $identifier);
|
||||
}
|
||||
);
|
||||
}
|
||||
)->sum('transactions.amount');
|
||||
|
||||
return strval($sum);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPiggyBanksWithAmount() : Collection
|
||||
public function getPiggyBanksWithAmount(): Collection
|
||||
{
|
||||
$set = $this->getPiggyBanks();
|
||||
foreach ($set as $piggy) {
|
||||
|
@ -58,7 +58,7 @@ interface PiggyBankRepositoryInterface
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getEvents(PiggyBank $piggyBank) : Collection;
|
||||
public function getEvents(PiggyBank $piggyBank): Collection;
|
||||
|
||||
/**
|
||||
* Highest order of all piggy banks.
|
||||
@ -72,14 +72,14 @@ interface PiggyBankRepositoryInterface
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPiggyBanks() : Collection;
|
||||
public function getPiggyBanks(): Collection;
|
||||
|
||||
/**
|
||||
* Also add amount in name.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPiggyBanksWithAmount() : Collection;
|
||||
public function getPiggyBanksWithAmount(): Collection;
|
||||
|
||||
/**
|
||||
* Set all piggy banks to order 0.
|
||||
|
@ -93,7 +93,7 @@ class TagRepository implements TagRepositoryInterface
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public function find(int $tagId) : Tag
|
||||
public function find(int $tagId): Tag
|
||||
{
|
||||
$tag = $this->user->tags()->find($tagId);
|
||||
if (is_null($tag)) {
|
||||
@ -108,7 +108,7 @@ class TagRepository implements TagRepositoryInterface
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public function findByTag(string $tag) : Tag
|
||||
public function findByTag(string $tag): Tag
|
||||
{
|
||||
$tags = $this->user->tags()->get();
|
||||
/** @var Tag $tag */
|
||||
|
@ -49,14 +49,14 @@ interface TagRepositoryInterface
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public function find(int $tagId) : Tag;
|
||||
public function find(int $tagId): Tag;
|
||||
|
||||
/**
|
||||
* @param string $tag
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public function findByTag(string $tag) : Tag;
|
||||
public function findByTag(string $tag): Tag;
|
||||
|
||||
/**
|
||||
* This method returns all the user's tags.
|
||||
|
@ -113,12 +113,11 @@ class UserRepository implements UserRepositoryInterface
|
||||
$return['bills'] = $user->bills()->count();
|
||||
$return['categories'] = $user->categories()->count();
|
||||
$return['budgets'] = $user->budgets()->count();
|
||||
$return['budgets_with_limits'] = BudgetLimit
|
||||
::distinct()
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->where('amount', '>', 0)
|
||||
->whereNull('budgets.deleted_at')
|
||||
->where('budgets.user_id', $user->id)->get(['budget_limits.budget_id'])->count();
|
||||
$return['budgets_with_limits'] = BudgetLimit::distinct()
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->where('amount', '>', 0)
|
||||
->whereNull('budgets.deleted_at')
|
||||
->where('budgets.user_id', $user->id)->get(['budget_limits.budget_id'])->count();
|
||||
$return['export_jobs'] = $user->exportJobs()->count();
|
||||
$return['export_jobs_success'] = $user->exportJobs()->where('status', 'export_downloaded')->count();
|
||||
$return['import_jobs'] = $user->exportJobs()->count();
|
||||
|
@ -40,20 +40,7 @@ class ExpandedForm
|
||||
*/
|
||||
public function amount(string $name, $value = null, array $options = []): string
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = 'any';
|
||||
$options['min'] = '0.01';
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
unset($options['currency']);
|
||||
unset($options['placeholder']);
|
||||
$html = view('form.amount', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
return $this->currencyField($name, 'amount', $value, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,20 +52,7 @@ class ExpandedForm
|
||||
*/
|
||||
public function amountSmall(string $name, $value = null, array $options = []): string
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = 'any';
|
||||
$options['min'] = '0.01';
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
unset($options['currency']);
|
||||
unset($options['placeholder']);
|
||||
$html = view('form.amount-small', compact('defaultCurrency', 'currencies', 'classes', 'name', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
return $this->currencyField($name, 'amount-small', $value, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,18 +64,7 @@ class ExpandedForm
|
||||
*/
|
||||
public function balance(string $name, $value = null, array $options = []): string
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = round($this->fillFieldValue($name, $value), 2);
|
||||
$options['step'] = 'any';
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
unset($options['currency']);
|
||||
unset($options['placeholder']);
|
||||
$html = view('form.balance', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
return $this->currencyField($name, 'balance', $value, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -320,7 +283,6 @@ class ExpandedForm
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param array $list
|
||||
@ -500,4 +462,29 @@ class ExpandedForm
|
||||
return strval(trans('form.' . $name));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $view
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function currencyField(string $name, string $view, $value = null, array $options = []): string
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = 'any';
|
||||
$options['min'] = '0.01';
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
unset($options['currency']);
|
||||
unset($options['placeholder']);
|
||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
@ -246,8 +246,8 @@ class Navigation
|
||||
* If the date difference between start and end is less than a month, method returns "Y-m-d". If the difference is less than a year,
|
||||
* method returns "Y-m". If the date difference is larger, method returns "Y".
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -270,8 +270,8 @@ class Navigation
|
||||
* If the date difference between start and end is less than a month, method returns "1D". If the difference is less than a year,
|
||||
* method returns "1M". If the date difference is larger, method returns "1Y".
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -109,8 +109,7 @@ class Transaction extends Twig_Extension
|
||||
'optionalJournalAmount', function (int $journalId, string $transactionAmount, string $code, string $type): string {
|
||||
|
||||
$amount = strval(
|
||||
TransactionModel
|
||||
::where('transaction_journal_id', $journalId)
|
||||
TransactionModel::where('transaction_journal_id', $journalId)
|
||||
->whereNull('deleted_at')
|
||||
->where('amount', '<', 0)
|
||||
->sum('amount')
|
||||
@ -193,8 +192,7 @@ class Transaction extends Twig_Extension
|
||||
// name is present in object, use that one:
|
||||
if (bccomp($transaction->transaction_amount, '0') === -1 && !is_null($transaction->opposing_account_id)) {
|
||||
|
||||
$name = intval($transaction->opposing_account_encrypted) === 1 ? Crypt::decrypt($transaction->opposing_account_name)
|
||||
: $transaction->opposing_account_name;
|
||||
$name = $transaction->opposing_account_name;
|
||||
$id = intval($transaction->opposing_account_id);
|
||||
$type = intval($transaction->opposing_account_type);
|
||||
}
|
||||
@ -204,8 +202,7 @@ class Transaction extends Twig_Extension
|
||||
// if the amount is negative, find the opposing account and use that one:
|
||||
$journalId = $transaction->journal_id;
|
||||
/** @var TransactionModel $other */
|
||||
$other = TransactionModel
|
||||
::where('transaction_journal_id', $journalId)->where('transactions.id', '!=', $transaction->id)
|
||||
$other = TransactionModel::where('transaction_journal_id', $journalId)->where('transactions.id', '!=', $transaction->id)
|
||||
->where('amount', '=', bcmul($transaction->transaction_amount, '-1'))->where('identifier', $transaction->identifier)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
@ -278,8 +275,7 @@ class Transaction extends Twig_Extension
|
||||
if (bccomp($transaction->transaction_amount, '0') === 1 && is_null($transaction->opposing_account_id)) {
|
||||
$journalId = $transaction->journal_id;
|
||||
/** @var TransactionModel $other */
|
||||
$other = TransactionModel
|
||||
::where('transaction_journal_id', $journalId)->where('transactions.id', '!=', $transaction->id)
|
||||
$other = TransactionModel::where('transaction_journal_id', $journalId)->where('transactions.id', '!=', $transaction->id)
|
||||
->where('amount', '=', bcmul($transaction->transaction_amount, '-1'))->where('identifier', $transaction->identifier)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
|
@ -57,8 +57,6 @@ class FireflyValidator extends Validator
|
||||
* @param $value
|
||||
*
|
||||
* @return bool
|
||||
* @internal param $parameters
|
||||
*
|
||||
*
|
||||
*/
|
||||
public function validate2faCode($attribute, $value): bool
|
||||
@ -95,6 +93,27 @@ class FireflyValidator extends Validator
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attribute
|
||||
* @param $value
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function validateBic($attribute, $value): bool
|
||||
{
|
||||
$regex = '/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i';
|
||||
$result = preg_match($regex, $value);
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
if ($result === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attribute
|
||||
* @param $value
|
||||
@ -455,7 +474,6 @@ class FireflyValidator extends Validator
|
||||
* @param $value
|
||||
*
|
||||
* @return bool
|
||||
* @internal param $parameters
|
||||
*
|
||||
*/
|
||||
private function validateByAccountId($value): bool
|
||||
|
106
composer.lock
generated
106
composer.lock
generated
@ -105,20 +105,20 @@
|
||||
},
|
||||
{
|
||||
"name": "classpreloader/classpreloader",
|
||||
"version": "3.0.0",
|
||||
"version": "3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ClassPreloader/ClassPreloader.git",
|
||||
"reference": "9b10b913c2bdf90c3d2e0d726b454fb7f77c552a"
|
||||
"reference": "bc7206aa892b5a33f4680421b69b191efd32b096"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/9b10b913c2bdf90c3d2e0d726b454fb7f77c552a",
|
||||
"reference": "9b10b913c2bdf90c3d2e0d726b454fb7f77c552a",
|
||||
"url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/bc7206aa892b5a33f4680421b69b191efd32b096",
|
||||
"reference": "bc7206aa892b5a33f4680421b69b191efd32b096",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nikic/php-parser": "^1.0|^2.0",
|
||||
"nikic/php-parser": "^1.0|^2.0|^3.0",
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -127,7 +127,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
"dev-master": "3.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -155,7 +155,7 @@
|
||||
"class",
|
||||
"preload"
|
||||
],
|
||||
"time": "2015-11-09 22:51:51"
|
||||
"time": "2016-09-16 12:50:15"
|
||||
},
|
||||
{
|
||||
"name": "davejamesmiller/laravel-breadcrumbs",
|
||||
@ -445,16 +445,16 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/common",
|
||||
"version": "v2.6.1",
|
||||
"version": "v2.6.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/common.git",
|
||||
"reference": "a579557bc689580c19fee4e27487a67fe60defc0"
|
||||
"reference": "7bce00698899aa2c06fe7365c76e4d78ddb15fa3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/common/zipball/a579557bc689580c19fee4e27487a67fe60defc0",
|
||||
"reference": "a579557bc689580c19fee4e27487a67fe60defc0",
|
||||
"url": "https://api.github.com/repos/doctrine/common/zipball/7bce00698899aa2c06fe7365c76e4d78ddb15fa3",
|
||||
"reference": "7bce00698899aa2c06fe7365c76e4d78ddb15fa3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -514,7 +514,7 @@
|
||||
"persistence",
|
||||
"spl"
|
||||
],
|
||||
"time": "2015-12-25 13:18:31"
|
||||
"time": "2016-11-30 16:50:46"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/dbal",
|
||||
@ -797,20 +797,20 @@
|
||||
},
|
||||
{
|
||||
"name": "jeremeamia/SuperClosure",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jeremeamia/super_closure.git",
|
||||
"reference": "29a88be2a4846d27c1613aed0c9071dfad7b5938"
|
||||
"reference": "443c3df3207f176a1b41576ee2a66968a507b3db"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/29a88be2a4846d27c1613aed0c9071dfad7b5938",
|
||||
"reference": "29a88be2a4846d27c1613aed0c9071dfad7b5938",
|
||||
"url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/443c3df3207f176a1b41576ee2a66968a507b3db",
|
||||
"reference": "443c3df3207f176a1b41576ee2a66968a507b3db",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nikic/php-parser": "^1.2|^2.0",
|
||||
"nikic/php-parser": "^1.2|^2.0|^3.0",
|
||||
"php": ">=5.4",
|
||||
"symfony/polyfill-php56": "^1.0"
|
||||
},
|
||||
@ -820,7 +820,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2-dev"
|
||||
"dev-master": "2.3-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -851,7 +851,7 @@
|
||||
"serialize",
|
||||
"tokenizer"
|
||||
],
|
||||
"time": "2015-12-05 17:17:57"
|
||||
"time": "2016-12-07 09:37:55"
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
@ -2060,16 +2060,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v3.1.7",
|
||||
"version": "v3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "28b0832b2553ffb80cabef6a7a812ff1e670c0bc"
|
||||
"reference": "e8f47a327c2f0fd5aa04fa60af2b693006ed7283"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/28b0832b2553ffb80cabef6a7a812ff1e670c0bc",
|
||||
"reference": "28b0832b2553ffb80cabef6a7a812ff1e670c0bc",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e8f47a327c2f0fd5aa04fa60af2b693006ed7283",
|
||||
"reference": "e8f47a327c2f0fd5aa04fa60af2b693006ed7283",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2089,7 +2089,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
"dev-master": "3.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -2116,7 +2116,7 @@
|
||||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-10-13 06:28:43"
|
||||
"time": "2016-10-13 06:29:04"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
@ -3578,16 +3578,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d"
|
||||
"reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6cba06ff75a1a63a71033e1a01b89056f3af1e8d",
|
||||
"reference": "6cba06ff75a1a63a71033e1a01b89056f3af1e8d",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/903fd6318d0a90b4770a009ff73e4a4e9c437929",
|
||||
"reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3637,7 +3637,7 @@
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2016-11-01 05:06:24"
|
||||
"time": "2016-11-28 16:00:31"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -3822,16 +3822,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "5.6.5",
|
||||
"version": "5.7.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "875145fabfa261fa9c1aea663dd29ddce92dca8f"
|
||||
"reference": "336aff0ac52e306c98e7455bc3e8d7b0bf777a5e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/875145fabfa261fa9c1aea663dd29ddce92dca8f",
|
||||
"reference": "875145fabfa261fa9c1aea663dd29ddce92dca8f",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/336aff0ac52e306c98e7455bc3e8d7b0bf777a5e",
|
||||
"reference": "336aff0ac52e306c98e7455bc3e8d7b0bf777a5e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3843,14 +3843,14 @@
|
||||
"myclabs/deep-copy": "~1.3",
|
||||
"php": "^5.6 || ^7.0",
|
||||
"phpspec/prophecy": "^1.3.1",
|
||||
"phpunit/php-code-coverage": "^4.0.1",
|
||||
"phpunit/php-code-coverage": "^4.0.3",
|
||||
"phpunit/php-file-iterator": "~1.4",
|
||||
"phpunit/php-text-template": "~1.2",
|
||||
"phpunit/php-timer": "^1.0.6",
|
||||
"phpunit/phpunit-mock-objects": "^3.2",
|
||||
"sebastian/comparator": "~1.2.2",
|
||||
"sebastian/diff": "~1.2",
|
||||
"sebastian/environment": "^1.3 || ^2.0",
|
||||
"sebastian/environment": "^1.3.4 || ^2.0",
|
||||
"sebastian/exporter": "~2.0",
|
||||
"sebastian/global-state": "~1.0",
|
||||
"sebastian/object-enumerator": "~2.0",
|
||||
@ -3874,7 +3874,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.6.x-dev"
|
||||
"dev-master": "5.7.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -3900,7 +3900,7 @@
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2016-11-21 15:23:34"
|
||||
"time": "2016-12-03 08:33:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit-mock-objects",
|
||||
@ -4476,16 +4476,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/class-loader",
|
||||
"version": "v3.1.7",
|
||||
"version": "v3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/class-loader.git",
|
||||
"reference": "61de6c27f9d4efe988ea8274f19c2d4e331dd4e4"
|
||||
"reference": "87cd4e69435d98de01d0162c5f9c0ac017075c63"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/class-loader/zipball/61de6c27f9d4efe988ea8274f19c2d4e331dd4e4",
|
||||
"reference": "61de6c27f9d4efe988ea8274f19c2d4e331dd4e4",
|
||||
"url": "https://api.github.com/repos/symfony/class-loader/zipball/87cd4e69435d98de01d0162c5f9c0ac017075c63",
|
||||
"reference": "87cd4e69435d98de01d0162c5f9c0ac017075c63",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -4501,7 +4501,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
"dev-master": "3.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -4528,7 +4528,7 @@
|
||||
],
|
||||
"description": "Symfony ClassLoader Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-11-15 12:07:16"
|
||||
"time": "2016-11-29 08:26:13"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
@ -4641,25 +4641,31 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v3.1.7",
|
||||
"version": "v3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "9da375317228e54f4ea1b013b30fa47417e84943"
|
||||
"reference": "f2300ba8fbb002c028710b92e1906e7457410693"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/9da375317228e54f4ea1b013b30fa47417e84943",
|
||||
"reference": "9da375317228e54f4ea1b013b30fa47417e84943",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/f2300ba8fbb002c028710b92e1906e7457410693",
|
||||
"reference": "f2300ba8fbb002c028710b92e1906e7457410693",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "~2.8|~3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "For validating YAML files using the lint command"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1-dev"
|
||||
"dev-master": "3.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -4686,7 +4692,7 @@
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-11-18 21:05:29"
|
||||
"time": "2016-11-18 21:17:59"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
|
@ -24,7 +24,7 @@ return [
|
||||
'must_confirm_account' => false,
|
||||
],
|
||||
'chart' => 'chartjs',
|
||||
'version' => '4.2.0',
|
||||
'version' => '4.2.1',
|
||||
'csv_import_enabled' => true,
|
||||
'maxUploadSize' => 5242880,
|
||||
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
|
||||
|
@ -87,7 +87,7 @@ class CreateMainTables extends Migration
|
||||
$table->integer('user_id', false, true);
|
||||
$table->integer('account_type_id', false, true);
|
||||
$table->string('name', 1024);
|
||||
$table->decimal('virtual_balance', 10, 4)->nullable();
|
||||
$table->decimal('virtual_balance', 14, 4)->nullable();
|
||||
$table->string('iban', 255)->nullable();
|
||||
|
||||
$table->boolean('active')->default(1);
|
||||
@ -165,8 +165,8 @@ class CreateMainTables extends Migration
|
||||
$table->integer('user_id', false, true);
|
||||
$table->string('name', 1024);
|
||||
$table->string('match', 1024);
|
||||
$table->decimal('amount_min', 10, 4);
|
||||
$table->decimal('amount_max', 10, 4);
|
||||
$table->decimal('amount_min', 14, 4);
|
||||
$table->decimal('amount_max', 14, 4);
|
||||
$table->date('date');
|
||||
$table->string('repeat_freq', 30);
|
||||
$table->smallInteger('skip', false, true)->default(0);
|
||||
@ -215,7 +215,7 @@ class CreateMainTables extends Migration
|
||||
$table->timestamps();
|
||||
$table->integer('budget_id', false, true);
|
||||
$table->date('startdate');
|
||||
$table->decimal('amount', 10, 4);
|
||||
$table->decimal('amount', 14, 4);
|
||||
$table->string('repeat_freq', 30);
|
||||
$table->boolean('repeats')->default(0);
|
||||
|
||||
@ -233,7 +233,7 @@ class CreateMainTables extends Migration
|
||||
$table->integer('budget_limit_id', false, true);
|
||||
$table->date('startdate');
|
||||
$table->date('enddate');
|
||||
$table->decimal('amount', 10, 4);
|
||||
$table->decimal('amount', 14, 4);
|
||||
|
||||
// link budget limit id to budget_limitss table
|
||||
$table->foreign('budget_limit_id')->references('id')->on('budget_limits')->onDelete('cascade');
|
||||
@ -313,7 +313,7 @@ class CreateMainTables extends Migration
|
||||
$table->softDeletes();
|
||||
$table->integer('account_id', false, true);
|
||||
$table->string('name', 1024);
|
||||
$table->decimal('targetamount', 10, 4);
|
||||
$table->decimal('targetamount', 14, 4);
|
||||
$table->date('startdate')->nullable();
|
||||
$table->date('targetdate')->nullable();
|
||||
$table->integer('order', false, true)->default(0);
|
||||
@ -334,7 +334,7 @@ class CreateMainTables extends Migration
|
||||
$table->integer('piggy_bank_id', false, true);
|
||||
$table->date('startdate')->nullable();
|
||||
$table->date('targetdate')->nullable();
|
||||
$table->decimal('currentamount', 10, 4);
|
||||
$table->decimal('currentamount', 14, 4);
|
||||
|
||||
$table->foreign('piggy_bank_id')->references('id')->on('piggy_banks')->onDelete('cascade');
|
||||
|
||||
@ -606,7 +606,7 @@ class CreateMainTables extends Migration
|
||||
$table->integer('piggy_bank_id', false, true);
|
||||
$table->integer('transaction_journal_id', false, true)->nullable();
|
||||
$table->date('date');
|
||||
$table->decimal('amount', 10, 4);
|
||||
$table->decimal('amount', 14, 4);
|
||||
|
||||
$table->foreign('piggy_bank_id')->references('id')->on('piggy_banks')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('set null');
|
||||
@ -623,7 +623,7 @@ class CreateMainTables extends Migration
|
||||
$table->integer('account_id', false, true);
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
$table->string('description', 1024)->nullable();
|
||||
$table->decimal('amount', 10, 4);
|
||||
$table->decimal('amount', 14, 4);
|
||||
|
||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
|
@ -1,4 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* 2016_10_09_150037_expand_transactions_table.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
@ -1,4 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* 2016_10_22_075804_changes_for_v410.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
@ -1,4 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* 2016_11_24_210552_changes_for_v420.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
@ -28,6 +28,7 @@ class TransactionCurrencySeeder extends Seeder
|
||||
TransactionCurrency::create(['code' => 'HUF', 'name' => 'Hungarian forint', 'symbol' => 'Ft']);
|
||||
TransactionCurrency::create(['code' => 'BRL', 'name' => 'Real', 'symbol' => 'R$']);
|
||||
TransactionCurrency::create(['code' => 'GBP', 'name' => 'British Pound', 'symbol' => '£']);
|
||||
TransactionCurrency::create(['code' => 'IDR', 'name' => 'Indonesian rupiah', 'symbol' => 'Rp']);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,9 +6,6 @@
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/* global $, lineChart, dateString, accountID, token, incomeByCategoryUri, expenseByCategoryUri, expenseByBudgetUri */
|
||||
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
var fixHelper = function (e, tr) {
|
||||
"use strict";
|
||||
@ -24,11 +21,11 @@ var fixHelper = function (e, tr) {
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
lineChart('chart/account/' + accountID + '/' + dateString, 'period-specific-account');
|
||||
lineChart(periodUri, 'period-specific-account');
|
||||
|
||||
pieChart(incomeByCategoryUri, 'account-cat-in');
|
||||
pieChart(expenseByCategoryUri, 'account-cat-out');
|
||||
pieChart(expenseByBudgetUri, 'account-budget-out');
|
||||
pieChart(incomeCategoryUri, 'account-cat-in');
|
||||
pieChart(expenseCategoryUri, 'account-cat-out');
|
||||
pieChart(expenseBudgetUri, 'account-budget-out');
|
||||
|
||||
|
||||
// sortable!
|
@ -15,10 +15,10 @@ var fixHelper = function (e, tr) {
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
lineChart('chart/account/' + accountID, 'overview-chart');
|
||||
pieChart(incomeByCategoryUri, 'account-cat-in');
|
||||
pieChart(expenseByCategoryUri, 'account-cat-out');
|
||||
pieChart(expenseByBudgetUri, 'account-budget-out');
|
||||
lineChart(singleUri, 'overview-chart');
|
||||
pieChart(incomeCategoryUri, 'account-cat-in');
|
||||
pieChart(expenseCategoryUri, 'account-cat-out');
|
||||
pieChart(expenseBudgetUri, 'account-budget-out');
|
||||
|
||||
|
||||
// sortable!
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(columnChart) === 'function' && typeof(billID) !== 'undefined') {
|
||||
columnChart('chart/bill/' + billID, 'bill-overview');
|
||||
}
|
||||
columnChart(billUri, 'bill-overview');
|
||||
}
|
||||
);
|
@ -1,117 +1,6 @@
|
||||
/* globals $, budgeted:true, currencySymbol, budgetIncomeTotal, columnChart, budgetedMuch, budgetedPercentage, token, budgetID, repetitionID, spent, lineChart */
|
||||
|
||||
function drawSpentBar() {
|
||||
"use strict";
|
||||
if ($('.spentBar').length > 0) {
|
||||
var overspent = spent > budgeted;
|
||||
var pct;
|
||||
|
||||
if (overspent) {
|
||||
// draw overspent bar
|
||||
pct = (budgeted / spent) * 100;
|
||||
$('.spentBar .progress-bar-warning').css('width', pct + '%');
|
||||
$('.spentBar .progress-bar-danger').css('width', (100 - pct) + '%');
|
||||
} else {
|
||||
// draw normal bar:
|
||||
pct = (spent / budgeted) * 100;
|
||||
$('.spentBar .progress-bar-info').css('width', pct + '%');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawBudgetedBar() {
|
||||
"use strict";
|
||||
|
||||
if ($('.budgetedBar').length > 0) {
|
||||
var budgetedMuch = budgeted > budgetIncomeTotal;
|
||||
|
||||
// recalculate percentage:
|
||||
|
||||
var pct;
|
||||
if (budgetedMuch) {
|
||||
// budgeted too much.
|
||||
pct = (budgetIncomeTotal / budgeted) * 100;
|
||||
$('.budgetedBar .progress-bar-warning').css('width', pct + '%');
|
||||
$('.budgetedBar .progress-bar-danger').css('width', (100 - pct) + '%');
|
||||
$('.budgetedBar .progress-bar-info').css('width', 0);
|
||||
} else {
|
||||
pct = (budgeted / budgetIncomeTotal) * 100;
|
||||
$('.budgetedBar .progress-bar-warning').css('width', 0);
|
||||
$('.budgetedBar .progress-bar-danger').css('width', 0);
|
||||
$('.budgetedBar .progress-bar-info').css('width', pct + '%');
|
||||
}
|
||||
|
||||
$('#budgetedAmount').html(currencySymbol + ' ' + budgeted.toFixed(2));
|
||||
}
|
||||
}
|
||||
|
||||
function updateBudgetedAmounts(e) {
|
||||
"use strict";
|
||||
var target = $(e.target);
|
||||
var id = target.data('id');
|
||||
var value = target.val();
|
||||
var original = target.data('original');
|
||||
var difference = value - original;
|
||||
if (difference !== 0) {
|
||||
// add difference to 'budgeted' var
|
||||
budgeted = budgeted + difference;
|
||||
|
||||
// update original:
|
||||
target.data('original', value);
|
||||
// run drawBudgetedBar() again:
|
||||
drawBudgetedBar();
|
||||
|
||||
// send a post to Firefly to update the amount:
|
||||
$.post('budgets/amount/' + id, {amount: value, _token: token}).done(function (data) {
|
||||
// update the link if relevant:
|
||||
if (data.repetition > 0) {
|
||||
$('.budget-link[data-id="' + id + '"]').attr('href', 'budgets/show/' + id + '/' + data.repetition);
|
||||
} else {
|
||||
$('.budget-link[data-id="' + id + '"]').attr('href', 'budgets/show/' + id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
console.log('Budget id is ' + id);
|
||||
console.log('Difference = ' + (value - original ));
|
||||
|
||||
}
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
$('.updateIncome').on('click', updateIncome);
|
||||
|
||||
/*
|
||||
On start, fill the "spent"-bar using the content from the page.
|
||||
*/
|
||||
drawSpentBar();
|
||||
drawBudgetedBar();
|
||||
|
||||
/*
|
||||
When the input changes, update the percentages for the budgeted bar:
|
||||
*/
|
||||
$('input[type="number"]').on('input', updateBudgetedAmounts);
|
||||
|
||||
|
||||
/*
|
||||
Draw the charts, if necessary:
|
||||
*/
|
||||
if (typeof budgetID !== 'undefined' && typeof repetitionID === 'undefined') {
|
||||
columnChart('chart/budget/' + budgetID, 'budgetOverview');
|
||||
}
|
||||
if (typeof budgetID !== 'undefined' && typeof repetitionID !== 'undefined') {
|
||||
lineChart('chart/budget/' + budgetID + '/' + repetitionID, 'budgetOverview');
|
||||
}
|
||||
columnChart(budgetChartUri, 'budgetOverview');
|
||||
|
||||
});
|
||||
|
||||
function updateIncome() {
|
||||
"use strict";
|
||||
$('#defaultModal').empty().load('budgets/income', function () {
|
||||
$('#defaultModal').modal('show');
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1,19 +1,4 @@
|
||||
/* globals $, categoryID, columnChart, categoryDate */
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof categoryID !== 'undefined') {
|
||||
// more splits:
|
||||
if ($('#all').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
}
|
||||
if ($('#period').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/period', 'period');
|
||||
}
|
||||
|
||||
}
|
||||
if (typeof categoryID !== 'undefined' && typeof categoryDate !== 'undefined') {
|
||||
columnChart('chart/category/' + categoryID + '/period/' + categoryDate, 'period-specific-period');
|
||||
}
|
||||
|
||||
|
||||
});
|
4
public/js/ff/categories/show-by-date.js
Normal file
4
public/js/ff/categories/show-by-date.js
Normal file
@ -0,0 +1,4 @@
|
||||
$(function () {
|
||||
"use strict";
|
||||
columnChart(specific, 'period-specific-period');
|
||||
});
|
@ -1,19 +1,5 @@
|
||||
/* globals $, categoryID, columnChart, categoryDate */
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof categoryID !== 'undefined') {
|
||||
// more splits:
|
||||
if ($('#all').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
}
|
||||
if ($('#period').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/period', 'period');
|
||||
}
|
||||
|
||||
}
|
||||
if (typeof categoryID !== 'undefined' && typeof categoryDate !== 'undefined') {
|
||||
columnChart('chart/category/' + categoryID + '/period/' + categoryDate, 'period-specific-period');
|
||||
}
|
||||
|
||||
|
||||
columnChart(all, 'all');
|
||||
columnChart(current, 'period');
|
||||
});
|
@ -1,19 +0,0 @@
|
||||
/* globals $, categoryID, columnChart, categoryDate */
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof categoryID !== 'undefined') {
|
||||
// more splits:
|
||||
if ($('#all').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
}
|
||||
if ($('#period').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/period', 'period');
|
||||
}
|
||||
|
||||
}
|
||||
if (typeof categoryID !== 'undefined' && typeof categoryDate !== undefined) {
|
||||
columnChart('chart/category/' + categoryID + '/period/' + categoryDate, 'period-specific-period');
|
||||
}
|
||||
|
||||
|
||||
});
|
@ -32,14 +32,14 @@ function endTheTour() {
|
||||
|
||||
function drawChart() {
|
||||
"use strict";
|
||||
lineChart('chart/account/frontpage', 'accounts-chart');
|
||||
lineChart(accountFrontpageUri, 'accounts-chart');
|
||||
if (billCount > 0) {
|
||||
pieChart('chart/bill/frontpage', 'bills-chart');
|
||||
}
|
||||
stackedColumnChart('chart/budget/frontpage', 'budgets-chart');
|
||||
columnChart('chart/category/frontpage', 'categories-chart');
|
||||
columnChart('chart/account/expense', 'expense-accounts-chart');
|
||||
columnChart('chart/account/revenue', 'revenue-accounts-chart');
|
||||
columnChart(accountExpenseUri, 'expense-accounts-chart');
|
||||
columnChart(accountRevenueUri, 'revenue-accounts-chart');
|
||||
|
||||
|
||||
getBoxAmounts();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user