Compare commits

...

124 Commits

Author SHA1 Message Date
James Cole
8081eeb007 Merge branch 'release/3.4.0.1' 2015-05-05 12:35:22 +02:00
James Cole
56f91bd10d Increment version. 2015-05-05 12:35:11 +02:00
James Cole
8e20b78731 Cleanup. 2015-05-05 10:30:39 +02:00
James Cole
23a09b7081 Code cleanup. 2015-05-05 10:23:01 +02:00
James Cole
67fdd27499 Various code cleanup [skip ci] 2015-05-05 07:51:02 +02:00
James Cole
e1941daedd Updated phpdoc. [skip ci] 2015-05-05 07:48:34 +02:00
James Cole
f28bc568a4 Some cleanup [skip ci] 2015-05-05 07:43:16 +02:00
James Cole
f24cfe39aa Expanded some tests. 2015-05-05 07:41:30 +02:00
James Cole
59d2bf3f79 Covered transaction controller. 2015-05-05 07:28:04 +02:00
James Cole
3176e54614 Partial coverage of the transaction controller. 2015-05-04 23:46:14 +02:00
James Cole
eb090f7265 Better factory. 2015-05-04 22:33:52 +02:00
James Cole
6d3a9bfd18 Some cleaning up 2015-05-04 22:33:03 +02:00
James Cole
76f08b7acb Full coverage for chart controller. 2015-05-04 19:28:49 +02:00
James Cole
1ff99346aa Update chart [skip ci] 2015-05-04 18:51:51 +02:00
James Cole
369695ab32 Update chart [skip ci] 2015-05-04 18:51:38 +02:00
James Cole
7e23dd1d66 Update composer.lock [skip ci] 2015-05-04 18:45:32 +02:00
James Cole
0205d3fc5c Overspent transactions have a separate colour [skip ci] 2015-05-04 18:45:20 +02:00
James Cole
4660cf2ad5 Fixed a bug in the display of the current currency code. 2015-05-03 16:16:43 +02:00
James Cole
e26d08d674 Update git ignore. [skip ci] 2015-05-03 16:14:15 +02:00
James Cole
0932bf2797 Don't need these files [skip ci] 2015-05-03 16:13:38 +02:00
James Cole
f560fc6d76 Covered search controller. 2015-05-03 15:55:19 +02:00
James Cole
aa6209af00 Covered tag controller. 2015-05-03 15:00:39 +02:00
James Cole
4a51176193 General cleanup. 2015-05-03 12:58:55 +02:00
James Cole
bb84f7a434 Fixed parameter order [skip ci] 2015-05-03 12:54:39 +02:00
James Cole
48168b1ef0 Covered report controller. 2015-05-03 11:02:34 +02:00
James Cole
8281c7c83e Don't escape currency symbol [skip ci] 2015-05-03 10:11:16 +02:00
James Cole
a07c1e3c71 See code. [skip ci] 2015-05-03 10:07:18 +02:00
James Cole
0766bb31fe Better amount formatting [skip ci] 2015-05-03 10:03:50 +02:00
James Cole
ff4472c1a5 FormatAmountPlain is HTML safe [skip ci] 2015-05-03 10:01:38 +02:00
James Cole
17424740e5 Show plain amount instead of coloured amounts. [skip ci] 2015-05-03 10:00:47 +02:00
James Cole
dad0b2fcd3 Show plain amount instead of coloured amounts. [skip ci] 2015-05-03 10:00:03 +02:00
James Cole
c48dbf030f Covered the reminder controller. 2015-05-03 09:55:22 +02:00
James Cole
617808d603 Covered profile controller with tests. 2015-05-03 09:19:14 +02:00
James Cole
845149deee Boxes are empty, so even when it's zero, place the amount. 2015-05-03 08:56:44 +02:00
James Cole
1a9e009327 Merge branch 'release/3.4' into develop 2015-05-02 23:51:45 +02:00
James Cole
ae90815708 Merge branch 'release/3.4' 2015-05-02 23:51:44 +02:00
James Cole
1c460343b7 New version! 2015-05-02 23:51:34 +02:00
James Cole
26079622f9 Fixed JSON controller tests. 2015-05-02 23:39:39 +02:00
James Cole
06c6d6096f Fixed coverage. 2015-05-02 23:28:04 +02:00
James Cole
c8183aea51 Format amount [skip ci] 2015-05-02 22:50:40 +02:00
James Cole
7531134ad2 Some tag related fine tuning. 2015-05-02 22:41:32 +02:00
James Cole
cd0c6439c2 Delete tags now possible. 2015-05-02 22:30:59 +02:00
James Cole
c918c93f51 Forget me own head next. [skip ci] 2015-05-02 22:13:37 +02:00
James Cole
97d3bd68ed Show balance act tags. 2015-05-02 22:12:26 +02:00
James Cole
75f1e034ae Fixed menu. [skip ci] 2015-05-02 22:09:21 +02:00
James Cole
8e72f218f1 Show HTML 2015-05-02 22:05:57 +02:00
James Cole
d643e05c5a Basic amount format fix. 2015-05-02 22:05:18 +02:00
James Cole
fea44834d0 Fixed test to match fixed controller. 2015-05-02 21:22:27 +02:00
James Cole
195a2d7523 Removed all the old views. 2015-05-02 21:18:04 +02:00
James Cole
b2fd346ef8 Merge branch 'feature/twig' into develop 2015-05-02 21:16:21 +02:00
James Cole
1ff8b62cb7 And now with actual coverage. 2015-05-02 19:44:31 +02:00
James Cole
c7ae15a41a This should fix all twig tests. Let's find out! 2015-05-02 19:44:12 +02:00
James Cole
efe6f59f79 Last templates. Should cover everything. [skip ci] 2015-05-02 19:19:47 +02:00
James Cole
8e31d0491d Fixed search [skip ci] 2015-05-02 18:30:59 +02:00
James Cole
73d4a10351 Fixed reports [skip ci] 2015-05-02 18:26:55 +02:00
James Cole
81d9d4dbc7 Various files updated to twig [skip ci] 2015-05-02 13:20:49 +02:00
James Cole
184ec13f99 Fixed bills [skip ci] 2015-05-02 12:51:02 +02:00
James Cole
dee0422eff Fix preferences [skip ci] 2015-05-02 12:22:19 +02:00
James Cole
81a2975f1a Show piggy banks [skip ci] 2015-05-02 11:32:45 +02:00
James Cole
5cd2ef4a5e Some generic templates and the first piggy bank ones [skip ci] 2015-05-02 10:53:54 +02:00
James Cole
466c2a68c2 Add delete form [skip ci] 2015-05-02 10:42:41 +02:00
James Cole
0fb9fba531 New currency routes 2015-05-02 10:40:20 +02:00
James Cole
356dd2c6cd Creat / edit / index [skip ci] 2015-05-02 10:37:16 +02:00
James Cole
32c4661233 Fixed no budget / no category bread crumb [skip ci] 2015-05-02 09:49:37 +02:00
James Cole
a245b504ec Fixed bread crumbs. 2015-05-02 09:31:57 +02:00
James Cole
a2f5fbdfd3 Working on two more views [skip ci] 2015-05-02 09:29:34 +02:00
James Cole
04be26adc5 Fixed title [skip ci] 2015-05-02 09:26:20 +02:00
James Cole
be0adb7cf2 Create / edit category 2015-05-02 09:25:45 +02:00
James Cole
84fd92bf5a Categories [skip ci] 2015-05-02 09:21:42 +02:00
James Cole
ee4e061739 Removed code from budget index [skip ci] 2015-05-02 09:21:32 +02:00
James Cole
4a2b01cd9a Menu fixes [skip ci] 2015-05-02 09:16:17 +02:00
James Cole
efdd6460fb Fixed injection. 2015-05-02 09:08:41 +02:00
James Cole
803827e05c Fixed more views. [skip ci] 2015-05-02 09:06:07 +02:00
James Cole
a41d5e9ab3 New budget [skip ci] 2015-05-02 08:32:20 +02:00
James Cole
e94333f877 Can view budgets [skip ci] 2015-05-02 08:28:24 +02:00
James Cole
6dbb80d687 Optimisations [skip ci] 2015-05-02 08:09:54 +02:00
James Cole
31a1031624 And delete is fixed. 2015-05-01 23:39:45 +02:00
James Cole
f8e9ce0d52 Can edit as well. 2015-05-01 23:35:35 +02:00
James Cole
11baa968cd Can create accounts. 2015-05-01 23:17:17 +02:00
James Cole
3e5e5b376f Made it almost to the accounts. 2015-05-01 22:44:35 +02:00
James Cole
bda18f296d Optimised Twig extensions. 2015-05-01 20:17:06 +02:00
James Cole
287d110c84 Small bug fix in budget chart. 2015-05-01 18:45:42 +02:00
James Cole
c98275e73a More templates converted to twig. 2015-05-01 18:44:49 +02:00
James Cole
aa573cc951 Fix redirect 2015-05-01 14:32:31 +02:00
James Cole
883d3d86e3 Update a test. 2015-05-01 14:32:26 +02:00
James Cole
fb047bd5f4 Fix migration. 2015-05-01 08:34:53 +02:00
James Cole
66a04d8365 Slightly different chart on index. 2015-05-01 08:34:44 +02:00
James Cole
a0e501f9fd First attempt at implementing Twig. 2015-05-01 08:29:41 +02:00
James Cole
8b40d3346d An attempt at showing tag info. 2015-05-01 06:47:24 +02:00
James Cole
eddf5cd250 Fix button, close #74 2015-05-01 06:38:48 +02:00
James Cole
ee5c534ca3 Took the time to fix the tests. 2015-04-30 17:32:00 +02:00
James Cole
fd4e77ae0f Catch empty tags. 2015-04-28 21:01:54 +02:00
James Cole
b747c50aa3 Fix method to return object, not key. 2015-04-28 21:00:26 +02:00
James Cole
deebdd86a6 And another small JS fix [skip ci] 2015-04-28 20:20:16 +02:00
James Cole
b2db79cc10 Fixed some small CSS / JS problems. 2015-04-28 20:17:31 +02:00
James Cole
bbab370b1e Some new code. 2015-04-28 17:10:52 +02:00
James Cole
db4adf399d Cleaning up. 2015-04-28 15:26:30 +02:00
James Cole
0683c87e52 Small check in tags. 2015-04-28 14:08:58 +02:00
James Cole
3f62b647fc Removed code related to "related transactions". 2015-04-28 13:50:53 +02:00
James Cole
2562a5b30d Don't save all tags unconditionally. 2015-04-28 13:47:13 +02:00
James Cole
e232f2e223 Delete tags 2015-04-28 11:04:46 +02:00
James Cole
21644ff4dd Routes will throw 404's 2015-04-28 11:04:38 +02:00
James Cole
be96a4fce5 Show tags in transaction. 2015-04-28 10:51:56 +02:00
James Cole
a1cabcbed3 Show tag icons. 2015-04-28 10:50:43 +02:00
James Cole
ce933b1f06 Edit and update tags. 2015-04-28 10:36:13 +02:00
James Cole
51ae130922 Fixed the build by adding new migrations for each step. 2015-04-28 09:54:22 +02:00
James Cole
da1bc18a47 Better list for piggy banks. 2015-04-28 09:15:31 +02:00
James Cole
e7165a526b First attempt at basic tag functionality. 2015-04-28 08:58:01 +02:00
James Cole
6081cc399f Small bug fixes and cleaning up. 2015-04-28 08:12:12 +02:00
James Cole
7c5c24e15d Moved edit buttons. 2015-04-26 07:42:55 +02:00
James Cole
e3e55b4347 Moved all create-buttons lower. 2015-04-26 07:39:49 +02:00
James Cole
40d8e7d1ad Fixed a bug where transfers away from a piggy bank's account would not properly reflect the piggy bank. 2015-04-24 12:06:13 +02:00
James Cole
59e23b89f2 Removed unnecessary sort. 2015-04-24 11:54:23 +02:00
James Cole
cc33af8193 Could not set order. 2015-04-24 10:00:56 +02:00
James Cole
0e1e7eb2a9 Merge branch 'release/3.3.9' 2015-04-22 08:08:14 +02:00
James Cole
52a28a7758 Merge branch 'release/3.3.9' into develop 2015-04-22 08:08:14 +02:00
James Cole
3f752d6832 New read me. 2015-04-22 08:08:05 +02:00
James Cole
fe714e9989 Built a routine that will allow you to completely delete an account. 2015-04-22 07:54:56 +02:00
James Cole
0d3213a379 Covered the preferences controller. 2015-04-21 17:19:14 +02:00
James Cole
44056629e8 Use local db instead of constant migrating. 2015-04-20 22:08:24 +02:00
James Cole
54125c05d3 New tests and prep for future runs. 2015-04-20 21:57:20 +02:00
James Cole
7d32e50f25 Mentioned wrong amount. 2015-04-20 20:56:28 +02:00
James Cole
4af9ff49a0 Fixed a bug in the report controller that grouped transactions wrong. 2015-04-20 20:54:55 +02:00
James Cole
41dad4091a Merge branch 'release/3.3.8' into develop 2015-04-20 18:07:02 +02:00
257 changed files with 8786 additions and 4571 deletions

3
.gitignore vendored
View File

@@ -28,3 +28,6 @@ tests/_output/*
clover.xml clover.xml
node_modules/ node_modules/
addNewLines.php addNewLines.php
.phpstorm.meta.php
.env.backup
.env.local

View File

@@ -1,4 +1,4 @@
Firefly III (v3.3.8) Firefly III (v3.4.0.1)
=========== ===========
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii) [![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii)
@@ -6,7 +6,7 @@ Firefly III (v3.3.8)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102/mini.png)](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102/mini.png)](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102)
[![Code Climate](https://codeclimate.com/github/JC5/firefly-iii/badges/gpa.svg)](https://codeclimate.com/github/JC5/firefly-iii) [![Code Climate](https://codeclimate.com/github/JC5/firefly-iii/badges/gpa.svg)](https://codeclimate.com/github/JC5/firefly-iii)
[![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.svg?branch=master)](https://coveralls.io/r/JC5/firefly-iii?branch=master) [![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.svg?branch=master)](https://coveralls.io/r/JC5/firefly-iii?branch=master)
[![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.svg?branch=master)](https://coveralls.io/r/JC5/firefly-iii?branch=develop) [![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.svg?branch=develop)](https://coveralls.io/r/JC5/firefly-iii?branch=develop)
[![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii) [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![Total Downloads](https://poser.pugx.org/grumpydictator/firefly-iii/downloads.svg)](https://packagist.org/packages/grumpydictator/firefly-iii) [![Total Downloads](https://poser.pugx.org/grumpydictator/firefly-iii/downloads.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
@@ -22,7 +22,9 @@ laptop and [Firefly II](https://github.com/JC5/Firefly) is live.
If you're not sure if this tool is for you, please read the [full description](https://github.com/JC5/firefly-iii/wiki/full-description). If you're not sure if this tool is for you, please read the [full description](https://github.com/JC5/firefly-iii/wiki/full-description).
To install and use Firefly III, please read [the installation guide](https://github.com/JC5/firefly-iii/wiki/Installation), To install and use Firefly III, please read [the installation guide](https://github.com/JC5/firefly-iii/wiki/Installation),
[the upgrade guide](https://github.com/JC5/firefly-iii/wiki/Upgrade-instructions) (if applicable) and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)** [the upgrade guide](https://github.com/JC5/firefly-iii/wiki/Upgrade-instructions) (if applicable) 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.
## Current features ## Current features

View File

@@ -19,7 +19,8 @@ class JournalCreated extends Event
/** /**
* Create a new event instance. * Create a new event instance.
* *
* @return void * @param TransactionJournal $journal
* @param $piggyBankId
*/ */
public function __construct(TransactionJournal $journal, $piggyBankId) public function __construct(TransactionJournal $journal, $piggyBankId)
{ {

View File

@@ -2,6 +2,11 @@
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
/**
* Class JournalDeleted
*
* @package FireflyIII\Events
*/
class JournalDeleted extends Event class JournalDeleted extends Event
{ {
@@ -10,7 +15,6 @@ class JournalDeleted extends Event
/** /**
* Create a new event instance. * Create a new event instance.
* *
* @return void
*/ */
public function __construct() public function __construct()
{ {

View File

@@ -3,6 +3,11 @@
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
/**
* Class JournalSaved
*
* @package FireflyIII\Events
*/
class JournalSaved extends Event class JournalSaved extends Event
{ {
@@ -13,7 +18,7 @@ class JournalSaved extends Event
/** /**
* Create a new event instance. * Create a new event instance.
* *
* @return void * @param TransactionJournal $journal
*/ */
public function __construct(TransactionJournal $journal) public function __construct(TransactionJournal $journal)
{ {

View File

@@ -49,8 +49,7 @@ class Handler extends ExceptionHandler
*/ */
public function report(Exception $e) public function report(Exception $e)
{ {
/** @noinspection PhpInconsistentReturnPointsInspection */ parent::report($e);
return parent::report($e);
} }
} }

View File

@@ -19,7 +19,6 @@ class ConnectJournalToPiggyBank
/** /**
* Create the event handler. * Create the event handler.
* *
* @return void
*/ */
public function __construct() public function __construct()
{ {
@@ -65,6 +64,22 @@ class ConnectJournalToPiggyBank
} }
Log::debug('Found rep! ' . $repetition->id); Log::debug('Found rep! ' . $repetition->id);
/*
* Add amount when
*/
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
if ($transaction->account_id == $piggyBank->account_id) {
if ($transaction->amount < 0) {
$amount = $amount * -1;
Log::debug('Transaction is away from piggy, so amount becomes ' . $amount);
} else {
Log::debug('Transaction is to from piggy, so amount stays ' . $amount);
}
}
}
$repetition->currentamount += $amount; $repetition->currentamount += $amount;
$repetition->save(); $repetition->save();

View File

@@ -15,7 +15,6 @@ class RescanJournal
/** /**
* Create the event handler. * Create the event handler.
* *
* @return void
*/ */
public function __construct() public function __construct()
{ {
@@ -41,7 +40,7 @@ class RescanJournal
Log::debug('Found ' . $list->count() . ' bills to check.'); Log::debug('Found ' . $list->count() . ' bills to check.');
/** @var Bill $bill */ /** @var \FireflyIII\Models\Bill $bill */
foreach ($list as $bill) { foreach ($list as $bill) {
Log::debug('Now calling bill #' . $bill->id . ' (' . $bill->name . ')'); Log::debug('Now calling bill #' . $bill->id . ' (' . $bill->name . ')');
$repository->scan($bill, $journal); $repository->scan($bill, $journal);

View File

@@ -15,7 +15,6 @@ class UpdateJournalConnection
/** /**
* Create the event handler. * Create the event handler.
* *
* @return void
*/ */
public function __construct() public function __construct()
{ {

View File

@@ -54,7 +54,9 @@ class Help implements HelpInterface
} }
/** /**
* @return boolean * @param $route
*
* @return bool
*/ */
public function hasRoute($route) public function hasRoute($route)
{ {
@@ -62,10 +64,10 @@ class Help implements HelpInterface
} }
/** /**
* @param $title * @param $route
* @param array $content * @param array $content
* *
* @return void * @internal param $title
*/ */
public function putInCache($route, array $content) public function putInCache($route, array $content)
{ {

View File

@@ -18,16 +18,25 @@ interface HelpInterface
public function getFromCache($key); public function getFromCache($key);
/** /**
* @return boolean * @param $route
*
* @return array
*/
public function getFromGithub($route);
/**
* @param $route
*
* @return bool
*/ */
public function hasRoute($route); public function hasRoute($route);
/** /**
* @param $route * @param $route
* *
* @return array * @return bool
*/ */
public function getFromGithub($route); public function inCache($route);
/** /**
* @param $route * @param $route
@@ -36,11 +45,4 @@ interface HelpInterface
* @return void * @return void
*/ */
public function putInCache($route, array $content); public function putInCache($route, array $content);
/**
* @param $route
*
* @return bool
*/
public function inCache($route);
} }

View File

@@ -91,11 +91,11 @@ class ReportHelper implements ReportHelperInterface
$end = Carbon::now(); $end = Carbon::now();
$months = []; $months = [];
while ($start <= $end) { while ($start <= $end) {
$year = $start->format('Y'); $year = $start->year;
$months[$year][] = [ $months[$year][] = [
'formatted' => $start->format('F Y'), 'formatted' => $start->format('F Y'),
'month' => intval($start->format('m')), 'month' => $start->month,
'year' => intval($start->format('Y')), 'year' => $year,
]; ];
$start->addMonth(); $start->addMonth();
} }
@@ -114,10 +114,10 @@ class ReportHelper implements ReportHelperInterface
$end = Carbon::now(); $end = Carbon::now();
$years = []; $years = [];
while ($start <= $end) { while ($start <= $end) {
$years[] = $start->format('Y'); $years[] = $start->year;
$start->addYear(); $start->addYear();
} }
$years[] = Carbon::now()->format('Y'); $years[] = Carbon::now()->year;
// force the current year. // force the current year.
$years = array_unique($years); $years = array_unique($years);

View File

@@ -150,8 +150,16 @@ class ReportQuery implements ReportQueryInterface
$set = $query->get(['accounts.*']); $set = $query->get(['accounts.*']);
$set->each( $set->each(
function (Account $account) use ($start, $end) { function (Account $account) use ($start, $end) {
/**
* The balance for today always incorporates transactions
* made on today. So to get todays "start" balance, we sub one
* day.
*/
$yesterday = clone $start;
$yesterday->subDay();
/** @noinspection PhpParamsInspection */ /** @noinspection PhpParamsInspection */
$account->startBalance = Steam::balance($account, $start); $account->startBalance = Steam::balance($account, $yesterday);
$account->endBalance = Steam::balance($account, $end); $account->endBalance = Steam::balance($account, $end);
} }
); );
@@ -230,7 +238,7 @@ class ReportQuery implements ReportQueryInterface
// any deposit is fine. // any deposit is fine.
$query->where('transaction_types.type', 'Deposit'); $query->where('transaction_types.type', 'Deposit');
} }
$query->groupBy('t_from.account_id')->orderBy('transaction_journals.date'); $query->groupBy('transaction_journals.id')->orderBy('transaction_journals.date');
// get everything, decrypt and return // get everything, decrypt and return
$data = $query->get( $data = $query->get(

View File

@@ -11,6 +11,7 @@ use Input;
use Redirect; use Redirect;
use Session; use Session;
use Steam; use Steam;
use URL;
use View; use View;
/** /**
@@ -25,6 +26,7 @@ class AccountController extends Controller
*/ */
public function __construct() public function __construct()
{ {
parent::__construct();
View::share('mainTitleIcon', 'fa-credit-card'); View::share('mainTitleIcon', 'fa-credit-card');
View::share('title', 'Accounts'); View::share('title', 'Accounts');
} }
@@ -39,6 +41,12 @@ class AccountController extends Controller
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$subTitle = 'Create a new ' . e($what) . ' account'; $subTitle = 'Create a new ' . e($what) . ' account';
// put previous url in session if not redirect from store (not "create another").
if (Session::get('accounts.create.fromStore') !== true) {
Session::put('accounts.create.url', URL::previous());
}
Session::forget('accounts.create.fromStore');
return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle')); return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle'));
} }
@@ -52,15 +60,19 @@ class AccountController extends Controller
{ {
$subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; $subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
// put previous url in session
Session::put('accounts.delete.url', URL::previous());
return view('accounts.delete', compact('account', 'subTitle')); return view('accounts.delete', compact('account', 'subTitle'));
} }
/** /**
* @param Account $account * @param AccountRepositoryInterface $repository
* @param Account $account
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function destroy(Account $account, AccountRepositoryInterface $repository) public function destroy(AccountRepositoryInterface $repository, Account $account)
{ {
$type = $account->accountType->type; $type = $account->accountType->type;
@@ -71,16 +83,16 @@ class AccountController extends Controller
Session::flash('success', 'The ' . e($typeName) . ' account "' . e($name) . '" was deleted.'); Session::flash('success', 'The ' . e($typeName) . ' account "' . e($name) . '" was deleted.');
return Redirect::route('accounts.index', $typeName); return Redirect::to(Session::get('accounts.delete.url'));
} }
/** /**
* @param Account $account
* @param AccountRepositoryInterface $repository * @param AccountRepositoryInterface $repository
* @param Account $account
* *
* @return View * @return View
*/ */
public function edit(Account $account, AccountRepositoryInterface $repository) public function edit(AccountRepositoryInterface $repository, Account $account)
{ {
$what = Config::get('firefly.shortNamesByFullName')[$account->accountType->type]; $what = Config::get('firefly.shortNamesByFullName')[$account->accountType->type];
@@ -88,6 +100,12 @@ class AccountController extends Controller
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$openingBalance = $repository->openingBalanceTransaction($account); $openingBalance = $repository->openingBalanceTransaction($account);
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('accounts.edit.fromUpdate') !== true) {
Session::put('accounts.edit.url', URL::previous());
}
Session::forget('accounts.edit.fromUpdate');
// pre fill some useful values. // pre fill some useful values.
// the opening balance is tricky: // the opening balance is tricky:
@@ -112,12 +130,12 @@ class AccountController extends Controller
} }
/** /**
* @param $what
* @param AccountRepositoryInterface $repository * @param AccountRepositoryInterface $repository
* @param $what
* *
* @return View * @return View
*/ */
public function index($what, AccountRepositoryInterface $repository) public function index(AccountRepositoryInterface $repository, $what)
{ {
$subTitle = Config::get('firefly.subTitlesByIdentifier.' . $what); $subTitle = Config::get('firefly.subTitlesByIdentifier.' . $what);
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
@@ -141,12 +159,12 @@ class AccountController extends Controller
} }
/** /**
* @param Account $account
* @param AccountRepositoryInterface $repository * @param AccountRepositoryInterface $repository
* @param Account $account
* *
* @return View * @return View
*/ */
public function show(Account $account, AccountRepositoryInterface $repository) public function show(AccountRepositoryInterface $repository, Account $account)
{ {
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); $page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type); $subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type);
@@ -184,23 +202,28 @@ class AccountController extends Controller
Session::flash('success', 'New account "' . $account->name . '" stored!'); Session::flash('success', 'New account "' . $account->name . '" stored!');
if (intval(Input::get('create_another')) === 1) { if (intval(Input::get('create_another')) === 1) {
return Redirect::route('accounts.create', $request->input('what'))->withInput(); // set value so create routine will not overwrite URL:
Session::put('accounts.create.fromStore', true);
return Redirect::route('accounts.create')->withInput();
} }
return Redirect::route('accounts.index', $request->input('what')); // redirect to previous URL.
return Redirect::to(Session::get('accounts.create.url'));
} }
/** /**
* @param Account $account
* @param AccountFormRequest $request * @param AccountFormRequest $request
* @param AccountRepositoryInterface $repository * @param AccountRepositoryInterface $repository
* @param Account $account
* *
* @return \Illuminate\Http\RedirectResponse * @return $this|\Illuminate\Http\RedirectResponse
*/ */
public function update(Account $account, AccountFormRequest $request, AccountRepositoryInterface $repository) public function update(AccountFormRequest $request, AccountRepositoryInterface $repository, Account $account)
{ {
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$accountData = [ $accountData = [
'name' => $request->input('name'), 'name' => $request->input('name'),
'active' => $request->input('active'), 'active' => $request->input('active'),
@@ -219,10 +242,14 @@ class AccountController extends Controller
Session::flash('success', 'Account "' . $account->name . '" updated.'); Session::flash('success', 'Account "' . $account->name . '" updated.');
if (intval(Input::get('return_to_edit')) === 1) { if (intval(Input::get('return_to_edit')) === 1) {
return Redirect::route('accounts.edit', $account->id); // set value so edit routine will not overwrite URL:
Session::put('accounts.edit.fromUpdate', true);
return Redirect::route('accounts.edit', $account->id)->withInput(['return_to_edit' => 1]);
} }
return Redirect::route('accounts.index', $what); // redirect to previous URL.
return Redirect::to(Session::get('accounts.edit.url'));
} }

View File

@@ -8,6 +8,7 @@ use Illuminate\Http\Request;
use Illuminate\Mail\Message; use Illuminate\Mail\Message;
use Mail; use Mail;
use Session; use Session;
use Twig;
/** /**
* Class AuthController * Class AuthController
@@ -47,6 +48,16 @@ class AuthController extends Controller
$this->middleware('guest', ['except' => 'getLogout']); $this->middleware('guest', ['except' => 'getLogout']);
} }
/**
* Show the application login form.
*
* @return \Illuminate\Http\Response
*/
public function getLogin()
{
return Twig::render('auth.login');
}
/** /**
* Handle a registration request for the application. * Handle a registration request for the application.
* *

View File

@@ -29,16 +29,18 @@ class BillController extends Controller
*/ */
public function __construct() public function __construct()
{ {
parent::__construct();
View::share('title', 'Bills'); View::share('title', 'Bills');
View::share('mainTitleIcon', 'fa-calendar-o'); View::share('mainTitleIcon', 'fa-calendar-o');
} }
/** /**
* @param Bill $bill * @param AccountRepositoryInterface $repository
* @param Bill $bill
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function add(Bill $bill, AccountRepositoryInterface $repository) public function add(AccountRepositoryInterface $repository, Bill $bill)
{ {
$matches = explode(',', $bill->match); $matches = explode(',', $bill->match);
$description = []; $description = [];
@@ -83,7 +85,14 @@ class BillController extends Controller
{ {
$periods = Config::get('firefly.periods_to_text'); $periods = Config::get('firefly.periods_to_text');
return view('bills.create')->with('periods', $periods)->with('subTitle', 'Create new'); // put previous url in session if not redirect from store (not "create another").
if (Session::get('bills.create.fromStore') !== true) {
Session::put('bills.create.url', URL::previous());
}
Session::forget('bills.create.fromStore');
$subTitle = 'Create new bill';
return view('bills.create', compact('periods', 'subTitle'));
} }
/** /**
@@ -93,21 +102,26 @@ class BillController extends Controller
*/ */
public function delete(Bill $bill) public function delete(Bill $bill)
{ {
return view('bills.delete')->with('bill', $bill)->with('subTitle', 'Delete "' . e($bill->name) . '"'); // put previous url in session
Session::put('bills.delete.url', URL::previous());
$subTitle = 'Delete "' . e($bill->name) . '"';
return view('bills.delete', compact('bill', 'subTitle'));
} }
/** /**
* @param Bill $bill * @param BillRepositoryInterface $repository
* @param Bill $bill
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function destroy(Bill $bill, BillRepositoryInterface $repository) public function destroy(BillRepositoryInterface $repository, Bill $bill)
{ {
$repository->destroy($bill); $repository->destroy($bill);
Session::flash('success', 'The bill was deleted.'); Session::flash('success', 'The bill was deleted.');
return Redirect::route('bills.index'); return Redirect::to(Session::get('bills.delete.url'));
} }
@@ -118,9 +132,16 @@ class BillController extends Controller
*/ */
public function edit(Bill $bill) public function edit(Bill $bill)
{ {
$periods = Config::get('firefly.periods_to_text'); $periods = Config::get('firefly.periods_to_text');
$subTitle = 'Edit "' . e($bill->name) . '"';
return view('bills.edit')->with('periods', $periods)->with('bill', $bill)->with('subTitle', 'Edit "' . e($bill->name) . '"'); // put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('bills.edit.fromUpdate') !== true) {
Session::put('bills.edit.url', URL::previous());
}
Session::forget('bills.edit.fromUpdate');
return view('bills.edit', compact('subTitle', 'periods', 'bill'));
} }
/** /**
@@ -142,11 +163,12 @@ class BillController extends Controller
} }
/** /**
* @param Bill $bill * @param BillRepositoryInterface $repository
* @param Bill $bill
* *
* @return mixed * @return \Illuminate\Http\RedirectResponse
*/ */
public function rescan(Bill $bill, BillRepositoryInterface $repository) public function rescan(BillRepositoryInterface $repository, Bill $bill)
{ {
if (intval($bill->active) == 0) { if (intval($bill->active) == 0) {
Session::flash('warning', 'Inactive bills cannot be scanned.'); Session::flash('warning', 'Inactive bills cannot be scanned.');
@@ -167,21 +189,26 @@ class BillController extends Controller
} }
/** /**
* @param Bill $bill * @param BillRepositoryInterface $repository
* @param Bill $bill
* *
* @return mixed * @return mixed
*/ */
public function show(Bill $bill, BillRepositoryInterface $repository) public function show(BillRepositoryInterface $repository, Bill $bill)
{ {
$journals = $repository->getJournals($bill); $journals = $repository->getJournals($bill);
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill); $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill);
$hideBill = true; $hideBill = true;
$subTitle = e($bill->name);
return view('bills.show', compact('journals', 'hideBill', 'bill'))->with('subTitle', e($bill->name)); return view('bills.show', compact('journals', 'hideBill', 'bill', 'subTitle'));
} }
/** /**
* @return $this * @param BillFormRequest $request
* @param BillRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
*/ */
public function store(BillFormRequest $request, BillRepositoryInterface $repository) public function store(BillFormRequest $request, BillRepositoryInterface $repository)
{ {
@@ -190,30 +217,40 @@ class BillController extends Controller
Session::flash('success', 'Bill "' . e($bill->name) . '" stored.'); Session::flash('success', 'Bill "' . e($bill->name) . '" stored.');
if (intval(Input::get('create_another')) === 1) { if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('bills.create.fromStore', true);
return Redirect::route('bills.create')->withInput(); return Redirect::route('bills.create')->withInput();
} }
return Redirect::route('bills.index'); // redirect to previous URL.
return Redirect::to(Session::get('bills.create.url'));
} }
/** /**
* @param Bill $bill * @param BillFormRequest $request
* @param BillRepositoryInterface $repository
* @param Bill $bill
* *
* @return $this * @return $this|\Illuminate\Http\RedirectResponse
*/ */
public function update(Bill $bill, BillFormRequest $request, BillRepositoryInterface $repository) public function update(BillFormRequest $request, BillRepositoryInterface $repository, Bill $bill)
{ {
$billData = $request->getBillData(); $billData = $request->getBillData();
$bill = $repository->update($bill, $billData); $bill = $repository->update($bill, $billData);
if (intval(Input::get('return_to_edit')) === 1) {
return Redirect::route('bills.edit', $bill->id);
}
Session::flash('success', 'Bill "' . e($bill->name) . '" updated.'); Session::flash('success', 'Bill "' . e($bill->name) . '" updated.');
return Redirect::route('bills.index'); if (intval(Input::get('return_to_edit')) === 1) {
// set value so edit routine will not overwrite URL:
Session::put('bills.edit.fromUpdate', true);
return Redirect::route('bills.edit', $bill->id)->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.
return Redirect::to(Session::get('bills.edit.url'));
} }

View File

@@ -29,16 +29,19 @@ class BudgetController extends Controller
*/ */
public function __construct() public function __construct()
{ {
parent::__construct();
View::share('title', 'Budgets'); View::share('title', 'Budgets');
View::share('mainTitleIcon', 'fa-tasks'); View::share('mainTitleIcon', 'fa-tasks');
View::share('hideBudgets', true);
} }
/** /**
* @param Budget $budget * @param BudgetRepositoryInterface $repository
* @param Budget $budget
* *
* @return \Illuminate\Http\JsonResponse * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function amount(Budget $budget, BudgetRepositoryInterface $repository) public function amount(BudgetRepositoryInterface $repository, Budget $budget)
{ {
$amount = intval(Input::get('amount')); $amount = intval(Input::get('amount'));
$date = Session::get('start', Carbon::now()->startOfMonth()); $date = Session::get('start', Carbon::now()->startOfMonth());
@@ -58,8 +61,9 @@ class BudgetController extends Controller
Session::put('budgets.create.url', URL::previous()); Session::put('budgets.create.url', URL::previous());
} }
Session::forget('budgets.create.fromStore'); Session::forget('budgets.create.fromStore');
$subTitle = 'Create a new budget';
return view('budgets.create')->with('subTitle', 'Create a new budget'); return view('budgets.create', compact('subTitle'));
} }
/** /**
@@ -78,7 +82,8 @@ class BudgetController extends Controller
} }
/** /**
* @param Budget $budget * @param Budget $budget
* @param BudgetRepositoryInterface $repository
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
@@ -114,7 +119,9 @@ class BudgetController extends Controller
} }
/** /**
* @return mixed * @param BudgetRepositoryInterface $repository
*
* @return View
*/ */
public function index(BudgetRepositoryInterface $repository) public function index(BudgetRepositoryInterface $repository)
{ {
@@ -148,7 +155,9 @@ class BudgetController extends Controller
} }
/** /**
* @return \Illuminate\View\View * @param BudgetRepositoryInterface $repository
*
* @return View
*/ */
public function noBudget(BudgetRepositoryInterface $repository) public function noBudget(BudgetRepositoryInterface $repository)
{ {
@@ -161,7 +170,7 @@ class BudgetController extends Controller
} }
/** /**
* @return mixed * @return \Illuminate\Http\RedirectResponse
*/ */
public function postUpdateIncome() public function postUpdateIncome()
{ {
@@ -173,24 +182,26 @@ class BudgetController extends Controller
} }
/** /**
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
* *
* @param Budget $budget * @return View
* @param LimitRepetition $repetition
*
* @return \Illuminate\View\View
*/ */
public function show(Budget $budget, LimitRepetition $repetition = null, BudgetRepositoryInterface $repository) public function show(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition = null)
{ {
if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) { if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) {
return view('error')->with('message', 'Invalid selection.'); $message = 'Invalid selection.';
return view('error', compact('message'));
} }
$hideBudget = true; // used in transaction list. $journals = $repository->getJournals($budget, $repetition);
$journals = $repository->getJournals($budget, $repetition); $limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget);
$limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget); $subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name);
$subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name); $journals->setPath('/budgets/show/' . $budget->id);
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget')); return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
} }
/** /**
@@ -222,13 +233,13 @@ class BudgetController extends Controller
} }
/** /**
* @param Budget $budget
* @param BudgetFormRequest $request * @param BudgetFormRequest $request
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* @param Budget $budget
* *
* @return \Illuminate\Http\RedirectResponse * @return $this|\Illuminate\Http\RedirectResponse
*/ */
public function update(Budget $budget, BudgetFormRequest $request, BudgetRepositoryInterface $repository) public function update(BudgetFormRequest $request, BudgetRepositoryInterface $repository, Budget $budget)
{ {
$budgetData = [ $budgetData = [
'name' => $request->input('name'), 'name' => $request->input('name'),
@@ -252,14 +263,14 @@ class BudgetController extends Controller
} }
/** /**
* @return $this * @return View
*/ */
public function updateIncome() public function updateIncome()
{ {
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); $date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$budgetAmount = Preferences::get('budgetIncomeTotal' . $date, 1000); $amount = Preferences::get('budgetIncomeTotal' . $date, 1000);
return view('budgets.income')->with('amount', $budgetAmount); return view('budgets.income', compact('amount'));
} }
} }

View File

@@ -2,7 +2,6 @@
use Auth; use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\CategoryFormRequest; use FireflyIII\Http\Requests\CategoryFormRequest;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
@@ -26,6 +25,7 @@ class CategoryController extends Controller
*/ */
public function __construct() public function __construct()
{ {
parent::__construct();
View::share('title', 'Categories'); View::share('title', 'Categories');
View::share('mainTitleIcon', 'fa-bar-chart'); View::share('mainTitleIcon', 'fa-bar-chart');
} }
@@ -40,8 +40,9 @@ class CategoryController extends Controller
Session::put('categories.create.url', URL::previous()); Session::put('categories.create.url', URL::previous());
} }
Session::forget('categories.create.fromStore'); Session::forget('categories.create.fromStore');
$subTitle = 'Create a new category';
return view('categories.create')->with('subTitle', 'Create a new category'); return view('categories.create', compact('subTitle'));
} }
/** /**
@@ -51,7 +52,7 @@ class CategoryController extends Controller
*/ */
public function delete(Category $category) public function delete(Category $category)
{ {
$subTitle = 'Delete category' . e($category->name) . '"'; $subTitle = 'Delete category "' . e($category->name) . '"';
// put previous url in session // put previous url in session
Session::put('categories.delete.url', URL::previous()); Session::put('categories.delete.url', URL::previous());
@@ -60,11 +61,12 @@ class CategoryController extends Controller
} }
/** /**
* @param Category $category * @param CategoryRepositoryInterface $repository
* @param Category $category
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function destroy(Category $category, CategoryRepositoryInterface $repository) public function destroy(CategoryRepositoryInterface $repository, Category $category)
{ {
$name = $category->name; $name = $category->name;
@@ -95,8 +97,9 @@ class CategoryController extends Controller
} }
/** /**
* @return $this * @param CategoryRepositoryInterface $repository
* *
* @return $this
*/ */
public function index(CategoryRepositoryInterface $repository) public function index(CategoryRepositoryInterface $repository)
{ {
@@ -112,6 +115,8 @@ class CategoryController extends Controller
} }
/** /**
* @param CategoryRepositoryInterface $repository
*
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function noCategory(CategoryRepositoryInterface $repository) public function noCategory(CategoryRepositoryInterface $repository)
@@ -125,11 +130,12 @@ class CategoryController extends Controller
} }
/** /**
* @param Category $category * @param CategoryRepositoryInterface $repository
* @param Category $category
* *
* @return $this * @return View
*/ */
public function show(Category $category, CategoryRepositoryInterface $repository) public function show(CategoryRepositoryInterface $repository, Category $category)
{ {
$hideCategory = true; // used in list. $hideCategory = true; // used in list.
$page = intval(Input::get('page')); $page = intval(Input::get('page'));
@@ -168,13 +174,13 @@ class CategoryController extends Controller
/** /**
* @param Category $category
* @param CategoryFormRequest $request * @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository * @param CategoryRepositoryInterface $repository
* @param Category $category
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function update(Category $category, CategoryFormRequest $request, CategoryRepositoryInterface $repository) public function update(CategoryFormRequest $request, CategoryRepositoryInterface $repository, Category $category)
{ {
$categoryData = [ $categoryData = [
'name' => $request->input('name'), 'name' => $request->input('name'),

View File

@@ -3,6 +3,7 @@
use Illuminate\Foundation\Bus\DispatchesCommands; use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController; use Illuminate\Routing\Controller as BaseController;
use View;
/** /**
* Class Controller * Class Controller
@@ -14,4 +15,14 @@ abstract class Controller extends BaseController
use DispatchesCommands, ValidatesRequests; use DispatchesCommands, ValidatesRequests;
/**
*
*/
public function __construct()
{
View::share('hideBudgets', false);
View::share('hideCategories', false);
View::share('hideBills', false);
View::share('hideTags', false);
}
} }

View File

@@ -27,7 +27,7 @@ class CurrencyController extends Controller
*/ */
public function __construct() public function __construct()
{ {
parent::__construct();
View::share('title', 'Currencies'); View::share('title', 'Currencies');
View::share('mainTitleIcon', 'fa-usd'); View::share('mainTitleIcon', 'fa-usd');
} }
@@ -68,11 +68,12 @@ class CurrencyController extends Controller
} }
/** /**
* @param TransactionCurrency $currency * @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
* *
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View * @return \Illuminate\Http\RedirectResponse|View
*/ */
public function delete(TransactionCurrency $currency, CurrencyRepositoryInterface $repository) public function delete(CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{ {
if ($repository->countJournals($currency) > 0) { if ($repository->countJournals($currency) > 0) {
@@ -89,11 +90,13 @@ class CurrencyController extends Controller
} }
/** /**
* @param TransactionCurrency $currency * @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
* @throws \Exception
*/ */
public function destroy(TransactionCurrency $currency, CurrencyRepositoryInterface $repository) public function destroy(CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{ {
if ($repository->countJournals($currency) > 0) { if ($repository->countJournals($currency) > 0) {
Session::flash('error', 'Cannot destroy ' . e($currency->name) . ' because there are still transactions attached to it.'); Session::flash('error', 'Cannot destroy ' . e($currency->name) . ' because there are still transactions attached to it.');
@@ -130,6 +133,8 @@ class CurrencyController extends Controller
} }
/** /**
* @param CurrencyRepositoryInterface $repository
*
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function index(CurrencyRepositoryInterface $repository) public function index(CurrencyRepositoryInterface $repository)
@@ -141,7 +146,9 @@ class CurrencyController extends Controller
} }
/** /**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. *
* @param CurrencyFormRequest $request
* @param CurrencyRepositoryInterface $repository
* *
* @return $this|\Illuminate\Http\RedirectResponse * @return $this|\Illuminate\Http\RedirectResponse
*/ */
@@ -166,11 +173,13 @@ class CurrencyController extends Controller
} }
/** /**
* @param TransactionCurrency $currency * @param CurrencyFormRequest $request
* @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
* *
* @return $this|\Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function update(TransactionCurrency $currency, CurrencyFormRequest $request, CurrencyRepositoryInterface $repository) public function update(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{ {
$data = $request->getCurrencyData(); $data = $request->getCurrencyData();
$currency = $repository->update($currency, $data); $currency = $repository->update($currency, $data);

View File

@@ -35,12 +35,12 @@ class GoogleChartController extends Controller
/** /**
* @param GChart $chart
* @param Account $account * @param Account $account
* @param string $view
* *
* @return \Illuminate\Http\JsonResponse * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function accountBalanceChart(Account $account, GChart $chart) public function accountBalanceChart(GChart $chart, Account $account)
{ {
$chart->addColumn('Day of month', 'date'); $chart->addColumn('Day of month', 'date');
$chart->addColumn('Balance for ' . $account->name, 'number'); $chart->addColumn('Balance for ' . $account->name, 'number');
@@ -64,7 +64,8 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart * @param GChart $chart
* @param AccountRepositoryInterface $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
@@ -104,11 +105,13 @@ class GoogleChartController extends Controller
} }
/** /**
* @param int $year * @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param $year
* *
* @return $this|\Illuminate\Http\JsonResponse * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function allBudgetsAndSpending($year, GChart $chart, BudgetRepositoryInterface $repository) public function allBudgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, $year)
{ {
$budgets = $repository->getBudgets(); $budgets = $repository->getBudgets();
$chart->addColumn('Month', 'date'); $chart->addColumn('Month', 'date');
@@ -137,15 +140,16 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart * @param GChart $chart
* @param BudgetRepositoryInterface $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function allBudgetsHomeChart(GChart $chart, BudgetRepositoryInterface $repository) public function allBudgetsHomeChart(GChart $chart, BudgetRepositoryInterface $repository)
{ {
$chart->addColumn('Budget', 'string'); $chart->addColumn('Budget', 'string');
$chart->addColumn('Budgeted', 'number'); $chart->addColumn('Left', 'number');
$chart->addColumn('Spent', 'number'); $chart->addColumn('Overspent', 'number');
$budgets = $repository->getBudgets(); $budgets = $repository->getBudgets();
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
@@ -171,7 +175,15 @@ class GoogleChartController extends Controller
foreach ($allEntries as $entry) { foreach ($allEntries as $entry) {
if ($entry[2] > 0) { if ($entry[2] > 0) {
$chart->addRow($entry[0], $entry[1], $entry[2]); $left = $entry[1] - $entry[2];
if ($left > 0) {
$chart->addRow($entry[0], $left, null);
} else {
if ($left < 0) {
$chart->addRow($entry[0], null, $left);
}
}
} }
} }
@@ -182,7 +194,8 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart * @param GChart $chart
* @param CategoryRepositoryInterface $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
@@ -209,12 +222,13 @@ class GoogleChartController extends Controller
} }
/** /**
* @param Bill $bill * @param GChart $chart
* @param GChart $chart * @param BillRepositoryInterface $repository
* @param Bill $bill
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function billOverview(Bill $bill, GChart $chart, BillRepositoryInterface $repository) public function billOverview(GChart $chart, BillRepositoryInterface $repository, Bill $bill)
{ {
$chart->addColumn('Date', 'date'); $chart->addColumn('Date', 'date');
@@ -236,7 +250,10 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart * @param GChart $chart
*
* @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
@@ -318,13 +335,14 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
* *
* @param Budget $budget * @return \Symfony\Component\HttpFoundation\Response
* @param LimitRepetition $repetition
*
* @return \Illuminate\Http\JsonResponse
*/ */
public function budgetLimitSpending(Budget $budget, LimitRepetition $repetition, GChart $chart, BudgetRepositoryInterface $repository) public function budgetLimitSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
{ {
$start = clone $repetition->startdate; $start = clone $repetition->startdate;
$end = $repetition->enddate; $end = $repetition->enddate;
@@ -351,14 +369,14 @@ class GoogleChartController extends Controller
} }
/** /**
* @param Budget $budget
* @param int $year
* @param GChart $chart * @param GChart $chart
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param int $year
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function budgetsAndSpending(Budget $budget, $year = 0, GChart $chart, BudgetRepositoryInterface $repository) public function budgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, $year = 0)
{ {
$chart->addColumn('Month', 'date'); $chart->addColumn('Month', 'date');
$chart->addColumn('Budgeted', 'number'); $chart->addColumn('Budgeted', 'number');
@@ -388,12 +406,13 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
* *
* @param Category $category * @return \Symfony\Component\HttpFoundation\Response
*
* @return \Illuminate\Http\JsonResponse
*/ */
public function categoryOverviewChart(Category $category, GChart $chart, CategoryRepositoryInterface $repository) public function categoryOverviewChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{ {
// oldest transaction in category: // oldest transaction in category:
$start = $repository->getFirstActivityDate($category); $start = $repository->getFirstActivityDate($category);
@@ -424,12 +443,13 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
* *
* @param Category $category * @return \Symfony\Component\HttpFoundation\Response
*
* @return \Illuminate\Http\JsonResponse
*/ */
public function categoryPeriodChart(Category $category, GChart $chart, CategoryRepositoryInterface $repository) public function categoryPeriodChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{ {
$start = clone Session::get('start', Carbon::now()->startOfMonth()); $start = clone Session::get('start', Carbon::now()->startOfMonth());
$chart->addColumn('Period', 'date'); $chart->addColumn('Period', 'date');
@@ -451,11 +471,13 @@ class GoogleChartController extends Controller
/** /**
* @param PiggyBank $piggyBank * @param GChart $chart
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
* *
* @return \Illuminate\Http\JsonResponse * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function piggyBankHistory(PiggyBank $piggyBank, GChart $chart, PiggyBankRepositoryInterface $repository) public function piggyBankHistory(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{ {
$chart->addColumn('Date', 'date'); $chart->addColumn('Date', 'date');
$chart->addColumn('Balance', 'number'); $chart->addColumn('Balance', 'number');
@@ -476,12 +498,13 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
* *
* @param $year * @return \Symfony\Component\HttpFoundation\Response
*
* @return \Illuminate\Http\JsonResponse
*/ */
public function yearInExp($year, GChart $chart, ReportQueryInterface $query) public function yearInExp(GChart $chart, ReportQueryInterface $query, $year)
{ {
$start = new Carbon('01-01-' . $year); $start = new Carbon('01-01-' . $year);
$chart->addColumn('Month', 'date'); $chart->addColumn('Month', 'date');
@@ -514,12 +537,13 @@ class GoogleChartController extends Controller
} }
/** /**
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
* *
* @param $year * @return \Symfony\Component\HttpFoundation\Response
*
* @return \Illuminate\Http\JsonResponse
*/ */
public function yearInExpSum($year, GChart $chart, ReportQueryInterface $query) public function yearInExpSum(GChart $chart, ReportQueryInterface $query, $year)
{ {
$start = new Carbon('01-01-' . $year); $start = new Carbon('01-01-' . $year);
$chart->addColumn('Summary', 'string'); $chart->addColumn('Summary', 'string');

View File

@@ -1,12 +1,8 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Cache;
use ErrorException;
use FireflyIII\Helpers\Help\HelpInterface; use FireflyIII\Helpers\Help\HelpInterface;
use League\CommonMark\CommonMarkConverter;
use Log; use Log;
use Response; use Response;
use Route;
/** /**
* Class HelpController * Class HelpController
@@ -17,11 +13,12 @@ class HelpController extends Controller
{ {
/** /**
* @param $route * @param HelpInterface $help
* @param $route
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function show($route, HelpInterface $help) public function show(HelpInterface $help, $route)
{ {
$content = [ $content = [
'text' => '<p>There is no help for this route!</p>', 'text' => '<p>There is no help for this route!</p>',

View File

@@ -86,7 +86,7 @@ class HomeController extends Controller
} }
} }
return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal','piggyBankAccounts')); return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal', 'piggyBankAccounts'));
} }

View File

@@ -1,17 +1,18 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Amount; use Amount;
use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Preferences; use Preferences;
use Response; use Response;
@@ -28,7 +29,9 @@ class JsonController extends Controller
/** /**
* @param BillRepositoryInterface $repository * @param BillRepositoryInterface $repository
*
* @param AccountRepositoryInterface $accountRepository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
@@ -149,6 +152,8 @@ class JsonController extends Controller
/** /**
* Returns a list of categories. * Returns a list of categories.
* *
* @param CategoryRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function categories(CategoryRepositoryInterface $repository) public function categories(CategoryRepositoryInterface $repository)
@@ -166,6 +171,8 @@ class JsonController extends Controller
/** /**
* Returns a JSON list of all beneficiaries. * Returns a JSON list of all beneficiaries.
* *
* @param AccountRepositoryInterface $accountRepository
*
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function expenseAccounts(AccountRepositoryInterface $accountRepository) public function expenseAccounts(AccountRepositoryInterface $accountRepository)
@@ -181,6 +188,27 @@ class JsonController extends Controller
} }
/** /**
* Returns a JSON list of all beneficiaries.
*
* @param TagRepositoryInterface $tagRepository
*
* @return \Illuminate\Http\JsonResponse
*/
public function tags(TagRepositoryInterface $tagRepository)
{
$list = $tagRepository->get();
$return = [];
foreach ($list as $entry) {
$return[] = $entry->tag;
}
return Response::json($return);
}
/**
* @param AccountRepositoryInterface $accountRepository
*
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function revenueAccounts(AccountRepositoryInterface $accountRepository) public function revenueAccounts(AccountRepositoryInterface $accountRepository)
@@ -200,6 +228,7 @@ class JsonController extends Controller
*/ */
public function setSharedReports() public function setSharedReports()
{ {
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false); $pref = Preferences::get('showSharedReports', false);
$new = !$pref->data; $new = !$pref->data;
Preferences::set('showSharedReports', $new); Preferences::set('showSharedReports', $new);
@@ -219,11 +248,12 @@ class JsonController extends Controller
} }
/** /**
* @param $what * @param JournalRepositoryInterface $repository
* @param $what
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function transactionJournals($what, JournalRepositoryInterface $repository) public function transactionJournals(JournalRepositoryInterface $repository, $what)
{ {
$descriptions = []; $descriptions = [];
$dbType = $repository->getTransactionType($what); $dbType = $repository->getTransactionType($what);

View File

@@ -1,12 +1,12 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Amount; use Amount;
use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use Config; use Config;
use ExpandedForm; use ExpandedForm;
use FireflyIII\Http\Requests; use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\PiggyBankFormRequest; use FireflyIII\Http\Requests\PiggyBankFormRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -32,6 +32,7 @@ class PiggyBankController extends Controller
*/ */
public function __construct() public function __construct()
{ {
parent::__construct();
View::share('title', 'Piggy banks'); View::share('title', 'Piggy banks');
View::share('mainTitleIcon', 'fa-sort-amount-asc'); View::share('mainTitleIcon', 'fa-sort-amount-asc');
} }
@@ -39,11 +40,12 @@ class PiggyBankController extends Controller
/** /**
* Add money to piggy bank * Add money to piggy bank
* *
* @param PiggyBank $piggyBank * @param AccountRepositoryInterface $repository
* @param PiggyBank $piggyBank
* *
* @return $this * @return $this
*/ */
public function add(PiggyBank $piggyBank, AccountRepositoryInterface $repository) public function add(AccountRepositoryInterface $repository, PiggyBank $piggyBank)
{ {
$leftOnAccount = $repository->leftOnAccount($piggyBank->account); $leftOnAccount = $repository->leftOnAccount($piggyBank->account);
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount; $savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
@@ -54,15 +56,15 @@ class PiggyBankController extends Controller
} }
/** /**
* @param AccountRepositoryInterface $repository
*
* @return mixed * @return mixed
*/ */
public function create() public function create(AccountRepositoryInterface $repository)
{ {
$periods = Config::get('firefly.piggy_bank_periods'); $periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList( $accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*'])
);
$subTitle = 'Create new piggy bank'; $subTitle = 'Create new piggy bank';
$subTitleIcon = 'fa-plus'; $subTitleIcon = 'fa-plus';
@@ -91,33 +93,32 @@ class PiggyBankController extends Controller
} }
/** /**
* @param PiggyBank $piggyBank * @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function destroy(PiggyBank $piggyBank) public function destroy(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{ {
Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.'); Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.');
$piggyBank->delete(); $repository->destroy($piggyBank);
return Redirect::to(Session::get('piggy-banks.delete.url')); return Redirect::to(Session::get('piggy-banks.delete.url'));
} }
/** /**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. * @param AccountRepositoryInterface $repository
* @param PiggyBank $piggyBank
* *
* @param PiggyBank $piggyBank * @return View
*
* @return $this
*/ */
public function edit(PiggyBank $piggyBank) public function edit(AccountRepositoryInterface $repository, PiggyBank $piggyBank)
{ {
$periods = Config::get('firefly.piggy_bank_periods'); $periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList( $accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*'])
);
$subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"'; $subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"';
$subTitleIcon = 'fa-pencil'; $subTitleIcon = 'fa-pencil';
@@ -149,18 +150,21 @@ class PiggyBankController extends Controller
} }
/** /**
* @return $this * @param AccountRepositoryInterface $repository
* @param PiggyBankRepositoryInterface $piggyRepository
*
* @return View
*/ */
public function index(AccountRepositoryInterface $repository) public function index(AccountRepositoryInterface $repository, PiggyBankRepositoryInterface $piggyRepository)
{ {
/** @var Collection $piggyBanks */ /** @var Collection $piggyBanks */
$piggyBanks = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get(); $piggyBanks = $piggyRepository->getPiggyBanks();
$accounts = []; $accounts = [];
/** @var PiggyBank $piggyBank */ /** @var PiggyBank $piggyBank */
foreach ($piggyBanks as $piggyBank) { foreach ($piggyBanks as $piggyBank) {
$piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount); $piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount);
$piggyBank->percentage = intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100); $piggyBank->percentage = $piggyBank->savedSoFar != 0 ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0;
$piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar; $piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar;
/* /*
@@ -187,7 +191,7 @@ class PiggyBankController extends Controller
} }
/** /**
* Allow user to order piggy banks. * @param PiggyBankRepositoryInterface $repository
*/ */
public function order(PiggyBankRepositoryInterface $repository) public function order(PiggyBankRepositoryInterface $repository)
{ {
@@ -204,13 +208,13 @@ class PiggyBankController extends Controller
} }
/** /**
* POST add money to piggy bank * @param PiggyBankRepositoryInterface $repository
* * @param AccountRepositoryInterface $accounts
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function postAdd(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts) public function postAdd(PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts, PiggyBank $piggyBank)
{ {
$amount = round(floatval(Input::get('amount')), 2); $amount = round(floatval(Input::get('amount')), 2);
$leftOnAccount = $accounts->leftOnAccount($piggyBank->account); $leftOnAccount = $accounts->leftOnAccount($piggyBank->account);
@@ -223,8 +227,8 @@ class PiggyBankController extends Controller
$repetition->currentamount += $amount; $repetition->currentamount += $amount;
$repetition->save(); $repetition->save();
// create event. // create event
PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]); $repository->createEvent($piggyBank, $amount);
/* /*
* Create event! * Create event!
@@ -240,11 +244,12 @@ class PiggyBankController extends Controller
} }
/** /**
* @param PiggyBank $piggyBank * @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function postRemove(PiggyBank $piggyBank) public function postRemove(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{ {
$amount = floatval(Input::get('amount')); $amount = floatval(Input::get('amount'));
@@ -255,12 +260,8 @@ class PiggyBankController extends Controller
$repetition->currentamount -= $amount; $repetition->currentamount -= $amount;
$repetition->save(); $repetition->save();
PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount * -1, 'piggy_bank_id' => $piggyBank->id]); // create event
$repository->createEvent($piggyBank, $amount * -1);
/*
* Create event!
*/
//Event::fire('piggy_bank.removeMoney', [$piggyBank, $amount]); // new and used.
Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".'); Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
} else { } else {
@@ -273,7 +274,6 @@ class PiggyBankController extends Controller
/** /**
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
* @SuppressWarnings("Unused")
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
@@ -283,14 +283,14 @@ class PiggyBankController extends Controller
} }
/** /**
* @param PiggyBank $piggyBank * @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
* *
* @return $this * @return View
*/ */
public function show(PiggyBank $piggyBank) public function show(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{ {
$events = $repository->getEvents($piggyBank);
$events = $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
/* /*
* Number of reminders: * Number of reminders:
@@ -310,6 +310,7 @@ class PiggyBankController extends Controller
*/ */
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository) public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
{ {
$piggyBankData = [ $piggyBankData = [
'name' => $request->get('name'), 'name' => $request->get('name'),
'startdate' => new Carbon, 'startdate' => new Carbon,
@@ -336,13 +337,13 @@ class PiggyBankController extends Controller
} }
/** /**
* @param PiggyBank $piggyBank * @param PiggyBankRepositoryInterface $repository
* * @param PiggyBankFormRequest $request
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. * @param PiggyBank $piggyBank
* *
* @return $this * @return $this
*/ */
public function update(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request) public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank)
{ {
$piggyBankData = [ $piggyBankData = [
'name' => $request->get('name'), 'name' => $request->get('name'),
@@ -354,7 +355,6 @@ class PiggyBankController extends Controller
'remind_me' => $request->get('remind_me') 'remind_me' => $request->get('remind_me')
]; ];
$piggyBank = $repository->update($piggyBank, $piggyBankData); $piggyBank = $repository->update($piggyBank, $piggyBankData);
Session::flash('success', 'Updated piggy bank "' . e($piggyBank->name) . '".'); Session::flash('success', 'Updated piggy bank "' . e($piggyBank->name) . '".');

View File

@@ -1,6 +1,6 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Auth; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input; use Input;
use Preferences; use Preferences;
use Redirect; use Redirect;
@@ -20,26 +20,26 @@ class PreferencesController extends Controller
*/ */
public function __construct() public function __construct()
{ {
parent::__construct();
View::share('title', 'Preferences'); View::share('title', 'Preferences');
View::share('mainTitleIcon', 'fa-gear'); View::share('mainTitleIcon', 'fa-gear');
} }
/** /**
* @param AccountRepositoryInterface $repository
*
* @return $this|\Illuminate\View\View * @return $this|\Illuminate\View\View
*/ */
public function index() public function index(AccountRepositoryInterface $repository)
{ {
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']); $accounts = $repository->getAccounts(['Default account', 'Asset account']);
$viewRange = Preferences::get('viewRange', '1M'); $viewRangePref = Preferences::get('viewRange', '1M');
$viewRangeValue = $viewRange->data; $viewRange = $viewRangePref->data;
$frontPage = Preferences::get('frontPageAccounts', []); $frontPageAccounts = Preferences::get('frontPageAccounts', []);
$budgetMax = Preferences::get('budgetMaximum', 1000); $budgetMax = Preferences::get('budgetMaximum', 1000);
$budgetMaximum = $budgetMax->data; $budgetMaximum = $budgetMax->data;
return view('preferences.index', compact('budgetMaximum'))->with('accounts', $accounts)->with('frontPageAccounts', $frontPage)->with( return view('preferences.index', compact('budgetMaximum', 'accounts', 'frontPageAccounts', 'viewRange'));
'viewRange', $viewRangeValue
);
} }
/** /**

View File

@@ -2,6 +2,7 @@
use Auth; use Auth;
use FireflyIII\Http\Requests; use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\DeleteAccountFormRequest;
use FireflyIII\Http\Requests\ProfileFormRequest; use FireflyIII\Http\Requests\ProfileFormRequest;
use Hash; use Hash;
use Redirect; use Redirect;
@@ -25,6 +26,16 @@ class ProfileController extends Controller
); );
} }
/**
* @return \Illuminate\View\View
*/
public function deleteAccount()
{
return view('profile.delete-account')->with('title', Auth::user()->email)->with('subTitle', 'Delete account')->with(
'mainTitleIcon', 'fa-user'
);
}
/** /**
* @return \Illuminate\View\View * @return \Illuminate\View\View
* *
@@ -35,6 +46,8 @@ class ProfileController extends Controller
} }
/** /**
* @param ProfileFormRequest $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/ */
public function postChangePassword(ProfileFormRequest $request) public function postChangePassword(ProfileFormRequest $request)
@@ -45,7 +58,7 @@ class ProfileController extends Controller
return Redirect::route('change-password'); return Redirect::route('change-password');
} }
$result = $this->validatePassword($request->get('current_password'), $request->get('new_password'), $request->get('new_password_confirmation')); $result = $this->validatePassword($request->get('current_password'), $request->get('new_password'));
if (!($result === true)) { if (!($result === true)) {
Session::flash('error', $result); Session::flash('error', $result);
@@ -62,29 +75,43 @@ class ProfileController extends Controller
} }
/** /**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
* *
* @param string $old * @param string $old
* @param string $new1 * @param string $new1
* @param string $new2
* *
* @return string|bool * @return string|bool
*/ */
protected function validatePassword($old, $new1, $new2) protected function validatePassword($old, $new1)
{ {
if (strlen($new1) == 0 || strlen($new2) == 0) {
return 'Do fill in a password!';
}
if ($new1 == $old) { if ($new1 == $old) {
return 'The idea is to change your password.'; return 'The idea is to change your password.';
} }
if ($new1 !== $new2) {
return 'New passwords do not match!';
}
return true; return true;
} }
/**
* @param DeleteAccountFormRequest $request
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Exception
*/
public function postDeleteAccount(DeleteAccountFormRequest $request)
{
// old, new1, new2
if (!Hash::check($request->get('password'), Auth::user()->password)) {
Session::flash('error', 'Invalid password!');
return Redirect::route('delete-account');
}
// DELETE!
Auth::user()->delete();
Session::flush();
return Redirect::route('index');
}
} }

View File

@@ -1,164 +0,0 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Support\Collection;
use Input;
use Redirect;
use Response;
use URL;
/**
* Class RelatedController
*
* @package FireflyIII\Http\Controllers
*/
class RelatedController extends Controller
{
/**
*
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\JsonResponse
*/
public function alreadyRelated(TransactionJournal $journal)
{
$ids = [];
/** @var TransactionGroup $group */
foreach ($journal->transactiongroups()->get() as $group) {
/** @var TransactionJournal $loopJournal */
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id != $journal->id) {
$ids[] = $loopJournal->id;
}
}
}
$unique = array_unique($ids);
$journals = new Collection;
if (count($unique) > 0) {
$journals = Auth::user()->transactionjournals()->whereIn('id', $unique)->get();
}
$parent = $journal;
return view('related.alreadyRelated', compact('parent', 'journals'));
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @param TransactionJournal $parentJournal
* @param TransactionJournal $childJournal
*
* @return \Illuminate\Http\JsonResponse
* @throws Exception
*/
public function getRemoveRelation(TransactionJournal $parentJournal, TransactionJournal $childJournal)
{
$groups = $parentJournal->transactiongroups()->get();
/** @var TransactionGroup $group */
foreach ($groups as $group) {
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id == $childJournal->id) {
// remove from group:
$group->transactionjournals()->detach($childJournal);
}
}
if ($group->transactionjournals()->count() == 1) {
$group->delete();
}
}
return Redirect::to(URL::previous());
}
/**
* @param TransactionJournal $parentJournal
* @param TransactionJournal $childJournal
*
* @return \Illuminate\Http\JsonResponse
*/
public function relate(TransactionJournal $parentJournal, TransactionJournal $childJournal)
{
$group = new TransactionGroup;
$group->relation = 'balance';
$group->user_id = Auth::user()->id;
$group->save();
$group->transactionjournals()->save($parentJournal);
$group->transactionjournals()->save($childJournal);
return Response::json(true);
}
/**
* @param TransactionJournal $journal
*
* @return \Illuminate\View\View
*/
public function related(TransactionJournal $journal)
{
$groups = $journal->transactiongroups()->get();
$members = new Collection;
/** @var TransactionGroup $group */
foreach ($groups as $group) {
/** @var TransactionJournal $loopJournal */
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id != $journal->id) {
$members->push($loopJournal);
}
}
}
return view('related.relate', compact('journal', 'members'));
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @param TransactionJournal $parentJournal
* @param TransactionJournal $childJournal
*
* @return \Illuminate\Http\JsonResponse
* @throws Exception
*/
public function removeRelation(TransactionJournal $parentJournal, TransactionJournal $childJournal)
{
$groups = $parentJournal->transactiongroups()->get();
/** @var TransactionGroup $group */
foreach ($groups as $group) {
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id == $childJournal->id) {
// remove from group:
$group->transactionjournals()->detach($childJournal);
}
}
if ($group->transactionjournals()->count() == 1) {
$group->delete();
}
}
return Response::json(true);
}
/**
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\JsonResponse
*/
public function search(TransactionJournal $journal, JournalRepositoryInterface $repository)
{
$search = e(trim(Input::get('searchValue')));
$parent = $journal;
$journals = $repository->searchRelated($search, $journal);
return view('related.searchResult', compact('journals', 'search', 'parent'));
}
}

View File

@@ -1,9 +1,7 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use FireflyIII\Helpers\Reminders\ReminderHelperInterface;
use FireflyIII\Models\Reminder; use FireflyIII\Models\Reminder;
use FireflyIII\Repositories\Reminder\ReminderRepositoryInterface;
use Redirect; use Redirect;
use Session; use Session;
use URL; use URL;
@@ -19,6 +17,8 @@ class ReminderController extends Controller
/** /**
* @param Reminder $reminder * @param Reminder $reminder
*
* @return \Illuminate\Http\RedirectResponse
*/ */
public function act(Reminder $reminder) public function act(Reminder $reminder)
{ {
@@ -36,6 +36,8 @@ class ReminderController extends Controller
/** /**
* @param Reminder $reminder * @param Reminder $reminder
*
* @return \Illuminate\Http\RedirectResponse
*/ */
public function dismiss(Reminder $reminder) public function dismiss(Reminder $reminder)
{ {
@@ -48,55 +50,18 @@ class ReminderController extends Controller
} }
/** /**
* @param ReminderRepositoryInterface $repository
* *
* @return \Illuminate\View\View
*/ */
public function index(ReminderHelperInterface $helper) public function index(ReminderRepositoryInterface $repository)
{ {
$reminders = Auth::user()->reminders()->get();
$reminders->each( $active = $repository->getActiveReminders();
function (Reminder $reminder) use ($helper) { $expired = $repository->getExpiredReminders();
$reminder->description = $helper->getReminderText($reminder); $inactive = $repository->getInactiveReminders();
} $dismissed = $repository->getDismissedReminders();
);
$today = new Carbon;
// active reminders:
$active = $reminders->filter(
function (Reminder $reminder) use ($today) {
if ($reminder->notnow === false && $reminder->active === true && $reminder->startdate <= $today && $reminder->enddate >= $today) {
return $reminder;
}
}
);
// expired reminders:
$expired = $reminders->filter(
function (Reminder $reminder) use ($today) {
if ($reminder->notnow === false && $reminder->active === true && $reminder->startdate > $today || $reminder->enddate < $today) {
return $reminder;
}
}
);
// inactive reminders
$inactive = $reminders->filter(
function (Reminder $reminder) {
if ($reminder->active === false) {
return $reminder;
}
}
);
// dismissed reminders
$dismissed = $reminders->filter(
function (Reminder $reminder) {
if ($reminder->notnow === true) {
return $reminder;
}
}
);
$title = 'Reminders'; $title = 'Reminders';
$mainTitleIcon = 'fa-clock-o'; $mainTitleIcon = 'fa-clock-o';
@@ -106,6 +71,8 @@ class ReminderController extends Controller
/** /**
* @param Reminder $reminder * @param Reminder $reminder
*
* @return \Illuminate\View\View
*/ */
public function show(Reminder $reminder) public function show(Reminder $reminder)
{ {

View File

@@ -1,7 +1,6 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use Exception;
use FireflyIII\Helpers\Report\ReportHelperInterface; use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
@@ -47,50 +46,52 @@ class ReportController extends Controller
*/ */
public function budget($year = '2014', $month = '1') public function budget($year = '2014', $month = '1')
{ {
try { $date = new Carbon($year . '-' . $month . '-01');
new Carbon($year . '-' . $month . '-01'); $subTitle = 'Budget report for ' . $date->format('F Y');
} catch (Exception $e) { $subTitleIcon = 'fa-calendar';
return view('error')->with('message', 'Invalid date'); $start = clone $date;
}
$date = new Carbon($year . '-' . $month . '-01');
$start = clone $date;
$start->startOfMonth(); $start->startOfMonth();
$end = clone $date; $end = clone $date;
$end->endOfMonth(); $end->endOfMonth();
$start->subDay();
// should show shared reports?
/** @var Preference $pref */ /** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false); $pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data; $showSharedReports = $pref->data;
$accountAmounts = []; // array with sums of spent amounts on each account.
$accounts = $this->query->getAllAccounts($start, $end, $showSharedReports); // all accounts and some data.
foreach ($accounts as $account) {
$dayEarly = clone $date; $budgets = $this->query->getBudgetSummary($account, $start, $end);// get budget summary for this account:
$subTitle = 'Budget report for ' . $date->format('F Y'); $balancedAmount = $this->query->balancedTransactionsSum($account, $start, $end);
$subTitleIcon = 'fa-calendar'; $accountAmounts[$account->id] = $balancedAmount;
$dayEarly = $dayEarly->subDay(); // balance out the transactions (see transaction groups & tags) ^^
$accounts = $this->query->getAllAccounts($start, $end, $showSharedReports);
$start->addDay();
$accounts->each( // array with budget information for each account:
function (Account $account) use ($start, $end) { $array = [];
$budgets = $this->query->getBudgetSummary($account, $start, $end); // should always hide account
$balancedAmount = $this->query->balancedTransactionsSum($account, $start, $end); $hide = true;
$array = []; // loop all budgets
$hide = true; /** @var \FireflyIII\Models\Budget $budget */
foreach ($budgets as $budget) { foreach ($budgets as $budget) {
$id = intval($budget->id); $id = intval($budget->id);
$data = $budget->toArray(); $data = $budget->toArray();
$array[$id] = $data; $array[$id] = $data;
if (floatval($data['queryAmount']) != 0) {
$hide = false; // no longer hide account if any budget has money in it.
} if (floatval($data['queryAmount']) != 0) {
$hide = false;
} }
$account->hide = $hide; $accountAmounts[$account->id] += $data['queryAmount'];
$account->budgetInformation = $array;
$account->balancedAmount = $balancedAmount;
} }
); $account->hide = $hide;
$account->budgetInformation = $array;
$account->balancedAmount = $balancedAmount;
}
/** /**
* Start getBudgetsForMonth DONE * Start getBudgetsForMonth DONE
@@ -101,14 +102,14 @@ class ReportController extends Controller
* End getBudgetsForMonth DONE * End getBudgetsForMonth DONE
*/ */
return view('reports.budget', compact('subTitle', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly')); return view('reports.budget', compact('subTitle', 'accountAmounts', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets'));
} }
/** /**
* @param ReportHelperInterface $helper
*
* @return View * @return View
* @internal param ReportHelperInterface $helper
*
*/ */
public function index() public function index()
{ {
@@ -131,11 +132,6 @@ class ReportController extends Controller
public function modalBalancedTransfers(Account $account, $year = '2014', $month = '1') public function modalBalancedTransfers(Account $account, $year = '2014', $month = '1')
{ {
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date');
}
$start = new Carbon($year . '-' . $month . '-01'); $start = new Carbon($year . '-' . $month . '-01');
$end = clone $start; $end = clone $start;
$end->endOfMonth(); $end->endOfMonth();
@@ -148,20 +144,16 @@ class ReportController extends Controller
} }
/** /**
* @param Account $account * @param Account $account
* @param string $year * @param string $year
* @param string $month * @param string $month
* @param ReportQueryInterface $query
* *
* @return View * @return View
* @internal param ReportQueryInterface $query
*
*/ */
public function modalLeftUnbalanced(Account $account, $year = '2014', $month = '1') public function modalLeftUnbalanced(Account $account, $year = '2014', $month = '1')
{ {
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date');
}
$start = new Carbon($year . '-' . $month . '-01'); $start = new Carbon($year . '-' . $month . '-01');
$end = clone $start; $end = clone $start;
$end->endOfMonth(); $end->endOfMonth();
@@ -173,6 +165,8 @@ class ReportController extends Controller
if ($count == 0) { if ($count == 0) {
return $journal; return $journal;
} }
return null;
} }
); );
@@ -188,11 +182,6 @@ class ReportController extends Controller
*/ */
public function modalNoBudget(Account $account, $year = '2014', $month = '1') public function modalNoBudget(Account $account, $year = '2014', $month = '1')
{ {
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date');
}
$start = new Carbon($year . '-' . $month . '-01'); $start = new Carbon($year . '-' . $month . '-01');
$end = clone $start; $end = clone $start;
$end->endOfMonth(); $end->endOfMonth();
@@ -210,11 +199,6 @@ class ReportController extends Controller
*/ */
public function month($year = '2014', $month = '1') public function month($year = '2014', $month = '1')
{ {
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date.');
}
$date = new Carbon($year . '-' . $month . '-01'); $date = new Carbon($year . '-' . $month . '-01');
$subTitle = 'Report for ' . $date->format('F Y'); $subTitle = 'Report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar'; $subTitleIcon = 'fa-calendar';
@@ -326,11 +310,6 @@ class ReportController extends Controller
*/ */
public function year($year) public function year($year)
{ {
try {
new Carbon('01-01-' . $year);
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date.');
}
/** @var Preference $pref */ /** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false); $pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data; $showSharedReports = $pref->data;

View File

@@ -12,6 +12,10 @@ class SearchController extends Controller
{ {
/** /**
* Results always come in the form of an array [results, count, fullCount] * Results always come in the form of an array [results, count, fullCount]
*
* @param SearchInterface $searcher
*
* @return $this
*/ */
public function index(SearchInterface $searcher) public function index(SearchInterface $searcher)
{ {

View File

@@ -0,0 +1,325 @@
<?php
namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use FireflyIII\Http\Requests\TagFormRequest;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Input;
use Preferences;
use Redirect;
use Response;
use Session;
use URL;
use View;
/**
* Class TagController
*
* Remember: a balancingAct takes at most one expense and one transfer.
* an advancePayment takes at most one expense, infinite deposits and NO transfers.
*
* TODO transaction can only have one advancePayment OR balancingAct.
* TODO Other attempts to put in such a tag are blocked.
* TODO also show an error when editing a tag and it becomes either
* TODO of these two types. Or rather, block editing of the tag.
*
* @package FireflyIII\Http\Controllers
*/
class TagController extends Controller
{
/**
*
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Tags');
View::share('mainTitleIcon', 'fa-tags');
View::share('hideTags', true);
$tagOptions = [
'nothing' => 'Just a regular tag.',
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
];
View::share('tagOptions', $tagOptions);
}
/**
* @return \Illuminate\View\View
*/
public function create()
{
$subTitle = 'New tag';
$subTitleIcon = 'fa-tag';
$preFilled = [
'tagMode' => 'nothing'
];
if (!Input::old('tagMode')) {
Session::flash('preFilled', $preFilled);
}
// put previous url in session if not redirect from store (not "create another").
if (Session::get('tags.create.fromStore') !== true) {
Session::put('tags.create.url', URL::previous());
}
Session::forget('tags.create.fromStore');
return view('tags.create', compact('subTitle', 'subTitleIcon'));
}
/**
* @param Tag $tag
*
* @return \Illuminate\View\View
*/
public function delete(Tag $tag)
{
$subTitle = 'Delete "' . e($tag->tag) . '"';
// put previous url in session
Session::put('tags.delete.url', URL::previous());
return view('tags.delete', compact('tag', 'subTitle'));
}
/**
* @param TagRepositoryInterface $repository
* @param Tag $tag
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(TagRepositoryInterface $repository, Tag $tag)
{
$tagName = $tag->tag;
$repository->destroy($tag);
Session::flash('success', 'Tag "' . e($tagName) . '" was deleted.');
return Redirect::to(route('tags.index'));
}
/**
* @param Tag $tag
*
* @return View
*/
public function edit(Tag $tag)
{
$subTitle = 'Edit tag "' . e($tag->tag) . '"';
$subTitleIcon = 'fa-tag';
/*
* Default tag options (again)
*/
$tagOptions = [
'nothing' => 'Just a regular tag.',
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
];
/*
* Can this tag become another type?
*/
$allowToAdvancePayment = true;
$allowToBalancingAct = true;
/*
* If this tag is a balancing act, and it contains transfers, it cannot be
* changes to an advancePayment.
*/
if ($tag->tagMode == 'balancingAct') {
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Transfer') {
$allowToAdvancePayment = false;
}
}
}
/*
* If this tag contains more than one expenses, it cannot become an advance payment.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Withdrawal') {
$count++;
}
}
if ($count > 1) {
$allowToAdvancePayment = false;
}
/*
* If has more than two transactions already, cannot become a balancing act:
*/
if ($tag->transactionjournals->count() > 2) {
$allowToBalancingAct = false;
}
/*
* If any transaction is a deposit, cannot become a balancing act.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Deposit') {
$count++;
}
}
if ($count > 0) {
$allowToBalancingAct = false;
}
// edit tag options:
if ($allowToAdvancePayment === false) {
unset($tagOptions['advancePayment']);
}
if ($allowToBalancingAct === false) {
unset($tagOptions['balancingAct']);
}
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('tags.edit.fromUpdate') !== true) {
Session::put('tags.edit.url', URL::previous());
}
Session::forget('tags.edit.fromUpdate');
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions'));
}
/**
* @param $state
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function hideTagHelp($state)
{
$state = $state == 'true' ? true : false;
Preferences::set('hideTagHelp', $state);
return Response::json(true);
}
/**
*
*/
public function index()
{
/** @var Preference $helpHiddenPref */
$helpHiddenPref = Preferences::get('hideTagHelp', false);
$title = 'Tags';
$mainTitleIcon = 'fa-tags';
$helpHidden = $helpHiddenPref->data;
$tags = Auth::user()->tags()->get();
return view('tags.index', compact('title', 'mainTitleIcon', 'helpHidden', 'tags'));
}
/**
* @param Tag $tag
*
* @return \Illuminate\View\View
*/
public function show(Tag $tag)
{
$subTitle = $tag->tag;
$subTitleIcon = 'fa-tag';
return view('tags.show', compact('tag', 'subTitle', 'subTitleIcon'));
}
/**
* @param TagFormRequest $request
*
* @param TagRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function store(TagFormRequest $request, TagRepositoryInterface $repository)
{
if (Input::get('setTag') == 'true') {
$latitude = strlen($request->get('latitude')) > 0 ? $request->get('latitude') : null;
$longitude = strlen($request->get('longitude')) > 0 ? $request->get('longitude') : null;
$zoomLevel = strlen($request->get('zoomLevel')) > 0 ? $request->get('zoomLevel') : null;
} else {
$latitude = null;
$longitude = null;
$zoomLevel = null;
}
$data = [
'tag' => $request->get('tag'),
'date' => strlen($request->get('date')) > 0 ? new Carbon($request->get('date')) : null,
'description' => strlen($request->get('description')) > 0 ? $request->get('description') : '',
'latitude' => $latitude,
'longitude' => $longitude,
'zoomLevel' => $zoomLevel,
'tagMode' => $request->get('tagMode'),
];
$repository->store($data);
Session::flash('success', 'The tag has been created!');
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('tags.create.fromStore', true);
return Redirect::route('tags.create')->withInput();
}
// redirect to previous URL.
return Redirect::to(Session::get('tags.create.url'));
}
/**
* @param TagFormRequest $request
* @param TagRepositoryInterface $repository
* @param Tag $tag
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function update(TagFormRequest $request, TagRepositoryInterface $repository, Tag $tag)
{
if (Input::get('setTag') == 'true') {
$latitude = strlen($request->get('latitude')) > 0 ? $request->get('latitude') : null;
$longitude = strlen($request->get('longitude')) > 0 ? $request->get('longitude') : null;
$zoomLevel = strlen($request->get('zoomLevel')) > 0 ? $request->get('zoomLevel') : null;
} else {
$latitude = null;
$longitude = null;
$zoomLevel = null;
}
$data = [
'tag' => $request->get('tag'),
'date' => strlen($request->get('date')) > 0 ? new Carbon($request->get('date')) : null,
'description' => strlen($request->get('description')) > 0 ? $request->get('description') : '',
'latitude' => $latitude,
'longitude' => $longitude,
'zoomLevel' => $zoomLevel,
'tagMode' => $request->get('tagMode'),
];
$repository->update($tag, $data);
Session::flash('success', 'Tag "' . e($data['tag']) . '" updated.');
if (intval(Input::get('return_to_edit')) === 1) {
// set value so edit routine will not overwrite URL:
Session::put('tags.edit.fromUpdate', true);
return Redirect::route('tags.edit', $tag->id)->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.
return Redirect::to(Session::get('tags.edit.url'));
}
}

View File

@@ -1,6 +1,7 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Auth; use Auth;
use Carbon\Carbon;
use ExpandedForm; use ExpandedForm;
use FireflyIII\Events\JournalCreated; use FireflyIII\Events\JournalCreated;
use FireflyIII\Events\JournalSaved; use FireflyIII\Events\JournalSaved;
@@ -8,8 +9,8 @@ use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\JournalFormRequest; use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Pagination\LengthAwarePaginator;
use Input; use Input;
use Redirect; use Redirect;
use Response; use Response;
@@ -28,24 +29,20 @@ class TransactionController extends Controller
*/ */
public function __construct() public function __construct()
{ {
parent::__construct();
View::share('title', 'Transactions'); View::share('title', 'Transactions');
View::share('mainTitleIcon', 'fa-repeat'); View::share('mainTitleIcon', 'fa-repeat');
} }
/** /**
* Shows the view helping the user to create a new transaction journal. * @param AccountRepositoryInterface $repository
* @param string $what
* *
* @param string $what * @return View
*
* @return \Illuminate\View\View
*/ */
public function create($what = 'deposit') public function create(AccountRepositoryInterface $repository, $what = 'deposit')
{ {
$accounts = ExpandedForm::makeSelectList( $accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->orderBy('name', 'ASC')->where(
'active', 1
)->orderBy('name', 'DESC')->get(['accounts.*'])
);
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); $budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)'; $budgets[0] = '(no budget)';
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get()); $piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
@@ -94,15 +91,16 @@ class TransactionController extends Controller
} }
/** /**
* @param TransactionJournal $transactionJournal * @param JournalRepositoryInterface $repository
* @param TransactionJournal $transactionJournal
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function destroy(TransactionJournal $transactionJournal) public function destroy(JournalRepositoryInterface $repository, TransactionJournal $transactionJournal)
{ {
Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.'); Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.');
$transactionJournal->delete(); $repository->delete($transactionJournal);
// redirect to previous URL: // redirect to previous URL:
return Redirect::to(Session::get('transactions.delete.url')); return Redirect::to(Session::get('transactions.delete.url'));
@@ -111,18 +109,15 @@ class TransactionController extends Controller
/** /**
* Shows the view to edit a transaction. * Shows the view to edit a transaction.
* *
* @param TransactionJournal $journal * @param AccountRepositoryInterface $repository
* @param TransactionJournal $journal
* *
* @return $this * @return $this
*/ */
public function edit(TransactionJournal $journal, JournalRepositoryInterface $repository) public function edit(AccountRepositoryInterface $repository, TransactionJournal $journal)
{ {
$what = strtolower($journal->transactiontype->type); $what = strtolower($journal->transactiontype->type);
$accounts = ExpandedForm::makeSelectList( $accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->where('active', 1)->orderBy(
'name', 'DESC'
)->get(['accounts.*'])
);
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); $budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)'; $budgets[0] = '(no budget)';
$transactions = $journal->transactions()->orderBy('amount', 'DESC')->get(); $transactions = $journal->transactions()->orderBy('amount', 'DESC')->get();
@@ -134,6 +129,12 @@ class TransactionController extends Controller
'budget_id' => 0, 'budget_id' => 0,
'piggy_bank_id' => 0 'piggy_bank_id' => 0
]; ];
// get tags:
$tags = [];
foreach ($journal->tags as $tag) {
$tags[] = $tag->tag;
}
$preFilled['tags'] = join(',', $tags);
$category = $journal->categories()->first(); $category = $journal->categories()->first();
if (!is_null($category)) { if (!is_null($category)) {
@@ -150,12 +151,14 @@ class TransactionController extends Controller
} }
$preFilled['amount'] = $journal->amount; $preFilled['amount'] = $journal->amount;
$preFilled['account_id'] = $repository->getAssetAccount($journal); $preFilled['account_id'] = $journal->assetAccount->id;
$preFilled['expense_account'] = $transactions[0]->account->name; $preFilled['expense_account'] = $transactions[0]->account->name;
$preFilled['revenue_account'] = $transactions[1]->account->name; $preFilled['revenue_account'] = $transactions[1]->account->name;
$preFilled['account_from_id'] = $transactions[1]->account->id; $preFilled['account_from_id'] = $transactions[1]->account->id;
$preFilled['account_to_id'] = $transactions[0]->account->id; $preFilled['account_to_id'] = $transactions[0]->account->id;
Session::flash('preFilled', $preFilled);
// put previous url in session if not redirect from store (not "return_to_edit"). // put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('transactions.edit.fromUpdate') !== true) { if (Session::get('transactions.edit.fromUpdate') !== true) {
Session::put('transactions.edit.url', URL::previous()); Session::put('transactions.edit.url', URL::previous());
@@ -167,12 +170,14 @@ class TransactionController extends Controller
} }
/** /**
* @param $what * @param JournalRepositoryInterface $repository
* @param $what
* *
* @return $this * @return View
*/ */
public function index($what) public function index(JournalRepositoryInterface $repository, $what)
{ {
$types = [];
switch ($what) { switch ($what) {
case 'expenses': case 'expenses':
case 'withdrawal': case 'withdrawal':
@@ -194,18 +199,10 @@ class TransactionController extends Controller
break; break;
} }
$page = intval(\Input::get('page')); $page = intval(Input::get('page'));
$offset = $page > 0 ? ($page - 1) * 50 : 0; $offset = $page > 0 ? ($page - 1) * 50 : 0;
$journals = $repository->getJournalsOfTypes($types, $offset, $page);
$set = Auth::user()->transactionJournals()->transactionTypes($types)->withRelevantData()->take(50)->offset($offset)
->orderBy('date', 'DESC')
->orderBy('order', 'ASC')
->orderBy('id', 'DESC')
->get(
['transaction_journals.*']
);
$count = Auth::user()->transactionJournals()->transactionTypes($types)->count();
$journals = new LengthAwarePaginator($set, $count, 50, $page);
$journals->setPath('transactions/' . $what); $journals->setPath('transactions/' . $what);
return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals')); return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals'));
@@ -213,15 +210,19 @@ class TransactionController extends Controller
} }
/** /**
* Reorder transactions (which all must have the same date) * @param JournalRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/ */
public function reorder() public function reorder(JournalRepositoryInterface $repository)
{ {
$ids = Input::get('items'); $ids = Input::get('items');
$date = new Carbon(Input::get('date'));
if (count($ids) > 0) { if (count($ids) > 0) {
$order = 0; $order = 0;
foreach ($ids as $id) { foreach ($ids as $id) {
$journal = Auth::user()->transactionjournals()->where('id', $id)->where('date', Input::get('date'))->first();
$journal = $repository->getWithDate($id, $date);
if ($journal) { if ($journal) {
$journal->order = $order; $journal->order = $order;
$order++; $order++;
@@ -235,31 +236,22 @@ class TransactionController extends Controller
} }
/** /**
* @param TransactionJournal $journal * @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
* *
* @return $this * @return $this
*/ */
public function show(TransactionJournal $journal) public function show(JournalRepositoryInterface $repository, TransactionJournal $journal)
{ {
$journal->transactions->each( $journal->transactions->each(
function (Transaction $t) use ($journal) { function (Transaction $t) use ($journal, $repository) {
$t->before = floatval( $t->before = $repository->getAmountBefore($journal, $t);
$t->account->transactions()->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)
->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d'))
->where('transaction_journals.order', '>=', $journal->order)
->where('transaction_journals.id', '!=', $journal->id)
->sum('transactions.amount')
);
$t->after = $t->before + $t->amount; $t->after = $t->before + $t->amount;
} }
); );
$subTitle = e($journal->transactiontype->type) . ' "' . e($journal->description) . '"';
return view('transactions.show', compact('journal', 'subTitle'));
return view('transactions.show', compact('journal'))->with(
'subTitle', e($journal->transactiontype->type) . ' "' . e($journal->description) . '"'
);
} }
/** /**
@@ -279,11 +271,7 @@ class TransactionController extends Controller
// ConnectJournalToPiggyBank // ConnectJournalToPiggyBank
event(new JournalCreated($journal, intval($request->get('piggy_bank_id')))); event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
if (intval($request->get('reminder_id')) > 0) { $repository->deactivateReminder($request->get('reminder_id'));
$reminder = Auth::user()->reminders()->find($request->get('reminder_id'));
$reminder->active = 0;
$reminder->save();
}
Session::flash('success', 'New transaction "' . $journal->description . '" stored!'); Session::flash('success', 'New transaction "' . $journal->description . '" stored!');
@@ -299,14 +287,15 @@ class TransactionController extends Controller
} }
/** /**
* @param TransactionJournal $journal * @param JournalFormRequest $request
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
* *
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. * @return $this|\Illuminate\Http\RedirectResponse
*
* @return $this
*/ */
public function update(TransactionJournal $journal, JournalFormRequest $request, JournalRepositoryInterface $repository) public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
{ {
$journalData = $request->getJournalData(); $journalData = $request->getJournalData();

View File

@@ -0,0 +1,32 @@
<?php
namespace FireflyIII\Http\Requests;
use Auth;
/**
* Class DeleteAccountFormRequest
*
* @package FireflyIII\Http\Requests
*/
class DeleteAccountFormRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return Auth::check();
}
/**
* @return array
*/
public function rules()
{
return [
'password' => 'required',
];
}
}

View File

@@ -42,6 +42,7 @@ class JournalFormRequest extends Request
'date' => new Carbon($this->get('date')), 'date' => new Carbon($this->get('date')),
'budget_id' => intval($this->get('budget_id')), 'budget_id' => intval($this->get('budget_id')),
'category' => $this->get('category'), 'category' => $this->get('category'),
'tags' => explode(',', $this->get('tags')),
]; ];
} }
@@ -56,7 +57,7 @@ class JournalFormRequest extends Request
$rules = [ $rules = [
'description' => 'required|min:1,max:255', 'description' => 'required|min:1,max:255',
'what' => 'required|in:withdrawal,deposit,transfer|exists:transaction_types,type', 'what' => 'required|in:withdrawal,deposit,transfer',
'amount' => 'numeric|required|min:0.01', 'amount' => 'numeric|required|min:0.01',
'date' => 'required|date', 'date' => 'required|date',
'reminder_id' => 'numeric|exists:reminders,id', 'reminder_id' => 'numeric|exists:reminders,id',

View File

@@ -0,0 +1,53 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 27/04/15
* Time: 12:50
*/
namespace FireflyIII\Http\Requests;
use Auth;
use FireflyIII\Models\Tag;
use Input;
/**
* Class TagFormRequest
*
* @package FireflyIII\Http\Requests
*/
class TagFormRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return Auth::check();
}
/**
* @return array
*/
public function rules()
{
$idRule = '';
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,TRUE';
if (Tag::find(Input::get('id'))) {
$idRule = 'belongsToUser:tags';
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,TRUE,' . Input::get('id');
}
return [
'tag' => $tagRule,
'id' => $idRule,
'description' => 'min:1',
'date' => 'date',
'latitude' => 'numeric|min:-90|max:90',
'longitude' => 'numeric|min:-90|max:90',
'tagMode' => 'required|in:nothing,balancingAct,advancePayment'
];
}
}

View File

@@ -9,6 +9,8 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder; use FireflyIII\Models\Reminder;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
/* /*
@@ -22,6 +24,14 @@ Breadcrumbs::register(
} }
); );
Breadcrumbs::register(
'index',
function (Generator $breadcrumbs) {
$breadcrumbs->push('Home', route('index'));
}
);
// accounts // accounts
Breadcrumbs::register( Breadcrumbs::register(
'accounts.index', function (Generator $breadcrumbs, $what) { 'accounts.index', function (Generator $breadcrumbs, $what) {
@@ -95,6 +105,13 @@ Breadcrumbs::register(
} }
); );
Breadcrumbs::register(
'budgets.noBudget', function (Generator $breadcrumbs, $subTitle) {
$breadcrumbs->parent('budgets.index');
$breadcrumbs->push($subTitle, route('budgets.noBudget'));
}
);
Breadcrumbs::register( Breadcrumbs::register(
'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) { 'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) {
$breadcrumbs->parent('budgets.index'); $breadcrumbs->parent('budgets.index');
@@ -142,6 +159,34 @@ Breadcrumbs::register(
} }
); );
Breadcrumbs::register(
'categories.noCategory', function (Generator $breadcrumbs, $subTitle) {
$breadcrumbs->parent('categories.index');
$breadcrumbs->push($subTitle, route('categories.noCategory'));
}
);
// currencies.
Breadcrumbs::register(
'currency.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Currencies', route('currency.index'));
}
);
Breadcrumbs::register(
'currency.edit', function (Generator $breadcrumbs, TransactionCurrency $currency) {
$breadcrumbs->parent('currency.index');
$breadcrumbs->push('Edit ' . $currency->name, route('currency.edit', $currency->id));
}
);
Breadcrumbs::register(
'currency.delete', function (Generator $breadcrumbs, TransactionCurrency $currency) {
$breadcrumbs->parent('currency.index');
$breadcrumbs->push('Delete ' . $currency->name, route('currency.delete', $currency->id));
}
);
// piggy banks // piggy banks
Breadcrumbs::register( Breadcrumbs::register(
@@ -268,21 +313,21 @@ Breadcrumbs::register(
Breadcrumbs::register( Breadcrumbs::register(
'reports.year', function (Generator $breadcrumbs, Carbon $date) { 'reports.year', function (Generator $breadcrumbs, Carbon $date) {
$breadcrumbs->parent('reports.index'); $breadcrumbs->parent('reports.index');
$breadcrumbs->push($date->format('Y'), route('reports.year', $date->format('Y'))); $breadcrumbs->push($date->year, route('reports.year', $date->year));
} }
); );
Breadcrumbs::register( Breadcrumbs::register(
'reports.month', function (Generator $breadcrumbs, Carbon $date) { 'reports.month', function (Generator $breadcrumbs, Carbon $date) {
$breadcrumbs->parent('reports.index'); $breadcrumbs->parent('reports.index');
$breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', $date)); $breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', [$date->year, $date->month]));
} }
); );
Breadcrumbs::register( Breadcrumbs::register(
'reports.budget', function (Generator $breadcrumbs, Carbon $date) { 'reports.budget', function (Generator $breadcrumbs, Carbon $date) {
$breadcrumbs->parent('reports.index'); $breadcrumbs->parent('reports.index');
$breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', $date)); $breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', [$date->year, $date->month]));
} }
); );
@@ -350,3 +395,24 @@ Breadcrumbs::register(
} }
); );
// tags
Breadcrumbs::register(
'tags.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Tags', route('tags.index'));
}
);
Breadcrumbs::register(
'tags.create', function (Generator $breadcrumbs) {
$breadcrumbs->parent('tags.index');
$breadcrumbs->push('Create tag', route('tags.create'));
}
);
Breadcrumbs::register(
'tags.show', function (Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.index');
$breadcrumbs->push(e($tag->tag), route('tags.show', $tag->id));
}
);

View File

@@ -6,121 +6,177 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder; use FireflyIII\Models\Reminder;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
// models // models
/** @noinspection PhpUnusedParameterInspection */
Route::bind( Route::bind(
'account', 'account',
function ($value, $route) { function ($value, $route) {
if (Auth::check()) { if (Auth::check()) {
$account = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') $object = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.editable', 1) ->where('account_types.editable', 1)
->where('accounts.id', $value) ->where('accounts.id', $value)
->where('user_id', Auth::user()->id) ->where('user_id', Auth::user()->id)
->first(['accounts.*']); ->first(['accounts.*']);
if ($account) { if ($object) {
return $account; return $object;
} }
} }
App::abort(404); throw new NotFoundHttpException;
} }
); );
Route::bind( /** @noinspection PhpUnusedParameterInspection */
'tjSecond', function ($value, $route) {
if (Auth::check()) {
return TransactionJournal::
where('id', $value)->where('user_id', Auth::user()->id)->first();
}
return null;
}
);
Route::bind( Route::bind(
'tj', function ($value, $route) { 'tj', function ($value, $route) {
if (Auth::check()) { if (Auth::check()) {
return TransactionJournal:: $object = TransactionJournal::where('id', $value)->where('user_id', Auth::user()->id)->first();
where('id', $value)->where('user_id', Auth::user()->id)->first(); if ($object) {
return $object;
}
} }
return null; throw new NotFoundHttpException;
} }
); );
/** @noinspection PhpUnusedParameterInspection */
Route::bind( Route::bind(
'currency', function ($value, $route) { 'currency', function ($value, $route) {
return TransactionCurrency::find($value); if (Auth::check()) {
$object = TransactionCurrency::find($value);
if ($object) {
return $object;
}
}
throw new NotFoundHttpException;
} }
); );
/** @noinspection PhpUnusedParameterInspection */
Route::bind( Route::bind(
'bill', function ($value, $route) { 'bill', function ($value, $route) {
if (Auth::check()) { if (Auth::check()) {
return Bill::where('id', $value)->where('user_id', Auth::user()->id)->first(); $object = Bill::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
} }
return null; throw new NotFoundHttpException;
} }
); );
/** @noinspection PhpUnusedParameterInspection */
Route::bind( Route::bind(
'budget', function ($value, $route) { 'budget', function ($value, $route) {
if (Auth::check()) { if (Auth::check()) {
return Budget::where('id', $value)->where('user_id', Auth::user()->id)->first(); $object = Budget::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
} }
return null; throw new NotFoundHttpException;
} }
); );
/** @noinspection PhpUnusedParameterInspection */
Route::bind( Route::bind(
'reminder', function ($value, $route) { 'reminder', function ($value, $route) {
if (Auth::check()) { if (Auth::check()) {
return Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first(); $object = Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
} }
return null; throw new NotFoundHttpException;
} }
); );
/** @noinspection PhpUnusedParameterInspection */
Route::bind( Route::bind(
'limitrepetition', function ($value, $route) { 'limitrepetition', function ($value, $route) {
if (Auth::check()) { if (Auth::check()) {
return LimitRepetition::where('limit_repetitions.id', $value) $object = LimitRepetition::where('limit_repetitions.id', $value)
->leftjoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id') ->leftjoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id') ->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->where('budgets.user_id', Auth::user()->id) ->where('budgets.user_id', Auth::user()->id)
->first(['limit_repetitions.*']); ->first(['limit_repetitions.*']);
if ($object) {
return $object;
}
} }
return null; throw new NotFoundHttpException;
} }
); );
/** @noinspection PhpUnusedParameterInspection */
Route::bind( Route::bind(
'piggyBank', function ($value, $route) { 'piggyBank', function ($value, $route) {
if (Auth::check()) { if (Auth::check()) {
return PiggyBank:: $object = PiggyBank::where('piggy_banks.id', $value)
where('piggy_banks.id', $value) ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('accounts.user_id', Auth::user()->id)
->where('accounts.user_id', Auth::user()->id) ->first(['piggy_banks.*']);
->first(['piggy_banks.*']); if ($object) {
return $object;
}
} }
return null; throw new NotFoundHttpException;
} }
); );
/** @noinspection PhpUnusedParameterInspection */
Route::bind( Route::bind(
'category', function ($value, $route) { 'category', function ($value, $route) {
if (Auth::check()) { if (Auth::check()) {
return Category::where('id', $value)->where('user_id', Auth::user()->id)->first(); $object = Category::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
} }
return null; throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'reminder', function ($value, $route) {
if (Auth::check()) {
/** @var \FireflyIII\Models\Reminder $object */
$object = Reminder::find($value);
if ($object) {
if ($object->remindersable->account->user_id == Auth::user()->id) {
return $object;
}
}
}
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'tag', function ($value, $route) {
if (Auth::check()) {
$object = Tag::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
}
throw new NotFoundHttpException;
} }
); );
@@ -245,6 +301,7 @@ Route::group(
Route::get('/json/expense-accounts', ['uses' => 'JsonController@expenseAccounts', 'as' => 'json.expense-accounts']); Route::get('/json/expense-accounts', ['uses' => 'JsonController@expenseAccounts', 'as' => 'json.expense-accounts']);
Route::get('/json/revenue-accounts', ['uses' => 'JsonController@revenueAccounts', 'as' => 'json.revenue-accounts']); 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/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']);
Route::get('/json/tags', ['uses' => 'JsonController@tags', 'as' => 'json.tags']);
Route::get('/json/box/in', ['uses' => 'JsonController@boxIn', 'as' => 'json.box.in']); 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/out', ['uses' => 'JsonController@boxOut', 'as' => 'json.box.out']);
Route::get('/json/box/bills-unpaid', ['uses' => 'JsonController@boxBillsUnpaid', 'as' => 'json.box.paid']); Route::get('/json/box/bills-unpaid', ['uses' => 'JsonController@boxBillsUnpaid', 'as' => 'json.box.paid']);
@@ -282,18 +339,10 @@ Route::group(
*/ */
Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']); Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']);
Route::get('/profile/change-password', ['uses' => 'ProfileController@changePassword', 'as' => 'change-password']); Route::get('/profile/change-password', ['uses' => 'ProfileController@changePassword', 'as' => 'change-password']);
Route::get('/profile/delete-account', ['uses' => 'ProfileController@deleteAccount', 'as' => 'delete-account']);
Route::post('/profile/delete-account', ['uses' => 'ProfileController@postDeleteAccount', 'as' => 'delete-account-post']);
Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']); Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']);
/**
* Related transactions controller
*/
Route::get('/related/alreadyRelated/{tj}', ['uses' => 'RelatedController@alreadyRelated', 'as' => 'related.alreadyRelated']);
Route::post('/related/relate/{tj}/{tjSecond}', ['uses' => 'RelatedController@relate', 'as' => 'related.relate']);
Route::post('/related/removeRelation/{tj}/{tjSecond}', ['uses' => 'RelatedController@removeRelation', 'as' => 'related.removeRelation']);
Route::get('/related/remove/{tj}/{tjSecond}', ['uses' => 'RelatedController@getRemoveRelation', 'as' => 'related.getRemoveRelation']);
Route::get('/related/related/{tj}', ['uses' => 'RelatedController@related', 'as' => 'related.related']);
Route::post('/related/search/{tj}', ['uses' => 'RelatedController@search', 'as' => 'related.search']);
/** /**
* Reminder Controller * Reminder Controller
*/ */
@@ -325,6 +374,22 @@ Route::group(
*/ */
Route::get('/search', ['uses' => 'SearchController@index', 'as' => 'search']); Route::get('/search', ['uses' => 'SearchController@index', 'as' => 'search']);
/**
* Tag Controller
*/
Route::get('/tags', ['uses' => 'TagController@index', 'as' => 'tags.index']);
Route::get('/tags/create', ['uses' => 'TagController@create', 'as' => 'tags.create']);
Route::get('/tags/show/{tag}', ['uses' => 'TagController@show', 'as' => 'tags.show']);
Route::get('/tags/edit/{tag}', ['uses' => 'TagController@edit', 'as' => 'tags.edit']);
Route::get('/tags/delete/{tag}', ['uses' => 'TagController@delete', 'as' => 'tags.delete']);
Route::post('/tags/store', ['uses' => 'TagController@store', 'as' => 'tags.store']);
Route::post('/tags/update/{tag}', ['uses' => 'TagController@update', 'as' => 'tags.update']);
Route::post('/tags/destroy/{tag}', ['uses' => 'TagController@destroy', 'as' => 'tags.destroy']);
Route::post('/tags/hideTagHelp/{state}', ['uses' => 'TagController@hideTagHelp', 'as' => 'tags.hideTagHelp']);
/** /**
* Transaction Controller * Transaction Controller
*/ */

View File

@@ -51,7 +51,7 @@ class Account extends Model
$account = Account::create($fields); $account = Account::create($fields);
if (is_null($account->id)) { if (is_null($account->id)) {
// could not create account: // could not create account:
App::abort(500, 'Could not create new account with data: ' . json_encode($fields).' because ' . json_encode($account->getErrors())); App::abort(500, 'Could not create new account with data: ' . json_encode($fields) . ' because ' . json_encode($account->getErrors()));
} }

View File

@@ -1,9 +1,10 @@
<?php namespace FireflyIII\Models; <?php namespace FireflyIII\Models;
use App;
use Crypt; use Crypt;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use App;
/** /**
* Class Category * Class Category
* *

View File

@@ -14,7 +14,7 @@ class PiggyBank extends Model
use SoftDeletes; use SoftDeletes;
protected $fillable protected $fillable
= ['name', 'account_id', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me']; = ['name', 'account_id', 'order', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me'];
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo

View File

@@ -78,6 +78,11 @@ class Reminder extends Model
return $query->where('reminders.startdate', '=', $start->format('Y-m-d 00:00:00'))->where('reminders.enddate', '=', $end->format('Y-m-d 00:00:00')); return $query->where('reminders.startdate', '=', $start->format('Y-m-d 00:00:00'))->where('reminders.enddate', '=', $end->format('Y-m-d 00:00:00'));
} }
/**
* @param EloquentBuilder $query
*
* @return $this
*/
public function scopeToday(EloquentBuilder $query) public function scopeToday(EloquentBuilder $query)
{ {
$today = new Carbon; $today = new Carbon;

128
app/Models/Tag.php Normal file
View File

@@ -0,0 +1,128 @@
<?php
namespace FireflyIII\Models;
use App;
use Crypt;
use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait;
/**
* Class Tag
*
* @package FireflyIII\Models
*/
class Tag extends Model
{
use ValidatingTrait;
protected $fillable = ['user_id', 'tag', 'date', 'description', 'longitude', 'latitude', 'zoomLevel', 'tagMode'];
protected $rules
= [
'tag' => 'required|min:1|uniqueObjectForUser:tags,tag,TRUE',
'description' => 'min:1',
'date' => 'date',
'latitude' => 'numeric|min:-90|max:90',
'longitude' => 'numeric|min:-90|max:90',
'tagMode' => 'required|in:nothing,balancingAct,advancePayment'
];
/**
* @param array $fields
*
* @return Tag|null
*/
public static function firstOrCreateEncrypted(array $fields)
{
// everything but the tag:
if (isset($fields['tagMode'])) {
unset($fields['tagMode']);
}
$query = Tag::orderBy('id');
foreach ($fields as $name => $value) {
if ($name != 'tag') {
$query->where($name, $value);
}
}
$set = $query->get(['tags.*']);
/** @var Tag $tag */
foreach ($set as $tag) {
if ($tag->tag == $fields['tag']) {
return $tag;
}
}
// create it!
$fields['tagMode'] = 'nothing';
$fields['description'] = isset($fields['description']) && !is_null($fields['description']) ? $fields['description'] : '';
$tag = Tag::create($fields);
if (is_null($tag->id)) {
// could not create account:
App::abort(500, 'Could not create new tag with data: ' . json_encode($fields) . ' because ' . json_encode($tag->getErrors()));
}
return $tag;
}
/**
* @return array
*/
public function getDates()
{
return ['created_at', 'updated_at', 'date'];
}
/**
* @param $value
*
* @return string
*/
public function getDescriptionAttribute($value)
{
return Crypt::decrypt($value);
}
/**
* @param $value
*
* @return string
*/
public function getTagAttribute($value)
{
return Crypt::decrypt($value);
}
/**
* @param $value
*/
public function setDescriptionAttribute($value)
{
$this->attributes['description'] = Crypt::encrypt($value);
}
/**
* @param $value
*/
public function setTagAttribute($value)
{
$this->attributes['tag'] = Crypt::encrypt($value);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactionjournals()
{
return $this->belongsToMany('FireflyIII\Models\TransactionJournal');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('FireflyIII\User');
}
}

View File

@@ -66,6 +66,39 @@ class TransactionJournal extends Model
return floatval($t->amount); return floatval($t->amount);
} }
} }
return 0;
}
/**
* @return Account|mixed
*/
public function getAssetAccountAttribute()
{
$positive = true; // the asset account is in the transaction with the positive amount.
if ($this->transactionType->type === 'Withdrawal') {
$positive = false;
}
/** @var Transaction $transaction */
foreach ($this->transactions()->get() as $transaction) {
if (floatval($transaction->amount) > 0 && $positive === true) {
return $transaction->account;
}
if (floatval($transaction->amount) < 0 && $positive === false) {
return $transaction->account;
}
}
return $this->transactions()->first();
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactions()
{
return $this->hasMany('FireflyIII\Models\Transaction');
} }
/** /**
@@ -201,6 +234,14 @@ class TransactionJournal extends Model
$this->attributes['encrypted'] = true; $this->attributes['encrypted'] = true;
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('FireflyIII\Models\Tag');
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */
@@ -225,14 +266,6 @@ class TransactionJournal extends Model
return $this->belongsToMany('FireflyIII\Models\TransactionGroup'); return $this->belongsToMany('FireflyIII\Models\TransactionGroup');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactions()
{
return $this->hasMany('FireflyIII\Models\Transaction');
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */

View File

@@ -35,6 +35,7 @@ class AppServiceProvider extends ServiceProvider
'Illuminate\Contracts\Auth\Registrar', 'Illuminate\Contracts\Auth\Registrar',
'FireflyIII\Services\Registrar' 'FireflyIII\Services\Registrar'
); );
} }
} }

View File

@@ -23,7 +23,227 @@ class ConfigServiceProvider extends ServiceProvider
{ {
config( config(
[ [
// 'twigbridge' => [
'twig' => [
/*
|--------------------------------------------------------------------------
| Extension
|--------------------------------------------------------------------------
|
| File extension for Twig view files.
|
*/
'extension' => 'twig',
/*
|--------------------------------------------------------------------------
| Accepts all Twig environment configuration options
|--------------------------------------------------------------------------
|
| http://twig.sensiolabs.org/doc/api.html#environment-options
|
*/
'environment' => [
// When set to true, the generated templates have a __toString() method
// that you can use to display the generated nodes.
// default: false
'debug' => config('app.debug', false),
// The charset used by the templates.
// default: utf-8
'charset' => 'utf-8',
// The base template class to use for generated templates.
// default: TwigBridge\Twig\Template
'base_template_class' => 'TwigBridge\Twig\Template',
// An absolute path where to store the compiled templates, or false to disable caching. If null
// then the cache file path is used.
// default: cache file storage path
'cache' => null,
// When developing with Twig, it's useful to recompile the template
// whenever the source code changes. If you don't provide a value
// for the auto_reload option, it will be determined automatically based on the debug value.
'auto_reload' => true,
// If set to false, Twig will silently ignore invalid variables
// (variables and or attributes/methods that do not exist) and
// replace them with a null value. When set to true, Twig throws an exception instead.
// default: false
'strict_variables' => false,
// If set to true, auto-escaping will be enabled by default for all templates.
// default: true
'autoescape' => true,
// A flag that indicates which optimizations to apply
// (default to -1 -- all optimizations are enabled; set it to 0 to disable)
'optimizations' => -1,
],
/*
|--------------------------------------------------------------------------
| Global variables
|--------------------------------------------------------------------------
|
| These will always be passed in and can be accessed as Twig variables.
| NOTE: these will be overwritten if you pass data into the view with the same key.
|
*/
'globals' => [],
],
'extensions' => [
/*
|--------------------------------------------------------------------------
| Extensions
|--------------------------------------------------------------------------
|
| Enabled extensions.
|
| `Twig_Extension_Debug` is enabled automatically if twig.debug is TRUE.
|
*/
'enabled' => [
'TwigBridge\Extension\Loader\Facades',
'TwigBridge\Extension\Loader\Filters',
'TwigBridge\Extension\Loader\Functions',
'TwigBridge\Extension\Laravel\Auth',
'TwigBridge\Extension\Laravel\Config',
'TwigBridge\Extension\Laravel\Dump',
'TwigBridge\Extension\Laravel\Input',
'TwigBridge\Extension\Laravel\Session',
'TwigBridge\Extension\Laravel\String',
'TwigBridge\Extension\Laravel\Translator',
'TwigBridge\Extension\Laravel\Url',
// 'TwigBridge\Extension\Laravel\Form',
// 'TwigBridge\Extension\Laravel\Html',
// 'TwigBridge\Extension\Laravel\Legacy\Facades',
],
/*
|--------------------------------------------------------------------------
| Facades
|--------------------------------------------------------------------------
|
| Available facades. Access like `{{ Config.get('foo.bar') }}`.
|
| Each facade can take an optional array of options. To mark the whole facade
| as safe you can set the option `'is_safe' => true`. Setting the facade as
| safe means that any HTML returned will not be escaped.
|
| It is advisable to not set the whole facade as safe and instead mark the
| each appropriate method as safe for security reasons. You can do that with
| the following syntax:
|
| <code>
| 'Form' => [
| 'is_safe' => [
| 'open'
| ]
| ]
| </code>
|
| The values of the `is_safe` array must match the called method on the facade
| in order to be marked as safe.
|
*/
'facades' => [
'Breadcrumbs' => [
'is_safe' => [
'renderIfExists'
]
],
'Session',
'Route',
'Auth',
'URL',
'Config',
'ExpandedForm' => [
'is_safe' => [
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
'multiRadio'
]
],
'Form' => [
'is_safe' => [
'input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea'
]
],
],
/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
|
| Available functions. Access like `{{ secure_url(...) }}`.
|
| Each function can take an optional array of options. These options are
| passed directly to `Twig_SimpleFunction`.
|
| So for example, to mark a function as safe you can do the following:
|
| <code>
| 'link_to' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| function differently in your Twig templates than what it's actually called.
|
| <code>
| 'link' => [
| 'callback' => 'link_to'
| ]
| </code>
|
*/
'functions' => [
'elixir',
'head',
'last',
'old'
],
/*
|--------------------------------------------------------------------------
| Filters
|--------------------------------------------------------------------------
|
| Available filters. Access like `{{ variable|filter }}`.
|
| Each filter can take an optional array of options. These options are
| passed directly to `Twig_SimpleFilter`.
|
| So for example, to mark a filter as safe you can do the following:
|
| <code>
| 'studly_case' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| filter differently in your Twig templates than what is actually called.
|
| <code>
| 'snake' => [
| 'callback' => 'snake_case'
| ]
| </code>
|
*/
'filters' => [],
],
]
] ]
); );
} }

View File

@@ -6,6 +6,7 @@ use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\Reminder;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Support\Facades\Navigation; use FireflyIII\Support\Facades\Navigation;
@@ -13,7 +14,6 @@ use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Log; use Log;
use FireflyIII\Models\Reminder;
/** /**
* Class EventServiceProvider * Class EventServiceProvider

View File

@@ -2,13 +2,21 @@
namespace FireflyIII\Providers; namespace FireflyIII\Providers;
use App;
use FireflyIII\Models\Account;
use FireflyIII\Support\Amount; use FireflyIII\Support\Amount;
use FireflyIII\Support\ExpandedForm; use FireflyIII\Support\ExpandedForm;
use FireflyIII\Support\Navigation; use FireflyIII\Support\Navigation;
use FireflyIII\Support\Preferences; use FireflyIII\Support\Preferences;
use FireflyIII\Support\Steam; use FireflyIII\Support\Steam;
use FireflyIII\Support\Twig\Budget;
use FireflyIII\Support\Twig\General;
use FireflyIII\Support\Twig\Journal;
use FireflyIII\Support\Twig\PiggyBank;
use FireflyIII\Validation\FireflyValidator; use FireflyIII\Validation\FireflyValidator;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Twig;
use TwigBridge\Extension\Loader\Functions;
use Validator; use Validator;
/** /**
@@ -25,10 +33,22 @@ class FireflyServiceProvider extends ServiceProvider
return new FireflyValidator($translator, $data, $rules, $messages); return new FireflyValidator($translator, $data, $rules, $messages);
} }
); );
/*
* Default Twig configuration:
*/
$config = App::make('config');
Twig::addExtension(new Functions($config));
Twig::addExtension(new PiggyBank);
Twig::addExtension(new General);
Twig::addExtension(new Journal);
Twig::addExtension(new Budget);
} }
public function register() public function register()
{ {
$this->app->bind( $this->app->bind(
'preferences', function () { 'preferences', function () {
return new Preferences; return new Preferences;
@@ -63,6 +83,8 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository'); $this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository');
$this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository'); $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\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository');
$this->app->bind('FireflyIII\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository');
$this->app->bind('FireflyIII\Repositories\Reminder\ReminderRepositoryInterface', 'FireflyIII\Repositories\Reminder\ReminderRepository');
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search'); $this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
@@ -71,6 +93,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper'); $this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper');
$this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery'); $this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery');
} }
} }

View File

@@ -374,6 +374,8 @@ class AccountRepository implements AccountRepositoryInterface
/** /**
* @param Account $account * @param Account $account
* @param array $data * @param array $data
*
* @return Account
*/ */
public function update(Account $account, array $data) public function update(Account $account, array $data)
{ {

View File

@@ -88,7 +88,7 @@ interface AccountRepositoryInterface
/** /**
* @param Account $account * @param Account $account
* @param string $range * @param $page
* *
* @return LengthAwarePaginator * @return LengthAwarePaginator
*/ */

View File

@@ -211,10 +211,12 @@ class BillRepository implements BillRepositoryInterface
* $today is the start of the next period, to make sure FF3 won't miss anything * $today is the start of the next period, to make sure FF3 won't miss anything
* when the current period has a transaction journal. * when the current period has a transaction journal.
*/ */
$today = Navigation::addPeriod(new Carbon, $bill->repeat_freq, 0); /** @var \Carbon\Carbon $obj */
$obj = new Carbon;
$today = Navigation::addPeriod($obj, $bill->repeat_freq, 0);
$skip = $bill->skip + 1; $skip = $bill->skip + 1;
$start = Navigation::startOfPeriod(new Carbon, $bill->repeat_freq); $start = Navigation::startOfPeriod($obj, $bill->repeat_freq);
/* /*
* go back exactly one month/week/etc because FF3 does not care about 'next' * go back exactly one month/week/etc because FF3 does not care about 'next'
* bills if they're too far into the past. * bills if they're too far into the past.

View File

@@ -72,8 +72,8 @@ interface CategoryRepositoryInterface
/** /**
* @param Category $category * @param Category $category
* @param Carbon $start * @param \Carbon\Carbon $start
* @param Carbon $end * @param \Carbon\Carbon $end
* *
* @return float * @return float
*/ */

View File

@@ -4,13 +4,17 @@ namespace FireflyIII\Repositories\Journal;
use App; use App;
use Auth; use Auth;
use Carbon\Carbon;
use DB;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Log; use Log;
@@ -22,6 +26,38 @@ use Log;
class JournalRepository implements JournalRepositoryInterface class JournalRepository implements JournalRepositoryInterface
{ {
/**
* @param int $reminderId
*
* @return bool
*/
public function deactivateReminder($reminderId)
{
$reminder = Auth::user()->reminders()->find($reminderId);
if ($reminder) {
$reminder->active = 0;
$reminder->save();
}
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function delete(TransactionJournal $journal)
{
// delete transactions first:
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
$transaction->delete();
}
$journal->delete();
return true;
}
/** /**
* Get users first transaction journal * Get users first transaction journal
* *
@@ -33,33 +69,22 @@ class JournalRepository implements JournalRepositoryInterface
} }
/** /**
*
* Get the account_id, which is the asset account that paid for the transaction.
*
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param Transaction $transaction
* *
* @return mixed * @return float
*/ */
public function getAssetAccount(TransactionJournal $journal) public function getAmountBefore(TransactionJournal $journal, Transaction $transaction)
{ {
$positive = true; // the asset account is in the transaction with the positive amount. return floatval(
switch ($journal->transactionType->type) { $transaction->account->transactions()->leftJoin(
case 'Withdrawal': 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
$positive = false; )
break; ->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d'))
} ->where('transaction_journals.order', '>=', $journal->order)
/** @var Transaction $transaction */ ->where('transaction_journals.id', '!=', $journal->id)
foreach ($journal->transactions()->get() as $transaction) { ->sum('transactions.amount')
if (floatval($transaction->amount) > 0 && $positive === true) { );
return $transaction->account_id;
}
if (floatval($transaction->amount) < 0 && $positive === false) {
return $transaction->account_id;
}
}
return $journal->transactions()->first()->account_id;
} }
/** /**
@@ -72,6 +97,28 @@ class JournalRepository implements JournalRepositoryInterface
return Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id)->orderBy('id', 'DESC')->take(50)->get(); return Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id)->orderBy('id', 'DESC')->take(50)->get();
} }
/**
* @param array $types
* @param int $offset
* @param int $page
*
* @return LengthAwarePaginator
*/
public function getJournalsOfTypes(array $types, $offset, $page)
{
$set = Auth::user()->transactionJournals()->transactionTypes($types)->withRelevantData()->take(50)->offset($offset)
->orderBy('date', 'DESC')
->orderBy('order', 'ASC')
->orderBy('id', 'DESC')
->get(
['transaction_journals.*']
);
$count = Auth::user()->transactionJournals()->transactionTypes($types)->count();
$journals = new LengthAwarePaginator($set, $count, 50, $page);
return $journals;
}
/** /**
* @param $type * @param $type
* *
@@ -83,55 +130,37 @@ class JournalRepository implements JournalRepositoryInterface
} }
/** /**
* @param string $query * @param $id
* @param TransactionJournal $journal * @param Carbon $date
* *
* @return Collection * @return TransactionJournal
*/ */
public function searchRelated($query, TransactionJournal $journal) public function getWithDate($id, Carbon $date)
{ {
$start = clone $journal->date; return Auth::user()->transactionjournals()->where('id', $id)->where('date', $date->format('Y-m-d'))->first();
$end = clone $journal->date; }
$start->startOfMonth();
$end->endOfMonth();
// get already related transactions: /**
$exclude = [$journal->id]; *
foreach ($journal->transactiongroups()->get() as $group) { * * Remember: a balancingAct takes at most one expense and one transfer.
foreach ($group->transactionjournals()->get() as $current) { * an advancePayment takes at most one expense, infinite deposits and NO transfers.
$exclude[] = $current->id; *
* @param TransactionJournal $journal
* @param array $array
*
* @return void
*/
public function saveTags(TransactionJournal $journal, array $array)
{
/** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
foreach ($array as $name) {
if (strlen(trim($name)) > 0) {
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
$tagRepository->connect($journal, $tag);
} }
} }
$exclude = array_unique($exclude);
/** @var Collection $collection */
$collection = Auth::user()->transactionjournals()
->withRelevantData()
->before($end)->after($start)->where('encrypted', 0)
->whereNotIn('id', $exclude)
->where('description', 'LIKE', '%' . $query . '%')
->get();
// manually search encrypted entries:
/** @var Collection $encryptedCollection */
$encryptedCollection = Auth::user()->transactionjournals()
->withRelevantData()
->before($end)->after($start)
->where('encrypted', 1)
->whereNotIn('id', $exclude)
->get();
$encrypted = $encryptedCollection->filter(
function (TransactionJournal $journal) use ($query) {
$strPos = strpos(strtolower($journal->description), strtolower($query));
if ($strPos !== false) {
return $journal;
}
return null;
}
);
return $collection->merge($encrypted);
} }
/** /**
@@ -166,6 +195,7 @@ class JournalRepository implements JournalRepositoryInterface
// store or get budget // store or get budget
if (intval($data['budget_id']) > 0) { if (intval($data['budget_id']) > 0) {
/** @var \FireflyIII\Models\Budget $budget */
$budget = Budget::find($data['budget_id']); $budget = Budget::find($data['budget_id']);
$journal->budgets()->save($budget); $journal->budgets()->save($budget);
} }
@@ -191,6 +221,11 @@ class JournalRepository implements JournalRepositoryInterface
$journal->completed = 1; $journal->completed = 1;
$journal->save(); $journal->save();
// store tags
if (isset($data['tags']) && is_array($data['tags'])) {
$this->saveTags($journal, $data['tags']);
}
return $journal; return $journal;
@@ -220,6 +255,7 @@ class JournalRepository implements JournalRepositoryInterface
// unlink all budgets and recreate them: // unlink all budgets and recreate them:
$journal->budgets()->detach(); $journal->budgets()->detach();
if (intval($data['budget_id']) > 0) { if (intval($data['budget_id']) > 0) {
/** @var \FireflyIII\Models\Budget $budget */
$budget = Budget::find($data['budget_id']); $budget = Budget::find($data['budget_id']);
$journal->budgets()->save($budget); $journal->budgets()->save($budget);
} }
@@ -246,9 +282,54 @@ class JournalRepository implements JournalRepositoryInterface
$journal->save(); $journal->save();
// update tags:
if (isset($data['tags']) && is_array($data['tags'])) {
$this->updateTags($journal, $data['tags']);
}
return $journal; return $journal;
} }
/**
* @param TransactionJournal $journal
* @param array $array
*
* @return void
*/
public function updateTags(TransactionJournal $journal, array $array)
{
// create tag repository
/** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
// find or create all tags:
$tags = [];
$ids = [];
foreach ($array as $name) {
if (strlen(trim($name)) > 0) {
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
$tags[] = $tag;
$ids[] = $tag->id;
}
}
// delete all tags connected to journal not in this array:
if (count($ids) > 0) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete();
}
// if count is zero, delete them all:
if (count($ids) == 0) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete();
}
// connect each tag to journal (if not yet connected):
/** @var Tag $tag */
foreach ($tags as $tag) {
$tagRepository->connect($journal, $tag);
}
}
/** /**
* @param TransactionType $type * @param TransactionType $type
* @param array $data * @param array $data

View File

@@ -2,9 +2,11 @@
namespace FireflyIII\Repositories\Journal; namespace FireflyIII\Repositories\Journal;
use Carbon\Carbon;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@@ -14,6 +16,20 @@ use Illuminate\Support\Collection;
*/ */
interface JournalRepositoryInterface interface JournalRepositoryInterface
{ {
/**
* @param int $reminderId
*
* @return bool
*/
public function deactivateReminder($reminderId);
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function delete(TransactionJournal $journal);
/** /**
* Get users first transaction journal * Get users first transaction journal
* *
@@ -22,14 +38,12 @@ interface JournalRepositoryInterface
public function first(); public function first();
/** /**
*
* Get the account_id, which is the asset account that paid for the transaction.
*
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param Transaction $transaction
* *
* @return int * @return float
*/ */
public function getAssetAccount(TransactionJournal $journal); public function getAmountBefore(TransactionJournal $journal, Transaction $transaction);
/** /**
* @param TransactionType $dbType * @param TransactionType $dbType
@@ -39,13 +53,13 @@ interface JournalRepositoryInterface
public function getJournalsOfType(TransactionType $dbType); public function getJournalsOfType(TransactionType $dbType);
/** /**
* @param string $query * @param array $types
* @param TransactionJournal $journal * @param int $offset
* @param int $page
* *
* @return Collection * @return LengthAwarePaginator
*/ */
public function searchRelated($query, TransactionJournal $journal); public function getJournalsOfTypes(array $types, $offset, $page);
/** /**
* @param $type * @param $type
@@ -53,6 +67,30 @@ interface JournalRepositoryInterface
* @return TransactionType * @return TransactionType
*/ */
public function getTransactionType($type); public function getTransactionType($type);
/**
* @param $id
* @param Carbon $date
*
* @return TransactionJournal
*/
public function getWithDate($id, Carbon $date);
/**
* @param TransactionJournal $journal
* @param array $array
*
* @return void
/**
*
* @param TransactionJournal $journal
* @param array $array
*
* @return void
*/
public function saveTags(TransactionJournal $journal, array $array);
/** /**
* @param array $data * @param array $data
* *
@@ -67,4 +105,12 @@ interface JournalRepositoryInterface
* @return mixed * @return mixed
*/ */
public function update(TransactionJournal $journal, array $data); public function update(TransactionJournal $journal, array $data);
/**
* @param TransactionJournal $journal
* @param array $array
*
* @return mixed
*/
public function updateTags(TransactionJournal $journal, array $array);
} }

View File

@@ -3,8 +3,10 @@
namespace FireflyIII\Repositories\PiggyBank; namespace FireflyIII\Repositories\PiggyBank;
use Auth; use Auth;
use Carbon\Carbon;
use DB; use DB;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\PiggyBankRepetition;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Navigation; use Navigation;
@@ -19,7 +21,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
/** /**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
* *
* Based on the piggy bank, the reminder-setting and * Based on the piggy bank, the reminder-setting and
* other variables this method tries to divide the piggy bank into equal parts. Each is * other variables this method tries to divide the piggy bank into equal parts. Each is
@@ -69,6 +70,19 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
return $bars; return $bars;
} }
/**
* @param PiggyBank $piggyBank
* @param $amount
*
* @return bool
*/
public function createEvent(PiggyBank $piggyBank, $amount)
{
PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]);
return true;
}
/** /**
* @param array $data * @param array $data
* *
@@ -87,6 +101,16 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
return $part; return $part;
} }
/**
* @param PiggyBank $piggyBank
*
* @return bool
*/
public function destroy(PiggyBank $piggyBank)
{
return $piggyBank->delete();
}
/** /**
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
@@ -97,7 +121,26 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
return DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]); return DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]);
} }
/**
* @param PiggyBank $piggyBank
*
* @return Collection
*/
public function getEvents(PiggyBank $piggyBank)
{
return $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
}
/**
* @return Collection
*/
public function getPiggyBanks()
{
/** @var Collection $set */
$set = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get();
return $set;
}
/** /**
* Set all piggy banks to order 0. * Set all piggy banks to order 0.
@@ -145,10 +188,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
} }
/** /**
* @param PiggyBank $account * @param PiggyBank $piggyBank
* @param array $data * @param array $data
* *
* @return PiggyBank * @return PiggyBank
* @internal param PiggyBank $account
*/ */
public function update(PiggyBank $piggyBank, array $data) public function update(PiggyBank $piggyBank, array $data)
{ {

View File

@@ -15,7 +15,6 @@ interface PiggyBankRepositoryInterface
{ {
/** /**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
* *
* Based on the piggy bank, the reminder-setting and * Based on the piggy bank, the reminder-setting and
* other variables this method tries to divide the piggy bank into equal parts. Each is * other variables this method tries to divide the piggy bank into equal parts. Each is
@@ -27,6 +26,18 @@ interface PiggyBankRepositoryInterface
*/ */
public function calculateParts(PiggyBankRepetition $repetition); public function calculateParts(PiggyBankRepetition $repetition);
/**
* @return Collection
*/
public function getPiggyBanks();
/**
* @param PiggyBank $piggyBank
*
* @return Collection
*/
public function getEvents(PiggyBank $piggyBank);
/** /**
* @param array $data * @param array $data
* *
@@ -34,6 +45,14 @@ interface PiggyBankRepositoryInterface
*/ */
public function createPiggyBankPart(array $data); public function createPiggyBankPart(array $data);
/**
* @param PiggyBank $piggyBank
* @param $amount
*
* @return bool
*/
public function createEvent(PiggyBank $piggyBank, $amount);
/** /**
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
@@ -41,6 +60,13 @@ interface PiggyBankRepositoryInterface
*/ */
public function getEventSummarySet(PiggyBank $piggyBank); public function getEventSummarySet(PiggyBank $piggyBank);
/**
* @param PiggyBank $piggyBank
*
* @return bool
*/
public function destroy(PiggyBank $piggyBank);
/** /**
* Set all piggy banks to order 0. * Set all piggy banks to order 0.
* *
@@ -68,7 +94,7 @@ interface PiggyBankRepositoryInterface
public function store(array $data); public function store(array $data);
/** /**
* @param PiggyBank $account * @param PiggyBank $piggyBank
* @param array $data * @param array $data
* *
* @return PiggyBank * @return PiggyBank

View File

@@ -0,0 +1,116 @@
<?php
namespace FireflyIII\Repositories\Reminder;
use App;
use Auth;
use Carbon\Carbon;
use FireflyIII\Models\Reminder;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
/**
* Class ReminderRepository
*
* @package FireflyIII\Repositories\Reminder
*/
class ReminderRepository implements ReminderRepositoryInterface
{
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface */
protected $helper;
/**
*
*/
public function __construct()
{
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface helper */
$this->helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
}
/**
* @return Collection
*/
public function getActiveReminders()
{
$today = new Carbon;
// active reminders:
$active = Auth::user()->reminders()
->where('notnow', 0)
->where('active', 1)
->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))
->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))
->get();
$active->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $active;
}
/**
* @return Collection
*/
public function getDismissedReminders()
{
$dismissed = Auth::user()->reminders()
->where('notnow', 1)
->get();
$dismissed->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $dismissed;
}
/**
* @return Collection
*/
public function getExpiredReminders()
{
$expired = Auth::user()->reminders()
->where('notnow', 0)
->where('active', 1)
->where(
function (Builder $q) {
$today = new Carbon;
$q->where('startdate', '>', $today->format('Y-m-d 00:00:00'));
$q->orWhere('enddate', '<', $today->format('Y-m-d 00:00:00'));
}
)->get();
$expired->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $expired;
}
/**
* @return Collection
*/
public function getInactiveReminders()
{
$inactive = Auth::user()->reminders()
->where('active', 0)
->get();
$inactive->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $inactive;
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace FireflyIII\Repositories\Reminder;
use Illuminate\Support\Collection;
/**
* Interface ReminderRepositoryInterface
*
* @package FireflyIII\Repositories\Reminder
*/
interface ReminderRepositoryInterface
{
/**
* @return Collection
*/
public function getActiveReminders();
/**
* @return Collection
*/
public function getDismissedReminders();
/**
* @return Collection
*/
public function getExpiredReminders();
/**
* @return Collection
*/
public function getInactiveReminders();
}

View File

@@ -0,0 +1,180 @@
<?php
namespace FireflyIII\Repositories\Tag;
use Auth;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Support\Collection;
/**
* Class TagRepository
*
* @package FireflyIII\Repositories\Tag
*/
class TagRepository implements TagRepositoryInterface
{
/**
* @param TransactionJournal $journal
* @param Tag $tag
*
* @return boolean
*/
public function connect(TransactionJournal $journal, Tag $tag)
{
/*
* Already connected:
*/
if ($journal->tags()->find($tag->id)) {
return false;
}
if ($tag->tagMode == 'nothing') {
// save it, no problem:
$journal->tags()->save($tag);
return true;
}
/*
* get some withdrawal types:
*/
/** @var TransactionType $withdrawal */
$withdrawal = TransactionType::whereType('Withdrawal')->first();
/** @var TransactionType $deposit */
$deposit = TransactionType::whereType('Deposit')->first();
/** @var TransactionType $transfer */
$transfer = TransactionType::whereType('Transfer')->first();
$withdrawals = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->count();
$transfers = $tag->transactionjournals()->where('transaction_type_id', $transfer->id)->count();
if ($tag->tagMode == 'balancingAct') {
// only if this is the only withdrawal.
if ($journal->transaction_type_id == $withdrawal->id && $withdrawals < 1) {
$journal->tags()->save($tag);
return true;
}
// and only if this is the only transfer
if ($journal->transaction_type_id == $transfer->id && $transfers < 1) {
$journal->tags()->save($tag);
return true;
}
// ignore expense
return false;
}
if ($tag->tagMode == 'advancePayment') {
// only if this is the only withdrawal
if ($journal->transaction_type_id == $withdrawal->id && $withdrawals < 1) {
$journal->tags()->save($tag);
return true;
}
// only if this is a deposit.
if ($journal->transaction_type_id == $deposit->id) {
// if this is a deposit, account must match the current only journal
// (if already present):
$currentWithdrawal = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->first();
if ($currentWithdrawal && $currentWithdrawal->assetAccount->id == $journal->assetAccount->id) {
$journal->tags()->save($tag);
return true;
} else {
if (is_null($currentWithdrawal)) {
$journal->tags()->save($tag);
return true;
}
}
}
return false;
}
return false;
}
/**
* @param Tag $tag
*
* @return boolean
*/
public function destroy(Tag $tag)
{
$tag->delete();
return true;
}
/**
* @return Collection
*/
public function get()
{
/** @var Collection $tags */
$tags = Auth::user()->tags()->get();
$tags->sortBy(
function (Tag $tag) {
return $tag->tag;
}
);
return $tags;
}
/**
* @param array $data
*
* @return Tag
*/
public function store(array $data)
{
$tag = new Tag;
$tag->tag = $data['tag'];
$tag->date = $data['date'];
$tag->description = $data['description'];
$tag->latitude = $data['latitude'];
$tag->longitude = $data['longitude'];
$tag->zoomLevel = $data['zoomLevel'];
$tag->tagMode = $data['tagMode'];
$tag->user()->associate(Auth::user());
$tag->save();
return $tag;
}
/**
* @param Tag $tag
* @param array $data
*
* @return Tag
*/
public function update(Tag $tag, array $data)
{
$tag->tag = $data['tag'];
$tag->date = $data['date'];
$tag->description = $data['description'];
$tag->latitude = $data['latitude'];
$tag->longitude = $data['longitude'];
$tag->zoomLevel = $data['zoomLevel'];
$tag->tagMode = $data['tagMode'];
$tag->save();
return $tag;
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace FireflyIII\Repositories\Tag;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
/**
* Interface TagRepositoryInterface
*
* @package FireflyIII\Repositories\Tag
*/
interface TagRepositoryInterface
{
/**
* @param array $data
*
* @return Tag
*/
public function store(array $data);
/**
* @return Collection
*/
public function get();
/**
* @param Tag $tag
* @param array $data
*
* @return Tag
*/
public function update(Tag $tag, array $data);
/**
* @param Tag $tag
*
* @return boolean
*/
public function destroy(Tag $tag);
/**
* @param TransactionJournal $journal
* @param Tag $tag
*
* @return boolean
*/
public function connect(TransactionJournal $journal, Tag $tag);
}

View File

@@ -84,9 +84,11 @@ class Amount
} }
/** /**
* @return string
* *
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param bool $coloured
*
* @return string
*/ */
public function formatJournal(TransactionJournal $journal, $coloured = true) public function formatJournal(TransactionJournal $journal, $coloured = true)
{ {
@@ -151,23 +153,25 @@ class Amount
if (defined('FFCURRENCYCODE')) { if (defined('FFCURRENCYCODE')) {
return FFCURRENCYCODE; return FFCURRENCYCODE;
} }
if (Cache::has('FFCURRENCYCODE')) {
define('FFCURRENCYCODE', Cache::get('FFCURRENCYCODE'));
return FFCURRENCYCODE;
}
$currencyPreference = Prefs::get('currencyPreference', 'EUR'); $currencyPreference = Prefs::get('currencyPreference', 'EUR');
$currency = TransactionCurrency::whereCode($currencyPreference->data)->first();
\Cache::forever('FFCURRENCYCODE', $currency->code); $currency = TransactionCurrency::whereCode($currencyPreference->data)->first();
if ($currency) {
define('FFCURRENCYCODE', $currency->code); Cache::forever('FFCURRENCYCODE', $currency->code);
define('FFCURRENCYCODE', $currency->code);
return $currency->code; return $currency->code;
}
return 'EUR';
} }
/**
* @return mixed|static
*/
public function getDefaultCurrency() public function getDefaultCurrency()
{ {
$currencyPreference = Prefs::get('currencyPreference', 'EUR'); $currencyPreference = Prefs::get('currencyPreference', 'EUR');

View File

@@ -62,7 +62,10 @@ class ExpandedForm
'account_id' => 'Asset account', 'account_id' => 'Asset account',
'budget_id' => 'Budget', 'budget_id' => 'Budget',
'openingBalance' => 'Opening balance', 'openingBalance' => 'Opening balance',
'tagMode' => 'Tag mode',
'tagPosition' => 'Tag location',
'virtualBalance' => 'Virtual balance', 'virtualBalance' => 'Virtual balance',
'longitude_latitude' => 'Location',
'targetamount' => 'Target amount', 'targetamount' => 'Target amount',
'accountRole' => 'Account role', 'accountRole' => 'Account role',
'openingBalanceDate' => 'Opening balance date', 'openingBalanceDate' => 'Opening balance date',
@@ -194,24 +197,6 @@ class ExpandedForm
return $html; return $html;
} }
/**
* @param $name
* @param null $value
* @param array $options
*
* @return string
*/
public function month($name, $value = null, array $options = [])
{
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value);
$html = View::make('form.month', compact('classes', 'name', 'label', 'value', 'options'))->render();
return $html;
}
/** /**
* @param $name * @param $name
* @param null $value * @param null $value
@@ -233,12 +218,30 @@ class ExpandedForm
} }
/** /**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. * @param $name
* @param null $value
* @param array $options
*
* @return string
*/
public function location($name, $value = null, array $options = [])
{
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value);
$html = View::make('form.location', compact('classes', 'name', 'label', 'value', 'options'))->render();
return $html;
}
/**
* *
* Takes any collection and tries to make a sensible select list compatible array of it. * Takes any collection and tries to make a sensible select list compatible array of it.
* *
* @param Collection $set * @param \Illuminate\Support\Collection $set
* @param bool $addEmpty * @param bool $addEmpty
* *
* @return mixed * @return mixed
*/ */
@@ -265,6 +268,46 @@ class ExpandedForm
return $selectList; return $selectList;
} }
/**
* @param $name
* @param null $value
* @param array $options
*
* @return string
*/
public function month($name, $value = null, array $options = [])
{
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value);
$html = View::make('form.month', compact('classes', 'name', 'label', 'value', 'options'))->render();
return $html;
}
/**
* @param $name
* @param array $list
* @param null $selected
* @param array $options
*
* @return string
* @internal param null $value
*/
public function multiRadio($name, array $list = [], $selected = null, array $options = [])
{
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$selected = $this->fillFieldValue($name, $selected);
unset($options['class']);
$html = View::make('form.multiRadio', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
return $html;
}
/** /**
* @param $type * @param $type
* @param $name * @param $name
@@ -336,4 +379,24 @@ class ExpandedForm
return $html; return $html;
} }
/**
* @param $name
* @param null $value
* @param array $options
*
* @return string
*/
public function textarea($name, $value = null, array $options = [])
{
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value);
$options['rows'] = 4;
$html = View::make('form.textarea', compact('classes', 'name', 'label', 'value', 'options'))->render();
return $html;
}
} }

View File

@@ -15,7 +15,7 @@ class Navigation
/** /**
* @param Carbon $theDate * @param \Carbon\Carbon $theDate
* @param $repeatFreq * @param $repeatFreq
* @param $skip * @param $skip
* *
@@ -64,10 +64,10 @@ class Navigation
} }
/** /**
* @param Carbon $theCurrentEnd * @param \Carbon\Carbon $theCurrentEnd
* @param $repeatFreq * @param $repeatFreq
* *
* @return Carbon * @return \Carbon\Carbon
* @throws FireflyException * @throws FireflyException
*/ */
public function endOfPeriod(Carbon $theCurrentEnd, $repeatFreq) public function endOfPeriod(Carbon $theCurrentEnd, $repeatFreq)
@@ -148,9 +148,8 @@ class Navigation
} }
if (isset($specials[$repeatFreq])) { if (isset($specials[$repeatFreq])) {
$month = intval($theCurrentEnd->format('m'));
$currentEnd->endOfYear(); $currentEnd->endOfYear();
if ($month <= 6) { if ($theCurrentEnd->month <= 6) {
$currentEnd->subMonths(6); $currentEnd->subMonths(6);
} }
} }
@@ -184,7 +183,7 @@ class Navigation
$date->lastOfQuarter()->addDay(); $date->lastOfQuarter()->addDay();
break; break;
case '6M': case '6M':
if (intval($date->format('m')) >= 7) { if ($date->month >= 7) {
$date->startOfYear()->addYear(); $date->startOfYear()->addYear();
} else { } else {
$date->startOfYear()->addMonths(6); $date->startOfYear()->addMonths(6);
@@ -230,9 +229,8 @@ class Navigation
return $date; return $date;
} }
if ($range == '6M') { if ($range == '6M') {
$month = intval($date->format('m'));
$date->startOfYear(); $date->startOfYear();
if ($month <= 6) { if ($date->month <= 6) {
$date->subMonths(6); $date->subMonths(6);
} }
@@ -260,16 +258,15 @@ class Navigation
return $date->format($formatMap[$range]); return $date->format($formatMap[$range]);
} }
if ($range == '3M') { if ($range == '3M') {
$month = intval($date->format('m'));
return 'Q' . ceil(($month / 12) * 4) . ' ' . $date->format('Y');
return 'Q' . ceil(($date->month / 12) * 4) . ' ' . $date->year;
} }
if ($range == '6M') { if ($range == '6M') {
$month = intval($date->format('m')); $half = ceil(($date->month / 12) * 2);
$half = ceil(($month / 12) * 2);
$halfName = $half == 1 ? 'first' : 'second'; $halfName = $half == 1 ? 'first' : 'second';
return $halfName . ' half of ' . $date->format('Y'); return $halfName . ' half of ' . $date->year;
} }
throw new FireflyException('No _periodName() for range "' . $range . '"'); throw new FireflyException('No _periodName() for range "' . $range . '"');
} }
@@ -301,10 +298,10 @@ class Navigation
} }
/** /**
* @param Carbon $theDate * @param \Carbon\Carbon $theDate
* @param $repeatFreq * @param $repeatFreq
* *
* @return Carbon * @return \Carbon\Carbon
* @throws FireflyException * @throws FireflyException
*/ */
public function startOfPeriod(Carbon $theDate, $repeatFreq) public function startOfPeriod(Carbon $theDate, $repeatFreq)
@@ -333,7 +330,7 @@ class Navigation
return $date; return $date;
} }
if ($repeatFreq == 'half-year' || $repeatFreq == '6M') { if ($repeatFreq == 'half-year' || $repeatFreq == '6M') {
$month = intval($date->format('m')); $month = $date->month;
$date->startOfYear(); $date->startOfYear();
if ($month >= 7) { if ($month >= 7) {
$date->addMonths(6); $date->addMonths(6);
@@ -388,9 +385,9 @@ class Navigation
/** /**
* @param $range * @param $range
* @param Carbon $start * @param \Carbon\Carbon $start
* *
* @return Carbon * @return \Carbon\Carbon
* @throws FireflyException * @throws FireflyException
*/ */
public function updateEndDate($range, Carbon $start) public function updateEndDate($range, Carbon $start)
@@ -411,7 +408,7 @@ class Navigation
return $end; return $end;
} }
if ($range == '6M') { if ($range == '6M') {
if (intval($start->format('m')) >= 7) { if ($start->month >= 7) {
$end->endOfYear(); $end->endOfYear();
} else { } else {
$end->startOfYear()->addMonths(6); $end->startOfYear()->addMonths(6);
@@ -423,10 +420,10 @@ class Navigation
} }
/** /**
* @param $range * @param $range
* @param Carbon $start * @param \Carbon\Carbon $start
* *
* @return Carbon * @return \Carbon\Carbon
* @throws FireflyException * @throws FireflyException
*/ */
public function updateStartDate($range, Carbon $start) public function updateStartDate($range, Carbon $start)
@@ -445,7 +442,7 @@ class Navigation
return $start; return $start;
} }
if ($range == '6M') { if ($range == '6M') {
if (intval($start->format('m')) >= 7) { if ($start->month >= 7) {
$start->startOfYear()->addMonths(6); $start->startOfYear()->addMonths(6);
} else { } else {
$start->startOfYear(); $start->startOfYear();

View File

@@ -16,7 +16,7 @@ class Preferences
* @param $name * @param $name
* @param null $default * @param null $default
* *
* @return null|Preference * @return null|\FireflyIII\Models\Preference
*/ */
public function get($name, $default = null) public function get($name, $default = null)
{ {

View File

@@ -84,7 +84,6 @@ class Search implements SearchInterface
} }
/** /**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* *
* @param array $words * @param array $words
* *
@@ -122,6 +121,7 @@ class Search implements SearchInterface
return $journal; return $journal;
} }
} }
return null;
} }
); );

View File

@@ -17,8 +17,8 @@ class Steam
{ {
/** /**
* *
* @param Account $account * @param \FireflyIII\Models\Account $account
* @param Carbon $date * @param \Carbon\Carbon $date
* @param bool $ignoreVirtualBalance * @param bool $ignoreVirtualBalance
* *
* @return float * @return float
@@ -91,7 +91,7 @@ class Steam
* Turns a collection into an array. Needs the field 'id' for the key, * Turns a collection into an array. Needs the field 'id' for the key,
* and saves only 'name' and 'amount' as a sub array. * and saves only 'name' and 'amount' as a sub array.
* *
* @param Collection $collection * @param \Illuminate\Support\Collection $collection
* *
* @return array * @return array
*/ */

View File

@@ -0,0 +1,53 @@
<?php
namespace FireflyIII\Support\Twig;
use Auth;
use DB;
use FireflyIII\Models\LimitRepetition;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Class Budget
*
* @package FireflyIII\Support\Twig
*/
class Budget extends Twig_Extension
{
/**
* {@inheritDoc}
*/
public function getFunctions()
{
$functions[] = new Twig_SimpleFunction(
'spentInRepetition', function (LimitRepetition $repetition) {
$sum = DB::table('transactions')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('transaction_journals.date', '>=', $repetition->startdate->format('Y-m-d'))
->where('transaction_journals.date', '<=', $repetition->enddate->format('Y-m-d'))
->where('transaction_journals.user_id', Auth::user()->id)
->whereNull('transactions.deleted_at')
->where('transactions.amount', '>', 0)
->where('limit_repetitions.id', '=', $repetition->id)
->sum('transactions.amount');
return floatval($sum);
}
);
return $functions;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'FireflyIII\Support\Twig\Budget';
}
}

View File

@@ -0,0 +1,146 @@
<?php
namespace FireflyIII\Support\Twig;
use App;
use Config;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use Route;
use Twig_Extension;
use Twig_SimpleFilter;
use Twig_SimpleFunction;
/**
* Class TwigSupport
*
* @package FireflyIII\Support
*/
class General extends Twig_Extension
{
/**
* @return array
*/
public function getFilters()
{
$filters = [];
$filters[] = new Twig_SimpleFilter(
'formatAmount', function ($string) {
return App::make('amount')->format($string);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'formatTransaction', function (Transaction $transaction) {
return App::make('amount')->formatTransaction($transaction);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'formatAmountPlain', function ($string) {
return App::make('amount')->format($string, false);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'formatJournal', function ($journal) {
return App::make('amount')->formatJournal($journal);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'balance', function (Account $account = null) {
if (is_null($account)) {
return 'NULL';
}
return App::make('steam')->balance($account);
}
);
// should be a function but OK
$filters[] = new Twig_SimpleFilter(
'getAccountRole', function ($name) {
return Config::get('firefly.accountRoles.' . $name);
}
);
return $filters;
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'getCurrencyCode', function () {
return App::make('amount')->getCurrencyCode();
}
);
$functions[] = new Twig_SimpleFunction(
'getCurrencySymbol', function () {
return App::make('amount')->getCurrencySymbol();
}
);
$functions[] = new Twig_SimpleFunction(
'phpdate', function ($str) {
return date($str);
}
);
$functions[] = new Twig_SimpleFunction(
'env', function ($name, $default) {
return env($name, $default);
}
);
$functions[] = new Twig_SimpleFunction(
'activeRoute', function ($context) {
$args = func_get_args();
$route = $args[1];
$what = isset($args[2]) ? $args[2] : false;
$strict = isset($args[3]) ? $args[3] : false;
$activeWhat = isset($context['what']) ? $context['what'] : false;
// activeRoute
if (!($what === false)) {
if ($what == $activeWhat && Route::getCurrentRoute()->getName() == $route) {
return 'active because-active-what';
}
} else {
if (!$strict && !(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
return 'active because-route-matches-non-strict';
} else {
if ($strict && Route::getCurrentRoute()->getName() == $route) {
return 'active because-route-matches-strict';
}
}
}
return 'not-xxx-at-all';
}, ['needs_context' => true]
);
return $functions;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'FireflyIII\Support\Twig\General';
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace FireflyIII\Support\Twig;
use App;
use FireflyIII\Models\TransactionJournal;
use Twig_Extension;
use Twig_SimpleFilter;
use Twig_SimpleFunction;
/**
* Class Journal
*
* @package FireflyIII\Support\Twig
*/
class Journal extends Twig_Extension
{
/**
* @return array
*/
public function getFilters()
{
$filters = [];
$filters[] = new Twig_SimpleFilter(
'typeIcon', function (TransactionJournal $journal) {
$type = $journal->transactionType->type;
if ($type == 'Withdrawal') {
return '<span class="glyphicon glyphicon-arrow-left" title="Withdrawal"></span>';
}
if ($type == 'Deposit') {
return '<span class="glyphicon glyphicon-arrow-right" title="Deposit"></span>';
}
if ($type == 'Transfer') {
return '<i class="fa fa-fw fa-exchange" title="Transfer"></i>';
}
if ($type == 'Opening balance') {
return '<span class="glyphicon glyphicon-ban-circle" title="Opening balance"></span>';
}
return '';
}, ['is_safe' => ['html']]
);
return $filters;
}
/**
* @return array
*/
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'invalidJournal', function (TransactionJournal $journal) {
if (!isset($journal->transactions[1]) || !isset($journal->transactions[0])) {
return true;
}
return false;
}
);
$functions[] = new Twig_SimpleFunction(
'relevantTags', function (TransactionJournal $journal) {
if ($journal->tags->count() == 0) {
return App::make('amount')->formatJournal($journal);
}
foreach ($journal->tags as $tag) {
if ($tag->tagMode == 'balancingAct') {
// return tag formatted for a "balancing act".
$amount = App::make('amount')->formatJournal($journal, false);
return '<a href="' . route('tags.show', $tag->id) . '" class="label label-success" title="' . $amount
. '"><i class="fa fa-fw fa-refresh"></i> ' . $tag->tag . '</span>';
}
}
return 'TODO: ' . $journal->amount;
}
);
return $functions;
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'FireflyIII\Support\Twig\Journals';
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace FireflyIII\Support\Twig;
use FireflyIII\Models\PiggyBank as PB;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Class PiggyBank
*
* @package FireflyIII\Support\Twig
*/
class PiggyBank extends Twig_Extension
{
/**
*
*/
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'currentRelevantRepAmount', function (PB $piggyBank) {
return $piggyBank->currentRelevantRep()->currentamount;
}
);
return $functions;
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'FireflyIII\Support\Twig\PiggyBank';
}
}

View File

@@ -43,6 +43,14 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return $this->hasMany('FireflyIII\Models\Account'); return $this->hasMany('FireflyIII\Models\Account');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function tags()
{
return $this->hasMany('FireflyIII\Models\Tag');
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/ */

View File

@@ -13,6 +13,7 @@ use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Validation\Validator; use Illuminate\Validation\Validator;
use Log; use Log;
use Navigation; use Navigation;
use Symfony\Component\Translation\TranslatorInterface;
/** /**
* Class FireflyValidator * Class FireflyValidator
@@ -22,6 +23,18 @@ use Navigation;
class FireflyValidator extends Validator class FireflyValidator extends Validator
{ {
/**
* @param TranslatorInterface $translator
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
*/
public function __construct(TranslatorInterface $translator, array $data, array $rules, array $messages = [], array $customAttributes = [])
{
parent::__construct($translator, $data, $rules, $messages);
}
/** /**
* @param $attribute * @param $attribute
* @param $value * @param $value
@@ -181,12 +194,22 @@ class FireflyValidator extends Validator
*/ */
public function validateUniqueObjectForUser($attribute, $value, $parameters) public function validateUniqueObjectForUser($attribute, $value, $parameters)
{ {
$table = $parameters[0]; $table = $parameters[0];
$field = $parameters[1]; $field = $parameters[1];
$encrypted = isset($parameters[2]) ? $parameters[2] : 'encrypted'; $encrypted = isset($parameters[2]) ? $parameters[2] : 'encrypted';
$exclude = isset($parameters[3]) ? $parameters[3] : null; $exclude = isset($parameters[3]) ? $parameters[3] : null;
$alwaysEncrypted = false;
if ($encrypted == 'TRUE') {
$alwaysEncrypted = true;
}
if (is_null(Auth::user())) {
// user is not logged in.. weird.
return true;
} else {
$query = DB::table($table)->where('user_id', Auth::user()->id);
}
$query = DB::table($table)->where('user_id', Auth::user()->id);
if (!is_null($exclude)) { if (!is_null($exclude)) {
$query->where('id', '!=', $exclude); $query->where('id', '!=', $exclude);
@@ -195,8 +218,12 @@ class FireflyValidator extends Validator
$set = $query->get(); $set = $query->get();
foreach ($set as $entry) { foreach ($set as $entry) {
$isEncrypted = intval($entry->$encrypted) == 1 ? true : false; if (!$alwaysEncrypted) {
$checkValue = $isEncrypted ? Crypt::decrypt($entry->$field) : $entry->$field; $isEncrypted = intval($entry->$encrypted) == 1 ? true : false;
} else {
$isEncrypted = true;
}
$checkValue = $isEncrypted ? Crypt::decrypt($entry->$field) : $entry->$field;
if ($checkValue == $value) { if ($checkValue == $value) {
return false; return false;
} }

View File

@@ -11,6 +11,7 @@
| |
*/ */
$app = new Illuminate\Foundation\Application( $app = new Illuminate\Foundation\Application(
realpath(__DIR__ . '/../') realpath(__DIR__ . '/../')
); );
@@ -26,6 +27,8 @@ $app = new Illuminate\Foundation\Application(
| |
*/ */
$app->singleton( $app->singleton(
'Illuminate\Contracts\Http\Kernel', 'Illuminate\Contracts\Http\Kernel',
'FireflyIII\Http\Kernel' 'FireflyIII\Http\Kernel'
@@ -41,6 +44,9 @@ $app->singleton(
'FireflyIII\Exceptions\Handler' 'FireflyIII\Exceptions\Handler'
); );
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Return The Application | Return The Application

View File

@@ -26,7 +26,9 @@
"watson/validating": "~1.0", "watson/validating": "~1.0",
"doctrine/dbal": "~2.5", "doctrine/dbal": "~2.5",
"illuminate/html": "~5.0", "illuminate/html": "~5.0",
"league/commonmark": "0.7.*" "league/commonmark": "0.7.*",
"rcrowe/twigbridge": "0.7.x@dev",
"twig/extensions": "~1.2"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "@stable", "barryvdh/laravel-debugbar": "@stable",

339
composer.lock generated
View File

@@ -4,24 +4,24 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "0d43c4c85607c5cdc901cde2d18b75d5", "hash": "e3e90dd365b74f4878cf3b5b4a1c4007",
"packages": [ "packages": [
{ {
"name": "classpreloader/classpreloader", "name": "classpreloader/classpreloader",
"version": "1.2.0", "version": "1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ClassPreloader/ClassPreloader.git", "url": "https://github.com/ClassPreloader/ClassPreloader.git",
"reference": "f0bfbf71fb3335c9473f695d4d966ba2fb879a9f" "reference": "0544616ba33fb2a6b792b3a7822650810c6d65d9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/f0bfbf71fb3335c9473f695d4d966ba2fb879a9f", "url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/0544616ba33fb2a6b792b3a7822650810c6d65d9",
"reference": "f0bfbf71fb3335c9473f695d4d966ba2fb879a9f", "reference": "0544616ba33fb2a6b792b3a7822650810c6d65d9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"nikic/php-parser": "~1.0", "nikic/php-parser": "^1.2.2",
"php": ">=5.3.3", "php": ">=5.3.3",
"symfony/console": "~2.1", "symfony/console": "~2.1",
"symfony/filesystem": "~2.1", "symfony/filesystem": "~2.1",
@@ -36,7 +36,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.2-dev" "dev-master": "1.3-dev"
} }
}, },
"autoload": { "autoload": {
@@ -64,7 +64,7 @@
"class", "class",
"preload" "preload"
], ],
"time": "2015-01-26 22:06:19" "time": "2015-04-15 21:59:30"
}, },
{ {
"name": "danielstjules/stringy", "name": "danielstjules/stringy",
@@ -206,16 +206,16 @@
}, },
{ {
"name": "doctrine/annotations", "name": "doctrine/annotations",
"version": "v1.2.3", "version": "v1.2.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/annotations.git", "url": "https://github.com/doctrine/annotations.git",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4" "reference": "b5202eb9e83f8db52e0e58867e0a46e63be8332e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/eeda578cbe24a170331a1cfdf78be723412df7a4", "url": "https://api.github.com/repos/doctrine/annotations/zipball/b5202eb9e83f8db52e0e58867e0a46e63be8332e",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4", "reference": "b5202eb9e83f8db52e0e58867e0a46e63be8332e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -270,20 +270,20 @@
"docblock", "docblock",
"parser" "parser"
], ],
"time": "2014-12-20 20:49:38" "time": "2014-12-23 22:40:37"
}, },
{ {
"name": "doctrine/cache", "name": "doctrine/cache",
"version": "v1.4.0", "version": "v1.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/cache.git", "url": "https://github.com/doctrine/cache.git",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8" "reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/2346085d2b027b233ae1d5de59b07440b9f288c8", "url": "https://api.github.com/repos/doctrine/cache/zipball/c9eadeb743ac6199f7eec423cb9426bc518b7b03",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8", "reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -294,13 +294,13 @@
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": ">=3.7", "phpunit/phpunit": ">=3.7",
"predis/predis": "~0.8", "predis/predis": "~1.0",
"satooshi/php-coveralls": "~0.6" "satooshi/php-coveralls": "~0.6"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.4.x-dev" "dev-master": "1.5.x-dev"
} }
}, },
"autoload": { "autoload": {
@@ -340,25 +340,28 @@
"cache", "cache",
"caching" "caching"
], ],
"time": "2015-01-15 20:38:55" "time": "2015-04-15 00:11:59"
}, },
{ {
"name": "doctrine/collections", "name": "doctrine/collections",
"version": "v1.2", "version": "v1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/collections.git", "url": "https://github.com/doctrine/collections.git",
"reference": "b99c5c46c87126201899afe88ec490a25eedd6a2" "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/collections/zipball/b99c5c46c87126201899afe88ec490a25eedd6a2", "url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
"reference": "b99c5c46c87126201899afe88ec490a25eedd6a2", "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.2" "php": ">=5.3.2"
}, },
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
@@ -375,17 +378,6 @@
"MIT" "MIT"
], ],
"authors": [ "authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{ {
"name": "Roman Borschel", "name": "Roman Borschel",
"email": "roman@code-factory.org" "email": "roman@code-factory.org"
@@ -394,11 +386,17 @@
"name": "Benjamin Eberlei", "name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de" "email": "kontakt@beberlei.de"
}, },
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{ {
"name": "Johannes Schmitt", "name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com", "email": "schmittjoh@gmail.com"
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
} }
], ],
"description": "Collections Abstraction library", "description": "Collections Abstraction library",
@@ -408,7 +406,7 @@
"collections", "collections",
"iterator" "iterator"
], ],
"time": "2014-02-03 23:07:43" "time": "2015-04-14 22:21:58"
}, },
{ {
"name": "doctrine/common", "name": "doctrine/common",
@@ -945,16 +943,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v5.0.27", "version": "v5.0.28",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "4d6330118a295086ce9ff8eed2200d5b67f17688" "reference": "06a09429322cf53e5bd4587db1060f02a291562e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/4d6330118a295086ce9ff8eed2200d5b67f17688", "url": "https://api.github.com/repos/laravel/framework/zipball/06a09429322cf53e5bd4587db1060f02a291562e",
"reference": "4d6330118a295086ce9ff8eed2200d5b67f17688", "reference": "06a09429322cf53e5bd4587db1060f02a291562e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1024,7 +1022,7 @@
"predis/predis": "~1.0" "predis/predis": "~1.0"
}, },
"suggest": { "suggest": {
"aws/aws-sdk-php": "Required to use the SQS queue driver (~2.4).", "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~2.4).",
"doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).",
"guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers (~5.0).", "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers (~5.0).",
"iron-io/iron_mq": "Required to use the iron queue driver (~1.5).", "iron-io/iron_mq": "Required to use the iron queue driver (~1.5).",
@@ -1067,7 +1065,7 @@
"framework", "framework",
"laravel" "laravel"
], ],
"time": "2015-04-04 01:34:57" "time": "2015-04-21 01:44:32"
}, },
{ {
"name": "league/commonmark", "name": "league/commonmark",
@@ -1377,16 +1375,16 @@
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
"version": "v1.2.2", "version": "v1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/PHP-Parser.git", "url": "https://github.com/nikic/PHP-Parser.git",
"reference": "08f97eb4efa029e2fafb6d8c98b71731bf0cf621" "reference": "dff239267fd1befa1cd40430c9ed12591aa720ca"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/08f97eb4efa029e2fafb6d8c98b71731bf0cf621", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dff239267fd1befa1cd40430c9ed12591aa720ca",
"reference": "08f97eb4efa029e2fafb6d8c98b71731bf0cf621", "reference": "dff239267fd1befa1cd40430c9ed12591aa720ca",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1396,7 +1394,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.2-dev" "dev-master": "1.3-dev"
} }
}, },
"autoload": { "autoload": {
@@ -1418,7 +1416,7 @@
"parser", "parser",
"php" "php"
], ],
"time": "2015-04-03 14:33:59" "time": "2015-05-02 15:40:40"
}, },
{ {
"name": "psr/log", "name": "psr/log",
@@ -1529,6 +1527,70 @@
], ],
"time": "2015-03-26 18:43:54" "time": "2015-03-26 18:43:54"
}, },
{
"name": "rcrowe/twigbridge",
"version": "0.7.x-dev",
"source": {
"type": "git",
"url": "https://github.com/rcrowe/TwigBridge.git",
"reference": "ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026",
"reference": "ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026",
"shasum": ""
},
"require": {
"illuminate/support": "5.0.*",
"illuminate/view": "5.0.*",
"php": ">=5.4.0",
"twig/twig": "~1.15"
},
"require-dev": {
"laravel/framework": "5.0.*",
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "~0.6",
"squizlabs/php_codesniffer": "~1.5"
},
"suggest": {
"laravelcollective/html": "For bringing back html/form in Laravel 5.x",
"twig/extensions": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.7-dev"
}
},
"autoload": {
"psr-4": {
"TwigBridge\\": "src",
"TwigBridge\\Tests\\": "tests"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
},
{
"name": "Rob Crowe",
"email": "hello@vivalacrowe.com"
}
],
"description": "Adds the power of Twig to Laravel",
"keywords": [
"laravel",
"twig"
],
"time": "2015-04-22 09:19:03"
},
{ {
"name": "swiftmailer/swiftmailer", "name": "swiftmailer/swiftmailer",
"version": "v5.4.0", "version": "v5.4.0",
@@ -2293,6 +2355,115 @@
], ],
"time": "2015-03-31 08:12:29" "time": "2015-03-31 08:12:29"
}, },
{
"name": "twig/extensions",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig-extensions.git",
"reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/8cf4b9fe04077bd54fc73f4fde83347040c3b8cd",
"reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd",
"shasum": ""
},
"require": {
"twig/twig": "~1.12"
},
"require-dev": {
"symfony/translation": "~2.3"
},
"suggest": {
"symfony/translation": "Allow the time_diff output to be translated"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"psr-0": {
"Twig_Extensions_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Common additional features for Twig that do not directly belong in core",
"homepage": "http://twig.sensiolabs.org/doc/extensions/index.html",
"keywords": [
"i18n",
"text"
],
"time": "2014-10-30 14:30:03"
},
{
"name": "twig/twig",
"version": "v1.18.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/9f70492f44398e276d1b81c1b43adfe6751c7b7f",
"reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f",
"shasum": ""
},
"require": {
"php": ">=5.2.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.18-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
},
{
"name": "Twig Team",
"homepage": "http://twig.sensiolabs.org/contributors",
"role": "Contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"time": "2015-04-19 08:30:27"
},
{ {
"name": "vlucas/phpdotenv", "name": "vlucas/phpdotenv",
"version": "v1.1.0", "version": "v1.1.0",
@@ -3027,23 +3198,23 @@
}, },
{ {
"name": "phpspec/phpspec", "name": "phpspec/phpspec",
"version": "2.1.1", "version": "2.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpspec/phpspec.git", "url": "https://github.com/phpspec/phpspec.git",
"reference": "66a1df93099282b1514e9e001fcf6e9393f7783d" "reference": "9727d75919a00455433e867565bc022f0b985a39"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpspec/phpspec/zipball/66a1df93099282b1514e9e001fcf6e9393f7783d", "url": "https://api.github.com/repos/phpspec/phpspec/zipball/9727d75919a00455433e867565bc022f0b985a39",
"reference": "66a1df93099282b1514e9e001fcf6e9393f7783d", "reference": "9727d75919a00455433e867565bc022f0b985a39",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"doctrine/instantiator": "~1.0,>=1.0.1", "doctrine/instantiator": "^1.0.1",
"php": ">=5.3.3", "php": ">=5.3.3",
"phpspec/php-diff": "~1.0.0", "phpspec/php-diff": "~1.0.0",
"phpspec/prophecy": "~1.1", "phpspec/prophecy": "~1.4",
"sebastian/exporter": "~1.0", "sebastian/exporter": "~1.0",
"symfony/console": "~2.3", "symfony/console": "~2.3",
"symfony/event-dispatcher": "~2.1", "symfony/event-dispatcher": "~2.1",
@@ -3052,9 +3223,11 @@
"symfony/yaml": "~2.1" "symfony/yaml": "~2.1"
}, },
"require-dev": { "require-dev": {
"behat/behat": "~3.0,>=3.0.11", "behat/behat": "^3.0.11",
"bossa/phpspec2-expect": "~1.0", "bossa/phpspec2-expect": "~1.0",
"symfony/filesystem": "~2.1" "phpunit/phpunit": "~4.4",
"symfony/filesystem": "~2.1",
"symfony/process": "~2.1"
}, },
"suggest": { "suggest": {
"phpspec/nyan-formatters": "~1.0 Adds Nyan formatters" "phpspec/nyan-formatters": "~1.0 Adds Nyan formatters"
@@ -3065,7 +3238,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.1.x-dev" "dev-master": "2.2.x-dev"
} }
}, },
"autoload": { "autoload": {
@@ -3099,20 +3272,20 @@
"testing", "testing",
"tests" "tests"
], ],
"time": "2015-01-09 13:21:45" "time": "2015-04-18 16:22:51"
}, },
{ {
"name": "phpspec/prophecy", "name": "phpspec/prophecy",
"version": "1.4.0", "version": "v1.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpspec/prophecy.git", "url": "https://github.com/phpspec/prophecy.git",
"reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5" "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373",
"reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5", "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3159,20 +3332,20 @@
"spy", "spy",
"stub" "stub"
], ],
"time": "2015-03-27 19:31:25" "time": "2015-04-27 22:15:08"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "2.0.15", "version": "2.0.16",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "34cc484af1ca149188d0d9e91412191e398e0b67" "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c",
"reference": "34cc484af1ca149188d0d9e91412191e398e0b67", "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3221,7 +3394,7 @@
"testing", "testing",
"xunit" "xunit"
], ],
"time": "2015-01-24 10:06:35" "time": "2015-04-11 04:35:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
@@ -3360,16 +3533,16 @@
}, },
{ {
"name": "phpunit/php-token-stream", "name": "phpunit/php-token-stream",
"version": "1.4.0", "version": "1.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git", "url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74" "reference": "eab81d02569310739373308137284e0158424330"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/db32c18eba00b121c145575fcbcd4d4d24e6db74", "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330",
"reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74", "reference": "eab81d02569310739373308137284e0158424330",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3405,20 +3578,20 @@
"keywords": [ "keywords": [
"tokenizer" "tokenizer"
], ],
"time": "2015-01-17 09:51:32" "time": "2015-04-08 04:46:07"
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "4.6.1", "version": "4.6.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "08b2aacdd8433abbba468f995d6d64b76a7a62ec" "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/08b2aacdd8433abbba468f995d6d64b76a7a62ec", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3afe303d873a4d64c62ef84de491b97b006fbdac",
"reference": "08b2aacdd8433abbba468f995d6d64b76a7a62ec", "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3457,9 +3630,6 @@
"autoload": { "autoload": {
"classmap": [ "classmap": [
"src/" "src/"
],
"files": [
"src/Framework/Assert/Functions.php"
] ]
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@@ -3480,7 +3650,7 @@
"testing", "testing",
"xunit" "xunit"
], ],
"time": "2015-04-03 13:46:59" "time": "2015-04-29 15:18:52"
}, },
{ {
"name": "phpunit/phpunit-mock-objects", "name": "phpunit/phpunit-mock-objects",
@@ -4182,6 +4352,7 @@
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": { "stability-flags": {
"rcrowe/twigbridge": 20,
"barryvdh/laravel-debugbar": 0 "barryvdh/laravel-debugbar": 0
}, },
"prefer-stable": false, "prefer-stable": false,

View File

@@ -136,7 +136,11 @@ return [
'Illuminate\Validation\ValidationServiceProvider', 'Illuminate\Validation\ValidationServiceProvider',
'Illuminate\View\ViewServiceProvider', 'Illuminate\View\ViewServiceProvider',
'Illuminate\Html\HtmlServiceProvider', 'Illuminate\Html\HtmlServiceProvider',
'TwigBridge\ServiceProvider',
'DaveJamesMiller\Breadcrumbs\ServiceProvider', 'DaveJamesMiller\Breadcrumbs\ServiceProvider',
'Barryvdh\Debugbar\ServiceProvider',
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
/* /*
* Application Service Providers... * Application Service Providers...
@@ -149,6 +153,7 @@ return [
'FireflyIII\Providers\FireflyServiceProvider', 'FireflyIII\Providers\FireflyServiceProvider',
'FireflyIII\Providers\TestingServiceProvider', 'FireflyIII\Providers\TestingServiceProvider',
], ],
/* /*
@@ -198,13 +203,14 @@ return [
'View' => 'Illuminate\Support\Facades\View', 'View' => 'Illuminate\Support\Facades\View',
'Form' => 'Illuminate\Html\FormFacade', 'Form' => 'Illuminate\Html\FormFacade',
'Html' => 'Illuminate\Html\HtmlFacade', 'Html' => 'Illuminate\Html\HtmlFacade',
'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade', 'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade',
'Preferences' => 'FireflyIII\Support\Facades\Preferences', 'Preferences' => 'FireflyIII\Support\Facades\Preferences',
'Navigation' => 'FireflyIII\Support\Facades\Navigation', 'Navigation' => 'FireflyIII\Support\Facades\Navigation',
'Amount' => 'FireflyIII\Support\Facades\Amount', 'Amount' => 'FireflyIII\Support\Facades\Amount',
'Steam' => 'FireflyIII\Support\Facades\Steam', 'Steam' => 'FireflyIII\Support\Facades\Steam',
'ExpandedForm' => 'FireflyIII\Support\Facades\ExpandedForm', 'ExpandedForm' => 'FireflyIII\Support\Facades\ExpandedForm',
'Twig' => 'TwigBridge\Facade\Twig',
], ],

View File

@@ -48,7 +48,7 @@ return [
'sqlite' => [ 'sqlite' => [
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => ':memory:', 'database' => __DIR__.'/../storage/database/testing.db',
'prefix' => '', 'prefix' => '',
], ],

View File

@@ -14,7 +14,7 @@ return [
*/ */
'paths' => [ 'paths' => [
realpath(base_path('resources/views')) realpath(base_path('resources/twig'))
], ],
/* /*

View File

@@ -4,6 +4,8 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
/** /**
* @SuppressWarnings(PHPMD.ShortMethodName)
*
* Class CreatePasswordResetsTable * Class CreatePasswordResetsTable
*/ */
class CreatePasswordResetsTable extends Migration class CreatePasswordResetsTable extends Migration

View File

@@ -41,6 +41,9 @@ class CreateAccountMetaTable extends Migration
$table->unique(['account_id', 'name']); $table->unique(['account_id', 'name']);
// link to account!
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
} }
); );

View File

@@ -7,6 +7,7 @@ use FireflyIII\Models\Component;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
/** /**
* @SuppressWarnings(PHPMD.ShortMethodName) // method names are mandated by laravel. * @SuppressWarnings(PHPMD.ShortMethodName) // method names are mandated by laravel.
* @SuppressWarnings("TooManyMethods") // I'm fine with this * @SuppressWarnings("TooManyMethods") // I'm fine with this

View File

@@ -5,7 +5,7 @@ use Illuminate\Database\Schema\Blueprint;
/** /**
* @SuppressWarnings(PHPMD.ShortMethodName) * @SuppressWarnings(PHPMD.ShortMethodName)
* @SuppressWarnings("MethodLength") // I don't mind this in case of migrations. * @SuppressWarnings("PHPMD.ExcessiveMethodLength")
* *
* Class ChangesForV322 * Class ChangesForV322
*/ */

View File

@@ -5,7 +5,7 @@ use Illuminate\Database\Schema\Blueprint;
/** /**
* @SuppressWarnings(PHPMD.ShortMethodName) * @SuppressWarnings(PHPMD.ShortMethodName)
* @SuppressWarnings("MethodLength") // I don't mind this in case of migrations. * @SuppressWarnings("PHPMD.ExcessiveMethodLength")
* *
* Class ChangesForV325 * Class ChangesForV325
*/ */

View File

@@ -4,6 +4,8 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
/** /**
* @SuppressWarnings(PHPMD.ShortMethodName)
*
* Class ChangesForV332 * Class ChangesForV332
*/ */
class ChangesForV332 extends Migration class ChangesForV332 extends Migration

View File

@@ -3,6 +3,11 @@
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
*
* Class ChangesForV333
*/
class ChangesForV333 extends Migration class ChangesForV333 extends Migration
{ {

View File

@@ -4,6 +4,9 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
/** /**
* @SuppressWarnings(PHPMD.ShortMethodName)
* @SuppressWarnings("PHPMD.ExcessiveMethodLength")
*
* Class ChangesForV336 * Class ChangesForV336
*/ */
class ChangesForV336 extends Migration class ChangesForV336 extends Migration
@@ -134,7 +137,7 @@ class ChangesForV336 extends Migration
// reinstate a long forgotten index: // reinstate a long forgotten index:
Schema::table( Schema::table(
'budget_limits', function (Blueprint $table) { 'budget_limits', function (Blueprint $table) {
$table->unique(['budget_id', 'startdate'],'unique_limit'); $table->unique(['budget_id', 'startdate'], 'unique_limit');
} }
); );

View File

@@ -0,0 +1,83 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
* @SuppressWarnings("PHPMD.ExcessiveMethodLength")
*
* Class ChangesForV3310
*/
class ChangesForV3310 extends Migration
{
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('tag_transaction_journal');
Schema::drop('tags');
}
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
Schema::table(
'transaction_groups', function (Blueprint $table) {
// drop column "relation"
$table->dropColumn('relation');
}
);
/*
* New table!
*/
Schema::create(
'tags', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->softDeletes();
$table->integer('user_id')->unsigned();
$table->string('tag', 1024);
$table->string('tagMode', 1024);
$table->date('date')->nullable();
$table->text('description')->nullable();
$table->decimal('latitude', 18, 12)->nullable();
$table->decimal('longitude', 18, 12)->nullable();
$table->smallInteger('zoomLevel', false, true)->nullable();
// connect reminders to users
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
}
);
Schema::create(
'tag_transaction_journal', function (Blueprint $table) {
$table->increments('id');
$table->integer('tag_id')->unsigned();
$table->integer('transaction_journal_id')->unsigned();
// link to foreign tables.
$table->foreign('tag_id', 'tag_grp_id')->references('id')->on('tags')->onDelete('cascade');
$table->foreign('transaction_journal_id', 'tag_trj_id')->references('id')->on('transaction_journals')->onDelete('cascade');
// add unique.
$table->unique(['tag_id', 'transaction_journal_id'], 'tag_t_joined');
}
);
}
}

View File

@@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
*
* Class ChangesForV3310a
*/
class ChangesForV3310a extends Migration
{
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table(
'transaction_groups', function (Blueprint $table) {
// new column, relation.
$table->string('relation', 50)->nullable();
}
);
// make new column "relation"
}
}

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
*
* Class ChangesForV3310b
*/
class ChangesForV3310b extends Migration
{
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// set all current entries to be "balance"
DB::table('transaction_groups')->update(['relation' => 'balance']);
}
}

View File

@@ -7,7 +7,7 @@
convertNoticesToExceptions="true" convertNoticesToExceptions="true"
convertWarningsToExceptions="true" convertWarningsToExceptions="true"
processIsolation="false" processIsolation="false"
stopOnFailure="false" stopOnFailure="true"
syntaxCheck="false"> syntaxCheck="false">
<testsuites> <testsuites>
<testsuite name="Application Test Suite"> <testsuite name="Application Test Suite">

5
pu.sh
View File

@@ -1,8 +1,5 @@
#!/bin/bash #!/bin/bash
# backup .env file.
cp .env .env.backup
# set testing environment # set testing environment
cp .env.testing .env cp .env.testing .env
@@ -18,4 +15,4 @@ then
fi fi
# restore .env file # restore .env file
mv .env.backup .env cp .env.local .env

View File

@@ -5,4 +5,9 @@
.ui-sortable-placeholder { .ui-sortable-placeholder {
display: inline-block; display: inline-block;
height: 1px; height: 1px;
}
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
} }

View File

@@ -0,0 +1 @@
{"version":3,"file":"dist/bootstrap-tagsinput-angular.min.js","sources":["src/bootstrap-tagsinput-angular.js"],"names":["angular","module","directive","getItemProperty","scope","property","isFunction","$parent","item","undefined","restrict","model","template","replace","link","element","attrs","$","isArray","select","typeaheadSourceArray","typeaheadSource","split","length","tagsinput","options","typeahead","source","itemValue","itemvalue","itemText","itemtext","confirmKeys","confirmkeys","JSON","parse","tagClass","tagclass","i","on","event","indexOf","push","idx","splice","prev","slice","$watch","added","filter","removed"],"mappings":";;;;;AAAAA,QAAQC,OAAO,0BACdC,UAAU,sBAAuB,WAEhC,QAASC,GAAgBC,EAAOC,GAC9B,MAAKA,GAGDL,QAAQM,WAAWF,EAAMG,QAAQF,IAC5BD,EAAMG,QAAQF,GAEhB,SAASG,GACd,MAAOA,GAAKH,IANLI,OAUX,OACEC,SAAU,KACVN,OACEO,MAAO,YAETC,SAAU,6BACVC,SAAS,EACTC,KAAM,SAASV,EAAOW,EAASC,GAC7BC,EAAE,WACKjB,QAAQkB,QAAQd,EAAMO,SACzBP,EAAMO,SAER,IAAIQ,GAASF,EAAE,SAAUF,GACrBK,EAAuBJ,EAAMK,gBAAkBL,EAAMK,gBAAgBC,MAAM,KAAO,KAClFD,EAAkBD,EACjBA,EAAqBG,OAAS,EAC3BnB,EAAMG,QAAQa,EAAqB,IAAIA,EAAqB,IAC1DhB,EAAMG,QAAQa,EAAqB,IACvC,IAEND,GAAOK,UAAUpB,EAAMG,QAAQS,EAAMS,SAAW,MAC9CC,WACEC,OAAW3B,QAAQM,WAAWe,GAAmBA,EAAkB,MAErEO,UAAWzB,EAAgBC,EAAOY,EAAMa,WACxCC,SAAW3B,EAAgBC,EAAOY,EAAMe,UACxCC,YAAc7B,EAAgBC,EAAOY,EAAMiB,aAAeC,KAAKC,MAAMnB,EAAMiB,cAAgB,IAC3FG,SAAWpC,QAAQM,WAAWF,EAAMG,QAAQS,EAAMqB,WAAajC,EAAMG,QAAQS,EAAMqB,UAAY,WAAiB,MAAOrB,GAAMqB,WAG/H,KAAK,GAAIC,GAAI,EAAGA,EAAIlC,EAAMO,MAAMY,OAAQe,IACtCnB,EAAOK,UAAU,MAAOpB,EAAMO,MAAM2B,GAGtCnB,GAAOoB,GAAG,YAAa,SAASC,GACU,KAApCpC,EAAMO,MAAM8B,QAAQD,EAAMhC,OAC5BJ,EAAMO,MAAM+B,KAAKF,EAAMhC,QAG3BW,EAAOoB,GAAG,cAAe,SAASC,GAChC,GAAIG,GAAMvC,EAAMO,MAAM8B,QAAQD,EAAMhC,KACxB,MAARmC,GACFvC,EAAMO,MAAMiC,OAAOD,EAAK,IAK5B,IAAIE,GAAOzC,EAAMO,MAAMmC,OACvB1C,GAAM2C,OAAO,QAAS,WACpB,GAEIT,GAFAU,EAAQ5C,EAAMO,MAAMsC,OAAO,SAASX,GAAI,MAA2B,KAApBO,EAAKJ,QAAQH,KAC5DY,EAAUL,EAAKI,OAAO,SAASX,GAAI,MAAkC,KAA3BlC,EAAMO,MAAM8B,QAAQH,IAMlE,KAHAO,EAAOzC,EAAMO,MAAMmC,QAGdR,EAAI,EAAGA,EAAIY,EAAQ3B,OAAQe,IAC9BnB,EAAOK,UAAU,SAAU0B,EAAQZ,GAOrC,KAHAnB,EAAOK,UAAU,WAGZc,EAAI,EAAGA,EAAIU,EAAMzB,OAAQe,IAC5BnB,EAAOK,UAAU,MAAOwB,EAAMV,MAE/B"}

View File

@@ -3,7 +3,7 @@ google.setOnLoadCallback(drawChart);
function drawChart() { function drawChart() {
googleLineChart('chart/home/account', 'accounts-chart'); googleLineChart('chart/home/account', 'accounts-chart');
googleBarChart('chart/home/budgets', 'budgets-chart'); googleColumnChart('chart/home/budgets', 'budgets-chart');
googleColumnChart('chart/home/categories', 'categories-chart'); googleColumnChart('chart/home/categories', 'categories-chart');
googlePieChart('chart/home/bills', 'bills-chart'); googlePieChart('chart/home/bills', 'bills-chart');
getBoxAmounts(); getBoxAmounts();
@@ -14,9 +14,7 @@ function getBoxAmounts() {
for (x in boxes) { for (x in boxes) {
var box = boxes[x]; var box = boxes[x];
$.getJSON('/json/box/' + box).success(function (data) { $.getJSON('/json/box/' + box).success(function (data) {
if (data.amount_raw != 0) { $('#box-' + data.box).html(data.amount);
$('#box-' + data.box).html(data.amount);
}
}).fail(function () { }).fail(function () {
console.log('Failed to get box!') console.log('Failed to get box!')
}); });

View File

@@ -5,14 +5,43 @@ $(function () {
if (typeof(googleLineChart) === 'function' && typeof(piggyBankID) !== 'undefined') { if (typeof(googleLineChart) === 'function' && typeof(piggyBankID) !== 'undefined') {
googleLineChart('chart/piggy-history/' + piggyBankID, 'piggy-bank-history'); googleLineChart('chart/piggy-history/' + piggyBankID, 'piggy-bank-history');
} }
$('#sortable').sortable(
$('#sortable tbody').sortable(
{ {
helper: fixHelper,
stop: stopSorting, stop: stopSorting,
handle: '.handle' handle: '.handle',
start: function (event, ui) {
// Build a placeholder cell that spans all the cells in the row
var cellCount = 0;
$('td, th', ui.helper).each(function () {
// For each TD or TH try and get it's colspan attribute, and add that or 1 to the total
var colspan = 1;
var colspanAttr = $(this).attr('colspan');
if (colspanAttr > 1) {
colspan = colspanAttr;
}
cellCount += colspan;
});
// Add the placeholder UI - note that this is the item's content, so TD rather than TR
ui.placeholder.html('<td colspan="' + cellCount + '">&nbsp;</td>');
}
} }
); );
}); });
// Return a helper with preserved width of cells
var fixHelper = function(e, tr) {
var $originals = tr.children();
var $helper = tr.clone();
$helper.children().each(function (index) {
// Set helper cell sizes to match the original sizes
$(this).width($originals.eq(index).width());
});
return $helper;
}
function addMoney(e) { function addMoney(e) {
var pigID = parseInt($(e.target).data('id')); var pigID = parseInt($(e.target).data('id'));
$('#moneyManagementModal').empty().load('piggy-banks/add/' + pigID, function () { $('#moneyManagementModal').empty().load('piggy-banks/add/' + pigID, function () {
@@ -33,7 +62,7 @@ function removeMoney(e) {
function stopSorting() { function stopSorting() {
$('.loadSpin').addClass('fa fa-refresh fa-spin'); $('.loadSpin').addClass('fa fa-refresh fa-spin');
var order = []; var order = [];
$.each($('#sortable>div'), function(i,v) { $.each($('#sortable>tbody>tr'), function(i,v) {
var holder = $(v); var holder = $(v);
var id = holder.data('id'); var id = holder.data('id');
order.push(id); order.push(id);

View File

@@ -1,112 +0,0 @@
$(document).ready(function () {
$('.relateTransaction').click(relateTransactionDialog);
//$('.unrelate-checkbox').click(unrelateTransaction);
});
function unrelateTransaction(e) {
var target = $(e.target);
var id = target.data('id');
var parent = target.data('parent');
if(typeof id == "undefined" && typeof parent == "undefined") {
target = target.parent();
id = target.data('id');
parent = target.data('parent');
}
console.log('unlink ' + id + ' from ' + parent);
$.post('related/removeRelation/' + id + '/' + parent, {_token: token}).success(function (data) {
target.parent().parent().remove();
}).fail(function () {
alert('Could not!');
});
return false;
//$.post('related/removeRelation/' + id + '/' + relatedTo, {_token: token}).success(function (data) {
// target.parent().parent().remove();
//}).fail(function () {
// alert('Could not!');
//});
}
function relateTransactionDialog(e) {
var target = $(e.target);
var ID = target.data('id');
$('#relationModal').empty().load('related/related/' + ID, function () {
$('#relationModal').modal('show');
getAlreadyRelatedTransactions(e, ID);
$('#searchRelated').submit(function (e) {
searchRelatedTransactions(e, ID);
return false;
});
});
return false;
}
function searchRelatedTransactions(e, ID) {
var searchValue = $('#relatedSearchValue').val();
if (searchValue != '') {
$.post('related/search/' + ID, {searchValue: searchValue, _token: token}).success(function (data) {
// post the results to some div.
$('#relatedSearchResultsTitle').show();
$('#relatedSearchResults').empty().html(data);
// remove any clicks.
$('.relate').unbind('click').on('click', doRelateNewTransaction);
}).fail(function () {
alert('Could not search. Sorry.');
});
}
return false;
}
function doRelateNewTransaction(e) {
// remove the row from the table:
var target = $(e.target);
var id = target.data('id');
var parent = target.data('parent');
if (typeof id == "undefined" && typeof parent == "undefined") {
target = target.parent();
console.log(target);
id = target.data('id');
parent = target.data('parent');
}
console.log('Relate ' + id + ' to ' + parent);
$.post('related/relate/' + parent + '/' + id, {_token: token}).success(function (data) {
// success! remove entry:
target.parent().parent().remove();
// get related stuff (again).
getAlreadyRelatedTransactions(null, parent);
}).fail(function () {
// could not relate.
alert('Could not relate this transaction to the intended target.');
});
return false;
}
function getAlreadyRelatedTransactions(e, ID) {
//#alreadyRelated
$.get('related/alreadyRelated/' + ID).success(function (data) {
$('#alreadyRelated').empty().html(data);
// some event triggers.
$('.unrelate').unbind('click').on('click', unrelateTransaction);
}).fail(function () {
alert('Cannot get related stuff.');
});
}

View File

@@ -29,8 +29,8 @@ $(function() {
var url = window.location; var url = window.location;
var element = $('ul.nav a').filter(function() { var element = $('ul.nav a').filter(function() {
return this.href == url || url.href.indexOf(this.href) == 0; return this.href == url || url.href.indexOf(this.href) == 0;
}).addClass('active').parent().parent().addClass('in').parent(); }).parent().parent().addClass('in').parent();/*addClass('active')*/
if (element.is('li')) { if (element.is('li')) {
element.addClass('active'); //element.addClass('active');
} }
}); });

115
public/js/tags.js Normal file
View File

@@ -0,0 +1,115 @@
$(function () {
/*
Hide and show the tag index help.
*/
$('#tagHelp').on('show.bs.collapse', function () {
// set hideTagHelp = false
$.post('/tags/hideTagHelp/false', {_token: token});
$('#tagHelpButton').text('Hide help');
}).on('hide.bs.collapse', function () {
// set hideTagHelp = true
$.post('/tags/hideTagHelp/true', {_token: token});
$('#tagHelpButton').text('Show help');
});
$('#clearLocation').click(clearLocation);
});
/*
Some vars as prep for the map:
*/
var map;
var markers = [];
var setTag = false;
var mapOptions = {
zoom: zoomLevel,
center: new google.maps.LatLng(latitude, longitude),
disableDefaultUI: true
};
/*
Clear location and reset zoomLevel.
*/
function clearLocation() {
"use strict";
deleteMarkers();
$('input[name="latitude"]').val("");
$('input[name="longitude"]').val("");
$('input[name="zoomLevel"]').val("6");
setTag = false;
$('input[name="setTag"]').val('false');
return false;
}
function initialize() {
/*
Create new map:
*/
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
/*
Respond to click event.
*/
google.maps.event.addListener(map, 'rightclick', function (event) {
placeMarker(event);
});
/*
Respond to zoom event.
*/
google.maps.event.addListener(map, 'zoom_changed', function () {
saveZoomLevel(event);
});
/*
Maybe place marker?
*/
if(doPlaceMarker) {
var myLatlng = new google.maps.LatLng(latitude,longitude);
var fakeEvent = {};
fakeEvent.latLng = myLatlng;
placeMarker(fakeEvent);
}
}
/**
* save zoom level of map into hidden input.
*/
function saveZoomLevel() {
"use strict";
$('input[name="zoomLevel"]').val(map.getZoom());
}
/**
* Place marker on map.
* @param event
*/
function placeMarker(event) {
deleteMarkers();
var marker = new google.maps.Marker({position: event.latLng, map: map});
$('input[name="latitude"]').val(event.latLng.lat());
$('input[name="longitude"]').val(event.latLng.lng());
markers.push(marker);
setTag = true;
$('input[name="setTag"]').val('true');
}
/**
* Deletes all markers in the array by removing references to them.
*/
function deleteMarkers() {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers = [];
}
google.maps.event.addDomListener(window, 'load', initialize);

View File

@@ -8,6 +8,20 @@ $(document).ready(function () {
$('input[name="expense_account"]').typeahead({source: data}); $('input[name="expense_account"]').typeahead({source: data});
}); });
} }
if ($('input[name="tags"]').length > 0) {
$.getJSON('json/tags').success(function (data) {
var opt = {
typeahead: {
source: data
}
};
$('input[name="tags"]').tagsinput(
opt
);
});
}
if ($('input[name="revenue_account"]').length > 0) { if ($('input[name="revenue_account"]').length > 0) {
$.getJSON('json/revenue-accounts').success(function (data) { $.getJSON('json/revenue-accounts').success(function (data) {
$('input[name="revenue_account"]').typeahead({source: data}); $('input[name="revenue_account"]').typeahead({source: data});

View File

@@ -0,0 +1,61 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, what) }}
<form action="{{ route('accounts.store') }}" method="post" id="store" class="form-horizontal">
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<input type="hidden" name="what" value="{{ what }}" />
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa {{ subTitleIcon }}"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
{% if what == 'asset' %}
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-smile-o"></i> Optional fields
</div>
<div class="panel-body">
{{ ExpandedForm.balance('openingBalance') }}
{{ ExpandedForm.date('openingBalanceDate', phpdate('Y-m-d')) }}
{{ ExpandedForm.select('accountRole', Config.get('firefly.accountRoles'),null,{'helpText' : 'Any extra options resulting from your choice can be set later.'}) }}
{{ ExpandedForm.balance('virtualBalance') }}
</div>
</div>
{% endif %}
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('create','account') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new {{ what }} account
</button>
</p>
</div>
</div>
</form>
{% endblock %}

Some files were not shown because too many files have changed in this diff Show More