mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Various report updates and code cleanup.
This commit is contained in:
parent
905a2432c6
commit
f4b9b7ae84
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
$auditData[$id]['dayBeforeBalance'] = $dayBeforeBalance;
|
||||
}
|
||||
|
||||
$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',
|
||||
@ -87,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)
|
||||
|
@ -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, true);
|
||||
$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
|
||||
|
@ -252,6 +252,48 @@ class BudgetController extends Controller
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function periodNoBudget(BudgetRepositoryInterface $repository, Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
// 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
|
||||
|
@ -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;
|
||||
@ -31,14 +32,13 @@ class BudgetController extends Controller
|
||||
|
||||
/**
|
||||
*
|
||||
* @param BudgetReportHelperInterface $helper
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function budgetPeriodReport(BudgetReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||
public function budgetPeriodReport(Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
@ -46,12 +46,19 @@ class BudgetController extends Controller
|
||||
$cache->addProperty('budget-period-report');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$budgets = $helper->getBudgetPeriodReport($start, $end, $accounts);
|
||||
$result = view('reports.partials.budget-period', compact('budgets', 'periods'))->render();
|
||||
// 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;
|
||||
@ -86,4 +93,31 @@ class BudgetController extends Controller
|
||||
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;
|
||||
}
|
||||
}
|
@ -31,40 +31,6 @@ use Navigation;
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function categoryPeriodReport(Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category-period-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();
|
||||
$report = $repository->getCategoryPeriodReport($categories, $accounts, $start, $end, true);
|
||||
$report = $this->filterCategoryPeriodReport($report);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
|
||||
$result = view('reports.partials.category-period', compact('categories', 'periods', 'report'))->render();
|
||||
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReportHelperInterface $helper
|
||||
* @param Carbon $start
|
||||
@ -93,6 +59,73 @@ class CategoryController extends Controller
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function expenseReport(Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
$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 incomeReport(Carbon $start, Carbon $end, Collection $accounts)
|
||||
{
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters empty results from category period report
|
||||
*
|
||||
@ -100,22 +133,16 @@ class CategoryController extends Controller
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function filterCategoryPeriodReport(array $data): array
|
||||
private function filterReport(array $data): array
|
||||
{
|
||||
/**
|
||||
* @var string $type
|
||||
* @var array $report
|
||||
*/
|
||||
foreach ($data as $type => $report) {
|
||||
foreach ($report as $categoryId => $set) {
|
||||
$sum = '0';
|
||||
foreach ($set['entries'] as $amount) {
|
||||
$sum = bcadd($amount, $sum);
|
||||
}
|
||||
$data[$type][$categoryId]['sum'] = $sum;
|
||||
if (bccomp('0', $sum) === 0) {
|
||||
unset($data[$type][$categoryId]);
|
||||
}
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,25 +150,5 @@ class CategoryController extends Controller
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $categoryId
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getCategoryName(int $categoryId, Collection $categories): string
|
||||
{
|
||||
|
||||
$first = $categories->filter(
|
||||
function (Category $category) use ($categoryId) {
|
||||
return $categoryId === $category->id;
|
||||
}
|
||||
);
|
||||
if (!is_null($first->first())) {
|
||||
return $first->first()->name;
|
||||
}
|
||||
|
||||
return '(unknown)';
|
||||
}
|
||||
|
||||
}
|
@ -368,10 +368,10 @@ 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.*']);
|
||||
->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.');
|
||||
|
||||
|
@ -250,19 +250,19 @@ class AccountTasker implements AccountTaskerInterface
|
||||
$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);
|
||||
->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']);
|
||||
}
|
||||
@ -302,25 +302,27 @@ class AccountTasker implements AccountTaskerInterface
|
||||
$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');
|
||||
->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']);
|
||||
|
@ -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
|
||||
|
@ -219,11 +219,10 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $noBudget
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end, bool $noBudget): array
|
||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
$data = [];
|
||||
@ -252,11 +251,6 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
$data[$budgetId]['entries'][$date] = bcadd($data[$budgetId]['entries'][$date] ?? '0', $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
if ($noBudget) {
|
||||
// and now the same for stuff without a budget:
|
||||
$data[0] = $this->getNoBudgetPeriodReport($start, $end);
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
@ -295,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
|
||||
@ -533,58 +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)';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getNoBudgetPeriodReport(Carbon $start, Carbon $end): array
|
||||
{
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->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;
|
||||
}
|
||||
}
|
||||
|
@ -96,11 +96,10 @@ interface BudgetRepositoryInterface
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $noBudget
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end, bool $noBudget): array;
|
||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
@ -112,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
|
||||
|
@ -175,32 +175,6 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is being used to generate the category overview in the year/multi-year report. Its used
|
||||
* in both the year/multi-year budget overview AND in the accompanying chart.
|
||||
*
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param @bool $noCategory
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCategoryPeriodReport(Collection $categories, Collection $accounts, Carbon $start, Carbon $end, bool $noCategory): array
|
||||
{
|
||||
$data = [
|
||||
'income' => $this->getCategoryReportData($categories, $accounts, $start, $end, $noCategory, [TransactionType::DEPOSIT, TransactionType::TRANSFER]),
|
||||
'expense' => $this->getCategoryReportData(
|
||||
$categories, $accounts, $start, $end, $noCategory, [TransactionType::WITHDRAWAL, TransactionType::TRANSFER]
|
||||
),
|
||||
];
|
||||
|
||||
return $data;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param Collection $accounts
|
||||
@ -250,6 +224,158 @@ 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) {
|
||||
$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);
|
||||
$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) {
|
||||
$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) {
|
||||
$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
|
||||
{
|
||||
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])->enableInternalFilter();
|
||||
$collector->withoutCategory();
|
||||
$transactions = $collector->getJournals();
|
||||
$result = [
|
||||
'entries' => [],
|
||||
'name' => strval(trans('firefly.no_category')),
|
||||
'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 $categories
|
||||
* @param Collection $accounts
|
||||
@ -314,55 +440,6 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $noCategory
|
||||
* @param array $types
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getCategoryReportData(Collection $categories, Collection $accounts, Carbon $start, Carbon $end, bool $noCategory, array $types): 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($types)
|
||||
->withOpposingAccount()
|
||||
->enableInternalFilter();
|
||||
$transactions = $collector->getJournals();
|
||||
|
||||
// loop transactions:
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$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);
|
||||
}
|
||||
|
||||
if ($noCategory) {
|
||||
// and now the same for stuff without a budget:
|
||||
//$data[0] = $this->getNoBudgetPeriodReport($start, $end);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
|
@ -24,7 +24,6 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface CategoryRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
@ -83,20 +82,6 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function getCategories(): Collection;
|
||||
|
||||
/**
|
||||
* This method is being used to generate the category overview in the year/multi-year report. Its used
|
||||
* in both the year/multi-year budget overview AND in the accompanying chart.
|
||||
*
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $noCategory
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCategoryPeriodReport(Collection $categories, Collection $accounts, Carbon $start, Carbon $end, bool $noCategory): array;
|
||||
|
||||
/**
|
||||
* Return most recent transaction(journal) date.
|
||||
*
|
||||
@ -107,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
|
||||
|
@ -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
|
||||
|
@ -172,36 +172,36 @@ class JournalTasker implements JournalTaskerInterface
|
||||
|
||||
// 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');
|
||||
->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.
|
||||
|
@ -114,10 +114,10 @@ class UserRepository implements UserRepositoryInterface
|
||||
$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();
|
||||
->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();
|
||||
|
@ -5,7 +5,9 @@ $(function () {
|
||||
drawChart();
|
||||
|
||||
loadAjaxPartial('budgetPeriodReport', budgetPeriodReportUri);
|
||||
loadAjaxPartial('categoryPeriodReport', categoryPeriodReportUri);
|
||||
|
||||
loadAjaxPartial('categoryExpense', categoryExpenseUri);
|
||||
loadAjaxPartial('categoryIncome', categoryIncomeUri);
|
||||
});
|
||||
|
||||
function drawChart() {
|
||||
|
@ -85,4 +85,5 @@ return [
|
||||
'file' => 'The :attribute must be a file.',
|
||||
'in_array' => 'The :attribute field does not exist in :other.',
|
||||
'present' => 'The :attribute field must be present.',
|
||||
'amount_zero' => 'The total amount cannot be zero',
|
||||
];
|
||||
|
@ -113,14 +113,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# same thing but for categories #}
|
||||
{# same thing but for categories (expenses) #}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'categories'|_ }}</h3>
|
||||
<h3 class="box-title">{{ 'categories'|_ }} ({{ 'expenses'|_ }})</h3>
|
||||
</div>
|
||||
<div class="box-body no-padding table-responsive loading" id="categoryPeriodReport">
|
||||
<div class="box-body no-padding table-responsive loading" id="categoryExpense">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# same thing but for categories (income) #}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'categories'|_ }} ({{ 'income'|_ }})</h3>
|
||||
</div>
|
||||
<div class="box-body no-padding table-responsive loading" id="categoryIncome">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -164,7 +177,9 @@
|
||||
var incExpReportUri = '{{ route('reports.data.incExpReport', [start.format('Ymd'), end.format('Ymd'), accountIds]) }}';
|
||||
|
||||
var budgetPeriodReportUri = '{{ route('reports.data.budgetPeriodReport', [start.format('Ymd'), end.format('Ymd'), accountIds]) }}';
|
||||
var categoryPeriodReportUri = '{{ route('reports.data.categoryPeriodReport', [start.format('Ymd'), end.format('Ymd'), accountIds]) }}';
|
||||
var categoryExpenseUri = '{{ route('reports.data.categoryExpense', [start.format('Ymd'), end.format('Ymd'), accountIds]) }}';
|
||||
var categoryIncomeUri = '{{ route('reports.data.categoryIncome', [start.format('Ymd'), end.format('Ymd'), accountIds]) }}';
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="js/ff/reports/default/all.js"></script>
|
||||
|
@ -9,7 +9,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for id, info in budgets %}
|
||||
{% for id, info in report %}
|
||||
<tr>
|
||||
<td data-value="{{ info.name }}">
|
||||
<a title="{{ info.name }}" href="#" data-budget="{{ id }}" class="budget-chart-activate">{{ info.name }}</a>
|
||||
|
@ -1,75 +1,44 @@
|
||||
<table class="table table-hover sortable table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan="2" data-defaultsort="disabled">{{ 'category'|_ }}</th>
|
||||
<th data-defaultsort="disabled">{{ 'category'|_ }}</th>
|
||||
{% for period in periods %}
|
||||
<th colspan="2" data-defaultsort="disabled">{{ period }}</th>
|
||||
<th data-defaultsort="disabled">{{ period }}</th>
|
||||
{% endfor %}
|
||||
<th colspan="2" data-defaultsort="disabled">{{ 'sum'|_ }}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
{% for period in periods %}
|
||||
<th data-defaultsign="_19">In</th>
|
||||
<th data-defaultsign="_19">Out</th>
|
||||
{% endfor %}
|
||||
<th data-defaultsign="_19">In</th>
|
||||
<th data-defaultsign="_19">Out</th>
|
||||
<th data-defaultsort="disabled">{{ 'sum'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for category in categories %}
|
||||
{% if report.income[category.id] or report.expense[category.id] %}
|
||||
<tr>
|
||||
<td data-value="{{ category.name }}">
|
||||
<a title="{{ category.name }}" href="#" data-category="{{ category.id }}" class="category-chart-activate">{{ category.name }}</a>
|
||||
{% for id, info in report %}
|
||||
<tr>
|
||||
<td data-value="{{ info.name }}">
|
||||
<a title="{{ info.name }}" href="#" data-category="{{ id }}" class="category-chart-activate">{{ info.name }}</a>
|
||||
</td>
|
||||
|
||||
{% for key, period in periods %}
|
||||
{# income first #}
|
||||
{% if(info.entries[key]) %}
|
||||
<td data-value="{{ info.entries[key] }}">
|
||||
{{ info.entries[key]|formatAmount }}
|
||||
</td>
|
||||
{% else %}
|
||||
<td data-value="0">
|
||||
{{ 0|formatAmount }}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{# if sum of income, display: #}
|
||||
{% if info.sum %}
|
||||
<td data-value="{{ info.sum }}">
|
||||
{{ info.sum|formatAmount }}
|
||||
</td>
|
||||
|
||||
{% for key, period in periods %}
|
||||
{# income first #}
|
||||
{% if(report.income[category.id].entries[key]) %}
|
||||
<td data-value="{{ report.income[category.id].entries[key] }}">
|
||||
{{ report.income[category.id].entries[key]|formatAmount }}
|
||||
</td>
|
||||
{% else %}
|
||||
<td data-value="0">
|
||||
{{ 0|formatAmount }}
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
{# expenses #}
|
||||
{% if(report.expense[category.id].entries[key]) %}
|
||||
<td data-value="{{ report.expense[category.id].entries[key] }}">
|
||||
{{ report.expense[category.id].entries[key]|formatAmount }}
|
||||
</td>
|
||||
{% else %}
|
||||
<td data-value="0">
|
||||
{{ 0|formatAmount }}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{# if sum of income, display: #}
|
||||
{% if report.income[category.id].sum %}
|
||||
<td data-value="{{ report.income[category.id].sum }}">
|
||||
{{ report.income[category.id].sum|formatAmount }}
|
||||
</td>
|
||||
{% else %}
|
||||
<td data-value="0">
|
||||
{{ 0|formatAmount }}
|
||||
</td>
|
||||
{% endif %}
|
||||
{# if sum of expense, display: #}
|
||||
{% if report.expense[category.id].sum %}
|
||||
<td data-value="{{ report.expense[category.id].sum }}">
|
||||
{{ report.expense[category.id].sum|formatAmount }}
|
||||
</td>
|
||||
{% else %}
|
||||
<td data-value="0">
|
||||
{{ 0|formatAmount }}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<td data-value="0">
|
||||
{{ 0|formatAmount }}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
@ -210,6 +210,7 @@ Route::group(
|
||||
|
||||
// budgets:
|
||||
Route::get('/chart/budget/frontpage', ['uses' => 'Chart\BudgetController@frontpage']);
|
||||
Route::get('/chart/budget/period/0/default/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\BudgetController@periodNoBudget']);
|
||||
Route::get('/chart/budget/period/{budget}/default/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\BudgetController@period']);
|
||||
|
||||
// this chart is used in reports:
|
||||
@ -410,11 +411,16 @@ Route::group(
|
||||
['uses' => 'Report\BudgetController@budgetPeriodReport', 'as' => 'reports.data.budgetPeriodReport']
|
||||
);
|
||||
|
||||
// category period overview
|
||||
// category period overview (expense and income)
|
||||
Route::get(
|
||||
'/reports/data/category-period/{start_date}/{end_date}/{accountList}',
|
||||
['uses' => 'Report\CategoryController@categoryPeriodReport', 'as' => 'reports.data.categoryPeriodReport']
|
||||
'/reports/data/category-expense/{start_date}/{end_date}/{accountList}',
|
||||
['uses' => 'Report\CategoryController@expenseReport', 'as' => 'reports.data.categoryExpense']
|
||||
);
|
||||
Route::get(
|
||||
'/reports/data/category-income/{start_date}/{end_date}/{accountList}',
|
||||
['uses' => 'Report\CategoryController@incomeReport', 'as' => 'reports.data.categoryIncome']
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Rules Controller
|
||||
|
Loading…
Reference in New Issue
Block a user