mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-25 06:51:08 +00:00
Initial code for new budget report #426
This commit is contained in:
@@ -110,6 +110,16 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $budgets
|
||||||
|
*
|
||||||
|
* @return ReportGeneratorInterface
|
||||||
|
*/
|
||||||
|
public function setBudgets(Collection $budgets): ReportGeneratorInterface
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $categories
|
* @param Collection $categories
|
||||||
*
|
*
|
||||||
|
@@ -15,7 +15,6 @@ namespace FireflyIII\Generator\Report\Category;
|
|||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Crypt;
|
|
||||||
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
use FireflyIII\Helpers\Collector\JournalCollector;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
@@ -95,6 +94,16 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $budgets
|
||||||
|
*
|
||||||
|
* @return ReportGeneratorInterface
|
||||||
|
*/
|
||||||
|
public function setBudgets(Collection $budgets): ReportGeneratorInterface
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $categories
|
* @param Collection $categories
|
||||||
*
|
*
|
||||||
|
@@ -36,6 +36,13 @@ interface ReportGeneratorInterface
|
|||||||
*/
|
*/
|
||||||
public function setAccounts(Collection $accounts): ReportGeneratorInterface;
|
public function setAccounts(Collection $accounts): ReportGeneratorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $budgets
|
||||||
|
*
|
||||||
|
* @return ReportGeneratorInterface
|
||||||
|
*/
|
||||||
|
public function setBudgets(Collection $budgets): ReportGeneratorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $categories
|
* @param Collection $categories
|
||||||
*
|
*
|
||||||
|
@@ -63,6 +63,16 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $budgets
|
||||||
|
*
|
||||||
|
* @return ReportGeneratorInterface
|
||||||
|
*/
|
||||||
|
public function setBudgets(Collection $budgets): ReportGeneratorInterface
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $categories
|
* @param Collection $categories
|
||||||
*
|
*
|
||||||
|
@@ -60,6 +60,16 @@ class MultiYearReportGenerator implements ReportGeneratorInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $budgets
|
||||||
|
*
|
||||||
|
* @return ReportGeneratorInterface
|
||||||
|
*/
|
||||||
|
public function setBudgets(Collection $budgets): ReportGeneratorInterface
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $categories
|
* @param Collection $categories
|
||||||
*
|
*
|
||||||
|
@@ -60,6 +60,16 @@ class YearReportGenerator implements ReportGeneratorInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $budgets
|
||||||
|
*
|
||||||
|
* @return ReportGeneratorInterface
|
||||||
|
*/
|
||||||
|
public function setBudgets(Collection $budgets): ReportGeneratorInterface
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $categories
|
* @param Collection $categories
|
||||||
*
|
*
|
||||||
|
@@ -20,6 +20,7 @@ use FireflyIII\Helpers\Report\ReportHelperInterface;
|
|||||||
use FireflyIII\Http\Requests\ReportFormRequest;
|
use FireflyIII\Http\Requests\ReportFormRequest;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@@ -95,6 +96,42 @@ class ReportController extends Controller
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $accounts
|
||||||
|
* @param Collection $categories
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function budgetReport(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
if ($end < $start) {
|
||||||
|
return view('error')->with('message', trans('firefly.end_after_start_date'));
|
||||||
|
}
|
||||||
|
if ($start < session('first')) {
|
||||||
|
$start = session('first');
|
||||||
|
}
|
||||||
|
|
||||||
|
View::share(
|
||||||
|
'subTitle', trans(
|
||||||
|
'firefly.report_budget',
|
||||||
|
[
|
||||||
|
'start' => $start->formatLocalized($this->monthFormat),
|
||||||
|
'end' => $end->formatLocalized($this->monthFormat),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$generator = ReportGeneratorFactory::reportGenerator('Budget', $start, $end);
|
||||||
|
$generator->setAccounts($accounts);
|
||||||
|
$generator->setBudgets($budgets);
|
||||||
|
$result = $generator->generate();
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
* @param Collection $categories
|
* @param Collection $categories
|
||||||
@@ -198,6 +235,9 @@ class ReportController extends Controller
|
|||||||
case 'category':
|
case 'category':
|
||||||
$result = $this->categoryReportOptions();
|
$result = $this->categoryReportOptions();
|
||||||
break;
|
break;
|
||||||
|
case 'budget':
|
||||||
|
$result = $this->budgetReportOptions();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response::json(['html' => $result]);
|
return Response::json(['html' => $result]);
|
||||||
@@ -217,6 +257,7 @@ class ReportController extends Controller
|
|||||||
$end = $request->getEndDate()->format('Ymd');
|
$end = $request->getEndDate()->format('Ymd');
|
||||||
$accounts = join(',', $request->getAccountList()->pluck('id')->toArray());
|
$accounts = join(',', $request->getAccountList()->pluck('id')->toArray());
|
||||||
$categories = join(',', $request->getCategoryList()->pluck('id')->toArray());
|
$categories = join(',', $request->getCategoryList()->pluck('id')->toArray());
|
||||||
|
$budgets = join(',', $request->getBudgetList()->pluck('id')->toArray());
|
||||||
|
|
||||||
if ($request->getAccountList()->count() === 0) {
|
if ($request->getAccountList()->count() === 0) {
|
||||||
Session::flash('error', trans('firefly.select_more_than_one_account'));
|
Session::flash('error', trans('firefly.select_more_than_one_account'));
|
||||||
@@ -230,6 +271,12 @@ class ReportController extends Controller
|
|||||||
return redirect(route('reports.index'));
|
return redirect(route('reports.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($request->getBudgetList()->count() === 0 && $reportType === 'budget') {
|
||||||
|
Session::flash('error', trans('firefly.select_more_than_one_budget'));
|
||||||
|
|
||||||
|
return redirect(route('reports.index'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($end < $start) {
|
if ($end < $start) {
|
||||||
return view('error')->with('message', trans('firefly.end_after_start_date'));
|
return view('error')->with('message', trans('firefly.end_after_start_date'));
|
||||||
}
|
}
|
||||||
@@ -251,11 +298,28 @@ class ReportController extends Controller
|
|||||||
case 'audit':
|
case 'audit':
|
||||||
$uri = route('reports.report.audit', [$accounts, $start, $end]);
|
$uri = route('reports.report.audit', [$accounts, $start, $end]);
|
||||||
break;
|
break;
|
||||||
|
case 'budget':
|
||||||
|
$uri = route('reports.report.budget', [$accounts, $budgets, $start, $end]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect($uri);
|
return redirect($uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function budgetReportOptions(): string
|
||||||
|
{
|
||||||
|
/** @var BudgetRepositoryInterface $repository */
|
||||||
|
$repository = app(BudgetRepositoryInterface::class);
|
||||||
|
$budgets = $repository->getBudgets();
|
||||||
|
$result = view('reports.options.budget', compact('budgets'))->render();
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@@ -17,6 +17,7 @@ use Carbon\Carbon;
|
|||||||
use Exception;
|
use Exception;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
@@ -79,6 +80,27 @@ class ReportFormRequest extends Request
|
|||||||
return $collection;
|
return $collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getBudgetList(): Collection
|
||||||
|
{
|
||||||
|
/** @var BudgetRepositoryInterface $repository */
|
||||||
|
$repository = app(BudgetRepositoryInterface::class);
|
||||||
|
$set = $this->get('budget');
|
||||||
|
$collection = new Collection;
|
||||||
|
if (is_array($set)) {
|
||||||
|
foreach ($set as $budgetId) {
|
||||||
|
$budget = $repository->find(intval($budgetId));
|
||||||
|
if (!is_null($budget->id)) {
|
||||||
|
$collection->push($budget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $collection;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Carbon
|
* @return Carbon
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
@@ -125,7 +147,7 @@ class ReportFormRequest extends Request
|
|||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'report_type' => 'in:audit,default,category',
|
'report_type' => 'in:audit,default,category,budget',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -65,12 +65,22 @@ function getReportOptions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setOptionalFromCookies() {
|
function setOptionalFromCookies() {
|
||||||
|
var arr;
|
||||||
|
// categories
|
||||||
if ((readCookie('report-categories') !== null)) {
|
if ((readCookie('report-categories') !== null)) {
|
||||||
var arr = readCookie('report-categories').split(',');
|
arr = readCookie('report-categories').split(',');
|
||||||
arr.forEach(function (val) {
|
arr.forEach(function (val) {
|
||||||
$('input[class="category-checkbox"][type="checkbox"][value="' + val + '"]').prop('checked', true);
|
$('input[class="category-checkbox"][type="checkbox"][value="' + val + '"]').prop('checked', true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// and budgets!
|
||||||
|
if ((readCookie('report-budgets') !== null)) {
|
||||||
|
arr = readCookie('report-budgets').split(',');
|
||||||
|
arr.forEach(function (val) {
|
||||||
|
$('input[class="budget-checkbox"][type="checkbox"][value="' + val + '"]').prop('checked', true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function catchSubmit() {
|
function catchSubmit() {
|
||||||
@@ -90,7 +100,6 @@ function catchSubmit() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// all category ids:
|
// all category ids:
|
||||||
//category-checkbox
|
|
||||||
var categories = [];
|
var categories = [];
|
||||||
$.each($('.category-checkbox'), function (i, v) {
|
$.each($('.category-checkbox'), function (i, v) {
|
||||||
var c = $(v);
|
var c = $(v);
|
||||||
@@ -99,6 +108,15 @@ function catchSubmit() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// all budget ids:
|
||||||
|
var budgets = [];
|
||||||
|
$.each($('.budget-checkbox'), function (i, v) {
|
||||||
|
var c = $(v);
|
||||||
|
if (c.prop('checked')) {
|
||||||
|
budgets.push(c.val());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// remember all
|
// remember all
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
@@ -106,6 +124,7 @@ function catchSubmit() {
|
|||||||
createCookie('report-type', $('select[name="report_type"]').val(), 365);
|
createCookie('report-type', $('select[name="report_type"]').val(), 365);
|
||||||
createCookie('report-accounts', accounts, 365);
|
createCookie('report-accounts', accounts, 365);
|
||||||
createCookie('report-categories', categories, 365);
|
createCookie('report-categories', categories, 365);
|
||||||
|
createCookie('report-budgets', budgets, 365);
|
||||||
createCookie('report-start', moment(picker.startDate).format("YYYYMMDD"), 365);
|
createCookie('report-start', moment(picker.startDate).format("YYYYMMDD"), 365);
|
||||||
createCookie('report-end', moment(picker.endDate).format("YYYYMMDD"), 365);
|
createCookie('report-end', moment(picker.endDate).format("YYYYMMDD"), 365);
|
||||||
}
|
}
|
||||||
|
@@ -679,6 +679,7 @@ return [
|
|||||||
'report_type_default' => 'Default financial report',
|
'report_type_default' => 'Default financial report',
|
||||||
'report_type_audit' => 'Transaction history overview (audit)',
|
'report_type_audit' => 'Transaction history overview (audit)',
|
||||||
'report_type_category' => 'Category report',
|
'report_type_category' => 'Category report',
|
||||||
|
'report_type_budget' => 'Budget report',
|
||||||
'report_type_meta-history' => 'Categories, budgets and bills overview',
|
'report_type_meta-history' => 'Categories, budgets and bills overview',
|
||||||
'more_info_help' => 'More information about these types of reports can be found in the help pages. Press the (?) icon in the top right corner.',
|
'more_info_help' => 'More information about these types of reports can be found in the help pages. Press the (?) icon in the top right corner.',
|
||||||
'report_included_accounts' => 'Included accounts',
|
'report_included_accounts' => 'Included accounts',
|
||||||
@@ -698,6 +699,7 @@ return [
|
|||||||
'reports_submit' => 'View report',
|
'reports_submit' => 'View report',
|
||||||
'end_after_start_date' => 'End date of report must be after start date.',
|
'end_after_start_date' => 'End date of report must be after start date.',
|
||||||
'select_category' => 'Select one or more categories.',
|
'select_category' => 'Select one or more categories.',
|
||||||
|
'select_budget' => 'Select one or more budgets.',
|
||||||
'income_per_category' => 'Income per category',
|
'income_per_category' => 'Income per category',
|
||||||
'expense_per_category' => 'Expense per category',
|
'expense_per_category' => 'Expense per category',
|
||||||
'income_per_account' => 'Income per account',
|
'income_per_account' => 'Income per account',
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
<select name="report_type" class="form-control" id="inputReportType">
|
<select name="report_type" class="form-control" id="inputReportType">
|
||||||
<option selected label="{{ 'report_type_default'|_ }}" value="default">{{ 'report_type_default'|_ }}</option>
|
<option selected label="{{ 'report_type_default'|_ }}" value="default">{{ 'report_type_default'|_ }}</option>
|
||||||
<option label="{{ 'report_type_audit'|_ }}" value="audit">{{ 'report_type_audit'|_ }}</option>
|
<option label="{{ 'report_type_audit'|_ }}" value="audit">{{ 'report_type_audit'|_ }}</option>
|
||||||
|
<option label="{{ 'report_type_budget'|_ }}" value="budget">{{ 'report_type_budget'|_ }}</option>
|
||||||
<option label="{{ 'report_type_category'|_ }}" value="category">{{ 'report_type_category'|_ }}</option>
|
<option label="{{ 'report_type_category'|_ }}" value="category">{{ 'report_type_category'|_ }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
8
resources/views/reports/options/budget.twig
Normal file
8
resources/views/reports/options/budget.twig
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<p>
|
||||||
|
{{ 'select_budget'|_ }}
|
||||||
|
</p>
|
||||||
|
{% for budget in budgets %}
|
||||||
|
<label class="checkbox-inline">
|
||||||
|
<input type="checkbox" class="budget-checkbox" name="budget[]" value="{{ budget.id }}"> {{ budget.name }}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
@@ -456,6 +456,7 @@ Route::group(
|
|||||||
Route::get('default/{accountList}/{start_date}/{end_date}', ['uses' => 'ReportController@defaultReport', 'as' => 'report.default']);
|
Route::get('default/{accountList}/{start_date}/{end_date}', ['uses' => 'ReportController@defaultReport', 'as' => 'report.default']);
|
||||||
Route::get('audit/{accountList}/{start_date}/{end_date}', ['uses' => 'ReportController@auditReport', 'as' => 'report.audit']);
|
Route::get('audit/{accountList}/{start_date}/{end_date}', ['uses' => 'ReportController@auditReport', 'as' => 'report.audit']);
|
||||||
Route::get('category/{accountList}/{categoryList}/{start_date}/{end_date}', ['uses' => 'ReportController@categoryReport', 'as' => 'report.category']);
|
Route::get('category/{accountList}/{categoryList}/{start_date}/{end_date}', ['uses' => 'ReportController@categoryReport', 'as' => 'report.category']);
|
||||||
|
Route::get('budget/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'ReportController@budgetReport', 'as' => 'report.budget']);
|
||||||
|
|
||||||
Route::post('', ['uses' => 'ReportController@postIndex', 'as' => 'index.post']);
|
Route::post('', ['uses' => 'ReportController@postIndex', 'as' => 'index.post']);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user