mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-16 19:04:36 +00:00
Compare commits
122 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
8b9607f9b5 | ||
|
af107ad5e8 | ||
|
8926d62165 | ||
|
45344ee347 | ||
|
b7dab817f2 | ||
|
2c966a1234 | ||
|
143ea69c0d | ||
|
8a02ead013 | ||
|
930d5ab941 | ||
|
e54a56d3a8 | ||
|
f5216c0d85 | ||
|
ebc77540b9 | ||
|
28d2583c10 | ||
|
b0988a7b00 | ||
|
2c4920db2d | ||
|
8321663815 | ||
|
ac0280d460 | ||
|
ba6f4268f0 | ||
|
0bd18f94ac | ||
|
66fb63661f | ||
|
d9b16beb0a | ||
|
6a01a9bdfd | ||
|
b81b34a706 | ||
|
3750a00b5f | ||
|
05ddcc169d | ||
|
f571a5f1bd | ||
|
48b786adea | ||
|
d691fa9b4d | ||
|
da50f9e419 | ||
|
103de5e18a | ||
|
dac6efd98b | ||
|
46aa7f81b2 | ||
|
0683c7cd67 | ||
|
50d7aa7b6a | ||
|
b781215d0a | ||
|
866bc2f3bd | ||
|
49d4705014 | ||
|
9163fcfccb | ||
|
7e10641461 | ||
|
cdc0e3cfd8 | ||
|
466e81d56a | ||
|
5953f691d1 | ||
|
e2790ca6c1 | ||
|
66dbd48b76 | ||
|
73cfbbd2ba | ||
|
38bc38bf26 | ||
|
e12d13c838 | ||
|
fcc3af6136 | ||
|
491298e1cb | ||
|
72b5895217 | ||
|
0a8f4017bd | ||
|
cb985f5897 | ||
|
968ec0853f | ||
|
0bde72d3df | ||
|
45293fbd42 | ||
|
72997065f0 | ||
|
a838dc163d | ||
|
3d15a4ca6d | ||
|
51c7d4fb1b | ||
|
fa586dba7e | ||
|
8ad40389f2 | ||
|
b3333cc2d3 | ||
|
3699a7ba9a | ||
|
204e521ba4 | ||
|
c9bab3e5c3 | ||
|
3d00e20238 | ||
|
c3958ed3c4 | ||
|
e5b88be5fa | ||
|
425552988a | ||
|
a81dd8abe5 | ||
|
bac8154a5b | ||
|
737d15fa0e | ||
|
5f2317af7f | ||
|
2bd1f783e5 | ||
|
d6c0c9f963 | ||
|
21b6ad7a41 | ||
|
a65d609fdc | ||
|
04e676b936 | ||
|
be8eaaffdf | ||
|
28c753523f | ||
|
7fbd0b2ffc | ||
|
7ffb48a87a | ||
|
d485270e1f | ||
|
5fd688b266 | ||
|
3716668e0c | ||
|
ae7fd18c34 | ||
|
4f59b1d32f | ||
|
90cb3279df | ||
|
cf0c7ef6b2 | ||
|
47c23781d9 | ||
|
e258c050f7 | ||
|
57801b2f34 | ||
|
710e9c9423 | ||
|
deefef83bd | ||
|
51e30aed66 | ||
|
8d109a3cfe | ||
|
3424e019b5 | ||
|
c6b4bceb67 | ||
|
afb4155015 | ||
|
8d99baf38a | ||
|
b91cb60328 | ||
|
c0d62237fc | ||
|
223ea80860 | ||
|
5a77bef494 | ||
|
80c0efe821 | ||
|
8044d89557 | ||
|
4f0ed97410 | ||
|
af7952f204 | ||
|
d8dcae856b | ||
|
7296796ed9 | ||
|
a2c2bb4948 | ||
|
72ebfdc20e | ||
|
16b95ea78a | ||
|
c04f08dfd8 | ||
|
a30793e818 | ||
|
e39e1eaf21 | ||
|
ab22d2cbaa | ||
|
96ddbe7227 | ||
|
4d09235aef | ||
|
136b8975e3 | ||
|
e21b1eca17 | ||
|
244b90b1d4 |
@@ -1,6 +1,6 @@
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_KEY=SomeRandomString
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
|
@@ -82,7 +82,7 @@ If you're still interested please read [the installation guide](https://github.c
|
||||
and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)**.
|
||||
|
||||
If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/).
|
||||
This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site.
|
||||
This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site. Accounts on the demo sites will stop working after one week.
|
||||
|
||||
## Credits
|
||||
|
||||
|
@@ -40,4 +40,13 @@ interface AccountChartGenerator
|
||||
* @return array
|
||||
*/
|
||||
public function single(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end);
|
||||
}
|
||||
|
@@ -32,6 +32,69 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator
|
||||
return $this->frontpage($accounts, $start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [], 'datasets' => [[
|
||||
'label' => trans('firefly.spent'),
|
||||
'data' => []]]];
|
||||
|
||||
bcscale(2);
|
||||
$start->subDay();
|
||||
$ids = $this->getIdsFromCollection($accounts);
|
||||
$startBalances = Steam::balancesById($ids, $start);
|
||||
$endBalances = Steam::balancesById($ids, $end);
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($startBalances, $endBalances) {
|
||||
$id = $account->id;
|
||||
$startBalance = $this->isInArray($startBalances, $id);
|
||||
$endBalance = $this->isInArray($endBalances, $id);
|
||||
$diff = bcsub($endBalance, $startBalance);
|
||||
$account->difference = round($diff, 2);
|
||||
}
|
||||
);
|
||||
|
||||
$accounts = $accounts->sortByDesc(
|
||||
function (Account $account) {
|
||||
return $account->difference;
|
||||
}
|
||||
);
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->difference > 0) {
|
||||
$data['labels'][] = $account->name;
|
||||
$data['datasets'][0]['data'][] = $account->difference;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $array
|
||||
* @param $entryId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function isInArray($array, $entryId)
|
||||
{
|
||||
if (isset($array[$entryId])) {
|
||||
return $array[$entryId];
|
||||
}
|
||||
|
||||
return '0';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
@@ -112,4 +175,20 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getIdsFromCollection(Collection $collection)
|
||||
{
|
||||
$ids = [];
|
||||
foreach ($collection as $entry) {
|
||||
$ids[] = $entry->id;
|
||||
}
|
||||
|
||||
return array_unique($ids);
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
use Steam;
|
||||
|
||||
|
||||
/**
|
||||
* Class GoogleAccountChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Account
|
||||
*/
|
||||
class GoogleAccountChartGenerator implements AccountChartGenerator
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// make chart (original code):
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
$index = 1;
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty($index);
|
||||
$index++;
|
||||
}
|
||||
$current = clone $start;
|
||||
$current->subDay();
|
||||
$today = Carbon::now();
|
||||
while ($end >= $current) {
|
||||
$row = [clone $current];
|
||||
$certain = $current < $today;
|
||||
foreach ($accounts as $account) {
|
||||
$row[] = Steam::balance($account, $current);
|
||||
$row[] = $certain;
|
||||
}
|
||||
$chart->addRowArray($row);
|
||||
$current->addDay();
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
return $this->all($accounts, $start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function single(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$current = clone $start;
|
||||
$today = new Carbon;
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty(1);
|
||||
|
||||
while ($end >= $current) {
|
||||
$certain = $current < $today;
|
||||
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
|
||||
$current->addDay();
|
||||
}
|
||||
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
@@ -33,7 +33,7 @@ class ChartJsBillChartGenerator implements BillChartGenerator
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($paid as $entry) { // loop paid and create single entry:
|
||||
$paidDescriptions[] = $entry->description;
|
||||
$paidAmount = bcadd($paidAmount, $entry->amount);
|
||||
$paidAmount = bcadd($paidAmount, $entry->amount_positive);
|
||||
}
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) { // loop unpaid:
|
||||
@@ -91,7 +91,7 @@ class ChartJsBillChartGenerator implements BillChartGenerator
|
||||
$data['labels'][] = $entry->date->formatLocalized($format);
|
||||
$minAmount[] = round($bill->amount_min, 2);
|
||||
$maxAmount[] = round($bill->amount_max, 2);
|
||||
$actualAmount[] = round($entry->amount, 2);
|
||||
$actualAmount[] = round(($entry->amount * -1), 2);
|
||||
}
|
||||
|
||||
$data['datasets'][] = [
|
||||
|
@@ -1,94 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Bill;
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class GoogleBillChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Bill
|
||||
*/
|
||||
class GoogleBillChartGenerator implements BillChartGenerator
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $paid
|
||||
* @param Collection $unpaid
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $paid, Collection $unpaid)
|
||||
{
|
||||
// loop paid and create single entry:
|
||||
$paidDescriptions = [];
|
||||
$paidAmount = 0;
|
||||
$unpaidDescriptions = [];
|
||||
$unpaidAmount = 0;
|
||||
|
||||
bcscale(2);
|
||||
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($paid as $entry) {
|
||||
|
||||
$paidDescriptions[] = $entry->description;
|
||||
$paidAmount = bcadd($paidAmount, $entry->amount);
|
||||
}
|
||||
|
||||
// loop unpaid:
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
|
||||
$amount = bcdiv(bcadd($entry[0]->amount_max, $entry[0]->amount_min), 2);
|
||||
$unpaidDescriptions[] = $description;
|
||||
$unpaidAmount = bcadd($unpaidAmount, $amount);
|
||||
unset($amount, $description);
|
||||
}
|
||||
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.name'), 'string');
|
||||
$chart->addColumn(trans('firefly.amount'), 'number');
|
||||
|
||||
$chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount);
|
||||
$chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount);
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function single(Bill $bill, Collection $entries)
|
||||
{
|
||||
// make chart:
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.date'), 'date');
|
||||
$chart->addColumn(trans('firefly.maxAmount'), 'number');
|
||||
$chart->addColumn(trans('firefly.minAmount'), 'number');
|
||||
$chart->addColumn(trans('firefly.billEntry'), 'number');
|
||||
|
||||
/** @var TransactionJournal $result */
|
||||
foreach ($entries as $result) {
|
||||
$chart->addRow(
|
||||
clone $result->date,
|
||||
round($bill->amount_max, 2),
|
||||
round($bill->amount_min, 2),
|
||||
round($result->amount, 2)
|
||||
);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
@@ -1,102 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Budget;
|
||||
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class GoogleBudgetChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Budget
|
||||
*/
|
||||
class GoogleBudgetChartGenerator implements BudgetChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function budget(Collection $entries)
|
||||
{
|
||||
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRow($entry[0], $entry[1]);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function budgetLimit(Collection $entries)
|
||||
{
|
||||
return $this->budget($entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.budget'), 'string');
|
||||
$chart->addColumn(trans('firefly.left'), 'number');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
$chart->addColumn(trans('firefly.overspent'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
|
||||
$chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $budgets, Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
// add columns:
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
foreach ($budgets as $budget) {
|
||||
$chart->addColumn($budget->name, 'number');
|
||||
}
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
|
||||
$chart->addRowArray($entry);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
@@ -31,7 +31,7 @@ interface CategoryChartGenerator
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function month(Collection $entries);
|
||||
public function period(Collection $entries);
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,5 +40,13 @@ interface CategoryChartGenerator
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $categories, Collection $entries);
|
||||
public function spentInYear(Collection $categories, Collection $entries);
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function earnedInYear(Collection $categories, Collection $entries);
|
||||
}
|
||||
|
@@ -17,31 +17,35 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
* @param string $dateFormat
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $entries, $dateFormat = 'month')
|
||||
public function all(Collection $entries)
|
||||
{
|
||||
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.' . $dateFormat . '.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'count' => 2,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => trans('firefly.spent'),
|
||||
'data' => []
|
||||
],
|
||||
[
|
||||
'label' => trans('firefly.earned'),
|
||||
'data' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$data['labels'][] = $entry[0]->formatLocalized($format);
|
||||
$data['datasets'][0]['data'][] = round($entry[1], 2);
|
||||
$data['labels'][] = $entry[1];
|
||||
$spent = round($entry[2], 2);
|
||||
$earned = round($entry[3], 2);
|
||||
|
||||
$data['datasets'][0]['data'][] = $spent == 0 ? null : $spent * -1;
|
||||
$data['datasets'][1]['data'][] = $earned == 0 ? null : $earned;
|
||||
}
|
||||
|
||||
return $data;
|
||||
@@ -67,7 +71,7 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry['sum'] != 0) {
|
||||
$data['labels'][] = $entry['name'];
|
||||
$data['datasets'][0]['data'][] = round($entry['sum'], 2);
|
||||
$data['datasets'][0]['data'][] = round(($entry['sum'] * -1), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,9 +85,9 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function month(Collection $entries)
|
||||
public function period(Collection $entries)
|
||||
{
|
||||
return $this->all($entries, 'monthAndDay');
|
||||
return $this->all($entries);
|
||||
|
||||
}
|
||||
|
||||
@@ -93,7 +97,41 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $categories, Collection $entries)
|
||||
public function spentInYear(Collection $categories, Collection $entries)
|
||||
{
|
||||
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.month.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 0,
|
||||
'labels' => [],
|
||||
'datasets' => [],
|
||||
];
|
||||
|
||||
foreach ($categories as $category) {
|
||||
$data['labels'][] = $category->name;
|
||||
}
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$date = $entry[0]->formatLocalized($format);
|
||||
array_shift($entry);
|
||||
$data['count']++;
|
||||
$data['datasets'][] = ['label' => $date, 'data' => $entry];
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function earnedInYear(Collection $categories, Collection $entries)
|
||||
{
|
||||
|
||||
// language:
|
||||
|
@@ -1,106 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Category;
|
||||
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class GoogleCategoryChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Category
|
||||
*/
|
||||
class GoogleCategoryChartGenerator implements CategoryChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRow($entry[0], $entry[1]);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.category'), 'string');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$sum = $entry['sum'];
|
||||
if ($sum != 0) {
|
||||
$chart->addRow($entry['name'], $sum);
|
||||
}
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function month(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRow($entry[0], $entry[1]);
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $categories, Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
foreach ($categories as $category) {
|
||||
$chart->addColumn($category->name, 'number');
|
||||
}
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRowArray($entry);
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@ use Preferences;
|
||||
|
||||
|
||||
/**
|
||||
* Class GooglePiggyBankChartGenerator
|
||||
* Class ChartJsPiggyBankChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\PiggyBank
|
||||
*/
|
||||
|
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\PiggyBank;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Class GooglePiggyBankChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\PiggyBank
|
||||
*/
|
||||
class GooglePiggyBankChartGenerator implements PiggyBankChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function history(Collection $set)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.date'), 'date');
|
||||
$chart->addColumn(trans('firefly.balance'), 'number');
|
||||
|
||||
$sum = '0';
|
||||
bcscale(2);
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$sum = bcadd($sum, $entry->sum);
|
||||
$chart->addRow(new Carbon($entry->date), $sum);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
@@ -7,7 +7,7 @@ use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class GoogleReportChartGenerator
|
||||
* Class ChartJsReportChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Report
|
||||
*/
|
||||
@@ -74,9 +74,9 @@ class ChartJsReportChartGenerator implements ReportChartGenerator
|
||||
],
|
||||
];
|
||||
$data['datasets'][0]['data'][] = round($income, 2);
|
||||
$data['datasets'][1]['data'][] = round($expense, 2);
|
||||
$data['datasets'][1]['data'][] = round( $expense, 2);
|
||||
$data['datasets'][0]['data'][] = round(($income / $count), 2);
|
||||
$data['datasets'][1]['data'][] = round(($expense / $count), 2);
|
||||
$data['datasets'][1]['data'][] = round(( $expense / $count), 2);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Report;
|
||||
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class GoogleReportChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Report
|
||||
*/
|
||||
class GoogleReportChartGenerator implements ReportChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOut(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
$chart->addColumn(trans('firefly.income'), 'number');
|
||||
$chart->addColumn(trans('firefly.expenses'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRowArray($entry);
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $income
|
||||
* @param string $expense
|
||||
* @param int $count
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOutSummarized($income, $expense, $count)
|
||||
{
|
||||
$chart = new GChart;
|
||||
|
||||
$chart->addColumn(trans('firefly.summary'), 'string');
|
||||
$chart->addColumn(trans('firefly.income'), 'number');
|
||||
$chart->addColumn(trans('firefly.expenses'), 'number');
|
||||
$chart->addRow(trans('firefly.sum'), $income, $expense);
|
||||
$chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count));
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
@@ -53,7 +53,7 @@ class ConnectJournalToPiggyBank
|
||||
}
|
||||
bcscale(2);
|
||||
|
||||
$amount = $journal->actual_amount;
|
||||
$amount = $journal->amount_positive;
|
||||
// if piggy account matches source account, the amount is positive
|
||||
if ($piggyBank->account_id == $journal->source_account->id) {
|
||||
$amount = $amount * -1;
|
||||
|
@@ -34,7 +34,8 @@ class Category
|
||||
*/
|
||||
public function addCategory(CategoryModel $category)
|
||||
{
|
||||
if ($category->spent > 0) {
|
||||
// spent is minus zero for an expense report:
|
||||
if ($category->spent < 0) {
|
||||
$this->categories->push($category);
|
||||
}
|
||||
}
|
||||
|
@@ -33,11 +33,10 @@ class Expense
|
||||
*/
|
||||
public function addOrCreateExpense(TransactionJournal $entry)
|
||||
{
|
||||
|
||||
$accountId = $entry->account_id;
|
||||
if (!$this->expenses->has($accountId)) {
|
||||
$newObject = new stdClass;
|
||||
$newObject->amount = strval(round($entry->amount, 2));
|
||||
$newObject->amount = strval(round($entry->amount_positive, 2));
|
||||
$newObject->name = $entry->name;
|
||||
$newObject->count = 1;
|
||||
$newObject->id = $accountId;
|
||||
@@ -45,7 +44,7 @@ class Expense
|
||||
} else {
|
||||
bcscale(2);
|
||||
$existing = $this->expenses->get($accountId);
|
||||
$existing->amount = bcadd($existing->amount, $entry->amount);
|
||||
$existing->amount = bcadd($existing->amount, $entry->amount_positive);
|
||||
$existing->count++;
|
||||
$this->expenses->put($accountId, $existing);
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ class Income
|
||||
$accountId = $entry->account_id;
|
||||
if (!$this->incomes->has($accountId)) {
|
||||
$newObject = new stdClass;
|
||||
$newObject->amount = strval(round($entry->amount, 2));
|
||||
$newObject->amount = strval(round($entry->amount_positive, 2));
|
||||
$newObject->name = $entry->name;
|
||||
$newObject->count = 1;
|
||||
$newObject->id = $accountId;
|
||||
@@ -46,7 +46,7 @@ class Income
|
||||
} else {
|
||||
bcscale(2);
|
||||
$existing = $this->incomes->get($accountId);
|
||||
$existing->amount = bcadd($existing->amount, $entry->amount);
|
||||
$existing->amount = bcadd($existing->amount, $entry->amount_positive);
|
||||
$existing->count++;
|
||||
$this->incomes->put($accountId, $existing);
|
||||
}
|
||||
|
@@ -3,6 +3,9 @@
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use InvalidArgumentException;
|
||||
use Log;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
@@ -19,8 +22,16 @@ class Date extends BasicConverter implements ConverterInterface
|
||||
public function convert()
|
||||
{
|
||||
$format = Session::get('csv-date-format');
|
||||
try {
|
||||
$date = Carbon::createFromFormat($format, $this->value);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::error('Date conversion error: ' . $e->getMessage() . '. Value was "' . $this->value . '", format was "' . $format . '".');
|
||||
|
||||
$message = trans('firefly.csv_date_parse_error', ['format' => $format, 'value' => $this->value]);
|
||||
|
||||
throw new FireflyException($message);
|
||||
}
|
||||
|
||||
$date = Carbon::createFromFormat($format, $this->value);
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
@@ -124,7 +124,7 @@ class Importer
|
||||
*/
|
||||
protected function parseRow($index)
|
||||
{
|
||||
return (($this->data->hasHeaders() && $index > 1) || !$this->data->hasHeaders());
|
||||
return (($this->data->hasHeaders() && $index >= 1) || !$this->data->hasHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -133,7 +133,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
$line->setBudget($budget);
|
||||
|
||||
// get budget amount for current period:
|
||||
$rep = $repository->getCurrentRepetition($budget, $start);
|
||||
$rep = $repository->getCurrentRepetition($budget, $start, $end);
|
||||
$line->setRepetition($rep);
|
||||
|
||||
// loop accounts:
|
||||
@@ -263,7 +263,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
|
||||
// no repetition(s) for this budget:
|
||||
if ($repetitions->count() == 0) {
|
||||
$spent = $repository->spentInPeriodCorrected($budget, $start, $end, $shared);
|
||||
$spent = $repository->balanceInPeriod($budget, $start, $end, $shared);
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setBudget($budget);
|
||||
$budgetLine->setOverspent($spent);
|
||||
@@ -278,7 +278,8 @@ class ReportHelper implements ReportHelperInterface
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setBudget($budget);
|
||||
$budgetLine->setRepetition($repetition);
|
||||
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, $shared);
|
||||
$expenses = $repository->balanceInPeriod($budget, $repetition->startdate, $repetition->enddate, $shared);
|
||||
$expenses = $expenses * -1;
|
||||
$left = $expenses < $repetition->amount ? bcsub($repetition->amount, $expenses) : 0;
|
||||
$spent = $expenses > $repetition->amount ? 0 : $expenses;
|
||||
$overspent = $expenses > $repetition->amount ? bcsub($expenses, $repetition->amount) : 0;
|
||||
@@ -327,7 +328,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
$repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface');
|
||||
$set = $repository->getCategories();
|
||||
foreach ($set as $category) {
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $end, $shared);
|
||||
$spent = $repository->balanceInPeriod($category, $start, $end, $shared);
|
||||
$category->spent = $spent;
|
||||
$object->addCategory($category);
|
||||
$object->addTotal($spent);
|
||||
@@ -350,7 +351,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
$object = new Expense;
|
||||
$set = $this->query->expenseInPeriodCorrected($start, $end, $shared);
|
||||
foreach ($set as $entry) {
|
||||
$object->addToTotal($entry->amount);
|
||||
$object->addToTotal($entry->amount_positive);
|
||||
$object->addOrCreateExpense($entry);
|
||||
}
|
||||
|
||||
@@ -371,7 +372,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
$object = new Income;
|
||||
$set = $this->query->incomeInPeriodCorrected($start, $end, $shared);
|
||||
foreach ($set as $entry) {
|
||||
$object->addToTotal($entry->amount);
|
||||
$object->addToTotal($entry->amount_positive);
|
||||
$object->addOrCreateIncome($entry);
|
||||
}
|
||||
|
||||
|
@@ -50,6 +50,7 @@ class ReportQuery implements ReportQueryInterface
|
||||
function (Builder $q) { // and transfers from a shared account.
|
||||
$q->where('transaction_types.type', 'Transfer');
|
||||
$q->where('acm_to.data', '=', '"sharedAsset"');
|
||||
$q->where('acm_from.data', '!=', '"sharedAsset"');
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -69,15 +70,6 @@ class ReportQuery implements ReportQueryInterface
|
||||
}
|
||||
}
|
||||
);
|
||||
$data = $data->filter(
|
||||
function (TransactionJournal $journal) {
|
||||
if ($journal->amount != 0) {
|
||||
return $journal;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
@@ -164,6 +156,7 @@ class ReportQuery implements ReportQueryInterface
|
||||
function (Builder $q) {
|
||||
$q->where('transaction_types.type', 'Transfer');
|
||||
$q->where('acm_from.data', '=', '"sharedAsset"');
|
||||
$q->where('acm_to.data','!=','"sharedAsset"');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Input;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
@@ -136,24 +137,27 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function index(BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$budgets = $repository->getActiveBudgets();
|
||||
$inactive = $repository->getInactiveBudgets();
|
||||
$spent = '0';
|
||||
$budgeted = '0';
|
||||
$budgets = $repository->getActiveBudgets();
|
||||
$inactive = $repository->getInactiveBudgets();
|
||||
$spent = '0';
|
||||
$budgeted = '0';
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
|
||||
$budgetIncomeTotal = Preferences::get($key, 1000)->data;
|
||||
$period = Navigation::periodShow($start, $range);
|
||||
bcscale(2);
|
||||
/**
|
||||
* Do some cleanup:
|
||||
*/
|
||||
$repository->cleanupBudgets();
|
||||
|
||||
|
||||
// loop the budgets:
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
$date = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$budget->spent = $repository->spentInPeriodCorrected($budget, $date, $end);
|
||||
$budget->currentRep = $repository->getCurrentRepetition($budget, $date);
|
||||
$budget->spent = $repository->balanceInPeriod($budget, $start, $end);
|
||||
$budget->currentRep = $repository->getCurrentRepetition($budget, $start, $end);
|
||||
if ($budget->currentRep) {
|
||||
$budgeted = bcadd($budgeted, $budget->currentRep->amount);
|
||||
}
|
||||
@@ -161,13 +165,12 @@ class BudgetController extends Controller
|
||||
|
||||
}
|
||||
|
||||
$dateAsString = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
|
||||
$budgetIncomeTotal = Preferences::get('budgetIncomeTotal' . $dateAsString, 1000)->data;
|
||||
$budgetMaximum = Preferences::get('budgetMaximum', 1000)->data;
|
||||
$defaultCurrency = Amount::getDefaultCurrency();
|
||||
|
||||
$budgetMaximum = Preferences::get('budgetMaximum', 1000)->data;
|
||||
$defaultCurrency = Amount::getDefaultCurrency();
|
||||
|
||||
return view(
|
||||
'budgets.index', compact('budgetMaximum', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted')
|
||||
'budgets.index', compact('budgetMaximum','period', 'range', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -178,8 +181,9 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function noBudget(BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->startOfMonth());
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$list = $repository->getWithoutBudget($start, $end);
|
||||
$subTitle = trans(
|
||||
'firefly.without_budget_between',
|
||||
@@ -194,9 +198,12 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function postUpdateIncome()
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
|
||||
|
||||
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
|
||||
Preferences::set('budgetIncomeTotal' . $date, intval(Input::get('amount')));
|
||||
Preferences::set($key, intval(Input::get('amount')));
|
||||
Preferences::mark();
|
||||
|
||||
return redirect(route('budgets.index'));
|
||||
@@ -297,8 +304,11 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function updateIncome()
|
||||
{
|
||||
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
|
||||
$amount = Preferences::get('budgetIncomeTotal' . $date, 1000);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
|
||||
$amount = Preferences::get($key, 1000);
|
||||
|
||||
return view('budgets.income', compact('amount'));
|
||||
}
|
||||
|
@@ -5,8 +5,11 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Http\Requests\CategoryFormRequest;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Input;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Session;
|
||||
use URL;
|
||||
@@ -139,6 +142,31 @@ class CategoryController extends Controller
|
||||
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);
|
||||
$subTitle = $category->name;
|
||||
|
||||
$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', 'subTitle', 'carbon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
* @param Category $category
|
||||
@@ -151,10 +179,47 @@ class CategoryController extends Controller
|
||||
$page = intval(Input::get('page'));
|
||||
$set = $repository->getJournals($category, $page);
|
||||
$count = $repository->countJournals($category);
|
||||
$subTitle = $category->name;
|
||||
$journals = new LengthAwarePaginator($set, $count, 50, $page);
|
||||
$journals->setPath('categories/show/' . $category->id);
|
||||
|
||||
return view('categories.show', compact('category', 'journals', 'hideCategory'));
|
||||
// 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', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -79,6 +79,36 @@ class AccountController extends Controller
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the balances for all the user's expense accounts.
|
||||
*
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function expenseAccounts(AccountRepositoryInterface $repository)
|
||||
{
|
||||
$start = clone Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = clone Session::get('end', Carbon::now()->endOfMonth());
|
||||
$accounts = $repository->getAccounts(['Expense account', 'Beneficiary account']);
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expenseAccounts');
|
||||
$cache->addProperty('accounts');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$data = $this->generator->expenseAccounts($accounts, $start, $end);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the balances for all the user's frontpage accounts.
|
||||
*
|
||||
|
@@ -68,7 +68,7 @@ class BudgetController extends Controller
|
||||
$end->subDay();
|
||||
$chartDate = clone $end;
|
||||
$chartDate->startOfMonth();
|
||||
$spent = $repository->spentInPeriodCorrected($budget, $first, $end);
|
||||
$spent = $repository->balanceInPeriod($budget, $first, $end) * -1;
|
||||
$entries->push([$chartDate, $spent]);
|
||||
$first = Navigation::addPeriod($first, $range, 0);
|
||||
}
|
||||
@@ -156,13 +156,13 @@ class BudgetController extends Controller
|
||||
foreach ($budgets as $budget) {
|
||||
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
|
||||
if ($repetitions->count() == 0) {
|
||||
$expenses = $repository->spentInPeriodCorrected($budget, $start, $end, true);
|
||||
$expenses = $repository->balanceInPeriod($budget, $start, $end, true) * -1;
|
||||
$allEntries->push([$budget->name, 0, 0, $expenses, 0, 0]);
|
||||
continue;
|
||||
}
|
||||
/** @var LimitRepetition $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true);
|
||||
$expenses = $repository->balanceInPeriod($budget, $repetition->startdate, $repetition->enddate, true) * -1;
|
||||
// $left can be less than zero.
|
||||
// $overspent can be more than zero ( = overspending)
|
||||
|
||||
@@ -199,10 +199,11 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function year(BudgetRepositoryInterface $repository, $year, $shared = false)
|
||||
{
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$budgets = $repository->getBudgets();
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$allBudgets = $repository->getBudgets();
|
||||
$budgets = new Collection;
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
@@ -214,6 +215,15 @@ class BudgetController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// filter empty budgets:
|
||||
|
||||
foreach ($allBudgets as $budget) {
|
||||
$spent = $repository->balanceInPeriod($budget, $start, $end, $shared);
|
||||
if ($spent != 0) {
|
||||
$budgets->push($budget);
|
||||
}
|
||||
}
|
||||
|
||||
$entries = new Collection;
|
||||
|
||||
while ($start < $end) {
|
||||
@@ -224,14 +234,14 @@ class BudgetController extends Controller
|
||||
|
||||
// each budget, fill the row:
|
||||
foreach ($budgets as $budget) {
|
||||
$spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared);
|
||||
$row[] = $spent;
|
||||
$spent = $repository->balanceInPeriod($budget, $start, $month, $shared);
|
||||
$row[] = $spent * -1;
|
||||
}
|
||||
$entries->push($row);
|
||||
$start->endOfMonth()->addDay();
|
||||
}
|
||||
|
||||
$data = $this->generator->year($budgets, $entries);
|
||||
$data = $this->generator->year($allBudgets, $entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
@@ -46,11 +46,10 @@ class CategoryController extends Controller
|
||||
public function all(CategoryRepositoryInterface $repository, Category $category)
|
||||
{
|
||||
// oldest transaction in category:
|
||||
$start = $repository->getFirstActivityDate($category);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = new Carbon;
|
||||
|
||||
$start = $repository->getFirstActivityDate($category);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = new Carbon;
|
||||
$entries = new Collection;
|
||||
|
||||
|
||||
@@ -66,11 +65,16 @@ class CategoryController extends Controller
|
||||
|
||||
while ($start <= $end) {
|
||||
$currentEnd = Navigation::endOfPeriod($start, $range);
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
|
||||
$entries->push([clone $start, $spent]);
|
||||
$spent = $repository->spentInPeriod($category, $start, $currentEnd);
|
||||
$earned = $repository->earnedInPeriod($category, $start, $currentEnd);
|
||||
$date = Navigation::periodShow($start, $range);
|
||||
$entries->push([clone $start, $date, $spent, $earned]);
|
||||
$start = Navigation::addPeriod($start, $range, 0);
|
||||
|
||||
}
|
||||
// limit the set to the last 40:
|
||||
$entries = $entries->reverse();
|
||||
$entries = $entries->slice(0, 48);
|
||||
$entries = $entries->reverse();
|
||||
|
||||
$data = $this->generator->all($entries);
|
||||
$cache->store($data);
|
||||
@@ -112,7 +116,7 @@ class CategoryController extends Controller
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($left['sum'] < $right['sum']) ? 1 : -1;
|
||||
return ($left['sum'] < $right['sum']) ? -1 : 1;
|
||||
}
|
||||
);
|
||||
$set = new Collection($array);
|
||||
@@ -128,7 +132,7 @@ class CategoryController extends Controller
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function month(CategoryRepositoryInterface $repository, Category $category)
|
||||
public function currentPeriod(CategoryRepositoryInterface $repository, Category $category)
|
||||
{
|
||||
$start = clone Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
@@ -139,7 +143,7 @@ class CategoryController extends Controller
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($category->id);
|
||||
$cache->addProperty('category');
|
||||
$cache->addProperty('month');
|
||||
$cache->addProperty('currentPeriod');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
@@ -147,13 +151,57 @@ class CategoryController extends Controller
|
||||
|
||||
|
||||
while ($start <= $end) {
|
||||
$spent = $repository->spentOnDaySumCorrected($category, $start);
|
||||
|
||||
$entries->push([clone $start, $spent]);
|
||||
$spent = $repository->spentOnDaySumCorrected($category, $start);
|
||||
$earned = $repository->earnedOnDaySumCorrected($category, $start);
|
||||
$date = Navigation::periodShow($start, '1D');
|
||||
$entries->push([clone $start, $date, $spent, $earned]);
|
||||
$start->addDay();
|
||||
}
|
||||
|
||||
$data = $this->generator->month($entries);
|
||||
$data = $this->generator->period($entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
* @param Category $category
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function specificPeriod(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);
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($category->id);
|
||||
$cache->addProperty('category');
|
||||
$cache->addProperty('specificPeriod');
|
||||
$cache->addProperty($date);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$entries = new Collection;
|
||||
|
||||
|
||||
while ($start <= $end) {
|
||||
$spent = $repository->spentOnDaySumCorrected($category, $start);
|
||||
$earned = $repository->earnedOnDaySumCorrected($category, $start);
|
||||
$theDate = Navigation::periodShow($start, '1D');
|
||||
$entries->push([clone $start, $theDate, $spent, $earned]);
|
||||
$start->addDay();
|
||||
}
|
||||
|
||||
$data = $this->generator->period($entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
@@ -170,7 +218,7 @@ class CategoryController extends Controller
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function year(CategoryRepositoryInterface $repository, $year, $shared = false)
|
||||
public function spentInYear(CategoryRepositoryInterface $repository, $year, $shared = false)
|
||||
{
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
@@ -179,14 +227,24 @@ class CategoryController extends Controller
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category');
|
||||
$cache->addProperty('year');
|
||||
$cache->addProperty('spent-in-year');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$categories = $repository->getCategories();
|
||||
$entries = new Collection;
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$allCategories = $repository->getCategories();
|
||||
$entries = new Collection;
|
||||
$categories = $allCategories->filter(
|
||||
function (Category $category) use ($repository, $start, $end, $shared) {
|
||||
$spent = $repository->balanceInPeriod($category, $start, $end, $shared);
|
||||
if ($spent < 0) {
|
||||
return $category;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
while ($start < $end) {
|
||||
$month = clone $start; // month is the current end of the period
|
||||
@@ -194,15 +252,76 @@ class CategoryController extends Controller
|
||||
$row = [clone $start]; // make a row:
|
||||
|
||||
foreach ($categories as $category) { // each budget, fill the row
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
|
||||
$row[] = $spent;
|
||||
$spent = $repository->balanceInPeriod($category, $start, $month, $shared);
|
||||
if ($spent < 0) {
|
||||
$row[] = $spent * -1;
|
||||
} else {
|
||||
$row[] = 0;
|
||||
}
|
||||
}
|
||||
$entries->push($row);
|
||||
|
||||
$start->addMonth();
|
||||
}
|
||||
$data = $this->generator->spentInYear($categories, $entries);
|
||||
$cache->store($data);
|
||||
|
||||
$data = $this->generator->year($categories, $entries);
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* This chart will only show income.
|
||||
*
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
* @param $year
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function earnedInYear(CategoryRepositoryInterface $repository, $year, $shared = false)
|
||||
{
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
|
||||
$cache = new CacheProperties; // chart properties for cache:
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category');
|
||||
$cache->addProperty('earned-in-year');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$allCategories = $repository->getCategories();
|
||||
$allEntries = new Collection;
|
||||
$categories = $allCategories->filter(
|
||||
function (Category $category) use ($repository, $start, $end, $shared) {
|
||||
$spent = $repository->balanceInPeriod($category, $start, $end, $shared);
|
||||
if ($spent > 0) {
|
||||
return $category;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
while ($start < $end) {
|
||||
$month = clone $start; // month is the current end of the period
|
||||
$month->endOfMonth();
|
||||
$row = [clone $start]; // make a row:
|
||||
|
||||
foreach ($categories as $category) { // each budget, fill the row
|
||||
$spent = $repository->balanceInPeriod($category, $start, $month, $shared);
|
||||
if ($spent > 0) {
|
||||
$row[] = $spent;
|
||||
} else {
|
||||
$row[] = 0;
|
||||
}
|
||||
}
|
||||
$allEntries->push($row);
|
||||
$start->addMonth();
|
||||
}
|
||||
$data = $this->generator->earnedInYear($categories, $allEntries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
@@ -9,6 +9,7 @@ use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Response;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class ReportController
|
||||
@@ -62,8 +63,8 @@ class ReportController extends Controller
|
||||
$month = clone $start;
|
||||
$month->endOfMonth();
|
||||
// total income and total expenses:
|
||||
$incomeSum = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount');
|
||||
$expenseSum = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount');
|
||||
$incomeSum = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount_positive');
|
||||
$expenseSum = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount_positive');
|
||||
|
||||
$entries->push([clone $start, $incomeSum, $expenseSum]);
|
||||
$start->addMonth();
|
||||
@@ -110,8 +111,18 @@ class ReportController extends Controller
|
||||
$month = clone $start;
|
||||
$month->endOfMonth();
|
||||
// total income and total expenses:
|
||||
$income = bcadd($income, $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
|
||||
$expense = bcadd($expense, $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
|
||||
$currentIncome = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount_positive');
|
||||
$currentExpense = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount_positive');
|
||||
|
||||
Log::debug('Date ['.$month->format('M Y').']: income = ['.$income.' + '.$currentIncome.'], out = ['.$expense.' + '.$currentExpense.']');
|
||||
|
||||
$income = bcadd($income, $currentIncome);
|
||||
$expense = bcadd($expense, $currentExpense);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$count++;
|
||||
$start->addMonth();
|
||||
}
|
||||
|
@@ -25,32 +25,42 @@ class CronController extends Controller
|
||||
|
||||
if (strlen(env('SENDGRID_USERNAME')) > 0 && strlen(env('SENDGRID_PASSWORD')) > 0) {
|
||||
|
||||
$URL = 'https://api.sendgrid.com/api/bounces.get.json';
|
||||
$parameters = [
|
||||
'api_user' => env('SENDGRID_USERNAME'),
|
||||
'api_key' => env('SENDGRID_PASSWORD'),
|
||||
'date' => 1,
|
||||
'days' => 7
|
||||
];
|
||||
$fullURL = $URL . '?' . http_build_query($parameters);
|
||||
$data = json_decode(file_get_contents($fullURL));
|
||||
$set = [
|
||||
'blocks' => 'https://api.sendgrid.com/api/blocks.get.json',
|
||||
'bounces' => 'https://api.sendgrid.com/api/bounces.get.json',
|
||||
'invalids' => 'https://api.sendgrid.com/api/invalidemails.get.json',
|
||||
|
||||
/*
|
||||
* Loop the result, if any.
|
||||
*/
|
||||
if (is_array($data)) {
|
||||
echo 'Found ' . count($data) . ' entries in the SendGrid bounce list.' . "\n";
|
||||
foreach ($data as $entry) {
|
||||
$address = $entry->email;
|
||||
$user = User::where('email', $address)->where('blocked', 0)->first();
|
||||
if (!is_null($user)) {
|
||||
echo 'Found a user: ' . $address . ', who is now blocked.' . "\n";
|
||||
$user->blocked = 1;
|
||||
$user->blocked_code = 'bounced';
|
||||
$user->password = 'bounced';
|
||||
$user->save();
|
||||
} else {
|
||||
echo 'Found no user: ' . $address . ', did nothing.' . "\n";
|
||||
];
|
||||
echo '<pre>';
|
||||
foreach ($set as $name => $URL) {
|
||||
|
||||
|
||||
$parameters = [
|
||||
'api_user' => env('SENDGRID_USERNAME'),
|
||||
'api_key' => env('SENDGRID_PASSWORD'),
|
||||
'date' => 1,
|
||||
'days' => 7
|
||||
];
|
||||
$fullURL = $URL . '?' . http_build_query($parameters);
|
||||
$data = json_decode(file_get_contents($fullURL));
|
||||
|
||||
/*
|
||||
* Loop the result, if any.
|
||||
*/
|
||||
if (is_array($data)) {
|
||||
echo 'Found ' . count($data) . ' entries in the SendGrid ' . $name . ' list.' . "\n";
|
||||
foreach ($data as $entry) {
|
||||
$address = $entry->email;
|
||||
$user = User::where('email', $address)->where('blocked', 0)->first();
|
||||
if (!is_null($user)) {
|
||||
echo 'Found a user: ' . $address . ', who is now blocked.' . "\n";
|
||||
$user->blocked = 1;
|
||||
$user->blocked_code = 'bounced';
|
||||
$user->password = 'bounced';
|
||||
$user->save();
|
||||
} else {
|
||||
echo 'Found no user: ' . $address . ', did nothing.' . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -79,18 +79,16 @@ class HomeController extends Controller
|
||||
return redirect(route('new-user.index'));
|
||||
}
|
||||
|
||||
$title = 'Firefly';
|
||||
$subTitle = trans('firefly.welcomeBack');
|
||||
$mainTitleIcon = 'fa-fire';
|
||||
$transactions = [];
|
||||
$frontPage = Preferences::get('frontPageAccounts', []);
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$showTour = Preferences::get('tour', true)->data;
|
||||
|
||||
$accounts = $repository->getFrontpageAccounts($frontPage);
|
||||
$savings = $repository->getSavingsAccounts();
|
||||
|
||||
$title = 'Firefly';
|
||||
$subTitle = trans('firefly.welcomeBack');
|
||||
$mainTitleIcon = 'fa-fire';
|
||||
$transactions = [];
|
||||
$frontPage = Preferences::get('frontPageAccounts', []);
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$showTour = Preferences::get('tour', true)->data;
|
||||
$accounts = $repository->getFrontpageAccounts($frontPage);
|
||||
$savings = $repository->getSavingsAccounts();
|
||||
$piggyBankAccounts = $repository->getPiggyBankAccounts();
|
||||
|
||||
|
||||
|
@@ -93,6 +93,8 @@ class JsonController extends Controller
|
||||
}
|
||||
unset($bill, $bills);
|
||||
|
||||
$amount = $amount * -1; // make the amount positive again.
|
||||
|
||||
$creditCards = $accountRepository->getCreditCards(); // Find credit card accounts and possibly unpaid credit card bills.
|
||||
/** @var Account $creditCard */
|
||||
foreach ($creditCards as $creditCard) {
|
||||
@@ -219,6 +221,7 @@ class JsonController extends Controller
|
||||
}
|
||||
|
||||
$amount = $reportQuery->expenseInPeriodCorrected($start, $end, true)->sum('amount');
|
||||
$amount = $amount * -1;
|
||||
|
||||
$data = ['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
|
||||
$cache->store($data);
|
||||
|
@@ -44,9 +44,9 @@ class TagController extends Controller
|
||||
View::share('mainTitleIcon', 'fa-tags');
|
||||
View::share('hideTags', true);
|
||||
$this->tagOptions = [
|
||||
'nothing' => 'Just a regular tag.',
|
||||
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
|
||||
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
|
||||
'nothing' => trans('firefly.regular_tag'),
|
||||
'balancingAct' => trans('firefly.balancing_act'),
|
||||
'advancePayment' => trans('firefly.advance_payment'),
|
||||
];
|
||||
View::share('tagOptions', $this->tagOptions);
|
||||
}
|
||||
@@ -190,7 +190,8 @@ class TagController extends Controller
|
||||
$tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date', 'ASC')->get();
|
||||
$tags = $tags->sortBy(
|
||||
function (Tag $tag) {
|
||||
$date = $tag->date->format('Ymd');
|
||||
$date = !is_null($tag->date) ? $tag->date->format('Ymd') : '000000';
|
||||
|
||||
|
||||
return strtolower($date . $tag->tag);
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Amount;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
@@ -8,6 +9,7 @@ use FireflyIII\Events\JournalCreated;
|
||||
use FireflyIII\Events\JournalSaved;
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Http\Requests\JournalFormRequest;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
@@ -51,11 +53,19 @@ class TransactionController extends Controller
|
||||
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
|
||||
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
|
||||
$budgets[0] = trans('form.noBudget');
|
||||
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
|
||||
$piggies[0] = trans('form.noPiggybank');
|
||||
$preFilled = Session::has('preFilled') ? Session::get('preFilled') : [];
|
||||
$respondTo = ['account_id', 'account_from_id'];
|
||||
$subTitle = trans('form.add_new_' . $what);
|
||||
|
||||
// piggy bank list:
|
||||
$piggyBanks = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get();
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggyBanks as $piggy) {
|
||||
$piggy->name = $piggy->name . ' (' . Amount::format($piggy->currentRelevantRep()->currentamount, false) . ')';
|
||||
}
|
||||
|
||||
$piggies = ExpandedForm::makeSelectList($piggyBanks);
|
||||
$piggies[0] = trans('form.noPiggybank');
|
||||
$preFilled = Session::has('preFilled') ? Session::get('preFilled') : [];
|
||||
$respondTo = ['account_id', 'account_from_id'];
|
||||
$subTitle = trans('form.add_new_' . $what);
|
||||
|
||||
foreach ($respondTo as $r) {
|
||||
$preFilled[$r] = Input::get($r);
|
||||
@@ -126,6 +136,12 @@ class TransactionController extends Controller
|
||||
*/
|
||||
public function edit(AccountRepositoryInterface $repository, TransactionJournal $journal)
|
||||
{
|
||||
// cannot edit opening balance
|
||||
if ($journal->transactionType->type == 'Opening balance') {
|
||||
return view('error')->with('message', 'Cannot edit this transaction. Edit the account instead!');
|
||||
}
|
||||
|
||||
|
||||
$maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize'));
|
||||
$maxPostSize = Steam::phpBytes(ini_get('post_max_size'));
|
||||
$uploadSize = min($maxFileSize, $maxPostSize);
|
||||
@@ -163,7 +179,7 @@ class TransactionController extends Controller
|
||||
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id;
|
||||
}
|
||||
|
||||
$preFilled['amount'] = $journal->actual_amount;
|
||||
$preFilled['amount'] = $journal->amount_positive;
|
||||
|
||||
if ($journal->transactionType->type == 'Withdrawal') {
|
||||
$preFilled['account_id'] = $journal->source_account->id;
|
||||
@@ -323,6 +339,11 @@ class TransactionController extends Controller
|
||||
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att, TransactionJournal $journal)
|
||||
{
|
||||
|
||||
// cannot edit opening balance
|
||||
if ($journal->transactionType->type == 'Opening balance') {
|
||||
return view('error')->with('message', 'Cannot edit this transaction. Edit the account instead!');
|
||||
}
|
||||
|
||||
$journalData = $request->getJournalData();
|
||||
$repository->update($journal, $journalData);
|
||||
|
||||
|
@@ -42,7 +42,7 @@ Breadcrumbs::register(
|
||||
Breadcrumbs::register(
|
||||
'accounts.create', function (Generator $breadcrumbs, $what) {
|
||||
$breadcrumbs->parent('accounts.index', $what);
|
||||
$breadcrumbs->push(trans('breadcrumbs.new_' . strtolower(e($what)) . '_account'), route('accounts.create', [$what]));
|
||||
$breadcrumbs->push(trans('firefly.new_' . strtolower(e($what)) . '_account'), route('accounts.create', [$what]));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -129,7 +129,7 @@ Breadcrumbs::register(
|
||||
Breadcrumbs::register(
|
||||
'categories.create', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('categories.index');
|
||||
$breadcrumbs->push(trans('breadcrumbs.newCategory'), route('categories.create'));
|
||||
$breadcrumbs->push(trans('firefly.new_category'), route('categories.create'));
|
||||
}
|
||||
);
|
||||
|
||||
@@ -154,6 +154,19 @@ Breadcrumbs::register(
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'categories.show.date', function (Generator $breadcrumbs, Category $category, Carbon $date) {
|
||||
|
||||
// get current period preference.
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
|
||||
$breadcrumbs->parent('categories.index');
|
||||
$breadcrumbs->push(e($category->name), route('categories.show', [$category->id]));
|
||||
$breadcrumbs->push(Navigation::periodShow($date, $range), route('categories.show.date', [$category->id, $date->format('Y-m-d')]));
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'categories.noCategory', function (Generator $breadcrumbs, $subTitle) {
|
||||
$breadcrumbs->parent('categories.index');
|
||||
@@ -231,7 +244,7 @@ Breadcrumbs::register(
|
||||
Breadcrumbs::register(
|
||||
'piggy-banks.index', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('breadcrumbs.piggyBanks'), route('piggy-banks.index'));
|
||||
$breadcrumbs->push(trans('firefly.piggyBanks'), route('piggy-banks.index'));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
@@ -250,7 +263,7 @@ Breadcrumbs::register(
|
||||
Breadcrumbs::register(
|
||||
'piggy-banks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
|
||||
$breadcrumbs->push(trans('breadcrumbs.delete_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.delete', [$piggyBank->id]));
|
||||
$breadcrumbs->push(trans('firefly.delete_piggy_bank', ['name' => e($piggyBank->name)]), route('piggy-banks.delete', [$piggyBank->id]));
|
||||
}
|
||||
);
|
||||
|
||||
|
@@ -162,7 +162,7 @@ Route::get('/cron/sendgrid', ['uses' => 'CronController@sendgrid']);
|
||||
|
||||
Route::controllers(
|
||||
[
|
||||
'auth' => 'Auth\AuthController',
|
||||
'auth' => 'Auth\AuthController',
|
||||
'password' => 'Auth\PasswordController',
|
||||
]
|
||||
);
|
||||
@@ -244,6 +244,7 @@ Route::group(
|
||||
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/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::post('/categories/store', ['uses' => 'CategoryController@store', 'as' => 'categories.store']);
|
||||
Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']);
|
||||
@@ -282,6 +283,7 @@ Route::group(
|
||||
*/
|
||||
// accounts:
|
||||
Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']);
|
||||
Route::get('/chart/account/expense', ['uses' => 'Chart\AccountController@expenseAccounts']);
|
||||
Route::get('/chart/account/month/{year}/{month}/{shared?}', ['uses' => 'Chart\AccountController@all'])->where(
|
||||
['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared']
|
||||
);
|
||||
@@ -300,8 +302,14 @@ Route::group(
|
||||
|
||||
// categories:
|
||||
Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']);
|
||||
Route::get('/chart/category/year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
|
||||
Route::get('/chart/category/{category}/month', ['uses' => 'Chart\CategoryController@month']); // should be period.
|
||||
Route::get('/chart/category/spent-in-year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@spentInYear'])->where(
|
||||
['year' => '[0-9]{4}', 'shared' => 'shared']
|
||||
);
|
||||
Route::get('/chart/category/earned-in-year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@earnedInYear'])->where(
|
||||
['year' => '[0-9]{4}', 'shared' => 'shared']
|
||||
);
|
||||
Route::get('/chart/category/{category}/period', ['uses' => 'Chart\CategoryController@currentPeriod']);
|
||||
Route::get('/chart/category/{category}/period/{date}', ['uses' => 'Chart\CategoryController@specificPeriod']);
|
||||
Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']);
|
||||
|
||||
// piggy banks:
|
||||
|
@@ -39,8 +39,8 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereSkip($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereNameEncrypted($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereMatchEncrypted($value)
|
||||
* @property-read \Carbon\Carbon $nextExpectedMatch
|
||||
* @property-read \Carbon\Carbon $lastFoundMatch
|
||||
* @property \Carbon\Carbon $nextExpectedMatch
|
||||
* @property \Carbon\Carbon $lastFoundMatch
|
||||
*/
|
||||
class Bill extends Model
|
||||
{
|
||||
|
@@ -25,7 +25,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUserId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereEncrypted($value)
|
||||
* @property-read float $spent
|
||||
* @property-read \Carbon\Carbon $lastActivity
|
||||
* @property \Carbon\Carbon $lastActivity
|
||||
*/
|
||||
class Category extends Model
|
||||
{
|
||||
|
@@ -69,6 +69,7 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @property string $name
|
||||
* @property-read string $symbol
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Attachment[] $attachments
|
||||
* @property-read mixed $amount_positive
|
||||
*/
|
||||
class TransactionJournal extends Model
|
||||
{
|
||||
@@ -120,7 +121,7 @@ class TransactionJournal extends Model
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getActualAmountAttribute()
|
||||
public function getAmountPositiveAttribute()
|
||||
{
|
||||
$amount = '0';
|
||||
/** @var Transaction $t */
|
||||
@@ -146,18 +147,11 @@ class TransactionJournal extends Model
|
||||
}
|
||||
|
||||
bcscale(2);
|
||||
$set = $this->transactions->sortByDesc('amount');
|
||||
$amount = $set->first()->amount;
|
||||
|
||||
if (intval($this->tag_count) === 1) {
|
||||
// get amount for single tag:
|
||||
$amount = $this->amountByTag($this->tags()->first(), $amount);
|
||||
}
|
||||
|
||||
if (intval($this->tag_count) > 1) {
|
||||
// get amount for either tag.
|
||||
$amount = $this->amountByTags($amount);
|
||||
|
||||
$type = $this->transactionType->type;
|
||||
$transaction = $this->transactions->sortByDesc('amount')->first();
|
||||
$amount = $transaction->amount;
|
||||
if ($type == 'Withdrawal') {
|
||||
$amount = $amount * -1;
|
||||
}
|
||||
$cache->store($amount);
|
||||
|
||||
@@ -176,7 +170,7 @@ class TransactionJournal extends Model
|
||||
if ($this->transactionType->type == 'Withdrawal') {
|
||||
$others = $tag->transactionJournals()->transactionTypes(['Deposit'])->get();
|
||||
foreach ($others as $other) {
|
||||
$amount = bcsub($amount, $other->actual_amount);
|
||||
$amount = bcsub($amount, $other->amount_positive);
|
||||
}
|
||||
|
||||
return $amount;
|
||||
@@ -199,7 +193,7 @@ class TransactionJournal extends Model
|
||||
if ($this->transactionType->type == 'Withdrawal') {
|
||||
$transfer = $tag->transactionJournals()->transactionTypes(['Transfer'])->first();
|
||||
if ($transfer) {
|
||||
$amount = bcsub($amount, $transfer->actual_amount);
|
||||
$amount = bcsub($amount, $transfer->amount_positive);
|
||||
|
||||
return $amount;
|
||||
}
|
||||
@@ -260,21 +254,6 @@ class TransactionJournal extends Model
|
||||
return $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCorrectAmountAttribute()
|
||||
{
|
||||
|
||||
switch ($this->transactionType->type) {
|
||||
case 'Deposit':
|
||||
return $this->transactions()->where('amount', '>', 0)->first()->amount;
|
||||
case 'Withdrawal':
|
||||
return $this->transactions()->where('amount', '<', 0)->first()->amount;
|
||||
}
|
||||
|
||||
return $this->transactions()->where('amount', '>', 0)->first()->amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
|
@@ -98,7 +98,6 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
$this->app->bind('FireflyIII\Helpers\Attachments\AttachmentHelperInterface', 'FireflyIII\Helpers\Attachments\AttachmentHelper');
|
||||
|
||||
// make charts:
|
||||
// alternative is Google instead of ChartJs
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Account\AccountChartGenerator', 'FireflyIII\Generator\Chart\Account\ChartJsAccountChartGenerator');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Bill\BillChartGenerator', 'FireflyIII\Generator\Chart\Bill\ChartJsBillChartGenerator');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator', 'FireflyIII\Generator\Chart\Budget\ChartJsBudgetChartGenerator');
|
||||
|
@@ -375,6 +375,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
return TransactionJournal
|
||||
::orderBy('transaction_journals.date', 'ASC')
|
||||
->accountIs($account)
|
||||
->transactionTypes(['Opening balance'])
|
||||
->orderBy('created_at', 'ASC')
|
||||
->first(['transaction_journals.*']);
|
||||
}
|
||||
@@ -394,10 +395,9 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
|
||||
// continue with the opposing account:
|
||||
if ($data['openingBalance'] != 0) {
|
||||
$type = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
|
||||
$opposingData = [
|
||||
'user' => $data['user'],
|
||||
'accountType' => $type,
|
||||
'accountType' => 'initial',
|
||||
'virtualBalance' => 0,
|
||||
'name' => $data['name'] . ' initial balance',
|
||||
'active' => false,
|
||||
|
@@ -9,6 +9,7 @@ use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Steam;
|
||||
|
||||
@@ -97,7 +98,10 @@ class BillRepository implements BillRepositoryInterface
|
||||
|
||||
$set = $set->sortBy(
|
||||
function (Bill $bill) {
|
||||
return strtolower($bill->name);
|
||||
|
||||
$int = $bill->active == 1 ? 0 : 1;
|
||||
|
||||
return $int . strtolower($bill->name);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -150,7 +154,9 @@ class BillRepository implements BillRepositoryInterface
|
||||
}
|
||||
$journals = new Collection;
|
||||
if (count($ids) > 0) {
|
||||
$journals = Auth::user()->transactionjournals()->whereIn('id', $ids)->get();
|
||||
$journals = Auth::user()->transactionjournals()->transactionTypes(['Withdrawal'])->whereIn('transaction_journals.id', $ids)->get(
|
||||
['transaction_journals.*']
|
||||
);
|
||||
}
|
||||
|
||||
return $journals;
|
||||
@@ -273,7 +279,8 @@ class BillRepository implements BillRepositoryInterface
|
||||
$matches = explode(',', $bill->match);
|
||||
$description = strtolower($journal->description) . ' ' . strtolower($journal->destination_account->name);
|
||||
$wordMatch = $this->doWordMatch($matches, $description);
|
||||
$amountMatch = $this->doAmountMatch($journal->amount, $bill->amount_min, $bill->amount_max);
|
||||
$amountMatch = $this->doAmountMatch($journal->amount_positive, $bill->amount_min, $bill->amount_max);
|
||||
Log::debug('Journal #' . $journal->id . ' has description "' . $description . '"');
|
||||
|
||||
/*
|
||||
* If both, update!
|
||||
@@ -283,6 +290,8 @@ class BillRepository implements BillRepositoryInterface
|
||||
$journal->save();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
Log::debug('Wordmatch: ' . (($wordMatch) ? 'true' : 'false') . ' AmountMatch: ' . (($amountMatch) ? 'true' : 'false'));
|
||||
}
|
||||
if ($bill->id == $journal->bill_id) {
|
||||
// if no match, but bill used to match, remove it:
|
||||
|
@@ -55,7 +55,7 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
bcscale(2);
|
||||
$sum = $budget->transactionjournals()->transactionTypes(['Withdrawal'])->onDate($date)->get(['transaction_journals.*'])->sum('amount');
|
||||
|
||||
return bcmul($sum, -1);
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,20 +122,26 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return LimitRepetition|null
|
||||
*/
|
||||
public function getCurrentRepetition(Budget $budget, Carbon $date)
|
||||
public function getCurrentRepetition(Budget $budget, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($budget->id);
|
||||
$cache->addProperty($date);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
|
||||
$cache->addProperty('getCurrentRepetition');
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
$data = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']);
|
||||
$data = $budget->limitrepetitions()
|
||||
->where('limit_repetitions.startdate', $start)
|
||||
->where('limit_repetitions.enddate', $end)
|
||||
->first(['limit_repetitions.*']);
|
||||
$cache->store($data);
|
||||
|
||||
return $data;
|
||||
@@ -313,9 +319,9 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriodCorrected(Budget $budget, Carbon $start, Carbon $end, $shared = true)
|
||||
public function balanceInPeriod(Budget $budget, Carbon $start, Carbon $end, $shared = true)
|
||||
{
|
||||
return $this->spentInPeriod($budget, $start, $end, $shared);
|
||||
return $this->commonBalanceInPeriod($budget, $start, $end, $shared);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -65,11 +65,12 @@ interface BudgetRepositoryInterface
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return LimitRepetition|null
|
||||
*/
|
||||
public function getCurrentRepetition(Budget $budget, Carbon $date);
|
||||
public function getCurrentRepetition(Budget $budget, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
@@ -136,7 +137,7 @@ interface BudgetRepositoryInterface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriodCorrected(Budget $budget, Carbon $start, Carbon $end, $shared = true);
|
||||
public function balanceInPeriod(Budget $budget, Carbon $start, Carbon $end, $shared = true);
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
|
@@ -8,6 +8,7 @@ use Crypt;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Shared\ComponentRepository;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
@@ -57,6 +58,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
return $set;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Carbon $start
|
||||
@@ -64,7 +66,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCategoriesAndExpensesCorrected($start, $end)
|
||||
public function getCategoriesAndExpensesCorrected(Carbon $start, Carbon $end)
|
||||
{
|
||||
$set = Auth::user()->transactionjournals()
|
||||
->leftJoin(
|
||||
@@ -77,15 +79,15 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->get(['categories.id as category_id', 'categories.encrypted as category_encrypted', 'categories.name', 'transaction_journals.*']);
|
||||
|
||||
bcscale(2);
|
||||
$result = [];
|
||||
foreach ($set as $entry) {
|
||||
$categoryId = intval($entry->category_id);
|
||||
if (isset($result[$categoryId])) {
|
||||
bcscale(2);
|
||||
$result[$categoryId]['sum'] = bcadd($result[$categoryId]['sum'], $entry->amount);
|
||||
} else {
|
||||
$isEncrypted = intval($entry->category_encrypted) == 1 ? true : false;
|
||||
$name = strlen($entry->name) == 0 ? trans('firefly.no_category') : $entry->name;
|
||||
$isEncrypted = intval($entry->category_encrypted) === 1 ? true : false;
|
||||
$name = strlen($entry->name) === 0 ? trans('firefly.no_category') : $entry->name;
|
||||
$name = $isEncrypted ? Crypt::decrypt($name) : $name;
|
||||
$result[$categoryId] = [
|
||||
'name' => $name,
|
||||
@@ -183,9 +185,9 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriodCorrected(Category $category, Carbon $start, Carbon $end, $shared = false)
|
||||
public function balanceInPeriod(Category $category, Carbon $start, Carbon $end, $shared = false)
|
||||
{
|
||||
return $this->spentInPeriod($category, $start, $end, $shared);
|
||||
return $this->commonBalanceInPeriod($category, $start, $end, $shared);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +200,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
*/
|
||||
public function spentOnDaySumCorrected(Category $category, Carbon $date)
|
||||
{
|
||||
return $category->transactionjournals()->onDate($date)->get(['transaction_journals.*'])->sum('amount');
|
||||
return $category->transactionjournals()->transactionTypes(['Withdrawal'])->onDate($date)->get(['transaction_journals.*'])->sum('amount');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,4 +235,138 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the sum of the journals in the category, optionally
|
||||
* limited by a start or end date.
|
||||
*
|
||||
* @param Category $category
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function journalsSum(Category $category, Carbon $start = null, Carbon $end = null)
|
||||
{
|
||||
$query = $category->transactionJournals()
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC');
|
||||
if (!is_null($start)) {
|
||||
$query->after($start);
|
||||
}
|
||||
|
||||
if (!is_null($end)) {
|
||||
$query->before($end);
|
||||
}
|
||||
|
||||
return $query->get(['transaction_journals.*'])->sum('amount');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
*
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriod(Category $category, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties; // we must cache this.
|
||||
$cache->addProperty($category->id);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('spentInPeriod');
|
||||
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$sum = $category->transactionjournals()->transactionTypes(['Withdrawal'])->before($end)->after($start)->get(['transaction_journals.*'])->sum(
|
||||
'amount'
|
||||
);
|
||||
|
||||
$cache->store($sum);
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
*
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function earnedInPeriod(Category $category, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties; // we must cache this.
|
||||
$cache->addProperty($category->id);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('earnedInPeriod');
|
||||
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$sum = $category->transactionjournals()->transactionTypes(['Deposit'])->before($end)->after($start)->get(['transaction_journals.*'])->sum(
|
||||
'amount'
|
||||
);
|
||||
|
||||
$cache->store($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();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Corrected for tags.
|
||||
*
|
||||
* @param Category $category
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function earnedOnDaySumCorrected(Category $category, Carbon $date)
|
||||
{
|
||||
return $category->transactionjournals()->transactionTypes(['Deposit'])->onDate($date)->get(['transaction_journals.*'])->sum('amount');
|
||||
}
|
||||
}
|
||||
|
@@ -20,6 +20,13 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function countJournals(Category $category);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countJournalsInRange(Category $category, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
@@ -40,7 +47,7 @@ interface CategoryRepositoryInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCategoriesAndExpensesCorrected($start, $end);
|
||||
public function getCategoriesAndExpensesCorrected(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
@@ -57,6 +64,26 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
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
|
||||
* limited by a start or end date.
|
||||
*
|
||||
* @param Category $category
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function journalsSum(Category $category, Carbon $start = null, Carbon $end = null);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
@@ -83,7 +110,29 @@ interface CategoryRepositoryInterface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriodCorrected(Category $category, Carbon $start, Carbon $end, $shared = false);
|
||||
public function balanceInPeriod(Category $category, Carbon $start, Carbon $end, $shared = false);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
*
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriod(Category $category, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
*
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function earnedInPeriod(Category $category, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -96,6 +145,17 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function spentOnDaySumCorrected(Category $category, Carbon $date);
|
||||
|
||||
/**
|
||||
*
|
||||
* Corrected for tags.
|
||||
*
|
||||
* @param Category $category
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function earnedOnDaySumCorrected(Category $category, Carbon $date);
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
|
@@ -24,7 +24,7 @@ class ComponentRepository
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function spentInPeriod($object, Carbon $start, Carbon $end, $shared = false)
|
||||
protected function commonBalanceInPeriod($object, Carbon $start, Carbon $end, $shared = false)
|
||||
{
|
||||
$cache = new CacheProperties; // we must cache this.
|
||||
$cache->addProperty($object->id);
|
||||
@@ -32,22 +32,22 @@ class ComponentRepository
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($shared);
|
||||
$cache->addProperty('spentInPeriod');
|
||||
$cache->addProperty('balanceInPeriod');
|
||||
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if ($shared === true) { // shared is true: always ignore transfers between accounts!
|
||||
$sum = $object->transactionjournals()->transactionTypes(['Withdrawal'])->before($end)->after($start)
|
||||
$sum = $object->transactionjournals()->transactionTypes(['Withdrawal', 'Deposit', 'Opening balance'])->before($end)->after($start)
|
||||
->get(['transaction_journals.*'])->sum('amount');
|
||||
} else {
|
||||
// do something else, SEE budgets.
|
||||
// get all journals in this month where the asset account is NOT shared.
|
||||
$sum = $object->transactionjournals()->before($end)->after($start)
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->transactionTypes(['Withdrawal', 'Deposit', 'Opening balance'])
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
|
@@ -99,24 +99,21 @@ class Amount
|
||||
} else {
|
||||
$symbol = $journal->symbol;
|
||||
}
|
||||
$amount = $journal->amount;
|
||||
if ($journal->transactionType->type == 'Withdrawal') {
|
||||
$amount = $amount * -1;
|
||||
}
|
||||
|
||||
if ($journal->transactionType->type == 'Transfer' && $coloured) {
|
||||
$txt = '<span class="text-info">' . $this->formatWithSymbol($symbol, $amount, false) . '</span>';
|
||||
$txt = '<span class="text-info">' . $this->formatWithSymbol($symbol, $journal->amount_positive, false) . '</span>';
|
||||
$cache->store($txt);
|
||||
|
||||
return $txt;
|
||||
}
|
||||
if ($journal->transactionType->type == 'Transfer' && !$coloured) {
|
||||
$txt = $this->formatWithSymbol($symbol, $amount, false);
|
||||
$txt = $this->formatWithSymbol($symbol, $journal->amount_positive, false);
|
||||
$cache->store($txt);
|
||||
|
||||
return $txt;
|
||||
}
|
||||
|
||||
$txt = $this->formatWithSymbol($symbol, $amount, $coloured);
|
||||
$txt = $this->formatWithSymbol($symbol, $journal->amount, $coloured);
|
||||
$cache->store($txt);
|
||||
|
||||
return $txt;
|
||||
|
@@ -106,16 +106,21 @@ class Navigation
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
public function endOfX(Carbon $theCurrentEnd, $repeatFreq, Carbon $maxDate)
|
||||
public function endOfX(Carbon $theCurrentEnd, $repeatFreq, Carbon $maxDate = null)
|
||||
{
|
||||
$functionMap = [
|
||||
'1D' => 'endOfDay',
|
||||
'daily' => 'endOfDay',
|
||||
'1W' => 'endOfWeek',
|
||||
'week' => 'endOfWeek',
|
||||
'weekly' => 'endOfWeek',
|
||||
'month' => 'endOfMonth',
|
||||
'1M' => 'endOfMonth',
|
||||
'monthly' => 'endOfMonth',
|
||||
'3M' => 'lastOfQuarter',
|
||||
'quarter' => 'lastOfQuarter',
|
||||
'quarterly' => 'lastOfQuarter',
|
||||
'1Y' => 'endOfYear',
|
||||
'year' => 'endOfYear',
|
||||
'yearly' => 'endOfYear',
|
||||
];
|
||||
@@ -128,7 +133,7 @@ class Navigation
|
||||
|
||||
}
|
||||
|
||||
if ($currentEnd > $maxDate) {
|
||||
if (!is_null($maxDate) && $currentEnd > $maxDate) {
|
||||
return clone $maxDate;
|
||||
}
|
||||
|
||||
@@ -145,12 +150,17 @@ class Navigation
|
||||
public function periodShow(Carbon $date, $repeatFrequency)
|
||||
{
|
||||
$formatMap = [
|
||||
'1D' => '%e %B %Y',
|
||||
'daily' => '%e %B %Y',
|
||||
'1W' => 'Week %W, %Y',
|
||||
'week' => 'Week %W, %Y',
|
||||
'weekly' => 'Week %W, %Y',
|
||||
'3M' => '%B %Y',
|
||||
'quarter' => '%B %Y',
|
||||
'1M' => '%B %Y',
|
||||
'month' => '%B %Y',
|
||||
'monthly' => '%B %Y',
|
||||
'1Y' => '%Y',
|
||||
'year' => '%Y',
|
||||
'yearly' => '%Y',
|
||||
|
||||
@@ -218,12 +228,15 @@ class Navigation
|
||||
public function subtractPeriod(Carbon $theDate, $repeatFreq, $subtract = 1)
|
||||
{
|
||||
$date = clone $theDate;
|
||||
|
||||
// 1D 1W 1M 3M 6M 1Y
|
||||
$functionMap = [
|
||||
'1D' => 'subDays',
|
||||
'daily' => 'subDays',
|
||||
'week' => 'subWeeks',
|
||||
'1W' => 'subWeeks',
|
||||
'weekly' => 'subWeeks',
|
||||
'month' => 'subMonths',
|
||||
'1M' => 'subMonths',
|
||||
'monthly' => 'subMonths',
|
||||
'year' => 'subYears',
|
||||
'yearly' => 'subYears',
|
||||
|
@@ -181,7 +181,7 @@ class Journal extends Twig_Extension
|
||||
if ($tag->tagMode == 'balancingAct') {
|
||||
// return tag formatted for a "balancing act", even if other
|
||||
// tags are present.
|
||||
$amount = app('amount')->format($journal->actual_amount, false);
|
||||
$amount = app('amount')->format($journal->amount_positive, false);
|
||||
$string = '<a href="' . route('tags.show', [$tag->id]) . '" class="label label-success" title="' . $amount
|
||||
. '"><i class="fa fa-fw fa-refresh"></i> ' . $tag->tag . '</a>';
|
||||
|
||||
|
@@ -62,21 +62,11 @@ class FireflyValidator extends Validator
|
||||
*/
|
||||
public function validateIban($attribute, $value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
return false;
|
||||
}
|
||||
if (is_null($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
if (!is_string($value) || is_null($value) || strlen($value) < 6) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = strtoupper($value);
|
||||
if (strlen($value) < 6) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$search = [' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
||||
$replace = ['', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31',
|
||||
@@ -282,7 +272,8 @@ class FireflyValidator extends Validator
|
||||
$exclude = isset($parameters[2]) ? intval($parameters[2]) : 0;
|
||||
|
||||
// get entries from table
|
||||
$set = DB::table($table)->where('user_id', Auth::user()->id)->where('id', '!=', $exclude)->get([$field]);
|
||||
$set = DB::table($table)->where('user_id', Auth::user()->id)
|
||||
->where('id', '!=', $exclude)->get([$field]);
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$fieldValue = $this->tryDecrypt($entry->$field);
|
||||
@@ -306,6 +297,7 @@ class FireflyValidator extends Validator
|
||||
{
|
||||
$exclude = isset($parameters[0]) ? $parameters[0] : null;
|
||||
$query = DB::table('piggy_banks');
|
||||
$query->whereNull('piggy_banks.deleted_at');
|
||||
$query->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id');
|
||||
$query->where('accounts.user_id', Auth::user()->id);
|
||||
if (!is_null($exclude)) {
|
||||
|
@@ -26,12 +26,10 @@
|
||||
"watson/validating": "~1.0",
|
||||
"doctrine/dbal": "~2.5",
|
||||
"illuminate/html": "~5.0",
|
||||
"league/commonmark": "0.7.*",
|
||||
"league/commonmark": "~0.7",
|
||||
"rcrowe/twigbridge": "0.7.x@dev",
|
||||
"zizaco/entrust": "dev-laravel-5",
|
||||
"codeception/codeception": "*",
|
||||
"league/csv": "^7.1",
|
||||
"nesbot/carbon": "^1.20"
|
||||
"league/csv": "^7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "@stable",
|
||||
|
1518
composer.lock
generated
1518
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
|
||||
return [
|
||||
'chart' => 'chartjs',
|
||||
'version' => '3.4.10',
|
||||
'version' => '3.5.2',
|
||||
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
|
||||
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
|
||||
'csv_import_enabled' => true,
|
||||
@@ -85,7 +85,9 @@ return [
|
||||
[
|
||||
'asset' => 'Asset account',
|
||||
'expense' => 'Expense account',
|
||||
'revenue' => 'Revenue account'
|
||||
'revenue' => 'Revenue account',
|
||||
'opening' => 'Initial balance account',
|
||||
'initial' => 'Initial balance account',
|
||||
],
|
||||
'shortNamesByFullName' =>
|
||||
[
|
||||
|
40
pu.sh
40
pu.sh
@@ -1,40 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# set testing environment
|
||||
cp .env.testing .env
|
||||
|
||||
# test!
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
phpunit --verbose
|
||||
fi
|
||||
|
||||
# directories to look in:
|
||||
dirs=("controllers" "database" "factories" "generators" "helpers" "models" "middleware" "repositories" "support")
|
||||
|
||||
if [ ! -z "$1" ]
|
||||
then
|
||||
for i in "${dirs[@]}"
|
||||
do
|
||||
firstFile="./tests/$i/$1.php"
|
||||
secondFile="./tests/$i/$1Test.php"
|
||||
if [ -f "$firstFile" ]
|
||||
then
|
||||
# run it!
|
||||
phpunit --verbose $firstFile
|
||||
exit $?
|
||||
fi
|
||||
if [ -f "$secondFile" ]
|
||||
then
|
||||
# run it!
|
||||
phpunit --verbose $secondFile
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
# restore .env file
|
||||
cp .env.local .env
|
@@ -1,335 +0,0 @@
|
||||
/*!
|
||||
* Stylesheet for the Date Range Picker, for use with Bootstrap 3.x
|
||||
*
|
||||
* Copyright 2013-2015 Dan Grossman ( http://www.dangrossman.info )
|
||||
* Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Built for http://www.improvely.com
|
||||
*/
|
||||
|
||||
.daterangepicker.dropdown-menu {
|
||||
max-width: none;
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
.daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar {
|
||||
float: left;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar,
|
||||
.daterangepicker.openscenter .ranges, .daterangepicker.openscenter .calendar {
|
||||
float: right;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker.single .ranges, .daterangepicker.single .calendar {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges {
|
||||
width: 160px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges .range_inputs>div {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges .range_inputs>div:nth-child(2) {
|
||||
padding-left: 11px;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar {
|
||||
display: none;
|
||||
max-width: 270px;
|
||||
}
|
||||
|
||||
.daterangepicker.show-calendar .calendar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar.single .calendar-date {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar th, .daterangepicker .calendar td {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
.daterangepicker .daterangepicker_start_input label,
|
||||
.daterangepicker .daterangepicker_end_input label {
|
||||
color: #333;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 2px;
|
||||
text-shadow: #fff 1px 1px 0px;
|
||||
text-transform: uppercase;
|
||||
width: 74px;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges input {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges .input-mini {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
color: #555;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
vertical-align: middle;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0 6px;
|
||||
width: 74px;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges li {
|
||||
font-size: 13px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #f5f5f5;
|
||||
color: #08c;
|
||||
padding: 3px 12px;
|
||||
margin-bottom: 8px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {
|
||||
background: #08c;
|
||||
border: 1px solid #08c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar-date {
|
||||
border: 1px solid #ddd;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar-time {
|
||||
text-align: center;
|
||||
margin: 8px auto 0 auto;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.daterangepicker {
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
top: 100px;
|
||||
left: 20px;
|
||||
padding: 4px;
|
||||
margin-top: 1px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker.opensleft:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
right: 9px;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensleft:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: 10px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.openscenter:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.openscenter:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensright:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 9px;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensright:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 10px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.dropup{
|
||||
margin-top: -5px;
|
||||
}
|
||||
.daterangepicker.dropup:before{
|
||||
top: initial;
|
||||
bottom:-7px;
|
||||
border-bottom: initial;
|
||||
border-top: 7px solid #ccc;
|
||||
}
|
||||
.daterangepicker.dropup:after{
|
||||
top: initial;
|
||||
bottom:-6px;
|
||||
border-bottom: initial;
|
||||
border-top: 6px solid #fff;
|
||||
}
|
||||
|
||||
.daterangepicker table {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.daterangepicker td, .daterangepicker th {
|
||||
text-align: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.daterangepicker td.off {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.daterangepicker td.disabled, .daterangepicker option.disabled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.daterangepicker td.available:hover, .daterangepicker th.available:hover {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.daterangepicker td.in-range {
|
||||
background: #ebf4f8;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.daterangepicker td.start-date {
|
||||
-webkit-border-radius: 4px 0 0 4px;
|
||||
-moz-border-radius: 4px 0 0 4px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.daterangepicker td.end-date {
|
||||
-webkit-border-radius: 0 4px 4px 0;
|
||||
-moz-border-radius: 0 4px 4px 0;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.daterangepicker td.start-date.end-date {
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker td.active, .daterangepicker td.active:hover {
|
||||
background-color: #357ebd;
|
||||
border-color: #3071a9;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker td.week, .daterangepicker th.week {
|
||||
font-size: 80%;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
|
||||
font-size: 12px;
|
||||
padding: 1px;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.daterangepicker select.monthselect {
|
||||
margin-right: 2%;
|
||||
width: 56%;
|
||||
}
|
||||
|
||||
.daterangepicker select.yearselect {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
|
||||
width: 50px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.daterangepicker_start_input {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.daterangepicker_end_input {
|
||||
float: left;
|
||||
padding-left: 11px
|
||||
}
|
||||
|
||||
.daterangepicker th.month {
|
||||
width: auto;
|
||||
}
|
341
public/css/daterangepicker.css
Executable file
341
public/css/daterangepicker.css
Executable file
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
* A stylesheet for use with Bootstrap 3.x
|
||||
* @author: Dan Grossman http://www.dangrossman.info/
|
||||
* @copyright: Copyright (c) 2012-2015 Dan Grossman. All rights reserved.
|
||||
* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
|
||||
* @website: https://www.improvely.com/
|
||||
*/
|
||||
|
||||
/* Container Appearance */
|
||||
|
||||
.daterangepicker {
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
top: 100px;
|
||||
left: 20px;
|
||||
padding: 4px;
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker.opensleft:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
right: 9px;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensleft:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: 10px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.openscenter:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.openscenter:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensright:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 9px;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensright:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 10px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.dropup{
|
||||
margin-top: -5px;
|
||||
}
|
||||
.daterangepicker.dropup:before{
|
||||
top: initial;
|
||||
bottom:-7px;
|
||||
border-bottom: initial;
|
||||
border-top: 7px solid #ccc;
|
||||
}
|
||||
.daterangepicker.dropup:after{
|
||||
top: initial;
|
||||
bottom:-6px;
|
||||
border-bottom: initial;
|
||||
border-top: 6px solid #fff;
|
||||
}
|
||||
|
||||
.daterangepicker.dropdown-menu {
|
||||
max-width: none;
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges, .daterangepicker .calendar {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.daterangepicker.single .ranges, .daterangepicker.single .calendar {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges {
|
||||
margin: 4px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar {
|
||||
display: none;
|
||||
max-width: 270px;
|
||||
}
|
||||
|
||||
.daterangepicker.show-calendar .calendar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar.single .calendar-table {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Calendars */
|
||||
|
||||
.daterangepicker .calendar th, .daterangepicker .calendar td {
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar-table {
|
||||
border: 1px solid #ddd;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar.left .calendar-table {
|
||||
border-right: none;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar.right .calendar-table {
|
||||
border-left: none;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar.left {
|
||||
margin: 4px 0 4px 4px;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar.right {
|
||||
margin: 4px 4px 4px 0;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar.left .calendar-table {
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.daterangepicker table {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.daterangepicker td, .daterangepicker th {
|
||||
text-align: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date {
|
||||
color: #999;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker td.disabled, .daterangepicker option.disabled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.daterangepicker td.available:hover, .daterangepicker th.available:hover {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.daterangepicker td.in-range {
|
||||
background: #ebf4f8;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.daterangepicker td.start-date {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.daterangepicker td.end-date {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.daterangepicker td.start-date.end-date {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker td.active, .daterangepicker td.active:hover {
|
||||
background-color: #357ebd;
|
||||
border-color: #3071a9;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker td.week, .daterangepicker th.week {
|
||||
font-size: 80%;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
|
||||
font-size: 12px;
|
||||
padding: 1px;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.daterangepicker select.monthselect {
|
||||
margin-right: 2%;
|
||||
width: 56%;
|
||||
}
|
||||
|
||||
.daterangepicker select.yearselect {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
|
||||
width: 50px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.daterangepicker th.month {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Text Input Above Each Calendar */
|
||||
|
||||
.daterangepicker .input-mini {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
color: #555;
|
||||
display: block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
vertical-align: middle;
|
||||
margin: 0 0 5px 0;
|
||||
padding: 0 6px 0 28px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.daterangepicker .input-mini.active {
|
||||
border: 1px solid #357ebd;
|
||||
}
|
||||
|
||||
.daterangepicker .daterangepicker_input i {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.daterangepicker .left .daterangepicker_input {
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.daterangepicker .daterangepicker_input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Time Picker */
|
||||
|
||||
.daterangepicker .calendar-time {
|
||||
text-align: center;
|
||||
margin: 5px auto;
|
||||
line-height: 30px;
|
||||
position: relative;
|
||||
padding-left: 28px;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar-time select.disabled {
|
||||
color: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Predefined Ranges */
|
||||
|
||||
.daterangepicker .ranges {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges li {
|
||||
font-size: 13px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #f5f5f5;
|
||||
color: #08c;
|
||||
padding: 3px 12px;
|
||||
margin-bottom: 8px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {
|
||||
background: #08c;
|
||||
border: 1px solid #08c;
|
||||
color: #fff;
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
#daterange {cursor:pointer;}
|
||||
.google-chart-error {height:30px;background:url('/images/error.png') no-repeat center center;}
|
||||
.general-chart-error {height:30px;background:url('/images/error.png') no-repeat center center;}
|
||||
.handle {cursor:move;}
|
||||
|
||||
.ui-sortable-placeholder {
|
||||
|
@@ -13,6 +13,7 @@ var fixHelper = function (e, ui) {
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(lineChart) === "function" && typeof accountID !== 'undefined') {
|
||||
|
||||
lineChart('chart/account/' + accountID, 'overview-chart');
|
||||
}
|
||||
|
||||
@@ -26,6 +27,8 @@ $(function () {
|
||||
handle: '.handle'
|
||||
}
|
||||
).disableSelection();
|
||||
} else {
|
||||
console.log('its null');
|
||||
}
|
||||
|
||||
});
|
||||
@@ -34,6 +37,7 @@ $(function () {
|
||||
function sortStop(event, ui) {
|
||||
"use strict";
|
||||
var current = $(ui.item);
|
||||
console.log('sort stop');
|
||||
var thisDate = current.data('date');
|
||||
var originalBG = current.css('backgroundColor');
|
||||
|
||||
|
@@ -1,11 +1,19 @@
|
||||
/* globals $, categoryID, columnChart */
|
||||
/* globals $, categoryID, columnChart, categoryDate */
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof categoryID !== 'undefined') {
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
columnChart('chart/category/' + categoryID + '/month', 'month');
|
||||
// more splits:
|
||||
if ($('#all').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
}
|
||||
if ($('#period').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/period', 'period');
|
||||
}
|
||||
|
||||
}
|
||||
if (typeof categoryID !== 'undefined' && typeof categoryDate !== undefined) {
|
||||
columnChart('chart/category/' + categoryID + '/period/' + categoryDate, 'period-specific-period');
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
@@ -3,18 +3,6 @@
|
||||
/*
|
||||
Make some colours:
|
||||
*/
|
||||
/*
|
||||
#555299
|
||||
#4285f4
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
#", "#", "#", "#"],
|
||||
*/
|
||||
var colourSet = [
|
||||
[53, 124, 165],
|
||||
[0, 141, 76],
|
||||
@@ -54,6 +42,7 @@ var defaultAreaOptions = {
|
||||
datasetStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
datasetFill: true,
|
||||
animation: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
scaleLabel: " <%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
|
||||
@@ -68,6 +57,7 @@ var defaultPieOptions = {
|
||||
datasetStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
datasetFill: false,
|
||||
animation: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
tooltipFillColor: "rgba(0,0,0,0.5)",
|
||||
@@ -81,6 +71,7 @@ var defaultLineOptions = {
|
||||
pointDotRadius: 2,
|
||||
datasetStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
animation: false,
|
||||
datasetFill: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
@@ -98,6 +89,7 @@ var defaultColumnOptions = {
|
||||
datasetFill: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
animation: false,
|
||||
scaleLabel: "<%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
|
||||
tooltipFillColor: "rgba(0,0,0,0.5)",
|
||||
tooltipTemplate: "<%if (label){%><%=label%>: <%}%>" + currencySymbol + " <%= value %>",
|
||||
@@ -110,6 +102,7 @@ var defaultStackedColumnOptions = {
|
||||
barStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
datasetFill: false,
|
||||
animation: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
scaleLabel: "<%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
|
||||
@@ -147,7 +140,7 @@ function lineChart(URL, container, options) {
|
||||
new Chart(ctx).Line(newData, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
console.log('URL for line chart : ' + URL);
|
||||
}
|
||||
@@ -182,7 +175,7 @@ function areaChart(URL, container, options) {
|
||||
new Chart(ctx).Line(newData, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
|
||||
console.log('URL for area chart: ' + URL);
|
||||
@@ -218,7 +211,7 @@ function columnChart(URL, container, options) {
|
||||
new Chart(ctx).Bar(newData, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
console.log('URL for column chart : ' + URL);
|
||||
}
|
||||
@@ -253,7 +246,7 @@ function stackedColumnChart(URL, container, options) {
|
||||
new Chart(ctx).StackedBar(newData, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
console.log('URL for stacked column chart : ' + URL);
|
||||
}
|
||||
@@ -286,7 +279,7 @@ function pieChart(URL, container, options) {
|
||||
new Chart(ctx).Pie(data, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,44 +1,55 @@
|
||||
/* globals token, start, end, dateRangeURL, everything, firstDate, moment, currentMonthName, $, previousMonthName, nextMonthName, applyLabel, cancelLabel, toLabel, customRangeLabel, fromLabel, */
|
||||
/* globals token, dateRangeConfig, $, */
|
||||
$(function () {
|
||||
"use strict";
|
||||
$('.currencySelect').click(currencySelect);
|
||||
|
||||
var ranges = {};
|
||||
ranges[currentMonthName] = [moment().startOf('month'), moment().endOf('month')];
|
||||
ranges[previousMonthName] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
|
||||
ranges[nextMonthName] = [moment().add(1, 'month').startOf('month'), moment().add(1, 'month').endOf('month')];
|
||||
ranges[everything] = [firstDate, moment()];
|
||||
// range for the current month:
|
||||
ranges[dateRangeConfig.currentMonth] = [moment().startOf('month'), moment().endOf('month')];
|
||||
|
||||
$('#daterange').daterangepicker(
|
||||
// range for the previous month:
|
||||
ranges[dateRangeConfig.previousMonth] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
|
||||
|
||||
// range for the next month:
|
||||
ranges[dateRangeConfig.nextMonth] = [moment().add(1, 'month').startOf('month'), moment().add(1, 'month').endOf('month')];
|
||||
|
||||
// range for everything:
|
||||
ranges[dateRangeConfig.everything] = [dateRangeConfig.firstDate, moment()];
|
||||
|
||||
|
||||
// build the data range:
|
||||
$('#daterange').text(dateRangeConfig.linkTitle).daterangepicker(
|
||||
{
|
||||
ranges: ranges,
|
||||
opens: 'left',
|
||||
locale: {
|
||||
applyLabel: applyLabel,
|
||||
cancelLabel: cancelLabel,
|
||||
fromLabel: fromLabel,
|
||||
toLabel: toLabel,
|
||||
applyLabel: dateRangeConfig.applyLabel,
|
||||
cancelLabel: dateRangeConfig.cancelLabel,
|
||||
fromLabel: dateRangeConfig.fromLabel,
|
||||
toLabel: dateRangeConfig.toLabel,
|
||||
weekLabel: 'W',
|
||||
customRangeLabel: customRangeLabel,
|
||||
customRangeLabel: dateRangeConfig.customRangeLabel,
|
||||
daysOfWeek: moment.weekdaysMin(),
|
||||
monthNames: moment.monthsShort(),
|
||||
firstDay: moment.localeData()._week.dow
|
||||
},
|
||||
format: 'DD-MM-YYYY',
|
||||
startDate: start,
|
||||
endDate: end
|
||||
format: 'YYYY-MM-DD',
|
||||
startDate: dateRangeConfig.startDate,
|
||||
endDate: dateRangeConfig.endDate
|
||||
},
|
||||
function (start, end, label) {
|
||||
|
||||
// send post.
|
||||
$.post(dateRangeURL, {
|
||||
$.post(dateRangeConfig.URL, {
|
||||
start: start.format('YYYY-MM-DD'),
|
||||
end: end.format('YYYY-MM-DD'),
|
||||
label: label,
|
||||
_token: token
|
||||
}).success(function () {
|
||||
console.log('Succesfully sent new date range.');
|
||||
window.location.reload(true);
|
||||
}).fail(function () {
|
||||
console.log('Could not send new date range.');
|
||||
alert('Could not change date range');
|
||||
|
||||
});
|
||||
|
@@ -1,319 +0,0 @@
|
||||
/* globals currencyCode, language */
|
||||
/* exported lineChart, googleColumnChart, stackedColumnChart, comboChart, pieChart, defaultLineChartOptions, defaultAreaChartOptions, defaultBarChartOptions, defaultComboChartOptions, defaultColumnChartOptions, defaultStackedColumnChartOptions, defaultPieChartOptions */
|
||||
var google = google || {};
|
||||
google.load('visualization', '1.1', {'packages': ['corechart', 'bar', 'line'], 'language': language});
|
||||
|
||||
|
||||
/* exported */
|
||||
|
||||
var defaultLineChartOptions = {
|
||||
curveType: 'function',
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
interpolateNulls: true,
|
||||
lineWidth: 1,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '95%',
|
||||
height: '90%'
|
||||
},
|
||||
height: 400,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
fontSize: 11,
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
var defaultAreaChartOptions = {
|
||||
curveType: 'function',
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
interpolateNulls: true,
|
||||
lineWidth: 1,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '95%',
|
||||
height: '90%'
|
||||
},
|
||||
height: 400,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
fontSize: 11,
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
var defaultBarChartOptions = {
|
||||
height: 400,
|
||||
bars: 'horizontal',
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
|
||||
},
|
||||
fontSize: 11,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
textPosition: 'in',
|
||||
gridlines: {
|
||||
|
||||
color: 'transparent'
|
||||
},
|
||||
baselineColor: '#aaaaaa'
|
||||
},
|
||||
chartArea: {
|
||||
left: 15,
|
||||
top: 10,
|
||||
width: '100%',
|
||||
height: '90%'
|
||||
},
|
||||
|
||||
legend: {
|
||||
position: 'none'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultComboChartOptions = {
|
||||
height: 300,
|
||||
chartArea: {
|
||||
left: 75,
|
||||
top: 10,
|
||||
width: '100%',
|
||||
height: '90%'
|
||||
},
|
||||
vAxis: {
|
||||
minValue: 0,
|
||||
format: '\u20AC #'
|
||||
},
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
fontSize: 11,
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
series: {
|
||||
0: {type: 'line'},
|
||||
1: {type: 'line'},
|
||||
2: {type: 'bars'}
|
||||
},
|
||||
bar: {groupWidth: 20}
|
||||
};
|
||||
|
||||
var defaultColumnChartOptions = {
|
||||
height: 400,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '85%',
|
||||
height: '80%'
|
||||
},
|
||||
fontSize: 11,
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
},
|
||||
baselineColor: '#aaaaaa'
|
||||
|
||||
},
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
},
|
||||
legend: {
|
||||
position: 'none'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultStackedColumnChartOptions = {
|
||||
height: 400,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '85%',
|
||||
height: '80%'
|
||||
},
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
fontSize: 11,
|
||||
isStacked: true,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
format: '\u20AC #'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultPieChartOptions = {
|
||||
chartArea: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
},
|
||||
fontSize: 11,
|
||||
height: 200,
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
};
|
||||
|
||||
|
||||
function googleChart(chartType, URL, container, options) {
|
||||
"use strict";
|
||||
if ($('#' + container).length === 1) {
|
||||
$.getJSON(URL).success(function (data) {
|
||||
/*
|
||||
Get the data from the JSON
|
||||
*/
|
||||
var gdata = new google.visualization.DataTable(data);
|
||||
|
||||
/*
|
||||
Format as money
|
||||
*/
|
||||
var money = new google.visualization.NumberFormat({
|
||||
decimalSymbol: ',',
|
||||
groupingSymbol: '.',
|
||||
prefix: currencyCode + ' '
|
||||
});
|
||||
for (var i = 1; i < gdata.getNumberOfColumns(); i++) {
|
||||
money.format(gdata, i);
|
||||
}
|
||||
|
||||
/*
|
||||
Create a new google charts object.
|
||||
*/
|
||||
var chart = false;
|
||||
var options = false;
|
||||
if (chartType === 'line') {
|
||||
chart = new google.visualization.LineChart(document.getElementById(container));
|
||||
options = options || defaultLineChartOptions;
|
||||
}
|
||||
if (chartType === 'area') {
|
||||
chart = new google.visualization.AreaChart(document.getElementById(container));
|
||||
options = options || defaultAreaChartOptions;
|
||||
}
|
||||
|
||||
if (chartType === 'column') {
|
||||
chart = new google.visualization.ColumnChart(document.getElementById(container));
|
||||
options = options || defaultColumnChartOptions;
|
||||
}
|
||||
if (chartType === 'pie') {
|
||||
chart = new google.visualization.PieChart(document.getElementById(container));
|
||||
options = options || defaultPieChartOptions;
|
||||
}
|
||||
if (chartType === 'bar') {
|
||||
chart = new google.visualization.BarChart(document.getElementById(container));
|
||||
options = options || defaultBarChartOptions;
|
||||
}
|
||||
if (chartType === 'stackedColumn') {
|
||||
chart = new google.visualization.ColumnChart(document.getElementById(container));
|
||||
options = options || defaultStackedColumnChartOptions;
|
||||
}
|
||||
if (chartType === 'combo') {
|
||||
chart = new google.visualization.ComboChart(document.getElementById(container));
|
||||
options = options || defaultComboChartOptions;
|
||||
}
|
||||
|
||||
if (chart === false) {
|
||||
alert('Cannot draw chart of type "' + chartType + '".');
|
||||
} else {
|
||||
chart.draw(gdata, options);
|
||||
}
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
});
|
||||
} else {
|
||||
console.log('No container found called "' + container + '"');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function lineChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('line', URL, container, options);
|
||||
}
|
||||
|
||||
function areaChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('area', URL, container, options);
|
||||
}
|
||||
|
||||
function columnChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('column', URL, container, options);
|
||||
}
|
||||
|
||||
function stackedColumnChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('stackedColumn', URL, container, options);
|
||||
}
|
||||
|
||||
function comboChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('combo', URL, container, options);
|
||||
}
|
||||
|
||||
function pieChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('pie', URL, container, options);
|
||||
}
|
@@ -2,13 +2,8 @@
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof google !== 'undefined') {
|
||||
// do google charts:
|
||||
google.setOnLoadCallback(drawChart);
|
||||
} else {
|
||||
// do chart JS stuff.
|
||||
drawChart();
|
||||
}
|
||||
// do chart JS stuff.
|
||||
drawChart();
|
||||
if (showTour) {
|
||||
$.getJSON('json/tour').success(function (data) {
|
||||
var tour = new Tour(
|
||||
@@ -41,6 +36,7 @@ function drawChart() {
|
||||
pieChart('chart/bill/frontpage', 'bills-chart');
|
||||
stackedColumnChart('chart/budget/frontpage', 'budgets-chart');
|
||||
columnChart('chart/category/frontpage', 'categories-chart');
|
||||
columnChart('chart/account/expense', 'expense-accounts-chart');
|
||||
|
||||
|
||||
getBoxAmounts();
|
||||
@@ -51,7 +47,7 @@ function getBoxAmounts() {
|
||||
var boxes = ['in', 'out', 'bills-unpaid', 'bills-paid'];
|
||||
for (var x in boxes) {
|
||||
var box = boxes[x];
|
||||
$.getJSON('/json/box/' + box).success(putData).fail(failData);
|
||||
$.getJSON('json/box/' + box).success(putData).fail(failData);
|
||||
}
|
||||
}
|
||||
|
||||
|
6
public/js/moment.min.js
vendored
Normal file → Executable file
6
public/js/moment.min.js
vendored
Normal file → Executable file
File diff suppressed because one or more lines are too long
@@ -1,15 +1,12 @@
|
||||
/* globals $, lineChart, token, piggyBankID */
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
var fixHelper = function (e, tr) {
|
||||
var fixHelper = function (e, ui) {
|
||||
"use strict";
|
||||
var $originals = tr.children();
|
||||
var $helper = tr.clone();
|
||||
$helper.children().each(function (index) {
|
||||
// Set helper cell sizes to match the original sizes
|
||||
$(this).width($originals.eq(index).width());
|
||||
ui.children().each(function () {
|
||||
$(this).width($(this).width());
|
||||
});
|
||||
return $helper;
|
||||
return ui;
|
||||
};
|
||||
|
||||
$(function () {
|
||||
|
@@ -2,11 +2,7 @@
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(google) !== 'undefined') {
|
||||
google.setOnLoadCallback(drawChart);
|
||||
} else {
|
||||
drawChart();
|
||||
}
|
||||
drawChart();
|
||||
});
|
||||
|
||||
|
||||
@@ -18,7 +14,8 @@ function drawChart() {
|
||||
}
|
||||
if (typeof stackedColumnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
|
||||
stackedColumnChart('chart/budget/year/' + year + shared, 'budgets');
|
||||
stackedColumnChart('chart/category/year/' + year + shared, 'categories');
|
||||
stackedColumnChart('chart/category/spent-in-year/' + year + shared, 'categories-spent-in-year');
|
||||
stackedColumnChart('chart/category/earned-in-year/' + year + shared, 'categories-earned-in-year');
|
||||
}
|
||||
if (typeof lineChart !== 'undefined' && typeof month !== 'undefined') {
|
||||
lineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
|
||||
|
@@ -1,2 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow:
|
||||
Disallow: /
|
@@ -4,23 +4,15 @@ return [
|
||||
|
||||
// accounts
|
||||
'cash_accounts' => 'Cash accounts',
|
||||
'new_asset_account' => 'New asset accounts',
|
||||
'new_expense_account' => 'New expense account',
|
||||
'new_revenue_account' => 'New revenue account',
|
||||
'edit_account' => 'Edit account ":name"',
|
||||
|
||||
// categories
|
||||
'newCategory' => 'Create a new category',
|
||||
|
||||
// currencies
|
||||
'edit_currency' => 'Edit currencies ":name"',
|
||||
'delete_currency' => 'Delete currencies ":name"',
|
||||
|
||||
// piggy banks
|
||||
'piggyBanks' => 'Piggy banks',
|
||||
'newPiggyBank' => 'Create a new piggy bank',
|
||||
'edit_piggyBank' => 'Edit piggy bank ":name"',
|
||||
'delete_piggyBank' => 'Delete piggy bank ":name"',
|
||||
|
||||
// top menu
|
||||
'preferences' => 'Preferences',
|
||||
|
@@ -15,6 +15,8 @@ return [
|
||||
'cancel' => 'Cancel',
|
||||
'from' => 'From',
|
||||
'to' => 'To',
|
||||
'total_sum' => 'Total sum',
|
||||
'period_sum' => 'Sum for period',
|
||||
'showEverything' => 'Show everything',
|
||||
'never' => 'Never',
|
||||
'search_results_for' => 'Search results for ":query"',
|
||||
@@ -23,14 +25,22 @@ return [
|
||||
'removed_amount' => 'Removed :amount',
|
||||
'added_amount' => 'Added :amount',
|
||||
'asset_account_role_help' => 'Any extra options resulting from your choice can be set later.',
|
||||
'Opening balance' => 'Opening balance',
|
||||
'create_new_stuff' => 'Create new stuff',
|
||||
'new_withdrawal' => 'New withdrawal',
|
||||
'new_deposit' => 'New deposit',
|
||||
'new_transfer' => 'New transfer',
|
||||
'new_asset_account' => 'New asset account',
|
||||
'new_expense_account' => 'New expense account',
|
||||
'new_revenue_account' => 'New revenue account',
|
||||
'new_budget' => 'New budget',
|
||||
'new_bill' => 'New bill',
|
||||
|
||||
// tags
|
||||
'store_new_tag' => 'Store new tag',
|
||||
'update_tag' => 'Update tag',
|
||||
'no_location_set' => 'No location set.',
|
||||
'meta_data' => 'Meta data',
|
||||
'edit_tag' => 'Edit tag',
|
||||
'delete_tag' => 'Delete tag',
|
||||
'location' => 'Location',
|
||||
|
||||
// preferences
|
||||
@@ -117,16 +127,16 @@ return [
|
||||
'onto existing data in Firefly, use the checkbox. The next step will show you what this button does.',
|
||||
'csv_column_roles_table' => 'Column roles',
|
||||
'csv_column' => 'CSV column',
|
||||
'cvs_column_name' => 'CSV column name',
|
||||
'cvs_column_example' => 'Column example data',
|
||||
'cvs_column_role' => 'Column contains?',
|
||||
'csv_column_name' => 'CSV column name',
|
||||
'csv_column_example' => 'Column example data',
|
||||
'csv_column_role' => 'Column contains?',
|
||||
'csv_do_map_value' => 'Map value?',
|
||||
'csv_continue' => 'Continue to the next step',
|
||||
'csv_go_back' => 'Go back to the previous step',
|
||||
'csv_map_title' => 'Map found values to existing values',
|
||||
'csv_map_text' => 'This page allows you to map the values from the CSV file to existing entries in your ' .
|
||||
'database. This ensures that accounts and other things won\'t be created twice.',
|
||||
'cvs_field_value' => 'Field value from CSV',
|
||||
'csv_field_value' => 'Field value from CSV',
|
||||
'csv_field_mapped_to' => 'Must be mapped to...',
|
||||
'csv_do_not_map' => 'Do not map this value',
|
||||
'csv_download_config_title' => 'Download CSV configuration',
|
||||
@@ -140,8 +150,8 @@ return [
|
||||
'csv_unsupported_map' => 'The importer cannot map the column ":columnRole" to existing values in the database.',
|
||||
'csv_unsupported_value' => 'The importer does not know how to handle values in columns marked as ":columnRole".',
|
||||
'csv_cannot_store_value' => 'The importer has not reserved space for columns marked ":columnRole" and will be incapable of processing them.',
|
||||
'csv_process_title' => 'CVS import finished!',
|
||||
'csv_process_text' => 'The CVS importer has finished and has processed :rows rows',
|
||||
'csv_process_title' => 'CSV import finished!',
|
||||
'csv_process_text' => 'The CSV importer has finished and has processed :rows rows',
|
||||
'csv_row' => 'Row',
|
||||
'csv_import_with_errors' => 'There was one error.|There were :errors errors.',
|
||||
'csv_error_see_logs' => 'Check the log files to see details.',
|
||||
@@ -180,6 +190,7 @@ return [
|
||||
'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
|
||||
'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which'
|
||||
. ' account the transactions in the CSV belong to.',
|
||||
'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
|
||||
|
||||
|
||||
// create new stuff:
|
||||
@@ -396,12 +407,15 @@ return [
|
||||
'hideTheRest' => 'Show only the top :number',
|
||||
'sum_of_year' => 'Sum of year',
|
||||
'average_of_year' => 'Average of year',
|
||||
'categories_earned_in_year' => 'Categories (by earnings)',
|
||||
'categories_spent_in_year' => 'Categories (by spendings)',
|
||||
|
||||
// charts:
|
||||
'dayOfMonth' => 'Day of the month',
|
||||
'month' => 'Month',
|
||||
'budget' => 'Budget',
|
||||
'spent' => 'Spent',
|
||||
'earned' => 'Earned',
|
||||
'overspent' => 'Overspent',
|
||||
'left' => 'Left',
|
||||
'noBudget' => '(no budget)',
|
||||
@@ -452,7 +466,11 @@ return [
|
||||
'delete_piggy_bank' => 'Delete piggy bank ":name"',
|
||||
|
||||
// tags
|
||||
'delete_tag' => 'Delete tag ":name"',
|
||||
'regular_tag' => 'Just a regular tag.',
|
||||
'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
|
||||
'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
|
||||
|
||||
'delete_tag' => 'Delete tag ":tag"',
|
||||
'new_tag' => 'Make new tag',
|
||||
'edit_tag' => 'Edit tag ":tag"',
|
||||
'no_year' => 'No year set',
|
||||
|
@@ -73,7 +73,6 @@ return [
|
||||
'delete_budget' => 'Delete budget ":name"',
|
||||
'delete_category' => 'Delete category ":name"',
|
||||
'delete_currency' => 'Delete currency ":name"',
|
||||
'delete_piggyBank' => 'Delete piggy bank ":name"',
|
||||
'delete_journal' => 'Delete transaction with description ":description"',
|
||||
'delete_attachment' => 'Delete attachment ":name"',
|
||||
|
||||
|
@@ -4,23 +4,15 @@ return [
|
||||
|
||||
// accounts
|
||||
'cash_accounts' => 'Contant geldrekeningen',
|
||||
'new_asset_account' => 'Nieuwe betaalrekening',
|
||||
'new_expense_account' => 'Nieuwe crediteur',
|
||||
'new_revenue_account' => 'Nieuwe debiteur',
|
||||
'edit_account' => 'Wijzig rekening ":name"',
|
||||
|
||||
// categories
|
||||
'newCategory' => 'Maak een nieuw categorie',
|
||||
|
||||
// currencies
|
||||
'edit_currency' => 'Wijzig valuta ":name"',
|
||||
'delete_currency' => 'Verwijder valuta ":name"',
|
||||
|
||||
// piggy banks
|
||||
'piggyBanks' => 'Spaarpotjes',
|
||||
'newPiggyBank' => 'Nieuw spaarpotje',
|
||||
'edit_piggyBank' => 'Wijzig spaarpotje ":name"',
|
||||
'delete_piggyBank' => 'Verwijder spaarportje ":name"',
|
||||
|
||||
// top menu
|
||||
'preferences' => 'Voorkeuren',
|
||||
|
@@ -15,6 +15,8 @@ return [
|
||||
'cancel' => 'Annuleren',
|
||||
'from' => 'Van',
|
||||
'to' => 'Tot',
|
||||
'total_sum' => 'Totale som',
|
||||
'period_sum' => 'Som van periode',
|
||||
'showEverything' => 'Laat alles zien',
|
||||
'never' => 'Nooit',
|
||||
'search_results_for' => 'Zoekresultaten voor ":query"',
|
||||
@@ -23,6 +25,16 @@ return [
|
||||
'removed_amount' => ':amount weggehaald',
|
||||
'added_amount' => ':amount toegevoegd',
|
||||
'asset_account_role_help' => 'Voorkeuren die voortkomen uit je keuze hier kan je later aangeven.',
|
||||
'Opening balance' => 'Startsaldo',
|
||||
'create_new_stuff' => 'Nieuw',
|
||||
'new_withdrawal' => 'Nieuwe uitgave',
|
||||
'new_deposit' => 'Nieuwe inkomsten',
|
||||
'new_transfer' => 'Nieuwe overschrijving',
|
||||
'new_asset_account' => 'Nieuwe betaalrekening',
|
||||
'new_expense_account' => 'Nieuwe crediteur',
|
||||
'new_revenue_account' => 'Nieuwe debiteur',
|
||||
'new_budget' => 'Nieuw budget',
|
||||
'new_bill' => 'Nieuw contract',
|
||||
|
||||
// tags
|
||||
'store_new_tag' => 'Sla tag op',
|
||||
@@ -116,24 +128,24 @@ return [
|
||||
. ' die al in Firefly staan, gebruik dan het vinkje. Tijdens de volgende stap komt Firefly hier dan op terug.',
|
||||
'csv_column_roles_table' => 'Kolominhoud',
|
||||
'csv_column' => 'CSV-kolom',
|
||||
'cvs_column_name' => 'CSV-kolomnaam',
|
||||
'cvs_column_example' => 'Voorbeeldgegevens',
|
||||
'cvs_column_role' => 'Kolom bevat?',
|
||||
'csv_column_name' => 'CSV-kolomnaam',
|
||||
'csv_column_example' => 'Voorbeeldgegevens',
|
||||
'csv_column_role' => 'Kolom bevat?',
|
||||
'csv_do_map_value' => 'Directe relatie?',
|
||||
'csv_continue' => 'Naar de volgende stap',
|
||||
'csv_go_back' => 'Terug naar de vorige stap',
|
||||
'csv_map_title' => 'Leg relaties met kolomwaardes',
|
||||
'csv_map_text' => 'Sommige kolommen bevatten waardes die misschien al in Firefly bestaan. Selecteer hier de juiste combinaties'
|
||||
. 'zodat het importeren netjes aansluit bij je huidige gegevens.',
|
||||
'cvs_field_value' => 'Veldwaarde',
|
||||
'csv_field_value' => 'Veldwaarde',
|
||||
'csv_field_mapped_to' => 'Is gelijk aan',
|
||||
'csv_do_not_map' => 'Geen relatie',
|
||||
'csv_download_config_title' => 'Download importconfiguratie',
|
||||
'csv_download_config_text' => 'Firefly is klaar om je bestand te importeren. De instellingen en selecties die je zojuist hebt gemaakt kan je downloaden'
|
||||
. ' en opslaan. Bij de volgende keer kan je dit bestand ook uploaden. Als je kommagescheiden bestand dezelfde indeling'
|
||||
. ' heeft, zullen alle selecties goed staan. Dat scheelt weer!',
|
||||
'csv_more_information_text' => 'Ook als het importeren fout gaat is dit bestand handig. Na het importeren krijg je nogmaals de gelegenheid dit bestand'
|
||||
. 'te downloaden.',
|
||||
'csv_download_config_text' => 'Firefly is klaar om je bestand te importeren. De instellingen en selecties die je zojuist hebt gemaakt' .
|
||||
' kan je downloaden en opslaan. Bij de volgende keer kan je dit bestand ook uploaden. Als je' .
|
||||
' kommagescheiden bestand dezelfde indeling heeft, zullen alle selecties goed staan. Dat scheelt weer!',
|
||||
'csv_more_information_text' => 'Ook als het importeren fout gaat is dit bestand handig. Na het importeren krijg je nogmaals' .
|
||||
' de gelegenheid dit bestand te downloaden.',
|
||||
'csv_do_download_config' => 'Download het configuratiebestand',
|
||||
'csv_empty_description' => '(geen beschrijving)',
|
||||
'csv_upload_form' => 'CSV upload formulier',
|
||||
@@ -181,6 +193,8 @@ return [
|
||||
'csv_specifix_RabobankDescription' => 'Vink dit aan als je Rabobank bestanden importeert.',
|
||||
'csv_specifix_Dummy' => 'Dit vinkje doet niks (dummy).',
|
||||
'csv_import_account_help' => 'Als jouw CSV bestand geen referenties bevat naar jouw rekening(en), geef dan hier aan om welke rekening het gaat.',
|
||||
'csv_date_parse_error' => 'Kan geen chocola maken van ":value" (met hulp van configuratie ":format").' .
|
||||
' Weet je zeker dat je CSV bestand geen fouten bevat?',
|
||||
|
||||
// create new stuff:
|
||||
'create_new_withdrawal' => 'Nieuwe uitgave',
|
||||
@@ -376,8 +390,8 @@ return [
|
||||
// reports:
|
||||
'reportForYear' => 'Jaaroverzicht :year',
|
||||
'reportForYearShared' => 'Jaaroverzicht :year (inclusief gedeelde rekeningen)',
|
||||
'reportForMonth' => 'Maandoverzicht van :date',
|
||||
'reportForMonthShared' => 'Maandoverzicht van :date (inclusief gedeelde rekeningen)',
|
||||
'reportForMonth' => 'Maandoverzicht voor :month',
|
||||
'reportForMonthShared' => 'Maandoverzicht voor :month (inclusief gedeelde rekeningen)',
|
||||
'incomeVsExpenses' => 'Inkomsten tegenover uitgaven',
|
||||
'accountBalances' => 'Rekeningsaldi',
|
||||
'balanceStartOfYear' => 'Saldo aan het begin van het jaar',
|
||||
@@ -404,12 +418,15 @@ return [
|
||||
'topX' => 'top :number',
|
||||
'showTheRest' => 'Laat alles zien',
|
||||
'hideTheRest' => 'Laat alleen de top :number zien',
|
||||
'categories_earned_in_year' => 'Categorieën (inkomsten)',
|
||||
'categories_spent_in_year' => 'Categorieën (uitgaven)',
|
||||
|
||||
// charts:
|
||||
'dayOfMonth' => 'Dag vd maand',
|
||||
'month' => 'Maand',
|
||||
'budget' => 'Budget',
|
||||
'spent' => 'Uitgegeven',
|
||||
'earned' => 'Verdiend',
|
||||
'overspent' => 'Teveel uitgegeven',
|
||||
'left' => 'Over',
|
||||
'noBudget' => '(geen budget)',
|
||||
@@ -460,7 +477,10 @@ return [
|
||||
'delete_piggy_bank' => 'Verwijder spaarpotje ":name"',
|
||||
|
||||
// tags
|
||||
'delete_tag' => 'Verwijder tag ":name"',
|
||||
'regular_tag' => 'Een gewone tag.',
|
||||
'balancing_act' => 'Er kunnen maar twee transacties worden getagged; een uitgaven en inkomsten. Ze balanceren elkaar.',
|
||||
'advance_payment' => 'Je kan een uitgave taggen en zoveel inkomsten om de uitgave (helemaal) te compenseren.',
|
||||
'delete_tag' => 'Verwijder tag ":tag"',
|
||||
'new_tag' => 'Maak nieuwe tag',
|
||||
'edit_tag' => 'Wijzig tag ":tag"',
|
||||
'no_year' => 'Zonder jaar',
|
||||
|
@@ -74,7 +74,6 @@ return [
|
||||
'delete_budget' => 'Verwijder budget ":name"',
|
||||
'delete_category' => 'Verwijder categorie ":name"',
|
||||
'delete_currency' => 'Verwijder valuta ":name"',
|
||||
'delete_piggyBank' => 'Verwijder spaarpotje ":name"',
|
||||
'delete_journal' => 'Verwijder transactie met omschrijving ":description"',
|
||||
'delete_attachment' => 'Verwijder bijlage ":name"',
|
||||
|
||||
|
@@ -22,22 +22,27 @@
|
||||
{{ trans('form.account_areYouSure', {'name': account.name}) }}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% if account.transactions|length > 0 %}
|
||||
{{ Lang.choice('form.also_delete_transactions', account.transactions|length, {count: account.transactions|length}) }}
|
||||
{% endif %}<br/>
|
||||
{% if account.piggyBanks|length > 0 %}
|
||||
{{ Lang.choice('form.also_delete_piggyBanks', account.piggyBanks|length, {count: account.piggyBanks|length}) }}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% if account.transactions|length > 0 or account.piggyBanks|length > 0 %}
|
||||
<p>
|
||||
{% if account.transactions|length > 0 %}
|
||||
{{ Lang.choice('form.also_delete_transactions', account.transactions|length, {count: account.transactions|length}) }}
|
||||
{% endif %}<br/>
|
||||
{% if account.piggyBanks|length > 0 %}
|
||||
{{ Lang.choice('form.also_delete_piggyBanks', account.piggyBanks|length, {count: account.piggyBanks|length}) }}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if account.transactions|length > 0 %}
|
||||
<p class="text-success">
|
||||
{{ 'save_transactions_by_moving'|_ }}
|
||||
</p>
|
||||
|
||||
<p class="text-success">
|
||||
{{ 'save_transactions_by_moving'|_ }}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{{ Form.select('move_account_before_delete', accountList, null, {class: 'form-control'}) }}
|
||||
</p>
|
||||
<p>
|
||||
{{ Form.select('move_account_before_delete', accountList, null, {class: 'form-control'}) }}
|
||||
</p>
|
||||
{% else %}
|
||||
<input type="hidden" name="move_account_before_delete" value="0"/>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
|
53
resources/twig/auth/reset.twig
Normal file
53
resources/twig/auth/reset.twig
Normal file
@@ -0,0 +1,53 @@
|
||||
{% extends "./layout/guest.twig" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if errors|length > 0 %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>Whoops!</strong> There were some problems with your input.<br><br>
|
||||
<ul>
|
||||
{% for error in errors.all %}
|
||||
<li>{{ error }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
<div class="register-box-body">
|
||||
<p class="login-box-msg">Reset your password</p>
|
||||
|
||||
<form method="POST" action="/password/reset">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
<input type="hidden" name="token" value="{{ token }}">
|
||||
|
||||
<div class="form-group has-feedback">
|
||||
<input type="email" name="email" class="form-control" value="{{ old('email') }}" placeholder="Email"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group has-feedback">
|
||||
<input type="password" class="form-control" placeholder="Password" name="password"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group has-feedback">
|
||||
<input type="password" class="form-control" placeholder="Password (again)" name="password_confirmation"/>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<button type="submit" class="btn btn-primary pull-right btn-flat">Reset Password</button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<a href="{{ URL.to('/auth/login') }}">I want to login</a><br>
|
||||
{% if Config.get('auth.allow_register') %}
|
||||
<a href="{{ route('register') }}" class="text-center">Register a new account</a><br>
|
||||
{% endif %}
|
||||
</div><!-- /.form-box -->
|
||||
|
||||
{% endblock %}
|
@@ -23,9 +23,8 @@
|
||||
<small>{{ 'budgeted'|_ }}: <span id="budgetedAmount" class="text-success">{{ budgeted|formatAmountPlain }}</span></small>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-4 col-sm-3" style="text-align:right;">
|
||||
<small>{{ trans('firefly.availableIn',{date : Session.get('start').formatLocalized(monthFormat) }) }}:
|
||||
<a href="#" class="updateIncome"><span id="budgetIncomeTotal"
|
||||
data-value="{{ budgetIncomeTotal }}">{{ budgetIncomeTotal|formatAmount }}</span></a>
|
||||
<small>{{ trans('firefly.availableIn',{date : period }) }}:
|
||||
<a href="#" class="updateIncome"><span id="budgetIncomeTotal" data-value="{{ budgetIncomeTotal }}">{{ budgetIncomeTotal|formatAmount }}</span></a>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,7 +43,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-4 col-sm-3">
|
||||
<small>{{ 'spent'|_ }}: {{ spent|formatAmount }}</small>
|
||||
<small>{{ 'spent'|_ }}: <span class="text-danger">{{ (spent*-1)|formatAmountPlain }}</span></small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -77,11 +76,26 @@
|
||||
<div class="box-body">
|
||||
<p>
|
||||
<a href="{{ route('budgets.noBudget') }}">
|
||||
{{ trans('firefly.transactionsWithoutBudgetDate', {date: Session.get('start').formatLocalized(monthFormat)}) }}
|
||||
{{ trans('firefly.transactionsWithoutBudgetDate', {date: period|lower }) }}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'createBudget'|_ }}</h3>
|
||||
|
||||
<!-- ACTIONS MENU -->
|
||||
<div class="box-tools pull-right">
|
||||
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<a href="{{ route('budgets.create') }}" class="btn btn-success pull-right">{{ 'createBudget'|_ }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -130,28 +144,14 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:50%;">{{ 'spent'|_ }}</td>
|
||||
<td>{{ budget.spent|formatAmount }}</td>
|
||||
<td><span class="text-danger">{{ (budget.spent*-1)|formatAmountPlain }}</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="col-lg-3 col-sm-4 col-md-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'createBudget'|_ }}</h3>
|
||||
|
||||
<!-- ACTIONS MENU -->
|
||||
<div class="box-tools pull-right">
|
||||
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<a href="{{ route('budgets.create') }}" class="btn btn-success pull-right">{{ 'createBudget'|_ }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if inactive|length > 0 %}
|
||||
<div class="col-lg-3 col-sm-4 col-md-6">
|
||||
<div class="box">
|
||||
@@ -179,7 +179,7 @@
|
||||
{% block scripts %}
|
||||
<script type="text/javascript">
|
||||
// actually spent bar data:
|
||||
var spent = {{ spent }};
|
||||
var spent = {{ spent * -1 }};
|
||||
var currencySymbol = "{{ getCurrencySymbol()|raw }}";
|
||||
|
||||
// budgeted data:
|
||||
|
@@ -50,6 +50,7 @@
|
||||
|
||||
{% for limit in limits %}
|
||||
{% for rep in limit.limitRepetitions %}
|
||||
{% set spentInRep = (spentInRepetitionCorrected(rep)*-1) %}
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title"><a href="{{ route('budgets.show',[budget.id,rep.id]) }}">{{ rep.startdate.formatLocalized(monthFormat) }}</a>
|
||||
@@ -61,15 +62,15 @@
|
||||
{{ 'amount'|_ }}: {{ rep.amount|formatAmount }}
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-6 col-sm-6">
|
||||
{{ 'spent'|_ }}: {{ spentInRepetitionCorrected(rep)|formatAmount }}
|
||||
{{ 'spent'|_ }}: <span class="text-danger">{{ spentInRep|formatAmountPlain }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
{% set overspent = spentInRepetitionCorrected(rep) > rep.amount %}
|
||||
{% set overspent = spentInRep > rep.amount %}
|
||||
|
||||
{% if overspent %}
|
||||
{% set spent = spentInRepetitionCorrected(rep) %}
|
||||
{% set pct = (spent != 0 ? (rep.amount / spent)*100 : 0) %}
|
||||
{% set pct = (spentInRep != 0 ? (rep.amount / spentInRep)*100 : 0) %}
|
||||
<div class="progress progress-striped">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{ pct|round }}" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: {{ pct|round }}%;"></div>
|
||||
@@ -78,7 +79,7 @@
|
||||
</div>
|
||||
{% else %}
|
||||
{% set amount = rep.amount %}
|
||||
{% set pct = (amount != 0 ? (spentInRepetitionCorrected(rep) / amount)*100 : 0) %}
|
||||
{% set pct = (amount != 0 ? ((spentInRep / amount)*100) : 0) %}
|
||||
<div class="progress progress-striped">
|
||||
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="{{ pct|round }}" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: {{ pct|round }}%;"></div>
|
||||
|
@@ -13,10 +13,10 @@
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if Config.get('firefly.chart') == 'google' %}
|
||||
<div id="month"></div>
|
||||
<div id="period"></div>
|
||||
{% endif %}
|
||||
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||
<canvas id="month" style="width:100%;height:350px;"></canvas>
|
||||
<canvas id="period" style="width:100%;height:350px;"></canvas>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -38,7 +38,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<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-header with-border">
|
||||
@@ -49,6 +49,35 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-4 col-sm-12 col-xs-12">
|
||||
{% for entry in entries %}
|
||||
{% if entry[2] != 0 or entry[3] != 0 %}
|
||||
<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>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
62
resources/twig/categories/show_with_date.twig
Normal file
62
resources/twig/categories/show_with_date.twig
Normal file
@@ -0,0 +1,62 @@
|
||||
{% extends "./layout/default.twig" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, category, carbon) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<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">{{ 'overview'|_ }} (period)</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if Config.get('firefly.chart') == 'google' %}
|
||||
<div id="period-specific-period"></div>
|
||||
{% endif %}
|
||||
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||
<canvas id="period-specific-period" 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 }};
|
||||
var categoryDate = "{{ carbon.format('Y-m-d') }}";
|
||||
</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 %}
|
@@ -45,9 +45,9 @@
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th style="width:20%;">{{ 'cvs_column_name'|_ }}</th>
|
||||
<th style="width:40%;">{{ 'cvs_column_example'|_ }}</th>
|
||||
<th style="width:30%;">{{ 'cvs_column_role'|_ }}</th>
|
||||
<th style="width:20%;">{{ 'csv_column_name'|_ }}</th>
|
||||
<th style="width:40%;">{{ 'csv_column_example'|_ }}</th>
|
||||
<th style="width:30%;">{{ 'csv_column_role'|_ }}</th>
|
||||
<th style="width:10%;">{{ 'csv_do_map_value'|_ }}</th>
|
||||
</thead>
|
||||
{% for index,header in headers %}
|
||||
|
@@ -48,7 +48,7 @@
|
||||
<div class="box-body no-padding">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<th style="width:50%;">{{ 'cvs_field_value'|_ }}</th>
|
||||
<th style="width:50%;">{{ 'csv_field_value'|_ }}</th>
|
||||
<th>{{ 'csv_field_mapped_to'|_ }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@@ -1 +1 @@
|
||||
Click here to reset your password: {{ url('password/reset/' . token) }}
|
||||
Click here to reset your password: {{ url('password/reset/' ~ token) }}
|
@@ -19,7 +19,7 @@
|
||||
<ul>
|
||||
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
||||
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 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!
|
||||
|
@@ -12,7 +12,7 @@ Firefly III:
|
||||
{{ address }}
|
||||
|
||||
Password reset:
|
||||
{{ address }}password/email
|
||||
{{ address }}/password/email
|
||||
|
||||
Documentation:
|
||||
https://github.com/JC5/firefly-iii/wiki/First-use
|
||||
|
@@ -67,119 +67,6 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SAVINGS -->
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'savings'|_ }}</h3>
|
||||
|
||||
<div class="box-tools pull-right">
|
||||
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if savings|length == 0 %}
|
||||
<p class="small"><em>{{ 'markAsSavingsToContinue'|_ }}</em></p>
|
||||
{% else %}
|
||||
{% for account in savings %}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"><h5><a href="{{ route('accounts.show') }}">{{ account.name }}</a></h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- start -->
|
||||
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.startBalance|formatAmount }}</div>
|
||||
<!-- bar -->
|
||||
<div class="col-lg-8 col-md-8 col-sm-6 col-xs-4">
|
||||
{% if account.difference < 0 %}
|
||||
<!-- green (100-pct), then red (pct) -->
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: {{ 100 - account.percentage }}%">
|
||||
{% if account.percentage <= 50 %}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-danger" style="width: {{ account.percentage }}%">
|
||||
{% if account.percentage > 50 %}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<!-- green (pct), then blue (100-pct) -->
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: {{ account.percentage }}%">
|
||||
{% if account.percentage <= 50 %}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-info" style="width: {{ 100 - account.percentage }}%">
|
||||
{% if account.percentage > 50 %}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<!-- end -->
|
||||
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.endBalance|formatAmount }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="box-footer clearfix">
|
||||
<span class="pull-right">{{ 'sum'|_ }}: {{ savingsTotal|formatAmount }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PIGGY BANKS -->
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'piggyBanks'|_ }}</h3>
|
||||
|
||||
<div class="box-tools pull-right">
|
||||
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if piggyBankAccounts|length == 0 %}
|
||||
<p class="small"><em>{{ 'createPiggyToContinue'|_ }}</em></p>
|
||||
{% else %}
|
||||
{% for account in piggyBankAccounts %}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"><h5><a href="{{ route('accounts.show') }}">{{ account.name }}</a></h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- start -->
|
||||
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.startBalance|formatAmount }}</div>
|
||||
<!-- bar -->
|
||||
<div class="col-lg-8 col-md-8 col-sm-6 col-xs-4">
|
||||
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-info progress-bar" style="width: {{ 100 - account.percentage }}%">
|
||||
{% if account.percentage <= 50 %}
|
||||
{{ account.piggyBalance|formatAmountPlain }} {{ 'divided'|_ }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-success progress-bar" style="width: {{ account.percentage }}%">
|
||||
{% if account.percentage > 50 %}
|
||||
{{ account.difference|formatAmountPlain }} {{ 'toDivide'|_ }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end -->
|
||||
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.piggyBalance|formatAmount }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-6 col-sm-12">
|
||||
|
||||
@@ -237,6 +124,143 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<!-- EXPENSE ACCOUNTS -->
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'expense_accounts'|_ }}</h3>
|
||||
|
||||
<div class="box-tools pull-right">
|
||||
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if Config.get('firefly.chart') == 'google' %}
|
||||
<div id="expense-accounts-chart"></div>
|
||||
{% endif %}
|
||||
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||
<canvas id="expense-accounts-chart" style="width:100%;height:400px;"></canvas>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-sm-12 col-md-12">
|
||||
<!-- SAVINGS -->
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'savings'|_ }}</h3>
|
||||
|
||||
<div class="box-tools pull-right">
|
||||
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if savings|length == 0 %}
|
||||
<p class="small"><em>{{ 'markAsSavingsToContinue'|_ }}</em></p>
|
||||
{% else %}
|
||||
{% for account in savings %}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"><h5><a href="{{ route('accounts.show', account.id) }}">{{ account.name }}</a></h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- start -->
|
||||
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.startBalance|formatAmount }}</div>
|
||||
<!-- bar -->
|
||||
<div class="col-lg-8 col-md-8 col-sm-6 col-xs-4">
|
||||
{% if account.difference < 0 %}
|
||||
<!-- green (100-pct), then red (pct) -->
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: {{ 100 - account.percentage }}%">
|
||||
{% if account.percentage <= 50 %}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-danger" style="width: {{ account.percentage }}%">
|
||||
{% if account.percentage > 50 %}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<!-- green (pct), then blue (100-pct) -->
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: {{ account.percentage }}%">
|
||||
{% if account.percentage <= 50 %}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-info" style="width: {{ 100 - account.percentage }}%">
|
||||
{% if account.percentage > 50 %}
|
||||
{{ account.difference|formatAmountPlain }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<!-- end -->
|
||||
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.endBalance|formatAmount }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="box-footer clearfix">
|
||||
<span class="pull-right">{{ 'sum'|_ }}: {{ savingsTotal|formatAmount }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-sm-12 col-md-12">
|
||||
<!-- PIGGY BANKS -->
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'piggyBanks'|_ }}</h3>
|
||||
|
||||
<div class="box-tools pull-right">
|
||||
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if piggyBankAccounts|length == 0 %}
|
||||
<p class="small"><em>{{ 'createPiggyToContinue'|_ }}</em></p>
|
||||
{% else %}
|
||||
{% for account in piggyBankAccounts %}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"><h5><a href="{{ route('accounts.show', account.id) }}">{{ account.name }}</a></h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- start -->
|
||||
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.startBalance|formatAmount }}</div>
|
||||
<!-- bar -->
|
||||
<div class="col-lg-8 col-md-8 col-sm-6 col-xs-4">
|
||||
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-info progress-bar" style="width: {{ 100 - account.percentage }}%">
|
||||
{% if account.percentage <= 50 %}
|
||||
{{ account.piggyBalance|formatAmountPlain }} {{ 'divided'|_ }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-success progress-bar" style="width: {{ account.percentage }}%">
|
||||
{% if account.percentage > 50 %}
|
||||
{{ account.difference|formatAmountPlain }} {{ 'toDivide'|_ }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end -->
|
||||
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.piggyBalance|formatAmount }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="robots" content="noindex, nofolllow, noarchive, noodp, NoImageIndex, noydir">
|
||||
<title>Firefly
|
||||
{% if title != "Firefly" %}
|
||||
// {{ title }}
|
||||
@@ -12,12 +13,13 @@
|
||||
{% endif %}
|
||||
</title>
|
||||
<base href="{{ route('index') }}/">
|
||||
|
||||
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
||||
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="dist/css/skins/skin-blue-light.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="css/daterangepicker-bs3.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="css/daterangepicker.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="css/firefly.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="css/bootstrap-tour.min.css" rel="stylesheet" type="text/css"/>
|
||||
|
||||
@@ -58,17 +60,17 @@
|
||||
|
||||
<!-- Messages: style can be found in dropdown.less-->
|
||||
<li>
|
||||
<a href="#">
|
||||
<span style="color:#fff;padding: 15px;display: block;line-height: 20px;">
|
||||
<span class="hidden-xs" id="daterange"></span>
|
||||
</a>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
<!-- Notifications: style can be found in dropdown.less -->
|
||||
<!-- User Account: style can be found in dropdown.less -->
|
||||
<li class="dropdown user user-menu">
|
||||
<a href="#">
|
||||
<span style="cursor:default;color:#fff;padding: 15px;display: block;line-height: 20px;">
|
||||
<span class="hidden-xs">{{ Auth.user.email }}</span>
|
||||
</a>
|
||||
</span>
|
||||
</li>
|
||||
<li id="sidebar-toggle">
|
||||
<a href="#" data-toggle="control-sidebar"><i class="fa fa-plus-circle"></i></a>
|
||||
@@ -159,56 +161,64 @@
|
||||
<script src="js/bootstrap-tour.min.js" type="text/javascript"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var start = "{{Session.get('start').format('d-m-Y')}}";
|
||||
var end = "{{Session.get('end').format('d-m-Y')}}";
|
||||
var titleString = "{{Session.get('start').formatLocalized(monthAndDayFormat)}} - {{Session.get('end').formatLocalized(monthAndDayFormat)}}";
|
||||
var dateRangeURL = "{{route('daterange')}}";
|
||||
|
||||
// date range picker configuration:
|
||||
var dateRangeConfig = {
|
||||
startDate: moment("{{Session.get('start').format('Y-m-d')}}"),
|
||||
endDate: moment("{{Session.get('end').format('Y-m-d')}}"),
|
||||
linkTitle: "{{Session.get('start').formatLocalized(monthAndDayFormat)}} - {{Session.get('end').formatLocalized(monthAndDayFormat)}}",
|
||||
URL: "{{route('daterange')}}",
|
||||
firstDate: moment("{{Session.get('first').format('Y-m-d')}}"),
|
||||
currentMonth: "{{ currentMonthName }}",
|
||||
previousMonth: "{{ previousMonthName }}",
|
||||
nextMonth: "{{ nextMonthName }}",
|
||||
everything: '{{ 'everything'|_ }}',
|
||||
customRangeLabel: '{{ 'customRange'|_ }}',
|
||||
applyLabel: '{{ 'apply'|_ }}',
|
||||
cancelLabel: '{{ 'cancel'|_ }}',
|
||||
fromLabel: '{{ 'from'|_ }}',
|
||||
toLabel: '{{ 'to'|_ }}'
|
||||
};
|
||||
|
||||
var token = "{{csrf_token()}}";
|
||||
var firstDate = moment("{{Session.get('first').format('Y-m-d')}}");
|
||||
var currentMonthName = "{{ currentMonthName }}";
|
||||
var previousMonthName = "{{ previousMonthName }}";
|
||||
var language = "{{ language }}";
|
||||
|
||||
// translations:
|
||||
var everything = '{{ 'everything'|_ }}';
|
||||
var customRangeLabel = '{{ 'customRange'|_ }}';
|
||||
var applyLabel = '{{ 'apply'|_ }}';
|
||||
var cancelLabel = '{{ 'cancel'|_ }}';
|
||||
var fromLabel = '{{ 'from'|_ }}';
|
||||
var toLabel = '{{ 'to'|_ }}';
|
||||
|
||||
var nextMonthName = "{{ nextMonthName }}";
|
||||
var currencyCode = '{{getCurrencyCode() }}';
|
||||
var currencySymbol = '{{getCurrencySymbol()|raw }}';
|
||||
$('#daterange').text(titleString);
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="js/firefly.js"></script>
|
||||
<script type="text/javascript" src="js/help.js"></script>
|
||||
{% block scripts %}{% endblock %}
|
||||
|
||||
<script>
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', {'siteSpeedSampleRate': 100});
|
||||
ga('send', 'pageview');
|
||||
// send an event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and not Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
|
||||
{% endif %}
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}', '{{ Session.get('gaEventLabel') }}');
|
||||
{% endif %}
|
||||
</script>
|
||||
{% if env('ANALYTICS_ID','') != '' %}
|
||||
<script>
|
||||
// send pageview
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', {'siteSpeedSampleRate': 100});
|
||||
ga('send', 'pageview');
|
||||
|
||||
// send an event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and not Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
|
||||
{% endif %}
|
||||
|
||||
// send event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}', '{{ Session.get('gaEventLabel') }}');
|
||||
{% endif %}
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -2,6 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="robots" content="noindex, nofolllow, noarchive, noodp, NoImageIndex, noydir">
|
||||
<title>Firefly III</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
||||
@@ -47,27 +48,33 @@
|
||||
<script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
|
||||
|
||||
<script>
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', {'siteSpeedSampleRate': 100});
|
||||
ga('send', 'pageview');
|
||||
// send an event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and not Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
|
||||
{% endif %}
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}', '{{ Session.get('gaEventLabel') }}');
|
||||
{% endif %}
|
||||
</script>
|
||||
{% if env('ANALYTICS_ID','') != '' %}
|
||||
<script>
|
||||
// send pageview
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', {'siteSpeedSampleRate': 100});
|
||||
ga('send', 'pageview');
|
||||
|
||||
// send an event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and not Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
|
||||
{% endif %}
|
||||
|
||||
// send event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}', '{{ Session.get('gaEventLabel') }}');
|
||||
{% endif %}
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -2,6 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="robots" content="noindex, nofolllow, noarchive, noodp, NoImageIndex, noydir">
|
||||
<title>Firefly III</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
|
||||
@@ -48,27 +49,33 @@
|
||||
<script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
|
||||
|
||||
<script>
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', {'siteSpeedSampleRate': 100});
|
||||
ga('send', 'pageview');
|
||||
// send an event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and not Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
|
||||
{% endif %}
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}', '{{ Session.get('gaEventLabel') }}');
|
||||
{% endif %}
|
||||
</script>
|
||||
{% if env('ANALYTICS_ID','') != '' %}
|
||||
<script>
|
||||
// send pageview
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', {'siteSpeedSampleRate': 100});
|
||||
ga('send', 'pageview');
|
||||
|
||||
// send an event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and not Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
|
||||
{% endif %}
|
||||
|
||||
// send event if relevant:
|
||||
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and Session.has('gaEventLabel') %}
|
||||
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}', '{{ Session.get('gaEventLabel') }}');
|
||||
{% endif %}
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
{{ journals.render|raw }}
|
||||
|
||||
<table class="table table-hover sortable sortable-table">
|
||||
<table class="table table-hover {% if sorting %}sortable-table{% endif %}">
|
||||
<thead>
|
||||
<tr class="ignore">
|
||||
<th class="hidden-xs" colspan="2"> </th>
|
||||
<th>{{ trans('list.description') }}</th>
|
||||
@@ -23,6 +24,9 @@
|
||||
<th class="hidden-xs"><i class="fa fa-fw fa-rotate-right" title="{{ trans('list.bill') }}"></i></th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% set _sum = 0 %}
|
||||
{% for journal in journals %}
|
||||
{% if invalidJournal(journal) %}
|
||||
<tr class="ignore">
|
||||
@@ -36,6 +40,7 @@
|
||||
<td colspan="7"><em>Invalid journal: Found {{ journal.transactions|length }} transaction(s)</em></td>
|
||||
</tr>
|
||||
{% else %}
|
||||
{% set _sum = _sum + journal.amount %}
|
||||
<tr class="drag" data-date="{{ journal.date.format('Y-m-d') }}" data-id="{{ journal.id }}">
|
||||
<td class="hidden-xs">
|
||||
<div class="btn-group btn-group-xs">
|
||||
@@ -59,11 +64,7 @@
|
||||
|
||||
</td>
|
||||
<td>
|
||||
{% if not hideTags %}
|
||||
{{ relevantTags(journal)|raw }}
|
||||
{% else %}
|
||||
{{ journal.correct_amount|formatAmount }}
|
||||
{% endif %}
|
||||
{{ journal.amount|formatAmount }}
|
||||
</td>
|
||||
<td class="hidden-sm hidden-xs">
|
||||
{{ journal.date.formatLocalized(monthAndDayFormat) }}
|
||||
@@ -111,8 +112,28 @@
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
{% if showPageSum %}
|
||||
<tr>
|
||||
<td colspan="3" style="text-align: right;"><em>{{ 'sum'|_ }}</em></td>
|
||||
<td colspan="2">{{ _sum|formatAmount }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if showPeriodSum %}
|
||||
<tr>
|
||||
<td colspan="3" style="text-align: right;"><em>{{ 'period_sum'|_ }}</em></td>
|
||||
<td colspan="2">{{ periodSum|formatAmount }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if showTotalSum %}
|
||||
<tr>
|
||||
<td colspan="3" style="text-align: right;"><em>{{ 'total_sum'|_ }}</em></td>
|
||||
<td colspan="2">{{ totalSum|formatAmount }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
{{ journals.render|raw }}
|
||||
|
@@ -4,14 +4,14 @@
|
||||
<div class="tab-content">
|
||||
<!-- Home tab content -->
|
||||
<div class="tab-panel active" id="control-sidebar-home-tab">
|
||||
<h3 class="control-sidebar-heading">Create new stuff</h3>
|
||||
<h3 class="control-sidebar-heading">{{ 'create_new_stuff'|_ }}</h3>
|
||||
<ul class='control-sidebar-menu'>
|
||||
<li>
|
||||
<a href="{{ route('transactions.create', 'withdrawal') }}">
|
||||
<i class="menu-icon fa fa-long-arrow-left bg-red"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">New withdrawal</h4>
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_withdrawal'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@@ -20,7 +20,7 @@
|
||||
<i class="menu-icon fa fa-long-arrow-right bg-green"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">New deposit</h4>
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_deposit'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@@ -29,7 +29,7 @@
|
||||
<i class="menu-icon fa fa-exchange bg-blue"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">New transfer</h4>
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_transfer'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@@ -38,7 +38,7 @@
|
||||
<i class="menu-icon fa fa-money bg-maroon"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">New asset account</h4>
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_asset_account'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@@ -47,7 +47,7 @@
|
||||
<i class="menu-icon fa fa-shopping-cart bg-maroon"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">New expense account</h4>
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_expense_account'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@@ -56,16 +56,47 @@
|
||||
<i class="menu-icon fa fa-download bg-maroon"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">New revenue</h4>
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_revenue_account'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{{ route('budgets.create') }}">
|
||||
<i class="menu-icon fa fa-download bg-red"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_budget'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{{ route('categories.create') }}">
|
||||
<i class="menu-icon fa fa-download bg-red"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_category'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{{ route('accounts.create', 'revenue') }}">
|
||||
<i class="menu-icon fa fa-download bg-maroon"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_revenue_account'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{{ route('piggy-banks.create') }}">
|
||||
<i class="menu-icon fa fa-sort-amount-asc bg-teal"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">New piggy bank</h4>
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_piggy_bank'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
@@ -74,7 +105,7 @@
|
||||
<i class="menu-icon fa fa-download bg-purple"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">New bill</h4>
|
||||
<h4 class="control-sidebar-subheading">{{ 'new_bill'|_ }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<tr>
|
||||
<th>{{ 'name'|_ }}</th>
|
||||
<th>{{ 'balanceStart'|_ }}</th>
|
||||
<th>{{ 'balanceStart'|_ }}</th>
|
||||
<th>{{ 'balanceEnd'|_ }}</th>
|
||||
<th>{{ 'difference'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@@ -16,14 +16,14 @@
|
||||
<td>
|
||||
<a href="{{ route('categories.show',cat.id) }}">{{ cat.name }}</a>
|
||||
</td>
|
||||
<td><span class="text-danger">{{ (cat.spent)|formatAmountPlain }}</span></td>
|
||||
<td><span class="text-danger">{{ (cat.spent * -1)|formatAmountPlain }}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td><em>{{ 'sum'|_ }}</em></td>
|
||||
<td class="text-danger">{{ categories.getTotal|formatAmountPlain }}</td>
|
||||
<td class="text-danger">{{ (categories.getTotal * -1)|formatAmountPlain }}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<div class="col-lg-6 col-lg-offset-3 col-md-12 col-sm-12">
|
||||
<div class="box box-danger">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ trans('form.delete_piggyBank', {'name': piggyBank.name}) }}</h3>
|
||||
<h3 class="box-title">{{ trans('firefly.delete_piggy_bank', {'name': piggyBank.name}) }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<p class="text-danger">
|
||||
|
@@ -56,19 +56,38 @@
|
||||
<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_spent_in_year'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if Config.get('firefly.chart') == 'google' %}
|
||||
<div id="categories"></div>
|
||||
<div id="categories-spent-in-year"></div>
|
||||
{% endif %}
|
||||
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||
<canvas id="categories" style="width:100%;height:400px;"></canvas>
|
||||
<canvas id="categories-spent-in-year" style="width:100%;height:400px;"></canvas>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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_earned_in_year'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if Config.get('firefly.chart') == 'google' %}
|
||||
<div id="categories-earned-in-year"></div>
|
||||
{% endif %}
|
||||
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||
<canvas id="categories-earned-in-year" style="width:100%;height:400px;"></canvas>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box">
|
||||
|
@@ -19,8 +19,8 @@
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown"><i class="fa fa-ellipsis-v"></i></button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{ route('tags.edit',tag.id) }}"><i class="fa fa-pencil fa-fw"></i> {{ 'edit_tag'|_ }}</a></li>
|
||||
<li><a href="{{ route('tags.delete',tag.id) }}"><i class="fa fa-trash fa-fw"></i> {{ 'delete_tag'|_ }}</a></li>
|
||||
<li><a href="{{ route('tags.edit',tag.id) }}"><i class="fa fa-pencil fa-fw"></i> {{ trans('firefly.edit_tag',{tag: tag.tag}) }}</a></li>
|
||||
<li><a href="{{ route('tags.delete',tag.id) }}"><i class="fa fa-trash fa-fw"></i> {{ trans('firefly.delete_tag',{tag: tag.tag}) }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -50,8 +50,8 @@
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown"><i class="fa fa-ellipsis-v"></i></button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{ route('tags.edit',tag.id) }}"><i class="fa fa-pencil fa-fw"></i> {{ 'edit_tag'|_ }}</a></li>
|
||||
<li><a href="{{ route('tags.delete',tag.id) }}"><i class="fa fa-trash fa-fw"></i> {{ 'delete_tag'|_ }}</a></li>
|
||||
<li><a href="{{ route('tags.edit',tag.id) }}"><i class="fa fa-pencil fa-fw"></i> {{ trans('firefly.edit_tag',{tag: tag.tag}) }}</a></li>
|
||||
<li><a href="{{ route('tags.delete',tag.id) }}"><i class="fa fa-trash fa-fw"></i> {{ trans('firefly.delete_tag',{tag: tag.tag}) }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,14 +80,14 @@
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown"><i class="fa fa-ellipsis-v"></i></button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{ route('tags.edit',tag.id) }}"><i class="fa fa-pencil fa-fw"></i> {{ 'edit_tag'|_ }}</a></li>
|
||||
<li><a href="{{ route('tags.delete',tag.id) }}"><i class="fa fa-trash fa-fw"></i> {{ 'delete_tag'|_ }}</a></li>
|
||||
<li><a href="{{ route('tags.edit',tag.id) }}"><i class="fa fa-pencil fa-fw"></i> {{ trans('firefly.edit_tag',{tag: tag.tag}) }}</a></li>
|
||||
<li><a href="{{ route('tags.delete',tag.id) }}"><i class="fa fa-trash fa-fw"></i> {{ trans('firefly.delete_tag',{tag: tag.tag}) }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body table-responsive no-padding">
|
||||
{% include 'list/journals.twig' with {'journals': tag.transactionjournals} %}
|
||||
{% include 'list/journals.twig' with {'journals': tag.transactionjournals, 'showPageSum' : true} %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user