mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-05 12:12:18 +00:00
Fixes for #109.
This commit is contained in:
@@ -45,14 +45,11 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
|||||||
|
|
||||||
foreach ($entries as $entry) {
|
foreach ($entries as $entry) {
|
||||||
$data['labels'][] = $entry[0]->formatLocalized($format);
|
$data['labels'][] = $entry[0]->formatLocalized($format);
|
||||||
$amount = round($entry[1], 2);
|
$spent = round($entry[1], 2);
|
||||||
if ($amount > 0) {
|
$earned = round($entry[2], 2);
|
||||||
$data['datasets'][0]['data'][] = null;
|
|
||||||
$data['datasets'][1]['data'][] = $amount;
|
$data['datasets'][0]['data'][] = $spent == 0 ? null : $spent;
|
||||||
} else {
|
$data['datasets'][1]['data'][] = $earned == 0 ? null : $earned;
|
||||||
$data['datasets'][0]['data'][] = $amount * -1;
|
|
||||||
$data['datasets'][1]['data'][] = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
@@ -5,8 +5,11 @@ use Carbon\Carbon;
|
|||||||
use FireflyIII\Http\Requests\CategoryFormRequest;
|
use FireflyIII\Http\Requests\CategoryFormRequest;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
|
use FireflyIII\Support\CacheProperties;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
use Input;
|
||||||
|
use Navigation;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Session;
|
use Session;
|
||||||
use URL;
|
use URL;
|
||||||
@@ -139,6 +142,30 @@ class CategoryController extends Controller
|
|||||||
return view('categories.noCategory', compact('list', 'subTitle'));
|
return view('categories.noCategory', compact('list', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param CategoryRepositoryInterface $repository
|
||||||
|
* @param Category $category
|
||||||
|
*
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function showWithDate(CategoryRepositoryInterface $repository, Category $category, $date)
|
||||||
|
{
|
||||||
|
$carbon = new Carbon($date);
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
$start = Navigation::startOfPeriod($carbon, $range);
|
||||||
|
$end = Navigation::endOfPeriod($carbon, $range);
|
||||||
|
|
||||||
|
$hideCategory = true; // used in list.
|
||||||
|
$page = intval(Input::get('page'));
|
||||||
|
|
||||||
|
$set = $repository->getJournalsInRange($category, $page, $start, $end);
|
||||||
|
$count = $repository->countJournalsInRange($category, $start, $end);
|
||||||
|
$journals = new LengthAwarePaginator($set, $count, 50, $page);
|
||||||
|
$journals->setPath('categories/show/' . $category->id . '/' . $date);
|
||||||
|
|
||||||
|
return view('categories.show_with_date', compact('category', 'journals', 'hideCategory'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CategoryRepositoryInterface $repository
|
* @param CategoryRepositoryInterface $repository
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
@@ -156,7 +183,43 @@ class CategoryController extends Controller
|
|||||||
$journals = new LengthAwarePaginator($set, $count, 50, $page);
|
$journals = new LengthAwarePaginator($set, $count, 50, $page);
|
||||||
$journals->setPath('categories/show/' . $category->id);
|
$journals->setPath('categories/show/' . $category->id);
|
||||||
|
|
||||||
return view('categories.show', compact('category', 'journals', 'hideCategory', 'totalSum', 'periodSum'));
|
// list of ranges for list of periods:
|
||||||
|
|
||||||
|
// oldest transaction in category:
|
||||||
|
$start = $repository->getFirstActivityDate($category);
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
$start = Navigation::startOfPeriod($start, $range);
|
||||||
|
$end = Navigation::endOfX(new Carbon, $range);
|
||||||
|
$entries = new Collection;
|
||||||
|
|
||||||
|
// chart properties for cache:
|
||||||
|
$cache = new CacheProperties();
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('category-show');
|
||||||
|
$cache->addProperty($category->id);
|
||||||
|
if ($cache->has()) {
|
||||||
|
$entries = $cache->get();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
while ($end >= $start) {
|
||||||
|
$end = Navigation::startOfPeriod($end, $range);
|
||||||
|
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||||
|
|
||||||
|
// here do something.
|
||||||
|
$spent = $repository->spentInPeriod($category, $end, $currentEnd);
|
||||||
|
$earned = $repository->earnedInPeriod($category, $end, $currentEnd);
|
||||||
|
$dateStr = $end->format('Y-m-d');
|
||||||
|
$dateName = Navigation::periodShow($end, $range);
|
||||||
|
$entries->push([$dateStr, $dateName, $spent, $earned]);
|
||||||
|
|
||||||
|
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
$cache->store($entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('categories.show', compact('category', 'journals', 'entries', 'hideCategory', 'totalSum', 'periodSum'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -69,7 +69,6 @@ class CategoryController extends Controller
|
|||||||
$earned = $repository->earnedInPeriod($category, $start, $currentEnd);
|
$earned = $repository->earnedInPeriod($category, $start, $currentEnd);
|
||||||
$entries->push([clone $start, $spent, $earned]);
|
$entries->push([clone $start, $spent, $earned]);
|
||||||
$start = Navigation::addPeriod($start, $range, 0);
|
$start = Navigation::addPeriod($start, $range, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->generator->all($entries);
|
$data = $this->generator->all($entries);
|
||||||
|
@@ -244,6 +244,7 @@ Route::group(
|
|||||||
Route::get('/categories/edit/{category}', ['uses' => 'CategoryController@edit', 'as' => 'categories.edit']);
|
Route::get('/categories/edit/{category}', ['uses' => 'CategoryController@edit', 'as' => 'categories.edit']);
|
||||||
Route::get('/categories/delete/{category}', ['uses' => 'CategoryController@delete', 'as' => 'categories.delete']);
|
Route::get('/categories/delete/{category}', ['uses' => 'CategoryController@delete', 'as' => 'categories.delete']);
|
||||||
Route::get('/categories/show/{category}', ['uses' => 'CategoryController@show', 'as' => 'categories.show']);
|
Route::get('/categories/show/{category}', ['uses' => 'CategoryController@show', 'as' => 'categories.show']);
|
||||||
|
Route::get('/categories/show/{category}/{date}', ['uses' => 'CategoryController@showWithDate', 'as' => 'categories.show.date']);
|
||||||
Route::get('/categories/list/noCategory', ['uses' => 'CategoryController@noCategory', 'as' => 'categories.noCategory']);
|
Route::get('/categories/list/noCategory', ['uses' => 'CategoryController@noCategory', 'as' => 'categories.noCategory']);
|
||||||
Route::post('/categories/store', ['uses' => 'CategoryController@store', 'as' => 'categories.store']);
|
Route::post('/categories/store', ['uses' => 'CategoryController@store', 'as' => 'categories.store']);
|
||||||
Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']);
|
Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']);
|
||||||
|
@@ -309,7 +309,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
|||||||
$cache->addProperty($category->id);
|
$cache->addProperty($category->id);
|
||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty('spentInPeriod');
|
$cache->addProperty('earnedInPeriod');
|
||||||
|
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return $cache->get(); // @codeCoverageIgnore
|
return $cache->get(); // @codeCoverageIgnore
|
||||||
@@ -323,4 +323,36 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
|||||||
|
|
||||||
return $sum;
|
return $sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Category $category
|
||||||
|
* @param int $page
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
$offset = $page > 0 ? $page * 50 : 0;
|
||||||
|
|
||||||
|
return $category->transactionJournals()
|
||||||
|
->after($start)
|
||||||
|
->before($end)
|
||||||
|
->withRelevantData()->take(50)->offset($offset)
|
||||||
|
->orderBy('transaction_journals.date', 'DESC')
|
||||||
|
->orderBy('transaction_journals.order', 'ASC')
|
||||||
|
->orderBy('transaction_journals.id', 'DESC')
|
||||||
|
->get(
|
||||||
|
['transaction_journals.*']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Category $category
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function countJournalsInRange(Category $category, Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
return $category->transactionJournals()->before($end)->after($start)->count();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,13 @@ interface CategoryRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function countJournals(Category $category);
|
public function countJournals(Category $category);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Category $category
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function countJournalsInRange(Category $category, Carbon $start, Carbon $end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
@@ -57,6 +64,14 @@ interface CategoryRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function getJournals(Category $category, $page);
|
public function getJournals(Category $category, $page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Category $category
|
||||||
|
* @param int $page
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the sum of the journals in the category, optionally
|
* This method returns the sum of the journals in the category, optionally
|
||||||
* limited by a start or end date.
|
* limited by a start or end date.
|
||||||
|
@@ -106,13 +106,14 @@ class Navigation
|
|||||||
*
|
*
|
||||||
* @return Carbon
|
* @return Carbon
|
||||||
*/
|
*/
|
||||||
public function endOfX(Carbon $theCurrentEnd, $repeatFreq, Carbon $maxDate)
|
public function endOfX(Carbon $theCurrentEnd, $repeatFreq, Carbon $maxDate = null)
|
||||||
{
|
{
|
||||||
$functionMap = [
|
$functionMap = [
|
||||||
'daily' => 'endOfDay',
|
'daily' => 'endOfDay',
|
||||||
'week' => 'endOfWeek',
|
'week' => 'endOfWeek',
|
||||||
'weekly' => 'endOfWeek',
|
'weekly' => 'endOfWeek',
|
||||||
'month' => 'endOfMonth',
|
'month' => 'endOfMonth',
|
||||||
|
'1M' => 'endOfMonth',
|
||||||
'monthly' => 'endOfMonth',
|
'monthly' => 'endOfMonth',
|
||||||
'quarter' => 'lastOfQuarter',
|
'quarter' => 'lastOfQuarter',
|
||||||
'quarterly' => 'lastOfQuarter',
|
'quarterly' => 'lastOfQuarter',
|
||||||
@@ -128,7 +129,7 @@ class Navigation
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($currentEnd > $maxDate) {
|
if (!is_null($maxDate) && $currentEnd > $maxDate) {
|
||||||
return clone $maxDate;
|
return clone $maxDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +150,7 @@ class Navigation
|
|||||||
'week' => 'Week %W, %Y',
|
'week' => 'Week %W, %Y',
|
||||||
'weekly' => 'Week %W, %Y',
|
'weekly' => 'Week %W, %Y',
|
||||||
'quarter' => '%B %Y',
|
'quarter' => '%B %Y',
|
||||||
|
'1M' => '%B %Y',
|
||||||
'month' => '%B %Y',
|
'month' => '%B %Y',
|
||||||
'monthly' => '%B %Y',
|
'monthly' => '%B %Y',
|
||||||
'year' => '%Y',
|
'year' => '%Y',
|
||||||
@@ -224,6 +226,7 @@ class Navigation
|
|||||||
'week' => 'subWeeks',
|
'week' => 'subWeeks',
|
||||||
'weekly' => 'subWeeks',
|
'weekly' => 'subWeeks',
|
||||||
'month' => 'subMonths',
|
'month' => 'subMonths',
|
||||||
|
'1M' => 'subMonths',
|
||||||
'monthly' => 'subMonths',
|
'monthly' => 'subMonths',
|
||||||
'year' => 'subYears',
|
'year' => 'subYears',
|
||||||
'yearly' => 'subYears',
|
'yearly' => 'subYears',
|
||||||
|
@@ -38,7 +38,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12 col-md-12">
|
<div class="col-lg-8 col-md-8 col-sm-12 col-xs-12">
|
||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
@@ -49,6 +49,33 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-lg-4 col-md-4 col-sm-12 col-xs-12">
|
||||||
|
{% for entry in entries %}
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title"><a href="{{ route('categories.show.date',[category.id,entry[0]]) }}">{{ entry[1] }}</a>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body no-padding">
|
||||||
|
<table class="table table-hover">
|
||||||
|
{% if entry[2] != 0 %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="33%">{{ 'spent'|_ }}</td>
|
||||||
|
<td colspan="67%">{{ entry[2]|formatAmount }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if entry[3] != 0 %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="33%">{{ 'earned'|_ }}</td>
|
||||||
|
<td colspan="67%">{{ entry[3]|formatAmount }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
75
resources/twig/categories/show_with_date.twig
Normal file
75
resources/twig/categories/show_with_date.twig
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{% extends "./layout/default.twig" %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, category) }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'overview'|_ }} (month)</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
{% if Config.get('firefly.chart') == 'google' %}
|
||||||
|
<div id="month"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||||
|
<canvas id="month" style="width:100%;height:350px;"></canvas>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'overview'|_ }} (all)</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
{% if Config.get('firefly.chart') == 'google' %}
|
||||||
|
<div id="all"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||||
|
<canvas id="all" style="width:100%;height:350px;"></canvas>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||||
|
<p><a href="{{ route('categories.show',[category.id]) }}">Back to all periods</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'transactions'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body no-padding">
|
||||||
|
{% include 'list/journals' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
{% block scripts %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
var categoryID = {{ category.id }};
|
||||||
|
</script>
|
||||||
|
<!-- load the libraries and scripts necessary for Google Charts: -->
|
||||||
|
{% if Config.get('firefly.chart') == 'google' %}
|
||||||
|
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
|
||||||
|
<script type="text/javascript" src="js/gcharts.js"></script>
|
||||||
|
{% endif %}
|
||||||
|
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||||
|
<script type="text/javascript" src="js/Chart.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js/charts.js"></script>
|
||||||
|
{% endif %}
|
||||||
|
<script type="text/javascript" src="js/categories.js"></script>
|
||||||
|
|
||||||
|
{% endblock %}
|
@@ -19,7 +19,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
||||||
If you have forgotten your password already, please reset it using
|
If you have forgotten your password already, please reset it using
|
||||||
<a style="color:#337ab7" href="{{ address }}password/email">the password reset tool</a>.
|
<a style="color:#337ab7" href="{{ address }}/password/email">the password reset tool</a>.
|
||||||
</li>
|
</li>
|
||||||
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
||||||
There is a help-icon in the top right corner of each page. If you need help, click it!
|
There is a help-icon in the top right corner of each page. If you need help, click it!
|
||||||
|
@@ -12,7 +12,7 @@ Firefly III:
|
|||||||
{{ address }}
|
{{ address }}
|
||||||
|
|
||||||
Password reset:
|
Password reset:
|
||||||
{{ address }}password/email
|
{{ address }}/password/email
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
https://github.com/JC5/firefly-iii/wiki/First-use
|
https://github.com/JC5/firefly-iii/wiki/First-use
|
||||||
|
Reference in New Issue
Block a user