mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-21 10:41:22 +00:00
Compare commits
179 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d485270e1f | ||
|
|
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 | ||
|
|
b318f3f940 | ||
|
|
e211c9812e | ||
|
|
eef28d96f4 | ||
|
|
c8227e09ee | ||
|
|
3e05fd91d9 | ||
|
|
450baba56a | ||
|
|
17a8c4918c | ||
|
|
0e2419d61a | ||
|
|
79b1a2ca6d | ||
|
|
2213c68155 | ||
|
|
2492b1fa96 | ||
|
|
6c6598dac5 | ||
|
|
a137112e66 | ||
|
|
8642ae8180 | ||
|
|
894c4dc5a7 | ||
|
|
d96063ea6e | ||
|
|
c3dc193f3e | ||
|
|
3c2952009e | ||
|
|
f4ade470df | ||
|
|
2e33b43389 | ||
|
|
92799699bc | ||
|
|
7ab0508167 | ||
|
|
3c65c28936 | ||
|
|
43892da07e | ||
|
|
7c436920a4 | ||
|
|
89d565e63b | ||
|
|
150b6fe5b6 | ||
|
|
0e77574c26 | ||
|
|
df23863443 | ||
|
|
581bf11b21 | ||
|
|
d602d4b429 | ||
|
|
d1d4a52934 | ||
|
|
375d113769 | ||
|
|
9b83974bff | ||
|
|
3c68c99bd5 | ||
|
|
ec4b37c596 | ||
|
|
ba9601d21c | ||
|
|
50c13fd469 | ||
|
|
7af072b8fc | ||
|
|
faa128d41e | ||
|
|
868fe46932 | ||
|
|
e9e4307ce5 | ||
|
|
774d4844a9 | ||
|
|
586c53e670 | ||
|
|
68e073fbff | ||
|
|
8101dc37b1 | ||
|
|
63f16c458d | ||
|
|
821e007e95 | ||
|
|
1656a2f11a | ||
|
|
4dbc135dce | ||
|
|
fc886f6bc1 | ||
|
|
f93e480466 | ||
|
|
fe807e23f8 | ||
|
|
ecf61c31f1 | ||
|
|
4feff18af5 | ||
|
|
a07c52e0d8 | ||
|
|
7bb07d7f55 | ||
|
|
f12dfc8a14 | ||
|
|
be030f15c4 | ||
|
|
f5fb6c063b | ||
|
|
fb722f06b9 | ||
|
|
c0ea19e15e | ||
|
|
cdeb1ad87c | ||
|
|
0dbe4e94fa | ||
|
|
b5e2e8aa1d | ||
|
|
9502010248 | ||
|
|
fea0557b47 | ||
|
|
ed4fcc9011 | ||
|
|
ed12ea7cfb | ||
|
|
73e526645e | ||
|
|
72aeafb2b5 | ||
|
|
cc1af60cb4 | ||
|
|
359fab315f | ||
|
|
6a9574bab9 | ||
|
|
83d6158483 | ||
|
|
63ef89b6cc | ||
|
|
b0beab4cd3 | ||
|
|
a34782575f | ||
|
|
142bdc9430 | ||
|
|
14b79cb0a4 | ||
|
|
ce5beeaf2c | ||
|
|
31114a2ca5 | ||
|
|
32528094ad | ||
|
|
0a2a01c44c | ||
|
|
c1888dc3ac | ||
|
|
4d76afbe01 | ||
|
|
76d7a97f93 | ||
|
|
8b1366b20a | ||
|
|
e0f9685578 | ||
|
|
5235657954 | ||
|
|
a15fbc8094 | ||
|
|
546f1d9c50 | ||
|
|
74231f552a | ||
|
|
b250a10e3c | ||
|
|
a9f1b31dd6 | ||
|
|
7fe393acaf | ||
|
|
04faba4db5 | ||
|
|
91bba40c20 | ||
|
|
79e39f7de8 | ||
|
|
9c09353559 | ||
|
|
50752a5bfe | ||
|
|
d59879db7d | ||
|
|
aab125da27 | ||
|
|
74fc731f96 | ||
|
|
bd0050fec2 | ||
|
|
aa5e313b92 | ||
|
|
e89d613b7e | ||
|
|
8757929ead | ||
|
|
e0a9b19802 | ||
|
|
308da6dc6e | ||
|
|
b6960fb0e5 | ||
|
|
137208c3fd | ||
|
|
d7a9a62a1d | ||
|
|
075315bdaa | ||
|
|
3948fcd614 | ||
|
|
8e61e129ab | ||
|
|
20cffd0502 | ||
|
|
5df09dab09 | ||
|
|
7446b911e5 | ||
|
|
f15267c1ab | ||
|
|
9c9fc2b5dc | ||
|
|
28f601b54b | ||
|
|
18b8a05014 | ||
|
|
910c995ed8 | ||
|
|
498468aa2c | ||
|
|
637aebcb34 | ||
|
|
9afd5cb277 | ||
|
|
bc525e7272 | ||
|
|
a80180780d | ||
|
|
0d73086c37 | ||
|
|
02ae39238d | ||
|
|
43d6b51d42 | ||
|
|
84566310de | ||
|
|
6a6ec9fbe4 | ||
|
|
84a7f825d7 | ||
|
|
0372c1aaf1 | ||
|
|
c9fff197f7 | ||
|
|
6900392e43 | ||
|
|
c00bcd78cc | ||
|
|
3de57c668f |
@@ -1,6 +1,6 @@
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_KEY=SomeRandomString
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
@@ -19,3 +19,6 @@ ANALYTICS_ID=
|
||||
EMAIL_PRETEND=false
|
||||
RUNCLEANUP=true
|
||||
SITE_OWNER=mail@example.com
|
||||
|
||||
SENDGRID_USERNAME=
|
||||
SENDGRID_PASSWORD=
|
||||
@@ -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
|
||||
|
||||
@@ -90,6 +90,7 @@ Firefly III uses the following libraries and tools:
|
||||
|
||||
* The AdminLTE template by [Almsaseed Studio](https://almsaeedstudio.com/)
|
||||
* The [Google charts](https://developers.google.com/chart/) library.
|
||||
* [Chart.js](http://www.chartjs.org/)
|
||||
* [Bootstrap](http://getbootstrap.com/)
|
||||
* [Laravel](http://laravel.com/)
|
||||
* [Twig](http://twig.sensiolabs.org/)
|
||||
|
||||
@@ -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,65 @@ 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)
|
||||
{
|
||||
// language:
|
||||
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => trans('firefly.spent'),
|
||||
'data' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
$ids = [];
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
$ids[] = $account->id;
|
||||
}
|
||||
$start->subDay();
|
||||
|
||||
$startBalances = Steam::balancesById($ids, $start);
|
||||
$endBalances = Steam::balancesById($ids, $end);
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($startBalances, $endBalances) {
|
||||
$id = $account->id;
|
||||
$startBalance = isset($startBalances[$id]) ? $startBalances[$id] : 0;
|
||||
$endBalance = isset($endBalances[$id]) ? $endBalances[$id] : 0;
|
||||
$diff = $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 Collection $accounts
|
||||
* @param Carbon $start
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class ChartJsBillChartGenerator implements BillChartGenerator
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) { // loop unpaid:
|
||||
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
|
||||
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$amount = bcdiv(bcadd($entry[0]->amount_max, $entry[0]->amount_min), 2);
|
||||
$unpaidDescriptions[] = $description;
|
||||
$unpaidAmount = bcadd($unpaidAmount, $amount);
|
||||
unset($amount, $description);
|
||||
|
||||
@@ -1,93 +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 = ($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,
|
||||
floatval($bill->amount_max),
|
||||
floatval($bill->amount_min),
|
||||
floatval($result->amount));
|
||||
}
|
||||
|
||||
$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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -29,19 +29,30 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
||||
$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[0]->formatLocalized($format);
|
||||
$amount = round($entry[1], 2);
|
||||
if ($amount > 0) {
|
||||
$data['datasets'][0]['data'][] = null;
|
||||
$data['datasets'][1]['data'][] = $amount;
|
||||
} else {
|
||||
$data['datasets'][0]['data'][] = $amount * -1;
|
||||
$data['datasets'][1]['data'][] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
@@ -93,7 +104,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
|
||||
*/
|
||||
@@ -26,7 +26,7 @@ class ChartJsPiggyBankChartGenerator implements PiggyBankChartGenerator
|
||||
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.month.' . $language);
|
||||
$format = Config::get('firefly.monthAndDay.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 1,
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -61,7 +61,7 @@ class ChartJsReportChartGenerator implements ReportChartGenerator
|
||||
|
||||
$data = [
|
||||
'count' => 2,
|
||||
'labels' => [],
|
||||
'labels' => [trans('firefly.sum_of_year'), trans('firefly.average_of_year')],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => trans('firefly.income'),
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use App;
|
||||
use FireflyIII\Events\JournalSaved;
|
||||
use Log;
|
||||
|
||||
@@ -36,7 +35,7 @@ class RescanJournal
|
||||
Log::debug('Triggered saved event for journal #' . $journal->id . ' (' . $journal->description . ')');
|
||||
|
||||
/** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface');
|
||||
$repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface');
|
||||
$list = $journal->user->bills()->where('active', 1)->where('automatch', 1)->get();
|
||||
|
||||
Log::debug('Found ' . $list->count() . ' bills to check.');
|
||||
|
||||
@@ -49,10 +49,12 @@ class UpdateJournalConnection
|
||||
if (is_null($repetition)) {
|
||||
return;
|
||||
}
|
||||
$amount = $journal->amount;
|
||||
$diff = $amount - $event->amount; // update current repetition
|
||||
bcscale(2);
|
||||
|
||||
$repetition->currentamount += $diff;
|
||||
$amount = $journal->amount;
|
||||
$diff = bcsub($amount, $event->amount); // update current repetition
|
||||
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $diff);
|
||||
$repetition->save();
|
||||
|
||||
|
||||
|
||||
222
app/Helpers/Attachments/AttachmentHelper.php
Normal file
222
app/Helpers/Attachments/AttachmentHelper.php
Normal file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Attachments;
|
||||
|
||||
use Auth;
|
||||
use Config;
|
||||
use Crypt;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Input;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
/**
|
||||
* Class AttachmentHelper
|
||||
*
|
||||
* @package FireflyIII\Helpers\Attachments
|
||||
*/
|
||||
class AttachmentHelper implements AttachmentHelperInterface
|
||||
{
|
||||
|
||||
/** @var int */
|
||||
protected $maxUploadSize;
|
||||
/** @var array */
|
||||
protected $allowedMimes;
|
||||
/** @var MessageBag */
|
||||
public $errors;
|
||||
/** @var MessageBag */
|
||||
public $messages;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->maxUploadSize = Config::get('firefly.maxUploadSize');
|
||||
$this->allowedMimes = Config::get('firefly.allowedMimes');
|
||||
$this->errors = new MessageBag;
|
||||
$this->messages = new MessageBag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAttachmentLocation(Attachment $attachment)
|
||||
{
|
||||
$path = storage_path('upload') . DIRECTORY_SEPARATOR . 'at-' . $attachment->id . '.data';
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveAttachmentsForModel(Model $model)
|
||||
{
|
||||
$files = Input::file('attachments');
|
||||
|
||||
if (is_array($files)) {
|
||||
foreach ($files as $entry) {
|
||||
if (!is_null($entry)) {
|
||||
$this->processFile($entry, $model);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->processFile($files, $model);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UploadedFile $file
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasFile(UploadedFile $file, Model $model)
|
||||
{
|
||||
$md5 = md5_file($file->getRealPath());
|
||||
$name = $file->getClientOriginalName();
|
||||
$class = get_class($model);
|
||||
$count = Auth::user()->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count();
|
||||
|
||||
if ($count > 0) {
|
||||
$msg = trans('validation.file_already_attached', ['name' => $name]);
|
||||
$this->errors->add('attachments', $msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UploadedFile $file
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateUpload(UploadedFile $file, Model $model)
|
||||
{
|
||||
if (!$this->validMime($file)) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->validSize($file)) {
|
||||
return false;
|
||||
}
|
||||
if ($this->hasFile($file, $model)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UploadedFile $file
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool|Attachment
|
||||
*/
|
||||
protected function processFile(UploadedFile $file, Model $model)
|
||||
{
|
||||
$validation = $this->validateUpload($file, $model);
|
||||
if ($validation === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$attachment = new Attachment; // create Attachment object.
|
||||
$attachment->user()->associate(Auth::user());
|
||||
$attachment->attachable()->associate($model);
|
||||
$attachment->md5 = md5_file($file->getRealPath());
|
||||
$attachment->filename = $file->getClientOriginalName();
|
||||
$attachment->mime = $file->getMimeType();
|
||||
$attachment->size = $file->getSize();
|
||||
$attachment->uploaded = 0;
|
||||
$attachment->save();
|
||||
|
||||
$path = $file->getRealPath(); // encrypt and move file to storage.
|
||||
$content = file_get_contents($path);
|
||||
$encrypted = Crypt::encrypt($content);
|
||||
|
||||
// store it:
|
||||
$upload = $this->getAttachmentLocation($attachment);
|
||||
if (is_writable(dirname($upload))) {
|
||||
file_put_contents($upload, $encrypted);
|
||||
}
|
||||
|
||||
$attachment->uploaded = 1; // update attachment
|
||||
$attachment->save();
|
||||
|
||||
$name = e($file->getClientOriginalName()); // add message:
|
||||
$msg = trans('validation.file_attached', ['name' => $name]);
|
||||
$this->messages->add('attachments', $msg);
|
||||
|
||||
// return it.
|
||||
return $attachment;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UploadedFile $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function validMime(UploadedFile $file)
|
||||
{
|
||||
$mime = e($file->getMimeType());
|
||||
$name = e($file->getClientOriginalName());
|
||||
|
||||
if (!in_array($mime, $this->allowedMimes)) {
|
||||
$msg = trans('validation.file_invalid_mime', ['name' => $name, 'mime' => $mime]);
|
||||
$this->errors->add('attachments', $msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UploadedFile $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function validSize(UploadedFile $file)
|
||||
{
|
||||
$size = $file->getSize();
|
||||
$name = e($file->getClientOriginalName());
|
||||
if ($size > $this->maxUploadSize) {
|
||||
$msg = trans('validation.file_too_large', ['name' => $name]);
|
||||
$this->errors->add('attachments', $msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MessageBag
|
||||
*/
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MessageBag
|
||||
*/
|
||||
public function getMessages()
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
41
app/Helpers/Attachments/AttachmentHelperInterface.php
Normal file
41
app/Helpers/Attachments/AttachmentHelperInterface.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Attachments;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\MessageBag;
|
||||
|
||||
/**
|
||||
* Interface AttachmentHelperInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Attachments
|
||||
*/
|
||||
interface AttachmentHelperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveAttachmentsForModel(Model $model);
|
||||
|
||||
/**
|
||||
* @return MessageBag
|
||||
*/
|
||||
public function getErrors();
|
||||
|
||||
/**
|
||||
* @return MessageBag
|
||||
*/
|
||||
public function getMessages();
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttachmentLocation(Attachment $attachment);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class AccountId
|
||||
@@ -19,9 +20,17 @@ class AccountId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
|
||||
/** @var Account $account */
|
||||
$account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
|
||||
/** @var Account $account */
|
||||
$account = Auth::user()->accounts()->find($this->value);
|
||||
|
||||
if (!is_null($account)) {
|
||||
Log::debug('Found ' . $account->accountType->type . ' named "******" with ID: ' . $this->value . ' (not mapped) ');
|
||||
}
|
||||
}
|
||||
|
||||
return $account;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface
|
||||
/** @var Account $account */
|
||||
foreach ($set as $account) {
|
||||
if ($account->iban == $this->value) {
|
||||
Log::debug('OpposingAccountIban::convert found an Account (#' . $account->id . ': ' . $account->name . ') with IBAN ' . $this->value);
|
||||
Log::debug('OpposingAccountIban::convert found an Account (#' . $account->id . ': ******) with IBAN ******');
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
@@ -25,16 +25,19 @@ class Data
|
||||
protected $hasHeaders;
|
||||
|
||||
/** @var array */
|
||||
protected $map;
|
||||
protected $map = [];
|
||||
/** @var array */
|
||||
protected $mapped;
|
||||
protected $mapped = [];
|
||||
/** @var Reader */
|
||||
protected $reader;
|
||||
/** @var array */
|
||||
protected $roles;
|
||||
protected $roles = [];
|
||||
|
||||
/** @var array */
|
||||
protected $specifix;
|
||||
protected $specifix = [];
|
||||
|
||||
/** @var int */
|
||||
protected $importAccount = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -48,6 +51,7 @@ class Data
|
||||
$this->sessionRoles();
|
||||
$this->sessionMapped();
|
||||
$this->sessionSpecifix();
|
||||
$this->sessionImportAccount();
|
||||
}
|
||||
|
||||
protected function sessionHasHeaders()
|
||||
@@ -57,6 +61,13 @@ class Data
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionImportAccount()
|
||||
{
|
||||
if (Session::has('csv-import-account')) {
|
||||
$this->importAccount = intval(Session::get('csv-import-account'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionDateFormat()
|
||||
{
|
||||
if (Session::has('csv-date-format')) {
|
||||
@@ -116,6 +127,15 @@ class Data
|
||||
$this->dateFormat = $dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $importAccount
|
||||
*/
|
||||
public function setImportAccount($importAccount)
|
||||
{
|
||||
Session::put('csv-import-account', $importAccount);
|
||||
$this->importAccount = $importAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
@@ -247,7 +267,7 @@ class Data
|
||||
*/
|
||||
public function getSpecifix()
|
||||
{
|
||||
return $this->specifix;
|
||||
return is_array($this->specifix) ? $this->specifix : [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
|
||||
namespace FireflyIII\Helpers\Csv;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Config;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Converter\ConverterInterface;
|
||||
use FireflyIII\Helpers\Csv\PostProcessing\PostProcessorInterface;
|
||||
use FireflyIII\Helpers\Csv\Specifix\SpecifixInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Log;
|
||||
|
||||
@@ -42,7 +43,10 @@ class Importer
|
||||
/** @var int */
|
||||
protected $rows = 0;
|
||||
/** @var array */
|
||||
protected $specifix;
|
||||
protected $specifix = [];
|
||||
|
||||
/** @var Collection */
|
||||
protected $journals;
|
||||
|
||||
/**
|
||||
* Used by CsvController.
|
||||
@@ -74,6 +78,15 @@ class Importer
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournals()
|
||||
{
|
||||
return $this->journals;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
@@ -81,6 +94,7 @@ class Importer
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
$this->journals = new Collection;
|
||||
$this->map = $this->data->getMap();
|
||||
$this->roles = $this->data->getRoles();
|
||||
$this->mapped = $this->data->getMapped();
|
||||
@@ -88,14 +102,17 @@ class Importer
|
||||
|
||||
foreach ($this->data->getReader() as $index => $row) {
|
||||
if ($this->parseRow($index)) {
|
||||
Log::debug('--- Importing row ' . $index);
|
||||
$this->rows++;
|
||||
$result = $this->importRow($row);
|
||||
if (!($result === true)) {
|
||||
if (!($result instanceof TransactionJournal)) {
|
||||
Log::error('Caught error at row #' . $index . ': ' . $result);
|
||||
$this->errors[$index] = $result;
|
||||
} else {
|
||||
$this->imported++;
|
||||
$this->journals->push($result);
|
||||
}
|
||||
Log::debug('---');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,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());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,14 +135,17 @@ class Importer
|
||||
*/
|
||||
protected function importRow($row)
|
||||
{
|
||||
|
||||
$data = $this->getFiller(); // These fields are necessary to create a new transaction journal. Some are optional
|
||||
foreach ($row as $index => $value) {
|
||||
$role = isset($this->roles[$index]) ? $this->roles[$index] : '_ignore';
|
||||
$class = Config::get('csv.roles.' . $role . '.converter');
|
||||
$field = Config::get('csv.roles.' . $role . '.field');
|
||||
|
||||
Log::debug('Column #' . $index . ' (role: ' . $role . ') : converter ' . $class . ' stores its data into field ' . $field . ':');
|
||||
|
||||
/** @var ConverterInterface $converter */
|
||||
$converter = App::make('FireflyIII\Helpers\Csv\Converter\\' . $class);
|
||||
$converter = app('FireflyIII\Helpers\Csv\Converter\\' . $class);
|
||||
$converter->setData($data); // the complete array so far.
|
||||
$converter->setField($field);
|
||||
$converter->setIndex($index);
|
||||
@@ -133,7 +153,6 @@ class Importer
|
||||
$converter->setValue($value);
|
||||
$converter->setRole($role);
|
||||
$data[$field] = $converter->convert();
|
||||
|
||||
}
|
||||
// move to class vars.
|
||||
$this->importData = $data;
|
||||
@@ -147,11 +166,8 @@ class Importer
|
||||
return $result; // return error.
|
||||
}
|
||||
$journal = $this->createTransactionJournal();
|
||||
if ($journal instanceof TransactionJournal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,6 +185,7 @@ class Importer
|
||||
// some extra's:
|
||||
$filler['bill-id'] = null;
|
||||
$filler['opposing-account-object'] = null;
|
||||
$filler['asset-account-object'] = null;
|
||||
$filler['amount-modifier'] = '1';
|
||||
|
||||
return $filler;
|
||||
@@ -186,9 +203,10 @@ class Importer
|
||||
|
||||
foreach ($this->getSpecifix() as $className) {
|
||||
/** @var SpecifixInterface $specifix */
|
||||
$specifix = App::make('FireflyIII\Helpers\Csv\Specifix\\' . $className);
|
||||
$specifix = app('FireflyIII\Helpers\Csv\Specifix\\' . $className);
|
||||
$specifix->setData($this->importData);
|
||||
$specifix->setRow($this->importRow);
|
||||
Log::debug('Now post-process specifix named ' . $className . ':');
|
||||
$this->importData = $specifix->fix();
|
||||
}
|
||||
|
||||
@@ -196,8 +214,9 @@ class Importer
|
||||
$set = Config::get('csv.post_processors');
|
||||
foreach ($set as $className) {
|
||||
/** @var PostProcessorInterface $postProcessor */
|
||||
$postProcessor = App::make('FireflyIII\Helpers\Csv\PostProcessing\\' . $className);
|
||||
$postProcessor = app('FireflyIII\Helpers\Csv\PostProcessing\\' . $className);
|
||||
$postProcessor->setData($this->importData);
|
||||
Log::debug('Now post-process processor named ' . $className . ':');
|
||||
$this->importData = $postProcessor->process();
|
||||
}
|
||||
|
||||
@@ -208,7 +227,7 @@ class Importer
|
||||
*/
|
||||
public function getSpecifix()
|
||||
{
|
||||
return $this->specifix;
|
||||
return is_array($this->specifix) ? $this->specifix : [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,6 +243,10 @@ class Importer
|
||||
return 'Opposing account is null';
|
||||
}
|
||||
|
||||
if (!($this->importData['asset-account-object'] instanceof Account)) {
|
||||
return 'No asset account to import into.';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -238,6 +261,8 @@ class Importer
|
||||
if (is_null($this->importData['date'])) {
|
||||
$date = $this->importData['date-rent'];
|
||||
}
|
||||
|
||||
|
||||
$transactionType = $this->getTransactionType(); // defaults to deposit
|
||||
$errors = new MessageBag;
|
||||
$journal = TransactionJournal::create(
|
||||
@@ -245,10 +270,13 @@ class Importer
|
||||
'description' => $this->importData['description'], 'completed' => 0, 'date' => $date, 'bill_id' => $this->importData['bill-id'],]
|
||||
);
|
||||
if ($journal->getErrors()->count() == 0) {
|
||||
$accountId = $this->importData['asset-account']->id; // create first transaction:
|
||||
// first transaction
|
||||
$accountId = $this->importData['asset-account-object']->id; // create first transaction:
|
||||
$amount = $this->importData['amount'];
|
||||
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
|
||||
$errors = $transaction->getErrors();
|
||||
|
||||
// second transaction
|
||||
$accountId = $this->importData['opposing-account-object']->id; // create second transaction:
|
||||
$amount = bcmul($this->importData['amount'], -1);
|
||||
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
|
||||
@@ -266,6 +294,18 @@ class Importer
|
||||
$this->saveCategory($journal);
|
||||
$this->saveTags($journal);
|
||||
|
||||
// some debug info:
|
||||
$journalId = $journal->id;
|
||||
$type = $journal->transactionType->type;
|
||||
/** @var Account $asset */
|
||||
$asset = $this->importData['asset-account-object'];
|
||||
/** @var Account $opposing */
|
||||
$opposing = $this->importData['opposing-account-object'];
|
||||
|
||||
Log::info('Created journal #' . $journalId . ' of type ' . $type . '!');
|
||||
Log::info('Asset account ****** (#' . $asset->id . ') lost/gained: ' . $this->importData['amount']);
|
||||
Log::info($opposing->accountType->type . ' ****** (#' . $opposing->id . ') lost/gained: ' . bcmul($this->importData['amount'], -1));
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class AnyAccount implements MapperInterface
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class AssetAccount implements MapperInterface
|
||||
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class Bill implements MapperInterface
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class Budget implements MapperInterface
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class Category implements MapperInterface
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class Tag implements MapperInterface
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class TransactionCurrency implements MapperInterface
|
||||
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
185
app/Helpers/Csv/PostProcessing/AssetAccount.php
Normal file
185
app/Helpers/Csv/PostProcessing/AssetAccount.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use Log;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* Class AssetAccount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class AssetAccount implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
$result = $this->checkIdNameObject(); // has object in ID or Name?
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $this->checkIbanString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $this->checkNameString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function checkIdNameObject()
|
||||
{
|
||||
if ($this->data['asset-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any
|
||||
$this->data['asset-account-object'] = $this->data['asset-account-id'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if ($this->data['asset-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any.
|
||||
$this->data['asset-account-object'] = $this->data['asset-account-iban'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkIbanString()
|
||||
{
|
||||
$rules = ['iban' => 'iban'];
|
||||
$check = ['iban' => $this->data['asset-account-iban']];
|
||||
$validator = Validator::make($check, $rules);
|
||||
if (!$validator->fails()) {
|
||||
$this->data['asset-account-object'] = $this->parseIbanString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function parseIbanString()
|
||||
{
|
||||
// create by name and/or iban.
|
||||
$accounts = Auth::user()->accounts()->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->iban == $this->data['asset-account-iban']) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
$account = $this->createAccount();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function createAccount()
|
||||
{
|
||||
$accountType = $this->getAccountType();
|
||||
|
||||
// create if not exists:
|
||||
$name = is_string($this->data['asset-account-name']) && strlen($this->data['asset-account-name']) > 0 ? $this->data['asset-account-name']
|
||||
: $this->data['asset-account-iban'];
|
||||
$account = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $name,
|
||||
'iban' => $this->data['asset-account-iban'],
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return AccountType
|
||||
*/
|
||||
protected function getAccountType()
|
||||
{
|
||||
return AccountType::where('type', 'Asset account')->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkNameString()
|
||||
{
|
||||
if ($this->data['asset-account-name'] instanceof Account) { // third: try to find account based on name, if any.
|
||||
$this->data['asset-account-object'] = $this->data['asset-account-name'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if (is_string($this->data['asset-account-name'])) {
|
||||
$this->data['asset-account-object'] = $this->parseNameString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function parseNameString()
|
||||
{
|
||||
$accountType = $this->getAccountType();
|
||||
$accounts = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->name == $this->data['asset-account-name']) {
|
||||
Log::debug('Found an asset account with this name (#' . $entry->id . ': ******)');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
// create if not exists:
|
||||
$account = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $this->data['asset-account-name'],
|
||||
'iban' => '',
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,10 @@ class OpposingAccount implements PostProcessorInterface
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
// three values:
|
||||
// opposing-account-id, opposing-account-iban, opposing-account-name
|
||||
|
||||
|
||||
$result = $this->checkIdNameObject();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
@@ -56,11 +60,13 @@ class OpposingAccount implements PostProcessorInterface
|
||||
protected function checkIdNameObject()
|
||||
{
|
||||
if ($this->data['opposing-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any
|
||||
Log::debug('OpposingAccountPostProcession: opposing-account-id is an Account.');
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-id'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if ($this->data['opposing-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any.
|
||||
Log::debug('OpposingAccountPostProcession: opposing-account-iban is an Account.');
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-iban'];
|
||||
|
||||
return $this->data;
|
||||
@@ -75,9 +81,12 @@ class OpposingAccount implements PostProcessorInterface
|
||||
protected function checkIbanString()
|
||||
{
|
||||
$rules = ['iban' => 'iban'];
|
||||
$check = ['iban' => $this->data['opposing-account-iban']];
|
||||
$iban = $this->data['opposing-account-iban'];
|
||||
$check = ['iban' => $iban];
|
||||
$validator = Validator::make($check, $rules);
|
||||
if (!$validator->fails()) {
|
||||
if (is_string($iban) && strlen($iban) > 0 && !$validator->fails()) {
|
||||
|
||||
Log::debug('OpposingAccountPostProcession: opposing-account-iban is a string (******).');
|
||||
$this->data['opposing-account-object'] = $this->parseIbanString();
|
||||
|
||||
return $this->data;
|
||||
@@ -95,12 +104,14 @@ class OpposingAccount implements PostProcessorInterface
|
||||
$accounts = Auth::user()->accounts()->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->iban == $this->data['opposing-account-iban']) {
|
||||
Log::debug('OpposingAccountPostProcession: opposing-account-iban matches an Account.');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
$account = $this->createAccount();
|
||||
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
@@ -123,6 +134,7 @@ class OpposingAccount implements PostProcessorInterface
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
Log::debug('OpposingAccountPostProcession: created a new account.');
|
||||
|
||||
return $account;
|
||||
}
|
||||
@@ -153,11 +165,13 @@ class OpposingAccount implements PostProcessorInterface
|
||||
protected function checkNameString()
|
||||
{
|
||||
if ($this->data['opposing-account-name'] instanceof Account) { // third: try to find account based on name, if any.
|
||||
Log::debug('OpposingAccountPostProcession: opposing-account-name is an Account.');
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-name'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if (is_string($this->data['opposing-account-name'])) {
|
||||
|
||||
$this->data['opposing-account-object'] = $this->parseNameString();
|
||||
|
||||
return $this->data;
|
||||
@@ -175,7 +189,7 @@ class OpposingAccount implements PostProcessorInterface
|
||||
$accounts = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->name == $this->data['opposing-account-name']) {
|
||||
Log::debug('Found an account with this name (#' . $entry->id . ': ' . $entry->name . ')');
|
||||
Log::debug('Found an account with this name (#' . $entry->id . ': ******)');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Specifix;
|
||||
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RabobankDescription
|
||||
*
|
||||
@@ -32,10 +34,16 @@ class RabobankDescription
|
||||
*/
|
||||
protected function rabobankFixEmptyOpposing()
|
||||
{
|
||||
if (strlen($this->data['opposing-account-name']) == 0) {
|
||||
Log::debug('RaboSpecifix: Opposing account name is "******".');
|
||||
if (is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) == 0) {
|
||||
Log::debug('RaboSpecifix: opp-name is zero length, changed to: "******"');
|
||||
$this->data['opposing-account-name'] = $this->row[10];
|
||||
|
||||
Log::debug('Description was: "******".');
|
||||
$this->data['description'] = trim(str_replace($this->row[10], '', $this->data['description']));
|
||||
Log::debug('Description is now: "******".');
|
||||
}
|
||||
$this->data['description'] = trim(str_replace($this->row[10], '', $this->data['description']));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?php
|
||||
namespace FireflyIII\Helpers\Csv;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Config;
|
||||
use Crypt;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Mapper\MapperInterface;
|
||||
use League\Csv\Reader;
|
||||
use Log;
|
||||
use ReflectionException;
|
||||
use Session;
|
||||
|
||||
@@ -45,9 +45,7 @@ class Wizard implements WizardInterface
|
||||
/*
|
||||
* Make each one unique.
|
||||
*/
|
||||
foreach ($values as $column => $found) {
|
||||
$values[$column] = array_unique($found);
|
||||
}
|
||||
$values = $this->uniqueRecursive($values);
|
||||
|
||||
return $values;
|
||||
}
|
||||
@@ -112,6 +110,8 @@ class Wizard implements WizardInterface
|
||||
{
|
||||
foreach ($fields as $field) {
|
||||
if (!Session::has($field)) {
|
||||
Log::error('Session is missing field: ' . $field);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ class Wizard implements WizardInterface
|
||||
$class = 'FireflyIII\Helpers\Csv\Mapper\\' . $mapper;
|
||||
try {
|
||||
/** @var MapperInterface $mapObject */
|
||||
$mapObject = App::make($class);
|
||||
$mapObject = app($class);
|
||||
} catch (ReflectionException $e) {
|
||||
throw new FireflyException('Column "' . $columnRole . '" cannot be mapped because class ' . $mapper . ' does not exist.');
|
||||
}
|
||||
@@ -177,4 +177,18 @@ class Wizard implements WizardInterface
|
||||
{
|
||||
return ($hasHeaders && $index > 1) || !$hasHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function uniqueRecursive(array $array)
|
||||
{
|
||||
foreach ($array as $column => $found) {
|
||||
$array[$column] = array_unique($found);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collection\Account as AccountCollection;
|
||||
use FireflyIII\Helpers\Collection\Balance;
|
||||
@@ -80,7 +79,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
foreach ($accounts as $account) {
|
||||
$start = bcadd($start, $account->startBalance);
|
||||
$end = bcadd($end, $account->endBalance);
|
||||
$diff = bcadd($diff, ($account->endBalance - $account->startBalance));
|
||||
$diff = bcadd($diff, bcsub($account->endBalance, $account->startBalance));
|
||||
}
|
||||
|
||||
$object = new AccountCollection;
|
||||
@@ -115,8 +114,8 @@ class ReportHelper implements ReportHelperInterface
|
||||
*/
|
||||
public function getBalanceReport(Carbon $start, Carbon $end, $shared)
|
||||
{
|
||||
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
|
||||
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
|
||||
$repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
|
||||
$tagRepository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface');
|
||||
$balance = new Balance;
|
||||
|
||||
// build a balance header:
|
||||
@@ -200,15 +199,15 @@ class ReportHelper implements ReportHelperInterface
|
||||
* This method generates a full report for the given period on all
|
||||
* the users bills and their payments.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return BillCollection
|
||||
*/
|
||||
public function getBillReport(Carbon $start, Carbon $end)
|
||||
{
|
||||
/** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface');
|
||||
$repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface');
|
||||
$bills = $repository->getBills();
|
||||
$collection = new BillCollection;
|
||||
|
||||
@@ -253,16 +252,18 @@ class ReportHelper implements ReportHelperInterface
|
||||
{
|
||||
$object = new BudgetCollection;
|
||||
/** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
|
||||
$repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
|
||||
$set = $repository->getBudgets();
|
||||
|
||||
bcscale(2);
|
||||
|
||||
foreach ($set as $budget) {
|
||||
|
||||
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
|
||||
|
||||
// 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);
|
||||
@@ -277,10 +278,10 @@ class ReportHelper implements ReportHelperInterface
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setBudget($budget);
|
||||
$budgetLine->setRepetition($repetition);
|
||||
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, $shared);
|
||||
$left = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0;
|
||||
$spent = $expenses > floatval($repetition->amount) ? 0 : $expenses;
|
||||
$overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0;
|
||||
$expenses = $repository->balanceInPeriod($budget, $repetition->startdate, $repetition->enddate, $shared);
|
||||
$left = $expenses < $repetition->amount ? bcsub($repetition->amount, $expenses) : 0;
|
||||
$spent = $expenses > $repetition->amount ? 0 : $expenses;
|
||||
$overspent = $expenses > $repetition->amount ? bcsub($expenses, $repetition->amount) : 0;
|
||||
|
||||
$budgetLine->setLeft($left);
|
||||
$budgetLine->setSpent($spent);
|
||||
@@ -323,10 +324,10 @@ class ReportHelper implements ReportHelperInterface
|
||||
* GET CATEGORIES:
|
||||
*/
|
||||
/** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Category\CategoryRepositoryInterface');
|
||||
$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);
|
||||
|
||||
@@ -35,8 +35,8 @@ interface ReportHelperInterface
|
||||
* This method generates a full report for the given period on all
|
||||
* the users bills and their payments.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return BillCollection
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,11 @@ use Steam;
|
||||
class ReportQuery implements ReportQueryInterface
|
||||
{
|
||||
/**
|
||||
* See ReportQueryInterface::incomeInPeriodCorrected
|
||||
* See ReportQueryInterface::incomeInPeriodCorrected.
|
||||
*
|
||||
* This method's length is caused mainly by the query build stuff. Therefor:
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
@@ -208,17 +212,19 @@ class ReportQuery implements ReportQueryInterface
|
||||
public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
||||
return floatval(
|
||||
Auth::user()->transactionjournals()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->where('transactions.account_id', $account->id)
|
||||
->before($end)
|
||||
->after($start)
|
||||
->where('budget_transaction_journal.budget_id', $budget->id)
|
||||
->get(['transaction_journals.*'])->sum('amount')
|
||||
) * -1;
|
||||
bcscale(2);
|
||||
|
||||
return bcmul(
|
||||
Auth::user()->transactionjournals()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->where('transactions.account_id', $account->id)
|
||||
->before($end)
|
||||
->after($start)
|
||||
->where('budget_transaction_journal.budget_id', $budget->id)
|
||||
->get(['transaction_journals.*'])->sum('amount'), -1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Http\Requests\AccountFormRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
@@ -57,17 +58,19 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function delete(Account $account)
|
||||
public function delete(AccountRepositoryInterface $repository, Account $account)
|
||||
{
|
||||
$typeName = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||
$subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]);
|
||||
$typeName = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||
$subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]);
|
||||
$accountList = Expandedform::makeSelectList($repository->getAccounts([$account->accountType->type]), true);
|
||||
unset($accountList[$account->id]);
|
||||
|
||||
// put previous url in session
|
||||
Session::put('accounts.delete.url', URL::previous());
|
||||
Session::flash('gaEventCategory', 'accounts');
|
||||
Session::flash('gaEventAction', 'delete-' . $typeName);
|
||||
|
||||
return view('accounts.delete', compact('account', 'subTitle'));
|
||||
return view('accounts.delete', compact('account', 'subTitle', 'accountList'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,12 +81,12 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function destroy(AccountRepositoryInterface $repository, Account $account)
|
||||
{
|
||||
|
||||
$type = $account->accountType->type;
|
||||
$typeName = Config::get('firefly.shortNamesByFullName.' . $type);
|
||||
$name = $account->name;
|
||||
$moveTo = Auth::user()->accounts()->find(intval(Input::get('move_account_before_delete')));
|
||||
|
||||
$repository->destroy($account);
|
||||
$repository->destroy($account, $moveTo);
|
||||
|
||||
Session::flash('success', trans('firefly.' . $typeName . '_deleted', ['name' => $name]));
|
||||
Preferences::mark();
|
||||
@@ -127,7 +130,7 @@ class AccountController extends Controller
|
||||
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
|
||||
'openingBalanceDate' => $openingBalance ? $openingBalance->date->format('Y-m-d') : null,
|
||||
'openingBalance' => $openingBalanceAmount,
|
||||
'virtualBalance' => floatval($account->virtual_balance)
|
||||
'virtualBalance' => round($account->virtual_balance, 2)
|
||||
];
|
||||
Session::flash('preFilled', $preFilled);
|
||||
Session::flash('gaEventCategory', 'accounts');
|
||||
@@ -153,12 +156,24 @@ class AccountController extends Controller
|
||||
* HERE WE ARE
|
||||
*/
|
||||
$start = clone Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = clone Session::get('end', Carbon::now()->endOfMonth());
|
||||
$start->subDay();
|
||||
|
||||
// start balances:
|
||||
$ids = [];
|
||||
foreach ($accounts as $account) {
|
||||
$ids[] = $account->id;
|
||||
}
|
||||
|
||||
$startBalances = Steam::balancesById($ids, $start);
|
||||
$endBalances = Steam::balancesById($ids, $end);
|
||||
$activities = Steam::getLastActivities($ids);
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($start, $repository) {
|
||||
$account->lastActivityDate = $repository->getLastActivity($account);
|
||||
$account->startBalance = Steam::balance($account, $start);
|
||||
$account->endBalance = Steam::balance($account, clone Session::get('end', Carbon::now()->endOfMonth()));
|
||||
function (Account $account) use ($activities, $startBalances, $endBalances) {
|
||||
$account->lastActivityDate = isset($activities[$account->id]) ? $activities[$account->id] : null;
|
||||
$account->startBalance = isset($startBalances[$account->id]) ? $startBalances[$account->id] : null;
|
||||
$account->endBalance = isset($endBalances[$account->id]) ? $endBalances[$account->id] : null;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -195,12 +210,12 @@ class AccountController extends Controller
|
||||
$accountData = [
|
||||
'name' => $request->input('name'),
|
||||
'accountType' => $request->input('what'),
|
||||
'virtualBalance' => floatval($request->input('virtualBalance')),
|
||||
'virtualBalance' => round($request->input('virtualBalance'), 2),
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'iban' => $request->input('iban'),
|
||||
'accountRole' => $request->input('accountRole'),
|
||||
'openingBalance' => floatval($request->input('openingBalance')),
|
||||
'openingBalance' => round($request->input('openingBalance'), 2),
|
||||
'openingBalanceDate' => new Carbon((string)$request->input('openingBalanceDate')),
|
||||
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
|
||||
|
||||
@@ -238,8 +253,8 @@ class AccountController extends Controller
|
||||
'user' => Auth::user()->id,
|
||||
'iban' => $request->input('iban'),
|
||||
'accountRole' => $request->input('accountRole'),
|
||||
'virtualBalance' => floatval($request->input('virtualBalance')),
|
||||
'openingBalance' => floatval($request->input('openingBalance')),
|
||||
'virtualBalance' => round($request->input('virtualBalance'), 2),
|
||||
'openingBalance' => round($request->input('openingBalance'), 2),
|
||||
'openingBalanceDate' => new Carbon((string)$request->input('openingBalanceDate')),
|
||||
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
|
||||
'ccType' => $request->input('ccType'),
|
||||
|
||||
173
app/Http/Controllers/AttachmentController.php
Normal file
173
app/Http/Controllers/AttachmentController.php
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
|
||||
use Crypt;
|
||||
use File;
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Http\Requests\AttachmentFormRequest;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class AttachmentController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class AttachmentController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
View::share('mainTitleIcon', 'fa-paperclip');
|
||||
View::share('title', trans('firefly.attachments'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function edit(Attachment $attachment)
|
||||
{
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
$subTitle = trans('firefly.edit_attachment', ['name' => $attachment->filename]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (Session::get('attachments.edit.fromUpdate') !== true) {
|
||||
Session::put('attachments.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('attachments.edit.fromUpdate');
|
||||
|
||||
return view('attachments.edit', compact('attachment', 'subTitleIcon', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function delete(Attachment $attachment)
|
||||
{
|
||||
$subTitle = trans('firefly.delete_attachment', ['name' => $attachment->filename]);
|
||||
|
||||
// put previous url in session
|
||||
Session::put('attachments.delete.url', URL::previous());
|
||||
Session::flash('gaEventCategory', 'attachments');
|
||||
Session::flash('gaEventAction', 'delete-attachment');
|
||||
|
||||
return view('attachments.delete', compact('attachment', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AttachmentRepositoryInterface $repository
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(AttachmentRepositoryInterface $repository, Attachment $attachment)
|
||||
{
|
||||
$name = $attachment->filename;
|
||||
|
||||
$repository->destroy($attachment);
|
||||
|
||||
Session::flash('success', trans('firefly.attachment_deleted', ['name' => $name]));
|
||||
Preferences::mark();
|
||||
|
||||
return redirect(Session::get('attachments.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*/
|
||||
public function download(Attachment $attachment, AttachmentHelperInterface $helper)
|
||||
{
|
||||
|
||||
$file = $helper->getAttachmentLocation($attachment);
|
||||
if (file_exists($file)) {
|
||||
|
||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Disposition: attachment; filename=' . $quoted);
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Connection: Keep-Alive');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
header('Pragma: public');
|
||||
header('Content-Length: ' . $attachment->size);
|
||||
|
||||
echo Crypt::decrypt(file_get_contents($file));
|
||||
|
||||
} else {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function preview(Attachment $attachment)
|
||||
{
|
||||
if ($attachment->mime == 'application/pdf') {
|
||||
$file = public_path('images/page_white_acrobat.png');
|
||||
} else {
|
||||
$file = public_path('images/page_green.png');
|
||||
}
|
||||
|
||||
$response = Response::make(File::get($file));
|
||||
$response->header('Content-Type', 'image/png');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param AttachmentFormRequest $request
|
||||
* @param AttachmentRepositoryInterface $repository
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(AttachmentFormRequest $request, AttachmentRepositoryInterface $repository, Attachment $attachment)
|
||||
{
|
||||
|
||||
$attachmentData = [
|
||||
'title' => $request->input('title'),
|
||||
'description' => $request->input('description'),
|
||||
'notes' => $request->input('notes'),
|
||||
];
|
||||
|
||||
$repository->update($attachment, $attachmentData);
|
||||
|
||||
Session::flash('success', 'Attachment "' . $attachment->filename . '" updated.');
|
||||
Preferences::mark();
|
||||
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('attachments.edit.fromUpdate', true);
|
||||
|
||||
return redirect(route('attachments.edit', [$attachment->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return redirect(Session::get('attachments.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
<?php namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Role;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
|
||||
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Mail\Message;
|
||||
use Mail;
|
||||
use Request as Rq;
|
||||
use Session;
|
||||
use Twig;
|
||||
use Validator;
|
||||
@@ -20,19 +21,81 @@ use Validator;
|
||||
*/
|
||||
class AuthController extends Controller
|
||||
{
|
||||
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Registration & Login Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles the registration of new users, as well as the
|
||||
| authentication of existing users. By default, this controller uses
|
||||
| a simple trait to add these behaviors. Why don't you explore it?
|
||||
|
|
||||
*/
|
||||
/**
|
||||
* Show the application registration form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function getRegister()
|
||||
{
|
||||
$host = Rq::getHttpHost();
|
||||
|
||||
return view('auth.register', compact('host'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a login request to the application.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function postLogin(Request $request)
|
||||
{
|
||||
$this->validate(
|
||||
$request, [
|
||||
$this->loginUsername() => 'required', 'password' => 'required',
|
||||
]
|
||||
);
|
||||
|
||||
// If the class is using the ThrottlesLogins trait, we can automatically throttle
|
||||
// the login attempts for this application. We'll key this by the username and
|
||||
// the IP address of the client making these requests into this application.
|
||||
$throttles = $this->isUsingThrottlesLoginsTrait();
|
||||
|
||||
if ($throttles && $this->hasTooManyLoginAttempts($request)) {
|
||||
return $this->sendLockoutResponse($request);
|
||||
}
|
||||
|
||||
$credentials = $this->getCredentials($request);
|
||||
$credentials['blocked'] = 0; // most not be blocked.
|
||||
|
||||
if (Auth::attempt($credentials, $request->has('remember'))) {
|
||||
return $this->handleUserWasAuthenticated($request, $throttles);
|
||||
}
|
||||
|
||||
// default error message:
|
||||
$message = $this->getFailedLoginMessage();
|
||||
|
||||
// try to find a blocked user with this email address.
|
||||
/** @var User $foundUser */
|
||||
$foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first();
|
||||
if (!is_null($foundUser)) {
|
||||
// if it exists, show message:
|
||||
$code = $foundUser->blocked_code;
|
||||
$message = trans('firefly.' . $code . '_error', ['email' => $credentials['email']]);
|
||||
}
|
||||
|
||||
// try
|
||||
|
||||
// If the login attempt was unsuccessful we will increment the number of attempts
|
||||
// to login and redirect the user back to the login form. Of course, when this
|
||||
// user surpasses their maximum number of attempts they will get locked out.
|
||||
if ($throttles) {
|
||||
$this->incrementLoginAttempts($request);
|
||||
}
|
||||
|
||||
return redirect($this->loginPath())
|
||||
->withInput($request->only($this->loginUsername(), 'remember'))
|
||||
->withErrors(
|
||||
[
|
||||
$this->loginUsername() => $message,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
use AuthenticatesAndRegistersUsers;
|
||||
|
||||
public $redirectTo = '/';
|
||||
|
||||
@@ -44,6 +107,8 @@ class AuthController extends Controller
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware('guest', ['except' => 'getLogout']);
|
||||
}
|
||||
|
||||
@@ -109,7 +174,7 @@ class AuthController extends Controller
|
||||
return redirect($this->redirectPath());
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
App::abort(500, 'Not a user!');
|
||||
abort(500, 'Not a user!');
|
||||
|
||||
return redirect('/');
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
@@ -36,6 +36,7 @@ class PasswordController extends Controller
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ class BudgetController extends Controller
|
||||
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->spent = $repository->balanceInPeriod($budget, $date, $end);
|
||||
$budget->currentRep = $repository->getCurrentRepetition($budget, $date);
|
||||
if ($budget->currentRep) {
|
||||
$budgeted = bcadd($budgeted, $budget->currentRep->amount);
|
||||
|
||||
@@ -151,10 +151,12 @@ class CategoryController extends Controller
|
||||
$page = intval(Input::get('page'));
|
||||
$set = $repository->getJournals($category, $page);
|
||||
$count = $repository->countJournals($category);
|
||||
$totalSum = $repository->journalsSum($category);
|
||||
$periodSum = $repository->journalsSum($category, Session::get('start'), Session::get('end'));
|
||||
$journals = new LengthAwarePaginator($set, $count, 50, $page);
|
||||
$journals->setPath('categories/show/' . $category->id);
|
||||
|
||||
return view('categories.show', compact('category', 'journals', 'hideCategory'));
|
||||
return view('categories.show', compact('category', 'journals', 'hideCategory', 'totalSum', 'periodSum'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
@@ -31,7 +30,7 @@ class AccountController extends Controller
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Account\AccountChartGenerator');
|
||||
$this->generator = app('FireflyIII\Generator\Chart\Account\AccountChartGenerator');
|
||||
}
|
||||
|
||||
|
||||
@@ -80,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.
|
||||
*
|
||||
|
||||
@@ -2,18 +2,14 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Response;
|
||||
use Session;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class BillController
|
||||
@@ -33,26 +29,21 @@ class BillController extends Controller
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Bill\BillChartGenerator');
|
||||
$this->generator = app('FireflyIII\Generator\Chart\Bill\BillChartGenerator');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows all bills and whether or not theyve been paid this month (pie chart).
|
||||
*
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param AccountRepositoryInterface $accounts
|
||||
* @param BillRepositoryInterface $repository
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function frontpage(BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
|
||||
public function frontpage(BillRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
$cache = new CacheProperties(); // chart properties for cache:
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('bills');
|
||||
@@ -61,46 +52,13 @@ class BillController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$bills = $repository->getActiveBills();
|
||||
$paid = new Collection; // journals.
|
||||
$unpaid = new Collection; // bills
|
||||
$set = $repository->getBillsForChart($start, $end);
|
||||
|
||||
// optionally expand this set with credit card data
|
||||
$set = $repository->getCreditCardInfoForChart($set, $start, $end);
|
||||
$paid = $set->get('paid');
|
||||
$unpaid = $set->get('unpaid');
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
$ranges = $repository->getRanges($bill, $start, $end);
|
||||
|
||||
foreach ($ranges as $range) {
|
||||
// paid a bill in this range?
|
||||
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
|
||||
if ($journals->count() == 0) {
|
||||
$unpaid->push([$bill, $range['start']]);
|
||||
} else {
|
||||
$paid = $paid->merge($journals);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$creditCards = $accounts->getCreditCards();
|
||||
foreach ($creditCards as $creditCard) {
|
||||
$balance = Steam::balance($creditCard, $end, true);
|
||||
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
|
||||
if ($balance < 0) {
|
||||
// unpaid! create a fake bill that matches the amount.
|
||||
$description = $creditCard->name;
|
||||
$amount = $balance * -1;
|
||||
$fakeBill = $repository->createFakeBill($description, $date, $amount);
|
||||
unset($description, $amount);
|
||||
$unpaid->push([$fakeBill, $date]);
|
||||
}
|
||||
if ($balance == 0) {
|
||||
// find transfer(s) TO the credit card which should account for
|
||||
// anything paid. If not, the CC is not yet used.
|
||||
$journals = $accounts->getTransfersInRange($creditCard, $start, $end);
|
||||
$paid = $paid->merge($journals);
|
||||
}
|
||||
}
|
||||
|
||||
// build chart:
|
||||
$data = $this->generator->frontpage($paid, $unpaid);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Budget;
|
||||
@@ -33,7 +32,7 @@ class BudgetController extends Controller
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator');
|
||||
$this->generator = app('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,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);
|
||||
$entries->push([$chartDate, $spent]);
|
||||
$first = Navigation::addPeriod($first, $range, 0);
|
||||
}
|
||||
@@ -157,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);
|
||||
$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);
|
||||
// $left can be less than zero.
|
||||
// $overspent can be more than zero ( = overspending)
|
||||
|
||||
@@ -200,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();
|
||||
@@ -215,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) {
|
||||
@@ -225,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);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Category;
|
||||
@@ -32,7 +31,7 @@ class CategoryController extends Controller
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Category\CategoryChartGenerator');
|
||||
$this->generator = app('FireflyIII\Generator\Chart\Category\CategoryChartGenerator');
|
||||
}
|
||||
|
||||
|
||||
@@ -47,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;
|
||||
|
||||
|
||||
@@ -67,7 +65,7 @@ class CategoryController extends Controller
|
||||
|
||||
while ($start <= $end) {
|
||||
$currentEnd = Navigation::endOfPeriod($start, $range);
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
|
||||
$spent = $repository->balanceInPeriod($category, $start, $currentEnd);
|
||||
$entries->push([clone $start, $spent]);
|
||||
$start = Navigation::addPeriod($start, $range, 0);
|
||||
|
||||
@@ -171,7 +169,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');
|
||||
@@ -180,14 +178,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
|
||||
@@ -195,15 +203,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);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use App;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
@@ -29,7 +28,7 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator');
|
||||
$this->generator = app('FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Report\ReportQueryInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
@@ -29,7 +28,7 @@ class ReportController extends Controller
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Report\ReportChartGenerator');
|
||||
$this->generator = app('FireflyIII\Generator\Chart\Report\ReportChartGenerator');
|
||||
}
|
||||
|
||||
|
||||
|
||||
64
app/Http/Controllers/CronController.php
Normal file
64
app/Http/Controllers/CronController.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\User;
|
||||
|
||||
/**
|
||||
* Class WebhookController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class CronController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Firefly doesn't have anything that should be in the a cron job, except maybe this one, and it's fairly exceptional.
|
||||
*
|
||||
* If you use SendGrid like I do, you can detect bounces and thereby check if users gave an invalid address. If they did,
|
||||
* it's easy to block them and change their password. Optionally, you could notify yourself about it and send them a message.
|
||||
*
|
||||
* But thats something not supported right now.
|
||||
*/
|
||||
public function sendgrid()
|
||||
{
|
||||
|
||||
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));
|
||||
|
||||
/*
|
||||
* 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 'Done!' . "\n";
|
||||
} else {
|
||||
echo 'Please fill in SendGrid details.';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use App;
|
||||
use Config;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Data;
|
||||
use FireflyIII\Helpers\Csv\Importer;
|
||||
use FireflyIII\Helpers\Csv\WizardInterface;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Input;
|
||||
use Log;
|
||||
@@ -41,8 +42,8 @@ class CsvController extends Controller
|
||||
throw new FireflyException('CSV Import is not enabled.');
|
||||
}
|
||||
|
||||
$this->wizard = App::make('FireflyIII\Helpers\Csv\WizardInterface');
|
||||
$this->data = App::make('FireflyIII\Helpers\Csv\Data');
|
||||
$this->wizard = app('FireflyIII\Helpers\Csv\WizardInterface');
|
||||
$this->data = app('FireflyIII\Helpers\Csv\Data');
|
||||
|
||||
}
|
||||
|
||||
@@ -56,7 +57,7 @@ class CsvController extends Controller
|
||||
public function columnRoles()
|
||||
{
|
||||
|
||||
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers'];
|
||||
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-import-account'];
|
||||
if (!$this->wizard->sessionHasValues($fields)) {
|
||||
Session::flash('warning', 'Could not recover upload.');
|
||||
|
||||
@@ -103,7 +104,7 @@ class CsvController extends Controller
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
$data = [
|
||||
'date-format' => Session::get('date-format'),
|
||||
'date-format' => Session::get('csv-date-format'),
|
||||
'has-headers' => Session::get('csv-has-headers')
|
||||
];
|
||||
if (Session::has('csv-map')) {
|
||||
@@ -116,6 +117,10 @@ class CsvController extends Controller
|
||||
$data['mapped'] = Session::get('csv-mapped');
|
||||
}
|
||||
|
||||
if (Session::has('csv-specifix')) {
|
||||
$data['specifix'] = Session::get('csv-specifix');
|
||||
}
|
||||
|
||||
$result = json_encode($data, JSON_PRETTY_PRINT);
|
||||
$name = 'csv-configuration-' . date('Y-m-d') . '.json';
|
||||
|
||||
@@ -143,13 +148,14 @@ class CsvController extends Controller
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
public function index(AccountRepositoryInterface $repository)
|
||||
{
|
||||
$subTitle = trans('firefly.csv_import');
|
||||
|
||||
Session::forget('csv-date-format');
|
||||
Session::forget('csv-has-headers');
|
||||
Session::forget('csv-file');
|
||||
Session::forget('csv-import-account');
|
||||
Session::forget('csv-map');
|
||||
Session::forget('csv-roles');
|
||||
Session::forget('csv-mapped');
|
||||
@@ -161,11 +167,14 @@ class CsvController extends Controller
|
||||
$specifix[$entry] = trans('firefly.csv_specifix_' . $entry);
|
||||
}
|
||||
|
||||
// get a list of asset accounts:
|
||||
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Asset account', 'Default account']));
|
||||
|
||||
// can actually upload?
|
||||
$uploadPossible = is_writable(storage_path('upload'));
|
||||
$path = storage_path('upload');
|
||||
|
||||
return view('csv.index', compact('subTitle', 'uploadPossible', 'path', 'specifix'));
|
||||
return view('csv.index', compact('subTitle', 'uploadPossible', 'path', 'specifix', 'accounts'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,12 +306,13 @@ class CsvController extends Controller
|
||||
$rows = $importer->getRows();
|
||||
$errors = $importer->getErrors();
|
||||
$imported = $importer->getImported();
|
||||
$journals = $importer->getJournals();
|
||||
|
||||
Preferences::mark();
|
||||
|
||||
$subTitle = trans('firefly.csv_process_title');
|
||||
|
||||
return view('csv.process', compact('rows', 'errors', 'imported', 'subTitle'));
|
||||
return view('csv.process', compact('rows', 'errors', 'imported', 'subTitle', 'journals'));
|
||||
|
||||
}
|
||||
|
||||
@@ -367,19 +377,17 @@ class CsvController extends Controller
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
|
||||
$fullPath = $this->wizard->storeCsvFile($request->file('csv')->getRealPath());
|
||||
$settings = [];
|
||||
$settings['date-format'] = Input::get('date_format');
|
||||
$settings['has-headers'] = intval(Input::get('has_headers')) === 1;
|
||||
$settings['specifix'] = Input::get('specifix');
|
||||
$settings['map'] = [];
|
||||
$settings['mapped'] = [];
|
||||
$settings['roles'] = [];
|
||||
$fullPath = $this->wizard->storeCsvFile($request->file('csv')->getRealPath());
|
||||
$settings = [];
|
||||
$settings['date-format'] = Input::get('date_format');
|
||||
$settings['has-headers'] = intval(Input::get('has_headers')) === 1;
|
||||
$settings['specifix'] = Input::get('specifix');
|
||||
$settings['import-account'] = intval(Input::get('csv_import_account'));
|
||||
$settings['map'] = [];
|
||||
$settings['mapped'] = [];
|
||||
$settings['roles'] = [];
|
||||
|
||||
/*
|
||||
* Process config file if present.
|
||||
*/
|
||||
if ($request->hasFile('csv_config')) {
|
||||
if ($request->hasFile('csv_config')) { // Process config file if present.
|
||||
$data = file_get_contents($request->file('csv_config')->getRealPath());
|
||||
$json = json_decode($data, true);
|
||||
if (is_array($json)) {
|
||||
@@ -394,6 +402,7 @@ class CsvController extends Controller
|
||||
$this->data->setMapped($settings['mapped']);
|
||||
$this->data->setRoles($settings['roles']);
|
||||
$this->data->setSpecifix($settings['specifix']);
|
||||
$this->data->setImportAccount($settings['import-account']);
|
||||
|
||||
return redirect(route('csv.column-roles'));
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Artisan;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Input;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Route;
|
||||
use Session;
|
||||
@@ -57,6 +59,7 @@ class HomeController extends Controller
|
||||
|
||||
|
||||
Session::clear();
|
||||
Artisan::call('cache:clear');
|
||||
|
||||
return redirect(route('index'));
|
||||
}
|
||||
@@ -72,22 +75,20 @@ class HomeController extends Controller
|
||||
$count = $repository->countAccounts($types);
|
||||
bcscale(2);
|
||||
|
||||
|
||||
if ($count == 0) {
|
||||
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());
|
||||
|
||||
$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();
|
||||
|
||||
|
||||
@@ -114,7 +115,9 @@ class HomeController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal', 'piggyBankAccounts'));
|
||||
return view(
|
||||
'index', compact('count', 'showTour', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal', 'piggyBankAccounts')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,6 +131,7 @@ class HomeController extends Controller
|
||||
|
||||
return redirect(route('index'));
|
||||
}
|
||||
Log::debug('Make log.');
|
||||
|
||||
// get all routes:
|
||||
$routeCollection = Route::getRoutes();
|
||||
|
||||
@@ -12,6 +12,7 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use Steam;
|
||||
@@ -24,6 +25,43 @@ use Steam;
|
||||
class JsonController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function endTour()
|
||||
{
|
||||
Preferences::set('tour', false);
|
||||
|
||||
return Response::json('true');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function tour()
|
||||
{
|
||||
$pref = Preferences::get('tour', true);
|
||||
if (!$pref) {
|
||||
abort(404);
|
||||
}
|
||||
$headers = ['main-content', 'sidebar-toggle', 'account-menu', 'budget-menu', 'report-menu', 'transaction-menu', 'option-menu', 'main-content-end'];
|
||||
$steps = [];
|
||||
foreach ($headers as $header) {
|
||||
$steps[] = [
|
||||
'element' => '#' . $header,
|
||||
'title' => trans('help.' . $header . '-title'),
|
||||
'content' => trans('help.' . $header . '-text'),
|
||||
];
|
||||
}
|
||||
$steps[0]['orphan'] = true;// orphan and backdrop for first element.
|
||||
$steps[0]['backdrop'] = true;
|
||||
$steps[1]['placement'] = 'left';// sidebar position left:
|
||||
$steps[7]['orphan'] = true; // final in the center again.
|
||||
$steps[7]['backdrop'] = true;
|
||||
$template = view('json.tour')->render();
|
||||
|
||||
return Response::json(['steps' => $steps, 'template' => $template]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BillRepositoryInterface $repository
|
||||
@@ -34,8 +72,9 @@ class JsonController extends Controller
|
||||
*/
|
||||
public function boxBillsPaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository)
|
||||
{
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$amount = 0;
|
||||
bcscale(2);
|
||||
|
||||
// works for json too!
|
||||
@@ -46,12 +85,7 @@ class JsonController extends Controller
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$amount = 0;
|
||||
|
||||
|
||||
// these two functions are the same as the chart
|
||||
$bills = $repository->getActiveBills();
|
||||
$bills = $repository->getActiveBills(); // these two functions are the same as the chart
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
@@ -59,14 +93,10 @@ class JsonController extends Controller
|
||||
}
|
||||
unset($bill, $bills);
|
||||
|
||||
/**
|
||||
* Find credit card accounts and possibly unpaid credit card bills.
|
||||
*/
|
||||
$creditCards = $accountRepository->getCreditCards();
|
||||
// if the balance is not zero, the monthly payment is still underway.
|
||||
$creditCards = $accountRepository->getCreditCards(); // Find credit card accounts and possibly unpaid credit card bills.
|
||||
/** @var Account $creditCard */
|
||||
foreach ($creditCards as $creditCard) {
|
||||
$balance = Steam::balance($creditCard, $end, true);
|
||||
$balance = Steam::balance($creditCard, $end, true); // if the balance is not zero, the monthly payment is still underway.
|
||||
if ($balance == 0) {
|
||||
// find a transfer TO the credit card which should account for
|
||||
// anything paid. If not, the CC is not yet used.
|
||||
@@ -76,7 +106,6 @@ class JsonController extends Controller
|
||||
$data = ['box' => 'bills-paid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
|
||||
$cache->store($data);
|
||||
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
@@ -132,8 +161,8 @@ class JsonController extends Controller
|
||||
}
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
$current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$amount = bcadd($amount, $current);
|
||||
$current = bcdiv(bcadd($entry[0]->amount_max, $entry[0]->amount_min), 2);
|
||||
$amount = bcadd($amount, $current);
|
||||
}
|
||||
|
||||
$data = ['box' => 'bills-unpaid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
|
||||
|
||||
@@ -53,12 +53,13 @@ class NewUserController extends Controller
|
||||
// create normal asset account:
|
||||
$assetAccount = [
|
||||
'name' => $request->get('bank_name'),
|
||||
'iban' => null,
|
||||
'accountType' => 'asset',
|
||||
'virtualBalance' => 0,
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'accountRole' => 'defaultAsset',
|
||||
'openingBalance' => floatval($request->input('bank_balance')),
|
||||
'openingBalance' => round($request->input('bank_balance'), 2),
|
||||
'openingBalanceDate' => new Carbon,
|
||||
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
|
||||
];
|
||||
@@ -69,12 +70,13 @@ class NewUserController extends Controller
|
||||
if (strlen($request->get('savings_balance') > 0)) {
|
||||
$savingsAccount = [
|
||||
'name' => $request->get('bank_name') . ' savings account',
|
||||
'iban' => null,
|
||||
'accountType' => 'asset',
|
||||
'virtualBalance' => 0,
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'accountRole' => 'savingAsset',
|
||||
'openingBalance' => floatval($request->input('savings_balance')),
|
||||
'openingBalance' => round($request->input('savings_balance'), 2),
|
||||
'openingBalanceDate' => new Carbon,
|
||||
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
|
||||
];
|
||||
@@ -86,8 +88,9 @@ class NewUserController extends Controller
|
||||
if (strlen($request->get('credit_card_limit') > 0)) {
|
||||
$creditAccount = [
|
||||
'name' => 'Credit card',
|
||||
'iban' => null,
|
||||
'accountType' => 'asset',
|
||||
'virtualBalance' => floatval($request->get('credit_card_limit')),
|
||||
'virtualBalance' => round($request->get('credit_card_limit'), 2),
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'accountRole' => 'ccAsset',
|
||||
|
||||
@@ -47,10 +47,11 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function add(AccountRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
bcscale(2);
|
||||
$date = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$leftOnAccount = $repository->leftOnAccount($piggyBank->account, $date);
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||
$leftToSave = $piggyBank->targetamount - $savedSoFar;
|
||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||
|
||||
return view('piggy-banks.add', compact('piggyBank', 'maxAmount'));
|
||||
@@ -66,7 +67,7 @@ class PiggyBankController extends Controller
|
||||
|
||||
$periods = Config::get('firefly.piggy_bank_periods');
|
||||
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
|
||||
$subTitle = trans('firefly.create_new_piggybank');
|
||||
$subTitle = trans('firefly.new_piggy_bank');
|
||||
$subTitleIcon = 'fa-plus';
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
@@ -171,9 +172,9 @@ class PiggyBankController extends Controller
|
||||
$accounts = [];
|
||||
/** @var PiggyBank $piggyBank */
|
||||
foreach ($piggyBanks as $piggyBank) {
|
||||
$piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount);
|
||||
$piggyBank->savedSoFar = round($piggyBank->currentRelevantRep()->currentamount, 2);
|
||||
$piggyBank->percentage = $piggyBank->savedSoFar != 0 ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0;
|
||||
$piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar;
|
||||
$piggyBank->leftToSave = bcsub($piggyBank->targetamount, $piggyBank->savedSoFar);
|
||||
|
||||
/*
|
||||
* Fill account information:
|
||||
@@ -185,7 +186,7 @@ class PiggyBankController extends Controller
|
||||
'balance' => Steam::balance($account, $end, true),
|
||||
'leftForPiggyBanks' => $repository->leftOnAccount($account, $end),
|
||||
'sumOfSaved' => $piggyBank->savedSoFar,
|
||||
'sumOfTargets' => floatval($piggyBank->targetamount),
|
||||
'sumOfTargets' => round($piggyBank->targetamount, 2),
|
||||
'leftToSave' => $piggyBank->leftToSave
|
||||
];
|
||||
} else {
|
||||
@@ -211,7 +212,7 @@ class PiggyBankController extends Controller
|
||||
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $order => $id) {
|
||||
$repository->setOrder(intval($id), (intval($order) + 1));
|
||||
$repository->setOrder(intval($id), ($order + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,13 +226,13 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function postAdd(PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts, PiggyBank $piggyBank)
|
||||
{
|
||||
$amount = round(floatval(Input::get('amount')), 2);
|
||||
bcscale(2);
|
||||
$amount = round(Input::get('amount'), 2);
|
||||
$date = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$leftOnAccount = $accounts->leftOnAccount($piggyBank->account, $date);
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||
$leftToSave = $piggyBank->targetamount - $savedSoFar;
|
||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||
$maxAmount = round(min($leftOnAccount, $leftToSave), 2);
|
||||
bcscale(2);
|
||||
|
||||
if ($amount <= $maxAmount) {
|
||||
$repetition = $piggyBank->currentRelevantRep();
|
||||
@@ -258,7 +259,7 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function postRemove(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
$amount = floatval(Input::get('amount'));
|
||||
$amount = round(Input::get('amount'), 2);
|
||||
bcscale(2);
|
||||
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||
@@ -319,7 +320,7 @@ class PiggyBankController extends Controller
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => new Carbon,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'targetamount' => round($request->get('targetamount'), 2),
|
||||
'remind_me' => false,
|
||||
'reminder_skip' => 0,
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
@@ -354,7 +355,7 @@ class PiggyBankController extends Controller
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'targetamount' => round($request->get('targetamount'), 2),
|
||||
'remind_me' => false,
|
||||
'reminder_skip' => 0,
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
|
||||
@@ -4,6 +4,7 @@ use Auth;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\DeleteAccountFormRequest;
|
||||
use FireflyIII\Http\Requests\ProfileFormRequest;
|
||||
use FireflyIII\User;
|
||||
use Hash;
|
||||
use Session;
|
||||
|
||||
@@ -20,7 +21,7 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function changePassword()
|
||||
{
|
||||
return view('profile.change-password')->with('title', Auth::user()->email)->with('subTitle', 'Change your password')->with(
|
||||
return view('profile.change-password')->with('title', Auth::user()->email)->with('subTitle', trans('firefly.change_your_password'))->with(
|
||||
'mainTitleIcon', 'fa-user'
|
||||
);
|
||||
}
|
||||
@@ -30,7 +31,7 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function deleteAccount()
|
||||
{
|
||||
return view('profile.delete-account')->with('title', Auth::user()->email)->with('subTitle', 'Delete account')->with(
|
||||
return view('profile.delete-account')->with('title', Auth::user()->email)->with('subTitle', trans('firefly.delete_account'))->with(
|
||||
'mainTitleIcon', 'fa-user'
|
||||
);
|
||||
}
|
||||
@@ -41,7 +42,7 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('profile.index')->with('title', 'Profile')->with('subTitle', Auth::user()->email)->with('mainTitleIcon', 'fa-user');
|
||||
return view('profile.index')->with('title', trans('firefly.profile'))->with('subTitle', Auth::user()->email)->with('mainTitleIcon', 'fa-user');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +54,7 @@ class ProfileController extends Controller
|
||||
{
|
||||
// old, new1, new2
|
||||
if (!Hash::check($request->get('current_password'), Auth::user()->password)) {
|
||||
Session::flash('error', 'Invalid current password!');
|
||||
Session::flash('error', trans('firefly.invalid_current_password'));
|
||||
|
||||
return redirect(route('profile.change-password'));
|
||||
}
|
||||
@@ -68,7 +69,7 @@ class ProfileController extends Controller
|
||||
Auth::user()->password = $request->get('new_password');
|
||||
Auth::user()->save();
|
||||
|
||||
Session::flash('success', 'Password changed!');
|
||||
Session::flash('success', trans('firefly.password_changed'));
|
||||
|
||||
return redirect(route('profile'));
|
||||
}
|
||||
@@ -83,7 +84,7 @@ class ProfileController extends Controller
|
||||
protected function validatePassword($old, $new1)
|
||||
{
|
||||
if ($new1 == $old) {
|
||||
return 'The idea is to change your password.';
|
||||
return trans('firefly.should_change');
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -100,17 +101,28 @@ class ProfileController extends Controller
|
||||
{
|
||||
// old, new1, new2
|
||||
if (!Hash::check($request->get('password'), Auth::user()->password)) {
|
||||
Session::flash('error', 'Invalid password!');
|
||||
Session::flash('error', trans('firefly.invalid_password'));
|
||||
|
||||
return redirect(route('profile.delete-account'));
|
||||
}
|
||||
|
||||
// DELETE!
|
||||
$email = Auth::user()->email;
|
||||
Auth::user()->delete();
|
||||
Session::flush();
|
||||
Session::flash('gaEventCategory', 'user');
|
||||
Session::flash('gaEventAction', 'delete-account');
|
||||
|
||||
// create a new user with the same email address so re-registration is blocked.
|
||||
User::create(
|
||||
[
|
||||
'email' => $email,
|
||||
'password' => 'deleted',
|
||||
'blocked' => 1,
|
||||
'blocked_code' => 'deleted'
|
||||
]
|
||||
);
|
||||
|
||||
return redirect(route('index'));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ use FireflyIII\Http\Requests\TagFormRequest;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Response;
|
||||
@@ -184,16 +185,28 @@ class TagController extends Controller
|
||||
// loop each types and get the tags, group them by year.
|
||||
$collection = [];
|
||||
foreach ($types as $type) {
|
||||
|
||||
/** @var Collection $tags */
|
||||
$tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date', 'ASC')->get();
|
||||
$tags = $tags->sortBy(
|
||||
function (Tag $tag) {
|
||||
$date = !is_null($tag->date) ? $tag->date->format('Ymd') : '000000';
|
||||
|
||||
|
||||
return strtolower($date . $tag->tag);
|
||||
}
|
||||
);
|
||||
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
$year = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year;
|
||||
$month = is_null($tag->date) ? trans('firefly.no_month') : $tag->date->formatLocalized($this->monthFormat);
|
||||
$collection[$type][$year][$month][] = $tag;
|
||||
|
||||
$year = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year;
|
||||
$monthFormatted = is_null($tag->date) ? trans('firefly.no_month') : $tag->date->formatLocalized($this->monthFormat);
|
||||
|
||||
$collection[$type][$year][$monthFormatted][] = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return view('tags.index', compact('title', 'mainTitleIcon', 'types', 'helpHidden', 'collection'));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Amount;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use ExpandedForm;
|
||||
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;
|
||||
@@ -15,6 +18,7 @@ use Input;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use Steam;
|
||||
use URL;
|
||||
use View;
|
||||
|
||||
@@ -43,10 +47,21 @@ class TransactionController extends Controller
|
||||
*/
|
||||
public function create(AccountRepositoryInterface $repository, $what = 'deposit')
|
||||
{
|
||||
$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());
|
||||
$maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize'));
|
||||
$maxPostSize = Steam::phpBytes(ini_get('post_max_size'));
|
||||
$uploadSize = min($maxFileSize, $maxPostSize);
|
||||
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
|
||||
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
|
||||
$budgets[0] = trans('form.noBudget');
|
||||
|
||||
// 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'];
|
||||
@@ -68,7 +83,7 @@ class TransactionController extends Controller
|
||||
asort($piggies);
|
||||
|
||||
|
||||
return view('transactions.create', compact('accounts', 'budgets', 'what', 'piggies', 'subTitle'));
|
||||
return view('transactions.create', compact('accounts', 'uploadSize', 'budgets', 'what', 'piggies', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,14 +136,17 @@ class TransactionController extends Controller
|
||||
*/
|
||||
public function edit(AccountRepositoryInterface $repository, TransactionJournal $journal)
|
||||
{
|
||||
$what = strtolower($journal->transactionType->type);
|
||||
$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');
|
||||
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
|
||||
$preFilled = [
|
||||
$maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize'));
|
||||
$maxPostSize = Steam::phpBytes(ini_get('post_max_size'));
|
||||
$uploadSize = min($maxFileSize, $maxPostSize);
|
||||
$what = strtolower($journal->transactionType->type);
|
||||
$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');
|
||||
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
|
||||
$preFilled = [
|
||||
'date' => $journal->date->format('Y-m-d'),
|
||||
'category' => '',
|
||||
'budget_id' => 0,
|
||||
@@ -179,7 +197,7 @@ class TransactionController extends Controller
|
||||
Session::forget('transactions.edit.fromUpdate');
|
||||
|
||||
|
||||
return View::make('transactions.edit', compact('journal', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled);
|
||||
return view('transactions.edit', compact('journal', 'uploadSize', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,10 +256,11 @@ class TransactionController extends Controller
|
||||
*/
|
||||
public function show(JournalRepositoryInterface $repository, TransactionJournal $journal)
|
||||
{
|
||||
bcscale(2);
|
||||
$journal->transactions->each(
|
||||
function (Transaction $t) use ($journal, $repository) {
|
||||
$t->before = $repository->getAmountBefore($journal, $t);
|
||||
$t->after = $t->before + $t->amount;
|
||||
$t->after = bcadd($t->before, $t->amount);
|
||||
}
|
||||
);
|
||||
$what = strtolower($journal->transactionType->type);
|
||||
@@ -256,15 +275,33 @@ class TransactionController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(JournalFormRequest $request, JournalRepositoryInterface $repository)
|
||||
public function store(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att)
|
||||
{
|
||||
|
||||
$journalData = $request->getJournalData();
|
||||
$journal = $repository->store($journalData);
|
||||
|
||||
// if not withdrawal, unset budgetid.
|
||||
if ($journalData['what'] != 'withdrawal') {
|
||||
$journalData['budget_id'] = 0;
|
||||
}
|
||||
|
||||
$journal = $repository->store($journalData);
|
||||
|
||||
// save attachments:
|
||||
$att->saveAttachmentsForModel($journal);
|
||||
|
||||
// flash errors
|
||||
if (count($att->getErrors()->get('attachments')) > 0) {
|
||||
Session::flash('error', $att->getErrors()->get('attachments'));
|
||||
}
|
||||
// flash messages
|
||||
if (count($att->getMessages()->get('attachments')) > 0) {
|
||||
Session::flash('info', $att->getMessages()->get('attachments'));
|
||||
}
|
||||
|
||||
// rescan journal, UpdateJournalConnection
|
||||
event(new JournalSaved($journal));
|
||||
// ConnectJournalToPiggyBank
|
||||
|
||||
if ($journal->transactionType->type == 'Transfer' && intval($request->get('piggy_bank_id')) > 0) {
|
||||
event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
|
||||
}
|
||||
@@ -288,16 +325,29 @@ class TransactionController extends Controller
|
||||
/**
|
||||
* @param JournalFormRequest $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
* @param AttachmentHelperInterface $att
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
|
||||
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att, TransactionJournal $journal)
|
||||
{
|
||||
|
||||
$journalData = $request->getJournalData();
|
||||
$repository->update($journal, $journalData);
|
||||
|
||||
// save attachments:
|
||||
$att->saveAttachmentsForModel($journal);
|
||||
|
||||
// flash errors
|
||||
if (count($att->getErrors()->get('attachments')) > 0) {
|
||||
Session::flash('error', $att->getErrors()->get('attachments'));
|
||||
}
|
||||
// flash messages
|
||||
if (count($att->getMessages()->get('attachments')) > 0) {
|
||||
Session::flash('info', $att->getMessages()->get('attachments'));
|
||||
}
|
||||
|
||||
event(new JournalSaved($journal));
|
||||
// update, get events by date and sort DESC
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ class Authenticate
|
||||
return redirect()->guest('auth/login');
|
||||
}
|
||||
}
|
||||
|
||||
if (intval($this->auth->user()->blocked) == 1) {
|
||||
return redirect()->route('logout');
|
||||
}
|
||||
|
||||
// if logged in, set user language:
|
||||
$pref = Preferences::get('language', 'en');
|
||||
App::setLocale($pref->data);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
namespace FireflyIII\Http\Middleware;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
@@ -65,7 +64,7 @@ class Range
|
||||
}
|
||||
if (!Session::has('first')) {
|
||||
/** @var \FireflyIII\Repositories\Journal\JournalRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Journal\JournalRepositoryInterface');
|
||||
$repository = app('FireflyIII\Repositories\Journal\JournalRepositoryInterface');
|
||||
$journal = $repository->first();
|
||||
if ($journal) {
|
||||
Session::put('first', $journal->date);
|
||||
|
||||
@@ -24,5 +24,4 @@ class VerifyCsrfToken extends BaseVerifier
|
||||
{
|
||||
return parent::handle($request, $next);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
36
app/Http/Requests/AttachmentFormRequest.php
Normal file
36
app/Http/Requests/AttachmentFormRequest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Auth;
|
||||
|
||||
/**
|
||||
* Class AttachmentFormRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Http\Requests
|
||||
*/
|
||||
class AttachmentFormRequest extends Request
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
// Only allow logged in users
|
||||
return Auth::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
|
||||
return [
|
||||
'title' => 'between:1,255',
|
||||
'description' => 'between:1,65536',
|
||||
'notes' => 'between:1,65536',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -31,9 +31,9 @@ class BillFormRequest extends Request
|
||||
return [
|
||||
'name' => $this->get('name'),
|
||||
'match' => $this->get('match'),
|
||||
'amount_min' => floatval($this->get('amount_min')),
|
||||
'amount_currency_id' => floatval($this->get('amount_currency_id')),
|
||||
'amount_max' => floatval($this->get('amount_max')),
|
||||
'amount_min' => round($this->get('amount_min'), 2),
|
||||
'amount_currency_id' => round($this->get('amount_currency_id'), 2),
|
||||
'amount_max' => round($this->get('amount_max'), 2),
|
||||
'date' => new Carbon($this->get('date')),
|
||||
'user' => Auth::user()->id,
|
||||
'repeat_freq' => $this->get('repeat_freq'),
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
@@ -38,7 +37,7 @@ class JournalFormRequest extends Request
|
||||
'account_to_id' => intval($this->get('account_to_id')),
|
||||
'expense_account' => $this->get('expense_account'),
|
||||
'revenue_account' => $this->get('revenue_account'),
|
||||
'amount' => floatval($this->get('amount')),
|
||||
'amount' => round($this->get('amount'), 2),
|
||||
'user' => Auth::user()->id,
|
||||
'amount_currency_id' => intval($this->get('amount_currency_id')),
|
||||
'date' => new Carbon($this->get('date')),
|
||||
@@ -85,7 +84,7 @@ class JournalFormRequest extends Request
|
||||
$rules['category'] = 'between:1,255';
|
||||
break;
|
||||
default:
|
||||
App::abort(500, 'Cannot handle ' . $what);
|
||||
abort(500, 'Cannot handle ' . $what);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,9 +280,16 @@ Breadcrumbs::register(
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'change-password', function (Generator $breadcrumbs) {
|
||||
'profile.change-password', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('profile');
|
||||
$breadcrumbs->push(trans('breadcrumbs.changePassword'), route('change-password'));
|
||||
$breadcrumbs->push(trans('breadcrumbs.changePassword'), route('profile.change-password'));
|
||||
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'profile.delete-account', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('profile');
|
||||
$breadcrumbs->push(trans('firefly.delete_account'), route('profile.delete-account'));
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
@@ -42,6 +43,19 @@ Route::bind(
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'attachment', function ($value) {
|
||||
if (Auth::check()) {
|
||||
$object = Attachment::where('id', $value)->where('user_id', Auth::user()->id)->first();
|
||||
if ($object) {
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'currency', function ($value) {
|
||||
if (Auth::check()) {
|
||||
@@ -144,10 +158,11 @@ Route::bind(
|
||||
* Auth\AuthController
|
||||
*/
|
||||
Route::get('/register', ['uses' => 'Auth\AuthController@getRegister', 'as' => 'register']);
|
||||
Route::get('/cron/sendgrid', ['uses' => 'CronController@sendgrid']);
|
||||
|
||||
Route::controllers(
|
||||
[
|
||||
'auth' => 'Auth\AuthController',
|
||||
'auth' => 'Auth\AuthController',
|
||||
'password' => 'Auth\PasswordController',
|
||||
]
|
||||
);
|
||||
@@ -177,6 +192,21 @@ Route::group(
|
||||
Route::post('/accounts/update/{account}', ['uses' => 'AccountController@update', 'as' => 'accounts.update']);
|
||||
Route::post('/accounts/destroy/{account}', ['uses' => 'AccountController@destroy', 'as' => 'accounts.destroy']);
|
||||
|
||||
|
||||
/**
|
||||
* Attachment Controller
|
||||
*/
|
||||
|
||||
Route::post('/attachment/update/{attachment}', ['uses' => 'AttachmentController@update', 'as' => 'attachments.update']);
|
||||
Route::post('/attachment/destroy/{attachment}', ['uses' => 'AttachmentController@destroy', 'as' => 'attachments.destroy']);
|
||||
|
||||
Route::get('/attachment/edit/{attachment}', ['uses' => 'AttachmentController@edit', 'as' => 'attachments.edit']);
|
||||
Route::get('/attachment/delete/{attachment}', ['uses' => 'AttachmentController@delete', 'as' => 'attachments.delete']);
|
||||
Route::get('/attachment/show/{attachment}', ['uses' => 'AttachmentController@show', 'as' => 'attachments.show']);
|
||||
Route::get('/attachment/preview/{attachment}', ['uses' => 'AttachmentController@preview', 'as' => 'attachments.preview']);
|
||||
Route::get('/attachment/download/{attachment}', ['uses' => 'AttachmentController@download', 'as' => 'attachments.download']);
|
||||
|
||||
|
||||
/**
|
||||
* Bills Controller
|
||||
*/
|
||||
@@ -252,6 +282,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']
|
||||
);
|
||||
@@ -270,7 +301,12 @@ 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/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}/month', ['uses' => 'Chart\CategoryController@month']); // should be period.
|
||||
Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']);
|
||||
|
||||
@@ -296,6 +332,9 @@ Route::group(
|
||||
Route::get('/json/revenue-accounts', ['uses' => 'JsonController@revenueAccounts', 'as' => 'json.revenue-accounts']);
|
||||
Route::get('/json/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']);
|
||||
Route::get('/json/tags', ['uses' => 'JsonController@tags', 'as' => 'json.tags']);
|
||||
Route::get('/json/tour', ['uses' => 'JsonController@tour', 'as' => 'json.tour']);
|
||||
Route::post('/json/end-tour', ['uses' => 'JsonController@endTour']);
|
||||
|
||||
Route::get('/json/box/in', ['uses' => 'JsonController@boxIn', 'as' => 'json.box.in']);
|
||||
Route::get('/json/box/out', ['uses' => 'JsonController@boxOut', 'as' => 'json.box.out']);
|
||||
Route::get('/json/box/bills-unpaid', ['uses' => 'JsonController@boxBillsUnpaid', 'as' => 'json.box.paid']);
|
||||
|
||||
@@ -21,9 +21,10 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @property boolean $active
|
||||
* @property boolean $encrypted
|
||||
* @property float $virtual_balance
|
||||
* @property string $virtual_balance_encrypted
|
||||
* @property string $iban
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\AccountMeta[] $accountMeta
|
||||
* @property-read \FireflyIII\Models\AccountType $accountType
|
||||
* @property-read mixed $name_for_editform
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBank[] $piggyBanks
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions
|
||||
* @property-read \FireflyIII\User $user
|
||||
@@ -37,19 +38,16 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereActive($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereEncrypted($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereVirtualBalance($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereVirtualBalanceEncrypted($value)
|
||||
* @method static \FireflyIII\Models\Account accountTypeIn($types)
|
||||
* @method static \FireflyIII\Models\Account hasMetaValue($name, $value)
|
||||
* @property boolean joinedAccountTypes
|
||||
* @property mixed startBalance
|
||||
* @property mixed endBalance
|
||||
* @property mixed lastActivityDate
|
||||
* @property mixed piggyBalance
|
||||
* @property mixed difference
|
||||
* @property mixed percentage
|
||||
* @property string $iban
|
||||
* @property-read mixed $name_for_editform
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereIban($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account accountTypeIn($types)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account hasMetaValue($name, $value)
|
||||
* @property-read bool $joinedAccountTypes
|
||||
* @property float $startBalance
|
||||
* @property float $endBalance
|
||||
* @property float $piggyBalance
|
||||
* @property float $percentage
|
||||
* @property float $difference
|
||||
* @property \Carbon\Carbon $lastActivityDate
|
||||
*/
|
||||
class Account extends Model
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ use Watson\Validating\ValidatingTrait;
|
||||
/**
|
||||
* Class AccountMeta
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
|
||||
@@ -5,7 +5,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
/**
|
||||
* Class AccountType
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
|
||||
190
app/Models/Attachment.php
Normal file
190
app/Models/Attachment.php
Normal file
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* Class Attachment
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property string $deleted_at
|
||||
* @property integer $attachable_id
|
||||
* @property string $attachable_type
|
||||
* @property integer $user_id
|
||||
* @property string $md5
|
||||
* @property string $filename
|
||||
* @property string $mime
|
||||
* @property integer $size
|
||||
* @property boolean $uploaded
|
||||
* @property-read \ $attachable
|
||||
* @property-read \FireflyIII\User $user
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereAttachableId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereAttachableType($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUserId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereMd5($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereFilename($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereMime($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereSize($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUploaded($value)
|
||||
* @property string $title
|
||||
* @property string $description
|
||||
* @property string $notes
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereTitle($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereDescription($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereNotes($value)
|
||||
*/
|
||||
class Attachment extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'md5', 'filename', 'mime', 'title', 'notes', 'description', 'size', 'uploaded'];
|
||||
|
||||
/**
|
||||
* Get all of the owning imageable models.
|
||||
*/
|
||||
public function attachable()
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getFilenameAttribute($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setFilenameAttribute($value)
|
||||
{
|
||||
$this->attributes['filename'] = Crypt::encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getMimeAttribute($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setMimeAttribute($value)
|
||||
{
|
||||
$this->attributes['mime'] = Crypt::encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getTitleAttribute($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setTitleAttribute($value)
|
||||
{
|
||||
$this->attributes['title'] = Crypt::encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getDescriptionAttribute($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setDescriptionAttribute($value)
|
||||
{
|
||||
$this->attributes['description'] = Crypt::encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getNotesAttribute($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setNotesAttribute($value)
|
||||
{
|
||||
$this->attributes['notes'] = Crypt::encrypt($value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,10 +4,9 @@ use Crypt;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* FireflyIII\Models\Bill
|
||||
* Class Bill
|
||||
*
|
||||
* @codeCoverageIgnore Class Bill
|
||||
* @package FireflyIII\Models
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
@@ -15,9 +14,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @property string $name
|
||||
* @property string $match
|
||||
* @property float $amount_min
|
||||
* @property string $amount_min_encrypted
|
||||
* @property float $amount_max
|
||||
* @property string $amount_max_encrypted
|
||||
* @property \Carbon\Carbon $date
|
||||
* @property boolean $active
|
||||
* @property boolean $automatch
|
||||
@@ -34,9 +31,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereName($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereMatch($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMin($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMinEncrypted($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMax($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMaxEncrypted($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereDate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereActive($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAutomatch($value)
|
||||
@@ -44,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 mixed nextExpectedMatch
|
||||
* @property mixed lastFoundMatch
|
||||
* @property-read \Carbon\Carbon $nextExpectedMatch
|
||||
* @property-read \Carbon\Carbon $lastFoundMatch
|
||||
*/
|
||||
class Bill extends Model
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
/**
|
||||
* Class Budget
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
@@ -39,9 +38,6 @@ class Budget extends Model
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
/**
|
||||
* Class BudgetLimit
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
@@ -13,7 +12,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @property integer $budget_id
|
||||
* @property \Carbon\Carbon $startdate
|
||||
* @property float $amount
|
||||
* @property string $amount_encrypted
|
||||
* @property boolean $repeats
|
||||
* @property string $repeat_freq
|
||||
* @property-read \FireflyIII\Models\Budget $budget
|
||||
@@ -24,7 +22,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereBudgetId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereStartdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereAmount($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereAmountEncrypted($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereRepeats($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereRepeatFreq($value)
|
||||
*/
|
||||
|
||||
@@ -24,8 +24,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereName($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUserId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereEncrypted($value)
|
||||
* @property mixed spent
|
||||
* @property mixed lastActivity
|
||||
* @property-read float $spent
|
||||
* @property \Carbon\Carbon $lastActivity
|
||||
*/
|
||||
class Category extends Model
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
/**
|
||||
* Class Component
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
|
||||
@@ -5,7 +5,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
/**
|
||||
* Class LimitRepetition
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
@@ -14,7 +13,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @property \Carbon\Carbon $startdate
|
||||
* @property \Carbon\Carbon $enddate
|
||||
* @property float $amount
|
||||
* @property string $amount_encrypted
|
||||
* @property-read \FireflyIII\Models\BudgetLimit $budgetLimit
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereCreatedAt($value)
|
||||
@@ -23,7 +21,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereStartdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereEnddate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereAmount($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereAmountEncrypted($value)
|
||||
*/
|
||||
class LimitRepetition extends Model
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ use Zizaco\Entrust\EntrustPermission;
|
||||
* @property string $description
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.role')[] $roles
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.role[] $roles
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereName($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereDisplayName($value)
|
||||
|
||||
@@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
/**
|
||||
* Class PiggyBank
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
@@ -16,11 +15,12 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @property integer $account_id
|
||||
* @property string $name
|
||||
* @property float $targetamount
|
||||
* @property string $targetamount_encrypted
|
||||
* @property \Carbon\Carbon $startdate
|
||||
* @property \Carbon\Carbon $targetdate
|
||||
* @property integer $order
|
||||
* @property boolean $encrypted
|
||||
* @property boolean $remind_me
|
||||
* @property integer $reminder_skip
|
||||
* @property-read \FireflyIII\Models\Account $account
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankRepetition[] $piggyBankRepetitions
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
|
||||
@@ -31,18 +31,15 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereAccountId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereName($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamount($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamountEncrypted($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereStartdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereOrder($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value)
|
||||
* @property PiggyBankRepetition currentRep
|
||||
* @property string $reminder
|
||||
* @property integer $reminder_skip
|
||||
* @property boolean $remind_me
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminder($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminderSkip($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereRemindMe($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminderSkip($value)
|
||||
* @property-read \FireflyIII\Models\PiggyBankRepetition $currentRep
|
||||
* @property string $reminder
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminder($value)
|
||||
*/
|
||||
class PiggyBank extends Model
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
/**
|
||||
* Class PiggyBankEvent
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
@@ -14,7 +13,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @property integer $transaction_journal_id
|
||||
* @property \Carbon\Carbon $date
|
||||
* @property float $amount
|
||||
* @property string $amount_encrypted
|
||||
* @property-read \FireflyIII\Models\PiggyBank $piggyBank
|
||||
* @property-read \FireflyIII\Models\TransactionJournal $transactionJournal
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereId($value)
|
||||
@@ -24,7 +22,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereTransactionJournalId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereDate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereAmount($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereAmountEncrypted($value)
|
||||
*/
|
||||
class PiggyBankEvent extends Model
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
/**
|
||||
* Class PiggyBankRepetition
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
@@ -16,7 +15,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @property \Carbon\Carbon $startdate
|
||||
* @property \Carbon\Carbon $targetdate
|
||||
* @property float $currentamount
|
||||
* @property string $currentamount_encrypted
|
||||
* @property-read \FireflyIII\Models\PiggyBank $piggyBank
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCreatedAt($value)
|
||||
@@ -25,9 +23,8 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereStartdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereTargetdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCurrentamount($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCurrentamountEncrypted($value)
|
||||
* @method static \FireflyIII\Models\PiggyBankRepetition onDates($start, $target)
|
||||
* @method static \FireflyIII\Models\PiggyBankRepetition relevantOnDate($date)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition onDates($start, $target)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition relevantOnDate($date)
|
||||
*/
|
||||
class PiggyBankRepetition extends Model
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
/**
|
||||
* Class Preference
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
|
||||
@@ -14,8 +14,8 @@ use Zizaco\Entrust\EntrustRole;
|
||||
* @property string $description
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('auth.model')[] $users
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.permission')[] $perms
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('auth.model[] $users
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.permission[] $perms
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereName($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereDisplayName($value)
|
||||
|
||||
@@ -64,7 +64,7 @@ class Tag extends Model
|
||||
// everything but the tag:
|
||||
unset($fields['tagMode']);
|
||||
$search = $fields;
|
||||
unset($search['name']);
|
||||
unset($search['tag']);
|
||||
|
||||
$query = Tag::orderBy('id');
|
||||
foreach ($search as $name => $value) {
|
||||
|
||||
@@ -9,7 +9,6 @@ use Watson\Validating\ValidatingTrait;
|
||||
/**
|
||||
* Class Transaction
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
@@ -19,7 +18,6 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @property integer $transaction_journal_id
|
||||
* @property string $description
|
||||
* @property float $amount
|
||||
* @property string $amount_encrypted
|
||||
* @property-read \FireflyIII\Models\Account $account
|
||||
* @property-read \FireflyIII\Models\TransactionJournal $transactionJournal
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereId($value)
|
||||
@@ -30,11 +28,10 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereTransactionJournalId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereDescription($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAmount($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAmountEncrypted($value)
|
||||
* @method static \FireflyIII\Models\Transaction after($date)
|
||||
* @method static \FireflyIII\Models\Transaction before($date)
|
||||
* @property mixed before
|
||||
* @property mixed after
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction after($date)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction before($date)
|
||||
* @property float $before
|
||||
* @property float $after
|
||||
*/
|
||||
class Transaction extends Model
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
/**
|
||||
* Class TransactionCurrency
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
|
||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
/**
|
||||
* Class TransactionGroup
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
|
||||
@@ -13,7 +13,6 @@ use Watson\Validating\ValidatingTrait;
|
||||
* Class TransactionJournal
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
* @SuppressWarnings (PHPMD.TooManyMethods)
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
@@ -27,16 +26,17 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @property \Carbon\Carbon $date
|
||||
* @property boolean $encrypted
|
||||
* @property integer $order
|
||||
* @property integer $tag_count
|
||||
* @property-read \FireflyIII\Models\Bill $bill
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $categories
|
||||
* @property-read mixed $actual_amount
|
||||
* @property-read mixed $amount
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Tag[] $tags
|
||||
* @property-read mixed $asset_account
|
||||
* @property-read mixed $correct_amount
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions
|
||||
* @property-read mixed $corrected_actual_amount
|
||||
* @property-read mixed $destination_account
|
||||
* @property-read mixed $source_account
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
|
||||
* @property-read \FireflyIII\Models\TransactionCurrency $transactionCurrency
|
||||
* @property-read \FireflyIII\Models\TransactionType $transactionType
|
||||
@@ -55,25 +55,20 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereEncrypted($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereOrder($value)
|
||||
* @method static \FireflyIII\Models\TransactionJournal accountIs($account)
|
||||
* @method static \FireflyIII\Models\TransactionJournal after($date)
|
||||
* @method static \FireflyIII\Models\TransactionJournal before($date)
|
||||
* @method static \FireflyIII\Models\TransactionJournal onDate($date)
|
||||
* @method static \FireflyIII\Models\TransactionJournal transactionTypes($types)
|
||||
* @method static \FireflyIII\Models\TransactionJournal withRelevantData()
|
||||
* @property-read mixed $expense_account
|
||||
* @property string account_encrypted
|
||||
* @property bool joinedTransactions
|
||||
* @property bool joinedTransactionTypes
|
||||
* @property mixed account_id
|
||||
* @property mixed name
|
||||
* @property mixed symbol
|
||||
* @property-read mixed $correct_amount
|
||||
* @method static \FireflyIII\Models\TransactionJournal orderBy
|
||||
* @method static \FireflyIII\Models\TransactionJournal|null first
|
||||
* @property-read mixed $source_account
|
||||
* @property integer $tag_count
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTagCount($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal accountIs($account)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal after($date)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal before($date)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal onDate($date)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal transactionTypes($types)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal withRelevantData()
|
||||
* @property-read bool $account_encrypted
|
||||
* @property-read bool $joinedTransactions
|
||||
* @property-read bool $joinedTransactionTypes
|
||||
* @property-read int $account_id
|
||||
* @property string $name
|
||||
* @property-read string $symbol
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Attachment[] $attachments
|
||||
*/
|
||||
class TransactionJournal extends Model
|
||||
{
|
||||
@@ -150,14 +145,9 @@ class TransactionJournal extends Model
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$amount = '0';
|
||||
bcscale(2);
|
||||
/** @var Transaction $t */
|
||||
foreach ($this->transactions as $t) {
|
||||
if ($t->amount > 0) {
|
||||
$amount = $t->amount;
|
||||
}
|
||||
}
|
||||
$set = $this->transactions->sortByDesc('amount');
|
||||
$amount = $set->first()->amount;
|
||||
|
||||
if (intval($this->tag_count) === 1) {
|
||||
// get amount for single tag:
|
||||
@@ -175,6 +165,49 @@ class TransactionJournal extends Model
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tag $tag
|
||||
* @param $amount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function amountByTagAdvancePayment(Tag $tag, $amount)
|
||||
{
|
||||
if ($this->transactionType->type == 'Withdrawal') {
|
||||
$others = $tag->transactionJournals()->transactionTypes(['Deposit'])->get();
|
||||
foreach ($others as $other) {
|
||||
$amount = bcsub($amount, $other->actual_amount);
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
if ($this->transactionType->type == 'Deposit') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tag
|
||||
* @param $amount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function amountByTagBalancingAct($tag, $amount)
|
||||
{
|
||||
if ($this->transactionType->type == 'Withdrawal') {
|
||||
$transfer = $tag->transactionJournals()->transactionTypes(['Transfer'])->first();
|
||||
if ($transfer) {
|
||||
$amount = bcsub($amount, $transfer->actual_amount);
|
||||
|
||||
return $amount;
|
||||
}
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assuming the journal has only one tag. Parameter amount is used as fallback.
|
||||
*
|
||||
@@ -186,28 +219,12 @@ class TransactionJournal extends Model
|
||||
protected function amountByTag(Tag $tag, $amount)
|
||||
{
|
||||
if ($tag->tagMode == 'advancePayment') {
|
||||
if ($this->transactionType->type == 'Withdrawal') {
|
||||
$others = $tag->transactionJournals()->transactionTypes(['Deposit'])->get();
|
||||
foreach ($others as $other) {
|
||||
$amount = bcsub($amount, $other->actual_amount);
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
if ($this->transactionType->type == 'Deposit') {
|
||||
return '0';
|
||||
}
|
||||
return $this->amountByTagAdvancePayment($tag, $amount);
|
||||
}
|
||||
|
||||
if ($tag->tagMode == 'balancingAct') {
|
||||
if ($this->transactionType->type == 'Withdrawal') {
|
||||
$transfer = $tag->transactionJournals()->transactionTypes(['Transfer'])->first();
|
||||
if ($transfer) {
|
||||
$amount = bcsub($amount, $transfer->actual_amount);
|
||||
return $this->amountByTagBalancingAct($tag, $amount);
|
||||
|
||||
return $amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $amount;
|
||||
@@ -451,6 +468,14 @@ class TransactionJournal extends Model
|
||||
$this->attributes['encrypted'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
*/
|
||||
public function attachments()
|
||||
{
|
||||
return $this->morphMany('FireflyIII\Models\Attachment', 'attachable');
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
|
||||
@@ -5,7 +5,6 @@ use Illuminate\Database\Eloquent\Model;
|
||||
/**
|
||||
* Class TransactionRelation
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class TransactionRelation extends Model
|
||||
|
||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
/**
|
||||
* Class TransactionType
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace FireflyIII\Providers;
|
||||
|
||||
use App;
|
||||
use FireflyIII\Support\Amount;
|
||||
use FireflyIII\Support\ExpandedForm;
|
||||
use FireflyIII\Support\Navigation;
|
||||
@@ -38,7 +37,7 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
* Default Twig configuration:
|
||||
*/
|
||||
|
||||
$config = App::make('config');
|
||||
$config = app('config');
|
||||
Twig::addExtension(new Functions($config));
|
||||
Twig::addExtension(new PiggyBank);
|
||||
Twig::addExtension(new General);
|
||||
@@ -89,13 +88,16 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
$this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface', 'FireflyIII\Repositories\Attachment\AttachmentRepository');
|
||||
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
|
||||
|
||||
// CSV import
|
||||
$this->app->bind('FireflyIII\Helpers\Csv\WizardInterface', 'FireflyIII\Helpers\Csv\Wizard');
|
||||
|
||||
// attachments
|
||||
$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');
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace FireflyIII\Repositories\Account;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
@@ -47,11 +46,17 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Account $moveTo
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy(Account $account)
|
||||
public function destroy(Account $account, Account $moveTo = null)
|
||||
{
|
||||
if (!is_null($moveTo)) {
|
||||
// update all transactions:
|
||||
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
|
||||
}
|
||||
|
||||
$account->delete();
|
||||
|
||||
return true;
|
||||
@@ -64,11 +69,18 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
public function getAccounts(array $types)
|
||||
{
|
||||
/** @var Collection $result */
|
||||
$result = Auth::user()->accounts()->with(
|
||||
['accountmeta' => function (HasMany $query) {
|
||||
$query->where('name', 'accountRole');
|
||||
}]
|
||||
)->accountTypeIn($types)->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
)->accountTypeIn($types)->get(['accounts.*']);
|
||||
|
||||
$result = $result->sortBy(
|
||||
function (Account $account) {
|
||||
return strtolower($account->name);
|
||||
}
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -116,17 +128,17 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
$query = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account']);
|
||||
|
||||
|
||||
if ($preference->data == []) {
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
} else {
|
||||
$accounts = Auth::user()->accounts()->whereIn('id', $preference->data)->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
if (count($preference->data) > 0) {
|
||||
$query->whereIn('accounts.id', $preference->data);
|
||||
}
|
||||
|
||||
$cache->store($accounts);
|
||||
$result = $query->get(['accounts.*']);
|
||||
|
||||
return $accounts;
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,23 +207,6 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function getLastActivity(Account $account)
|
||||
{
|
||||
$lastTransaction = $account->transactions()->leftJoin(
|
||||
'transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)->orderBy('transaction_journals.date', 'DESC')->first(['transactions.*', 'transaction_journals.date']);
|
||||
if ($lastTransaction) {
|
||||
return $lastTransaction->transactionjournal->date;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the accounts of a user that have piggy banks connected to them.
|
||||
*
|
||||
@@ -241,6 +236,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
if (count($ids) > 0) {
|
||||
$accounts = Auth::user()->accounts()->whereIn('id', $ids)->get();
|
||||
}
|
||||
bcscale(2);
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($start, $end) {
|
||||
@@ -254,7 +250,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
// sum of piggy bank amounts on this account:
|
||||
// diff between endBalance and piggyBalance.
|
||||
// then, percentage.
|
||||
$difference = $account->endBalance - $account->piggyBalance;
|
||||
$difference = bcsub($account->endBalance, $account->piggyBalance);
|
||||
$account->difference = $difference;
|
||||
$account->percentage = $difference != 0 && $account->endBalance != 0 ? round((($difference / $account->endBalance) * 100)) : 100;
|
||||
|
||||
@@ -282,13 +278,15 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$start = clone Session::get('start', new Carbon);
|
||||
$end = clone Session::get('end', new Carbon);
|
||||
|
||||
bcscale(2);
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($start, $end) {
|
||||
$account->startBalance = Steam::balance($account, $start);
|
||||
$account->endBalance = Steam::balance($account, $end);
|
||||
|
||||
// diff (negative when lost, positive when gained)
|
||||
$diff = $account->endBalance - $account->startBalance;
|
||||
$diff = bcsub($account->endBalance, $account->startBalance);
|
||||
|
||||
if ($diff < 0 && $account->startBalance > 0) {
|
||||
// percentage lost compared to start.
|
||||
@@ -417,11 +415,11 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
* @return string
|
||||
*/
|
||||
public function sumOfEverything()
|
||||
{
|
||||
return floatval(Auth::user()->transactions()->sum('amount'));
|
||||
return Auth::user()->transactions()->sum('amount');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -456,6 +454,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'accountType' => $type,
|
||||
'name' => $data['name'] . ' initial balance',
|
||||
'active' => false,
|
||||
'iban' => '',
|
||||
'virtualBalance' => 0,
|
||||
];
|
||||
$opposing = $this->storeAccount($opposingData);
|
||||
@@ -505,7 +504,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$existingAccount = Account::firstOrNullEncrypted($searchData);
|
||||
if (!$existingAccount) {
|
||||
Log::error('Account create error: ' . $newAccount->getErrors()->toJson());
|
||||
App::abort(500);
|
||||
abort(500);
|
||||
// @codeCoverageIgnoreStart
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
@@ -549,10 +548,8 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
protected function storeInitialBalance(Account $account, Account $opposing, array $data)
|
||||
{
|
||||
$type = $data['openingBalance'] < 0 ? 'Withdrawal' : 'Deposit';
|
||||
$transactionType = TransactionType::whereType($type)->first();
|
||||
|
||||
$journal = new TransactionJournal(
|
||||
$transactionType = TransactionType::whereType('Opening balance')->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => $data['user'],
|
||||
'transaction_type_id' => $transactionType->id,
|
||||
@@ -564,7 +561,6 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'encrypted' => true
|
||||
]
|
||||
);
|
||||
$journal->save();
|
||||
|
||||
if ($data['openingBalance'] < 0) {
|
||||
$firstAccount = $opposing;
|
||||
@@ -577,6 +573,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$firstAmount = $data['openingBalance'];
|
||||
$secondAmount = $data['openingBalance'] * -1;
|
||||
}
|
||||
|
||||
$one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]);
|
||||
$one->save();// first transaction: from
|
||||
|
||||
|
||||
@@ -26,10 +26,11 @@ interface AccountRepositoryInterface
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Account $moveTo
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy(Account $account);
|
||||
public function destroy(Account $account, Account $moveTo = null);
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
@@ -95,14 +96,7 @@ interface AccountRepositoryInterface
|
||||
public function getJournals(Account $account, $page);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function getLastActivity(Account $account);
|
||||
|
||||
/**
|
||||
* @return float
|
||||
* @return string
|
||||
*/
|
||||
public function sumOfEverything();
|
||||
|
||||
|
||||
47
app/Repositories/Attachment/AttachmentRepository.php
Normal file
47
app/Repositories/Attachment/AttachmentRepository.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Repositories\Attachment;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
|
||||
/**
|
||||
* Class AttachmentRepository
|
||||
*
|
||||
* @package FireflyIII\Repositories\Attachment
|
||||
*/
|
||||
class AttachmentRepository implements AttachmentRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy(Attachment $attachment)
|
||||
{
|
||||
/** @var \FireflyIII\Helpers\Attachments\AttachmentHelperInterface $helper */
|
||||
$helper = app('FireflyIII\Helpers\Attachments\AttachmentHelperInterface');
|
||||
|
||||
$file = $helper->getAttachmentLocation($attachment);
|
||||
unlink($file);
|
||||
$attachment->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
* @param array $data
|
||||
*
|
||||
* @return Attachment
|
||||
*/
|
||||
public function update(Attachment $attachment, array $data)
|
||||
{
|
||||
|
||||
$attachment->title = $data['title'];
|
||||
$attachment->description = $data['description'];
|
||||
$attachment->notes = $data['notes'];
|
||||
$attachment->save();
|
||||
|
||||
return $attachment;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Repositories\Attachment;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
|
||||
/**
|
||||
* Interface AttachmentRepositoryInterface
|
||||
*
|
||||
* @package FireflyIII\Repositories\Attachment
|
||||
*/
|
||||
interface AttachmentRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy(Attachment $attachment);
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
* @param array $attachmentData
|
||||
*
|
||||
* @return Attachment
|
||||
*/
|
||||
public function update(Attachment $attachment, array $attachmentData);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class BillRepository
|
||||
@@ -39,6 +40,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
return $amount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a fake bill to help the chart controller.
|
||||
*
|
||||
@@ -383,4 +385,84 @@ class BillRepository implements BillRepositoryInterface
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a collection of paid bills and a collection of unpaid bills to be used
|
||||
* in the pie chart on the front page.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBillsForChart(Carbon $start, Carbon $end)
|
||||
{
|
||||
$paid = new Collection;
|
||||
$unpaid = new Collection;
|
||||
|
||||
$bills = $this->getActiveBills();
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
$ranges = $this->getRanges($bill, $start, $end);
|
||||
|
||||
foreach ($ranges as $range) {
|
||||
// paid a bill in this range?
|
||||
$journals = $this->getJournalsInRange($bill, $range['start'], $range['end']);
|
||||
if ($journals->count() == 0) {
|
||||
$unpaid->push([$bill, $range['start']]);
|
||||
} else {
|
||||
$paid = $paid->merge($journals);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$set = new Collection;
|
||||
$set->put('paid', $paid);
|
||||
$set->put('unpaid', $unpaid);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the paid/unpaid bills collection set up before and expands it using
|
||||
* credit cards the user might have.
|
||||
*
|
||||
* @param Collection $set
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCreditCardInfoForChart(Collection $set, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
||||
$accounts = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
|
||||
$creditCards = $accounts->getCreditCards();
|
||||
$paid = $set->get('paid');
|
||||
$unpaid = $set->get('unpaid');
|
||||
|
||||
foreach ($creditCards as $creditCard) {
|
||||
$balance = Steam::balance($creditCard, $end, true);
|
||||
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
|
||||
if ($balance < 0) {
|
||||
// unpaid! create a fake bill that matches the amount.
|
||||
$description = $creditCard->name;
|
||||
$amount = $balance * -1;
|
||||
$fakeBill = $this->createFakeBill($description, $date, $amount);
|
||||
unset($description, $amount);
|
||||
$unpaid->push([$fakeBill, $date]);
|
||||
}
|
||||
if ($balance == 0) {
|
||||
// find transfer(s) TO the credit card which should account for
|
||||
// anything paid. If not, the CC is not yet used.
|
||||
$journals = $accounts->getTransfersInRange($creditCard, $start, $end);
|
||||
$paid = $paid->merge($journals);
|
||||
}
|
||||
}
|
||||
$set = new Collection;
|
||||
$set->put('paid', $paid);
|
||||
$set->put('unpaid', $unpaid);
|
||||
|
||||
return $set;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,29 @@ use Illuminate\Support\Collection;
|
||||
interface BillRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Takes the paid/unpaid bills collection set up before and expands it using
|
||||
* credit cards the user might have.
|
||||
*
|
||||
* @param Collection $set
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCreditCardInfoForChart(Collection $set, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Gets a collection of paid bills and a collection of unpaid bills to be used
|
||||
* in the pie chart on the front page.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBillsForChart(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Returns the sum of all payments connected to this bill between the dates.
|
||||
*
|
||||
|
||||
@@ -52,9 +52,10 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
*/
|
||||
public function expensesOnDayCorrected(Budget $budget, Carbon $date)
|
||||
{
|
||||
$sum = floatval($budget->transactionjournals()->transactionTypes(['Withdrawal'])->onDate($date)->get(['transaction_journals.*'])->sum('amount'));
|
||||
bcscale(2);
|
||||
$sum = $budget->transactionjournals()->transactionTypes(['Withdrawal'])->onDate($date)->get(['transaction_journals.*'])->sum('amount');
|
||||
|
||||
return $sum * -1;
|
||||
return bcmul($sum, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,9 +63,16 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
*/
|
||||
public function getActiveBudgets()
|
||||
{
|
||||
$budgets = Auth::user()->budgets()->where('active', 1)->get();
|
||||
/** @var Collection $set */
|
||||
$set = Auth::user()->budgets()->where('active', 1)->get();
|
||||
|
||||
return $budgets;
|
||||
$set = $set->sortBy(
|
||||
function (Budget $budget) {
|
||||
return strtolower($budget->name);
|
||||
}
|
||||
);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,9 +108,16 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
*/
|
||||
public function getBudgets()
|
||||
{
|
||||
$budgets = Auth::user()->budgets()->get();
|
||||
/** @var Collection $set */
|
||||
$set = Auth::user()->budgets()->get();
|
||||
|
||||
return $budgets;
|
||||
$set = $set->sortBy(
|
||||
function (Budget $budget) {
|
||||
return strtolower($budget->name);
|
||||
}
|
||||
);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +161,16 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
*/
|
||||
public function getInactiveBudgets()
|
||||
{
|
||||
return Auth::user()->budgets()->where('active', 0)->get();
|
||||
/** @var Collection $set */
|
||||
$set = Auth::user()->budgets()->where('active', 0)->get();
|
||||
|
||||
$set = $set->sortBy(
|
||||
function (Budget $budget) {
|
||||
return strtolower($budget->name);
|
||||
}
|
||||
);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,7 +248,7 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
->first(['limit_repetitions.*']);
|
||||
|
||||
if ($repetition) {
|
||||
return floatval($repetition->amount);
|
||||
return $repetition->amount;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -276,7 +300,9 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->get(['transaction_journals.*'])->sum('amount');
|
||||
|
||||
return floatval($noBudgetSet) * -1;
|
||||
bcscale(2);
|
||||
|
||||
return bcmul($noBudgetSet, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,9 +313,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -136,7 +136,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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user