mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-20 02:01:19 +00:00
Compare commits
199 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3011b5074d | ||
|
|
83190572c7 | ||
|
|
9cf9e5f865 | ||
|
|
5bdef7f1c7 | ||
|
|
ba285a2d2d | ||
|
|
0dff371e62 | ||
|
|
ce4a2a5851 | ||
|
|
2c978dc89a | ||
|
|
4b8b819109 | ||
|
|
c230b3a806 | ||
|
|
df08b9c5c6 | ||
|
|
eca65376a3 | ||
|
|
88e3705636 | ||
|
|
5476509ef5 | ||
|
|
0bd6636453 | ||
|
|
105894e00d | ||
|
|
230a319510 | ||
|
|
ae16a2b14f | ||
|
|
da0c0742bf | ||
|
|
61d60a9048 | ||
|
|
3e28e9a016 | ||
|
|
423f9fefa9 | ||
|
|
5707dc7579 | ||
|
|
3be1cdb249 | ||
|
|
426d3d948c | ||
|
|
9a3aed8038 | ||
|
|
fb58bf1bf5 | ||
|
|
a6dbd912c6 | ||
|
|
65ce277a20 | ||
|
|
0b2d423c87 | ||
|
|
da056092fb | ||
|
|
45aa85d690 | ||
|
|
5c35fee0c2 | ||
|
|
24bdc319dd | ||
|
|
f1dcc41e42 | ||
|
|
550f301ba2 | ||
|
|
d9bf4d1c0d | ||
|
|
c3c1a6eb22 | ||
|
|
2c4454418e | ||
|
|
e44de572f5 | ||
|
|
f27919f91b | ||
|
|
ba9968bde0 | ||
|
|
05ea8216ff | ||
|
|
fa1695672a | ||
|
|
ac6f98fc47 | ||
|
|
1a1f89f555 | ||
|
|
6c3262e176 | ||
|
|
b4bdb48f1e | ||
|
|
823afe877b | ||
|
|
cb8e082414 | ||
|
|
98c1fcc68f | ||
|
|
8c439a2852 | ||
|
|
50c6109be7 | ||
|
|
6e362663b5 | ||
|
|
74c9feb53f | ||
|
|
402e8588cf | ||
|
|
778a42bcc0 | ||
|
|
584f7ced84 | ||
|
|
8e892e7ea5 | ||
|
|
3386c8b455 | ||
|
|
6fa73ee28d | ||
|
|
8ec8042045 | ||
|
|
cddc123539 | ||
|
|
4c2938c5cd | ||
|
|
6d03ddadcc | ||
|
|
64311da4b4 | ||
|
|
0cbb50ae9d | ||
|
|
7e96054dc2 | ||
|
|
578298580e | ||
|
|
ee5afaa6bc | ||
|
|
15b023d116 | ||
|
|
1ef96c0b4d | ||
|
|
8c3ae40de1 | ||
|
|
94fcfacec4 | ||
|
|
ba7c01c6bc | ||
|
|
9f92e1b7bd | ||
|
|
1f0e692ee2 | ||
|
|
0acd75a24f | ||
|
|
eedf27f8a5 | ||
|
|
b451e207e2 | ||
|
|
c0c37eec7b | ||
|
|
89363ecfa3 | ||
|
|
593e799ca1 | ||
|
|
8fc055cad9 | ||
|
|
75f86462e2 | ||
|
|
40892ccfa7 | ||
|
|
87fbf9c1a5 | ||
|
|
4944b233b6 | ||
|
|
9f23462c42 | ||
|
|
84a24f0333 | ||
|
|
7a885bfc3c | ||
|
|
3ba0cf1454 | ||
|
|
2d67a3159d | ||
|
|
290f25f1a0 | ||
|
|
1659904f81 | ||
|
|
230bd6e40a | ||
|
|
ce27e97b92 | ||
|
|
18c1223c7b | ||
|
|
8ef659f5de | ||
|
|
037452e525 | ||
|
|
e3482011d5 | ||
|
|
62748fa255 | ||
|
|
7a9df05f6b | ||
|
|
335279e728 | ||
|
|
0332104738 | ||
|
|
9f04854902 | ||
|
|
73008a35fe | ||
|
|
eae96cd2af | ||
|
|
cb670bb27d | ||
|
|
fe1fb23e5b | ||
|
|
c2dd61e96b | ||
|
|
80f5e61b6b | ||
|
|
dbcae16b75 | ||
|
|
886dcae822 | ||
|
|
ed495ec600 | ||
|
|
ddb60ccdc5 | ||
|
|
335e2083af | ||
|
|
7b1d9d4962 | ||
|
|
da6ff9f90a | ||
|
|
48f26c7bf1 | ||
|
|
3ce317b170 | ||
|
|
b741565f57 | ||
|
|
d8fea44968 | ||
|
|
778300b67e | ||
|
|
cb2b44fef3 | ||
|
|
cdb5875d6b | ||
|
|
01c5e15bcd | ||
|
|
f0babb4be7 | ||
|
|
10b00da874 | ||
|
|
e9f391b2eb | ||
|
|
50be39b054 | ||
|
|
a94e0bb3da | ||
|
|
3f65d5d760 | ||
|
|
48cb528ae4 | ||
|
|
e62e0345df | ||
|
|
441f011fba | ||
|
|
af1349160a | ||
|
|
2072607889 | ||
|
|
073fd5aa0d | ||
|
|
7b4703e4ff | ||
|
|
1484621300 | ||
|
|
40709c8367 | ||
|
|
b6ab5770a2 | ||
|
|
83b7cb4ff9 | ||
|
|
256dba66b2 | ||
|
|
6ac12f8ffa | ||
|
|
82e438d29b | ||
|
|
e86547645c | ||
|
|
8b901084fe | ||
|
|
1a0cbbdb31 | ||
|
|
30ac62ffb7 | ||
|
|
8ab294e90b | ||
|
|
f5edb15f43 | ||
|
|
eed6107ce7 | ||
|
|
d49dc599a2 | ||
|
|
3c5179f145 | ||
|
|
067d17c09c | ||
|
|
4c88c9af86 | ||
|
|
1c84afe186 | ||
|
|
9d4c4be468 | ||
|
|
de7db8db78 | ||
|
|
407ba4dd6d | ||
|
|
5135be3000 | ||
|
|
b8ab7d1a14 | ||
|
|
6211fd8496 | ||
|
|
a4f273b48b | ||
|
|
68d820a97c | ||
|
|
ebadfd6358 | ||
|
|
cf93a88adc | ||
|
|
bd2c4252bb | ||
|
|
84e7af04b9 | ||
|
|
37c63bc6b5 | ||
|
|
e7d3716549 | ||
|
|
73bc5372c0 | ||
|
|
b999a8f0fb | ||
|
|
16678aa5e1 | ||
|
|
f9ab49911d | ||
|
|
3fabe2e9fb | ||
|
|
9a8a3e94d6 | ||
|
|
32ef2ef801 | ||
|
|
76cd3d35e2 | ||
|
|
900dea2c66 | ||
|
|
8e6ca0dd05 | ||
|
|
4b4ad7f1a8 | ||
|
|
21a0a5d573 | ||
|
|
3cfa3f3b27 | ||
|
|
c77b43458e | ||
|
|
9ab0a83f7c | ||
|
|
d3cda8811d | ||
|
|
55740c0d97 | ||
|
|
c0a524c8a3 | ||
|
|
e51c2d10f0 | ||
|
|
7af55b7268 | ||
|
|
7350b1da1b | ||
|
|
136adbe723 | ||
|
|
cb2863eaf3 | ||
|
|
d054f9b92f | ||
|
|
9c83c18137 | ||
|
|
999a7481e4 |
@@ -1,2 +1,3 @@
|
|||||||
src_dir: .
|
src_dir: .
|
||||||
coverage_clover: tests/_output/coverage.xml
|
coverage_clover: tests/_output/coverage.xml
|
||||||
|
json_path: tests/_output/coveralls-upload.json
|
||||||
|
|||||||
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,10 +1,8 @@
|
|||||||
/bootstrap/compiled.php
|
/bootstrap/compiled.php
|
||||||
/vendor
|
/vendor
|
||||||
composer.phar
|
composer.phar
|
||||||
composer.lock
|
|
||||||
.env.*.php
|
.env.*.php
|
||||||
.env.php
|
.env.php
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
.idea/
|
.idea/
|
||||||
tests/_output/*
|
tests/_output/*
|
||||||
@@ -14,8 +12,16 @@ index.html*
|
|||||||
app/storage/firefly-export*
|
app/storage/firefly-export*
|
||||||
.vagrant
|
.vagrant
|
||||||
firefly-iii-import-*.json
|
firefly-iii-import-*.json
|
||||||
|
|
||||||
tests/_output/*
|
tests/_output/*
|
||||||
testing.sqlite
|
testing.sqlite
|
||||||
c3.php
|
|
||||||
_ide_helper_models.php
|
_ide_helper_models.php
|
||||||
|
clean.sqlite
|
||||||
|
tests/acceptance/AcceptanceTester.php
|
||||||
|
tests/functional/FunctionalTester.php
|
||||||
|
tests/unit/UnitTester.php
|
||||||
|
pi.php
|
||||||
|
tests/_data/db.sqlite
|
||||||
|
tests/_data/dump.sql
|
||||||
|
db.sqlite_snapshot
|
||||||
|
c3.php
|
||||||
|
db.sqlite-journal
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ language: php
|
|||||||
php:
|
php:
|
||||||
- 5.5
|
- 5.5
|
||||||
- 5.6
|
- 5.6
|
||||||
- hhvm
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- composer install
|
- composer install
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- php vendor/bin/codecept run
|
- ./tests/_data/db.sh
|
||||||
|
- php vendor/bin/codecept build
|
||||||
|
- php vendor/bin/codecept run --coverage --coverage-xml
|
||||||
|
|
||||||
after_script:
|
after_script:
|
||||||
- php vendor/bin/coveralls
|
- php vendor/bin/coveralls
|
||||||
|
|||||||
27
README.md
27
README.md
@@ -1,8 +1,10 @@
|
|||||||
Firefly III
|
Firefly III
|
||||||
===========
|
===========
|
||||||
|
|
||||||
[](https://travis-ci.org/JC5/firefly-iii)
|
[](https://travis-ci.org/JC5/firefly-iii)
|
||||||

|
[](http://stillmaintained.com/JC5/firefly-iii)
|
||||||
|
[](https://coveralls.io/r/JC5/firefly-iii?branch=master)
|
||||||
|
[](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102)
|
||||||
|
|
||||||
[](https://packagist.org/packages/grumpydictator/firefly-iii)
|
[](https://packagist.org/packages/grumpydictator/firefly-iii)
|
||||||
[](https://packagist.org/packages/grumpydictator/firefly-iii)
|
[](https://packagist.org/packages/grumpydictator/firefly-iii)
|
||||||
@@ -17,13 +19,15 @@ laptop and [Firefly II](https://github.com/JC5/Firefly) is live.
|
|||||||
|
|
||||||
## Current features
|
## Current features
|
||||||
|
|
||||||
- [A double-entry bookkeeping system](http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system).
|
- [A double-entry bookkeeping system](http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system);
|
||||||
- You can store, edit and remove withdrawals, deposits and transfers. This allows you full financial management;
|
- You can store, edit and remove withdrawals, deposits and transfers. This allows you full financial management;
|
||||||
- It's possible to create, change and manage money using _budgets_;
|
- It's possible to create, change and manage money using _budgets_;
|
||||||
- Organize transactions using categories;
|
- Organize transactions using categories;
|
||||||
- Save towards a goal using piggy banks;
|
- Save towards a goal using piggy banks;
|
||||||
- Predict and anticipate large expenses using "repeated expenses" (ie. yearly taxes);
|
- Predict and anticipate large expenses using "repeated expenses" (ie. yearly taxes);
|
||||||
- Predict and anticipate bills using "recurring transactions" (rent for example).
|
- Predict and anticipate bills using "recurring transactions" (rent for example);
|
||||||
|
- View basic income / expense reports.
|
||||||
|
- Lots of help text in case you don't get it;
|
||||||
|
|
||||||
Everything is organised:
|
Everything is organised:
|
||||||
|
|
||||||
@@ -31,21 +35,20 @@ Everything is organised:
|
|||||||
- Easy navigation through your records;
|
- Easy navigation through your records;
|
||||||
- Browse back and forth to see previous months or even years;
|
- Browse back and forth to see previous months or even years;
|
||||||
- Lots of charts because we all love them.
|
- Lots of charts because we all love them.
|
||||||
|
- Financial reporting showing you how well you are doing;
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
Firefly III will feature, but does not feature yet:
|
Firefly III will feature, but does not feature yet:
|
||||||
|
|
||||||
- Financial reporting showing you how well you are doing;
|
|
||||||
- Lots of help text in case you don't get it;
|
|
||||||
- More control over other resources outside of personal finance
|
- More control over other resources outside of personal finance
|
||||||
- Accounts shared with a partner (household accounts)
|
- Accounts shared with a partner (household accounts)
|
||||||
- Debts
|
- Debts
|
||||||
- Credit cards
|
- Credit cards
|
||||||
- More test-coverage (aka: actual test coverage);
|
- More test-coverage;
|
||||||
- Firefly will be able to split transactions; a single purchase can be split in multiple entries, for more fine-grained control.
|
- Firefly will be able to split transactions; a single purchase can be split in multiple entries, for more fine-grained control.
|
||||||
- Firefly will be able to join transactions.
|
- Firefly will be able to join transactions.
|
||||||
- Transfers and transactions are combined into one internal datatype which is more consistent with what you're actually doing: moving money from A to B. The fact that A or B or both are yours should not matter.
|
|
||||||
- Any other features I might not have thought of.
|
- Any other features I might not have thought of.
|
||||||
|
|
||||||
Some stuff has been removed:
|
Some stuff has been removed:
|
||||||
@@ -64,13 +67,9 @@ Some stuff has been removed:
|
|||||||

|

|
||||||
|
|
||||||
## Current state
|
## Current state
|
||||||
I have the basics up and running. Test coverage is currently non-existent.
|
I have the basics up and running. Test coverage is currently coming, slowly.
|
||||||
|
|
||||||
Although I have not checked extensively, some forms and views have CSRF vulnerabilities. This is because not all
|
Although I have not checked extensively, some forms and views have CSRF vulnerabilities. This is because not all
|
||||||
views escape all characters by default. Will be fixed.
|
views escape all characters by default. Will be fixed.
|
||||||
|
|
||||||
The current layout / look & feel is a pretty basic Bootstrap3 template. I am currently working on a more consistent,
|
Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!
|
||||||
expanded layout which will feature shiny AJAX things and data tables and all the Web 3.0 goodies you've come to expect
|
|
||||||
from social media sites.
|
|
||||||
|
|
||||||
Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!
|
|
||||||
|
|||||||
606
_sql/firefly-iii-reference-3.2.2.sql
Normal file
606
_sql/firefly-iii-reference-3.2.2.sql
Normal file
@@ -0,0 +1,606 @@
|
|||||||
|
# ************************************************************
|
||||||
|
# Sequel Pro SQL dump
|
||||||
|
# Version 4096
|
||||||
|
#
|
||||||
|
# http://www.sequelpro.com/
|
||||||
|
# http://code.google.com/p/sequel-pro/
|
||||||
|
#
|
||||||
|
# Host: 127.0.0.1 (MySQL 5.6.19-0ubuntu0.14.04.1)
|
||||||
|
# Database: homestead
|
||||||
|
# Generation Time: 2015-01-02 19:01:30 +0000
|
||||||
|
# ************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||||
|
/*!40101 SET NAMES utf8 */;
|
||||||
|
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||||
|
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||||
|
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table account_meta
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `account_meta`;
|
||||||
|
|
||||||
|
CREATE TABLE `account_meta` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`account_id` int(10) unsigned NOT NULL,
|
||||||
|
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`data` text COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `account_meta_account_id_name_unique` (`account_id`,`name`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table account_types
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `account_types`;
|
||||||
|
|
||||||
|
CREATE TABLE `account_types` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`type` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`editable` tinyint(1) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `account_types_type_unique` (`type`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
LOCK TABLES `account_types` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `account_types` DISABLE KEYS */;
|
||||||
|
|
||||||
|
INSERT INTO `account_types` (`id`, `created_at`, `updated_at`, `type`, `editable`)
|
||||||
|
VALUES
|
||||||
|
(1,'2015-01-02 19:00:13','2015-01-02 19:00:13','Default account',1),
|
||||||
|
(2,'2015-01-02 19:00:13','2015-01-02 19:00:13','Cash account',0),
|
||||||
|
(3,'2015-01-02 19:00:13','2015-01-02 19:00:13','Asset account',1),
|
||||||
|
(4,'2015-01-02 19:00:13','2015-01-02 19:00:13','Expense account',1),
|
||||||
|
(5,'2015-01-02 19:00:13','2015-01-02 19:00:13','Revenue account',1),
|
||||||
|
(6,'2015-01-02 19:00:13','2015-01-02 19:00:13','Initial balance account',0),
|
||||||
|
(7,'2015-01-02 19:00:13','2015-01-02 19:00:13','Beneficiary account',1),
|
||||||
|
(8,'2015-01-02 19:00:13','2015-01-02 19:00:13','Import account',0);
|
||||||
|
|
||||||
|
/*!40000 ALTER TABLE `account_types` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table accounts
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `accounts`;
|
||||||
|
|
||||||
|
CREATE TABLE `accounts` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
`account_type_id` int(10) unsigned NOT NULL,
|
||||||
|
`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`active` tinyint(1) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `accounts_user_id_account_type_id_name_unique` (`user_id`,`account_type_id`,`name`),
|
||||||
|
KEY `accounts_account_type_id_foreign` (`account_type_id`),
|
||||||
|
CONSTRAINT `accounts_account_type_id_foreign` FOREIGN KEY (`account_type_id`) REFERENCES `account_types` (`id`) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT `accounts_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table bills
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `bills`;
|
||||||
|
|
||||||
|
CREATE TABLE `bills` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`match` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`amount_min` decimal(10,2) NOT NULL,
|
||||||
|
`amount_max` decimal(10,2) NOT NULL,
|
||||||
|
`date` date NOT NULL,
|
||||||
|
`active` tinyint(1) NOT NULL,
|
||||||
|
`automatch` tinyint(1) NOT NULL,
|
||||||
|
`repeat_freq` enum('daily','weekly','monthly','quarterly','half-year','yearly') COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`skip` smallint(5) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `uid_name_unique` (`user_id`,`name`),
|
||||||
|
CONSTRAINT `bills_uid_for` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table budget_limits
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `budget_limits`;
|
||||||
|
|
||||||
|
CREATE TABLE `budget_limits` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`budget_id` int(10) unsigned DEFAULT NULL,
|
||||||
|
`startdate` date NOT NULL,
|
||||||
|
`amount` decimal(10,2) NOT NULL,
|
||||||
|
`repeats` tinyint(1) NOT NULL,
|
||||||
|
`repeat_freq` enum('daily','weekly','monthly','quarterly','half-year','yearly') COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `unique_ci_combi` (`startdate`,`repeat_freq`),
|
||||||
|
UNIQUE KEY `unique_bl_combi` (`budget_id`,`startdate`,`repeat_freq`),
|
||||||
|
CONSTRAINT `bid_foreign` FOREIGN KEY (`budget_id`) REFERENCES `budgets` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table budget_transaction_journal
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `budget_transaction_journal`;
|
||||||
|
|
||||||
|
CREATE TABLE `budget_transaction_journal` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`budget_id` int(10) unsigned NOT NULL,
|
||||||
|
`transaction_journal_id` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `budid_tjid_unique` (`budget_id`,`transaction_journal_id`),
|
||||||
|
KEY `budget_transaction_journal_transaction_journal_id_foreign` (`transaction_journal_id`),
|
||||||
|
CONSTRAINT `budget_transaction_journal_transaction_journal_id_foreign` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT `budget_transaction_journal_budget_id_foreign` FOREIGN KEY (`budget_id`) REFERENCES `budgets` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table budgets
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `budgets`;
|
||||||
|
|
||||||
|
CREATE TABLE `budgets` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `budgets_user_id_name_unique` (`user_id`,`name`),
|
||||||
|
CONSTRAINT `budgets_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table categories
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `categories`;
|
||||||
|
|
||||||
|
CREATE TABLE `categories` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `categories_user_id_name_unique` (`user_id`,`name`),
|
||||||
|
CONSTRAINT `categories_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table category_transaction_journal
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `category_transaction_journal`;
|
||||||
|
|
||||||
|
CREATE TABLE `category_transaction_journal` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`category_id` int(10) unsigned NOT NULL,
|
||||||
|
`transaction_journal_id` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `catid_tjid_unique` (`category_id`,`transaction_journal_id`),
|
||||||
|
KEY `category_transaction_journal_transaction_journal_id_foreign` (`transaction_journal_id`),
|
||||||
|
CONSTRAINT `category_transaction_journal_transaction_journal_id_foreign` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT `category_transaction_journal_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table components
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `components`;
|
||||||
|
|
||||||
|
CREATE TABLE `components` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
`class` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `components_user_id_class_name_unique` (`user_id`,`class`,`name`),
|
||||||
|
CONSTRAINT `components_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table limit_repetitions
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `limit_repetitions`;
|
||||||
|
|
||||||
|
CREATE TABLE `limit_repetitions` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`budget_limit_id` int(10) unsigned NOT NULL,
|
||||||
|
`startdate` date NOT NULL,
|
||||||
|
`enddate` date NOT NULL,
|
||||||
|
`amount` decimal(10,2) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `limit_repetitions_limit_id_startdate_enddate_unique` (`budget_limit_id`,`startdate`,`enddate`),
|
||||||
|
CONSTRAINT `limit_repetitions_limit_id_foreign` FOREIGN KEY (`budget_limit_id`) REFERENCES `budget_limits` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table migrations
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `migrations`;
|
||||||
|
|
||||||
|
CREATE TABLE `migrations` (
|
||||||
|
`migration` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`batch` int(11) NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
LOCK TABLES `migrations` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `migrations` DISABLE KEYS */;
|
||||||
|
|
||||||
|
INSERT INTO `migrations` (`migration`, `batch`)
|
||||||
|
VALUES
|
||||||
|
('2014_06_27_163032_create_users_table',1),
|
||||||
|
('2014_06_27_163145_create_account_types_table',1),
|
||||||
|
('2014_06_27_163259_create_accounts_table',1),
|
||||||
|
('2014_06_27_163817_create_components_table',1),
|
||||||
|
('2014_06_27_163818_create_piggybanks_table',1),
|
||||||
|
('2014_06_27_164042_create_transaction_currencies_table',1),
|
||||||
|
('2014_06_27_164512_create_transaction_types_table',1),
|
||||||
|
('2014_06_27_164619_create_recurring_transactions_table',1),
|
||||||
|
('2014_06_27_164620_create_transaction_journals_table',1),
|
||||||
|
('2014_06_27_164836_create_transactions_table',1),
|
||||||
|
('2014_06_27_165344_create_component_transaction_table',1),
|
||||||
|
('2014_07_05_171326_create_component_transaction_journal_table',1),
|
||||||
|
('2014_07_06_123842_create_preferences_table',1),
|
||||||
|
('2014_07_09_204843_create_session_table',1),
|
||||||
|
('2014_07_17_183717_create_limits_table',1),
|
||||||
|
('2014_07_19_055011_create_limit_repeat_table',1),
|
||||||
|
('2014_08_06_044416_create_component_recurring_transaction_table',1),
|
||||||
|
('2014_08_12_173919_create_piggybank_repetitions_table',1),
|
||||||
|
('2014_08_18_100330_create_piggybank_events_table',1),
|
||||||
|
('2014_08_23_113221_create_reminders_table',1),
|
||||||
|
('2014_11_10_172053_create_account_meta_table',1),
|
||||||
|
('2014_11_29_135749_create_transaction_groups_table',1),
|
||||||
|
('2014_11_29_140217_create_transaction_group_transaction_journal_table',1),
|
||||||
|
('2014_12_13_190730_changes_for_v321',1),
|
||||||
|
('2014_12_24_191544_changes_for_v322',1);
|
||||||
|
|
||||||
|
/*!40000 ALTER TABLE `migrations` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table piggy_bank_events
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `piggy_bank_events`;
|
||||||
|
|
||||||
|
CREATE TABLE `piggy_bank_events` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`piggy_bank_id` int(10) unsigned NOT NULL,
|
||||||
|
`transaction_journal_id` int(10) unsigned DEFAULT NULL,
|
||||||
|
`date` date NOT NULL,
|
||||||
|
`amount` decimal(10,2) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `piggybank_events_piggybank_id_foreign` (`piggy_bank_id`),
|
||||||
|
KEY `piggybank_events_transaction_journal_id_foreign` (`transaction_journal_id`),
|
||||||
|
CONSTRAINT `piggybank_events_transaction_journal_id_foreign` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE SET NULL,
|
||||||
|
CONSTRAINT `piggybank_events_piggybank_id_foreign` FOREIGN KEY (`piggy_bank_id`) REFERENCES `piggy_banks` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table piggy_bank_repetitions
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `piggy_bank_repetitions`;
|
||||||
|
|
||||||
|
CREATE TABLE `piggy_bank_repetitions` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`piggy_bank_id` int(10) unsigned NOT NULL,
|
||||||
|
`startdate` date DEFAULT NULL,
|
||||||
|
`targetdate` date DEFAULT NULL,
|
||||||
|
`currentamount` decimal(10,2) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `piggybank_repetitions_piggybank_id_startdate_targetdate_unique` (`piggy_bank_id`,`startdate`,`targetdate`),
|
||||||
|
CONSTRAINT `piggybank_repetitions_piggybank_id_foreign` FOREIGN KEY (`piggy_bank_id`) REFERENCES `piggy_banks` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table piggy_banks
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `piggy_banks`;
|
||||||
|
|
||||||
|
CREATE TABLE `piggy_banks` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`account_id` int(10) unsigned NOT NULL,
|
||||||
|
`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`targetamount` decimal(10,2) NOT NULL,
|
||||||
|
`startdate` date DEFAULT NULL,
|
||||||
|
`targetdate` date DEFAULT NULL,
|
||||||
|
`repeats` tinyint(1) NOT NULL,
|
||||||
|
`rep_length` enum('day','week','quarter','month','year') COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
`rep_every` smallint(5) unsigned NOT NULL,
|
||||||
|
`rep_times` smallint(5) unsigned DEFAULT NULL,
|
||||||
|
`reminder` enum('day','week','quarter','month','year') COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
`reminder_skip` smallint(5) unsigned NOT NULL,
|
||||||
|
`remind_me` tinyint(1) NOT NULL,
|
||||||
|
`order` int(10) unsigned NOT NULL,
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `piggybanks_account_id_name_unique` (`account_id`,`name`),
|
||||||
|
CONSTRAINT `piggybanks_account_id_foreign` FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table preferences
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `preferences`;
|
||||||
|
|
||||||
|
CREATE TABLE `preferences` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`data` text COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `preferences_user_id_name_unique` (`user_id`,`name`),
|
||||||
|
CONSTRAINT `preferences_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table reminders
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `reminders`;
|
||||||
|
|
||||||
|
CREATE TABLE `reminders` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
`startdate` date NOT NULL,
|
||||||
|
`enddate` date DEFAULT NULL,
|
||||||
|
`active` tinyint(1) NOT NULL,
|
||||||
|
`notnow` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`remindersable_id` int(10) unsigned DEFAULT NULL,
|
||||||
|
`remindersable_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `reminders_user_id_foreign` (`user_id`),
|
||||||
|
CONSTRAINT `reminders_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table sessions
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `sessions`;
|
||||||
|
|
||||||
|
CREATE TABLE `sessions` (
|
||||||
|
`id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`payload` text COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`last_activity` int(11) NOT NULL,
|
||||||
|
UNIQUE KEY `sessions_id_unique` (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table transaction_currencies
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `transaction_currencies`;
|
||||||
|
|
||||||
|
CREATE TABLE `transaction_currencies` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`code` varchar(3) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`name` varchar(48) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
`symbol` varchar(8) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `transaction_currencies_code_unique` (`code`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
LOCK TABLES `transaction_currencies` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `transaction_currencies` DISABLE KEYS */;
|
||||||
|
|
||||||
|
INSERT INTO `transaction_currencies` (`id`, `created_at`, `updated_at`, `deleted_at`, `code`, `name`, `symbol`)
|
||||||
|
VALUES
|
||||||
|
(1,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'EUR','Euro','€'),
|
||||||
|
(2,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'USD','US Dollar','$'),
|
||||||
|
(3,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'HUF','Hungarian forint','Ft');
|
||||||
|
|
||||||
|
/*!40000 ALTER TABLE `transaction_currencies` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table transaction_group_transaction_journal
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `transaction_group_transaction_journal`;
|
||||||
|
|
||||||
|
CREATE TABLE `transaction_group_transaction_journal` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`transaction_group_id` int(10) unsigned NOT NULL,
|
||||||
|
`transaction_journal_id` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `tt_joined` (`transaction_group_id`,`transaction_journal_id`),
|
||||||
|
KEY `tr_trj_id` (`transaction_journal_id`),
|
||||||
|
CONSTRAINT `tr_trj_id` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT `tr_grp_id` FOREIGN KEY (`transaction_group_id`) REFERENCES `transaction_groups` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table transaction_groups
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `transaction_groups`;
|
||||||
|
|
||||||
|
CREATE TABLE `transaction_groups` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
`relation` enum('balance') COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `transaction_groups_user_id_foreign` (`user_id`),
|
||||||
|
CONSTRAINT `transaction_groups_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table transaction_journals
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `transaction_journals`;
|
||||||
|
|
||||||
|
CREATE TABLE `transaction_journals` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`user_id` int(10) unsigned NOT NULL,
|
||||||
|
`transaction_type_id` int(10) unsigned NOT NULL,
|
||||||
|
`bill_id` int(10) unsigned DEFAULT NULL,
|
||||||
|
`transaction_currency_id` int(10) unsigned NOT NULL,
|
||||||
|
`description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
`completed` tinyint(1) NOT NULL,
|
||||||
|
`date` date NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `transaction_journals_user_id_foreign` (`user_id`),
|
||||||
|
KEY `transaction_journals_transaction_type_id_foreign` (`transaction_type_id`),
|
||||||
|
KEY `transaction_journals_transaction_currency_id_foreign` (`transaction_currency_id`),
|
||||||
|
KEY `bill_id_foreign` (`bill_id`),
|
||||||
|
CONSTRAINT `bill_id_foreign` FOREIGN KEY (`bill_id`) REFERENCES `bills` (`id`) ON DELETE SET NULL,
|
||||||
|
CONSTRAINT `transaction_journals_transaction_currency_id_foreign` FOREIGN KEY (`transaction_currency_id`) REFERENCES `transaction_currencies` (`id`) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT `transaction_journals_transaction_type_id_foreign` FOREIGN KEY (`transaction_type_id`) REFERENCES `transaction_types` (`id`) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT `transaction_journals_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table transaction_types
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `transaction_types`;
|
||||||
|
|
||||||
|
CREATE TABLE `transaction_types` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`type` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `transaction_types_type_unique` (`type`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
LOCK TABLES `transaction_types` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `transaction_types` DISABLE KEYS */;
|
||||||
|
|
||||||
|
INSERT INTO `transaction_types` (`id`, `created_at`, `updated_at`, `deleted_at`, `type`)
|
||||||
|
VALUES
|
||||||
|
(1,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'Withdrawal'),
|
||||||
|
(2,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'Deposit'),
|
||||||
|
(3,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'Transfer'),
|
||||||
|
(4,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'Opening balance');
|
||||||
|
|
||||||
|
/*!40000 ALTER TABLE `transaction_types` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table transactions
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `transactions`;
|
||||||
|
|
||||||
|
CREATE TABLE `transactions` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`deleted_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`account_id` int(10) unsigned NOT NULL,
|
||||||
|
`transaction_journal_id` int(10) unsigned NOT NULL,
|
||||||
|
`description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
`amount` decimal(10,2) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `transactions_account_id_foreign` (`account_id`),
|
||||||
|
KEY `transactions_transaction_journal_id_foreign` (`transaction_journal_id`),
|
||||||
|
CONSTRAINT `transactions_account_id_foreign` FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT `transactions_transaction_journal_id_foreign` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Dump of table users
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `users`;
|
||||||
|
|
||||||
|
CREATE TABLE `users` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
|
`email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
`reset` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
`remember_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `users_email_unique` (`email`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||||
|
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||||
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
@@ -17,347 +17,353 @@ Breadcrumbs::register(
|
|||||||
// accounts
|
// accounts
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'accounts.index', function (Generator $breadcrumbs, $what) {
|
'accounts.index', function (Generator $breadcrumbs, $what) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push(ucfirst($what) . ' accounts', route('accounts.index', $what));
|
$breadcrumbs->push(ucfirst(e($what)) . ' accounts', route('accounts.index', $what));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'accounts.show', function (Generator $breadcrumbs, \Account $account) {
|
'accounts.show', function (Generator $breadcrumbs, \Account $account) {
|
||||||
switch ($account->accountType->type) {
|
switch ($account->accountType->type) {
|
||||||
default:
|
default:
|
||||||
throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"');
|
throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"');
|
||||||
break;
|
break;
|
||||||
case 'Default account':
|
case 'Default account':
|
||||||
case 'Asset account':
|
case 'Asset account':
|
||||||
$what = 'asset';
|
$what = 'asset';
|
||||||
break;
|
break;
|
||||||
case 'Expense account':
|
case 'Cash account':
|
||||||
case 'Beneficiary account':
|
$what = 'cash';
|
||||||
$what = 'expense';
|
break;
|
||||||
break;
|
case 'Expense account':
|
||||||
case 'Revenue account':
|
case 'Beneficiary account':
|
||||||
$what = 'revenue';
|
$what = 'expense';
|
||||||
break;
|
break;
|
||||||
}
|
case 'Revenue account':
|
||||||
$breadcrumbs->parent('accounts.index', $what);
|
$what = 'revenue';
|
||||||
$breadcrumbs->push($account->name, route('accounts.show', $account->id));
|
break;
|
||||||
}
|
}
|
||||||
|
$breadcrumbs->parent('accounts.index', $what);
|
||||||
|
$breadcrumbs->push(e($account->name), route('accounts.show', $account->id));
|
||||||
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'accounts.delete', function (Generator $breadcrumbs, \Account $account) {
|
'accounts.delete', function (Generator $breadcrumbs, \Account $account) {
|
||||||
$breadcrumbs->parent('accounts.show', $account);
|
$breadcrumbs->parent('accounts.show', $account);
|
||||||
$breadcrumbs->push('Delete ' . $account->name, route('accounts.delete', $account->id));
|
$breadcrumbs->push('Delete ' . e($account->name), route('accounts.delete', $account->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'accounts.edit', function (Generator $breadcrumbs, \Account $account) {
|
'accounts.edit', function (Generator $breadcrumbs, \Account $account) {
|
||||||
$breadcrumbs->parent('accounts.show', $account);
|
$breadcrumbs->parent('accounts.show', $account);
|
||||||
$breadcrumbs->push('Edit ' . $account->name, route('accounts.edit', $account->id));
|
$breadcrumbs->push('Edit ' . e($account->name), route('accounts.edit', $account->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// budgets.
|
// budgets.
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'budgets.index', function (Generator $breadcrumbs) {
|
'budgets.index', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Budgets', route('budgets.index'));
|
$breadcrumbs->push('Budgets', route('budgets.index'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'budgets.create', function (Generator $breadcrumbs) {
|
'budgets.create', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('budgets.index');
|
$breadcrumbs->parent('budgets.index');
|
||||||
$breadcrumbs->push('Create new budget', route('budgets.create'));
|
$breadcrumbs->push('Create new budget', route('budgets.create'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'budgets.edit', function (Generator $breadcrumbs, Budget $budget) {
|
'budgets.edit', function (Generator $breadcrumbs, Budget $budget) {
|
||||||
$breadcrumbs->parent('budgets.show', $budget);
|
$breadcrumbs->parent('budgets.show', $budget);
|
||||||
$breadcrumbs->push('Edit ' . $budget->name, route('budgets.edit', $budget->id));
|
$breadcrumbs->push('Edit ' . e($budget->name), route('budgets.edit', $budget->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'budgets.delete', function (Generator $breadcrumbs, Budget $budget) {
|
'budgets.delete', function (Generator $breadcrumbs, Budget $budget) {
|
||||||
$breadcrumbs->parent('budgets.show', $budget);
|
$breadcrumbs->parent('budgets.show', $budget);
|
||||||
$breadcrumbs->push('Delete ' . $budget->name, route('budgets.delete', $budget->id));
|
$breadcrumbs->push('Delete ' . e($budget->name), route('budgets.delete', $budget->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
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');
|
||||||
$breadcrumbs->push($budget->name, route('budgets.show', $budget->id));
|
$breadcrumbs->push(e($budget->name), route('budgets.show', $budget->id));
|
||||||
if (!is_null($repetition)) {
|
if (!is_null($repetition)) {
|
||||||
$breadcrumbs->push(
|
$breadcrumbs->push(
|
||||||
DateKit::periodShow($repetition->startdate, $repetition->limit->repeat_freq), route('budgets.show', $budget->id, $repetition->id)
|
DateKit::periodShow($repetition->startdate, $repetition->budgetlimit->repeat_freq), route('budgets.show', $budget->id, $repetition->id)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// categories
|
// categories
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'categories.index', function (Generator $breadcrumbs) {
|
'categories.index', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Categories', route('categories.index'));
|
$breadcrumbs->push('Categories', route('categories.index'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'categories.create', function (Generator $breadcrumbs) {
|
'categories.create', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('categories.index');
|
$breadcrumbs->parent('categories.index');
|
||||||
$breadcrumbs->push('Create new category', route('categories.create'));
|
$breadcrumbs->push('Create new category', route('categories.create'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'categories.edit', function (Generator $breadcrumbs, Category $category) {
|
'categories.edit', function (Generator $breadcrumbs, Category $category) {
|
||||||
$breadcrumbs->parent('categories.show', $category);
|
$breadcrumbs->parent('categories.show', $category);
|
||||||
$breadcrumbs->push('Edit ' . $category->name, route('categories.edit', $category->id));
|
$breadcrumbs->push('Edit ' . e($category->name), route('categories.edit', $category->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'categories.delete', function (Generator $breadcrumbs, Category $category) {
|
'categories.delete', function (Generator $breadcrumbs, Category $category) {
|
||||||
$breadcrumbs->parent('categories.show', $category);
|
$breadcrumbs->parent('categories.show', $category);
|
||||||
$breadcrumbs->push('Delete ' . $category->name, route('categories.delete', $category->id));
|
$breadcrumbs->push('Delete ' . e($category->name), route('categories.delete', $category->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'categories.show', function (Generator $breadcrumbs, Category $category) {
|
'categories.show', function (Generator $breadcrumbs, Category $category) {
|
||||||
$breadcrumbs->parent('categories.index');
|
$breadcrumbs->parent('categories.index');
|
||||||
$breadcrumbs->push($category->name, route('categories.show', $category->id));
|
$breadcrumbs->push(e($category->name), route('categories.show', $category->id));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// piggy banks
|
// piggy banks
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'piggybanks.index', function (Generator $breadcrumbs) {
|
'piggyBanks.index', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Piggy banks', route('piggybanks.index'));
|
$breadcrumbs->push('Piggy banks', route('piggyBanks.index'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'piggybanks.create', function (Generator $breadcrumbs) {
|
'piggyBanks.create', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('piggybanks.index');
|
$breadcrumbs->parent('piggyBanks.index');
|
||||||
$breadcrumbs->push('Create new piggy bank', route('piggybanks.create'));
|
$breadcrumbs->push('Create new piggy bank', route('piggyBanks.create'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'piggybanks.edit', function (Generator $breadcrumbs, Piggybank $piggybank) {
|
'piggyBanks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||||
$breadcrumbs->parent('piggybanks.show', $piggybank);
|
$breadcrumbs->parent('piggyBanks.show', $piggyBank);
|
||||||
$breadcrumbs->push('Edit ' . $piggybank->name, route('piggybanks.edit', $piggybank->id));
|
$breadcrumbs->push('Edit ' . e($piggyBank->name), route('piggyBanks.edit', $piggyBank->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'piggybanks.delete', function (Generator $breadcrumbs, Piggybank $piggybank) {
|
'piggyBanks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||||
$breadcrumbs->parent('piggybanks.show', $piggybank);
|
$breadcrumbs->parent('piggyBanks.show', $piggyBank);
|
||||||
$breadcrumbs->push('Delete ' . $piggybank->name, route('piggybanks.delete', $piggybank->id));
|
$breadcrumbs->push('Delete ' . e($piggyBank->name), route('piggyBanks.delete', $piggyBank->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'piggybanks.show', function (Generator $breadcrumbs, Piggybank $piggybank) {
|
'piggyBanks.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||||
$breadcrumbs->parent('piggybanks.index');
|
$breadcrumbs->parent('piggyBanks.index');
|
||||||
$breadcrumbs->push($piggybank->name, route('piggybanks.show', $piggybank->id));
|
$breadcrumbs->push(e($piggyBank->name), route('piggyBanks.show', $piggyBank->id));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// preferences
|
// preferences
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'preferences', function (Generator $breadcrumbs) {
|
'preferences', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Preferences', route('preferences'));
|
$breadcrumbs->push('Preferences', route('preferences'));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// profile
|
// profile
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'profile', function (Generator $breadcrumbs) {
|
'profile', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Profile', route('profile'));
|
$breadcrumbs->push('Profile', route('profile'));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'change-password', function (Generator $breadcrumbs) {
|
'change-password', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('profile');
|
$breadcrumbs->parent('profile');
|
||||||
$breadcrumbs->push('Change your password', route('change-password'));
|
$breadcrumbs->push('Change your password', route('change-password'));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// recurring transactions
|
// bills
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'recurring.index', function (Generator $breadcrumbs) {
|
'bills.index', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Recurring transactions', route('recurring.index'));
|
$breadcrumbs->push('Bills', route('bills.index'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'recurring.create', function (Generator $breadcrumbs) {
|
'bills.create', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('recurring.index');
|
$breadcrumbs->parent('bills.index');
|
||||||
$breadcrumbs->push('Create new recurring transaction', route('recurring.create'));
|
$breadcrumbs->push('Create new bill', route('bills.create'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'recurring.edit', function (Generator $breadcrumbs, RecurringTransaction $recurring) {
|
'bills.edit', function (Generator $breadcrumbs, Bill $bill) {
|
||||||
$breadcrumbs->parent('recurring.show', $recurring);
|
$breadcrumbs->parent('bills.show', $bill);
|
||||||
$breadcrumbs->push('Edit ' . $recurring->name, route('recurring.edit', $recurring->id));
|
$breadcrumbs->push('Edit ' . e($bill->name), route('bills.edit', $bill->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'recurring.delete', function (Generator $breadcrumbs, RecurringTransaction $recurring) {
|
'bills.delete', function (Generator $breadcrumbs, Bill $bill) {
|
||||||
$breadcrumbs->parent('recurring.show', $recurring);
|
$breadcrumbs->parent('bills.show', $bill);
|
||||||
$breadcrumbs->push('Delete ' . $recurring->name, route('recurring.delete', $recurring->id));
|
$breadcrumbs->push('Delete ' . e($bill->name), route('bills.delete', $bill->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'recurring.show', function (Generator $breadcrumbs, RecurringTransaction $recurring) {
|
'bills.show', function (Generator $breadcrumbs, Bill $bill) {
|
||||||
$breadcrumbs->parent('recurring.index');
|
$breadcrumbs->parent('bills.index');
|
||||||
$breadcrumbs->push($recurring->name, route('recurring.show', $recurring->id));
|
$breadcrumbs->push(e($bill->name), route('bills.show', $bill->id));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// reminders
|
// reminders
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
|
'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id));
|
$breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// repeated expenses
|
// repeated expenses
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'repeated.index', function (Generator $breadcrumbs) {
|
'repeated.index', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Repeated expenses', route('repeated.index'));
|
$breadcrumbs->push('Repeated expenses', route('repeated.index'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'repeated.create', function (Generator $breadcrumbs) {
|
'repeated.create', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('repeated.index');
|
$breadcrumbs->parent('repeated.index');
|
||||||
$breadcrumbs->push('Create new repeated expense', route('repeated.create'));
|
$breadcrumbs->push('Create new repeated expense', route('repeated.create'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'repeated.edit', function (Generator $breadcrumbs, Piggybank $piggybank) {
|
'repeated.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||||
$breadcrumbs->parent('repeated.show', $piggybank);
|
$breadcrumbs->parent('repeated.show', $piggyBank);
|
||||||
$breadcrumbs->push('Edit ' . $piggybank->name, route('repeated.edit', $piggybank->id));
|
$breadcrumbs->push('Edit ' . e($piggyBank->name), route('repeated.edit', $piggyBank->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'repeated.delete', function (Generator $breadcrumbs, Piggybank $piggybank) {
|
'repeated.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||||
$breadcrumbs->parent('repeated.show', $piggybank);
|
$breadcrumbs->parent('repeated.show', $piggyBank);
|
||||||
$breadcrumbs->push('Delete ' . $piggybank->name, route('repeated.delete', $piggybank->id));
|
$breadcrumbs->push('Delete ' . e($piggyBank->name), route('repeated.delete', $piggyBank->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'repeated.show', function (Generator $breadcrumbs, Piggybank $piggybank) {
|
'repeated.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||||
$breadcrumbs->parent('repeated.index');
|
$breadcrumbs->parent('repeated.index');
|
||||||
$breadcrumbs->push($piggybank->name, route('repeated.show', $piggybank->id));
|
$breadcrumbs->push(e($piggyBank->name), route('repeated.show', $piggyBank->id));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// reports
|
// reports
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'reports.index', function (Generator $breadcrumbs) {
|
'reports.index', function (Generator $breadcrumbs) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Reports', route('reports.index'));
|
$breadcrumbs->push('Reports', route('reports.index'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
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->format('Y'), route('reports.year', $date->format('Y')));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'reports.budgets', function (Generator $breadcrumbs, Carbon $date) {
|
'reports.month', function (Generator $breadcrumbs, Carbon $date) {
|
||||||
$breadcrumbs->parent('reports.index');
|
$breadcrumbs->parent('reports.index');
|
||||||
$breadcrumbs->push('Budgets in ' . $date->format('F Y'), route('reports.budgets', $date->format('Y')));
|
$breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', $date));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'reports.unbalanced', function (Generator $breadcrumbs, Carbon $date) {
|
'reports.budget', function (Generator $breadcrumbs, Carbon $date) {
|
||||||
$breadcrumbs->parent('reports.index');
|
$breadcrumbs->parent('reports.index');
|
||||||
$breadcrumbs->push('Unbalanced transactions in ' . $date->format('F Y'), route('reports.unbalanced', $date->format('Y')));
|
$breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', $date));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// search
|
// search
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'search', function (Generator $breadcrumbs, $query) {
|
'search', function (Generator $breadcrumbs, $query) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
$breadcrumbs->push('Search for "' . e($query) . '"', route('search'));
|
$breadcrumbs->push('Search for "' . e($query) . '"', route('search'));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// transactions
|
// transactions
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'transactions.index', function (Generator $breadcrumbs, $what) {
|
'transactions.index', function (Generator $breadcrumbs, $what) {
|
||||||
$breadcrumbs->parent('home');
|
$breadcrumbs->parent('home');
|
||||||
|
|
||||||
switch ($what) {
|
switch ($what) {
|
||||||
case 'expenses':
|
case 'expenses':
|
||||||
case 'withdrawal':
|
case 'withdrawal':
|
||||||
$subTitle = 'Expenses';
|
$subTitle = 'Expenses';
|
||||||
break;
|
break;
|
||||||
case 'revenue':
|
case 'revenue':
|
||||||
case 'deposit':
|
case 'deposit':
|
||||||
$subTitle = 'Revenue, income and deposits';
|
$subTitle = 'Revenue, income and deposits';
|
||||||
break;
|
break;
|
||||||
case 'transfer':
|
case 'transfer':
|
||||||
case 'transfers':
|
case 'transfers':
|
||||||
$subTitle = 'Transfers';
|
$subTitle = 'Transfers';
|
||||||
break;
|
break;
|
||||||
case 'opening balance':
|
case 'opening balance':
|
||||||
$subTitle = 'Opening balances';
|
$subTitle = 'Opening balances';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new FireflyException('Cannot handle $what "'.e($what).'" in bread crumbs');
|
throw new FireflyException('Cannot handle $what "' . e($what) . '" in bread crumbs');
|
||||||
}
|
|
||||||
|
|
||||||
$breadcrumbs->push($subTitle, route('transactions.index', $what));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$breadcrumbs->push($subTitle, route('transactions.index', $what));
|
||||||
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'transactions.create', function (Generator $breadcrumbs, $what) {
|
'transactions.create', function (Generator $breadcrumbs, $what) {
|
||||||
$breadcrumbs->parent('transactions.index', $what);
|
$breadcrumbs->parent('transactions.index', $what);
|
||||||
$breadcrumbs->push('Create new ' . $what, route('transactions.create', $what));
|
$breadcrumbs->push('Create new ' .e($what), route('transactions.create', $what));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) {
|
'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) {
|
||||||
$breadcrumbs->parent('transactions.show', $journal);
|
$breadcrumbs->parent('transactions.show', $journal);
|
||||||
$breadcrumbs->push('Edit ' . $journal->description, route('transactions.edit', $journal ->id));
|
$breadcrumbs->push('Edit ' . e($journal->description), route('transactions.edit', $journal->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) {
|
'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) {
|
||||||
$breadcrumbs->parent('transactions.show', $journal);
|
$breadcrumbs->parent('transactions.show', $journal);
|
||||||
$breadcrumbs->push('Delete ' . $journal->description, route('transactions.delete', $journal->id));
|
$breadcrumbs->push('Delete ' . e($journal->description), route('transactions.delete', $journal->id));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) {
|
'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) {
|
||||||
|
|
||||||
$breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type));
|
$breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type));
|
||||||
$breadcrumbs->push($journal->description, route('transactions.show', $journal->id));
|
$breadcrumbs->push(e($journal->description), route('transactions.show', $journal->id));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Cleanup
|
||||||
|
*/
|
||||||
class Cleanup extends Command
|
class Cleanup extends Command
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -21,9 +22,7 @@ class Cleanup extends Command
|
|||||||
protected $name = 'firefly:cleanup';
|
protected $name = 'firefly:cleanup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new command instance.
|
|
||||||
*
|
*
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -42,7 +41,7 @@ class Cleanup extends Command
|
|||||||
$this->info('Cleared compiled...');
|
$this->info('Cleared compiled...');
|
||||||
Artisan::call('ide-helper:generate');
|
Artisan::call('ide-helper:generate');
|
||||||
$this->info('IDE helper, done...');
|
$this->info('IDE helper, done...');
|
||||||
Artisan::call('ide-helper:models', ['write']);
|
Artisan::call('ide-helper:models');
|
||||||
$this->info('IDE models, done...');
|
$this->info('IDE models, done...');
|
||||||
Artisan::call('optimize');
|
Artisan::call('optimize');
|
||||||
$this->info('Optimized...');
|
$this->info('Optimized...');
|
||||||
|
|||||||
2
app/config/.gitignore
vendored
2
app/config/.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
local/
|
local/
|
||||||
laptop/
|
laptop/
|
||||||
vagrant/
|
vagrant/
|
||||||
production/
|
production/
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
return [
|
return [
|
||||||
'import' => ''
|
'import' => ''
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
return [
|
return [
|
||||||
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
|
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
|
||||||
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
|
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
|
||||||
'piggybank_periods' => [
|
'piggy_bank_periods' => [
|
||||||
'week' => 'Week',
|
'week' => 'Week',
|
||||||
'month' => 'Month',
|
'month' => 'Month',
|
||||||
'quarter' => 'Quarter',
|
'quarter' => 'Quarter',
|
||||||
@@ -46,4 +46,4 @@ return [
|
|||||||
'6M' => 'half-year',
|
'6M' => 'half-year',
|
||||||
'custom' => 'monthly'
|
'custom' => 'monthly'
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ return [
|
|||||||
*/
|
*/
|
||||||
'debug' => true,
|
'debug' => true,
|
||||||
'log_level' => 'debug',
|
'log_level' => 'debug',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -2,22 +2,7 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
||||||
/*
|
'default' => 'mysql',
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Database Connections
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Here are each of the database connections setup for your application.
|
|
||||||
| Of course, examples of configuring each database platform that is
|
|
||||||
| supported by Laravel is shown below to make development simple.
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| All database work in Laravel is done through the PHP PDO facilities
|
|
||||||
| so make sure you have the driver for your particular database of
|
|
||||||
| choice installed on your machine before you begin development.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'connections' => [
|
'connections' => [
|
||||||
|
|
||||||
'mysql' => [
|
'mysql' => [
|
||||||
@@ -30,6 +15,11 @@ return [
|
|||||||
'collation' => 'utf8_unicode_ci',
|
'collation' => 'utf8_unicode_ci',
|
||||||
'prefix' => '',
|
'prefix' => '',
|
||||||
],
|
],
|
||||||
|
'sqlite' => [
|
||||||
|
'driver' => 'sqlite',
|
||||||
|
'database' => realpath(__DIR__.'/../../../tests/_data/testing.sqlite'),
|
||||||
|
'prefix' => ''
|
||||||
|
],
|
||||||
|
|
||||||
'pgsql' => [
|
'pgsql' => [
|
||||||
'driver' => 'pgsql',
|
'driver' => 'pgsql',
|
||||||
@@ -44,4 +34,4 @@ return [
|
|||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of the TwigBridge package.
|
|
||||||
*
|
|
||||||
* @copyright Robert Crowe <hello@vivalacrowe.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration options for the built-in extensions.
|
|
||||||
*/
|
|
||||||
return [
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| 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\Form',
|
|
||||||
'TwigBridge\Extension\Laravel\Html',
|
|
||||||
'TwigBridge\Extension\Laravel\Input',
|
|
||||||
'TwigBridge\Extension\Laravel\Session',
|
|
||||||
'TwigBridge\Extension\Laravel\String',
|
|
||||||
'TwigBridge\Extension\Laravel\Translator',
|
|
||||||
'TwigBridge\Extension\Laravel\Url',
|
|
||||||
|
|
||||||
// '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' => [],
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| 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' => [],
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| 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' => [],
|
|
||||||
|
|
||||||
];
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of the TwigBridge package.
|
|
||||||
*
|
|
||||||
* @copyright Robert Crowe <hello@vivalacrowe.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration options for Twig.
|
|
||||||
*/
|
|
||||||
return [
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| 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::get('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' => [],
|
|
||||||
|
|
||||||
];
|
|
||||||
0
app/config/queue.php
Executable file → Normal file
0
app/config/queue.php
Executable file → Normal file
@@ -1,2 +1,2 @@
|
|||||||
<?php
|
<?php
|
||||||
return ['log_level' => 'debug',];
|
return ['log_level' => 'debug',];
|
||||||
|
|||||||
@@ -1,20 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return ['driver' => 'array',];
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Default Cache Driver
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This option controls the default cache "driver" that will be used when
|
|
||||||
| using the Caching library. Of course, you may use other drivers any
|
|
||||||
| time you wish. This is the default when another is not specified.
|
|
||||||
|
|
|
||||||
| Supported: "file", "database", "apc", "memcached", "redis", "array"
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'driver' => 'array',
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ return [
|
|||||||
'connections' => [
|
'connections' => [
|
||||||
'sqlite' => [
|
'sqlite' => [
|
||||||
'driver' => 'sqlite',
|
'driver' => 'sqlite',
|
||||||
'database' => 'tests/_data/testing.sqlite',
|
'database' => realpath(__DIR__.'/../../../tests/_data/db.sqlite'),
|
||||||
'prefix' => ''
|
'prefix' => ''
|
||||||
]
|
]
|
||||||
|
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,21 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return ['driver' => 'array',];
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Default Session Driver
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This option controls the default session "driver" that will be used on
|
|
||||||
| requests. By default, we will use the lightweight native driver but
|
|
||||||
| you may specify any of the other wonderful drivers provided here.
|
|
||||||
|
|
|
||||||
| Supported: "native", "cookie", "database", "apc",
|
|
||||||
| "memcached", "redis", "array"
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'driver' => 'array',
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|||||||
2
app/config/testingInMemory/app.php
Normal file
2
app/config/testingInMemory/app.php
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
return ['log_level' => 'debug',];
|
||||||
8
app/config/testingInMemory/auth.php
Normal file
8
app/config/testingInMemory/auth.php
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'verify_mail' => false,
|
||||||
|
'verify_reset' => true,
|
||||||
|
'allow_register' => true
|
||||||
|
|
||||||
|
];
|
||||||
3
app/config/testingInMemory/cache.php
Normal file
3
app/config/testingInMemory/cache.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return ['driver' => 'array',];
|
||||||
12
app/config/testingInMemory/database.php
Normal file
12
app/config/testingInMemory/database.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'default' => 'sqlite',
|
||||||
|
'connections' => [
|
||||||
|
'sqlite' => [
|
||||||
|
'driver' => 'sqlite',
|
||||||
|
'database' => ':memory:',
|
||||||
|
'prefix' => ''
|
||||||
|
]
|
||||||
|
|
||||||
|
]
|
||||||
|
];
|
||||||
13
app/config/testingInMemory/mail.php
Normal file
13
app/config/testingInMemory/mail.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'driver' => 'smtp',
|
||||||
|
'host' => '',
|
||||||
|
'port' => 587,
|
||||||
|
'from' => ['address' => '', 'name' => 'Firefly III'],
|
||||||
|
'encryption' => 'tls',
|
||||||
|
'username' => '',
|
||||||
|
'password' => '',
|
||||||
|
'sendmail' => '/usr/sbin/sendmail -bs',
|
||||||
|
'pretend' => true,
|
||||||
|
];
|
||||||
3
app/config/testingInMemory/session.php
Normal file
3
app/config/testingInMemory/session.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return ['driver' => 'array',];
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use FireflyIII\Database\Account as AccountRepository;
|
use FireflyIII\Database\Account\Account as AccountRepository;
|
||||||
use FireflyIII\Exception\FireflyException;
|
use FireflyIII\Exception\FireflyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,6 +28,7 @@ class AccountController extends BaseController
|
|||||||
'Expense account' => 'expense',
|
'Expense account' => 'expense',
|
||||||
'Beneficiary account' => 'expense',
|
'Beneficiary account' => 'expense',
|
||||||
'Revenue account' => 'revenue',
|
'Revenue account' => 'revenue',
|
||||||
|
'Cash account' => 'cash',
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var array */
|
/** @var array */
|
||||||
@@ -36,6 +37,7 @@ class AccountController extends BaseController
|
|||||||
'asset' => 'fa-money',
|
'asset' => 'fa-money',
|
||||||
'Asset account' => 'fa-money',
|
'Asset account' => 'fa-money',
|
||||||
'Default account' => 'fa-money',
|
'Default account' => 'fa-money',
|
||||||
|
'Cash account' => 'fa-money',
|
||||||
'expense' => 'fa-shopping-cart',
|
'expense' => 'fa-shopping-cart',
|
||||||
'Expense account' => 'fa-shopping-cart',
|
'Expense account' => 'fa-shopping-cart',
|
||||||
'Beneficiary account' => 'fa-shopping-cart',
|
'Beneficiary account' => 'fa-shopping-cart',
|
||||||
@@ -68,7 +70,7 @@ class AccountController extends BaseController
|
|||||||
public function create($what)
|
public function create($what)
|
||||||
{
|
{
|
||||||
$subTitleIcon = $this->_subIconsByIdentifier[$what];
|
$subTitleIcon = $this->_subIconsByIdentifier[$what];
|
||||||
$subTitle = 'Create a new ' . $what . ' account';
|
$subTitle = 'Create a new ' . e($what) . ' account';
|
||||||
|
|
||||||
return View::make('accounts.create', compact('subTitleIcon', 'what', 'subTitle'));
|
return View::make('accounts.create', compact('subTitleIcon', 'what', 'subTitle'));
|
||||||
}
|
}
|
||||||
@@ -80,7 +82,7 @@ class AccountController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function delete(Account $account)
|
public function delete(Account $account)
|
||||||
{
|
{
|
||||||
$subTitle = 'Delete ' . strtolower($account->accountType->type) . ' "' . $account->name . '"';
|
$subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
|
||||||
|
|
||||||
return View::make('accounts.delete', compact('account', 'subTitle'));
|
return View::make('accounts.delete', compact('account', 'subTitle'));
|
||||||
}
|
}
|
||||||
@@ -99,9 +101,9 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
$this->_repository->destroy($account);
|
$this->_repository->destroy($account);
|
||||||
|
|
||||||
Session::flash('success', 'The ' . $typeName . ' account "' . e($name) . '" was deleted.');
|
Session::flash('success', 'The ' . e($typeName) . ' account "' . e($name) . '" was deleted.');
|
||||||
|
|
||||||
return Redirect::route('accounts.index', $type);
|
return Redirect::route('accounts.index', $typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,7 +116,7 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
$openingBalance = $this->_repository->openingBalanceTransaction($account);
|
$openingBalance = $this->_repository->openingBalanceTransaction($account);
|
||||||
$subTitleIcon = $this->_subIconsByIdentifier[$account->accountType->type];
|
$subTitleIcon = $this->_subIconsByIdentifier[$account->accountType->type];
|
||||||
$subTitle = 'Edit ' . strtolower($account->accountType->type) . ' "' . $account->name . '"';
|
$subTitle = 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
|
||||||
|
|
||||||
// pre fill some useful values.
|
// pre fill some useful values.
|
||||||
$preFilled = [
|
$preFilled = [
|
||||||
@@ -155,7 +157,7 @@ class AccountController extends BaseController
|
|||||||
$subTitleIcon = $this->_subIconsByIdentifier[$account->accountType->type];
|
$subTitleIcon = $this->_subIconsByIdentifier[$account->accountType->type];
|
||||||
$what = $this->_shortNamesByFullName[$account->accountType->type];
|
$what = $this->_shortNamesByFullName[$account->accountType->type];
|
||||||
$journals = $this->_repository->getTransactionJournals($account, 50, $range);
|
$journals = $this->_repository->getTransactionJournals($account, 50, $range);
|
||||||
$subTitle = 'Details for ' . strtolower($account->accountType->type) . ' "' . $account->name . '"';
|
$subTitle = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
|
||||||
|
|
||||||
return View::make('accounts.show', compact('account', 'what', 'range', 'subTitleIcon', 'journals', 'subTitle'));
|
return View::make('accounts.show', compact('account', 'what', 'range', 'subTitleIcon', 'journals', 'subTitle'));
|
||||||
}
|
}
|
||||||
@@ -182,21 +184,17 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
// return to create screen:
|
// return to create screen:
|
||||||
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
return Redirect::route('accounts.create', $data['what'])->withInput();
|
return Redirect::route('accounts.create', e($data['what']))->withInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
// store:
|
// store
|
||||||
$this->_repository->store($data);
|
$this->_repository->store($data);
|
||||||
Session::flash('success', 'Account "' . e($data['name']) . '" stored.');
|
Session::flash('success', 'Account "' . e($data['name']) . '" stored.');
|
||||||
if ($data['post_submit_action'] == 'store') {
|
if ($data['post_submit_action'] == 'store') {
|
||||||
return Redirect::route('accounts.index', $data['what']);
|
return Redirect::route('accounts.index', e($data['what']));
|
||||||
}
|
|
||||||
// create another.
|
|
||||||
if ($data['post_submit_action'] == 'create_another') {
|
|
||||||
return Redirect::route('accounts.create', $data['what'])->withInput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::route('accounts.index', $data['what']);
|
return Redirect::route('accounts.create', e($data['what']))->withInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,6 +208,7 @@ class AccountController extends BaseController
|
|||||||
$data = Input::except('_token');
|
$data = Input::except('_token');
|
||||||
$data['what'] = $this->_shortNamesByFullName[$account->accountType->type];
|
$data['what'] = $this->_shortNamesByFullName[$account->accountType->type];
|
||||||
|
|
||||||
|
|
||||||
// always validate:
|
// always validate:
|
||||||
$messages = $this->_repository->validate($data);
|
$messages = $this->_repository->validate($data);
|
||||||
|
|
||||||
@@ -232,13 +231,10 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
// go back to list
|
// go back to list
|
||||||
if ($data['post_submit_action'] == 'update') {
|
if ($data['post_submit_action'] == 'update') {
|
||||||
return Redirect::route('accounts.index', $data['what']);
|
return Redirect::route('accounts.index', e($data['what']));
|
||||||
}
|
|
||||||
// go back to update screen.
|
|
||||||
if ($data['post_submit_action'] == 'return_to_edit') {
|
|
||||||
return Redirect::route('accounts.edit', $account->id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::route('accounts.index', $data['what']);
|
// go back to update screen.
|
||||||
|
return Redirect::route('accounts.edit', $account->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
212
app/controllers/BillController.php
Normal file
212
app/controllers/BillController.php
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
<?php
|
||||||
|
use FireflyIII\Database\Bill\Bill as Repository;
|
||||||
|
use FireflyIII\Exception\FireflyException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
* @SuppressWarnings("NPathComplexity")
|
||||||
|
* Class BillController
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class BillController extends BaseController
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @var Repository */
|
||||||
|
protected $_repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Repository $repository
|
||||||
|
*/
|
||||||
|
public function __construct(Repository $repository)
|
||||||
|
{
|
||||||
|
$this->_repository = $repository;
|
||||||
|
|
||||||
|
View::share('title', 'Bills');
|
||||||
|
View::share('mainTitleIcon', 'fa-calendar-o');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$periods = \Config::get('firefly.periods_to_text');
|
||||||
|
|
||||||
|
return View::make('bills.create')->with('periods', $periods)->with('subTitle', 'Create new');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function delete(Bill $bill)
|
||||||
|
{
|
||||||
|
return View::make('bills.delete')->with('bill', $bill)->with(
|
||||||
|
'subTitle', 'Delete "' . e($bill->name) . '"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function destroy(Bill $bill)
|
||||||
|
{
|
||||||
|
$this->_repository->destroy($bill);
|
||||||
|
Session::flash('success', 'The bill was deleted.');
|
||||||
|
|
||||||
|
return Redirect::route('bills.index');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function edit(Bill $bill)
|
||||||
|
{
|
||||||
|
$periods = \Config::get('firefly.periods_to_text');
|
||||||
|
|
||||||
|
return View::make('bills.edit')->with('periods', $periods)->with('bill', $bill)->with(
|
||||||
|
'subTitle', 'Edit "' . e($bill->name) . '"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$bills = $this->_repository->get();
|
||||||
|
$bills->each(
|
||||||
|
function (Bill $bill) {
|
||||||
|
$bill->nextExpectedMatch = $this->_repository->nextExpectedMatch($bill);
|
||||||
|
$bill->lastFoundMatch = $this->_repository->lastFoundMatch($bill);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return View::make('bills.index', compact('bills'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function rescan(Bill $bill)
|
||||||
|
{
|
||||||
|
if (intval($bill->active) == 0) {
|
||||||
|
Session::flash('warning', 'Inactive bills cannot be scanned.');
|
||||||
|
|
||||||
|
return Redirect::intended('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_repository->scanEverything($bill);
|
||||||
|
|
||||||
|
Session::flash('success', 'Rescanned everything.');
|
||||||
|
|
||||||
|
return Redirect::intended('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function show(Bill $bill)
|
||||||
|
{
|
||||||
|
$journals = $bill->transactionjournals()->withRelevantData()->orderBy('date', 'DESC')->get();
|
||||||
|
$bill->nextExpectedMatch = $this->_repository->nextExpectedMatch($bill);
|
||||||
|
$hideBill = true;
|
||||||
|
|
||||||
|
|
||||||
|
return View::make('bills.show', compact('journals', 'hideBill', 'bill'))->with(
|
||||||
|
'subTitle', e($bill->name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return $this
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function store()
|
||||||
|
{
|
||||||
|
$data = Input::all();
|
||||||
|
$data['user_id'] = Auth::user()->id;
|
||||||
|
|
||||||
|
|
||||||
|
// always validate:
|
||||||
|
$messages = $this->_repository->validate($data);
|
||||||
|
|
||||||
|
// flash messages:
|
||||||
|
Session::flash('warnings', $messages['warnings']);
|
||||||
|
Session::flash('successes', $messages['successes']);
|
||||||
|
Session::flash('errors', $messages['errors']);
|
||||||
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not store bill: ' . $messages['errors']->first());
|
||||||
|
}
|
||||||
|
|
||||||
|
// return to create screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('bills.create')->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
$this->_repository->store($data);
|
||||||
|
Session::flash('success', 'Bill "' . e($data['name']) . '" stored.');
|
||||||
|
if ($data['post_submit_action'] == 'store') {
|
||||||
|
return Redirect::route('bills.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('bills.create')->withInput();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function update(Bill $bill)
|
||||||
|
{
|
||||||
|
$data = Input::except('_token');
|
||||||
|
$data['active'] = isset($data['active']) ? 1 : 0;
|
||||||
|
$data['automatch'] = isset($data['automatch']) ? 1 : 0;
|
||||||
|
$data['user_id'] = Auth::user()->id;
|
||||||
|
|
||||||
|
// always validate:
|
||||||
|
$messages = $this->_repository->validate($data);
|
||||||
|
|
||||||
|
// flash messages:
|
||||||
|
Session::flash('warnings', $messages['warnings']);
|
||||||
|
Session::flash('successes', $messages['successes']);
|
||||||
|
Session::flash('errors', $messages['errors']);
|
||||||
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not update bill: ' . $messages['errors']->first());
|
||||||
|
}
|
||||||
|
|
||||||
|
// return to update screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('bills.edit', $bill->id)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
$this->_repository->update($bill, $data);
|
||||||
|
Session::flash('success', 'Bill "' . e($data['name']) . '" updated.');
|
||||||
|
|
||||||
|
// go back to list
|
||||||
|
if ($data['post_submit_action'] == 'update') {
|
||||||
|
return Redirect::route('bills.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// go back to update screen.
|
||||||
|
return Redirect::route('bills.edit', $bill->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,34 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use FireflyIII\Database\Budget as BudgetRepository;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exception\FireflyException;
|
use FireflyIII\Database\Budget\Budget as BudgetRepository;
|
||||||
use Illuminate\Support\MessageBag;
|
use FireflyIII\Shared\Preferences\PreferencesInterface as Pref;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetController
|
* Class BudgetController
|
||||||
|
*
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
* @SuppressWarnings("TooManyMethods") // I'm also fine with this.
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
* @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class BudgetController extends BaseController
|
class BudgetController extends BaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/** @var Pref */
|
||||||
|
protected $_preferences;
|
||||||
/** @var BudgetRepository */
|
/** @var BudgetRepository */
|
||||||
protected $_repository;
|
protected $_repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BudgetRepository $repository
|
* @param BudgetRepository $repository
|
||||||
|
* @param Pref $preferences
|
||||||
*/
|
*/
|
||||||
public function __construct(BudgetRepository $repository)
|
public function __construct(BudgetRepository $repository, Pref $preferences)
|
||||||
{
|
{
|
||||||
$this->_repository = $repository;
|
$this->_repository = $repository;
|
||||||
|
$this->_preferences = $preferences;
|
||||||
View::share('title', 'Budgets');
|
View::share('title', 'Budgets');
|
||||||
View::share('mainTitleIcon', 'fa-tasks');
|
View::share('mainTitleIcon', 'fa-tasks');
|
||||||
}
|
}
|
||||||
@@ -31,17 +41,11 @@ class BudgetController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function amount(Budget $budget)
|
public function amount(Budget $budget)
|
||||||
{
|
{
|
||||||
$amount = intval(Input::get('amount'));
|
$amount = intval(Input::get('amount'));
|
||||||
$date = Session::get('start');
|
$date = Session::get('start', Carbon::now()->startOfMonth());
|
||||||
$limit = $this->_repository->updateLimitAmount($budget, $date, $amount);
|
$limitRepetition = $this->_repository->updateLimitAmount($budget, $date, $amount);
|
||||||
|
|
||||||
// try to find the limit repetition for this limit:
|
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition->id]);
|
||||||
$repetition = $limit->limitrepetitions()->first();
|
|
||||||
if ($repetition) {
|
|
||||||
return Response::json(['name' => $budget->name, 'repetition' => $repetition->id]);
|
|
||||||
} else {
|
|
||||||
return Response::json(['name' => $budget->name, 'repetition' => null]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,8 +76,9 @@ class BudgetController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function destroy(Budget $budget)
|
public function destroy(Budget $budget)
|
||||||
{
|
{
|
||||||
|
Session::flash('success', 'Budget "' . e($budget->name) . '" was deleted.');
|
||||||
$this->_repository->destroy($budget);
|
$this->_repository->destroy($budget);
|
||||||
Session::flash('success', 'The budget was deleted.');
|
|
||||||
|
|
||||||
return Redirect::route('budgets.index');
|
return Redirect::route('budgets.index');
|
||||||
|
|
||||||
@@ -86,67 +91,50 @@ class BudgetController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function edit(Budget $budget)
|
public function edit(Budget $budget)
|
||||||
{
|
{
|
||||||
$subTitle = 'Edit budget "' . $budget->name . '"';
|
$subTitle = 'Edit budget "' . e($budget->name) . '"';
|
||||||
|
|
||||||
return View::make('budgets.edit', compact('budget', 'subTitle'));
|
return View::make('budgets.edit', compact('budget', 'subTitle'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The index of the budget controller contains all budgets and the current relevant limit repetition.
|
||||||
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
$budgets = $this->_repository->get();
|
||||||
|
|
||||||
/** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
|
// loop the budgets:
|
||||||
$preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
|
$budgets->each(
|
||||||
|
function (Budget $budget) {
|
||||||
/** @var \FireflyIII\Database\Budget $repos */
|
$budget->spent = $this->_repository->spentInMonth($budget, \Session::get('start', Carbon::now()->startOfMonth()));
|
||||||
$repos = App::make('FireflyIII\Database\Budget');
|
$budget->currentRep = $this->_repository->getRepetitionByDate($budget, \Session::get('start', Carbon::now()->startOfMonth()));
|
||||||
$budgets = $repos->get();
|
|
||||||
|
|
||||||
// get the limits for the current month.
|
|
||||||
$date = \Session::get('start');
|
|
||||||
$spent = 0;
|
|
||||||
/** @var \Budget $budget */
|
|
||||||
foreach ($budgets as $budget) {
|
|
||||||
|
|
||||||
$budget->spent = $repos->spentInMonth($budget, $date);
|
|
||||||
$spent += $budget->spent;
|
|
||||||
$budget->pct = 0;
|
|
||||||
$budget->limit = 0;
|
|
||||||
|
|
||||||
/** @var \Limit $limit */
|
|
||||||
foreach ($budget->limits as $limit) {
|
|
||||||
/** @var \LimitRepetition $repetition */
|
|
||||||
foreach ($limit->limitrepetitions as $repetition) {
|
|
||||||
if ($repetition->startdate == $date) {
|
|
||||||
$budget->currentRep = $repetition;
|
|
||||||
$budget->limit = floatval($repetition->amount);
|
|
||||||
if ($budget->limit > $budget->spent) {
|
|
||||||
// not overspent:
|
|
||||||
$budget->pct = 30;
|
|
||||||
} else {
|
|
||||||
$budget->pct = 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
|
|
||||||
$budgetAmount = $preferences->get('budgetIncomeTotal' . $date->format('FY'), 1000);
|
$spent = $budgets->sum('spent');
|
||||||
$amount = floatval($budgetAmount->data);
|
$amount = $this->_preferences->get('budgetIncomeTotal' . \Session::get('start', Carbon::now()->startOfMonth())->format('FY'), 1000)->data;
|
||||||
$overspent = $spent > $amount;
|
$overspent = $spent > $amount;
|
||||||
if ($overspent) {
|
$spentPCT = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100);
|
||||||
// overspent on total amount
|
$budgetMax = $this->_preferences->get('budgetMaximum', 1000);
|
||||||
$spentPCT = ceil($amount / $spent * 100);
|
$budgetMaximum = $budgetMax->data;
|
||||||
} else {
|
|
||||||
// not overspent on total amount.
|
|
||||||
$spentPCT = ceil($spent / $amount * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
return View::make('budgets.index', compact('budgets', 'spent', 'spentPCT', 'overspent'))->with('budgetAmount', $budgetAmount);
|
return View::make('budgets.index', compact('budgetMaximum', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function noBudget()
|
||||||
|
{
|
||||||
|
$start = \Session::get('start', Carbon::now()->startOfMonth());
|
||||||
|
$end = \Session::get('end', Carbon::now()->startOfMonth());
|
||||||
|
$list = $this->_repository->journalsNoBudget($start, $end);
|
||||||
|
$subTitle = 'Transactions without a budget in ' . $start->format('F Y');
|
||||||
|
|
||||||
|
return View::make('budgets.noBudget', compact('list', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,12 +142,7 @@ class BudgetController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function postUpdateIncome()
|
public function postUpdateIncome()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
|
$this->_preferences->set('budgetIncomeTotal' . Session::get('start', Carbon::now()->startOfMonth())->format('FY'), intval(Input::get('amount')));
|
||||||
$preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
|
|
||||||
$date = Session::get('start');
|
|
||||||
|
|
||||||
$value = intval(Input::get('amount'));
|
|
||||||
$preferences->set('budgetIncomeTotal' . $date->format('FY'), $value);
|
|
||||||
|
|
||||||
return Redirect::route('budgets.index');
|
return Redirect::route('budgets.index');
|
||||||
}
|
}
|
||||||
@@ -172,124 +155,90 @@ class BudgetController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function show(Budget $budget, LimitRepetition $repetition = null)
|
public function show(Budget $budget, LimitRepetition $repetition = null)
|
||||||
{
|
{
|
||||||
if (!is_null($repetition) && $repetition->limit->budget->id != $budget->id) {
|
if (!is_null($repetition) && $repetition->budgetLimit->budget->id != $budget->id) {
|
||||||
App::abort(500);
|
return View::make('error')->with('message', 'Invalid selection.');
|
||||||
}
|
}
|
||||||
/** @var \FireflyIII\Database\Budget $repos */
|
|
||||||
$repos = App::make('FireflyIII\Database\Budget');
|
|
||||||
|
|
||||||
if (is_null($repetition)) {
|
|
||||||
// get all other repetitions:
|
|
||||||
$limits = $budget->limits()->orderBy('startdate', 'DESC')->get();
|
|
||||||
// get all transaction journals for this budget.
|
|
||||||
$journals = $repos->getTransactionJournals($budget, 50);
|
|
||||||
|
|
||||||
$subTitle = $budget->name;
|
|
||||||
} else {
|
|
||||||
// get nothing? i dunno
|
|
||||||
$limits = [$repetition->limit];
|
|
||||||
// get all transaction journals for this budget and limit repetition.
|
|
||||||
$subTitle = $budget->name . ' in ' . $repetition->startdate->format('F Y');
|
|
||||||
$journals = $repos->getTransactionJournalsInRepetition($budget, $repetition, 50);
|
|
||||||
}
|
|
||||||
$hideBudget = true;
|
|
||||||
|
|
||||||
|
$hideBudget = true; // used in transaction list.
|
||||||
|
$journals = $this->_repository->getJournals($budget, $repetition);
|
||||||
|
$limits = $repetition ? [$repetition->budgetLimit] : $budget->budgetLimits()->orderBy('startdate', 'DESC')->get();
|
||||||
|
$subTitle = $repetition ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name);
|
||||||
|
|
||||||
return View::make('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget'));
|
return View::make('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return $this
|
* @return $this|\Illuminate\Http\RedirectResponse
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
*/
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Budget $repos */
|
$data = Input::except('_token');
|
||||||
$repos = App::make('FireflyIII\Database\Budget');
|
$data['user_id'] = Auth::user()->id;
|
||||||
$data = Input::except('_token');
|
|
||||||
|
|
||||||
switch ($data['post_submit_action']) {
|
// always validate:
|
||||||
default:
|
$messages = $this->_repository->validate($data);
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
|
|
||||||
break;
|
|
||||||
case 'create_another':
|
|
||||||
case 'store':
|
|
||||||
$messages = $repos->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save budget: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('budgets.create')->withInput()->withErrors($messages['errors']);
|
// flash messages:
|
||||||
}
|
Session::flash('warnings', $messages['warnings']);
|
||||||
// store!
|
Session::flash('successes', $messages['successes']);
|
||||||
$repos->store($data);
|
Session::flash('errors', $messages['errors']);
|
||||||
Session::flash('success', 'New budget stored!');
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not validate budget: ' . $messages['errors']->first());
|
||||||
if ($data['post_submit_action'] == 'create_another') {
|
|
||||||
return Redirect::route('budgets.create');
|
|
||||||
} else {
|
|
||||||
return Redirect::route('budgets.index');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('budgets.create')->withInput();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return to create screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('budgets.create')->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
$this->_repository->store($data);
|
||||||
|
Session::flash('success', 'Budget "' . e($data['name']) . '" stored.');
|
||||||
|
if ($data['post_submit_action'] == 'store') {
|
||||||
|
return Redirect::route('budgets.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// create another.
|
||||||
|
return Redirect::route('budgets.create')->withInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this|\Illuminate\Http\RedirectResponse
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
*/
|
||||||
public function update(Budget $budget)
|
public function update(Budget $budget)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Budget $repos */
|
$data = Input::except('_token');
|
||||||
$repos = App::make('FireflyIII\Database\Budget');
|
$data['user_id'] = Auth::user()->id;
|
||||||
$data = Input::except('_token');
|
|
||||||
|
|
||||||
switch (Input::get('post_submit_action')) {
|
// always validate:
|
||||||
default:
|
$messages = $this->_repository->validate($data);
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"');
|
|
||||||
break;
|
|
||||||
case 'return_to_edit':
|
|
||||||
case 'update':
|
|
||||||
$messages = $repos->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save budget: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('budgets.edit', $budget->id)->withInput()->withErrors($messages['errors']);
|
// flash messages:
|
||||||
}
|
Session::flash('warnings', $messages['warnings']);
|
||||||
// store!
|
Session::flash('successes', $messages['successes']);
|
||||||
$repos->update($budget, $data);
|
Session::flash('errors', $messages['errors']);
|
||||||
Session::flash('success', 'Budget updated!');
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not update budget: ' . $messages['errors']->first());
|
||||||
if ($data['post_submit_action'] == 'return_to_edit') {
|
|
||||||
return Redirect::route('budgets.edit', $budget->id);
|
|
||||||
} else {
|
|
||||||
return Redirect::route('budgets.index');
|
|
||||||
}
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('budgets.edit', $budget->id)->withInput();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return to update screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('budgets.edit', $budget->id)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
$this->_repository->update($budget, $data);
|
||||||
|
Session::flash('success', 'Budget "' . e($data['name']) . '" updated.');
|
||||||
|
|
||||||
|
// go back to list
|
||||||
|
if ($data['post_submit_action'] == 'update') {
|
||||||
|
return Redirect::route('budgets.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('budgets.edit', $budget->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -297,11 +246,8 @@ class BudgetController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function updateIncome()
|
public function updateIncome()
|
||||||
{
|
{
|
||||||
$date = Session::get('start');
|
$budgetAmount = $this->_preferences->get('budgetIncomeTotal' . Session::get('start', Carbon::now()->startOfMonth())->format('FY'), 1000);
|
||||||
/** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
|
|
||||||
$preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
|
|
||||||
$budgetAmount = $preferences->get('budgetIncomeTotal' . $date->format('FY'), 1000);
|
|
||||||
|
|
||||||
return View::make('budgets.income')->with('amount', $budgetAmount)->with('date', $date);
|
return View::make('budgets.income')->with('amount', $budgetAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,30 @@
|
|||||||
<?php
|
<?php
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Database\Category\Category as CategoryRepository;
|
||||||
use FireflyIII\Exception\FireflyException;
|
use FireflyIII\Exception\FireflyException;
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
*
|
||||||
* Class CategoryController
|
* Class CategoryController
|
||||||
*/
|
*/
|
||||||
class CategoryController extends BaseController
|
class CategoryController extends BaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/** @var CategoryRepository */
|
||||||
|
protected $_repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param CategoryRepository $repository
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(CategoryRepository $repository)
|
||||||
{
|
{
|
||||||
View::share('title', 'Categories');
|
View::share('title', 'Categories');
|
||||||
View::share('mainTitleIcon', 'fa-bar-chart');
|
View::share('mainTitleIcon', 'fa-bar-chart');
|
||||||
|
|
||||||
|
$this->_repository = $repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,6 +35,19 @@ class CategoryController extends BaseController
|
|||||||
return View::make('categories.create')->with('subTitle', 'Create a new category');
|
return View::make('categories.create')->with('subTitle', 'Create a new category');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function noCategory()
|
||||||
|
{
|
||||||
|
$start = \Session::get('start', Carbon::now()->startOfMonth());
|
||||||
|
$end = \Session::get('end', Carbon::now()->startOfMonth());
|
||||||
|
$list = $this->_repository->journalsNoCategory($start, $end);
|
||||||
|
$subTitle = 'Transactions without a category in ' . $start->format('F Y');
|
||||||
|
|
||||||
|
return View::make('categories.noCategory', compact('list', 'subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
@@ -31,7 +55,7 @@ class CategoryController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function delete(Category $category)
|
public function delete(Category $category)
|
||||||
{
|
{
|
||||||
return View::make('categories.delete')->with('category', $category)->with('subTitle', 'Delete category "' . $category->name . '"');
|
return View::make('categories.delete')->with('category', $category)->with('subTitle', 'Delete category "' . e($category->name) . '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,11 +65,9 @@ class CategoryController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function destroy(Category $category)
|
public function destroy(Category $category)
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Category $repos */
|
Session::flash('success', 'Category "' . e($category->name) . '" was deleted.');
|
||||||
$repos = App::make('FireflyIII\Database\Category');
|
$this->_repository->destroy($category);
|
||||||
|
|
||||||
$repos->destroy($category);
|
|
||||||
Session::flash('success', 'The category was deleted.');
|
|
||||||
|
|
||||||
return Redirect::route('categories.index');
|
return Redirect::route('categories.index');
|
||||||
}
|
}
|
||||||
@@ -57,7 +79,7 @@ class CategoryController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function edit(Category $category)
|
public function edit(Category $category)
|
||||||
{
|
{
|
||||||
return View::make('categories.edit')->with('category', $category)->with('subTitle', 'Edit category "' . $category->name . '"');
|
return View::make('categories.edit')->with('category', $category)->with('subTitle', 'Edit category "' . e($category->name) . '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,9 +87,7 @@ class CategoryController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Category $repos */
|
$categories = $this->_repository->get();
|
||||||
$repos = App::make('FireflyIII\Database\Category');
|
|
||||||
$categories = $repos->get();
|
|
||||||
|
|
||||||
return View::make('categories.index', compact('categories'));
|
return View::make('categories.index', compact('categories'));
|
||||||
}
|
}
|
||||||
@@ -79,12 +99,8 @@ class CategoryController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function show(Category $category)
|
public function show(Category $category)
|
||||||
{
|
{
|
||||||
$hideCategory = true;
|
$hideCategory = true; // used in list.
|
||||||
|
$journals = $this->_repository->getTransactionJournals($category, 50);
|
||||||
/** @var \FireflyIII\Database\Category $repos */
|
|
||||||
$repos = App::make('FireflyIII\Database\Category');
|
|
||||||
|
|
||||||
$journals = $repos->getTransactionJournals($category, 50);
|
|
||||||
|
|
||||||
return View::make('categories.show', compact('category', 'journals', 'hideCategory'));
|
return View::make('categories.show', compact('category', 'journals', 'hideCategory'));
|
||||||
}
|
}
|
||||||
@@ -95,44 +111,33 @@ class CategoryController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
$data = Input::all();
|
$data = Input::except('_token');
|
||||||
/** @var \FireflyIII\Database\Category $repos */
|
$data['user_id'] = Auth::user()->id;
|
||||||
$repos = App::make('FireflyIII\Database\Category');
|
|
||||||
|
|
||||||
switch ($data['post_submit_action']) {
|
// always validate:
|
||||||
default:
|
$messages = $this->_repository->validate($data);
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
|
|
||||||
break;
|
|
||||||
case 'create_another':
|
|
||||||
case 'store':
|
|
||||||
$messages = $repos->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save category: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('categories.create')->withInput()->withErrors($messages['errors']);
|
// flash messages:
|
||||||
}
|
Session::flash('warnings', $messages['warnings']);
|
||||||
// store!
|
Session::flash('successes', $messages['successes']);
|
||||||
$repos->store($data);
|
Session::flash('errors', $messages['errors']);
|
||||||
Session::flash('success', 'New category stored!');
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not store category: ' . $messages['errors']->first());
|
||||||
if ($data['post_submit_action'] == 'create_another') {
|
|
||||||
return Redirect::route('categories.create')->withInput();
|
|
||||||
} else {
|
|
||||||
return Redirect::route('categories.index');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('categories.create')->withInput();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return to create screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('categories.create')->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
$this->_repository->store($data);
|
||||||
|
Session::flash('success', 'Category "' . e($data['name']) . '" stored.');
|
||||||
|
if ($data['post_submit_action'] == 'store') {
|
||||||
|
return Redirect::route('categories.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('categories.create')->withInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,46 +148,39 @@ class CategoryController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function update(Category $category)
|
public function update(Category $category)
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Category $repos */
|
$data = Input::except('_token');
|
||||||
$repos = App::make('FireflyIII\Database\Category');
|
$data['user_id'] = Auth::user()->id;
|
||||||
$data = Input::except('_token');
|
|
||||||
|
|
||||||
switch (Input::get('post_submit_action')) {
|
// always validate:
|
||||||
default:
|
$messages = $this->_repository->validate($data);
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"');
|
|
||||||
break;
|
|
||||||
case 'return_to_edit':
|
|
||||||
case 'update':
|
|
||||||
$messages = $repos->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save category: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('categories.edit', $category->id)->withInput()->withErrors($messages['errors']);
|
// flash messages:
|
||||||
}
|
Session::flash('warnings', $messages['warnings']);
|
||||||
// store!
|
Session::flash('successes', $messages['successes']);
|
||||||
$repos->update($category, $data);
|
Session::flash('errors', $messages['errors']);
|
||||||
Session::flash('success', 'Category updated!');
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not update category: ' . $messages['errors']->first());
|
||||||
if ($data['post_submit_action'] == 'return_to_edit') {
|
|
||||||
return Redirect::route('categories.edit', $category->id);
|
|
||||||
} else {
|
|
||||||
return Redirect::route('categories.index');
|
|
||||||
}
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('categories.edit', $category->id)->withInput();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return to update screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('categories.edit', $category->id)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
$this->_repository->update($category, $data);
|
||||||
|
Session::flash('success', 'Category "' . e($data['name']) . '" updated.');
|
||||||
|
|
||||||
|
// go back to list
|
||||||
|
if ($data['post_submit_action'] == 'update') {
|
||||||
|
return Redirect::route('categories.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// go back to update screen.
|
||||||
|
return Redirect::route('categories.edit', $category->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
197
app/controllers/CurrencyController.php
Normal file
197
app/controllers/CurrencyController.php
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
<?php
|
||||||
|
use FireflyIII\Database\TransactionCurrency\TransactionCurrency as Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
*
|
||||||
|
* Class CurrencyController
|
||||||
|
*/
|
||||||
|
class CurrencyController extends BaseController
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @var Repository */
|
||||||
|
protected $_repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Repository $repository
|
||||||
|
*/
|
||||||
|
public function __construct(Repository $repository)
|
||||||
|
{
|
||||||
|
$this->_repository = $repository;
|
||||||
|
|
||||||
|
|
||||||
|
View::share('title', 'Currencies');
|
||||||
|
View::share('mainTitleIcon', 'fa-usd');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$subTitleIcon = 'fa-plus';
|
||||||
|
$subTitle = 'Create a new currency';
|
||||||
|
|
||||||
|
return View::make('currency.create', compact('subTitleIcon', 'subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function defaultCurrency(TransactionCurrency $currency)
|
||||||
|
{
|
||||||
|
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
|
||||||
|
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
|
||||||
|
|
||||||
|
$currencyPreference = $preferences->get('currencyPreference', 'EUR');
|
||||||
|
$currencyPreference->data = $currency->code;
|
||||||
|
$currencyPreference->save();
|
||||||
|
|
||||||
|
Session::flash('success', $currency->name.' is now the default currency.');
|
||||||
|
Cache::forget('FFCURRENCYSYMBOL');
|
||||||
|
Cache::forget('FFCURRENCYCODE');
|
||||||
|
|
||||||
|
return Redirect::route('currency.index');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function delete(TransactionCurrency $currency)
|
||||||
|
{
|
||||||
|
if ($currency->transactionJournals()->count() > 0) {
|
||||||
|
Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.');
|
||||||
|
|
||||||
|
return Redirect::route('currency.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return View::make('currency.delete', compact('currency'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function destroy(TransactionCurrency $currency)
|
||||||
|
{
|
||||||
|
Session::flash('success', 'Currency "' . e($currency->name) . '" deleted');
|
||||||
|
|
||||||
|
$this->_repository->destroy($currency);
|
||||||
|
|
||||||
|
return Redirect::route('currency.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function edit(TransactionCurrency $currency)
|
||||||
|
{
|
||||||
|
$subTitleIcon = 'fa-pencil';
|
||||||
|
$subTitle = 'Edit currency "' . e($currency->name) . '"';
|
||||||
|
$currency->symbol = htmlentities($currency->symbol);
|
||||||
|
|
||||||
|
return View::make('currency.edit', compact('currency', 'subTitle', 'subTitleIcon'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$currencies = $this->_repository->get();
|
||||||
|
|
||||||
|
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
|
||||||
|
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
|
||||||
|
|
||||||
|
$currencyPreference = $preferences->get('currencyPreference', 'EUR');
|
||||||
|
$defaultCurrency = $this->_repository->findByCode($currencyPreference->data);
|
||||||
|
|
||||||
|
|
||||||
|
return View::make('currency.index', compact('currencies', 'defaultCurrency'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return $this|\Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function store()
|
||||||
|
{
|
||||||
|
$data = Input::except('_token');
|
||||||
|
|
||||||
|
// always validate:
|
||||||
|
$messages = $this->_repository->validate($data);
|
||||||
|
|
||||||
|
// flash messages:
|
||||||
|
Session::flash('warnings', $messages['warnings']);
|
||||||
|
Session::flash('successes', $messages['successes']);
|
||||||
|
Session::flash('errors', $messages['errors']);
|
||||||
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not store currency: ' . $messages['errors']->first());
|
||||||
|
}
|
||||||
|
|
||||||
|
// return to create screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('currency.create')->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
$this->_repository->store($data);
|
||||||
|
Session::flash('success', 'Currency "' . e($data['name']) . '" stored.');
|
||||||
|
if ($data['post_submit_action'] == 'store') {
|
||||||
|
return Redirect::route('currency.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('currency.create')->withInput();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return $this|\Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function update(TransactionCurrency $currency)
|
||||||
|
{
|
||||||
|
$data = Input::except('_token');
|
||||||
|
|
||||||
|
// always validate:
|
||||||
|
$messages = $this->_repository->validate($data);
|
||||||
|
|
||||||
|
// flash messages:
|
||||||
|
Session::flash('warnings', $messages['warnings']);
|
||||||
|
Session::flash('successes', $messages['successes']);
|
||||||
|
Session::flash('errors', $messages['errors']);
|
||||||
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not update currency: ' . $messages['errors']->first());
|
||||||
|
}
|
||||||
|
|
||||||
|
// return to update screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('currency.edit', $currency->id)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
$this->_repository->update($currency, $data);
|
||||||
|
Session::flash('success', 'Currency "' . e($data['name']) . '" updated.');
|
||||||
|
|
||||||
|
// go back to list
|
||||||
|
if ($data['post_submit_action'] == 'update') {
|
||||||
|
return Redirect::route('currency.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('currency.edit', $currency->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,12 +1,41 @@
|
|||||||
<?php
|
<?php
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Chart\ChartInterface;
|
||||||
|
use Grumpydictator\Gchart\GChart as GChart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class GoogleChartController
|
* Class GoogleChartController
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
* @SuppressWarnings("TooManyMethods") // I'm also fine with this.
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
* @SuppressWarnings("MethodLength") // There is one with 45 lines and im gonna move it.
|
||||||
|
* @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove.
|
||||||
*/
|
*/
|
||||||
class GoogleChartController extends BaseController
|
class GoogleChartController extends BaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/** @var GChart */
|
||||||
|
protected $_chart;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_end;
|
||||||
|
/** @var ChartInterface */
|
||||||
|
protected $_repository;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_start;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param GChart $chart
|
||||||
|
* @param ChartInterface $repository
|
||||||
|
*/
|
||||||
|
public function __construct(GChart $chart, ChartInterface $repository)
|
||||||
|
{
|
||||||
|
$this->_chart = $chart;
|
||||||
|
$this->_repository = $repository;
|
||||||
|
$this->_start = Session::get('start', Carbon::now()->startOfMonth());
|
||||||
|
$this->_end = Session::get('end', Carbon::now()->endOfMonth());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
* @param string $view
|
* @param string $view
|
||||||
@@ -15,199 +44,35 @@ class GoogleChartController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function accountBalanceChart(Account $account, $view = 'session')
|
public function accountBalanceChart(Account $account, $view = 'session')
|
||||||
{
|
{
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
$this->_chart->addColumn('Day of month', 'date');
|
||||||
$chart = App::make('gchart');
|
$this->_chart->addColumn('Balance for ' . $account->name, 'number');
|
||||||
|
|
||||||
$chart->addColumn('Day of month', 'date');
|
$start = $this->_start;
|
||||||
$chart->addColumn('Balance for ' . $account->name, 'number');
|
$end = $this->_end;
|
||||||
|
$count = $account->transactions()->count();
|
||||||
|
|
||||||
/*
|
if ($view == 'all' && $count > 0) {
|
||||||
* Loop the date, then loop the accounts, then add balance.
|
$first = $account->transactions()->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->orderBy(
|
||||||
*/
|
'date', 'ASC'
|
||||||
switch ($view) {
|
)->first(['transaction_journals.date']);
|
||||||
default:
|
$last = $account->transactions()->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->orderBy(
|
||||||
case 'session':
|
'date', 'DESC'
|
||||||
$start = Session::get('start');
|
)->first(['transaction_journals.date']);
|
||||||
$end = Session::get('end');
|
$start = new Carbon($first->date);
|
||||||
break;
|
$end = new Carbon($last->date);
|
||||||
case 'all':
|
|
||||||
$first = $account->transactionjournals()->orderBy('date', 'DESC')->first();
|
|
||||||
$last = $account->transactionjournals()->orderBy('date', 'ASC')->first();
|
|
||||||
if (is_null($first)) {
|
|
||||||
$start = Session::get('start');
|
|
||||||
} else {
|
|
||||||
$start = clone $first->date;
|
|
||||||
}
|
|
||||||
if (is_null($last)) {
|
|
||||||
$end = Session::get('end');
|
|
||||||
} else {
|
|
||||||
$end = clone $last->date;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$current = clone $start;
|
$current = clone $start;
|
||||||
|
|
||||||
while ($end >= $current) {
|
while ($end >= $current) {
|
||||||
$row = [clone $current];
|
$this->_chart->addRow(clone $current, Steam::balance($account, $current));
|
||||||
if ($current > Carbon::now()) {
|
|
||||||
$row[] = null;
|
|
||||||
} else {
|
|
||||||
$row[] = Steam::balance($account, $current);
|
|
||||||
}
|
|
||||||
|
|
||||||
$chart->addRowArray($row);
|
|
||||||
$current->addDay();
|
$current->addDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$chart->generate();
|
$this->_chart->generate();
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param string $view
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function accountSankeyInChart(Account $account, $view = 'session')
|
|
||||||
{
|
|
||||||
// collect all relevant entries.
|
|
||||||
$set = [];
|
|
||||||
|
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
|
||||||
$chart = App::make('gchart');
|
|
||||||
$chart->addColumn('From', 'string');
|
|
||||||
$chart->addColumn('To', 'string', 'domain');
|
|
||||||
$chart->addColumn('Weight', 'number');
|
|
||||||
|
|
||||||
switch ($view) {
|
|
||||||
default:
|
|
||||||
case 'session':
|
|
||||||
$start = Session::get('start');
|
|
||||||
$end = Session::get('end');
|
|
||||||
break;
|
|
||||||
case 'all':
|
|
||||||
$first = $account->transactionjournals()->orderBy('date', 'DESC')->first();
|
|
||||||
$last = $account->transactionjournals()->orderBy('date', 'ASC')->first();
|
|
||||||
if (is_null($first)) {
|
|
||||||
$start = Session::get('start');
|
|
||||||
} else {
|
|
||||||
$start = clone $first->date;
|
|
||||||
}
|
|
||||||
if (is_null($last)) {
|
|
||||||
$end = Session::get('end');
|
|
||||||
} else {
|
|
||||||
$end = clone $last->date;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$transactions = $account->transactions()->with(
|
|
||||||
['transactionjournal', 'transactionjournal.transactions' => function ($q) {
|
|
||||||
$q->where('amount', '<', 0);
|
|
||||||
}, 'transactionjournal.budgets', 'transactionjournal.transactiontype', 'transactionjournal.categories']
|
|
||||||
)->before($end)->after($start)->get();
|
|
||||||
|
|
||||||
/** @var Transaction $transaction */
|
|
||||||
foreach ($transactions as $transaction) {
|
|
||||||
$amount = floatval($transaction->amount);
|
|
||||||
$type = $transaction->transactionJournal->transactionType->type;
|
|
||||||
|
|
||||||
if ($amount > 0 && $type != 'Transfer') {
|
|
||||||
|
|
||||||
$otherAccount = $transaction->transactionJournal->transactions[0]->account->name;
|
|
||||||
$categoryName = isset($transaction->transactionJournal->categories[0]) ? $transaction->transactionJournal->categories[0]->name : '(no cat)';
|
|
||||||
$set[] = [$otherAccount, $categoryName, $amount];
|
|
||||||
$set[] = [$categoryName, $account->name, $amount];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// loop the set, group everything together:
|
|
||||||
$grouped = [];
|
|
||||||
foreach ($set as $entry) {
|
|
||||||
$key = $entry[0] . $entry[1];
|
|
||||||
if (isset($grouped[$key])) {
|
|
||||||
$grouped[$key][2] += $entry[2];
|
|
||||||
} else {
|
|
||||||
$grouped[$key] = $entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add rows to the chart:
|
|
||||||
foreach ($grouped as $entry) {
|
|
||||||
$chart->addRow($entry[0], $entry[1], $entry[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$chart->generate();
|
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Account $account
|
|
||||||
* @param string $view
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function accountSankeyOutChart(Account $account, $view = 'session')
|
|
||||||
{
|
|
||||||
// collect all relevant entries.
|
|
||||||
$set = [];
|
|
||||||
|
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
|
||||||
$chart = App::make('gchart');
|
|
||||||
$chart->addColumn('From', 'string');
|
|
||||||
$chart->addColumn('To', 'string', 'domain');
|
|
||||||
$chart->addColumn('Weight', 'number');
|
|
||||||
|
|
||||||
$transactions = $account->transactions()->with(
|
|
||||||
['transactionjournal', 'transactionjournal.transactions', 'transactionjournal.budgets', 'transactionjournal.transactiontype',
|
|
||||||
'transactionjournal.categories']
|
|
||||||
)->before(Session::get('end'))->after(
|
|
||||||
Session::get('start')
|
|
||||||
)->get();
|
|
||||||
|
|
||||||
/** @var Transaction $transaction */
|
|
||||||
foreach ($transactions as $transaction) {
|
|
||||||
$amount = floatval($transaction->amount);
|
|
||||||
$type = $transaction->transactionJournal->transactionType->type;
|
|
||||||
|
|
||||||
if ($amount < 0 && $type != 'Transfer') {
|
|
||||||
|
|
||||||
// from account to a budget (if present).
|
|
||||||
$budgetName = isset($transaction->transactionJournal->budgets[0]) ? $transaction->transactionJournal->budgets[0]->name : '(no budget)';
|
|
||||||
$set[] = [$account->name, $budgetName, $amount * -1];
|
|
||||||
|
|
||||||
// from budget to category.
|
|
||||||
$categoryName = isset($transaction->transactionJournal->categories[0]) ? ' ' . $transaction->transactionJournal->categories[0]->name
|
|
||||||
: '(no cat)';
|
|
||||||
$set[] = [$budgetName, $categoryName, $amount * -1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// loop the set, group everything together:
|
|
||||||
$grouped = [];
|
|
||||||
foreach ($set as $entry) {
|
|
||||||
$key = $entry[0] . $entry[1];
|
|
||||||
if (isset($grouped[$key])) {
|
|
||||||
$grouped[$key][2] += $entry[2];
|
|
||||||
} else {
|
|
||||||
$grouped[$key] = $entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add rows to the chart:
|
|
||||||
foreach ($grouped as $entry) {
|
|
||||||
$chart->addRow($entry[0], $entry[1], $entry[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$chart->generate();
|
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
|
||||||
|
|
||||||
|
return Response::json($this->_chart->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -215,51 +80,35 @@ class GoogleChartController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function allAccountsBalanceChart()
|
public function allAccountsBalanceChart()
|
||||||
{
|
{
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
$this->_chart->addColumn('Day of the month', 'date');
|
||||||
$chart = App::make('gchart');
|
|
||||||
$chart->addColumn('Day of the month', 'date');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
|
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
|
||||||
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
|
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
|
||||||
$pref = $preferences->get('frontpageAccounts', []);
|
$pref = $preferences->get('frontPageAccounts', []);
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Account $acct */
|
/** @var \FireflyIII\Database\Account\Account $acct */
|
||||||
$acct = App::make('FireflyIII\Database\Account');
|
$acct = App::make('FireflyIII\Database\Account\Account');
|
||||||
if (count($pref->data) > 0) {
|
$accounts = count($pref->data) > 0 ? $acct->getByIds($pref->data) : $acct->getAssetAccounts();
|
||||||
$accounts = $acct->getByIds($pref->data);
|
|
||||||
} else {
|
|
||||||
$accounts = $acct->getAssetAccounts();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add a column for each account.
|
|
||||||
*/
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$chart->addColumn('Balance for ' . $account->name, 'number');
|
$this->_chart->addColumn('Balance for ' . $account->name, 'number');
|
||||||
}
|
}
|
||||||
/*
|
$current = clone $this->_start;
|
||||||
* Loop the date, then loop the accounts, then add balance.
|
$current->subDay();
|
||||||
*/
|
|
||||||
$start = Session::get('start');
|
|
||||||
$end = Session::get('end');
|
|
||||||
$current = clone $start;
|
|
||||||
|
|
||||||
while ($end >= $current) {
|
while ($this->_end >= $current) {
|
||||||
$row = [clone $current];
|
$row = [clone $current];
|
||||||
|
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$row[] = Steam::balance($account, $current);
|
$row[] = Steam::balance($account, $current);
|
||||||
}
|
}
|
||||||
|
$this->_chart->addRowArray($row);
|
||||||
$chart->addRowArray($row);
|
|
||||||
$current->addDay();
|
$current->addDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
$chart->generate();
|
$this->_chart->generate();
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,68 +117,50 @@ class GoogleChartController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function allBudgetsHomeChart()
|
public function allBudgetsHomeChart()
|
||||||
{
|
{
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
$this->_chart->addColumn('Budget', 'string');
|
||||||
$chart = App::make('gchart');
|
$this->_chart->addColumn('Budgeted', 'number');
|
||||||
$chart->addColumn('Budget', 'string');
|
$this->_chart->addColumn('Spent', 'number');
|
||||||
$chart->addColumn('Budgeted', 'number');
|
|
||||||
$chart->addColumn('Spent', 'number');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Budget $bdt */
|
Log::debug('Now in allBudgetsHomeChart()');
|
||||||
$bdt = App::make('FireflyIII\Database\Budget');
|
|
||||||
|
/** @var \FireflyIII\Database\Budget\Budget $bdt */
|
||||||
|
$bdt = App::make('FireflyIII\Database\Budget\Budget');
|
||||||
$budgets = $bdt->get();
|
$budgets = $bdt->get();
|
||||||
|
|
||||||
/*
|
|
||||||
* Loop budgets:
|
|
||||||
*/
|
|
||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
|
|
||||||
/*
|
Log::debug('Now working budget #' . $budget->id . ', ' . $budget->name);
|
||||||
* Is there a repetition starting on this particular date? We can use that.
|
|
||||||
*/
|
|
||||||
/** @var \LimitRepetition $repetition */
|
/** @var \LimitRepetition $repetition */
|
||||||
$repetition = $bdt->repetitionOnStartingOnDate($budget, Session::get('start'));
|
$repetition = $bdt->repetitionOnStartingOnDate($budget, $this->_start);
|
||||||
|
|
||||||
/*
|
|
||||||
* If there is, use it. Otherwise, forget it.
|
|
||||||
*/
|
|
||||||
if (is_null($repetition)) {
|
if (is_null($repetition)) {
|
||||||
|
\Log::debug('Budget #' . $budget->id . ' has no repetition on ' . $this->_start->format('Y-m-d'));
|
||||||
// use the session start and end for our search query
|
// use the session start and end for our search query
|
||||||
$searchStart = Session::get('start');
|
$searchStart = $this->_start;
|
||||||
$searchEnd = Session::get('end');
|
$searchEnd = $this->_end;
|
||||||
// the limit is zero:
|
$limit = 0; // the limit is zero:
|
||||||
$limit = 0;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
\Log::debug('Budget #' . $budget->id . ' has a repetition on ' . $this->_start->format('Y-m-d') . '!');
|
||||||
// use the limit's start and end for our search query
|
// use the limit's start and end for our search query
|
||||||
$searchStart = $repetition->startdate;
|
$searchStart = $repetition->startdate;
|
||||||
$searchEnd = $repetition->enddate;
|
$searchEnd = $repetition->enddate;
|
||||||
// the limit is the repetitions limit:
|
$limit = floatval($repetition->amount); // the limit is the repetitions limit:
|
||||||
$limit = floatval($repetition->amount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* No matter the result of the search for the repetition, get all the transactions associated
|
|
||||||
* with the budget, and sum up the expenses made.
|
|
||||||
*/
|
|
||||||
$expenses = floatval($budget->transactionjournals()->before($searchEnd)->after($searchStart)->lessThan(0)->sum('amount')) * -1;
|
$expenses = floatval($budget->transactionjournals()->before($searchEnd)->after($searchStart)->lessThan(0)->sum('amount')) * -1;
|
||||||
|
\Log::debug('Expenses in budget ' . $budget->name . ' before ' . $searchEnd->format('Y-m-d') . ' and after ' . $searchStart . ' are: ' . $expenses);
|
||||||
if ($expenses > 0) {
|
if ($expenses > 0) {
|
||||||
$chart->addRow($budget->name, $limit, $expenses);
|
$this->_chart->addRow($budget->name, $limit, $expenses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
$noBudgetSet = $bdt->expenseNoBudget($this->_start, $this->_end);
|
||||||
* Finally, get all transactions WITHOUT a budget and add those as well.
|
|
||||||
* (yes this method is oddly specific).
|
|
||||||
*/
|
|
||||||
$noBudgetSet = $bdt->transactionsWithoutBudgetInDateRange(Session::get('start'), Session::get('end'));
|
|
||||||
$sum = $noBudgetSet->sum('amount') * -1;
|
$sum = $noBudgetSet->sum('amount') * -1;
|
||||||
$chart->addRow('No budget', 0, $sum);
|
$this->_chart->addRow('No budget', 0, $sum);
|
||||||
|
$this->_chart->generate();
|
||||||
|
|
||||||
|
return Response::json($this->_chart->getData());
|
||||||
$chart->generate();
|
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -337,48 +168,94 @@ class GoogleChartController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function allCategoriesHomeChart()
|
public function allCategoriesHomeChart()
|
||||||
{
|
{
|
||||||
$data = [];
|
$this->_chart->addColumn('Category', 'string');
|
||||||
|
$this->_chart->addColumn('Spent', 'number');
|
||||||
|
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
// query!
|
||||||
$chart = App::make('gchart');
|
$set = $this->_repository->getCategorySummary($this->_start, $this->_end);
|
||||||
$chart->addColumn('Category', 'string');
|
|
||||||
$chart->addColumn('Spent', 'number');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $tj */
|
foreach ($set as $entry) {
|
||||||
$tj = App::make('FireflyIII\Database\TransactionJournal');
|
$entry->name = strlen($entry->name) == 0 ? '(no category)' : $entry->name;
|
||||||
|
$this->_chart->addRow($entry->name, floatval($entry->sum));
|
||||||
/*
|
|
||||||
* Get the journals:
|
|
||||||
*/
|
|
||||||
$journals = $tj->getInDateRange(Session::get('start'), Session::get('end'));
|
|
||||||
|
|
||||||
/** @var \TransactionJournal $journal */
|
|
||||||
foreach ($journals as $journal) {
|
|
||||||
if ($journal->transactionType->type == 'Withdrawal') {
|
|
||||||
$amount = $journal->getAmount();
|
|
||||||
$category = $journal->categories()->first();
|
|
||||||
if (!is_null($category)) {
|
|
||||||
if (isset($data[$category->name])) {
|
|
||||||
$data[$category->name] += $amount;
|
|
||||||
} else {
|
|
||||||
$data[$category->name] = $amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arsort($data);
|
|
||||||
foreach ($data as $key => $entry) {
|
|
||||||
$chart->addRow($key, $entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->_chart->generate();
|
||||||
|
|
||||||
$chart->generate();
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function billOverview(Bill $bill)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->_chart->addColumn('Date', 'date');
|
||||||
|
$this->_chart->addColumn('Max amount', 'number');
|
||||||
|
$this->_chart->addColumn('Min amount', 'number');
|
||||||
|
$this->_chart->addColumn('Current entry', 'number');
|
||||||
|
|
||||||
|
// get first transaction or today for start:
|
||||||
|
$first = $bill->transactionjournals()->orderBy('date', 'ASC')->first();
|
||||||
|
if ($first) {
|
||||||
|
$start = $first->date;
|
||||||
|
} else {
|
||||||
|
$start = new Carbon;
|
||||||
|
}
|
||||||
|
$end = new Carbon;
|
||||||
|
while ($start <= $end) {
|
||||||
|
$result = $bill->transactionjournals()->before($end)->after($start)->first();
|
||||||
|
if ($result) {
|
||||||
|
$amount = $result->getAmount();
|
||||||
|
} else {
|
||||||
|
$amount = 0;
|
||||||
|
}
|
||||||
|
unset($result);
|
||||||
|
$this->_chart->addRow(clone $start, $bill->amount_max, $bill->amount_min, $amount);
|
||||||
|
$start = DateKit::addPeriod($start, $bill->repeat_freq, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_chart->generate();
|
||||||
|
|
||||||
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
* @throws \FireflyIII\Exception\FireflyException
|
||||||
|
*/
|
||||||
|
public function billsOverview()
|
||||||
|
{
|
||||||
|
$paid = ['items' => [], 'amount' => 0];
|
||||||
|
$unpaid = ['items' => [], 'amount' => 0];
|
||||||
|
$this->_chart->addColumn('Name', 'string');
|
||||||
|
$this->_chart->addColumn('Amount', 'number');
|
||||||
|
|
||||||
|
$set = $this->_repository->getBillsSummary($this->_start, $this->_end);
|
||||||
|
|
||||||
|
foreach ($set as $entry) {
|
||||||
|
if (intval($entry->journalId) == 0) {
|
||||||
|
$unpaid['items'][] = $entry->name;
|
||||||
|
$unpaid['amount'] += floatval($entry->averageAmount);
|
||||||
|
} else {
|
||||||
|
$paid['items'][] = $entry->description;
|
||||||
|
$paid['amount'] += floatval($entry->actualAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']);
|
||||||
|
$this->_chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']);
|
||||||
|
$this->_chart->generate();
|
||||||
|
|
||||||
|
return Response::json($this->_chart->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param LimitRepetition $repetition
|
* @param LimitRepetition $repetition
|
||||||
*
|
*
|
||||||
@@ -389,10 +266,8 @@ class GoogleChartController extends BaseController
|
|||||||
$start = clone $repetition->startdate;
|
$start = clone $repetition->startdate;
|
||||||
$end = $repetition->enddate;
|
$end = $repetition->enddate;
|
||||||
|
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
$this->_chart->addColumn('Day', 'date');
|
||||||
$chart = App::make('gchart');
|
$this->_chart->addColumn('Left', 'number');
|
||||||
$chart->addColumn('Day', 'date');
|
|
||||||
$chart->addColumn('Left', 'number');
|
|
||||||
|
|
||||||
|
|
||||||
$amount = $repetition->amount;
|
$amount = $repetition->amount;
|
||||||
@@ -403,273 +278,132 @@ class GoogleChartController extends BaseController
|
|||||||
*/
|
*/
|
||||||
$sum = floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($start)->sum('amount'));
|
$sum = floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($start)->sum('amount'));
|
||||||
$amount += $sum;
|
$amount += $sum;
|
||||||
$chart->addRow(clone $start, $amount);
|
$this->_chart->addRow(clone $start, $amount);
|
||||||
$start->addDay();
|
$start->addDay();
|
||||||
}
|
}
|
||||||
$chart->generate();
|
$this->_chart->generate();
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $year
|
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @param Budget $budget
|
||||||
*/
|
|
||||||
public function budgetsReportChart($year)
|
|
||||||
{
|
|
||||||
|
|
||||||
try {
|
|
||||||
$start = new Carbon('01-01-' . $year);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
App::abort(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
|
||||||
$chart = App::make('gchart');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Budget $bdt */
|
|
||||||
$bdt = App::make('FireflyIII\Database\Budget');
|
|
||||||
$budgets = $bdt->get();
|
|
||||||
|
|
||||||
$chart->addColumn('Month', 'date');
|
|
||||||
/** @var \Budget $budget */
|
|
||||||
foreach ($budgets as $budget) {
|
|
||||||
$chart->addColumn($budget->name, 'number');
|
|
||||||
}
|
|
||||||
$chart->addColumn('No budget', 'number');
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loop budgets this year.
|
|
||||||
*/
|
|
||||||
$end = clone $start;
|
|
||||||
$end->endOfYear();
|
|
||||||
while ($start <= $end) {
|
|
||||||
$row = [clone $start];
|
|
||||||
|
|
||||||
foreach ($budgets as $budget) {
|
|
||||||
$row[] = $bdt->spentInMonth($budget, $start);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Without a budget:
|
|
||||||
*/
|
|
||||||
$endOfMonth = clone $start;
|
|
||||||
$endOfMonth->endOfMonth();
|
|
||||||
$set = $bdt->transactionsWithoutBudgetInDateRange($start, $endOfMonth);
|
|
||||||
$row[] = floatval($set->sum('amount')) * -1;
|
|
||||||
|
|
||||||
$chart->addRowArray($row);
|
|
||||||
$start->addMonth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$chart->generate();
|
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Component $component
|
|
||||||
* @param $year
|
* @param $year
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function componentsAndSpending(Component $component, $year)
|
public function budgetsAndSpending(Budget $budget, $year)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$start = new Carbon('01-01-' . $year);
|
new Carbon('01-01-' . $year);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
App::abort(500);
|
return View::make('error')->with('message', 'Invalid year.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($component->class == 'Budget') {
|
/** @var \FireflyIII\Database\Budget\Budget $budgetRepository */
|
||||||
/** @var \FireflyIII\Database\Budget $repos */
|
$budgetRepository = App::make('FireflyIII\Database\Budget\Budget');
|
||||||
$repos = App::make('FireflyIII\Database\Budget');
|
|
||||||
} else {
|
|
||||||
/** @var \FireflyIII\Database\Category $repos */
|
|
||||||
$repos = App::make('FireflyIII\Database\Category');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
$this->_chart->addColumn('Month', 'date');
|
||||||
$chart = App::make('gchart');
|
$this->_chart->addColumn('Budgeted', 'number');
|
||||||
$chart->addColumn('Month', 'date');
|
$this->_chart->addColumn('Spent', 'number');
|
||||||
$chart->addColumn('Budgeted', 'number');
|
|
||||||
$chart->addColumn('Spent', 'number');
|
|
||||||
|
|
||||||
$end = clone $start;
|
$start = new Carbon('01-01-' . $year);
|
||||||
|
$end = clone $start;
|
||||||
$end->endOfYear();
|
$end->endOfYear();
|
||||||
while ($start <= $end) {
|
while ($start <= $end) {
|
||||||
|
$spent = $budgetRepository->spentInMonth($budget, $start);
|
||||||
|
$repetition = $budgetRepository->repetitionOnStartingOnDate($budget, $start);
|
||||||
|
|
||||||
$spent = $repos->spentInMonth($component, $start);
|
|
||||||
$repetition = $repos->repetitionOnStartingOnDate($component, $start);
|
|
||||||
if ($repetition) {
|
if ($repetition) {
|
||||||
$budgeted = floatval($repetition->amount);
|
$budgeted = floatval($repetition->amount);
|
||||||
|
\Log::debug('Found a repetition on ' . $start->format('Y-m-d'). ' for budget ' . $budget->name.'!');
|
||||||
} else {
|
} else {
|
||||||
|
\Log::debug('No repetition on ' . $start->format('Y-m-d'). ' for budget ' . $budget->name);
|
||||||
$budgeted = null;
|
$budgeted = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$chart->addRow(clone $start, $budgeted, $spent);
|
$this->_chart->addRow(clone $start, $budgeted, $spent);
|
||||||
|
|
||||||
$start->addMonth();
|
$start->addMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$chart->generate();
|
$this->_chart->generate();
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggybank
|
*
|
||||||
|
* @param Category $component
|
||||||
|
* @param $year
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function piggyBankHistory(\Piggybank $piggybank)
|
public function categoriesAndSpending(Category $component, $year)
|
||||||
{
|
{
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
try {
|
||||||
$chart = App::make('gchart');
|
new Carbon('01-01-' . $year);
|
||||||
$chart->addColumn('Date', 'date');
|
} catch (Exception $e) {
|
||||||
$chart->addColumn('Balance', 'number');
|
return View::make('error')->with('message', 'Invalid year.');
|
||||||
|
}
|
||||||
|
|
||||||
$set = \DB::table('piggybank_events')->where('piggybank_id', $piggybank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]);
|
/** @var \FireflyIII\Database\Category\Category $categoryRepository */
|
||||||
|
$categoryRepository = App::make('FireflyIII\Database\Category\Category');
|
||||||
|
|
||||||
|
$this->_chart->addColumn('Month', 'date');
|
||||||
|
$this->_chart->addColumn('Budgeted', 'number');
|
||||||
|
$this->_chart->addColumn('Spent', 'number');
|
||||||
|
|
||||||
|
$start = new Carbon('01-01-' . $year);
|
||||||
|
$end = clone $start;
|
||||||
|
$end->endOfYear();
|
||||||
|
while ($start <= $end) {
|
||||||
|
|
||||||
|
$spent = $categoryRepository->spentInMonth($component, $start);
|
||||||
|
$budgeted = null;
|
||||||
|
|
||||||
|
$this->_chart->addRow(clone $start, $budgeted, $spent);
|
||||||
|
|
||||||
|
$start->addMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$this->_chart->generate();
|
||||||
|
|
||||||
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PiggyBank $piggyBank
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function piggyBankHistory(\PiggyBank $piggyBank)
|
||||||
|
{
|
||||||
|
$this->_chart->addColumn('Date', 'date');
|
||||||
|
$this->_chart->addColumn('Balance', 'number');
|
||||||
|
|
||||||
|
$set = \DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]);
|
||||||
|
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$chart->addRow(new Carbon($entry->date), floatval($entry->sum));
|
$this->_chart->addRow(new Carbon($entry->date), floatval($entry->sum));
|
||||||
}
|
}
|
||||||
|
|
||||||
$chart->generate();
|
$this->_chart->generate();
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RecurringTransaction $recurring
|
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function recurringOverview(RecurringTransaction $recurring)
|
|
||||||
{
|
|
||||||
|
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
|
||||||
$chart = App::make('gchart');
|
|
||||||
$chart->addColumn('Date', 'date');
|
|
||||||
$chart->addColumn('Max amount', 'number');
|
|
||||||
$chart->addColumn('Min amount', 'number');
|
|
||||||
$chart->addColumn('Current entry', 'number');
|
|
||||||
|
|
||||||
// get first transaction or today for start:
|
|
||||||
$first = $recurring->transactionjournals()->orderBy('date', 'ASC')->first();
|
|
||||||
if ($first) {
|
|
||||||
$start = $first->date;
|
|
||||||
} else {
|
|
||||||
$start = new Carbon;
|
|
||||||
}
|
|
||||||
$end = new Carbon;
|
|
||||||
while ($start <= $end) {
|
|
||||||
$result = $recurring->transactionjournals()->before($end)->after($start)->first();
|
|
||||||
if ($result) {
|
|
||||||
$amount = $result->getAmount();
|
|
||||||
} else {
|
|
||||||
$amount = 0;
|
|
||||||
}
|
|
||||||
unset($result);
|
|
||||||
$chart->addRow(clone $start, $recurring->amount_max, $recurring->amount_min, $amount);
|
|
||||||
$start = DateKit::addPeriod($start, $recurring->repeat_freq, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
$chart->generate();
|
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
* @throws \FireflyIII\Exception\FireflyException
|
|
||||||
*/
|
|
||||||
public function recurringTransactionsOverview()
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set of paid transaction journals.
|
|
||||||
* Set of unpaid recurring transactions.
|
|
||||||
*/
|
|
||||||
$paid = ['items' => [], 'amount' => 0];
|
|
||||||
$unpaid = ['items' => [], 'amount' => 0];
|
|
||||||
|
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
|
||||||
$chart = App::make('gchart');
|
|
||||||
$chart->addColumn('Name', 'string');
|
|
||||||
$chart->addColumn('Amount', 'number');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Recurring $rcr */
|
|
||||||
$rcr = App::make('FireflyIII\Database\Recurring');
|
|
||||||
|
|
||||||
$recurring = $rcr->get();
|
|
||||||
|
|
||||||
/** @var \RecurringTransaction $entry */
|
|
||||||
foreach ($recurring as $entry) {
|
|
||||||
/*
|
|
||||||
* Start another loop starting at the $date.
|
|
||||||
*/
|
|
||||||
$start = clone $entry->date;
|
|
||||||
$end = Carbon::now();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The jump we make depends on the $repeat_freq
|
|
||||||
*/
|
|
||||||
$current = clone $start;
|
|
||||||
|
|
||||||
while ($current <= $end) {
|
|
||||||
/*
|
|
||||||
* Get end of period for $current:
|
|
||||||
*/
|
|
||||||
$currentEnd = DateKit::endOfPeriod($current, $entry->repeat_freq);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In the current session range?
|
|
||||||
*/
|
|
||||||
if (\Session::get('end') >= $current and $currentEnd >= \Session::get('start')) {
|
|
||||||
/*
|
|
||||||
* Lets see if we've already spent money on this recurring transaction (it hath recurred).
|
|
||||||
*/
|
|
||||||
/** @var TransactionJournal $set */
|
|
||||||
$journal = $rcr->getJournalForRecurringInRange($entry, $current, $currentEnd);
|
|
||||||
|
|
||||||
if (is_null($journal)) {
|
|
||||||
$unpaid['items'][] = $entry->name;
|
|
||||||
$unpaid['amount'] += (($entry->amount_max + $entry->amount_min) / 2);
|
|
||||||
} else {
|
|
||||||
$amount = $journal->getAmount();
|
|
||||||
$paid['items'][] = $journal->description;
|
|
||||||
$paid['amount'] += $amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add some time for the next loop!
|
|
||||||
*/
|
|
||||||
$current = DateKit::addPeriod($current, $entry->repeat_freq, intval($entry->skip));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
/** @var \RecurringTransaction $entry */
|
|
||||||
$chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']);
|
|
||||||
$chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']);
|
|
||||||
|
|
||||||
$chart->generate();
|
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $year
|
* @param $year
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
@@ -679,37 +413,36 @@ class GoogleChartController extends BaseController
|
|||||||
try {
|
try {
|
||||||
$start = new Carbon('01-01-' . $year);
|
$start = new Carbon('01-01-' . $year);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
App::abort(500);
|
return View::make('error')->with('message', 'Invalid year.');
|
||||||
}
|
}
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
$this->_chart->addColumn('Month', 'date');
|
||||||
$chart = App::make('gchart');
|
$this->_chart->addColumn('Income', 'number');
|
||||||
$chart->addColumn('Month', 'date');
|
$this->_chart->addColumn('Expenses', 'number');
|
||||||
$chart->addColumn('Income', 'number');
|
|
||||||
$chart->addColumn('Expenses', 'number');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $tj */
|
/** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */
|
||||||
$tj = App::make('FireflyIII\Database\TransactionJournal');
|
$repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal');
|
||||||
|
|
||||||
$end = clone $start;
|
$end = clone $start;
|
||||||
$end->endOfYear();
|
$end->endOfYear();
|
||||||
while ($start < $end) {
|
while ($start < $end) {
|
||||||
|
|
||||||
// total income:
|
// total income:
|
||||||
$income = $tj->getSumOfIncomesByMonth($start);
|
$income = $repository->getSumOfIncomesByMonth($start);
|
||||||
$expense = $tj->getSumOfExpensesByMonth($start);
|
$expense = $repository->getSumOfExpensesByMonth($start);
|
||||||
|
|
||||||
$chart->addRow(clone $start, $income, $expense);
|
$this->_chart->addRow(clone $start, $income, $expense);
|
||||||
$start->addMonth();
|
$start->addMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$chart->generate();
|
$this->_chart->generate();
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @param $year
|
* @param $year
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
@@ -719,16 +452,14 @@ class GoogleChartController extends BaseController
|
|||||||
try {
|
try {
|
||||||
$start = new Carbon('01-01-' . $year);
|
$start = new Carbon('01-01-' . $year);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
App::abort(500);
|
return View::make('error')->with('message', 'Invalid year.');
|
||||||
}
|
}
|
||||||
/** @var \Grumpydictator\Gchart\GChart $chart */
|
$this->_chart->addColumn('Summary', 'string');
|
||||||
$chart = App::make('gchart');
|
$this->_chart->addColumn('Income', 'number');
|
||||||
$chart->addColumn('Summary', 'string');
|
$this->_chart->addColumn('Expenses', 'number');
|
||||||
$chart->addColumn('Income', 'number');
|
|
||||||
$chart->addColumn('Expenses', 'number');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $tj */
|
/** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */
|
||||||
$tj = App::make('FireflyIII\Database\TransactionJournal');
|
$repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal');
|
||||||
|
|
||||||
$end = clone $start;
|
$end = clone $start;
|
||||||
$end->endOfYear();
|
$end->endOfYear();
|
||||||
@@ -738,20 +469,20 @@ class GoogleChartController extends BaseController
|
|||||||
while ($start < $end) {
|
while ($start < $end) {
|
||||||
|
|
||||||
// total income:
|
// total income:
|
||||||
$income += $tj->getSumOfIncomesByMonth($start);
|
$income += $repository->getSumOfIncomesByMonth($start);
|
||||||
$expense += $tj->getSumOfExpensesByMonth($start);
|
$expense += $repository->getSumOfExpensesByMonth($start);
|
||||||
$count++;
|
$count++;
|
||||||
|
|
||||||
$start->addMonth();
|
$start->addMonth();
|
||||||
}
|
}
|
||||||
$chart->addRow('Sum', $income, $expense);
|
$this->_chart->addRow('Sum', $income, $expense);
|
||||||
$count = $count > 0 ? $count : 1;
|
$count = $count > 0 ? $count : 1;
|
||||||
$chart->addRow('Average', ($income / $count), ($expense / $count));
|
$this->_chart->addRow('Average', ($income / $count), ($expense / $count));
|
||||||
|
|
||||||
|
|
||||||
$chart->generate();
|
$this->_chart->generate();
|
||||||
|
|
||||||
return Response::json($chart->getData());
|
return Response::json($this->_chart->getData());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
*
|
||||||
* Class HelpController
|
* Class HelpController
|
||||||
*/
|
*/
|
||||||
class HelpController extends BaseController
|
class HelpController extends BaseController
|
||||||
@@ -12,15 +14,13 @@ class HelpController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function show($route)
|
public function show($route)
|
||||||
{
|
{
|
||||||
// no valid route
|
$helpText = '<p>There is no help for this route!</p>';
|
||||||
|
$helpTitle = 'Help';
|
||||||
if (!Route::has($route)) {
|
if (!Route::has($route)) {
|
||||||
$helpText = '<p>There is no help for this route!</p>';
|
\Log::error('No such route: ' . $route);
|
||||||
$helpTitle = 'Help';
|
|
||||||
|
|
||||||
return Response::json(['title' => $helpTitle, 'text' => $helpText]);
|
return Response::json(['title' => $helpTitle, 'text' => $helpText]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// content in cache
|
|
||||||
if (Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text')) {
|
if (Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text')) {
|
||||||
$helpText = Cache::get('help.' . $route . '.text');
|
$helpText = Cache::get('help.' . $route . '.text');
|
||||||
$helpTitle = Cache::get('help.' . $route . '.title');
|
$helpTitle = Cache::get('help.' . $route . '.title');
|
||||||
@@ -28,27 +28,27 @@ class HelpController extends BaseController
|
|||||||
return Response::json(['title' => $helpTitle, 'text' => $helpText]);
|
return Response::json(['title' => $helpTitle, 'text' => $helpText]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the help-content from Github:
|
$uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md';
|
||||||
$URL = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md';
|
\Log::debug('URL is: ' . $uri);
|
||||||
try {
|
try {
|
||||||
$content = file_get_contents($URL);
|
$helpText = file_get_contents($uri);
|
||||||
} catch (ErrorException $e) {
|
} catch (ErrorException $e) {
|
||||||
$content = '<p>There is no help for this route.</p>';
|
\Log::error(trim($e->getMessage()));
|
||||||
}
|
}
|
||||||
if (strlen($content) > 0) {
|
\Log::debug('Found help for ' . $route);
|
||||||
$helpText = \Michelf\Markdown::defaultTransform($content);
|
\Log::debug('Help text length for route ' . $route . ' is ' . strlen($helpText));
|
||||||
$helpTitle = $route;
|
\Log::debug('Help text IS: "' . $helpText . '".');
|
||||||
|
if (strlen(trim($helpText)) == 0) {
|
||||||
Cache::put('help.' . $route . '.text', $helpText, 10080); // a week.
|
$helpText = '<p>There is no help for this route.</p>';
|
||||||
Cache::put('help.' . $route . '.title', $helpTitle, 10080);
|
|
||||||
|
|
||||||
return Response::json(['title' => $helpTitle, 'text' => $helpText]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$helpText = '<p>There is no help for this route!</p>';
|
$helpText = \Michelf\Markdown::defaultTransform($helpText);
|
||||||
$helpTitle = 'Help';
|
$helpTitle = $route;
|
||||||
|
|
||||||
|
Cache::put('help.' . $route . '.text', $helpText, 10080); // a week.
|
||||||
|
Cache::put('help.' . $route . '.title', $helpTitle, 10080);
|
||||||
|
|
||||||
return Response::json(['title' => $helpTitle, 'text' => $helpText]);
|
return Response::json(['title' => $helpTitle, 'text' => $helpText]);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class HomeController
|
* Class HomeController
|
||||||
@@ -6,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
class HomeController extends BaseController
|
class HomeController extends BaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
@@ -22,32 +24,32 @@ class HomeController extends BaseController
|
|||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
// count, maybe Firefly needs some introducing text to show:
|
// count, maybe Firefly needs some introducing text to show:
|
||||||
/** @var \FireflyIII\Database\Account $acct */
|
/** @var \FireflyIII\Database\Account\Account $acct */
|
||||||
$acct = App::make('FireflyIII\Database\Account');
|
$acct = App::make('FireflyIII\Database\Account\Account');
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $jrnls */
|
/** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $journalRepository */
|
||||||
$jrnls = App::make('FireflyIII\Database\TransactionJournal');
|
$journalRepository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal');
|
||||||
|
|
||||||
/** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
|
/** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
|
||||||
$preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
|
$preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
|
||||||
|
|
||||||
$count = $acct->countAssetAccounts();
|
$count = $acct->countAssetAccounts();
|
||||||
|
|
||||||
$start = Session::get('start');
|
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||||
$end = Session::get('end');
|
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||||
|
|
||||||
|
|
||||||
// get the preference for the home accounts to show:
|
// get the preference for the home accounts to show:
|
||||||
$frontpage = $preferences->get('frontpageAccounts', []);
|
$frontPage = $preferences->get('frontPageAccounts', []);
|
||||||
if ($frontpage->data == []) {
|
if ($frontPage->data == []) {
|
||||||
$accounts = $acct->getAssetAccounts();
|
$accounts = $acct->getAssetAccounts();
|
||||||
} else {
|
} else {
|
||||||
$accounts = $acct->getByIds($frontpage->data);
|
$accounts = $acct->getByIds($frontPage->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
$transactions = [];
|
$transactions = [];
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$set = $jrnls->getInDateRangeAccount($account, 10, $start, $end);
|
$set = $journalRepository->getInDateRangeAccount($account, $start, $end, 10);
|
||||||
if (count($set) > 0) {
|
if (count($set) > 0) {
|
||||||
$transactions[] = [$set, $account];
|
$transactions[] = [$set, $account];
|
||||||
}
|
}
|
||||||
@@ -76,7 +78,7 @@ class HomeController extends BaseController
|
|||||||
Session::forget('range');
|
Session::forget('range');
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::back();
|
return Redirect::intended('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,7 +88,7 @@ class HomeController extends BaseController
|
|||||||
{
|
{
|
||||||
Navigation::next();
|
Navigation::next();
|
||||||
|
|
||||||
return Redirect::back();
|
return Redirect::intended('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,6 +98,6 @@ class HomeController extends BaseController
|
|||||||
{
|
{
|
||||||
Navigation::prev();
|
Navigation::prev();
|
||||||
|
|
||||||
return Redirect::back();
|
return Redirect::intended('/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ class JsonController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function categories()
|
public function categories()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Category $categories */
|
/** @var \FireflyIII\Database\Category\Category $categories */
|
||||||
$categories = App::make('FireflyIII\Database\Category');
|
$categories = App::make('FireflyIII\Database\Category\Category');
|
||||||
$list = $categories->get();
|
$list = $categories->get();
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($list as $entry) {
|
foreach ($list as $entry) {
|
||||||
@@ -34,8 +34,8 @@ class JsonController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function expenseAccounts()
|
public function expenseAccounts()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Account $accounts */
|
/** @var \FireflyIII\Database\Account\Account $accounts */
|
||||||
$accounts = App::make('FireflyIII\Database\Account');
|
$accounts = App::make('FireflyIII\Database\Account\Account');
|
||||||
$list = $accounts->getExpenseAccounts();
|
$list = $accounts->getExpenseAccounts();
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($list as $entry) {
|
foreach ($list as $entry) {
|
||||||
@@ -51,8 +51,8 @@ class JsonController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function revenueAccounts()
|
public function revenueAccounts()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Account $accounts */
|
/** @var \FireflyIII\Database\Account\Account $accounts */
|
||||||
$accounts = App::make('FireflyIII\Database\Account');
|
$accounts = App::make('FireflyIII\Database\Account\Account');
|
||||||
$list = $accounts->getRevenueAccounts();
|
$list = $accounts->getRevenueAccounts();
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($list as $entry) {
|
foreach ($list as $entry) {
|
||||||
@@ -62,4 +62,4 @@ class JsonController extends BaseController
|
|||||||
return Response::json($return);
|
return Response::json($return);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,55 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Database\PiggyBank\PiggyBank as Repository;
|
||||||
use FireflyIII\Exception\FireflyException;
|
use FireflyIII\Exception\FireflyException;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PiggybankController
|
*
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
* @SuppressWarnings("TooManyMethods") // I'm also fine with this.
|
||||||
|
* @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Class PiggyBankController
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class PiggybankController extends BaseController
|
class PiggyBankController extends BaseController
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/** @var Repository */
|
||||||
|
protected $_repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param Repository $repository
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(Repository $repository)
|
||||||
{
|
{
|
||||||
|
$this->_repository = $repository;
|
||||||
|
View::share('title', 'Piggy banks');
|
||||||
|
View::share('mainTitleIcon', 'fa-sort-amount-asc');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add money to piggy bank
|
* Add money to piggy bank
|
||||||
*
|
*
|
||||||
* @param Piggybank $piggybank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function add(Piggybank $piggybank)
|
public function add(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Piggybank $repos */
|
$leftOnAccount = $this->_repository->leftOnAccount($piggyBank->account);
|
||||||
$repos = App::make('FireflyIII\Database\Piggybank');
|
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||||
|
$leftToSave = $piggyBank->targetamount - $savedSoFar;
|
||||||
$leftOnAccount = $repos->leftOnAccount($piggybank->account);
|
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||||
$savedSoFar = $piggybank->currentRelevantRep()->currentamount;
|
|
||||||
$leftToSave = $piggybank->targetamount - $savedSoFar;
|
|
||||||
$amount = min($leftOnAccount, $leftToSave);
|
|
||||||
|
|
||||||
|
|
||||||
return View::make('piggybanks.add', compact('piggybank'))->with('maxAmount', $amount);
|
\Log::debug('Now going to view for piggy bank #' . $piggyBank->id . ' (' . $piggyBank->name . ')');
|
||||||
|
|
||||||
|
return View::make('piggy_banks.add', compact('piggyBank', 'maxAmount'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,76 +58,78 @@ class PiggybankController extends BaseController
|
|||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Account $acct */
|
/** @var \FireflyIII\Database\Account\Account $acct */
|
||||||
$acct = App::make('FireflyIII\Database\Account');
|
$acct = App::make('FireflyIII\Database\Account\Account');
|
||||||
|
|
||||||
$periods = Config::get('firefly.piggybank_periods');
|
$periods = Config::get('firefly.piggy_bank_periods');
|
||||||
|
$accounts = FFForm::makeSelectList($acct->getAssetAccounts());
|
||||||
|
$subTitle = 'Create new piggy bank';
|
||||||
|
$subTitleIcon = 'fa-plus';
|
||||||
|
|
||||||
|
return View::make('piggy_banks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon'));
|
||||||
$accounts = FFForm::makeSelectList($acct->getAssetAccounts());
|
|
||||||
|
|
||||||
return View::make('piggybanks.create', compact('accounts', 'periods'))->with('title', 'Piggy banks')->with('mainTitleIcon', 'fa-sort-amount-asc')->with(
|
|
||||||
'subTitle', 'Create new piggy bank'
|
|
||||||
)->with('subTitleIcon', 'fa-plus');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggybank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function delete(Piggybank $piggybank)
|
public function delete(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
return View::make('piggybanks.delete')->with('piggybank', $piggybank)->with('subTitle', 'Delete "' . $piggybank->name . '"')->with(
|
$subTitle = 'Delete "' . e($piggyBank->name) . '"';
|
||||||
'title', 'Piggy banks'
|
|
||||||
)->with('mainTitleIcon', 'fa-sort-amount-asc');
|
return View::make('piggy_banks.delete', compact('piggyBank', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggyBank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function destroy(Piggybank $piggyBank)
|
public function destroy(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Piggybank $acct */
|
|
||||||
$repos = App::make('FireflyIII\Database\Piggybank');
|
|
||||||
$repos->destroy($piggyBank);
|
|
||||||
Session::flash('success', 'Piggy bank deleted.');
|
|
||||||
|
|
||||||
return Redirect::route('piggybanks.index');
|
Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.');
|
||||||
|
$this->_repository->destroy($piggyBank);
|
||||||
|
|
||||||
|
return Redirect::route('piggy_banks.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggybank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function edit(Piggybank $piggybank)
|
public function edit(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Account $acct */
|
/** @var \FireflyIII\Database\Account\Account $acct */
|
||||||
$acct = App::make('FireflyIII\Database\Account');
|
$acct = App::make('FireflyIII\Database\Account\Account');
|
||||||
|
|
||||||
$periods = Config::get('firefly.piggybank_periods');
|
$periods = Config::get('firefly.piggy_bank_periods');
|
||||||
|
$accounts = FFForm::makeSelectList($acct->getAssetAccounts());
|
||||||
$accounts = FFForm::makeSelectList($acct->getAssetAccounts());
|
$subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"';
|
||||||
|
$subTitleIcon = 'fa-pencil';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flash some data to fill the form.
|
* Flash some data to fill the form.
|
||||||
*/
|
*/
|
||||||
$preFilled = ['name' => $piggybank->name,
|
if (is_null($piggyBank->targetdate) || $piggyBank->targetdate == '') {
|
||||||
'account_id' => $piggybank->account_id,
|
$targetDate = null;
|
||||||
'targetamount' => $piggybank->targetamount,
|
} else {
|
||||||
'targetdate' => !is_null($piggybank->targetdate) ? $piggybank->targetdate->format('Y-m-d') : null,
|
$targetDate = new Carbon($piggyBank->targetdate);
|
||||||
'reminder' => $piggybank->reminder,
|
$targetDate = $targetDate->format('Y-m-d');
|
||||||
'remind_me' => intval($piggybank->remind_me) == 1 || !is_null($piggybank->reminder) ? true : false
|
}
|
||||||
|
$preFilled = ['name' => $piggyBank->name,
|
||||||
|
'account_id' => $piggyBank->account_id,
|
||||||
|
'targetamount' => $piggyBank->targetamount,
|
||||||
|
'targetdate' => $targetDate,
|
||||||
|
'reminder' => $piggyBank->reminder,
|
||||||
|
'remind_me' => intval($piggyBank->remind_me) == 1 || !is_null($piggyBank->reminder) ? true : false
|
||||||
];
|
];
|
||||||
Session::flash('preFilled', $preFilled);
|
Session::flash('preFilled', $preFilled);
|
||||||
|
|
||||||
return View::make('piggybanks.edit', compact('piggybank', 'accounts', 'periods', 'preFilled'))->with('title', 'Piggybanks')->with(
|
return View::make('piggy_banks.edit', compact('subTitle', 'subTitleIcon', 'piggyBank', 'accounts', 'periods', 'preFilled'));
|
||||||
'mainTitleIcon', 'fa-sort-amount-asc'
|
|
||||||
)->with('subTitle', 'Edit piggy bank "' . e($piggybank->name) . '"')->with('subTitleIcon', 'fa-pencil');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,135 +137,134 @@ class PiggybankController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Piggybank $repos */
|
/** @var Collection $piggyBanks */
|
||||||
$repos = App::make('FireflyIII\Database\Piggybank');
|
$piggyBanks = $this->_repository->get();
|
||||||
|
|
||||||
/** @var Collection $piggybanks */
|
|
||||||
$piggybanks = $repos->get();
|
|
||||||
|
|
||||||
$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 = intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100);
|
||||||
$piggybank->leftToSave = $piggybank->targetamount - $piggybank->savedSoFar;
|
$piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill account information:
|
* Fill account information:
|
||||||
*/
|
*/
|
||||||
$account = $piggybank->account;
|
$account = $piggyBank->account;
|
||||||
if (!isset($accounts[$account->id])) {
|
if (!isset($accounts[$account->id])) {
|
||||||
$accounts[$account->id] = ['name' => $account->name, 'balance' => Steam::balance($account),
|
$accounts[$account->id] = [
|
||||||
'leftForPiggybanks' => $repos->leftOnAccount($account), 'sumOfSaved' => $piggybank->savedSoFar,
|
'name' => $account->name,
|
||||||
'sumOfTargets' => floatval($piggybank->targetamount), 'leftToSave' => $piggybank->leftToSave];
|
'balance' => Steam::balance($account),
|
||||||
|
'leftForPiggyBanks' => $this->_repository->leftOnAccount($account),
|
||||||
|
'sumOfSaved' => $piggyBank->savedSoFar,
|
||||||
|
'sumOfTargets' => floatval($piggyBank->targetamount),
|
||||||
|
'leftToSave' => $piggyBank->leftToSave
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
$accounts[$account->id]['sumOfSaved'] += $piggybank->savedSoFar;
|
$accounts[$account->id]['sumOfSaved'] += $piggyBank->savedSoFar;
|
||||||
$accounts[$account->id]['sumOfTargets'] += floatval($piggybank->targetamount);
|
$accounts[$account->id]['sumOfTargets'] += floatval($piggyBank->targetamount);
|
||||||
$accounts[$account->id]['leftToSave'] += $piggybank->leftToSave;
|
$accounts[$account->id]['leftToSave'] += $piggyBank->leftToSave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return View::make('piggybanks.index', compact('piggybanks', 'accounts'))->with('title', 'Piggy banks')->with('mainTitleIcon', 'fa-sort-amount-asc');
|
return View::make('piggy_banks.index', compact('piggyBanks', 'accounts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST add money to piggy bank
|
* POST add money to piggy bank
|
||||||
*
|
*
|
||||||
* @param Piggybank $piggybank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function postAdd(Piggybank $piggybank)
|
public function postAdd(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
$amount = round(floatval(Input::get('amount')), 2);
|
$amount = round(floatval(Input::get('amount')), 2);
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Piggybank $acct */
|
/** @var \FireflyIII\Database\PiggyBank\PiggyBank $acct */
|
||||||
$repos = App::make('FireflyIII\Database\Piggybank');
|
$piggyRepository = App::make('FireflyIII\Database\PiggyBank\PiggyBank');
|
||||||
|
|
||||||
$leftOnAccount = $repos->leftOnAccount($piggybank->account);
|
$leftOnAccount = $piggyRepository->leftOnAccount($piggyBank->account);
|
||||||
$savedSoFar = $piggybank->currentRelevantRep()->currentamount;
|
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||||
$leftToSave = $piggybank->targetamount - $savedSoFar;
|
$leftToSave = $piggyBank->targetamount - $savedSoFar;
|
||||||
$maxAmount = round(min($leftOnAccount, $leftToSave), 2);
|
$maxAmount = round(min($leftOnAccount, $leftToSave), 2);
|
||||||
|
|
||||||
if ($amount <= $maxAmount) {
|
if ($amount <= $maxAmount) {
|
||||||
$repetition = $piggybank->currentRelevantRep();
|
$repetition = $piggyBank->currentRelevantRep();
|
||||||
$repetition->currentamount += $amount;
|
$repetition->currentamount += $amount;
|
||||||
$repetition->save();
|
$repetition->save();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create event!
|
* Create event!
|
||||||
*/
|
*/
|
||||||
Event::fire('piggybank.addMoney', [$piggybank, $amount]); // new and used.
|
Event::fire('piggy_bank.addMoney', [$piggyBank, $amount]); // new and used.
|
||||||
|
|
||||||
Session::flash('success', 'Added ' . mf($amount, false) . ' to "' . e($piggybank->name) . '".');
|
Session::flash('success', 'Added ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
|
||||||
} else {
|
} else {
|
||||||
Session::flash('error', 'Could not add ' . mf($amount, false) . ' to "' . e($piggybank->name) . '".');
|
Session::flash('error', 'Could not add ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::route('piggybanks.index');
|
return Redirect::route('piggy_banks.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggybank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function postRemove(Piggybank $piggybank)
|
public function postRemove(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
$amount = floatval(Input::get('amount'));
|
$amount = floatval(Input::get('amount'));
|
||||||
|
|
||||||
$savedSoFar = $piggybank->currentRelevantRep()->currentamount;
|
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||||
|
|
||||||
if ($amount <= $savedSoFar) {
|
if ($amount <= $savedSoFar) {
|
||||||
$repetition = $piggybank->currentRelevantRep();
|
$repetition = $piggyBank->currentRelevantRep();
|
||||||
$repetition->currentamount -= $amount;
|
$repetition->currentamount -= $amount;
|
||||||
$repetition->save();
|
$repetition->save();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create event!
|
* Create event!
|
||||||
*/
|
*/
|
||||||
Event::fire('piggybank.removeMoney', [$piggybank, $amount]); // new and used.
|
Event::fire('piggy_bank.removeMoney', [$piggyBank, $amount]); // new and used.
|
||||||
|
|
||||||
Session::flash('success', 'Removed ' . mf($amount, false) . ' from "' . e($piggybank->name) . '".');
|
Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
|
||||||
} else {
|
} else {
|
||||||
Session::flash('error', 'Could not remove ' . mf($amount, false) . ' from "' . e($piggybank->name) . '".');
|
Session::flash('error', 'Could not remove ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::route('piggybanks.index');
|
return Redirect::route('piggy_banks.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggybank
|
* @param PiggyBank $piggyBank
|
||||||
|
*
|
||||||
|
* @SuppressWarnings("Unused")
|
||||||
*
|
*
|
||||||
* @return \Illuminate\View\View
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function remove(Piggybank $piggybank)
|
public function remove(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
return View::make('piggybanks.remove', compact('piggybank'));
|
return View::make('piggy_banks.remove', compact('piggyBank'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggybank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function show(Piggybank $piggybank)
|
public function show(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
|
|
||||||
$events = $piggybank->piggybankevents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
|
$events = $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of reminders:
|
* Number of reminders:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$amountPerReminder = $piggybank->amountPerReminder();
|
$subTitle = e($piggyBank->name);
|
||||||
$remindersCount = $piggybank->countFutureReminders();
|
|
||||||
|
|
||||||
return View::make('piggybanks.show', compact('amountPerReminder', 'remindersCount', 'piggybank', 'events'))->with('title', 'Piggy banks')->with(
|
return View::make('piggy_banks.show', compact('piggyBank', 'events', 'subTitle'));
|
||||||
'mainTitleIcon', 'fa-sort-amount-asc'
|
|
||||||
)->with(
|
|
||||||
'subTitle', $piggybank->name
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,101 +273,86 @@ class PiggybankController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
$data = Input::all();
|
$data = Input::all();
|
||||||
$data['repeats'] = 0;
|
$data['repeats'] = 0;
|
||||||
/** @var \FireflyIII\Database\Piggybank $repos */
|
$data['user_id'] = Auth::user()->id;
|
||||||
$repos = App::make('FireflyIII\Database\Piggybank');
|
$data['rep_every'] = 0;
|
||||||
|
$data['reminder_skip'] = 0;
|
||||||
|
$data['remind_me'] = intval(Input::get('remind_me'));
|
||||||
|
$data['order'] = 0;
|
||||||
|
|
||||||
switch ($data['post_submit_action']) {
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
|
|
||||||
break;
|
|
||||||
case 'create_another':
|
|
||||||
case 'store':
|
|
||||||
$messages = $repos->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save piggy bank: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('piggybanks.create')->withInput()->withErrors($messages['errors']);
|
// always validate:
|
||||||
}
|
$messages = $this->_repository->validate($data);
|
||||||
// store!
|
|
||||||
$piggyBank = $repos->store($data);
|
|
||||||
|
|
||||||
/*
|
// flash messages:
|
||||||
* Create the relevant repetition per Event.
|
Session::flash('warnings', $messages['warnings']);
|
||||||
*/
|
Session::flash('successes', $messages['successes']);
|
||||||
Event::fire('piggybank.store', [$piggyBank]); // new and used.
|
Session::flash('errors', $messages['errors']);
|
||||||
|
if ($messages['errors']->count() > 0) {
|
||||||
Session::flash('success', 'New piggy bank stored!');
|
Session::flash('error', 'Could not store piggy bank: ' . $messages['errors']->first());
|
||||||
|
|
||||||
if ($data['post_submit_action'] == 'create_another') {
|
|
||||||
return Redirect::route('piggybanks.create')->withInput();
|
|
||||||
} else {
|
|
||||||
return Redirect::route('piggybanks.index');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('piggybanks.create')->withInput();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// return to create screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('piggy_banks.create')->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
$piggyBank = $this->_repository->store($data);
|
||||||
|
Event::fire('piggy_bank.store', [$piggyBank]); // new and used.
|
||||||
|
Session::flash('success', 'Piggy bank "' . e($data['name']) . '" stored.');
|
||||||
|
if ($data['post_submit_action'] == 'store') {
|
||||||
|
return Redirect::route('piggy_banks.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('piggy_banks.create')->withInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggyBank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function update(Piggybank $piggyBank)
|
public function update(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Piggybank $repos */
|
$data = Input::except('_token');
|
||||||
$repos = App::make('FireflyIII\Database\Piggybank');
|
$data['rep_every'] = 0;
|
||||||
$data = Input::except('_token');
|
$data['reminder_skip'] = 0;
|
||||||
|
$data['order'] = 0;
|
||||||
|
$data['remind_me'] = isset($data['remind_me']) ? 1 : 0;
|
||||||
|
$data['user_id'] = Auth::user()->id;
|
||||||
|
$data['repeats'] = 0;
|
||||||
|
|
||||||
switch (Input::get('post_submit_action')) {
|
// always validate:
|
||||||
default:
|
$messages = $this->_repository->validate($data);
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"');
|
|
||||||
break;
|
|
||||||
case 'return_to_edit':
|
|
||||||
case 'update':
|
|
||||||
$messages = $repos->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save piggy bank: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('piggybanks.edit', $piggyBank->id)->withInput()->withErrors($messages['errors']);
|
Session::flash('warnings', $messages['warnings']);
|
||||||
}
|
Session::flash('successes', $messages['successes']);
|
||||||
// store!
|
Session::flash('errors', $messages['errors']);
|
||||||
$repos->update($piggyBank, $data);
|
if ($messages['errors']->count() > 0) {
|
||||||
Event::fire('piggybank.update', [$piggyBank]); // new and used.
|
Session::flash('error', 'Could not update piggy bank: ' . $messages['errors']->first());
|
||||||
Session::flash('success', 'Piggy bank updated!');
|
|
||||||
|
|
||||||
if ($data['post_submit_action'] == 'return_to_edit') {
|
|
||||||
return Redirect::route('piggybanks.edit', $piggyBank->id);
|
|
||||||
} else {
|
|
||||||
return Redirect::route('piggybanks.index');
|
|
||||||
}
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('piggybanks.edit', $piggyBank->id)->withInput();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return to update screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('piggy_banks.edit', $piggyBank->id)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
$this->_repository->update($piggyBank, $data);
|
||||||
|
Session::flash('success', 'Piggy bank "' . e($data['name']) . '" updated.');
|
||||||
|
|
||||||
|
// go back to list
|
||||||
|
if ($data['post_submit_action'] == 'update') {
|
||||||
|
return Redirect::route('piggy_banks.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// go back to update screen.
|
||||||
|
return Redirect::route('piggy_banks.edit', $piggyBank->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
/**
|
/**
|
||||||
* Class PreferencesController
|
* Class PreferencesController
|
||||||
*
|
*
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class PreferencesController extends BaseController
|
class PreferencesController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -21,8 +23,8 @@ class PreferencesController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Account $acct */
|
/** @var \FireflyIII\Database\Account\Account $acct */
|
||||||
$acct = App::make('FireflyIII\Database\Account');
|
$acct = App::make('FireflyIII\Database\Account\Account');
|
||||||
|
|
||||||
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
|
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
|
||||||
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
|
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
|
||||||
@@ -30,9 +32,13 @@ class PreferencesController extends BaseController
|
|||||||
$accounts = $acct->getAssetAccounts();
|
$accounts = $acct->getAssetAccounts();
|
||||||
$viewRange = $preferences->get('viewRange', '1M');
|
$viewRange = $preferences->get('viewRange', '1M');
|
||||||
$viewRangeValue = $viewRange->data;
|
$viewRangeValue = $viewRange->data;
|
||||||
$frontpage = $preferences->get('frontpageAccounts', []);
|
$frontPage = $preferences->get('frontPageAccounts', []);
|
||||||
|
$budgetMax = $preferences->get('budgetMaximum', 1000);
|
||||||
|
$budgetMaximum = $budgetMax->data;
|
||||||
|
|
||||||
return View::make('preferences.index')->with('accounts', $accounts)->with('frontpageAccounts', $frontpage)->with('viewRange', $viewRangeValue);
|
return View::make('preferences.index', compact('budgetMaximum'))->with('accounts', $accounts)->with('frontPageAccounts', $frontPage)->with(
|
||||||
|
'viewRange', $viewRangeValue
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,16 +46,15 @@ class PreferencesController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function postIndex()
|
public function postIndex()
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
|
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
|
||||||
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
|
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
|
||||||
|
|
||||||
// frontpage accounts
|
// front page accounts
|
||||||
$frontpageAccounts = [];
|
$frontPageAccounts = [];
|
||||||
foreach (Input::get('frontpageAccounts') as $id) {
|
foreach (Input::get('frontPageAccounts') as $id) {
|
||||||
$frontpageAccounts[] = intval($id);
|
$frontPageAccounts[] = intval($id);
|
||||||
}
|
}
|
||||||
$preferences->set('frontpageAccounts', $frontpageAccounts);
|
$preferences->set('frontPageAccounts', $frontPageAccounts);
|
||||||
|
|
||||||
// view range:
|
// view range:
|
||||||
$preferences->set('viewRange', Input::get('viewRange'));
|
$preferences->set('viewRange', Input::get('viewRange'));
|
||||||
@@ -58,9 +63,14 @@ class PreferencesController extends BaseController
|
|||||||
Session::forget('end');
|
Session::forget('end');
|
||||||
Session::forget('range');
|
Session::forget('range');
|
||||||
|
|
||||||
|
// budget maximum:
|
||||||
|
$budgetMaximum = intval(Input::get('budgetMaximum'));
|
||||||
|
$preferences->set('budgetMaximum', $budgetMaximum);
|
||||||
|
|
||||||
|
|
||||||
Session::flash('success', 'Preferences saved!');
|
Session::flash('success', 'Preferences saved!');
|
||||||
|
|
||||||
return Redirect::route('preferences');
|
return Redirect::route('preferences');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
*
|
||||||
* Class ProfileController
|
* Class ProfileController
|
||||||
*/
|
*/
|
||||||
class ProfileController extends BaseController
|
class ProfileController extends BaseController
|
||||||
@@ -32,7 +34,6 @@ class ProfileController extends BaseController
|
|||||||
{
|
{
|
||||||
|
|
||||||
// old, new1, new2
|
// old, new1, new2
|
||||||
/** @noinspection PhpUndefinedFieldInspection */
|
|
||||||
if (!Hash::check(Input::get('old'), Auth::user()->password)) {
|
if (!Hash::check(Input::get('old'), Auth::user()->password)) {
|
||||||
Session::flash('error', 'Invalid current password!');
|
Session::flash('error', 'Invalid current password!');
|
||||||
|
|
||||||
@@ -56,8 +57,8 @@ class ProfileController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update the user with the new password.
|
// update the user with the new password.
|
||||||
/** @var \FireflyIII\Database\User $repository */
|
/** @var \FireflyIII\Database\User\User $repository */
|
||||||
$repository = \App::make('FireflyIII\Database\User');
|
$repository = \App::make('FireflyIII\Database\User\User');
|
||||||
$repository->updatePassword(Auth::user(), Input::get('new1'));
|
$repository->updatePassword(Auth::user(), Input::get('new1'));
|
||||||
|
|
||||||
Session::flash('success', 'Password changed!');
|
Session::flash('success', 'Password changed!');
|
||||||
@@ -65,4 +66,4 @@ class ProfileController extends BaseController
|
|||||||
return Redirect::route('profile');
|
return Redirect::route('profile');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,225 +0,0 @@
|
|||||||
<?php
|
|
||||||
use FireflyIII\Exception\FireflyException;
|
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class RecurringController
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class RecurringController extends BaseController
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
|
|
||||||
View::share('title', 'Recurring transactions');
|
|
||||||
View::share('mainTitleIcon', 'fa-rotate-right');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$periods = \Config::get('firefly.periods_to_text');
|
|
||||||
|
|
||||||
return View::make('recurring.create')->with('periods', $periods)->with('subTitle', 'Create new');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RecurringTransaction $recurringTransaction
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function delete(RecurringTransaction $recurringTransaction)
|
|
||||||
{
|
|
||||||
return View::make('recurring.delete')->with('recurringTransaction', $recurringTransaction)->with(
|
|
||||||
'subTitle', 'Delete "' . $recurringTransaction->name . '"'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RecurringTransaction $recurringTransaction
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
|
||||||
*/
|
|
||||||
public function destroy(RecurringTransaction $recurringTransaction)
|
|
||||||
{
|
|
||||||
//Event::fire('recurring.destroy', [$recurringTransaction]);
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Recurring $repository */
|
|
||||||
$repository = App::make('FireflyIII\Database\Recurring');
|
|
||||||
|
|
||||||
$result = $repository->destroy($recurringTransaction);
|
|
||||||
if ($result === true) {
|
|
||||||
Session::flash('success', 'The recurring transaction was deleted.');
|
|
||||||
} else {
|
|
||||||
Session::flash('error', 'Could not delete the recurring transaction. Check the logs to be sure.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return Redirect::route('recurring.index');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RecurringTransaction $recurringTransaction
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function edit(RecurringTransaction $recurringTransaction)
|
|
||||||
{
|
|
||||||
$periods = \Config::get('firefly.periods_to_text');
|
|
||||||
|
|
||||||
return View::make('recurring.edit')->with('periods', $periods)->with('recurringTransaction', $recurringTransaction)->with(
|
|
||||||
'subTitle', 'Edit "' . $recurringTransaction->name . '"'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
/** @var \FireflyIII\Database\Recurring $repos */
|
|
||||||
$repos = App::make('FireflyIII\Database\Recurring');
|
|
||||||
|
|
||||||
$recurring = $repos->get();
|
|
||||||
|
|
||||||
return View::make('recurring.index', compact('recurring'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RecurringTransaction $recurringTransaction
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function rescan(RecurringTransaction $recurringTransaction)
|
|
||||||
{
|
|
||||||
if (intval($recurringTransaction->active) == 0) {
|
|
||||||
Session::flash('warning', 'Inactive recurring transactions cannot be scanned.');
|
|
||||||
|
|
||||||
return Redirect::back();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Recurring $repos */
|
|
||||||
$repos = App::make('FireflyIII\Database\Recurring');
|
|
||||||
$repos->scanEverything($recurringTransaction);
|
|
||||||
|
|
||||||
Session::flash('success', 'Rescanned everything.');
|
|
||||||
|
|
||||||
return Redirect::back();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RecurringTransaction $recurringTransaction
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function show(RecurringTransaction $recurringTransaction)
|
|
||||||
{
|
|
||||||
$journals = $recurringTransaction->transactionjournals()->withRelevantData()->orderBy('date', 'DESC')->get();
|
|
||||||
$hideRecurring = true;
|
|
||||||
|
|
||||||
|
|
||||||
return View::make('recurring.show', compact('journals', 'hideRecurring', 'finalDate'))->with('recurring', $recurringTransaction)->with(
|
|
||||||
'subTitle', $recurringTransaction->name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return $this
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public function store()
|
|
||||||
{
|
|
||||||
$data = Input::except('_token');
|
|
||||||
/** @var \FireflyIII\Database\Recurring $repos */
|
|
||||||
$repos = App::make('FireflyIII\Database\Recurring');
|
|
||||||
|
|
||||||
switch ($data['post_submit_action']) {
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
|
|
||||||
break;
|
|
||||||
case 'create_another':
|
|
||||||
case 'store':
|
|
||||||
$messages = $repos->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save recurring transaction: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('recurring.create')->withInput()->withErrors($messages['errors']);
|
|
||||||
}
|
|
||||||
// store!
|
|
||||||
$repos->store($data);
|
|
||||||
Session::flash('success', 'New recurring transaction stored!');
|
|
||||||
|
|
||||||
if ($data['post_submit_action'] == 'create_another') {
|
|
||||||
return Redirect::route('recurring.create')->withInput();
|
|
||||||
} else {
|
|
||||||
return Redirect::route('recurring.index');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('recurring.create')->withInput();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RecurringTransaction $recurringTransaction
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public function update(RecurringTransaction $recurringTransaction)
|
|
||||||
{
|
|
||||||
/** @var \FireflyIII\Database\Recurring $repos */
|
|
||||||
$repos = App::make('FireflyIII\Database\Recurring');
|
|
||||||
$data = Input::except('_token');
|
|
||||||
|
|
||||||
switch (Input::get('post_submit_action')) {
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"');
|
|
||||||
break;
|
|
||||||
case 'create_another':
|
|
||||||
case 'update':
|
|
||||||
$messages = $repos->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save recurring transaction: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput()->withErrors($messages['errors']);
|
|
||||||
}
|
|
||||||
// store!
|
|
||||||
$repos->update($recurringTransaction, $data);
|
|
||||||
Session::flash('success', 'Recurring transaction updated!');
|
|
||||||
|
|
||||||
if ($data['post_submit_action'] == 'create_another') {
|
|
||||||
return Redirect::route('recurring.edit', $recurringTransaction->id);
|
|
||||||
} else {
|
|
||||||
return Redirect::route('recurring.index');
|
|
||||||
}
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
139
app/controllers/RelatedController.php
Normal file
139
app/controllers/RelatedController.php
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<?php
|
||||||
|
use FireflyIII\Helper\Related\RelatedInterface;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RelatedController
|
||||||
|
*/
|
||||||
|
class RelatedController extends BaseController
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $_repository;
|
||||||
|
|
||||||
|
public function __construct(RelatedInterface $repository)
|
||||||
|
{
|
||||||
|
$this->_repository = $repository;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
if (count($unique) > 0) {
|
||||||
|
|
||||||
|
$set = $this->_repository->getJournalsByIds($unique);
|
||||||
|
$set->each(
|
||||||
|
function (TransactionJournal $journal) {
|
||||||
|
$journal->amount = Amount::format($journal->getAmount());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Response::json($set->toArray());
|
||||||
|
} else {
|
||||||
|
return Response::json((new Collection)->toArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 = $this->_repository->getUser()->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::make('related.relate', compact('journal', 'members'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
|
{
|
||||||
|
|
||||||
|
$search = e(trim(Input::get('searchValue')));
|
||||||
|
|
||||||
|
$result = $this->_repository->search($search, $journal);
|
||||||
|
$result->each(
|
||||||
|
function (TransactionJournal $j) {
|
||||||
|
$j->amount = Amount::format($j->getAmount());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Response::json($result->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -26,25 +26,22 @@ class ReminderController extends BaseController
|
|||||||
public function act(Reminder $reminder)
|
public function act(Reminder $reminder)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (get_class($reminder->remindersable)) {
|
$class = get_class($reminder->remindersable);
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot act on reminder for ' . get_class($reminder->remindersable));
|
|
||||||
break;
|
|
||||||
break;
|
|
||||||
case 'Piggybank':
|
|
||||||
$amount = Reminders::amountForReminder($reminder);
|
|
||||||
$preFilled = [
|
|
||||||
'amount' => round($amount, 2),
|
|
||||||
'description' => 'Money for ' . $reminder->remindersable->name,
|
|
||||||
'piggybank_id' => $reminder->remindersable_id,
|
|
||||||
'account_to_id' => $reminder->remindersable->account_id
|
|
||||||
];
|
|
||||||
Session::flash('preFilled', $preFilled);
|
|
||||||
|
|
||||||
return Redirect::route('transactions.create', 'transfer');
|
if ($class == 'PiggyBank') {
|
||||||
break;
|
$amount = Reminders::amountForReminder($reminder);
|
||||||
|
$preFilled = [
|
||||||
|
'amount' => round($amount, 2),
|
||||||
|
'description' => 'Money for ' . $reminder->remindersable->name,
|
||||||
|
'piggy_bank_id' => $reminder->remindersable_id,
|
||||||
|
'account_to_id' => $reminder->remindersable->account_id
|
||||||
|
];
|
||||||
|
Session::flash('preFilled', $preFilled);
|
||||||
|
|
||||||
|
return Redirect::route('transactions.create', 'transfer');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return View::make('error')->with('message', 'This reminder has an invalid class connected to it.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,7 +63,7 @@ class ReminderController extends BaseController
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function notnow(Reminder $reminder)
|
public function notNow(Reminder $reminder)
|
||||||
{
|
{
|
||||||
$reminder->active = 0;
|
$reminder->active = 0;
|
||||||
$reminder->notnow = 1;
|
$reminder->notnow = 1;
|
||||||
@@ -85,7 +82,7 @@ class ReminderController extends BaseController
|
|||||||
{
|
{
|
||||||
|
|
||||||
$amount = null;
|
$amount = null;
|
||||||
if (get_class($reminder->remindersable) == 'Piggybank') {
|
if (get_class($reminder->remindersable) == 'PiggyBank') {
|
||||||
|
|
||||||
$amount = Reminders::amountForReminder($reminder);
|
$amount = Reminders::amountForReminder($reminder);
|
||||||
}
|
}
|
||||||
@@ -93,4 +90,4 @@ class ReminderController extends BaseController
|
|||||||
return View::make('reminders.show', compact('reminder', 'amount'));
|
return View::make('reminders.show', compact('reminder', 'amount'));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,29 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Database\PiggyBank\RepeatedExpense as Repository;
|
||||||
use FireflyIII\Exception\FireflyException;
|
use FireflyIII\Exception\FireflyException;
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
* @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove.
|
||||||
|
*
|
||||||
* Class RepeatedExpenseController
|
* Class RepeatedExpenseController
|
||||||
*/
|
*/
|
||||||
class RepeatedExpenseController extends BaseController
|
class RepeatedExpenseController extends BaseController
|
||||||
{
|
{
|
||||||
|
/** @var Repository */
|
||||||
|
protected $_repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param Repository $repository
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(Repository $repository)
|
||||||
{
|
{
|
||||||
View::share('title', 'Repeated expenses');
|
View::share('title', 'Repeated expenses');
|
||||||
View::share('mainTitleIcon', 'fa-rotate-left');
|
View::share('mainTitleIcon', 'fa-rotate-left');
|
||||||
|
$this->_repository = $repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,19 +31,73 @@ class RepeatedExpenseController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\Account $acct */
|
/** @var \FireflyIII\Database\Account\Account $acct */
|
||||||
$acct = App::make('FireflyIII\Database\Account');
|
$acct = App::make('FireflyIII\Database\Account\Account');
|
||||||
|
$periods = Config::get('firefly.piggy_bank_periods');
|
||||||
$periods = Config::get('firefly.piggybank_periods');
|
|
||||||
|
|
||||||
|
|
||||||
$accounts = FFForm::makeSelectList($acct->getAssetAccounts());
|
$accounts = FFForm::makeSelectList($acct->getAssetAccounts());
|
||||||
|
|
||||||
return View::make('repeatedexpense.create', compact('accounts', 'periods'))->with('subTitle', 'Create new repeated expense')->with(
|
return View::make('repeatedExpense.create', compact('accounts', 'periods'))->with('subTitle', 'Create new repeated expense')->with(
|
||||||
'subTitleIcon', 'fa-plus'
|
'subTitleIcon', 'fa-plus'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PiggyBank $repeatedExpense
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function delete(PiggyBank $repeatedExpense)
|
||||||
|
{
|
||||||
|
$subTitle = 'Delete "' . e($repeatedExpense->name) . '"';
|
||||||
|
|
||||||
|
return View::make('repeatedExpense.delete', compact('repeatedExpense', 'subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PiggyBank $repeatedExpense
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function destroy(PiggyBank $repeatedExpense)
|
||||||
|
{
|
||||||
|
|
||||||
|
Session::flash('success', 'Repeated expense "' . e($repeatedExpense->name) . '" deleted.');
|
||||||
|
$this->_repository->destroy($repeatedExpense);
|
||||||
|
|
||||||
|
return Redirect::route('repeated.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PiggyBank $repeatedExpense
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function edit(PiggyBank $repeatedExpense)
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @var \FireflyIII\Database\Account\Account $acct */
|
||||||
|
$acct = App::make('FireflyIII\Database\Account\Account');
|
||||||
|
|
||||||
|
$periods = Config::get('firefly.piggy_bank_periods');
|
||||||
|
$accounts = FFForm::makeSelectList($acct->getAssetAccounts());
|
||||||
|
$subTitle = 'Edit repeated expense "' . e($repeatedExpense->name) . '"';
|
||||||
|
$subTitleIcon = 'fa-pencil';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flash some data to fill the form.
|
||||||
|
*/
|
||||||
|
$preFilled = ['name' => $repeatedExpense->name,
|
||||||
|
'account_id' => $repeatedExpense->account_id,
|
||||||
|
'targetamount' => $repeatedExpense->targetamount,
|
||||||
|
'targetdate' => $repeatedExpense->targetdate->format('Y-m-d'),
|
||||||
|
'reminder' => $repeatedExpense->reminder,
|
||||||
|
'remind_me' => intval($repeatedExpense->remind_me) == 1 || !is_null($repeatedExpense->reminder) ? true : false
|
||||||
|
];
|
||||||
|
Session::flash('preFilled', $preFilled);
|
||||||
|
|
||||||
|
return View::make('repeatedExpense.edit', compact('subTitle', 'subTitleIcon', 'repeatedExpense', 'accounts', 'periods', 'preFilled'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\View\View
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
@@ -44,92 +106,122 @@ class RepeatedExpenseController extends BaseController
|
|||||||
|
|
||||||
$subTitle = 'Overview';
|
$subTitle = 'Overview';
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\RepeatedExpense $repository */
|
$expenses = $this->_repository->get();
|
||||||
$repository = App::make('FireflyIII\Database\RepeatedExpense');
|
|
||||||
|
|
||||||
$expenses = $repository->get();
|
|
||||||
$expenses->each(
|
$expenses->each(
|
||||||
function (Piggybank $piggyBank) use ($repository) {
|
function (PiggyBank $piggyBank) {
|
||||||
$piggyBank->currentRelevantRep();
|
$piggyBank->currentRelevantRep();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return View::make('repeatedexpense.index', compact('expenses', 'subTitle'));
|
return View::make('repeatedExpense.index', compact('expenses', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Piggybank $piggyBank
|
* @param PiggyBank $repeatedExpense
|
||||||
*
|
*
|
||||||
* @return \Illuminate\View\View
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function show(Piggybank $piggyBank)
|
public function show(PiggyBank $repeatedExpense)
|
||||||
{
|
{
|
||||||
$subTitle = $piggyBank->name;
|
$subTitle = $repeatedExpense->name;
|
||||||
$today = Carbon::now();
|
$today = Carbon::now();
|
||||||
|
$repetitions = $repeatedExpense->piggyBankRepetitions()->get();
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\RepeatedExpense $repository */
|
|
||||||
$repository = App::make('FireflyIII\Database\RepeatedExpense');
|
|
||||||
|
|
||||||
$repetitions = $piggyBank->piggybankrepetitions()->get();
|
|
||||||
$repetitions->each(
|
$repetitions->each(
|
||||||
function (PiggybankRepetition $repetition) use ($repository) {
|
function (PiggyBankRepetition $repetition) {
|
||||||
$repository->calculateParts($repetition);
|
$repetition->bars = $this->_repository->calculateParts($repetition);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return View::make('repeatedexpense.show', compact('repetitions', 'piggyBank', 'today', 'subTitle'));
|
return View::make('repeatedExpense.show', compact('repetitions', 'repeatedExpense', 'today', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return $this
|
*
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
*/
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
$data = Input::all();
|
$data = Input::all();
|
||||||
$data['repeats'] = 1;
|
$data['repeats'] = 1;
|
||||||
/** @var \FireflyIII\Database\RepeatedExpense $repository */
|
$data['user_id'] = Auth::user()->id;
|
||||||
$repository = App::make('FireflyIII\Database\RepeatedExpense');
|
$targetDate = new Carbon($data['targetdate']);
|
||||||
|
$startDate = \DateKit::subtractPeriod($targetDate, $data['rep_length']);
|
||||||
|
$data['startdate'] = $startDate->format('Y-m-d');
|
||||||
|
$data['targetdate'] = $targetDate->format('Y-m-d');
|
||||||
|
$data['reminder_skip'] = 0;
|
||||||
|
$data['remind_me'] = isset($data['remind_me']) ? 1 : 0;
|
||||||
|
$data['order'] = 0;
|
||||||
|
|
||||||
switch ($data['post_submit_action']) {
|
// always validate:
|
||||||
default:
|
$messages = $this->_repository->validate($data);
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
|
|
||||||
break;
|
|
||||||
case 'create_another':
|
|
||||||
case 'store':
|
|
||||||
$messages = $repository->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save repeated expense: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('repeated.create')->withInput()->withErrors($messages['errors']);
|
Session::flash('warnings', $messages['warnings']);
|
||||||
}
|
Session::flash('successes', $messages['successes']);
|
||||||
// store!
|
Session::flash('errors', $messages['errors']);
|
||||||
$repeated = $repository->store($data);
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not store repeated expense: ' . $messages['errors']->first());
|
||||||
/*
|
|
||||||
* Create the relevant repetition per Event.
|
|
||||||
*/
|
|
||||||
Event::fire('piggybank.store', [$repeated]); // new and used.
|
|
||||||
|
|
||||||
Session::flash('success', 'New repeated expense stored!');
|
|
||||||
|
|
||||||
if ($data['post_submit_action'] == 'create_another') {
|
|
||||||
return Redirect::route('repeated.create')->withInput();
|
|
||||||
} else {
|
|
||||||
return Redirect::route('repeated.index');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repository->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('repeated.create')->withInput();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// return to create screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('repeated.create')->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
$piggyBank = $this->_repository->store($data);
|
||||||
|
Event::fire('piggy_bank.store', [$piggyBank]); // new and used.
|
||||||
|
Session::flash('success', 'Piggy bank "' . e($data['name']) . '" stored.');
|
||||||
|
if ($data['post_submit_action'] == 'store') {
|
||||||
|
return Redirect::route('repeated.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('repeated.create')->withInput();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* @param PiggyBank $repeatedExpense
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function update(PiggyBank $repeatedExpense)
|
||||||
|
{
|
||||||
|
|
||||||
|
$data = Input::except('_token');
|
||||||
|
$data['rep_every'] = 0;
|
||||||
|
$data['reminder_skip'] = 0;
|
||||||
|
$data['order'] = 0;
|
||||||
|
$data['repeats'] = 1;
|
||||||
|
$data['remind_me'] = isset($data['remind_me']) ? 1 : 0;
|
||||||
|
$data['user_id'] = Auth::user()->id;
|
||||||
|
|
||||||
|
// always validate:
|
||||||
|
$messages = $this->_repository->validate($data);
|
||||||
|
|
||||||
|
Session::flash('warnings', $messages['warnings']);
|
||||||
|
Session::flash('successes', $messages['successes']);
|
||||||
|
Session::flash('errors', $messages['errors']);
|
||||||
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not update repeated expense: ' . $messages['errors']->first());
|
||||||
|
}
|
||||||
|
|
||||||
|
// return to update screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('repeated.edit', $repeatedExpense->id)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
$this->_repository->update($repeatedExpense, $data);
|
||||||
|
Session::flash('success', 'Repeated expense "' . e($data['name']) . '" updated.');
|
||||||
|
|
||||||
|
// go back to list
|
||||||
|
if ($data['post_submit_action'] == 'update') {
|
||||||
|
return Redirect::route('repeated.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// go back to update screen.
|
||||||
|
return Redirect::route('repeated.edit', $repeatedExpense->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,142 +1,60 @@
|
|||||||
<?php
|
<?php
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Database\Account as AccountRepository;
|
use FireflyIII\Database\TransactionJournal\TransactionJournal as TransactionJournalRepository;
|
||||||
use FireflyIII\Database\Report as ReportRepository;
|
use FireflyIII\Report\ReportInterface as Report;
|
||||||
use FireflyIII\Database\TransactionJournal as TransactionJournalRepository;
|
|
||||||
use FireflyIII\Report\ReportInterface as ReportHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
*
|
||||||
* Class ReportController
|
* Class ReportController
|
||||||
*/
|
*/
|
||||||
class ReportController extends BaseController
|
class ReportController extends BaseController
|
||||||
{
|
{
|
||||||
/** @var AccountRepository */
|
/** @var \FireflyIII\Database\Budget\Budget */
|
||||||
protected $_accounts;
|
protected $_budgets;
|
||||||
|
|
||||||
/** @var TransactionJournalRepository */
|
/** @var TransactionJournalRepository */
|
||||||
protected $_journals;
|
protected $_journals;
|
||||||
|
/** @var Report */
|
||||||
/** @var ReportHelper */
|
|
||||||
protected $_reports;
|
|
||||||
|
|
||||||
/** @var ReportRepository */
|
|
||||||
protected $_repository;
|
protected $_repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AccountRepository $accounts
|
|
||||||
* @param TransactionJournalRepository $journals
|
* @param TransactionJournalRepository $journals
|
||||||
* @param ReportHelper $reports
|
* @param Report $repository
|
||||||
* @param ReportRepository $repository
|
|
||||||
*/
|
*/
|
||||||
public function __construct(AccountRepository $accounts, TransactionJournalRepository $journals, ReportHelper $reports, ReportRepository $repository)
|
public function __construct(TransactionJournalRepository $journals, Report $repository)
|
||||||
{
|
{
|
||||||
$this->_accounts = $accounts;
|
|
||||||
$this->_journals = $journals;
|
$this->_journals = $journals;
|
||||||
$this->_reports = $reports;
|
|
||||||
$this->_repository = $repository;
|
$this->_repository = $repository;
|
||||||
|
/** @var \FireflyIII\Database\Budget\Budget _budgets */
|
||||||
|
$this->_budgets = App::make('FireflyIII\Database\Budget\Budget');
|
||||||
|
|
||||||
|
|
||||||
|
View::share('title', 'Reports');
|
||||||
|
View::share('mainTitleIcon', 'fa-line-chart');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $year
|
* @param string $year
|
||||||
* @param $month
|
* @param string $month
|
||||||
*
|
*
|
||||||
* @return \Illuminate\View\View
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function budgets($year, $month)
|
public function budget($year = '2014', $month = '1')
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$start = new Carbon($year . '-' . $month . '-01');
|
new Carbon($year . '-' . $month . '-01');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
App::abort(500);
|
return View::make('error')->with('message', 'Invalid date');
|
||||||
}
|
}
|
||||||
$end = clone $start;
|
$date = new Carbon($year . '-' . $month . '-01');
|
||||||
$title = 'Reports';
|
$dayEarly = clone $date;
|
||||||
$subTitle = 'Budgets in ' . $start->format('F Y');
|
$dayEarly = $dayEarly->subDay();
|
||||||
$mainTitleIcon = 'fa-line-chart';
|
$accounts = $this->_repository->getAccountListBudgetOverview($date);
|
||||||
$subTitleIcon = 'fa-bar-chart';
|
$budgets = $this->_repository->getBudgetsForMonth($date);
|
||||||
|
|
||||||
$end->endOfMonth();
|
return View::make('reports.budget', compact('date', 'accounts', 'budgets', 'dayEarly'));
|
||||||
|
|
||||||
|
|
||||||
// get a list of all budgets and expenses.
|
|
||||||
/** @var \FireflyIII\Database\Budget $budgetRepository */
|
|
||||||
$budgetRepository = App::make('FireflyIII\Database\Budget');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Account $accountRepository */
|
|
||||||
$accountRepository = App::make('FireflyIII\Database\Account');
|
|
||||||
|
|
||||||
|
|
||||||
$budgets = $budgetRepository->get();
|
|
||||||
|
|
||||||
// calculate some stuff:
|
|
||||||
$budgets->each(
|
|
||||||
function (Budget $budget) use ($start, $end, $budgetRepository) {
|
|
||||||
$limitRepetitions = $budget->limitrepetitions()->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d'))->where(
|
|
||||||
'enddate', '<=', $end->format(
|
|
||||||
'Y-m-d'
|
|
||||||
)
|
|
||||||
)->get();
|
|
||||||
$repInfo = [];
|
|
||||||
/** @var LimitRepetition $repetition */
|
|
||||||
foreach ($limitRepetitions as $repetition) {
|
|
||||||
$spent = $budgetRepository->spentInPeriod($budget, $start, $end);
|
|
||||||
if ($spent > floatval($repetition->amount)) {
|
|
||||||
// overspent!
|
|
||||||
$overspent = true;
|
|
||||||
$pct = floatval($repetition->amount) / $spent * 100;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$overspent = false;
|
|
||||||
$pct = $spent / floatval($repetition->amount) * 100;
|
|
||||||
}
|
|
||||||
$pctDisplay = $spent / floatval($repetition->amount) * 100;
|
|
||||||
$repInfo[] = [
|
|
||||||
'date' => DateKit::periodShow($repetition->startdate, $repetition->limit->repeat_freq),
|
|
||||||
'spent' => $spent,
|
|
||||||
'budgeted' => floatval($repetition->amount),
|
|
||||||
'left' => floatval($repetition->amount) - $spent,
|
|
||||||
'pct' => ceil($pct),
|
|
||||||
'pct_display' => ceil($pctDisplay),
|
|
||||||
'overspent' => $overspent,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$budget->repInfo = $repInfo;
|
|
||||||
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$accounts = $accountRepository->getAssetAccounts();
|
|
||||||
|
|
||||||
$accounts->each(
|
|
||||||
function (Account $account) use ($start, $end, $accountRepository) {
|
|
||||||
$journals = $accountRepository->getTransactionJournalsInRange($account, $start, $end);
|
|
||||||
$budgets = [];
|
|
||||||
/** @var TransactionJournal $journal */
|
|
||||||
foreach ($journals as $journal) {
|
|
||||||
$budgetId = isset($journal->budgets[0]) ? $journal->budgets[0]->id : 0;
|
|
||||||
$budgetName = isset($journal->budgets[0]) ? $journal->budgets[0]->name : '(no budget)';
|
|
||||||
if (!isset($budgets[$budgetId])) {
|
|
||||||
$arr = [
|
|
||||||
'budget_id' => $budgetId,
|
|
||||||
'budget_name' => $budgetName,
|
|
||||||
'spent' => floatval($journal->getAmount()),
|
|
||||||
'budgeted' => 0,
|
|
||||||
];
|
|
||||||
$budgets[$budgetId] = $arr;
|
|
||||||
} else {
|
|
||||||
$budgets[$budgetId]['spent'] += floatval($journal->getAmount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($budgets as $budgetId => $budget) {
|
|
||||||
$budgets[$budgetId]['left'] = $budget['budgeted'] - $budget['spent'];
|
|
||||||
}
|
|
||||||
$account->budgetInfo = $budgets;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return View::make('reports.budgets', compact('start', 'end', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon', 'budgets', 'accounts'));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +64,8 @@ class ReportController extends BaseController
|
|||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$start = $this->_journals->firstDate();
|
$start = $this->_journals->firstDate();
|
||||||
$months = $this->_reports->listOfMonths(clone $start);
|
$months = $this->_repository->listOfMonths(clone $start);
|
||||||
$years = $this->_reports->listOfYears(clone $start);
|
$years = $this->_repository->listOfYears(clone $start);
|
||||||
$title = 'Reports';
|
$title = 'Reports';
|
||||||
$mainTitleIcon = 'fa-line-chart';
|
$mainTitleIcon = 'fa-line-chart';
|
||||||
|
|
||||||
@@ -155,82 +73,32 @@ class ReportController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $year
|
* @param string $year
|
||||||
* @param $month
|
* @param string $month
|
||||||
*
|
*
|
||||||
* @return \Illuminate\View\View
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function unbalanced($year, $month)
|
public function month($year = '2014', $month = '1')
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$date = new Carbon($year . '-' . $month . '-01');
|
new Carbon($year . '-' . $month . '-01');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
App::abort(500);
|
return View::make('error')->with('message', 'Invalid date.');
|
||||||
}
|
}
|
||||||
$start = new Carbon($year . '-' . $month . '-01');
|
$date = new Carbon($year . '-' . $month . '-01');
|
||||||
$end = clone $start;
|
$subTitle = 'Report for ' . $date->format('F Y');
|
||||||
$title = 'Reports';
|
$subTitleIcon = 'fa-calendar';
|
||||||
$subTitle = 'Unbalanced transactions in ' . $start->format('F Y');
|
$displaySum = true; // to show sums in report.
|
||||||
$mainTitleIcon = 'fa-line-chart';
|
$income = $this->_repository->getIncomeForMonth($date);
|
||||||
$subTitleIcon = 'fa-bar-chart';
|
$expenses = $this->_repository->getExpenseGroupedForMonth($date, 10);
|
||||||
$end->endOfMonth();
|
$budgets = $this->_repository->getBudgetsForMonth($date);
|
||||||
|
$categories = $this->_repository->getCategoriesForMonth($date, 10);
|
||||||
|
$accounts = $this->_repository->getAccountsForMonth($date);
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $journalRepository */
|
return View::make(
|
||||||
$journalRepository = App::make('FireflyIII\Database\TransactionJournal');
|
'reports.month',
|
||||||
|
compact('date', 'accounts', 'categories', 'budgets', 'expenses', 'subTitle', 'displaySum', 'subTitleIcon', 'income')
|
||||||
/*
|
|
||||||
* Get all journals from this month:
|
|
||||||
*/
|
|
||||||
$journals = $journalRepository->getInDateRange($start, $end);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Filter withdrawals:
|
|
||||||
*/
|
|
||||||
$withdrawals = $journals->filter(
|
|
||||||
function (TransactionJournal $journal) {
|
|
||||||
if ($journal->transactionType->type == 'Withdrawal' && count($journal->budgets) == 0) {
|
|
||||||
|
|
||||||
// count groups related to balance.
|
|
||||||
if ($journal->transactiongroups()->where('relation', 'balance')->count() == 0) {
|
|
||||||
return $journal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
/*
|
|
||||||
* Filter deposits.
|
|
||||||
*/
|
|
||||||
$deposits = $journals->filter(
|
|
||||||
function (TransactionJournal $journal) {
|
|
||||||
if ($journal->transactionType->type == 'Deposit' && count($journal->budgets) == 0) {
|
|
||||||
// count groups related to balance.
|
|
||||||
if ($journal->transactiongroups()->where('relation', 'balance')->count() == 0) {
|
|
||||||
return $journal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Filter transfers (not yet used)
|
|
||||||
*/
|
|
||||||
// $transfers = $journals->filter(
|
|
||||||
// function (TransactionJournal $journal) {
|
|
||||||
// if ($journal->transactionType->type == 'Transfer') {
|
|
||||||
// return $journal;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
$journals = $withdrawals->merge($deposits);
|
|
||||||
|
|
||||||
|
|
||||||
return View::make('reports.unbalanced', compact('start', 'end', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon', 'journals'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,76 +111,23 @@ class ReportController extends BaseController
|
|||||||
try {
|
try {
|
||||||
new Carbon('01-01-' . $year);
|
new Carbon('01-01-' . $year);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
App::abort(500);
|
return View::make('error')->with('message', 'Invalid date.');
|
||||||
}
|
}
|
||||||
$date = new Carbon('01-01-' . $year);
|
$date = new Carbon('01-01-' . $year);
|
||||||
|
$end = clone $date;
|
||||||
|
$end->endOfYear();
|
||||||
$title = 'Reports';
|
$title = 'Reports';
|
||||||
$subTitle = $year;
|
$subTitle = $year;
|
||||||
$subTitleIcon = 'fa-bar-chart';
|
$subTitleIcon = 'fa-bar-chart';
|
||||||
$mainTitleIcon = 'fa-line-chart';
|
$mainTitleIcon = 'fa-line-chart';
|
||||||
|
|
||||||
$balances = $this->_reports->yearBalanceReport($date);
|
$balances = $this->_repository->yearBalanceReport($date);
|
||||||
$groupedIncomes = $this->_reports->groupByRevenue($date, 'income');
|
$groupedIncomes = $this->_repository->revenueGroupedByAccount($date, $end, 15);
|
||||||
$groupedExpenses = $this->_reports->groupByRevenue($date, 'expense');
|
$groupedExpenses = $this->_repository->expensesGroupedByAccount($date, $end, 15);
|
||||||
|
|
||||||
|
|
||||||
return View::make(
|
return View::make(
|
||||||
'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon')
|
'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For this year, get:
|
|
||||||
* - the sum of all expenses.
|
|
||||||
* - the sum of all incomes
|
|
||||||
* - per month, the sum of all expenses
|
|
||||||
* - per month, the sum of all incomes
|
|
||||||
* - 2x for shared and not-shared alike.
|
|
||||||
*
|
|
||||||
* - balance difference for all accounts.
|
|
||||||
*/
|
|
||||||
|
|
||||||
$accounts = $accountRepository->getAssetAccounts();
|
|
||||||
|
|
||||||
// get some sums going
|
|
||||||
$summary = [];
|
|
||||||
|
|
||||||
$end = clone $date;
|
|
||||||
$end->endOfYear();
|
|
||||||
while ($date < $end) {
|
|
||||||
$month = $date->format('F');
|
|
||||||
|
|
||||||
$income = 0;
|
|
||||||
$incomeShared = 0;
|
|
||||||
$expense = 0;
|
|
||||||
$expenseShared = 0;
|
|
||||||
|
|
||||||
foreach ($accounts as $account) {
|
|
||||||
if ($account->accountRole == 'sharedExpense') {
|
|
||||||
$incomeShared += $reportRepository->getIncomeByMonth($account, $date);
|
|
||||||
$expenseShared += $reportRepository->getExpenseByMonth($account, $date);
|
|
||||||
} else {
|
|
||||||
$income += $reportRepository->getIncomeByMonth($account, $date);
|
|
||||||
$expense += $reportRepository->getExpenseByMonth($account, $date);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$summary[] = [
|
|
||||||
'month' => $month,
|
|
||||||
'income' => $income,
|
|
||||||
'expense' => $expense,
|
|
||||||
'incomeShared' => $incomeShared,
|
|
||||||
'expenseShared' => $expenseShared,
|
|
||||||
];
|
|
||||||
$date->addMonth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// draw some charts etc.
|
|
||||||
return View::make('reports.year', compact('summary', 'date'))->with('title', 'Reports')->with('mainTitleIcon', 'fa-line-chart')->with('subTitle', $year)
|
|
||||||
->with(
|
|
||||||
'subTitleIcon', 'fa-bar-chart'
|
|
||||||
)->with('year', $year);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class SearchController extends BaseController
|
|||||||
$subTitle = null;
|
$subTitle = null;
|
||||||
$rawQuery = null;
|
$rawQuery = null;
|
||||||
$result = [];
|
$result = [];
|
||||||
if (!is_null(Input::get('q'))) {
|
if (!is_null(Input::get('q')) && strlen(Input::get('q')) > 0) {
|
||||||
$rawQuery = trim(Input::get('q'));
|
$rawQuery = trim(Input::get('q'));
|
||||||
$words = explode(' ', $rawQuery);
|
$words = explode(' ', $rawQuery);
|
||||||
$subTitle = 'Results for "' . e($rawQuery) . '"';
|
$subTitle = 'Results for "' . e($rawQuery) . '"';
|
||||||
@@ -35,4 +35,4 @@ class SearchController extends BaseController
|
|||||||
'mainTitleIcon', 'fa-search'
|
'mainTitleIcon', 'fa-search'
|
||||||
)->with('query', $rawQuery)->with('result', $result);
|
)->with('query', $rawQuery)->with('result', $result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Database\TransactionJournal\TransactionJournal as Repository;
|
||||||
use FireflyIII\Exception\FireflyException;
|
use FireflyIII\Exception\FireflyException;
|
||||||
|
use FireflyIII\Helper\TransactionJournal\HelperInterface as Helper;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
|
||||||
|
* @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove.
|
||||||
|
* @SuppressWarnings("TooManyMethods") // I'm also fine with this.
|
||||||
|
* @SuppressWarnings("ExcessiveClassComplexity")
|
||||||
|
*
|
||||||
* Class TransactionController
|
* Class TransactionController
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -13,54 +21,25 @@ class TransactionController extends BaseController
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** @var Helper */
|
||||||
|
protected $_helper;
|
||||||
|
/** @var Repository */
|
||||||
|
protected $_repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new transaction controller with two of the most often used helpers.
|
* Construct a new transaction controller with two of the most often used helpers.
|
||||||
*
|
*
|
||||||
|
* @param Repository $repository
|
||||||
|
* @param Helper $helper
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(Repository $repository, Helper $helper)
|
||||||
{
|
{
|
||||||
|
$this->_repository = $repository;
|
||||||
|
$this->_helper = $helper;
|
||||||
View::share('title', 'Transactions');
|
View::share('title', 'Transactions');
|
||||||
View::share('mainTitleIcon', 'fa-repeat');
|
View::share('mainTitleIcon', 'fa-repeat');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* TODO this needs cleaning up and thinking over.
|
|
||||||
*
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
*
|
|
||||||
* @return array|\Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function alreadyRelated(TransactionJournal $journal)
|
|
||||||
{
|
|
||||||
|
|
||||||
$ids = [];
|
|
||||||
/** @var TransactionGroup $group */
|
|
||||||
foreach ($journal->transactiongroups()->get() as $group) {
|
|
||||||
/** @var TransactionJournal $jrnl */
|
|
||||||
foreach ($group->transactionjournals()->get() as $jrnl) {
|
|
||||||
if ($jrnl->id != $journal->id) {
|
|
||||||
$ids[] = $jrnl->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$unique = array_unique($ids);
|
|
||||||
if (count($ids) > 0) {
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $repository */
|
|
||||||
$repository = App::make('FireflyIII\Database\TransactionJournal');
|
|
||||||
$set = $repository->getByIds($ids);
|
|
||||||
$set->each(
|
|
||||||
function (TransactionJournal $journal) {
|
|
||||||
$journal->amount = mf($journal->getAmount());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return Response::json($set->toArray());
|
|
||||||
} else {
|
|
||||||
return (new Collection)->toArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the view helping the user to create a new transaction journal.
|
* Shows the view helping the user to create a new transaction journal.
|
||||||
@@ -71,40 +50,18 @@ class TransactionController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function create($what = 'deposit')
|
public function create($what = 'deposit')
|
||||||
{
|
{
|
||||||
/*
|
$accounts = FFForm::makeSelectList($this->_helper->getAssetAccounts());
|
||||||
* The repositories we need:
|
$budgets = FFForm::makeSelectList($this->_helper->getBudgets());
|
||||||
*/
|
$budgets[0] = '(no budget)';
|
||||||
|
$piggyBanks = $this->_helper->getPiggyBanks();
|
||||||
|
$repeatedExpenses = $this->_helper->getRepeatedExpenses();
|
||||||
|
$list = $piggyBanks->merge($repeatedExpenses);
|
||||||
|
$piggies = FFForm::makeSelectList($list);
|
||||||
|
$piggies[0] = '(no piggy bank)';
|
||||||
|
$preFilled = Session::has('preFilled') ? Session::get('preFilled') : [];
|
||||||
|
$respondTo = ['account_id', 'account_from_id'];
|
||||||
|
$subTitle = 'Add a new ' . e($what);
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Account $accountRepository */
|
|
||||||
$accountRepository = App::make('FireflyIII\Database\Account');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Budget $budgetRepository */
|
|
||||||
$budgetRepository = App::make('FireflyIII\Database\Budget');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\Piggybank $piggyRepository */
|
|
||||||
$piggyRepository = App::make('FireflyIII\Database\Piggybank');
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\RepeatedExpense $repRepository */
|
|
||||||
$repRepository = App::make('FireflyIII\Database\RepeatedExpense');
|
|
||||||
|
|
||||||
// get asset accounts with names and id's .
|
|
||||||
$assetAccounts = FFForm::makeSelectList($accountRepository->getAssetAccounts());
|
|
||||||
|
|
||||||
// get budgets as a select list.
|
|
||||||
$budgets = FFForm::makeSelectList($budgetRepository->get());
|
|
||||||
$budgets[0] = '(no budget)';
|
|
||||||
|
|
||||||
// get the piggy banks.
|
|
||||||
$list = $piggyRepository->get()->merge($repRepository->get());
|
|
||||||
$piggies = FFForm::makeSelectList($list);
|
|
||||||
$piggies[0] = '(no piggy bank)';
|
|
||||||
asort($piggies);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* respond to a possible given values in the URL.
|
|
||||||
*/
|
|
||||||
$preFilled = Session::has('preFilled') ? Session::get('preFilled') : [];
|
|
||||||
$respondTo = ['account_id', 'account_from_id'];
|
|
||||||
foreach ($respondTo as $r) {
|
foreach ($respondTo as $r) {
|
||||||
if (!is_null(Input::get($r))) {
|
if (!is_null(Input::get($r))) {
|
||||||
$preFilled[$r] = Input::get($r);
|
$preFilled[$r] = Input::get($r);
|
||||||
@@ -112,24 +69,25 @@ class TransactionController extends BaseController
|
|||||||
}
|
}
|
||||||
Session::put('preFilled', $preFilled);
|
Session::put('preFilled', $preFilled);
|
||||||
|
|
||||||
return View::make('transactions.create')->with('accounts', $assetAccounts)->with('budgets', $budgets)->with('what', $what)->with('piggies', $piggies)
|
asort($piggies);
|
||||||
->with('subTitle', 'Add a new ' . $what);
|
|
||||||
|
|
||||||
|
return View::make('transactions.create', compact('accounts', 'budgets', 'what', 'piggies', 'subTitle'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the form that allows a user to delete a transaction journal.
|
* Shows the form that allows a user to delete a transaction journal.
|
||||||
*
|
*
|
||||||
* @param TransactionJournal $transactionJournal
|
* @param TransactionJournal $journal
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function delete(TransactionJournal $transactionJournal)
|
public function delete(TransactionJournal $journal)
|
||||||
{
|
{
|
||||||
$type = strtolower($transactionJournal->transactionType->type);
|
$type = strtolower($journal->transactionType->type);
|
||||||
|
$subTitle = 'Delete ' . e($type) . ' "' . e($journal->description) . '"';
|
||||||
|
|
||||||
return View::make('transactions.delete')->with('journal', $transactionJournal)->with(
|
return View::make('transactions.delete', compact('journal', 'subTitle'));
|
||||||
'subTitle', 'Delete ' . $type . ' "' . $transactionJournal->description . '"'
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -141,14 +99,12 @@ class TransactionController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function destroy(TransactionJournal $transactionJournal)
|
public function destroy(TransactionJournal $transactionJournal)
|
||||||
{
|
{
|
||||||
$type = $transactionJournal->transactionType->type;
|
$type = $transactionJournal->transactionType->type;
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $repository */
|
|
||||||
$repository = App::make('FireflyIII\Database\TransactionJournal');
|
|
||||||
$repository->destroy($transactionJournal);
|
|
||||||
|
|
||||||
$return = 'withdrawal';
|
$return = 'withdrawal';
|
||||||
|
|
||||||
|
Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.');
|
||||||
|
|
||||||
|
$this->_repository->destroy($transactionJournal);
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'Deposit':
|
case 'Deposit':
|
||||||
@@ -162,38 +118,6 @@ class TransactionController extends BaseController
|
|||||||
return Redirect::route('transactions.index', $return);
|
return Redirect::route('transactions.index', $return);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO this needs cleaning up and thinking over.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function doRelate()
|
|
||||||
{
|
|
||||||
$id = intval(Input::get('id'));
|
|
||||||
$sister = intval(Input::get('relateTo'));
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $repository */
|
|
||||||
$repository = App::make('FireflyIII\Database\TransactionJournal');
|
|
||||||
|
|
||||||
$journal = $repository->find($id);
|
|
||||||
$sis = $repository->find($sister);
|
|
||||||
|
|
||||||
if ($journal && $sis) {
|
|
||||||
$group = new TransactionGroup;
|
|
||||||
$group->relation = 'balance';
|
|
||||||
$group->user_id = $repository->getUser()->id;
|
|
||||||
$group->save();
|
|
||||||
$group->transactionjournals()->save($journal);
|
|
||||||
$group->transactionjournals()->save($sis);
|
|
||||||
|
|
||||||
return Response::json(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response::json(false);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the view to edit a transaction.
|
* Shows the view to edit a transaction.
|
||||||
*
|
*
|
||||||
@@ -203,128 +127,42 @@ class TransactionController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function edit(TransactionJournal $journal)
|
public function edit(TransactionJournal $journal)
|
||||||
{
|
{
|
||||||
/*
|
$what = strtolower($journal->transactiontype->type);
|
||||||
* All the repositories we need:
|
$subTitle = 'Edit ' . e($what) . ' "' . e($journal->description) . '"';
|
||||||
*/
|
$budgets = FFForm::makeSelectList($this->_helper->getBudgets(), true);
|
||||||
|
$accounts = FFForm::makeSelectList($this->_helper->getAssetAccounts());
|
||||||
/** @var \FireflyIII\Database\Account $accountRepository */
|
$piggies = FFForm::makeSelectList($this->_helper->getPiggyBanks(), true);
|
||||||
$accountRepository = App::make('FireflyIII\Database\Account');
|
$transactions = $journal->transactions()->orderBy('amount', 'DESC')->get();
|
||||||
|
$preFilled = [
|
||||||
/** @var \FireflyIII\Database\Budget $budgetRepository */
|
'date' => $journal->date->format('Y-m-d'),
|
||||||
$budgetRepository = App::make('FireflyIII\Database\Budget');
|
'category' => '',
|
||||||
|
'budget_id' => 0,
|
||||||
/** @var \FireflyIII\Database\Piggybank $piggyRepository */
|
'piggy_bank_id' => 0
|
||||||
$piggyRepository = App::make('FireflyIII\Database\Piggybank');
|
|
||||||
|
|
||||||
|
|
||||||
// type is useful for display:
|
|
||||||
$what = strtolower($journal->transactiontype->type);
|
|
||||||
|
|
||||||
// get asset accounts with names and id's.
|
|
||||||
$accounts = FFForm::makeSelectList($accountRepository->getAssetAccounts());
|
|
||||||
|
|
||||||
// get budgets as a select list.
|
|
||||||
$budgets = FFForm::makeSelectList($budgetRepository->get());
|
|
||||||
$budgets[0] = '(no budget)';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get all piggy banks plus (if any) the relevant piggy bank. Since just one
|
|
||||||
* of the transactions in the journal has this field, it should all fill in nicely.
|
|
||||||
*/
|
|
||||||
// get the piggy banks.
|
|
||||||
$piggies = FFForm::makeSelectList($piggyRepository->get());
|
|
||||||
$piggies[0] = '(no piggy bank)';
|
|
||||||
$piggyBankId = 0;
|
|
||||||
foreach ($journal->transactions as $t) {
|
|
||||||
if (!is_null($t->piggybank_id)) {
|
|
||||||
$piggyBankId = $t->piggybank_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Data to properly display the edit form.
|
|
||||||
*/
|
|
||||||
$preFilled = [
|
|
||||||
'date' => $journal->date->format('Y-m-d'),
|
|
||||||
'category' => '',
|
|
||||||
'budget_id' => 0,
|
|
||||||
'piggybank_id' => $piggyBankId
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/*
|
|
||||||
* Fill in the category.
|
|
||||||
*/
|
|
||||||
$category = $journal->categories()->first();
|
$category = $journal->categories()->first();
|
||||||
if (!is_null($category)) {
|
if (!is_null($category)) {
|
||||||
$preFilled['category'] = $category->name;
|
$preFilled['category'] = $category->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
$budget = $journal->budgets()->first();
|
||||||
* Switch on the type of transaction edited by the user and fill in other
|
if (!is_null($budget)) {
|
||||||
* relevant fields:
|
$preFilled['budget_id'] = $budget->id;
|
||||||
*/
|
|
||||||
switch ($what) {
|
|
||||||
case 'withdrawal':
|
|
||||||
if (floatval($journal->transactions[0]->amount) < 0) {
|
|
||||||
// transactions[0] is the asset account that paid for the withdrawal.
|
|
||||||
$preFilled['account_id'] = $journal->transactions[0]->account->id;
|
|
||||||
$preFilled['expense_account'] = $journal->transactions[1]->account->name;
|
|
||||||
$preFilled['amount'] = floatval($journal->transactions[1]->amount);
|
|
||||||
} else {
|
|
||||||
// transactions[1] is the asset account that paid for the withdrawal.
|
|
||||||
$preFilled['account_id'] = $journal->transactions[1]->account->id;
|
|
||||||
$preFilled['expense_account'] = $journal->transactions[0]->account->name;
|
|
||||||
$preFilled['amount'] = floatval($journal->transactions[0]->amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$budget = $journal->budgets()->first();
|
|
||||||
if (!is_null($budget)) {
|
|
||||||
$preFilled['budget_id'] = $budget->id;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'deposit':
|
|
||||||
if (floatval($journal->transactions[0]->amount) < 0) {
|
|
||||||
// transactions[0] contains the account the money came from.
|
|
||||||
$preFilled['account_id'] = $journal->transactions[1]->account->id;
|
|
||||||
$preFilled['revenue_account'] = $journal->transactions[0]->account->name;
|
|
||||||
$preFilled['amount'] = floatval($journal->transactions[1]->amount);
|
|
||||||
} else {
|
|
||||||
// transactions[1] contains the account the money came from.
|
|
||||||
$preFilled['account_id'] = $journal->transactions[0]->account->id;
|
|
||||||
$preFilled['revenue_account'] = $journal->transactions[1]->account->name;
|
|
||||||
$preFilled['amount'] = floatval($journal->transactions[0]->amount);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'transfer':
|
|
||||||
if (floatval($journal->transactions[0]->amount) < 0) {
|
|
||||||
// zero = from account.
|
|
||||||
$preFilled['account_from_id'] = $journal->transactions[0]->account->id;
|
|
||||||
$preFilled['account_to_id'] = $journal->transactions[1]->account->id;
|
|
||||||
$preFilled['amount'] = floatval($journal->transactions[1]->amount);
|
|
||||||
} else {
|
|
||||||
// one = from account
|
|
||||||
$preFilled['account_from_id'] = $journal->transactions[1]->account->id;
|
|
||||||
$preFilled['account_to_id'] = $journal->transactions[0]->account->id;
|
|
||||||
$preFilled['amount'] = floatval($journal->transactions[0]->amount);
|
|
||||||
}
|
|
||||||
if ($journal->piggybankevents()->count() > 0) {
|
|
||||||
$preFilled['piggybank_id'] = $journal->piggybankevents()->first()->piggybank_id;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if ($journal->piggyBankEvents()->count() > 0) {
|
||||||
* Show the view.
|
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->first()->piggy_bank_id;
|
||||||
*/
|
}
|
||||||
|
|
||||||
return View::make('transactions.edit')->with('journal', $journal)->with('accounts', $accounts)->with(
|
$preFilled['amount'] = $journal->getAmount();
|
||||||
'what', $what
|
$preFilled['account_id'] = $this->_helper->getAssetAccount($what, $transactions);
|
||||||
)->with('budgets', $budgets)->with('data', $preFilled)->with('piggies', $piggies)->with(
|
$preFilled['expense_account'] = $transactions[0]->account->name;
|
||||||
'subTitle', 'Edit ' . $what . ' "' . $journal->description . '"'
|
$preFilled['revenue_account'] = $transactions[1]->account->name;
|
||||||
);
|
$preFilled['account_from_id'] = $transactions[1]->account->id;
|
||||||
|
$preFilled['account_to_id'] = $transactions[0]->account->id;
|
||||||
|
|
||||||
|
|
||||||
|
return View::make('transactions.edit', compact('journal', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -334,28 +172,24 @@ class TransactionController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function index($what)
|
public function index($what)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $repository */
|
|
||||||
$repository = App::make('FireflyIII\Database\TransactionJournal');
|
|
||||||
|
|
||||||
switch ($what) {
|
switch ($what) {
|
||||||
case 'expenses':
|
case 'expenses':
|
||||||
case 'withdrawal':
|
case 'withdrawal':
|
||||||
$subTitleIcon = 'fa-long-arrow-left';
|
$subTitleIcon = 'fa-long-arrow-left';
|
||||||
$subTitle = 'Expenses';
|
$subTitle = 'Expenses';
|
||||||
$journals = $repository->getWithdrawalsPaginated(50);
|
$journals = $this->_repository->getWithdrawalsPaginated(50);
|
||||||
break;
|
break;
|
||||||
case 'revenue':
|
case 'revenue':
|
||||||
case 'deposit':
|
case 'deposit':
|
||||||
$subTitleIcon = 'fa-long-arrow-right';
|
$subTitleIcon = 'fa-long-arrow-right';
|
||||||
$subTitle = 'Revenue, income and deposits';
|
$subTitle = 'Revenue, income and deposits';
|
||||||
$journals = $repository->getDepositsPaginated(50);
|
$journals = $this->_repository->getDepositsPaginated(50);
|
||||||
break;
|
break;
|
||||||
case 'transfer':
|
case 'transfer':
|
||||||
case 'transfers':
|
case 'transfers':
|
||||||
$subTitleIcon = 'fa-arrows-h';
|
$subTitleIcon = 'fa-arrows-h';
|
||||||
$subTitle = 'Transfers';
|
$subTitle = 'Transfers';
|
||||||
$journals = $repository->getTransfersPaginated(50);
|
$journals = $this->_repository->getTransfersPaginated(50);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,51 +197,7 @@ class TransactionController extends BaseController
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
*
|
|
||||||
* @return \Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function relate(TransactionJournal $journal)
|
|
||||||
{
|
|
||||||
$groups = $journal->transactiongroups()->get();
|
|
||||||
$members = new Collection;
|
|
||||||
/** @var TransactionGroup $group */
|
|
||||||
foreach ($groups as $group) {
|
|
||||||
/** @var TransactionJournal $jrnl */
|
|
||||||
foreach ($group->transactionjournals()->get() as $jrnl) {
|
|
||||||
if ($jrnl->id != $journal->id) {
|
|
||||||
$members->push($jrnl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return View::make('transactions.relate', compact('journal', 'members'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO this needs cleaning up and thinking over.
|
|
||||||
*
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function relatedSearch(TransactionJournal $journal)
|
|
||||||
{
|
|
||||||
$search = e(trim(Input::get('searchValue')));
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $repository */
|
|
||||||
$repository = App::make('FireflyIII\Database\TransactionJournal');
|
|
||||||
|
|
||||||
$result = $repository->searchRelated($search, $journal);
|
|
||||||
$result->each(
|
|
||||||
function (TransactionJournal $j) {
|
|
||||||
$j->amount = mf($j->getAmount());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return Response::json($result->toArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TransactionJournal $journal
|
* @param TransactionJournal $journal
|
||||||
@@ -431,16 +221,16 @@ class TransactionController extends BaseController
|
|||||||
$members = new Collection;
|
$members = new Collection;
|
||||||
/** @var TransactionGroup $group */
|
/** @var TransactionGroup $group */
|
||||||
foreach ($journal->transactiongroups()->get() as $group) {
|
foreach ($journal->transactiongroups()->get() as $group) {
|
||||||
/** @var TransactionJournal $jrnl */
|
/** @var TransactionJournal $loopJournal */
|
||||||
foreach ($group->transactionjournals()->get() as $jrnl) {
|
foreach ($group->transactionjournals()->get() as $loopJournal) {
|
||||||
if ($jrnl->id != $journal->id) {
|
if ($loopJournal->id != $journal->id) {
|
||||||
$members->push($jrnl);
|
$members->push($loopJournal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return View::make('transactions.show', compact('journal', 'members'))->with(
|
return View::make('transactions.show', compact('journal', 'members'))->with(
|
||||||
'subTitle', $journal->transactionType->type . ' "' . $journal->description . '"'
|
'subTitle', e($journal->transactionType->type) . ' "' . e($journal->description) . '"'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,156 +242,90 @@ class TransactionController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function store($what)
|
public function store($what)
|
||||||
{
|
{
|
||||||
$data = Input::except('_token');
|
$data = Input::except('_token');
|
||||||
$data['what'] = $what;
|
$transactionType = $this->_repository->getJournalType($what);
|
||||||
$data['currency'] = 'EUR';
|
$transactionCurrency = $this->_repository->getJournalCurrency('EUR');
|
||||||
|
$data['transaction_type_id'] = $transactionType->id;
|
||||||
|
$data['transaction_currency_id'] = $transactionCurrency->id;
|
||||||
|
$data['completed'] = 0;
|
||||||
|
$data['what'] = $what;
|
||||||
|
$data['currency'] = 'EUR';
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $repository */
|
// always validate:
|
||||||
$repository = App::make('FireflyIII\Database\TransactionJournal');
|
$messages = $this->_repository->validate($data);
|
||||||
|
|
||||||
switch ($data['post_submit_action']) {
|
Session::flash('warnings', $messages['warnings']);
|
||||||
default:
|
Session::flash('successes', $messages['successes']);
|
||||||
throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
|
Session::flash('errors', $messages['errors']);
|
||||||
break;
|
if ($messages['errors']->count() > 0) {
|
||||||
case 'create_another':
|
Session::flash('error', 'Could not store transaction: ' . $messages['errors']->first());
|
||||||
case 'store':
|
|
||||||
$messages = $repository->validate($data);
|
|
||||||
/** @var MessageBag $messages ['errors'] */
|
|
||||||
if ($messages['errors']->count() > 0) {
|
|
||||||
Session::flash('warnings', $messages['warnings']);
|
|
||||||
Session::flash('successes', $messages['successes']);
|
|
||||||
Session::flash('error', 'Could not save transaction: ' . $messages['errors']->first());
|
|
||||||
|
|
||||||
return Redirect::route('transactions.create', $what)->withInput()->withErrors($messages['errors']);
|
|
||||||
}
|
|
||||||
// store!
|
|
||||||
$journal = $repository->store($data);
|
|
||||||
Session::flash('success', 'New transaction stored!');
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Trigger a search for the related (if selected)
|
|
||||||
* piggy bank and store an event.
|
|
||||||
*/
|
|
||||||
$piggyID = null;
|
|
||||||
if (!is_null(Input::get('piggybank_id')) && intval(Input::get('piggybank_id')) > 0) {
|
|
||||||
$piggyID = intval(Input::get('piggybank_id'));
|
|
||||||
}
|
|
||||||
Event::fire('transactionJournal.store', [$journal, $piggyID]); // new and used.
|
|
||||||
/*
|
|
||||||
* Also trigger on both transactions.
|
|
||||||
*/
|
|
||||||
/** @var Transaction $transaction */
|
|
||||||
foreach ($journal->transactions as $transaction) {
|
|
||||||
Event::fire('transaction.store', [$transaction]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($data['post_submit_action'] == 'create_another') {
|
|
||||||
return Redirect::route('transactions.create', $what)->withInput();
|
|
||||||
} else {
|
|
||||||
return Redirect::route('transactions.index', $what);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repository->validate($data);
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('transactions.create', $what)->withInput();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO this needs cleaning up and thinking over.
|
|
||||||
*
|
|
||||||
* @param TransactionJournal $journal
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function unrelate(TransactionJournal $journal)
|
|
||||||
{
|
|
||||||
$groups = $journal->transactiongroups()->get();
|
|
||||||
$relatedTo = intval(Input::get('relation'));
|
|
||||||
/** @var TransactionGroup $group */
|
|
||||||
foreach ($groups as $group) {
|
|
||||||
foreach ($group->transactionjournals()->get() as $jrnl) {
|
|
||||||
if ($jrnl->id == $relatedTo) {
|
|
||||||
// remove from group:
|
|
||||||
$group->transactionjournals()->detach($relatedTo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($group->transactionjournals()->count() == 1) {
|
|
||||||
$group->delete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response::json(true);
|
// return to create screen:
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('transactions.create', $data['what'])->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
$journal = $this->_repository->store($data);
|
||||||
|
Event::fire('transactionJournal.store', [$journal, Input::get('piggy_bank_id')]); // new and used.
|
||||||
|
/*
|
||||||
|
* Also trigger on both transactions.
|
||||||
|
*/
|
||||||
|
/** @var Transaction $transaction */
|
||||||
|
foreach ($journal->transactions as $transaction) {
|
||||||
|
Event::fire('transaction.store', [$transaction]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::flash('success', 'Transaction "' . e($data['description']) . '" stored.');
|
||||||
|
if ($data['post_submit_action'] == 'store') {
|
||||||
|
return Redirect::route('transactions.index', $data['what']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redirect::route('transactions.create', $data['what'])->withInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TransactionJournal $journal
|
* @param TransactionJournal $journal
|
||||||
*
|
*
|
||||||
|
* @return $this
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function update(TransactionJournal $journal)
|
public function update(TransactionJournal $journal)
|
||||||
{
|
{
|
||||||
/** @var \FireflyIII\Database\TransactionJournal $repos */
|
$data = Input::except('_token');
|
||||||
$repos = App::make('FireflyIII\Database\TransactionJournal');
|
$data['currency'] = 'EUR';
|
||||||
|
$data['what'] = strtolower($journal->transactionType->type);
|
||||||
|
$data['transaction_type_id'] = $journal->transaction_type_id;
|
||||||
|
$data['transaction_currency_id'] = $journal->transaction_currency_id;
|
||||||
|
$data['completed'] = 1;
|
||||||
|
$messages = $this->_repository->validate($data);
|
||||||
|
|
||||||
$data = Input::except('_token');
|
Session::flash('warnings', $messages['warnings']);
|
||||||
$data['currency'] = 'EUR';
|
Session::flash('successes', $messages['successes']);
|
||||||
$data['what'] = strtolower($journal->transactionType->type);
|
Session::flash('errors', $messages['errors']);
|
||||||
|
if ($messages['errors']->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not update transaction: ' . $messages['errors']->first());
|
||||||
switch (Input::get('post_submit_action')) {
|
|
||||||
case 'update':
|
|
||||||
case 'return_to_edit':
|
|
||||||
$messageBag = $repos->update($journal, $data);
|
|
||||||
if ($messageBag->count() == 0) {
|
|
||||||
// has been saved, return to index:
|
|
||||||
Session::flash('success', 'Transaction updated!');
|
|
||||||
Event::fire('transactionJournal.update', [$journal]); // new and used.
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Also trigger on both transactions.
|
|
||||||
*/
|
|
||||||
/** @var Transaction $transaction */
|
|
||||||
foreach ($journal->transactions as $transaction) {
|
|
||||||
Event::fire('transaction.update', [$transaction]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input::get('post_submit_action') == 'return_to_edit') {
|
|
||||||
return Redirect::route('transactions.edit', $journal->id)->withInput();
|
|
||||||
} else {
|
|
||||||
return Redirect::route('transactions.index', $data['what']);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Session::flash('error', 'Could not update transaction: ' . $journal->getErrors()->first());
|
|
||||||
|
|
||||||
return Redirect::route('transactions.edit', $journal->id)->withInput()->withErrors(
|
|
||||||
$journal->getErrors()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'validate_only':
|
|
||||||
$messageBags = $repos->validate($data);
|
|
||||||
|
|
||||||
Session::flash('warnings', $messageBags['warnings']);
|
|
||||||
Session::flash('successes', $messageBags['successes']);
|
|
||||||
Session::flash('errors', $messageBags['errors']);
|
|
||||||
|
|
||||||
return Redirect::route('transactions.edit', $journal->id)->withInput();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.');
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
|
||||||
|
return Redirect::route('transactions.edit', $journal->id)->withInput();
|
||||||
|
}
|
||||||
|
$this->_repository->update($journal, $data);
|
||||||
|
Session::flash('success', 'Transaction "' . e($data['description']) . '" updated.');
|
||||||
|
Event::fire('transactionJournal.update', [$journal]); // new and used.
|
||||||
|
/** @var Transaction $transaction */
|
||||||
|
foreach ($journal->transactions()->get() as $transaction) {
|
||||||
|
Event::fire('transaction.update', [$transaction]);
|
||||||
|
}
|
||||||
|
if ($data['post_submit_action'] == 'update') {
|
||||||
|
return Redirect::route('transactions.index', $data['what']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// go back to update screen.
|
||||||
|
return Redirect::route('transactions.edit', $journal->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class UserController extends BaseController
|
|||||||
Auth::logout();
|
Auth::logout();
|
||||||
Session::flush();
|
Session::flush();
|
||||||
|
|
||||||
return Redirect::route('index');
|
return Redirect::route('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,29 +67,19 @@ class UserController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function postRegister()
|
public function postRegister()
|
||||||
{
|
{
|
||||||
if (Config::get('auth.allow_register') !== true) {
|
|
||||||
return View::make('error')->with('message', 'Not possible');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\User $repository */
|
/** @var \FireflyIII\Database\User\User $repository */
|
||||||
$repository = App::make('FireflyIII\Database\User');
|
$repository = App::make('FireflyIII\Database\User\User');
|
||||||
|
|
||||||
/** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
|
/** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
|
||||||
$email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
|
$email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
|
||||||
|
|
||||||
$user = $repository->register(Input::all());
|
$user = $repository->register(Input::all());
|
||||||
|
|
||||||
|
|
||||||
//$user = $this->user->register(Input::all());
|
|
||||||
if ($user) {
|
if ($user) {
|
||||||
if (Config::get('auth.verify_mail') === true) {
|
$email->sendVerificationMail($user);
|
||||||
$email->sendVerificationMail($user);
|
|
||||||
|
|
||||||
return View::make('user.verification-pending');
|
return View::make('user.verification-pending');
|
||||||
}
|
|
||||||
$email->sendPasswordMail($user);
|
|
||||||
|
|
||||||
return View::make('user.registered');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -102,11 +92,11 @@ class UserController extends BaseController
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\View\View
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function postRemindme()
|
public function postRemindMe()
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\User $repository */
|
/** @var \FireflyIII\Database\User\User $repository */
|
||||||
$repository = App::make('FireflyIII\Database\User');
|
$repository = App::make('FireflyIII\Database\User\User');
|
||||||
|
|
||||||
/** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
|
/** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
|
||||||
$email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
|
$email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
|
||||||
@@ -116,16 +106,11 @@ class UserController extends BaseController
|
|||||||
if (!$user) {
|
if (!$user) {
|
||||||
Session::flash('error', 'No good!');
|
Session::flash('error', 'No good!');
|
||||||
|
|
||||||
return View::make('user.remindme');
|
return View::make('user.remindMe');
|
||||||
}
|
}
|
||||||
if (Config::get('auth.verify_reset') === true) {
|
$email->sendResetVerification($user);
|
||||||
$email->sendResetVerification($user);
|
|
||||||
|
|
||||||
return View::make('user.verification-pending');
|
return View::make('user.verification-pending');
|
||||||
}
|
|
||||||
$email->sendPasswordMail($user);
|
|
||||||
|
|
||||||
return View::make('user.registered');
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,9 +121,6 @@ class UserController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
if (Config::get('auth.allow_register') !== true) {
|
|
||||||
return View::make('error')->with('message', 'Not possible');
|
|
||||||
}
|
|
||||||
|
|
||||||
return View::make('user.register');
|
return View::make('user.register');
|
||||||
}
|
}
|
||||||
@@ -148,9 +130,9 @@ class UserController extends BaseController
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\View\View
|
* @return \Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function remindme()
|
public function remindMe()
|
||||||
{
|
{
|
||||||
return View::make('user.remindme');
|
return View::make('user.remindMe');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,8 +145,8 @@ class UserController extends BaseController
|
|||||||
public function reset($reset)
|
public function reset($reset)
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var \FireflyIII\Database\User $repository */
|
/** @var \FireflyIII\Database\User\User $repository */
|
||||||
$repository = App::make('FireflyIII\Database\User');
|
$repository = App::make('FireflyIII\Database\User\User');
|
||||||
|
|
||||||
/** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
|
/** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
|
||||||
$email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
|
$email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
|
||||||
@@ -176,7 +158,7 @@ class UserController extends BaseController
|
|||||||
return View::make('user.registered');
|
return View::make('user.registered');
|
||||||
}
|
}
|
||||||
|
|
||||||
return View::make('error')->with('message', 'Yo no hablo reset code!');
|
return View::make('error')->with('message', 'No reset code found!');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CreateUsersTable
|
* Class CreateUsersTable
|
||||||
*
|
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateUsersTable extends Migration
|
class CreateUsersTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateAccountTypesTable
|
* Class CreateAccountTypesTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateAccountTypesTable extends Migration
|
class CreateAccountTypesTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateAccountsTable
|
* Class CreateAccountsTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateAccountsTable extends Migration
|
class CreateAccountsTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateComponentsTable
|
* Class CreateComponentsTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateComponentsTable extends Migration
|
class CreateComponentsTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreatePiggybanksTable
|
* Class CreatePiggybanksTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreatePiggybanksTable extends Migration
|
class CreatePiggybanksTable extends Migration
|
||||||
{
|
{
|
||||||
@@ -46,7 +45,7 @@ class CreatePiggybanksTable extends Migration
|
|||||||
$table->boolean('remind_me');
|
$table->boolean('remind_me');
|
||||||
$table->integer('order')->unsigned();
|
$table->integer('order')->unsigned();
|
||||||
|
|
||||||
// connect account to piggybank.
|
// connect account to piggy bank.
|
||||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||||
|
|
||||||
// for an account, the name must be unique.
|
// for an account, the name must be unique.
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateTransactionCurrenciesTable
|
* Class CreateTransactionCurrenciesTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateTransactionCurrenciesTable extends Migration
|
class CreateTransactionCurrenciesTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateTransactionTypesTable
|
* Class CreateTransactionTypesTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateTransactionTypesTable extends Migration
|
class CreateTransactionTypesTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateRecurringTransactionsTable
|
* Class CreateRecurringTransactionsTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateRecurringTransactionsTable extends Migration
|
class CreateRecurringTransactionsTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateTransactionJournalsTable
|
* Class CreateTransactionJournalsTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateTransactionJournalsTable extends Migration
|
class CreateTransactionJournalsTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateTransactionsTable
|
* Class CreateTransactionsTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateTransactionsTable extends Migration
|
class CreateTransactionsTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateComponentTransactionTable
|
* Class CreateComponentTransactionTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateComponentTransactionTable extends Migration
|
class CreateComponentTransactionTable extends Migration
|
||||||
{
|
{
|
||||||
@@ -18,7 +17,7 @@ class CreateComponentTransactionTable extends Migration
|
|||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::drop('component_transaction');
|
Schema::dropIfExists('component_transaction');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateComponentTransactionJournalTable
|
* Class CreateComponentTransactionJournalTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateComponentTransactionJournalTable extends Migration
|
class CreateComponentTransactionJournalTable extends Migration
|
||||||
{
|
{
|
||||||
@@ -30,19 +29,19 @@ class CreateComponentTransactionJournalTable extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create(
|
Schema::create(
|
||||||
'component_transaction_journal', function (Blueprint $table) {
|
'component_transaction_journal', function (Blueprint $table) {
|
||||||
$table->increments('id');
|
$table->increments('id');
|
||||||
$table->integer('component_id')->unsigned();
|
$table->integer('component_id')->unsigned();
|
||||||
$table->integer('transaction_journal_id')->unsigned();
|
$table->integer('transaction_journal_id')->unsigned();
|
||||||
|
|
||||||
// link components with component_id
|
// link components with component_id
|
||||||
$table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
|
$table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
|
||||||
|
|
||||||
// link transaction journals with transaction_journal_id
|
// link transaction journals with transaction_journal_id
|
||||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||||
|
|
||||||
// combo must be unique:
|
// combo must be unique:
|
||||||
$table->unique(['component_id', 'transaction_journal_id'],'cid_tjid_unique');
|
$table->unique(['component_id', 'transaction_journal_id'], 'cid_tjid_unique');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreatePreferencesTable
|
* Class CreatePreferencesTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreatePreferencesTable extends Migration
|
class CreatePreferencesTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CreateSessionTable
|
* Class CreateSessionTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateSessionTable extends Migration
|
class CreateSessionTable extends Migration
|
||||||
{
|
{
|
||||||
@@ -28,11 +28,11 @@ class CreateSessionTable extends Migration
|
|||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
Schema::create(
|
Schema::create(
|
||||||
'sessions', function ($t) {
|
'sessions', function (Blueprint $table) {
|
||||||
$t->string('id')->unique();
|
$table->string('id')->unique();
|
||||||
$t->text('payload');
|
$table->text('payload');
|
||||||
$t->integer('last_activity');
|
$table->integer('last_activity');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateLimitsTable
|
* Class CreateLimitsTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateLimitsTable extends Migration
|
class CreateLimitsTable extends Migration
|
||||||
{
|
{
|
||||||
@@ -30,19 +29,19 @@ class CreateLimitsTable extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create(
|
Schema::create(
|
||||||
'limits', function (Blueprint $table) {
|
'limits', function (Blueprint $table) {
|
||||||
$table->increments('id');
|
$table->increments('id');
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
$table->integer('component_id')->unsigned();
|
$table->integer('component_id')->unsigned();
|
||||||
$table->date('startdate');
|
$table->date('startdate');
|
||||||
$table->decimal('amount', 10, 2);
|
$table->decimal('amount', 10, 2);
|
||||||
$table->boolean('repeats');
|
$table->boolean('repeats');
|
||||||
$table->enum('repeat_freq', ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly']);
|
$table->enum('repeat_freq', ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly']);
|
||||||
|
|
||||||
$table->unique(['component_id', 'startdate', 'repeat_freq']);
|
$table->unique(['component_id', 'startdate', 'repeat_freq'], 'unique_ci_combi');
|
||||||
|
|
||||||
// connect component
|
// connect component
|
||||||
$table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
|
$table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateLimitRepeatTable
|
* Class CreateLimitRepeatTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateLimitRepeatTable extends Migration
|
class CreateLimitRepeatTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateComponentRecurringTransactionTable
|
* Class CreateComponentRecurringTransactionTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateComponentRecurringTransactionTable extends Migration
|
class CreateComponentRecurringTransactionTable extends Migration
|
||||||
{
|
{
|
||||||
@@ -18,7 +17,7 @@ class CreateComponentRecurringTransactionTable extends Migration
|
|||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::drop('component_recurring_transaction');
|
Schema::dropIfExists('component_recurring_transaction');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,21 +29,21 @@ class CreateComponentRecurringTransactionTable extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create(
|
Schema::create(
|
||||||
'component_recurring_transaction', function (Blueprint $table) {
|
'component_recurring_transaction', function (Blueprint $table) {
|
||||||
$table->increments('id');
|
$table->increments('id');
|
||||||
$table->integer('component_id')->unsigned();
|
$table->integer('component_id')->unsigned();
|
||||||
$table->integer('recurring_transaction_id')->unsigned();
|
$table->integer('recurring_transaction_id')->unsigned();
|
||||||
$table->boolean('optional');
|
$table->boolean('optional');
|
||||||
|
|
||||||
// link components with component_id
|
// link components with component_id
|
||||||
$table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
|
$table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
|
||||||
|
|
||||||
// link transaction journals with transaction_journal_id
|
// link transaction journals with transaction_journal_id
|
||||||
$table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('cascade');
|
$table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('cascade');
|
||||||
|
|
||||||
// component and recurring transaction must be unique.
|
// component and recurring transaction must be unique.
|
||||||
$table->unique(['component_id','recurring_transaction_id'],'cid_rtid_unique');
|
$table->unique(['component_id', 'recurring_transaction_id'], 'cid_rtid_unique');
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreatePiggyInstance
|
* Class CreatePiggyInstance
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreatePiggybankRepetitionsTable extends Migration
|
class CreatePiggybankRepetitionsTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreatePiggybankEventsTable
|
* Class CreatePiggybankEventsTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreatePiggybankEventsTable extends Migration
|
class CreatePiggybankEventsTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateRemindersTable
|
* Class CreateRemindersTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateRemindersTable extends Migration
|
class CreateRemindersTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateAccountMetaTable
|
* Class CreateAccountMetaTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateAccountMetaTable extends Migration
|
class CreateAccountMetaTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint;
|
|||||||
/**
|
/**
|
||||||
* Class CreateTransactionGroupsTable
|
* Class CreateTransactionGroupsTable
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ShortMethodName)
|
|
||||||
*/
|
*/
|
||||||
class CreateTransactionGroupsTable extends Migration
|
class CreateTransactionGroupsTable extends Migration
|
||||||
{
|
{
|
||||||
|
|||||||
494
app/database/migrations/2014_12_13_190730_changes_for_v321.php
Normal file
494
app/database/migrations/2014_12_13_190730_changes_for_v321.php
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Down:
|
||||||
|
* 1. Create new Components based on Budgets.
|
||||||
|
* 2. Create new Components based on Categories
|
||||||
|
* 3. Recreate component_id in limits
|
||||||
|
* 4. Update all budget_limits entries (component_id).
|
||||||
|
* 5. Add the foreign key to component_id in budget_limits
|
||||||
|
* 6. Drop column 'budget_id' in budget_limits.
|
||||||
|
* 7. Create table journal_components.
|
||||||
|
* 8. create entries for budgets in journal_components.
|
||||||
|
* 9. create entries for categories in journal_components.
|
||||||
|
* 10. drop table budget_journals
|
||||||
|
* 11. drop table category_journals
|
||||||
|
* 12. drop table budgets
|
||||||
|
* 13. drop table categories.
|
||||||
|
* 14. rename budget_limits to limits.
|
||||||
|
* 15. Rename piggy_bank_events to piggybank_events
|
||||||
|
* 16. Rename field 'budget_limit_id' to 'limit_id' in 'limit_repetitions'
|
||||||
|
* 17. Do not recreate component_recurring_transaction
|
||||||
|
* 18. Do not recreate component_transaction
|
||||||
|
* 19. Do not recreate field 'piggybank_id' in 'transactions'
|
||||||
|
* 20. Drop fields from currency table.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Up:
|
||||||
|
*
|
||||||
|
* 1. Create new budget table.
|
||||||
|
* 2. Create new category table.
|
||||||
|
* 3. Create journal_budget table.
|
||||||
|
* 4. Create journal_category table.
|
||||||
|
* 5. Move budgets to new budgets table AND move journal_components to budget_components.
|
||||||
|
* 6. Move categories to categories table AND move journal_components to category_components.
|
||||||
|
* 7. Rename limits to budget_limits.
|
||||||
|
* 8. Rename piggybank_events to piggy_bank_events
|
||||||
|
* 9. Rename field 'limit_id' to 'budget_limit_id' in 'limit_repetitions'
|
||||||
|
* 10. Create field budget_id in budget_limits.
|
||||||
|
* 11. Update budget_limits with budgets (instead of components).
|
||||||
|
* 12. drop table journal_components
|
||||||
|
* 13. Drop table component_recurring_transaction
|
||||||
|
* 14. Drop table component_transaction
|
||||||
|
* 15. Drop field 'piggybank_id' from 'transactions'
|
||||||
|
* 16. Drop field 'component_id' from 'budget_limits'
|
||||||
|
* 17. Expand currency table with new fields.
|
||||||
|
*
|
||||||
|
* Class ChangesForV321
|
||||||
|
*/
|
||||||
|
class ChangesForV321 extends Migration
|
||||||
|
{
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->moveBudgetsBack(); // 1.
|
||||||
|
$this->moveCategoriesBack(); // 2.
|
||||||
|
$this->createComponentId(); // 3.
|
||||||
|
$this->updateComponentInBudgetLimits(); // 4.
|
||||||
|
$this->createComponentIdForeignKey(); // 5.
|
||||||
|
$this->dropBudgetIdColumnInBudgetLimits(); // 6.
|
||||||
|
$createComponents = new CreateComponentTransactionJournalTable; // 7.
|
||||||
|
$createComponents->up();
|
||||||
|
$this->moveBackEntriesForBudgetsInJoinedTable(); // 8.
|
||||||
|
$this->moveBackEntriesForCategoriesInJoinedTable(); // 9.
|
||||||
|
$this->dropBudgetJournalTable(); // 10.
|
||||||
|
$this->dropCategoryJournalTable(); // 11.
|
||||||
|
$this->dropBudgetTable(); // 12.
|
||||||
|
$this->dropCategoryTable(); // 13.
|
||||||
|
$this->renameBudgetLimits(); // 14.
|
||||||
|
$this->renamePiggyBankEvents(); // 15.
|
||||||
|
$this->renameBudgetLimitToBudgetInRepetitions(); // 16.
|
||||||
|
// 17, 18, 19
|
||||||
|
$this->dropFieldsFromCurrencyTable(); // 20.
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function moveBudgetsBack()
|
||||||
|
{
|
||||||
|
Budget::get()->each(
|
||||||
|
function (Budget $budget) {
|
||||||
|
Component::firstOrCreate(
|
||||||
|
[
|
||||||
|
'name' => $budget->name,
|
||||||
|
'user_id' => $budget->user_id,
|
||||||
|
'class' => 'Budget'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function moveCategoriesBack()
|
||||||
|
{
|
||||||
|
Category::get()->each(
|
||||||
|
function (Category $category) {
|
||||||
|
Component::firstOrCreate(
|
||||||
|
[
|
||||||
|
'name' => $category->name,
|
||||||
|
'user_id' => $category->user_id,
|
||||||
|
'class' => 'Category'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createComponentId()
|
||||||
|
{
|
||||||
|
Schema::table(
|
||||||
|
'budget_limits', function (Blueprint $table) {
|
||||||
|
$table->integer('component_id')->unsigned();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateComponentInBudgetLimits()
|
||||||
|
{
|
||||||
|
BudgetLimit::get()->each(
|
||||||
|
function (BudgetLimit $bl) {
|
||||||
|
$budgetId = $bl->budget_id;
|
||||||
|
$budget = Budget::find($budgetId);
|
||||||
|
if ($budget) {
|
||||||
|
$component = Component::where('class', 'Budget')->where('user_id', $budget->user_id)->where('name', $budget->name)->first();
|
||||||
|
if ($component) {
|
||||||
|
$bl->component_id = $component->id;
|
||||||
|
$bl->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createComponentIdForeignKey()
|
||||||
|
{
|
||||||
|
Schema::table(
|
||||||
|
'budget_limits', function (Blueprint $table) {
|
||||||
|
$table->foreign('component_id', 'limits_component_id_foreign')->references('id')->on('components')->onDelete('cascade');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropBudgetIdColumnInBudgetLimits()
|
||||||
|
{
|
||||||
|
Schema::table(
|
||||||
|
'budget_limits', function (Blueprint $table) {
|
||||||
|
$table->dropForeign('bid_foreign');
|
||||||
|
$table->dropColumn('budget_id'); // also drop foreign key!
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function moveBackEntriesForBudgetsInJoinedTable()
|
||||||
|
{
|
||||||
|
$set = DB::table('budget_transaction_journal')->get();
|
||||||
|
foreach ($set as $entry) {
|
||||||
|
$budget = Budget::find($entry->budget_id);
|
||||||
|
if ($budget) {
|
||||||
|
$component = Component::where('class', 'Budget')->where('name', $budget->name)->where('user_id', $budget->user_id)->first();
|
||||||
|
if ($component) {
|
||||||
|
DB::table('component_transaction_journal')->insert(
|
||||||
|
[
|
||||||
|
'component_id' => $component->id,
|
||||||
|
'transaction_journal_id' => $entry->transaction_journal_id
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function moveBackEntriesForCategoriesInJoinedTable()
|
||||||
|
{
|
||||||
|
$set = DB::table('category_transaction_journal')->get();
|
||||||
|
foreach ($set as $entry) {
|
||||||
|
$category = Category::find($entry->category_id);
|
||||||
|
if ($category) {
|
||||||
|
$component = Component::where('class', 'Category')->where('name', $category->name)->where('user_id', $category->user_id)->first();
|
||||||
|
if ($component) {
|
||||||
|
DB::table('component_transaction_journal')->insert(
|
||||||
|
[
|
||||||
|
'component_id' => $component->id,
|
||||||
|
'transaction_journal_id' => $entry->transaction_journal_id
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropBudgetJournalTable()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('budget_transaction_journal');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropCategoryJournalTable()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('category_transaction_journal');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropBudgetTable()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('budgets');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropCategoryTable()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('categories');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renameBudgetLimits()
|
||||||
|
{
|
||||||
|
Schema::rename('budget_limits', 'limits');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renamePiggyBankEvents()
|
||||||
|
{
|
||||||
|
Schema::rename('piggy_bank_events', 'piggybank_events');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renameBudgetLimitToBudgetInRepetitions()
|
||||||
|
{
|
||||||
|
Schema::table(
|
||||||
|
'limit_repetitions', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('budget_limit_id', 'limit_id');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropFieldsFromCurrencyTable()
|
||||||
|
{
|
||||||
|
|
||||||
|
Schema::table(
|
||||||
|
'transaction_currencies', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('symbol');
|
||||||
|
$table->dropColumn('name');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$this->createBudgetTable(); // 1.
|
||||||
|
$this->createCategoryTable(); // 2.
|
||||||
|
$this->createBudgetJournalTable(); // 3
|
||||||
|
$this->createCategoryJournalTable(); // 4.
|
||||||
|
$this->moveBudgets(); // 5.
|
||||||
|
$this->moveCategories(); // 6.
|
||||||
|
$this->correctNameForBudgetLimits(); // 7.
|
||||||
|
$this->correctNameForPiggyBankEvents(); // 8.
|
||||||
|
$this->renameBudgetToBudgetLimitInRepetitions(); // 9.
|
||||||
|
$this->addBudgetIdFieldToBudgetLimits(); // 10.
|
||||||
|
$this->moveComponentIdToBudgetId(); // 11.
|
||||||
|
$this->dropComponentJournalTable(); // 12.
|
||||||
|
$this->dropComponentRecurringTransactionTable(); // 13.
|
||||||
|
$this->dropComponentTransactionTable(); // 14.
|
||||||
|
$this->dropPiggyBankIdFromTransactions(); // 15.
|
||||||
|
$this->dropComponentIdFromBudgetLimits(); // 16.
|
||||||
|
$this->expandCurrencyTable(); // 17.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createBudgetTable()
|
||||||
|
{
|
||||||
|
Schema::create(
|
||||||
|
'budgets', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
$table->string('name', 50);
|
||||||
|
$table->integer('user_id')->unsigned();
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
$table->unique(['user_id', 'name']);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createCategoryTable()
|
||||||
|
{
|
||||||
|
Schema::create(
|
||||||
|
'categories', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
$table->string('name', 50);
|
||||||
|
$table->integer('user_id')->unsigned();
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
$table->unique(['user_id', 'name']);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createBudgetJournalTable()
|
||||||
|
{
|
||||||
|
Schema::create(
|
||||||
|
'budget_transaction_journal', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->integer('budget_id')->unsigned();
|
||||||
|
$table->integer('transaction_journal_id')->unsigned();
|
||||||
|
$table->foreign('budget_id')->references('id')->on('budgets')->onDelete('cascade');
|
||||||
|
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||||
|
$table->unique(['budget_id', 'transaction_journal_id'], 'budid_tjid_unique');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createCategoryJournalTable()
|
||||||
|
{
|
||||||
|
Schema::create(
|
||||||
|
'category_transaction_journal', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->integer('category_id')->unsigned();
|
||||||
|
$table->integer('transaction_journal_id')->unsigned();
|
||||||
|
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
|
||||||
|
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||||
|
$table->unique(['category_id', 'transaction_journal_id'], 'catid_tjid_unique');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function moveBudgets()
|
||||||
|
{
|
||||||
|
Component::where('class', 'Budget')->get()->each(
|
||||||
|
function (Component $c) {
|
||||||
|
$entry = [
|
||||||
|
'user_id' => $c->user_id,
|
||||||
|
'name' => $c->name
|
||||||
|
|
||||||
|
];
|
||||||
|
$budget = Budget::firstOrCreate($entry);
|
||||||
|
Log::debug('Migrated budget #' . $budget->id . ': ' . $budget->name);
|
||||||
|
// create entry in budget_transaction_journal
|
||||||
|
$connections = DB::table('component_transaction_journal')->where('component_id', $c->id)->get();
|
||||||
|
foreach ($connections as $connection) {
|
||||||
|
DB::table('budget_transaction_journal')->insert(
|
||||||
|
[
|
||||||
|
'budget_id' => $budget->id,
|
||||||
|
'transaction_journal_id' => $connection->transaction_journal_id
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function moveCategories()
|
||||||
|
{
|
||||||
|
Component::where('class', 'Category')->get()->each(
|
||||||
|
function (Component $c) {
|
||||||
|
$entry = [
|
||||||
|
'user_id' => $c->user_id,
|
||||||
|
'name' => $c->name
|
||||||
|
|
||||||
|
];
|
||||||
|
$category = Category::firstOrCreate($entry);
|
||||||
|
Log::debug('Migrated category #' . $category->id . ': ' . $category->name);
|
||||||
|
// create entry in category_transaction_journal
|
||||||
|
$connections = DB::table('component_transaction_journal')->where('component_id', $c->id)->get();
|
||||||
|
foreach ($connections as $connection) {
|
||||||
|
DB::table('category_transaction_journal')->insert(
|
||||||
|
[
|
||||||
|
'category_id' => $category->id,
|
||||||
|
'transaction_journal_id' => $connection->transaction_journal_id
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function correctNameForBudgetLimits()
|
||||||
|
{
|
||||||
|
Schema::rename('limits', 'budget_limits');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function correctNameForPiggyBankEvents()
|
||||||
|
{
|
||||||
|
Schema::rename('piggybank_events', 'piggy_bank_events');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renameBudgetToBudgetLimitInRepetitions()
|
||||||
|
{
|
||||||
|
Schema::table(
|
||||||
|
'limit_repetitions', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('limit_id', 'budget_limit_id');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addBudgetIdFieldToBudgetLimits()
|
||||||
|
{
|
||||||
|
Schema::table(
|
||||||
|
'budget_limits', function (Blueprint $table) {
|
||||||
|
$table->integer('budget_id', false, true)->nullable()->after('updated_at');
|
||||||
|
$table->foreign('budget_id', 'bid_foreign')->references('id')->on('budgets')->onDelete('cascade');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function moveComponentIdToBudgetId()
|
||||||
|
{
|
||||||
|
\Log::debug('Now in moveComponentIdToBudgetId()');
|
||||||
|
BudgetLimit::get()->each(
|
||||||
|
function (BudgetLimit $bl) {
|
||||||
|
\Log::debug('Now at budgetLimit #' . $bl->id . ' with component_id: ' . $bl->component_id);
|
||||||
|
$component = Component::find($bl->component_id);
|
||||||
|
if ($component) {
|
||||||
|
\Log::debug('Found component with id #' . $component->id . ' and name ' . $component->name);
|
||||||
|
$budget = Budget::whereName($component->name)->whereUserId($component->user_id)->first();
|
||||||
|
if ($budget) {
|
||||||
|
\Log::debug('Found a budget with ID #' . $budget->id . ' and name ' . $budget->name);
|
||||||
|
$bl->budget_id = $budget->id;
|
||||||
|
$bl->save();
|
||||||
|
\Log::debug('Connected budgetLimit #' . $bl->id . ' to budget_id' . $budget->id);
|
||||||
|
} else {
|
||||||
|
\Log::debug('Could not find a matching budget with name ' . $component->name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
\Log::debug('Could not find a component with id ' . $bl->component_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
\Log::debug('Done with moveComponentIdToBudgetId()');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropComponentJournalTable()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('component_transaction_journal');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropComponentRecurringTransactionTable()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('component_recurring_transaction');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropComponentTransactionTable()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('component_transaction');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropPiggyBankIdFromTransactions()
|
||||||
|
{
|
||||||
|
|
||||||
|
Schema::table(
|
||||||
|
'transactions', function (Blueprint $table) {
|
||||||
|
if (Schema::hasColumn('transactions', 'piggybank_id')) {
|
||||||
|
$table->dropForeign('transactions_piggybank_id_foreign');
|
||||||
|
$table->dropColumn('piggybank_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dropComponentIdFromBudgetLimits()
|
||||||
|
{
|
||||||
|
Schema::table(
|
||||||
|
'budget_limits', function (Blueprint $table) {
|
||||||
|
$table->dropForeign('limits_component_id_foreign');
|
||||||
|
$table->dropColumn('component_id');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function expandCurrencyTable()
|
||||||
|
{
|
||||||
|
Schema::table(
|
||||||
|
'transaction_currencies', function (Blueprint $table) {
|
||||||
|
$table->string('name', 48)->nullable();
|
||||||
|
$table->string('symbol', 8)->nullable();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
\DB::update('UPDATE `transaction_currencies` SET `symbol` = "€", `name` = "Euro" WHERE `code` = "EUR";');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
168
app/database/migrations/2014_12_24_191544_changes_for_v322.php
Normal file
168
app/database/migrations/2014_12_24_191544_changes_for_v322.php
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ChangesForV322
|
||||||
|
*/
|
||||||
|
class ChangesForV322 extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
// rename tables:
|
||||||
|
Schema::rename('piggy_bank_repetitions', 'piggybank_repetitions');
|
||||||
|
Schema::rename('piggy_banks', 'piggybanks');
|
||||||
|
|
||||||
|
// rename fields
|
||||||
|
Schema::table(
|
||||||
|
'piggy_bank_events', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('piggy_bank_id', 'piggybank_id');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Schema::table(
|
||||||
|
'piggybank_repetitions', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('piggy_bank_id', 'piggybank_id');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove soft delete to piggy banks
|
||||||
|
Schema::table(
|
||||||
|
'piggybanks', function (Blueprint $table) {
|
||||||
|
$table->dropSoftDeletes();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// drop keys from bills (foreign bills_uid_for and unique uid_name_unique)
|
||||||
|
Schema::table(
|
||||||
|
'bills', function (Blueprint $table) {
|
||||||
|
$table->dropForeign('bills_uid_for');
|
||||||
|
$table->dropUnique('uid_name_unique');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// drop foreign key from transaction_journals (bill_id_foreign)
|
||||||
|
Schema::table(
|
||||||
|
'transaction_journals', function (Blueprint $table) {
|
||||||
|
$table->dropForeign('bill_id_foreign');
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// drop foreign key from budget_limits:
|
||||||
|
Schema::table(
|
||||||
|
'budget_limits', function (Blueprint $table) {
|
||||||
|
$table->dropForeign('bid_foreign');
|
||||||
|
$table->dropUnique('unique_bl_combi');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// rename bills to recurring_transactions
|
||||||
|
Schema::rename('bills', 'recurring_transactions');
|
||||||
|
// recreate foreign key recurring_transactions_user_id_foreign in recurring_transactions
|
||||||
|
// recreate unique recurring_transactions_user_id_name_unique in recurring_transactions
|
||||||
|
Schema::table(
|
||||||
|
'recurring_transactions', function (Blueprint $table) {
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
$table->unique(['user_id', 'name']);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// rename bill_id to recurring_transaction_id
|
||||||
|
// recreate foreign transaction_journals_recurring_transaction_id_foreign in transaction_journals
|
||||||
|
Schema::table(
|
||||||
|
'transaction_journals', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('bill_id', 'recurring_transaction_id');
|
||||||
|
$table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('set null');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
// rename tables:
|
||||||
|
Schema::rename('piggybank_repetitions', 'piggy_bank_repetitions');
|
||||||
|
Schema::rename('piggybanks', 'piggy_banks');
|
||||||
|
|
||||||
|
// recreate it the correct way:
|
||||||
|
Schema::table(
|
||||||
|
'budget_limits', function (Blueprint $table) {
|
||||||
|
$table->unique(['budget_id', 'startdate', 'repeat_freq'], 'unique_bl_combi');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// rename fields
|
||||||
|
Schema::table(
|
||||||
|
'piggy_bank_events', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('piggybank_id', 'piggy_bank_id');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Schema::table(
|
||||||
|
'piggy_bank_repetitions', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('piggybank_id', 'piggy_bank_id');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// add soft delete to piggy banks
|
||||||
|
Schema::table(
|
||||||
|
'piggy_banks', function (Blueprint $table) {
|
||||||
|
$table->softDeletes();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// rename everything related to recurring transactions, aka bills:
|
||||||
|
Schema::table(
|
||||||
|
'transaction_journals', function (Blueprint $table) {
|
||||||
|
|
||||||
|
|
||||||
|
// drop relation
|
||||||
|
$table->dropForeign('transaction_journals_recurring_transaction_id_foreign');
|
||||||
|
// rename column
|
||||||
|
$table->renameColumn('recurring_transaction_id', 'bill_id');
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Schema::table(
|
||||||
|
'recurring_transactions', function (Blueprint $table) {
|
||||||
|
$table->dropForeign('recurring_transactions_user_id_foreign');
|
||||||
|
$table->dropUnique('recurring_transactions_user_id_name_unique');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// rename table:
|
||||||
|
Schema::rename('recurring_transactions', 'bills');
|
||||||
|
|
||||||
|
// recreate foreign relation:
|
||||||
|
Schema::table(
|
||||||
|
'transaction_journals', function (Blueprint $table) {
|
||||||
|
$table->foreign('bill_id', 'bill_id_foreign')->references('id')->on('bills')->onDelete('set null');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// recreate more foreign relations.
|
||||||
|
Schema::table(
|
||||||
|
'bills', function (Blueprint $table) {
|
||||||
|
// connect user id to users
|
||||||
|
$table->foreign('user_id', 'bills_uid_for')->references('id')->on('users')->onDelete('cascade');
|
||||||
|
|
||||||
|
// for a user, the name must be unique
|
||||||
|
$table->unique(['user_id', 'name'], 'uid_name_unique');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -38,4 +38,4 @@ class AccountTypeSeeder extends Seeder
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,19 +8,15 @@ class DefaultUserSeeder extends Seeder
|
|||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
DB::table('users')->delete();
|
DB::table('users')->delete();
|
||||||
if (App::environment() == 'testing') {
|
if (App::environment() == 'testing' || App::environment() == 'homestead') {
|
||||||
|
|
||||||
|
User::create(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james', 'reset' => null, 'remember_token' => null]);
|
||||||
|
User::create(['email' => 'acceptance@example.com', 'password' => 'acceptance', 'reset' => null, 'remember_token' => null]);
|
||||||
|
User::create(['email' => 'functional@example.com', 'password' => 'functional', 'reset' => null, 'remember_token' => null]);
|
||||||
|
User::create(['email' => 'reset@example.com', 'password' => 'functional', 'reset' => 'okokokokokokokokokokokokokokokok', 'remember_token' => null]);
|
||||||
|
|
||||||
User::create(
|
|
||||||
['email' => 'thegrumpydictator@gmail.com', 'password' => 'james', 'reset' => null, 'remember_token' => null, 'migrated' => 0]
|
|
||||||
);
|
|
||||||
User::create(
|
|
||||||
['email' => 'acceptance@example.com', 'password' => 'acceptance', 'reset' => null, 'remember_token' => null, 'migrated' => 0]
|
|
||||||
);
|
|
||||||
User::create(
|
|
||||||
['email' => 'functional@example.com', 'password' => 'functional', 'reset' => null, 'remember_token' => null, 'migrated' => 0]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,168 +2,219 @@
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @SuppressWarnings("CamelCase") // I'm fine with this.
|
||||||
|
*
|
||||||
|
* Class TestContentSeeder
|
||||||
|
*/
|
||||||
class TestContentSeeder extends Seeder
|
class TestContentSeeder extends Seeder
|
||||||
{
|
{
|
||||||
|
/** @var string */
|
||||||
|
public $eom;
|
||||||
|
/** @var string */
|
||||||
|
public $neom;
|
||||||
|
/** @var string */
|
||||||
|
public $nsom;
|
||||||
|
/** @var string */
|
||||||
|
public $som;
|
||||||
|
/** @var string */
|
||||||
|
public $today;
|
||||||
|
/** @var string */
|
||||||
|
public $yaeom;
|
||||||
|
/** @var string */
|
||||||
|
public $yasom;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_endOfMonth;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_nextEndOfMonth;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_nextStartOfMonth;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_startOfMonth;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_today;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_yearAgoEndOfMonth;
|
||||||
|
/** @var Carbon */
|
||||||
|
protected $_yearAgoStartOfMonth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->_startOfMonth = Carbon::now()->startOfMonth();
|
||||||
|
$this->som = $this->_startOfMonth->format('Y-m-d');
|
||||||
|
|
||||||
|
$this->_endOfMonth = Carbon::now()->endOfMonth();
|
||||||
|
$this->eom = $this->_endOfMonth->format('Y-m-d');
|
||||||
|
|
||||||
|
$this->_nextStartOfMonth = Carbon::now()->addMonth()->startOfMonth();
|
||||||
|
$this->nsom = $this->_nextStartOfMonth->format('Y-m-d');
|
||||||
|
|
||||||
|
$this->_nextEndOfMonth = Carbon::now()->addMonth()->endOfMonth();
|
||||||
|
$this->neom = $this->_nextEndOfMonth->format('Y-m-d');
|
||||||
|
|
||||||
|
$this->_yearAgoStartOfMonth = Carbon::now()->subYear()->startOfMonth();
|
||||||
|
$this->yasom = $this->_yearAgoStartOfMonth->format('Y-m-d');
|
||||||
|
|
||||||
|
$this->_yearAgoEndOfMonth = Carbon::now()->subYear()->startOfMonth();
|
||||||
|
$this->yaeom = $this->_yearAgoEndOfMonth->format('Y-m-d');
|
||||||
|
|
||||||
|
|
||||||
|
$this->_today = Carbon::now();
|
||||||
|
$this->today = $this->_today->format('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dates are always this month, the start of this month or earlier.
|
||||||
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
if (App::environment() == 'testing') {
|
if (App::environment() == 'testing' || App::environment() == 'homestead') {
|
||||||
|
|
||||||
$assetType = AccountType::whereType('Asset account')->first();
|
|
||||||
$expenseType = AccountType::whereType('Expense account')->first();
|
|
||||||
$revenueType = AccountType::whereType('Revenue account')->first();
|
|
||||||
$ibType = AccountType::whereType('Initial balance account')->first();
|
|
||||||
|
|
||||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
|
||||||
|
|
||||||
$obType = TransactionType::whereType('Opening balance')->first();
|
|
||||||
$withdrawal = TransactionType::whereType('Withdrawal')->first();
|
|
||||||
$transfer = TransactionType::whereType('Transfer')->first();
|
|
||||||
$deposit = TransactionType::whereType('Deposit')->first();
|
|
||||||
|
|
||||||
$user = User::whereEmail('thegrumpydictator@gmail.com')->first();
|
$user = User::whereEmail('thegrumpydictator@gmail.com')->first();
|
||||||
|
|
||||||
if ($user) {
|
// create initial accounts and various other stuff:
|
||||||
// create two asset accounts.
|
$this->createAssetAccounts($user);
|
||||||
$checking = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Checking account', 'active' => 1]);
|
$this->createBudgets($user);
|
||||||
$savings = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Savings account', 'active' => 1]);
|
$this->createCategories($user);
|
||||||
|
$this->createPiggyBanks($user);
|
||||||
|
$this->createReminders($user);
|
||||||
|
$this->createRecurringTransactions($user);
|
||||||
|
$this->createBills($user);
|
||||||
|
$this->createExpenseAccounts($user);
|
||||||
|
$this->createRevenueAccounts($user);
|
||||||
|
|
||||||
// create two budgets:
|
// get some objects from the database:
|
||||||
$groceriesBudget = Budget::create(['user_id' => $user->id, 'name' => 'Groceries']);
|
$checking = Account::whereName('Checking account')->orderBy('id', 'DESC')->first();
|
||||||
$billsBudget = Budget::create(['user_id' => $user->id, 'name' => 'Bills']);
|
$savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first();
|
||||||
|
$landLord = Account::whereName('Land lord')->orderBy('id', 'DESC')->first();
|
||||||
// create two categories:
|
$utilities = Account::whereName('Utilities company')->orderBy('id', 'DESC')->first();
|
||||||
$dailyGroceries = Category::create(['user_id' => $user->id, 'name' => 'Daily groceries']);
|
$television = Account::whereName('TV company')->orderBy('id', 'DESC')->first();
|
||||||
$lunch = Category::create(['user_id' => $user->id, 'name' => 'Lunch']);
|
$phone = Account::whereName('Phone agency')->orderBy('id', 'DESC')->first();
|
||||||
$house = Category::create(['user_id' => $user->id, 'name' => 'House']);
|
$employer = Account::whereName('Employer')->orderBy('id', 'DESC')->first();
|
||||||
|
|
||||||
// create some expense accounts.
|
|
||||||
$ah = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Albert Heijn', 'active' => 1]);
|
|
||||||
$plus = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'PLUS', 'active' => 1]);
|
|
||||||
$vitens = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Vitens', 'active' => 1]);
|
|
||||||
$greenchoice = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Greenchoice', 'active' => 1]);
|
|
||||||
$portaal = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Portaal', 'active' => 1]);
|
|
||||||
$store = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Buy More', 'active' => 1]);
|
|
||||||
|
|
||||||
// create three revenue accounts.
|
|
||||||
$employer = Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Employer', 'active' => 1]);
|
|
||||||
$taxes = Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'IRS', 'active' => 1]);
|
|
||||||
$job = Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Job', 'active' => 1]);
|
|
||||||
|
|
||||||
// put money in the two accounts (initial balance)
|
|
||||||
$ibChecking = Account::create(
|
|
||||||
['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Checking account initial balance', 'active' => 0]
|
|
||||||
);
|
|
||||||
$ibSavings = Account::create(
|
|
||||||
['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Savings account initial balance', 'active' => 0]
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->createTransaction($ibChecking, $checking, 4000, $obType, 'Initial Balance for Checking account', '2014-01-01');
|
|
||||||
$this->createTransaction($ibSavings, $savings, 10000, $obType, 'Initial Balance for Savings account', '2014-01-01');
|
|
||||||
|
|
||||||
|
|
||||||
// create some expenses and incomes and what-not (for every month):
|
$bills = Budget::whereName('Bills')->orderBy('id', 'DESC')->first();
|
||||||
$start = new Carbon('2014-01-01');
|
$groceries = Budget::whereName('Groceries')->orderBy('id', 'DESC')->first();
|
||||||
$end = Carbon::now()->startOfMonth()->subDay();
|
|
||||||
while ($start <= $end) {
|
|
||||||
$this->createTransaction(
|
|
||||||
$checking, $portaal, 500, $withdrawal, 'Rent for ' . $start->format('F Y'), $start->format('Y-m-') . '01', $billsBudget, $house
|
|
||||||
);
|
|
||||||
$this->createTransaction(
|
|
||||||
$checking, $vitens, 12, $withdrawal, 'Water for ' . $start->format('F Y'), $start->format('Y-m-') . '02', $billsBudget, $house
|
|
||||||
);
|
|
||||||
$this->createTransaction(
|
|
||||||
$checking, $greenchoice, 110, $withdrawal, 'Power for ' . $start->format('F Y'), $start->format('Y-m-') . '02', $billsBudget, $house
|
|
||||||
);
|
|
||||||
|
|
||||||
// spend on groceries
|
$house = Category::whereName('House')->orderBy('id', 'DESC')->first();
|
||||||
$groceriesStart = clone $start;
|
|
||||||
for ($i = 0; $i < 13; $i++) {
|
|
||||||
$amt = rand(100, 300) / 10;
|
|
||||||
$lunchAmount = rand(30, 60) / 10;
|
|
||||||
$this->createTransaction(
|
|
||||||
$checking, $plus, $lunchAmount, $withdrawal, 'Lunch', $groceriesStart->format('Y-m-d'), $groceriesBudget, $lunch
|
|
||||||
);
|
|
||||||
$groceriesStart->addDay();
|
|
||||||
if (intval($groceriesStart->format('d')) % 2 == 0) {
|
|
||||||
$this->createTransaction(
|
|
||||||
$checking, $ah, $amt, $withdrawal, 'Groceries', $groceriesStart->format('Y-m-d'), $groceriesBudget, $dailyGroceries
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$groceriesStart->addDay();
|
|
||||||
}
|
|
||||||
|
|
||||||
// get income:
|
|
||||||
$this->createTransaction($employer, $checking, rand(1400, 1600), $deposit, 'Salary', $start->format('Y-m-') . '23');
|
|
||||||
|
|
||||||
// pay taxes:
|
|
||||||
$this->createTransaction($checking, $taxes, rand(50, 70), $withdrawal, 'Taxes in ' . $start->format('F Y'), $start->format('Y-m-') . '27');
|
|
||||||
|
|
||||||
// some other stuff.
|
|
||||||
|
|
||||||
|
|
||||||
$start->addMonth();
|
$withdrawal = TransactionType::whereType('Withdrawal')->first();
|
||||||
|
$deposit = TransactionType::whereType('Deposit')->first();
|
||||||
|
$transfer = TransactionType::whereType('Transfer')->first();
|
||||||
|
|
||||||
}
|
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||||
|
|
||||||
// create some big expenses, move some money around.
|
$rentBill = Bill::where('name', 'Rent')->first();
|
||||||
$this->createTransaction($savings, $checking, 1259, $transfer, 'Money for new PC', $end->format('Y-m') . '-11');
|
|
||||||
$this->createTransaction($checking, $store, 1259, $withdrawal, 'New PC', $end->format('Y-m') . '-12');
|
|
||||||
|
|
||||||
// create two budgets
|
|
||||||
|
|
||||||
// create two categories
|
$current = clone $this->_yearAgoStartOfMonth;
|
||||||
|
while ($current <= $this->_startOfMonth) {
|
||||||
|
$cur = $current->format('Y-m-d');
|
||||||
|
$formatted = $current->format('F Y');
|
||||||
|
|
||||||
// create
|
// create expenses for rent, utilities, TV, phone on the 1st of the month.
|
||||||
|
$this->createTransaction($checking, $landLord, 800, $withdrawal, 'Rent for ' . $formatted, $cur, $euro, $bills, $house, $rentBill);
|
||||||
|
$this->createTransaction($checking, $utilities, 150, $withdrawal, 'Utilities for ' . $formatted, $cur, $euro, $bills, $house);
|
||||||
|
$this->createTransaction($checking, $television, 50, $withdrawal, 'TV for ' . $formatted, $cur, $euro, $bills, $house);
|
||||||
|
$this->createTransaction($checking, $phone, 50, $withdrawal, 'Phone bill for ' . $formatted, $cur, $euro, $bills, $house);
|
||||||
|
|
||||||
|
// two transactions. One without a budget, one without a category.
|
||||||
|
$this->createTransaction($checking, $phone, 10, $withdrawal, 'Extra charges on phone bill for ' . $formatted, $cur, $euro, null, $house);
|
||||||
|
$this->createTransaction($checking, $television, 5, $withdrawal, 'Extra charges on TV bill for ' . $formatted, $cur, $euro, $bills, null);
|
||||||
|
|
||||||
|
// income from job:
|
||||||
|
$this->createTransaction($employer, $checking, rand(3500, 4000), $deposit, 'Salary for ' . $formatted, $cur, $euro);
|
||||||
|
$this->createTransaction($checking, $savings, 2000, $transfer, 'Salary to savings account in ' . $formatted, $cur, $euro);
|
||||||
|
|
||||||
|
$this->createGroceries($current);
|
||||||
|
$this->createBigExpense(clone $current);
|
||||||
|
|
||||||
|
echo 'Created test-content for ' . $current->format('F Y') . "\n";
|
||||||
|
$current->addMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// piggy bank event
|
||||||
|
// add money to this piggy bank
|
||||||
|
// create a piggy bank event to match:
|
||||||
|
$piggyBank = PiggyBank::whereName('New camera')->orderBy('id', 'DESC')->first();
|
||||||
|
$intoPiggy = $this->createTransaction($checking, $savings, 100, $transfer, 'Money for piggy', $this->yaeom, $euro, $groceries, $house);
|
||||||
|
PiggyBankEvent::create(
|
||||||
|
[
|
||||||
|
'piggy_bank_id' => $piggyBank->id,
|
||||||
|
'transaction_journal_id' => $intoPiggy->id,
|
||||||
|
'date' => $this->yaeom,
|
||||||
|
'amount' => 100
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Account $from
|
* @param User $user
|
||||||
* @param Account $to
|
*/
|
||||||
* @param $amount
|
public function createAssetAccounts(User $user)
|
||||||
* @param TransactionType $type
|
{
|
||||||
* @param $description
|
$assetType = AccountType::whereType('Asset account')->first();
|
||||||
* @param $date
|
$ibType = AccountType::whereType('Initial balance account')->first();
|
||||||
|
$obType = TransactionType::whereType('Opening balance')->first();
|
||||||
|
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||||
|
|
||||||
|
|
||||||
|
$acc_a = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Checking account', 'active' => 1]);
|
||||||
|
$acc_b = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Savings account', 'active' => 1]);
|
||||||
|
$acc_c = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Delete me', 'active' => 1]);
|
||||||
|
|
||||||
|
$acc_d = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Checking account initial balance', 'active' => 0]);
|
||||||
|
$acc_e = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Savings account initial balance', 'active' => 0]);
|
||||||
|
$acc_f = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Delete me initial balance', 'active' => 0]);
|
||||||
|
|
||||||
|
|
||||||
|
$this->createTransaction($acc_d, $acc_a, 4000, $obType, 'Initial Balance for Checking account', $this->yasom, $euro);
|
||||||
|
$this->createTransaction($acc_e, $acc_b, 10000, $obType, 'Initial Balance for Savings account', $this->yasom, $euro);
|
||||||
|
$this->createTransaction($acc_f, $acc_c, 100, $obType, 'Initial Balance for Delete me', $this->yasom, $euro);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Account $from
|
||||||
|
* @param Account $to
|
||||||
|
* @param $amount
|
||||||
|
* @param TransactionType $type
|
||||||
|
* @param $description
|
||||||
|
* @param $date
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @param Budget $budget
|
||||||
|
* @param Category $category
|
||||||
|
* @param Bill $bill
|
||||||
*
|
*
|
||||||
* @return TransactionJournal
|
* @return TransactionJournal
|
||||||
*/
|
*/
|
||||||
public function createTransaction(
|
public function createTransaction(
|
||||||
Account $from, Account $to, $amount, TransactionType $type, $description, $date, Budget $budget = null, Category $category = null
|
Account $from, Account $to, $amount, TransactionType $type, $description, $date, TransactionCurrency $currency, Budget $budget = null,
|
||||||
|
Category $category = null, Bill $bill = null
|
||||||
) {
|
) {
|
||||||
$user = User::whereEmail('thegrumpydictator@gmail.com')->first();
|
$user = User::whereEmail('thegrumpydictator@gmail.com')->first();
|
||||||
$euro = TransactionCurrency::whereCode('EUR')->first();
|
|
||||||
|
$billID = is_null($bill) ? null : $bill->id;
|
||||||
|
|
||||||
|
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
$journal = TransactionJournal::create(
|
$journal = TransactionJournal::create(
|
||||||
[
|
[
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id, 'transaction_type_id' => $type->id, 'transaction_currency_id' => $currency->id, 'bill_id' => $billID,
|
||||||
'transaction_type_id' => $type->id,
|
'description' => $description, 'completed' => 1, 'date' => $date
|
||||||
'transaction_currency_id' => $euro->id,
|
|
||||||
'description' => $description,
|
|
||||||
'completed' => 1,
|
|
||||||
'date' => $date
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
Transaction::create(
|
Transaction::create(['account_id' => $from->id, 'transaction_journal_id' => $journal->id, 'amount' => $amount * -1]);
|
||||||
[
|
Transaction::create(['account_id' => $to->id, 'transaction_journal_id' => $journal->id, 'amount' => $amount]);
|
||||||
'account_id' => $from->id,
|
|
||||||
'transaction_journal_id' => $journal->id,
|
|
||||||
'amount' => $amount * -1
|
|
||||||
]
|
|
||||||
|
|
||||||
);
|
|
||||||
Transaction::create(
|
|
||||||
[
|
|
||||||
'account_id' => $to->id,
|
|
||||||
'transaction_journal_id' => $journal->id,
|
|
||||||
'amount' => $amount
|
|
||||||
]
|
|
||||||
|
|
||||||
);
|
|
||||||
if (!is_null($budget)) {
|
if (!is_null($budget)) {
|
||||||
$journal->budgets()->save($budget);
|
$journal->budgets()->save($budget);
|
||||||
}
|
}
|
||||||
@@ -173,4 +224,338 @@ class TestContentSeeder extends Seeder
|
|||||||
|
|
||||||
return $journal;
|
return $journal;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function createBudgets(User $user)
|
||||||
|
{
|
||||||
|
|
||||||
|
$groceries = Budget::create(['user_id' => $user->id, 'name' => 'Groceries']);
|
||||||
|
$bills = Budget::create(['user_id' => $user->id, 'name' => 'Bills']);
|
||||||
|
$deleteMe = Budget::create(['user_id' => $user->id, 'name' => 'Delete me']);
|
||||||
|
Budget::create(['user_id' => $user->id, 'name' => 'Budget without repetition']);
|
||||||
|
$groceriesLimit = BudgetLimit::create(
|
||||||
|
['startdate' => $this->som, 'amount' => 201, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $groceries->id]
|
||||||
|
);
|
||||||
|
$billsLimit = BudgetLimit::create(
|
||||||
|
['startdate' => $this->som, 'amount' => 202, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $bills->id]
|
||||||
|
);
|
||||||
|
$deleteMeLimit = BudgetLimit::create(
|
||||||
|
['startdate' => $this->som, 'amount' => 203, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $deleteMe->id]
|
||||||
|
);
|
||||||
|
|
||||||
|
// and because we have no filters, some repetitions:
|
||||||
|
LimitRepetition::create(['budget_limit_id' => $groceriesLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 201]);
|
||||||
|
LimitRepetition::create(['budget_limit_id' => $billsLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 202]);
|
||||||
|
LimitRepetition::create(['budget_limit_id' => $deleteMeLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 203]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function createCategories(User $user)
|
||||||
|
{
|
||||||
|
Category::create(['user_id' => $user->id, 'name' => 'DailyGroceries']);
|
||||||
|
Category::create(['user_id' => $user->id, 'name' => 'Lunch']);
|
||||||
|
Category::create(['user_id' => $user->id, 'name' => 'House']);
|
||||||
|
Category::create(['user_id' => $user->id, 'name' => 'Delete me']);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function createPiggyBanks(User $user)
|
||||||
|
{
|
||||||
|
// account
|
||||||
|
$savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first();
|
||||||
|
|
||||||
|
// some dates
|
||||||
|
$endDate = clone $this->_startOfMonth;
|
||||||
|
$nextYear = clone $this->_startOfMonth;
|
||||||
|
|
||||||
|
$endDate->addMonths(4);
|
||||||
|
$nextYear->addYear()->subDay();
|
||||||
|
|
||||||
|
$next = $nextYear->format('Y-m-d');
|
||||||
|
$end = $endDate->format('Y-m-d');
|
||||||
|
|
||||||
|
// piggy bank
|
||||||
|
$newCamera = PiggyBank::create(
|
||||||
|
[
|
||||||
|
'account_id' => $savings->id,
|
||||||
|
'name' => 'New camera',
|
||||||
|
'targetamount' => 2000,
|
||||||
|
'startdate' => $this->som,
|
||||||
|
'targetdate' => null,
|
||||||
|
'repeats' => 0,
|
||||||
|
'rep_length' => null,
|
||||||
|
'rep_every' => 0,
|
||||||
|
'rep_times' => null,
|
||||||
|
'reminder' => null,
|
||||||
|
'reminder_skip' => 0,
|
||||||
|
'remind_me' => 0,
|
||||||
|
'order' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
// and some events!
|
||||||
|
PiggyBankEvent::create(['piggy_bank_id' => $newCamera->id, 'date' => $this->som, 'amount' => 100]);
|
||||||
|
PiggyBankRepetition::create(['piggy_bank_id' => $newCamera->id, 'startdate' => $this->som, 'targetdate' => null, 'currentamount' => 100]);
|
||||||
|
|
||||||
|
|
||||||
|
$newClothes = PiggyBank::create(
|
||||||
|
[
|
||||||
|
'account_id' => $savings->id,
|
||||||
|
'name' => 'New clothes',
|
||||||
|
'targetamount' => 2000,
|
||||||
|
'startdate' => $this->som,
|
||||||
|
'targetdate' => $end,
|
||||||
|
'repeats' => 0,
|
||||||
|
'rep_length' => null,
|
||||||
|
'rep_every' => 0,
|
||||||
|
'rep_times' => null,
|
||||||
|
'reminder' => null,
|
||||||
|
'reminder_skip' => 0,
|
||||||
|
'remind_me' => 0,
|
||||||
|
'order' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
PiggyBankEvent::create(['piggy_bank_id' => $newClothes->id, 'date' => $this->som, 'amount' => 100]);
|
||||||
|
PiggyBankRepetition::create(['piggy_bank_id' => $newClothes->id, 'startdate' => $this->som, 'targetdate' => $end, 'currentamount' => 100]);
|
||||||
|
|
||||||
|
// weekly reminder piggy bank
|
||||||
|
$weekly = PiggyBank::create(
|
||||||
|
[
|
||||||
|
'account_id' => $savings->id,
|
||||||
|
'name' => 'Weekly reminder for clothes',
|
||||||
|
'targetamount' => 2000,
|
||||||
|
'startdate' => $this->som,
|
||||||
|
'targetdate' => $next,
|
||||||
|
'repeats' => 0,
|
||||||
|
'rep_length' => null,
|
||||||
|
'rep_every' => 0,
|
||||||
|
'rep_times' => null,
|
||||||
|
'reminder' => 'week',
|
||||||
|
'reminder_skip' => 0,
|
||||||
|
'remind_me' => 1,
|
||||||
|
'order' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
PiggyBankRepetition::create(['piggy_bank_id' => $weekly->id, 'startdate' => $this->som, 'targetdate' => $next, 'currentamount' => 0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function createReminders(User $user)
|
||||||
|
{
|
||||||
|
// for weekly piggy bank (clothes)
|
||||||
|
$nextWeek = clone $this->_startOfMonth;
|
||||||
|
$piggyBank = PiggyBank::whereName('New clothes')->orderBy('id', 'DESC')->first();
|
||||||
|
$nextWeek->addWeek();
|
||||||
|
$week = $nextWeek->format('Y-m-d');
|
||||||
|
|
||||||
|
Reminder::create(
|
||||||
|
['user_id' => $user->id, 'startdate' => $this->som, 'enddate' => $week, 'active' => 1, 'notnow' => 0,
|
||||||
|
'remindersable_id' => $piggyBank->id, 'remindersable_type' => 'PiggyBank']
|
||||||
|
);
|
||||||
|
|
||||||
|
// a fake reminder::
|
||||||
|
Reminder::create(
|
||||||
|
['user_id' => $user->id, 'startdate' => $this->som, 'enddate' => $week, 'active' => 0, 'notnow' => 0, 'remindersable_id' => 40,
|
||||||
|
'remindersable_type' => 'Transaction']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*/
|
||||||
|
public function createRecurringTransactions(User $user)
|
||||||
|
{
|
||||||
|
// account
|
||||||
|
$savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first();
|
||||||
|
|
||||||
|
$recurring = PiggyBank::create(
|
||||||
|
[
|
||||||
|
'account_id' => $savings->id,
|
||||||
|
'name' => 'Nieuwe spullen',
|
||||||
|
'targetamount' => 1000,
|
||||||
|
'startdate' => $this->som,
|
||||||
|
'targetdate' => $this->eom,
|
||||||
|
'repeats' => 1,
|
||||||
|
'rep_length' => 'month',
|
||||||
|
'rep_every' => 0,
|
||||||
|
'rep_times' => 0,
|
||||||
|
'reminder' => 'month',
|
||||||
|
'reminder_skip' => 0,
|
||||||
|
'remind_me' => 1,
|
||||||
|
'order' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
PiggyBankRepetition::create(['piggy_bank_id' => $recurring->id, 'startdate' => $this->som, 'targetdate' => $this->eom, 'currentamount' => 0]);
|
||||||
|
PiggyBankRepetition::create(
|
||||||
|
['piggy_bank_id' => $recurring->id, 'startdate' => $this->nsom, 'targetdate' => $this->neom, 'currentamount' => 0]
|
||||||
|
);
|
||||||
|
Reminder::create(
|
||||||
|
['user_id' => $user->id, 'startdate' => $this->som, 'enddate' => $this->neom, 'active' => 1, 'notnow' => 0,
|
||||||
|
'remindersable_id' => $recurring->id, 'remindersable_type' => 'PiggyBank']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $user
|
||||||
|
*/
|
||||||
|
public function createBills($user)
|
||||||
|
{
|
||||||
|
// bill
|
||||||
|
Bill::create(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id, 'name' => 'Rent', 'match' => 'rent,landlord',
|
||||||
|
'amount_min' => 700,
|
||||||
|
'amount_max' => 900,
|
||||||
|
'date' => $this->som,
|
||||||
|
'active' => 1,
|
||||||
|
'automatch' => 1,
|
||||||
|
'repeat_freq' => 'monthly',
|
||||||
|
'skip' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// bill
|
||||||
|
Bill::create(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'name' => 'Gas licht',
|
||||||
|
'match' => 'no,match',
|
||||||
|
'amount_min' => 500,
|
||||||
|
'amount_max' => 700,
|
||||||
|
'date' => $this->som,
|
||||||
|
'active' => 1,
|
||||||
|
'automatch' => 1,
|
||||||
|
'repeat_freq' => 'monthly',
|
||||||
|
'skip' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// bill
|
||||||
|
Bill::create(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'name' => 'Something something',
|
||||||
|
'match' => 'mumble,mumble',
|
||||||
|
'amount_min' => 500,
|
||||||
|
'amount_max' => 700,
|
||||||
|
'date' => $this->som,
|
||||||
|
'active' => 0,
|
||||||
|
'automatch' => 1,
|
||||||
|
'repeat_freq' => 'monthly',
|
||||||
|
'skip' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $user
|
||||||
|
*/
|
||||||
|
public function createExpenseAccounts($user)
|
||||||
|
{
|
||||||
|
//// create expenses for rent, utilities, water, TV, phone on the 1st of the month.
|
||||||
|
$expenseType = AccountType::whereType('Expense account')->first();
|
||||||
|
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Land lord', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Utilities company', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Water company', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'TV company', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Phone agency', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Super savers', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Groceries House', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Lunch House', 'active' => 1]);
|
||||||
|
|
||||||
|
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Buy More', 'active' => 1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $user
|
||||||
|
*/
|
||||||
|
public function createRevenueAccounts($user)
|
||||||
|
{
|
||||||
|
$revenueType = AccountType::whereType('Revenue account')->first();
|
||||||
|
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Employer', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'IRS', 'active' => 1]);
|
||||||
|
Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Second job employer', 'active' => 1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $date
|
||||||
|
*/
|
||||||
|
public function createGroceries(Carbon $date)
|
||||||
|
{
|
||||||
|
// variables we need:
|
||||||
|
$checking = Account::whereName('Checking account')->orderBy('id', 'DESC')->first();
|
||||||
|
$shopOne = Account::whereName('Groceries House')->orderBy('id', 'DESC')->first();
|
||||||
|
$shopTwo = Account::whereName('Super savers')->orderBy('id', 'DESC')->first();
|
||||||
|
$lunchHouse = Account::whereName('Lunch House')->orderBy('id', 'DESC')->first();
|
||||||
|
$lunch = Category::whereName('Lunch')->orderBy('id', 'DESC')->first();
|
||||||
|
$daily = Category::whereName('DailyGroceries')->orderBy('id', 'DESC')->first();
|
||||||
|
$euro = TransactionCurrency::whereCode('EUR')->first();
|
||||||
|
$withdrawal = TransactionType::whereType('Withdrawal')->first();
|
||||||
|
$groceries = Budget::whereName('Groceries')->orderBy('id', 'DESC')->first();
|
||||||
|
|
||||||
|
|
||||||
|
$shops = [$shopOne, $shopTwo];
|
||||||
|
|
||||||
|
// create groceries and lunch (daily, between 5 and 10 euro).
|
||||||
|
$mStart = clone $date;
|
||||||
|
$mEnd = clone $date;
|
||||||
|
$mEnd->endOfMonth();
|
||||||
|
while ($mStart <= $mEnd) {
|
||||||
|
$mFormat = $mStart->format('Y-m-d');
|
||||||
|
$shop = $shops[rand(0, 1)];
|
||||||
|
|
||||||
|
$this->createTransaction($checking, $shop, (rand(500, 1000) / 100), $withdrawal, 'Groceries', $mFormat, $euro, $groceries, $daily);
|
||||||
|
$this->createTransaction($checking, $lunchHouse, (rand(200, 600) / 100), $withdrawal, 'Lunch', $mFormat, $euro, $groceries, $lunch);
|
||||||
|
|
||||||
|
$mStart->addDay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $date
|
||||||
|
*/
|
||||||
|
public function createBigExpense($date)
|
||||||
|
{
|
||||||
|
$date->addDays(12);
|
||||||
|
$dollar = TransactionCurrency::whereCode('USD')->first();
|
||||||
|
$checking = Account::whereName('Checking account')->orderBy('id', 'DESC')->first();
|
||||||
|
$savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first();
|
||||||
|
$buyMore = Account::whereName('Buy More')->orderBy('id', 'DESC')->first();
|
||||||
|
$withdrawal = TransactionType::whereType('Withdrawal')->first();
|
||||||
|
$transfer = TransactionType::whereType('Transfer')->first();
|
||||||
|
$user = User::whereEmail('thegrumpydictator@gmail.com')->first();
|
||||||
|
|
||||||
|
|
||||||
|
// create some big expenses, move some money around.
|
||||||
|
$amount = rand(500, 2000);
|
||||||
|
$one = $this->createTransaction(
|
||||||
|
$savings, $checking, $amount, $transfer, 'Money for big expense in ' . $date->format('F Y'), $date->format('Y-m-d'), $dollar
|
||||||
|
);
|
||||||
|
$two = $this->createTransaction(
|
||||||
|
$checking, $buyMore, $amount, $withdrawal, 'Big expense in ' . $date->format('F Y'), $date->format('Y-m-d'), $dollar
|
||||||
|
);
|
||||||
|
$group = TransactionGroup::create(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'relation' => 'balance'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$group->transactionjournals()->save($one);
|
||||||
|
$group->transactionjournals()->save($two);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ class TransactionCurrencySeeder extends Seeder
|
|||||||
{
|
{
|
||||||
DB::table('transaction_currencies')->delete();
|
DB::table('transaction_currencies')->delete();
|
||||||
|
|
||||||
TransactionCurrency::create(
|
TransactionCurrency::create(['code' => 'EUR','name' => 'Euro','symbol' => '€']);
|
||||||
['code' => 'EUR']
|
TransactionCurrency::create(['code' => 'USD','name' => 'US Dollar','symbol' => '$']);
|
||||||
);
|
TransactionCurrency::create(['code' => 'HUF','name' => 'Hungarian forint','symbol' => 'Ft']);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,4 +17,4 @@ class TransactionTypeSeeder extends Seeder
|
|||||||
TransactionType::create(['type' => 'Opening balance']);
|
TransactionType::create(['type' => 'Opening balance']);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,15 @@
|
|||||||
|
|
||||||
App::before(
|
App::before(
|
||||||
function ($request) {
|
function ($request) {
|
||||||
|
|
||||||
|
// put IP in session if not already there.
|
||||||
|
|
||||||
$reminders = [];
|
$reminders = [];
|
||||||
|
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
Filter::setSessionDateRange();
|
Filter::setSessionDateRange();
|
||||||
Reminders::updateReminders();
|
Reminders::updateReminders();
|
||||||
|
Steam::removeEmptyBudgetLimits();
|
||||||
$reminders = Reminders::getReminders();
|
$reminders = Reminders::getReminders();
|
||||||
}
|
}
|
||||||
View::share('reminders', $reminders);
|
View::share('reminders', $reminders);
|
||||||
@@ -90,3 +94,11 @@ Route::filter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Route::filter(
|
||||||
|
'allow-register', function () {
|
||||||
|
if (Config::get('auth.allow_register') !== true) {
|
||||||
|
return View::make('error')->with('message', 'Not possible');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Firefly\Database;
|
|
||||||
|
|
||||||
use LaravelBook\Ardent\Ardent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class SingleTableInheritanceEntity
|
|
||||||
*
|
|
||||||
* @package Firefly\Database
|
|
||||||
*/
|
|
||||||
abstract class SingleTableInheritanceEntity extends Ardent
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The field that stores the subclass
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $subclassField = null;
|
|
||||||
/**
|
|
||||||
* must be overridden and set to true in subclasses
|
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $isSubclass = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $attributes
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Database\Eloquent\Model|static
|
|
||||||
*/
|
|
||||||
public function newFromBuilder($attributes = [])
|
|
||||||
{
|
|
||||||
$instance = $this->mapData((array)$attributes)->newInstance([], true);
|
|
||||||
$instance->setRawAttributes((array)$attributes, true);
|
|
||||||
|
|
||||||
return $instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if no subclass is defined, function as normal
|
|
||||||
*
|
|
||||||
* @param array $attributes
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Database\Eloquent\Model|static
|
|
||||||
*/
|
|
||||||
public function mapData(array $attributes)
|
|
||||||
{
|
|
||||||
if (!$this->subclassField) {
|
|
||||||
return $this->newInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new $attributes[$this->subclassField];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* instead of using $this->newInstance(), call
|
|
||||||
* newInstance() on the object from mapData
|
|
||||||
*
|
|
||||||
* @param bool $excludeDeleted
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
|
||||||
*/
|
|
||||||
public function newQuery($excludeDeleted = true)
|
|
||||||
{
|
|
||||||
// If using Laravel 4.0.x then use the following commented version of this command
|
|
||||||
// $builder = new Builder($this->newBaseQueryBuilder());
|
|
||||||
// newEloquentBuilder() was added in 4.1
|
|
||||||
$builder = $this->newEloquentBuilder($this->newBaseQueryBuilder());
|
|
||||||
|
|
||||||
// Once Firefly has the query builders, it will set the model instances so the
|
|
||||||
// builder can easily access any information it may need from the model
|
|
||||||
// while it is constructing and executing various queries against it.
|
|
||||||
$builder->setModel($this)->with($this->with);
|
|
||||||
|
|
||||||
if ($excludeDeleted && $this->softDelete) {
|
|
||||||
$builder->whereNull($this->getQualifiedDeletedAtColumn());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->subclassField && $this->isSubclass()) {
|
|
||||||
$builder->where($this->subclassField, '=', get_class($this));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isSubclass()
|
|
||||||
{
|
|
||||||
return $this->isSubclass;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ensure that the subclass field is assigned on save
|
|
||||||
*
|
|
||||||
* @param array $rules
|
|
||||||
* @param array $customMessages
|
|
||||||
* @param array $options
|
|
||||||
* @param callable $beforeSave
|
|
||||||
* @param callable $afterSave
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function save(
|
|
||||||
array $rules = [],
|
|
||||||
array $customMessages = [],
|
|
||||||
array $options = [],
|
|
||||||
\Closure $beforeSave = null,
|
|
||||||
\Closure $afterSave = null
|
|
||||||
) {
|
|
||||||
if ($this->subclassField) {
|
|
||||||
$this->attributes[$this->subclassField] = get_class($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::save($rules, $customMessages, $options, $beforeSave, $afterSave);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Exception;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class FireflyException
|
|
||||||
*
|
|
||||||
* @package Firefly\Exception
|
|
||||||
*/
|
|
||||||
class FireflyException extends \Exception
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Firefly\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ValidationException
|
|
||||||
*
|
|
||||||
* @package Firefly\Exception
|
|
||||||
*/
|
|
||||||
class ValidationException extends \Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,365 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Form;
|
|
||||||
|
|
||||||
|
|
||||||
use Firefly\Exception\FireflyException;
|
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
class Form
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param null $value
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public static function ffInteger($name, $value = null, array $options = [])
|
|
||||||
{
|
|
||||||
$options['step'] = '1';
|
|
||||||
return self::ffInput('number', $name, $value, $options);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function ffCheckbox($name, $value = 1, $checked = null, $options = [])
|
|
||||||
{
|
|
||||||
$options['checked'] = $checked ? true : null;
|
|
||||||
return self::ffInput('checkbox', $name, $value, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param null $value
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public static function ffAmount($name, $value = null, array $options = [])
|
|
||||||
{
|
|
||||||
$options['step'] = 'any';
|
|
||||||
$options['min'] = '0.01';
|
|
||||||
return self::ffInput('amount', $name, $value, $options);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param null $value
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public static function ffBalance($name, $value = null, array $options = [])
|
|
||||||
{
|
|
||||||
$options['step'] = 'any';
|
|
||||||
return self::ffInput('amount', $name, $value, $options);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param null $value
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public static function ffDate($name, $value = null, array $options = [])
|
|
||||||
{
|
|
||||||
return self::ffInput('date', $name, $value, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param null $value
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public static function ffTags($name, $value = null, array $options = [])
|
|
||||||
{
|
|
||||||
$options['data-role'] = 'tagsinput';
|
|
||||||
return self::ffInput('text', $name, $value, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param array $list
|
|
||||||
* @param null $selected
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public static function ffSelect($name, array $list = [], $selected = null, array $options = [])
|
|
||||||
{
|
|
||||||
return self::ffInput('select', $name, $selected, $options, $list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param null $value
|
|
||||||
* @param array $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public static function ffText($name, $value = null, array $options = array())
|
|
||||||
{
|
|
||||||
return self::ffInput('text', $name, $value, $options);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $name
|
|
||||||
* @param $options
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function label($name, $options)
|
|
||||||
{
|
|
||||||
if (isset($options['label'])) {
|
|
||||||
return $options['label'];
|
|
||||||
}
|
|
||||||
$labels = [
|
|
||||||
'amount_min' => 'Amount (min)',
|
|
||||||
'amount_max' => 'Amount (max)',
|
|
||||||
'match' => 'Matches on',
|
|
||||||
'repeat_freq' => 'Repetition',
|
|
||||||
'account_from_id' => 'Account from',
|
|
||||||
'account_to_id' => 'Account to',
|
|
||||||
'account_id' => 'Asset account'
|
|
||||||
];
|
|
||||||
|
|
||||||
return isset($labels[$name]) ? $labels[$name] : str_replace('_', ' ', ucfirst($name));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return buttons for update/validate/return.
|
|
||||||
*
|
|
||||||
* @param $type
|
|
||||||
* @param $name
|
|
||||||
*/
|
|
||||||
public static function ffOptionsList($type, $name)
|
|
||||||
{
|
|
||||||
$previousValue = \Input::old('post_submit_action');
|
|
||||||
$previousValue = is_null($previousValue) ? 'store' : $previousValue;
|
|
||||||
/*
|
|
||||||
* Store.
|
|
||||||
*/
|
|
||||||
$store = '';
|
|
||||||
switch ($type) {
|
|
||||||
case 'create':
|
|
||||||
$store = '<div class="form-group"><label for="default" class="col-sm-4 control-label">Store</label>';
|
|
||||||
$store .= '<div class="col-sm-8"><div class="radio"><label>';
|
|
||||||
$store .= \Form::radio('post_submit_action', 'store', $previousValue == 'store');
|
|
||||||
$store .= 'Store ' . $name . '</label></div></div></div>';
|
|
||||||
break;
|
|
||||||
case 'update':
|
|
||||||
$store = '<div class="form-group"><label for="default" class="col-sm-4 control-label">Store</label>';
|
|
||||||
$store .= '<div class="col-sm-8"><div class="radio"><label>';
|
|
||||||
$store .= \Form::radio('post_submit_action', 'update', $previousValue == 'store');
|
|
||||||
$store .= 'Update ' . $name . '</label></div></div></div>';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot create ffOptionsList for option (store) ' . $type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* validate is always the same:
|
|
||||||
*/
|
|
||||||
$validate = '<div class="form-group"><label for="validate_only" class="col-sm-4 control-label">Validate only';
|
|
||||||
$validate .= '</label><div class="col-sm-8"><div class="radio"><label>';
|
|
||||||
$validate .= \Form::radio('post_submit_action', 'validate_only', $previousValue == 'validate_only');
|
|
||||||
$validate .= 'Only validate, do not save</label></div></div></div>';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Store & return:
|
|
||||||
*/
|
|
||||||
switch ($type) {
|
|
||||||
case 'create':
|
|
||||||
$return = '<div class="form-group"><label for="return_to_form" class="col-sm-4 control-label">';
|
|
||||||
$return .= 'Return here</label><div class="col-sm-8"><div class="radio"><label>';
|
|
||||||
$return .= \Form::radio('post_submit_action', 'create_another', $previousValue == 'create_another');
|
|
||||||
$return .= 'After storing, return here to create another one.</label></div></div></div>';
|
|
||||||
break;
|
|
||||||
case 'update':
|
|
||||||
$return = '<div class="form-group"><label for="return_to_edit" class="col-sm-4 control-label">';
|
|
||||||
$return .= 'Return here</label><div class="col-sm-8"><div class="radio"><label>';
|
|
||||||
$return .= \Form::radio('post_submit_action', 'return_to_edit', $previousValue == 'return_to_edit');
|
|
||||||
$return .= 'After updating, return here.</label></div></div></div>';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot create ffOptionsList for option (store+return) ' . $type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $store . $validate . $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $type
|
|
||||||
* @param $name
|
|
||||||
* @param null $value
|
|
||||||
* @param array $options
|
|
||||||
* @param array $list
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public static function ffInput($type, $name, $value = null, array $options = array(), $list = [])
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* add some defaults to this method:
|
|
||||||
*/
|
|
||||||
$options['class'] = 'form-control';
|
|
||||||
$options['id'] = 'ffInput_' . $name;
|
|
||||||
$options['autocomplete'] = 'off';
|
|
||||||
$label = self::label($name, $options);
|
|
||||||
/*
|
|
||||||
* Make label and placeholder look nice.
|
|
||||||
*/
|
|
||||||
$options['placeholder'] = ucfirst($name);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get pre filled value:
|
|
||||||
*/
|
|
||||||
if (\Session::has('prefilled')) {
|
|
||||||
$preFilled = \Session::get('preFilled');
|
|
||||||
$value = isset($prefilled[$name]) && is_null($value) ? $prefilled[$name] : $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the value.
|
|
||||||
*/
|
|
||||||
if (!is_null(\Input::old($name))) {
|
|
||||||
/*
|
|
||||||
* Old value overrules $value.
|
|
||||||
*/
|
|
||||||
$value = \Input::old($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get errors, warnings and successes from session:
|
|
||||||
*/
|
|
||||||
/** @var MessageBag $errors */
|
|
||||||
$errors = \Session::get('errors');
|
|
||||||
|
|
||||||
/** @var MessageBag $warnings */
|
|
||||||
$warnings = \Session::get('warnings');
|
|
||||||
|
|
||||||
/** @var MessageBag $successes */
|
|
||||||
$successes = \Session::get('successes');
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If errors, add some more classes.
|
|
||||||
*/
|
|
||||||
switch (true) {
|
|
||||||
case (!is_null($errors) && $errors->has($name)):
|
|
||||||
$classes = 'form-group has-error has-feedback';
|
|
||||||
break;
|
|
||||||
case (!is_null($warnings) && $warnings->has($name)):
|
|
||||||
$classes = 'form-group has-warning has-feedback';
|
|
||||||
break;
|
|
||||||
case (!is_null($successes) && $successes->has($name)):
|
|
||||||
$classes = 'form-group has-success has-feedback';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$classes = 'form-group';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add some HTML.
|
|
||||||
*/
|
|
||||||
$html = '<div class="' . $classes . '">';
|
|
||||||
$html .= '<label for="' . $options['id'] . '" class="col-sm-4 control-label">' . $label . '</label>';
|
|
||||||
$html .= '<div class="col-sm-8">';
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Switch input type:
|
|
||||||
*/
|
|
||||||
unset($options['label']);
|
|
||||||
switch ($type) {
|
|
||||||
case 'text':
|
|
||||||
$html .= \Form::input('text', $name, $value, $options);
|
|
||||||
break;
|
|
||||||
case 'amount':
|
|
||||||
$html .= '<div class="input-group"><div class="input-group-addon">€</div>';
|
|
||||||
$html .= \Form::input('number', $name, $value, $options);
|
|
||||||
$html .= '</div>';
|
|
||||||
break;
|
|
||||||
case 'number':
|
|
||||||
$html .= \Form::input('number', $name, $value, $options);
|
|
||||||
break;
|
|
||||||
case 'checkbox':
|
|
||||||
$checked = $options['checked'];
|
|
||||||
unset($options['checked'], $options['placeholder'], $options['autocomplete'], $options['class']);
|
|
||||||
$html .= '<div class="checkbox"><label>';
|
|
||||||
$html .= \Form::checkbox($name, $value, $checked, $options);
|
|
||||||
$html .= '</label></div>';
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'date':
|
|
||||||
$html .= \Form::input('date', $name, $value, $options);
|
|
||||||
break;
|
|
||||||
case 'select':
|
|
||||||
$html .= \Form::select($name, $list, $value, $options);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot handle type "' . $type . '" in FFFormBuilder.');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If errors, respond to them:
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!is_null($errors)) {
|
|
||||||
if ($errors->has($name)) {
|
|
||||||
$html .= '<span class="glyphicon glyphicon-remove form-control-feedback"></span>';
|
|
||||||
$html .= '<p class="text-danger">' . e($errors->first($name)) . '</p>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($errors);
|
|
||||||
/*
|
|
||||||
* If warnings, respond to them:
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!is_null($warnings)) {
|
|
||||||
if ($warnings->has($name)) {
|
|
||||||
$html .= '<span class="glyphicon glyphicon-warning-sign form-control-feedback"></span>';
|
|
||||||
$html .= '<p class="text-warning">' . e($warnings->first($name)) . '</p>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($warnings);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If successes, respond to them:
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!is_null($successes)) {
|
|
||||||
if ($successes->has($name)) {
|
|
||||||
$html .= '<span class="glyphicon glyphicon-ok form-control-feedback"></span>';
|
|
||||||
$html .= '<p class="text-success">' . e($successes->first($name)) . '</p>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($successes);
|
|
||||||
|
|
||||||
$html .= '</div>';
|
|
||||||
$html .= '</div>';
|
|
||||||
|
|
||||||
return $html;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Account
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
class Account implements AccountInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Account $account
|
|
||||||
*
|
|
||||||
* @return \TransactionJournal|null
|
|
||||||
*/
|
|
||||||
public function openingBalanceTransaction(\Account $account)
|
|
||||||
{
|
|
||||||
return \TransactionJournal::withRelevantData()
|
|
||||||
->accountIs($account)
|
|
||||||
->leftJoin(
|
|
||||||
'transaction_types', 'transaction_types.id', '=',
|
|
||||||
'transaction_journals.transaction_type_id'
|
|
||||||
)
|
|
||||||
->where('transaction_types.type', 'Opening balance')
|
|
||||||
->first(['transaction_journals.*']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Since it is entirely possible the database is messed up somehow it might be that a transaction
|
|
||||||
* journal has only one transaction. This is mainly caused by wrong deletions and other artefacts from the past.
|
|
||||||
*
|
|
||||||
* If it is the case, Firefly removes $item and continues like nothing ever happened. This will however,
|
|
||||||
* mess up some statisics but it's decided everybody should learn to live with that.
|
|
||||||
*
|
|
||||||
* Firefly might be needing some cleanup routine in the future.
|
|
||||||
*
|
|
||||||
* For now, Firefly simply warns the user of this.
|
|
||||||
*
|
|
||||||
* @param \Account $account
|
|
||||||
* @param $perPage
|
|
||||||
*
|
|
||||||
* @return array|mixed
|
|
||||||
* @throws \Firefly\Exception\FireflyException
|
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
|
||||||
*/
|
|
||||||
public function show(\Account $account, $perPage)
|
|
||||||
{
|
|
||||||
$start = \Session::get('start');
|
|
||||||
$end = \Session::get('end');
|
|
||||||
$stats = [
|
|
||||||
'accounts' => []
|
|
||||||
];
|
|
||||||
$items = [];
|
|
||||||
|
|
||||||
// build a query:
|
|
||||||
$query = \TransactionJournal::withRelevantData()
|
|
||||||
->defaultSorting()
|
|
||||||
->accountIs($account)
|
|
||||||
->after($start)
|
|
||||||
->before($end);
|
|
||||||
// filter some:
|
|
||||||
switch (\Input::get('type')) {
|
|
||||||
case 'transactions':
|
|
||||||
$query->transactionTypes(['Deposit', 'Withdrawal']);
|
|
||||||
break;
|
|
||||||
case 'transfers':
|
|
||||||
$query->transactionTypes(['Transfer']);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (\Input::get('show')) {
|
|
||||||
case 'expenses':
|
|
||||||
case 'out':
|
|
||||||
$query->lessThan(0);
|
|
||||||
break;
|
|
||||||
case 'income':
|
|
||||||
case 'in':
|
|
||||||
$query->moreThan(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// build paginator:
|
|
||||||
$totalItems = $query->count();
|
|
||||||
$page = max(1, intval(\Input::get('page')));
|
|
||||||
$skip = ($page - 1) * $perPage;
|
|
||||||
$result = $query->skip($skip)->take($perPage)->get(['transaction_journals.*']);
|
|
||||||
|
|
||||||
|
|
||||||
// get the relevant budgets, categories and accounts from this list:
|
|
||||||
/** @var $item \TransactionJournal */
|
|
||||||
foreach ($result as $index => $item) {
|
|
||||||
|
|
||||||
foreach ($item->components as $component) {
|
|
||||||
$stats[$component->class][$component->id] = $component;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($item->transactions) < 2) {
|
|
||||||
\Session::flash('warning', 'Some transactions are incomplete; they will not be shown.');
|
|
||||||
unset($result[$index]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$items[] = $item;
|
|
||||||
$fromAccount = $item->transactions[0]->account;
|
|
||||||
$toAccount = $item->transactions[1]->account;
|
|
||||||
$stats['accounts'][$fromAccount->id] = $fromAccount;
|
|
||||||
$stats['accounts'][$toAccount->id] = $toAccount;
|
|
||||||
}
|
|
||||||
$paginator = \Paginator::make($items, $totalItems, $perPage);
|
|
||||||
unset($result, $page, $item, $fromAccount, $toAccount);
|
|
||||||
|
|
||||||
|
|
||||||
// statistics (transactions)
|
|
||||||
$trIn = floatval(
|
|
||||||
\Transaction::before($end)->after($start)->accountIs($account)->moreThan(0)
|
|
||||||
->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount')
|
|
||||||
);
|
|
||||||
$trOut = floatval(
|
|
||||||
\Transaction::before($end)->after($start)->accountIs($account)->lessThan(0)
|
|
||||||
->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount')
|
|
||||||
);
|
|
||||||
$trDiff = $trIn + $trOut;
|
|
||||||
|
|
||||||
// statistics (transfers)
|
|
||||||
$trfIn = floatval(
|
|
||||||
\Transaction::before($end)->after($start)->accountIs($account)->moreThan(0)
|
|
||||||
->transactionTypes(['Transfer'])->sum('transactions.amount')
|
|
||||||
);
|
|
||||||
$trfOut = floatval(
|
|
||||||
\Transaction::before($end)->after($start)->accountIs($account)->lessThan(0)
|
|
||||||
->transactionTypes(['Transfer'])->sum('transactions.amount')
|
|
||||||
);
|
|
||||||
$trfDiff = $trfIn + $trfOut;
|
|
||||||
|
|
||||||
$stats['period'] = [
|
|
||||||
'in' => $trIn,
|
|
||||||
'out' => $trOut,
|
|
||||||
'diff' => $trDiff,
|
|
||||||
't_in' => $trfIn,
|
|
||||||
't_out' => $trfOut,
|
|
||||||
't_diff' => $trfDiff
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
$return = [
|
|
||||||
'journals' => $paginator,
|
|
||||||
'statistics' => $stats
|
|
||||||
];
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface AccountInterface
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
interface AccountInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Account $account
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function openingBalanceTransaction(\Account $account);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Account $account
|
|
||||||
* @param $perPage
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function show(\Account $account, $perPage);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,227 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Budget
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
class Budget implements BudgetInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* First, loop all budgets, all of their limits and all repetitions to get an overview per period
|
|
||||||
* and some basic information about that repetition's data.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param Collection $budgets
|
|
||||||
*
|
|
||||||
* @return mixed|void
|
|
||||||
*/
|
|
||||||
public function organizeByDate(Collection $budgets)
|
|
||||||
{
|
|
||||||
$return = [];
|
|
||||||
|
|
||||||
/** @var \Budget $budget */
|
|
||||||
foreach ($budgets as $budget) {
|
|
||||||
|
|
||||||
/** @var \Limit $limit */
|
|
||||||
foreach ($budget->limits as $limit) {
|
|
||||||
|
|
||||||
/** @var \LimitRepetition $repetition */
|
|
||||||
foreach ($limit->limitrepetitions as $repetition) {
|
|
||||||
$repetition->left = $repetition->leftInRepetition();
|
|
||||||
$periodOrder = $repetition->periodOrder();
|
|
||||||
$period = $repetition->periodShow();
|
|
||||||
if (!isset($return[$periodOrder])) {
|
|
||||||
|
|
||||||
$return[$periodOrder] = [
|
|
||||||
'date' => $period,
|
|
||||||
'start' => $repetition->startdate,
|
|
||||||
'end' => $repetition->enddate,
|
|
||||||
'budget_id' => $budget->id,
|
|
||||||
'limitrepetitions' => [$repetition]
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$return[$periodOrder]['limitrepetitions'][] = $repetition;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
krsort($return);
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a repetition (complex because of user check)
|
|
||||||
* and then get the transactions in it.
|
|
||||||
* @param $repetitionId
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function organizeRepetition(\LimitRepetition $repetition)
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
// get transactions:
|
|
||||||
$set = $repetition->limit->budget
|
|
||||||
->transactionjournals()
|
|
||||||
->withRelevantData()
|
|
||||||
->transactionTypes(['Withdrawal'])
|
|
||||||
->after($repetition->startdate)
|
|
||||||
->before($repetition->enddate)
|
|
||||||
->defaultSorting()
|
|
||||||
->get(['transaction_journals.*']);
|
|
||||||
|
|
||||||
$result[0] = [
|
|
||||||
'date' => $repetition->periodShow(),
|
|
||||||
'limit' => $repetition->limit,
|
|
||||||
'limitrepetition' => $repetition,
|
|
||||||
'journals' => $set,
|
|
||||||
'paginated' => false
|
|
||||||
];
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param \Budget $budget
|
|
||||||
* @param bool $useSessionDates
|
|
||||||
*
|
|
||||||
* @return array|mixed
|
|
||||||
* @throws \Firefly\Exception\FireflyException
|
|
||||||
*/
|
|
||||||
public function organizeRepetitions(\Budget $budget, $useSessionDates = false)
|
|
||||||
{
|
|
||||||
$sessionStart = \Session::get('start');
|
|
||||||
$sessionEnd = \Session::get('end');
|
|
||||||
|
|
||||||
$result = [];
|
|
||||||
$inRepetition = [];
|
|
||||||
|
|
||||||
// get the limits:
|
|
||||||
if ($useSessionDates) {
|
|
||||||
$limits = $budget->limits()->where('startdate', '>=', $sessionStart->format('Y-m-d'))->where(
|
|
||||||
'startdate', '<=', $sessionEnd->format('Y-m-d')
|
|
||||||
)->get();
|
|
||||||
} else {
|
|
||||||
$limits = $budget->limits;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var \Limit $limit */
|
|
||||||
foreach ($limits as $limit) {
|
|
||||||
foreach ($limit->limitrepetitions as $repetition) {
|
|
||||||
$order = $repetition->periodOrder();
|
|
||||||
$result[$order] = [
|
|
||||||
'date' => $repetition->periodShow(),
|
|
||||||
'limitrepetition' => $repetition,
|
|
||||||
'limit' => $limit,
|
|
||||||
'journals' => [],
|
|
||||||
'paginated' => false
|
|
||||||
];
|
|
||||||
$transactions = [];
|
|
||||||
$set = $budget->transactionjournals()
|
|
||||||
->withRelevantData()
|
|
||||||
->transactionTypes(['Withdrawal'])
|
|
||||||
->after($repetition->startdate)
|
|
||||||
->before($repetition->enddate)
|
|
||||||
->defaultSorting()
|
|
||||||
->get(['transaction_journals.*']);
|
|
||||||
foreach ($set as $entry) {
|
|
||||||
$transactions[] = $entry;
|
|
||||||
$inRepetition[] = $entry->id;
|
|
||||||
}
|
|
||||||
$result[$order]['journals'] = $transactions;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if ($useSessionDates === false) {
|
|
||||||
$query = $budget->transactionjournals()->withRelevantData()->defaultSorting();
|
|
||||||
if (count($inRepetition) > 0) {
|
|
||||||
$query->whereNotIn('transaction_journals.id', $inRepetition);
|
|
||||||
}
|
|
||||||
|
|
||||||
// build paginator:
|
|
||||||
$perPage = 25;
|
|
||||||
$totalItems = $query->count();
|
|
||||||
$page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1;
|
|
||||||
$skip = ($page - 1) * $perPage;
|
|
||||||
$set = $query->skip($skip)->take($perPage)->get();
|
|
||||||
|
|
||||||
// stupid paginator!
|
|
||||||
$items = [];
|
|
||||||
/** @var $item \TransactionJournal */
|
|
||||||
foreach ($set as $item) {
|
|
||||||
$items[] = $item;
|
|
||||||
}
|
|
||||||
$paginator = \Paginator::make($items, $totalItems, $perPage);
|
|
||||||
$result['0000'] = [
|
|
||||||
'date' => 'Not in an envelope',
|
|
||||||
'limit' => null,
|
|
||||||
'paginated' => true,
|
|
||||||
'journals' => $paginator];
|
|
||||||
}
|
|
||||||
krsort($result);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
*
|
|
||||||
* @return mixed|void
|
|
||||||
*/
|
|
||||||
public function outsideRepetitions(\Budget $budget)
|
|
||||||
{
|
|
||||||
$inRepetitions = [];
|
|
||||||
foreach ($budget->limits as $limit) {
|
|
||||||
foreach ($limit->limitrepetitions as $repetition) {
|
|
||||||
$set = $budget->transactionjournals()
|
|
||||||
->transactionTypes(['Withdrawal'])
|
|
||||||
->after($repetition->startdate)
|
|
||||||
->before($repetition->enddate)
|
|
||||||
->defaultSorting()
|
|
||||||
->get(['transaction_journals.id']);
|
|
||||||
foreach ($set as $item) {
|
|
||||||
$inRepetitions[] = $item->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = $budget->transactionjournals()
|
|
||||||
->withRelevantData()
|
|
||||||
->whereNotIn('transaction_journals.id', $inRepetitions)
|
|
||||||
->defaultSorting();
|
|
||||||
|
|
||||||
// build paginator:
|
|
||||||
$perPage = 25;
|
|
||||||
$totalItems = $query->count();
|
|
||||||
$page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1;
|
|
||||||
$skip = ($page - 1) * $perPage;
|
|
||||||
$set = $query->skip($skip)->take($perPage)->get();
|
|
||||||
|
|
||||||
// stupid paginator!
|
|
||||||
$items = [];
|
|
||||||
/** @var $item \TransactionJournal */
|
|
||||||
foreach ($set as $item) {
|
|
||||||
$items[] = $item;
|
|
||||||
}
|
|
||||||
$paginator = \Paginator::make($items, $totalItems, $perPage);
|
|
||||||
$result = [0 => [
|
|
||||||
'date' => 'Not in an envelope',
|
|
||||||
'limit' => null,
|
|
||||||
'paginated' => true,
|
|
||||||
'journals' => $paginator
|
|
||||||
]];
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface BudgetInterface
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
interface BudgetInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Collection $budgets
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function organizeByDate(Collection $budgets);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $repetitionId
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function organizeRepetition(\LimitRepetition $repetition);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
* @param bool $useSessionDates
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function organizeRepetitions(\Budget $budget, $useSessionDates = false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function outsideRepetitions(\Budget $budget);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Category
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
class Category implements CategoryInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param \Category $category
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function journalsInRange(\Category $category, Carbon $start, Carbon $end)
|
|
||||||
{
|
|
||||||
return $category->transactionjournals()->with(
|
|
||||||
['transactions', 'transactions.account', 'transactiontype', 'components']
|
|
||||||
)->orderBy('date', 'DESC')->orderBy('id', 'DESC')->before($end)->after($start)->get();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface CategoryInterface
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
interface CategoryInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Category $category
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function journalsInRange(\Category $category, Carbon $start, Carbon $end);
|
|
||||||
}
|
|
||||||
@@ -1,475 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Firefly\Exception\FireflyException;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Chart
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
class Chart implements ChartInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Account $account
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function account(\Account $account, Carbon $start, Carbon $end)
|
|
||||||
{
|
|
||||||
$current = clone $start;
|
|
||||||
$today = new Carbon;
|
|
||||||
$return = [
|
|
||||||
'name' => $account->name,
|
|
||||||
'id' => $account->id,
|
|
||||||
'type' => 'spline',
|
|
||||||
'pointStart' => $start->timestamp * 1000,
|
|
||||||
'pointInterval' => 24 * 3600 * 1000, // one day
|
|
||||||
'data' => []
|
|
||||||
];
|
|
||||||
|
|
||||||
while ($current <= $end) {
|
|
||||||
if ($current > $today) {
|
|
||||||
$return['data'][] = $account->predict(clone $current);
|
|
||||||
} else {
|
|
||||||
$return['data'][] = $account->balance(clone $current);
|
|
||||||
}
|
|
||||||
|
|
||||||
$current->addDay();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Account $account
|
|
||||||
* @param Carbon $date
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function accountDailySummary(\Account $account, Carbon $date)
|
|
||||||
{
|
|
||||||
$result = [
|
|
||||||
'rows' => [],
|
|
||||||
'sum' => 0
|
|
||||||
];
|
|
||||||
if ($account) {
|
|
||||||
// get journals in range:
|
|
||||||
$journals = \Auth::user()->transactionjournals()->with(
|
|
||||||
[
|
|
||||||
'transactions',
|
|
||||||
'transactions.account',
|
|
||||||
'transactioncurrency',
|
|
||||||
'transactiontype'
|
|
||||||
]
|
|
||||||
)
|
|
||||||
->distinct()
|
|
||||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
|
||||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
|
||||||
->where('transactions.account_id', $account->id)
|
|
||||||
->where('transaction_journals.date', $date->format('Y-m-d'))
|
|
||||||
->orderBy('transaction_journals.date', 'DESC')
|
|
||||||
->orderBy('transaction_journals.id', 'DESC')
|
|
||||||
->get(['transaction_journals.*']);
|
|
||||||
|
|
||||||
// loop all journals:
|
|
||||||
foreach ($journals as $journal) {
|
|
||||||
foreach ($journal->transactions as $transaction) {
|
|
||||||
$name = $transaction->account->name;
|
|
||||||
if ($transaction->account->id != $account->id) {
|
|
||||||
if (!isset($result['rows'][$name])) {
|
|
||||||
$result['rows'][$name] = [
|
|
||||||
'name' => $name,
|
|
||||||
'id' => $transaction->account->id,
|
|
||||||
'amount' => floatval($transaction->amount)
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
$result['rows'][$name]['amount'] += floatval($transaction->amount);
|
|
||||||
}
|
|
||||||
$result['sum'] += floatval($transaction->amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @throws \Firefly\Exception\FireflyException
|
|
||||||
*/
|
|
||||||
public function categories(Carbon $start, Carbon $end)
|
|
||||||
{
|
|
||||||
|
|
||||||
$result = [];
|
|
||||||
// grab all transaction journals in this period:
|
|
||||||
$journals = \TransactionJournal::
|
|
||||||
with(
|
|
||||||
['components', 'transactions' => function ($q) {
|
|
||||||
$q->where('amount', '>', 0);
|
|
||||||
}]
|
|
||||||
)
|
|
||||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
|
||||||
->where('transaction_types.type', 'Withdrawal')
|
|
||||||
->after($start)->before($end)
|
|
||||||
->where('completed', 1)
|
|
||||||
->get(['transaction_journals.*']);
|
|
||||||
foreach ($journals as $journal) {
|
|
||||||
// has to be one:
|
|
||||||
|
|
||||||
if (!isset($journal->transactions[0])) {
|
|
||||||
throw new FireflyException('Journal #' . $journal->id . ' has ' . count($journal->transactions)
|
|
||||||
. ' transactions!');
|
|
||||||
}
|
|
||||||
$transaction = $journal->transactions[0];
|
|
||||||
$amount = floatval($transaction->amount);
|
|
||||||
|
|
||||||
// get budget from journal:
|
|
||||||
$category = $journal->categories()->first();
|
|
||||||
$categoryName = is_null($category) ? '(no category)' : $category->name;
|
|
||||||
|
|
||||||
$result[$categoryName] = isset($result[$categoryName]) ? $result[$categoryName] + floatval($amount)
|
|
||||||
: $amount;
|
|
||||||
|
|
||||||
}
|
|
||||||
unset($journal, $transaction, $category, $amount);
|
|
||||||
|
|
||||||
// sort
|
|
||||||
arsort($result);
|
|
||||||
$chartData = [];
|
|
||||||
foreach ($result as $name => $value) {
|
|
||||||
$chartData[] = [$name, $value];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return $chartData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Category $category
|
|
||||||
* @param $range
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* @throws \Firefly\Exception\FireflyException
|
|
||||||
*/
|
|
||||||
public function categoryShowChart(\Category $category, $range, Carbon $start, Carbon $end)
|
|
||||||
{
|
|
||||||
$data = ['name' => $category->name . ' per ' . $range, 'data' => []];
|
|
||||||
// go back twelve periods. Skip if empty.
|
|
||||||
$beginning = clone $start;
|
|
||||||
switch ($range) {
|
|
||||||
default:
|
|
||||||
throw new FireflyException('No beginning for range ' . $range);
|
|
||||||
break;
|
|
||||||
case '1D':
|
|
||||||
$beginning->subDays(12);
|
|
||||||
break;
|
|
||||||
case '1W':
|
|
||||||
$beginning->subWeeks(12);
|
|
||||||
break;
|
|
||||||
case '1M':
|
|
||||||
$beginning->subYear();
|
|
||||||
break;
|
|
||||||
case '3M':
|
|
||||||
$beginning->subYears(3);
|
|
||||||
break;
|
|
||||||
case '6M':
|
|
||||||
$beginning->subYears(6);
|
|
||||||
break;
|
|
||||||
case 'custom':
|
|
||||||
$diff = $start->diff($end);
|
|
||||||
$days = $diff->days;
|
|
||||||
$beginning->subDays(12 * $days);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop over the periods:
|
|
||||||
while ($beginning <= $start) {
|
|
||||||
// increment currentEnd to fit beginning:
|
|
||||||
$currentEnd = clone $beginning;
|
|
||||||
// increase beginning for next round:
|
|
||||||
switch ($range) {
|
|
||||||
default:
|
|
||||||
throw new FireflyException('No currentEnd incremental for range ' . $range);
|
|
||||||
break;
|
|
||||||
case '1D':
|
|
||||||
break;
|
|
||||||
case '1W':
|
|
||||||
$currentEnd->addWeek()->subDay();
|
|
||||||
break;
|
|
||||||
case '1M':
|
|
||||||
$currentEnd->addMonth()->subDay();
|
|
||||||
break;
|
|
||||||
case '3M':
|
|
||||||
$currentEnd->addMonths(3)->subDay();
|
|
||||||
break;
|
|
||||||
case '6M':
|
|
||||||
$currentEnd->addMonths(6)->subDay();
|
|
||||||
break;
|
|
||||||
case 'custom':
|
|
||||||
$diff = $start->diff($end);
|
|
||||||
$days = $diff->days;
|
|
||||||
$days = $days == 1 ? 2 : $days;
|
|
||||||
$currentEnd->addDays($days)->subDay();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// now format the current range:
|
|
||||||
$title = '';
|
|
||||||
switch ($range) {
|
|
||||||
default:
|
|
||||||
throw new FireflyException('No date formats for frequency "' . $range . '"!');
|
|
||||||
break;
|
|
||||||
case '1D':
|
|
||||||
$title = $beginning->format('j F Y');
|
|
||||||
break;
|
|
||||||
case '1W':
|
|
||||||
$title = $beginning->format('\W\e\e\k W, Y');
|
|
||||||
break;
|
|
||||||
case '1M':
|
|
||||||
$title = $beginning->format('F Y');
|
|
||||||
break;
|
|
||||||
case '3M':
|
|
||||||
case '6M':
|
|
||||||
$title = $beginning->format('M Y') . ' - ' . $currentEnd->format('M Y');
|
|
||||||
break;
|
|
||||||
case 'custom':
|
|
||||||
$title = $beginning->format('d-m-Y') . ' - ' . $currentEnd->format('d-m-Y');
|
|
||||||
break;
|
|
||||||
case 'yearly':
|
|
||||||
// return $this->startdate->format('Y');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// get sum for current range:
|
|
||||||
$journals = \TransactionJournal::
|
|
||||||
with(
|
|
||||||
['transactions' => function ($q) {
|
|
||||||
$q->where('amount', '>', 0);
|
|
||||||
}]
|
|
||||||
)
|
|
||||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
|
||||||
->where('transaction_types.type', 'Withdrawal')
|
|
||||||
->leftJoin(
|
|
||||||
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
|
|
||||||
'transaction_journals.id'
|
|
||||||
)
|
|
||||||
->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id')
|
|
||||||
->where('components.id', '=', $category->id)
|
|
||||||
//->leftJoin()
|
|
||||||
->after($beginning)->before($currentEnd)
|
|
||||||
->where('completed', 1)
|
|
||||||
->get(['transaction_journals.*']);
|
|
||||||
$currentSum = 0;
|
|
||||||
foreach ($journals as $journal) {
|
|
||||||
if (!isset($journal->transactions[0])) {
|
|
||||||
throw new FireflyException('Journal #' . $journal->id . ' has ' . count($journal->transactions)
|
|
||||||
. ' transactions!');
|
|
||||||
}
|
|
||||||
$transaction = $journal->transactions[0];
|
|
||||||
$amount = floatval($transaction->amount);
|
|
||||||
$currentSum += $amount;
|
|
||||||
|
|
||||||
}
|
|
||||||
$data['data'][] = [$title, $currentSum];
|
|
||||||
|
|
||||||
// increase beginning for next round:
|
|
||||||
switch ($range) {
|
|
||||||
default:
|
|
||||||
throw new FireflyException('No incremental for range ' . $range);
|
|
||||||
break;
|
|
||||||
case '1D':
|
|
||||||
$beginning->addDay();
|
|
||||||
break;
|
|
||||||
case '1W':
|
|
||||||
$beginning->addWeek();
|
|
||||||
break;
|
|
||||||
case '1M':
|
|
||||||
$beginning->addMonth();
|
|
||||||
break;
|
|
||||||
case '3M':
|
|
||||||
$beginning->addMonths(3);
|
|
||||||
break;
|
|
||||||
case '6M':
|
|
||||||
$beginning->addMonths(6);
|
|
||||||
break;
|
|
||||||
case 'custom':
|
|
||||||
$diff = $start->diff($end);
|
|
||||||
$days = $diff->days;
|
|
||||||
|
|
||||||
$beginning->addDays($days);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
* @param Carbon $date
|
|
||||||
*
|
|
||||||
* @return float|null
|
|
||||||
*/
|
|
||||||
public function spentOnDay(\Budget $budget, Carbon $date)
|
|
||||||
{
|
|
||||||
return floatval(
|
|
||||||
\Transaction::
|
|
||||||
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
|
||||||
->leftJoin(
|
|
||||||
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
|
|
||||||
'transaction_journals.id'
|
|
||||||
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
|
|
||||||
'transaction_journals.date', $date->format('Y-m-d')
|
|
||||||
)->where('amount', '>', 0)->sum('amount')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
*
|
|
||||||
* @return int[]
|
|
||||||
*/
|
|
||||||
public function allJournalsInBudgetEnvelope(\Budget $budget)
|
|
||||||
{
|
|
||||||
$inRepetitions = [];
|
|
||||||
|
|
||||||
foreach ($budget->limits as $limit) {
|
|
||||||
foreach ($limit->limitrepetitions as $repetition) {
|
|
||||||
$set = $budget
|
|
||||||
->transactionjournals()
|
|
||||||
->transactionTypes(['Withdrawal'])
|
|
||||||
->after($repetition->startdate)
|
|
||||||
->before($repetition->enddate)
|
|
||||||
->get(['transaction_journals.id']);
|
|
||||||
|
|
||||||
foreach ($set as $item) {
|
|
||||||
$inRepetitions[] = $item->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $inRepetitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
* @param array $ids
|
|
||||||
*
|
|
||||||
* @return mixed|void
|
|
||||||
*/
|
|
||||||
public function journalsNotInSet(\Budget $budget, array $ids)
|
|
||||||
{
|
|
||||||
$query = $budget->transactionjournals()
|
|
||||||
->whereNotIn('transaction_journals.id', $ids)
|
|
||||||
->orderBy('date', 'DESC')
|
|
||||||
->orderBy('transaction_journals.id', 'DESC');
|
|
||||||
|
|
||||||
$result = $query->get(['transaction_journals.id']);
|
|
||||||
$set = [];
|
|
||||||
foreach ($result as $entry) {
|
|
||||||
$set[] = $entry->id;
|
|
||||||
}
|
|
||||||
return $set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $set
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function transactionsByJournals(array $set)
|
|
||||||
{
|
|
||||||
$transactions = \Transaction::whereIn('transaction_journal_id', $set)
|
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
|
||||||
->groupBy('transaction_journals.date')
|
|
||||||
->where('amount', '>', 0)->get(['transaction_journals.date', \DB::Raw('SUM(`amount`) as `aggregate`')]);
|
|
||||||
return $transactions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all limit (LimitRepetitions) for a budget falling in a certain date range.
|
|
||||||
*
|
|
||||||
* @param \Budget $budget
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function limitsInRange(\Budget $budget, Carbon $start, Carbon $end)
|
|
||||||
{
|
|
||||||
$reps = new Collection;
|
|
||||||
/** @var \Limit $limit */
|
|
||||||
foreach ($budget->limits as $limit) {
|
|
||||||
$set = $limit->limitrepetitions()->where(
|
|
||||||
function ($q) use ($start, $end) {
|
|
||||||
// startdate is between range
|
|
||||||
$q->where(
|
|
||||||
function ($q) use ($start, $end) {
|
|
||||||
$q->where('startdate', '>=', $start->format('Y-m-d'));
|
|
||||||
$q->where('startdate', '<=', $end->format('Y-m-d'));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// or enddate is between range.
|
|
||||||
$q->orWhere(
|
|
||||||
function ($q) use ($start, $end) {
|
|
||||||
$q->where('enddate', '>=', $start->format('Y-m-d'));
|
|
||||||
$q->where('enddate', '<=', $end->format('Y-m-d'));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)->get();
|
|
||||||
|
|
||||||
$reps = $reps->merge($set);
|
|
||||||
}
|
|
||||||
return $reps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Firefly checks how much money has been spend on the limitrepetition (aka: the current envelope) in
|
|
||||||
* the period denoted. Aka, the user has a certain amount of money in an envelope and wishes to know how
|
|
||||||
* much he has spent between the dates entered. This date range can be a partial match with the date range
|
|
||||||
* of the envelope or no match at all.
|
|
||||||
*
|
|
||||||
* @param \LimitRepetition $repetition
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function spentOnLimitRepetitionBetweenDates(\LimitRepetition $repetition, Carbon $start, Carbon $end)
|
|
||||||
{
|
|
||||||
return floatval(
|
|
||||||
\Transaction::
|
|
||||||
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
|
||||||
->leftJoin(
|
|
||||||
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
|
|
||||||
'transaction_journals.id'
|
|
||||||
)->where('component_transaction_journal.component_id', '=', $repetition->limit->budget->id)->where(
|
|
||||||
'transaction_journals.date', '>=', $start->format('Y-m-d')
|
|
||||||
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->where(
|
|
||||||
'amount', '>', 0
|
|
||||||
)->sum('amount')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface ChartInterface
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
interface ChartInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Account $account
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function account(\Account $account, Carbon $start, Carbon $end);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function categories(Carbon $start, Carbon $end);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Account $account
|
|
||||||
* @param Carbon $date
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function accountDailySummary(\Account $account, Carbon $date);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Category $category
|
|
||||||
* @param $range
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function categoryShowChart(\Category $category, $range, Carbon $start, Carbon $end);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
* @param Carbon $date
|
|
||||||
*
|
|
||||||
* @return float|null
|
|
||||||
*/
|
|
||||||
public function spentOnDay(\Budget $budget, Carbon $date);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
*
|
|
||||||
* @return int[]
|
|
||||||
*/
|
|
||||||
public function allJournalsInBudgetEnvelope(\Budget $budget);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Budget $budget
|
|
||||||
* @param array $ids
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function journalsNotInSet(\Budget $budget, array $ids);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $set
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function transactionsByJournals(array $set);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all limit (LimitRepetitions) for a budget falling in a certain date range.
|
|
||||||
*
|
|
||||||
* @param \Budget $budget
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function limitsInRange(\Budget $budget, Carbon $start, Carbon $end);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Firefly checks how much money has been spend on the limitrepetition (aka: the current envelope) in
|
|
||||||
* the period denoted. Aka, the user has a certain amount of money in an envelope and wishes to know how
|
|
||||||
* much he has spent between the dates entered. This date range can be a partial match with the date range
|
|
||||||
* of the envelope or no match at all.
|
|
||||||
*
|
|
||||||
* @param \LimitRepetition $repetition
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function spentOnLimitRepetitionBetweenDates(\LimitRepetition $repetition, Carbon $start, Carbon $end);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,396 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
use LaravelBook\Ardent\Builder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Json
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
class Json implements JsonInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Grabs all the parameters entered by the DataTables JQuery plugin and creates
|
|
||||||
* a nice array to be used by the other methods. It's also cleaning up and what-not.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function dataTableParameters()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Process all parameters!
|
|
||||||
*/
|
|
||||||
if (intval(\Input::get('length')) < 0) {
|
|
||||||
$length = 10000; // we get them all if no length is defined.
|
|
||||||
} else {
|
|
||||||
$length = intval(\Input::get('length'));
|
|
||||||
}
|
|
||||||
$parameters = [
|
|
||||||
'start' => intval(\Input::get('start')),
|
|
||||||
'length' => $length,
|
|
||||||
'draw' => intval(\Input::get('draw')),
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Columns:
|
|
||||||
*/
|
|
||||||
if (!is_null(\Input::get('columns')) && is_array(\Input::get('columns'))) {
|
|
||||||
foreach (\Input::get('columns') as $column) {
|
|
||||||
$parameters['columns'][] = [
|
|
||||||
'data' => $column['data'],
|
|
||||||
'name' => $column['name'],
|
|
||||||
'searchable' => $column['searchable'] == 'true' ? true : false,
|
|
||||||
'orderable' => $column['orderable'] == 'true' ? true : false,
|
|
||||||
'search' => [
|
|
||||||
'value' => $column['search']['value'],
|
|
||||||
'regex' => $column['search']['regex'] == 'true' ? true : false,
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sorting.
|
|
||||||
*/
|
|
||||||
$parameters['orderOnAccount'] = false;
|
|
||||||
if (!is_null(\Input::get('order')) && is_array(\Input::get('order'))) {
|
|
||||||
foreach (\Input::get('order') as $order) {
|
|
||||||
$columnIndex = intval($order['column']);
|
|
||||||
$columnName = $parameters['columns'][$columnIndex]['name'];
|
|
||||||
$parameters['order'][] = [
|
|
||||||
'name' => $columnName,
|
|
||||||
'dir' => strtoupper($order['dir'])
|
|
||||||
];
|
|
||||||
if ($columnName == 'to' || $columnName == 'from') {
|
|
||||||
$parameters['orderOnAccount'] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Search parameters:
|
|
||||||
*/
|
|
||||||
$parameters['search'] = [
|
|
||||||
'value' => '',
|
|
||||||
'regex' => false
|
|
||||||
];
|
|
||||||
if (!is_null(\Input::get('search')) && is_array(\Input::get('search'))) {
|
|
||||||
$search = \Input::get('search');
|
|
||||||
$parameters['search'] = [
|
|
||||||
'value' => $search['value'],
|
|
||||||
'regex' => $search['regex'] == 'true' ? true : false
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return $parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do some sorting, counting and ordering on the query and return a nicely formatted array
|
|
||||||
* that can be used by the DataTables JQuery plugin.
|
|
||||||
*
|
|
||||||
* @param array $parameters
|
|
||||||
* @param Builder $query
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function journalDataset(array $parameters, Builder $query)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Count query:
|
|
||||||
*/
|
|
||||||
$count = $query->count();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update the selection:
|
|
||||||
*/
|
|
||||||
|
|
||||||
$query->take($parameters['length']);
|
|
||||||
if ($parameters['start'] > 0) {
|
|
||||||
$query->skip($parameters['start']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input search parameters:
|
|
||||||
*/
|
|
||||||
$filtered = $count;
|
|
||||||
if (strlen($parameters['search']['value']) > 0) {
|
|
||||||
$query->where('transaction_journals.description', 'LIKE', '%' . e($parameters['search']['value']) . '%');
|
|
||||||
$filtered = $query->count();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Build return array:
|
|
||||||
*/
|
|
||||||
$data = [
|
|
||||||
'draw' => $parameters['draw'],
|
|
||||||
'recordsTotal' => $count,
|
|
||||||
'recordsFiltered' => $filtered,
|
|
||||||
'data' => [],
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get paginated result set:
|
|
||||||
*/
|
|
||||||
if ($parameters['orderOnAccount'] === true) {
|
|
||||||
/** @var Collection $set */
|
|
||||||
$set = $query->get(
|
|
||||||
[
|
|
||||||
'transaction_journals.*',
|
|
||||||
't1.amount',
|
|
||||||
't1.account_id AS from_id',
|
|
||||||
'a1.name AS from',
|
|
||||||
't2.account_id AS to_id',
|
|
||||||
'a2.name AS to',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
/** @var Collection $set */
|
|
||||||
$set = $query->get(
|
|
||||||
[
|
|
||||||
'transaction_journals.*',
|
|
||||||
'transactions.amount',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loop set and create entries to return.
|
|
||||||
*/
|
|
||||||
/** @var \TransactionJournal $entry */
|
|
||||||
foreach ($set as $entry) {
|
|
||||||
$from = $entry->transactions[0]->account;
|
|
||||||
$to = $entry->transactions[1]->account;
|
|
||||||
$budget = $entry->budgets()->first();
|
|
||||||
$category = $entry->categories()->first();
|
|
||||||
$recurring = $entry->recurringTransaction()->first();
|
|
||||||
$arr = [
|
|
||||||
'date' => $entry->date->format('j F Y'),
|
|
||||||
'description' => [
|
|
||||||
'description' => $entry->description,
|
|
||||||
'url' => route('transactions.show', $entry->id)
|
|
||||||
],
|
|
||||||
'amount' => floatval($entry->amount),
|
|
||||||
'from' => ['name' => $from->name, 'url' => route('accounts.show', $from->id)],
|
|
||||||
'to' => ['name' => $to->name, 'url' => route('accounts.show', $to->id)],
|
|
||||||
'components' => [
|
|
||||||
'budget_id' => 0,
|
|
||||||
'budget_url' => '',
|
|
||||||
'budget_name' => '',
|
|
||||||
'category_id' => 0,
|
|
||||||
'category_url' => '',
|
|
||||||
'category_name' => ''
|
|
||||||
],
|
|
||||||
'id' => [
|
|
||||||
'edit' => route('transactions.edit', $entry->id),
|
|
||||||
'delete' => route('transactions.delete', $entry->id)
|
|
||||||
]
|
|
||||||
];
|
|
||||||
if ($budget) {
|
|
||||||
$arr['components']['budget_id'] = $budget->id;
|
|
||||||
$arr['components']['budget_name'] = $budget->name;
|
|
||||||
$arr['components']['budget_url'] = route('budgets.show', $budget->id);
|
|
||||||
}
|
|
||||||
if ($category) {
|
|
||||||
$arr['components']['category_id'] = $category->id;
|
|
||||||
$arr['components']['category_name'] = $category->name;
|
|
||||||
$arr['components']['category_url'] = route('categories.show', $category->id);
|
|
||||||
}
|
|
||||||
if ($recurring) {
|
|
||||||
$arr['components']['recurring_id'] = $recurring->id;
|
|
||||||
$arr['components']['recurring_name'] = e($recurring->name);
|
|
||||||
$arr['components']['recurring_url'] = route('recurring.show', $recurring->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['data'][] = $arr;
|
|
||||||
|
|
||||||
}
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds most of the query required to grab transaction journals from the database.
|
|
||||||
* This is useful because all three pages showing different kinds of transactions use
|
|
||||||
* the exact same query with only slight differences.
|
|
||||||
*
|
|
||||||
* @param array $parameters
|
|
||||||
*
|
|
||||||
* @return Builder
|
|
||||||
*/
|
|
||||||
public function journalQuery(array $parameters)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* We need the following vars to fine tune the query:
|
|
||||||
*/
|
|
||||||
if ($parameters['amount'] == 'negative') {
|
|
||||||
$operator = '<';
|
|
||||||
$operatorNegated = '>';
|
|
||||||
$function = 'lessThan';
|
|
||||||
} else {
|
|
||||||
$operator = '>';
|
|
||||||
$operatorNegated = '<';
|
|
||||||
$function = 'moreThan';
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Build query:
|
|
||||||
*/
|
|
||||||
$query = \TransactionJournal::transactionTypes($parameters['transactionTypes'])->withRelevantData();
|
|
||||||
$query->where('user_id', \Auth::user()->id);
|
|
||||||
$query->where('completed', 1);
|
|
||||||
/*
|
|
||||||
* This is complex. Join `transactions` twice, once for the "to" account and once for the
|
|
||||||
* "from" account. Then get the amount from one of these (depends on type).
|
|
||||||
*
|
|
||||||
* Only need to do this when there's a sort order for "from" or "to".
|
|
||||||
*
|
|
||||||
* Also need the table prefix for this to work.
|
|
||||||
*/
|
|
||||||
if ($parameters['orderOnAccount'] === true) {
|
|
||||||
$connection = \Config::get('database.default');
|
|
||||||
$prefix = \Config::get('database.connections.' . $connection . '.prefix');
|
|
||||||
// left join first table for "from" account:
|
|
||||||
$query->leftJoin(
|
|
||||||
'transactions AS ' . $prefix . 't1', function ($join) use ($operator) {
|
|
||||||
$join->on('t1.transaction_journal_id', '=', 'transaction_journals.id')
|
|
||||||
->on('t1.amount', $operator, \DB::Raw(0));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// left join second table for "to" account:
|
|
||||||
$query->leftJoin(
|
|
||||||
'transactions AS ' . $prefix . 't2', function ($join) use ($operatorNegated) {
|
|
||||||
$join->on('t2.transaction_journal_id', '=', 'transaction_journals.id')
|
|
||||||
->on('t2.amount', $operatorNegated, \DB::Raw(0));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// also join accounts twice to get the account's name, which we need for sorting.
|
|
||||||
$query->leftJoin('accounts as ' . $prefix . 'a1', 'a1.id', '=', 't1.account_id');
|
|
||||||
$query->leftJoin('accounts as ' . $prefix . 'a2', 'a2.id', '=', 't2.account_id');
|
|
||||||
} else {
|
|
||||||
// less complex
|
|
||||||
$query->$function(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add sort parameters to query:
|
|
||||||
*/
|
|
||||||
if (isset($parameters['order']) && count($parameters['order']) > 0) {
|
|
||||||
foreach ($parameters['order'] as $order) {
|
|
||||||
$query->orderBy($order['name'], $order['dir']);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$query->defaultSorting();
|
|
||||||
}
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do some sorting, counting and ordering on the query and return a nicely formatted array
|
|
||||||
* that can be used by the DataTables JQuery plugin.
|
|
||||||
*
|
|
||||||
* @param array $parameters
|
|
||||||
* @param Builder $query
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function recurringTransactionsDataset(array $parameters, Builder $query)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Count query:
|
|
||||||
*/
|
|
||||||
$count = $query->count();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update the selection:
|
|
||||||
*/
|
|
||||||
|
|
||||||
$query->take($parameters['length']);
|
|
||||||
if ($parameters['start'] > 0) {
|
|
||||||
$query->skip($parameters['start']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Input search parameters:
|
|
||||||
*/
|
|
||||||
$filtered = $count;
|
|
||||||
if (strlen($parameters['search']['value']) > 0) {
|
|
||||||
$query->where('recurring_transactions.description', 'LIKE', '%' . e($parameters['search']['value']) . '%');
|
|
||||||
$filtered = $query->count();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Build return array:
|
|
||||||
*/
|
|
||||||
$data = [
|
|
||||||
'draw' => $parameters['draw'],
|
|
||||||
'recordsTotal' => $count,
|
|
||||||
'recordsFiltered' => $filtered,
|
|
||||||
'data' => [],
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get paginated result set:
|
|
||||||
*/
|
|
||||||
/** @var Collection $set */
|
|
||||||
$set = $query->get(
|
|
||||||
[
|
|
||||||
'recurring_transactions.*',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loop set and create entries to return.
|
|
||||||
*/
|
|
||||||
foreach ($set as $entry) {
|
|
||||||
$set = [
|
|
||||||
|
|
||||||
'name' => ['name' => $entry->name, 'url' => route('recurring.show', $entry->id)],
|
|
||||||
'match' => explode(' ', $entry->match),
|
|
||||||
'amount_max' => floatval($entry->amount_max),
|
|
||||||
'amount_min' => floatval($entry->amount_min),
|
|
||||||
'date' => $entry->date->format('j F Y'),
|
|
||||||
'active' => intval($entry->active),
|
|
||||||
'automatch' => intval($entry->automatch),
|
|
||||||
'repeat_freq' => $entry->repeat_freq,
|
|
||||||
'id' => [
|
|
||||||
'edit' => route('recurring.edit', $entry->id),
|
|
||||||
'delete' => route('recurring.delete', $entry->id)
|
|
||||||
]
|
|
||||||
];
|
|
||||||
if (intval($entry->skip) > 0) {
|
|
||||||
$set['repeat_freq'] = $entry->repeat_freq . ' (skip ' . $entry->skip . ')';
|
|
||||||
}
|
|
||||||
$data['data'][] = $set;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a query that will pick up all recurring transactions from the database.
|
|
||||||
*
|
|
||||||
* @param array $parameters
|
|
||||||
*
|
|
||||||
* @return Builder
|
|
||||||
*/
|
|
||||||
public function recurringTransactionsQuery(array $parameters)
|
|
||||||
{
|
|
||||||
$query = \RecurringTransaction::where('user_id', \Auth::user()->id);
|
|
||||||
|
|
||||||
if (isset($parameters['order']) && count($parameters['order']) > 0) {
|
|
||||||
foreach ($parameters['order'] as $order) {
|
|
||||||
$query->orderBy($order['name'], $order['dir']);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$query->orderBy('name', 'ASC');
|
|
||||||
}
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
use LaravelBook\Ardent\Builder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface JsonInterface
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
interface JsonInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grabs all the parameters entered by the DataTables JQuery plugin and creates
|
|
||||||
* a nice array to be used by the other methods. It's also cleaning up and what-not.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function dataTableParameters();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do some sorting, counting and ordering on the query and return a nicely formatted array
|
|
||||||
* that can be used by the DataTables JQuery plugin.
|
|
||||||
*
|
|
||||||
* @param array $parameters
|
|
||||||
* @param Builder $query
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function journalDataset(array $parameters, Builder $query);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds most of the query required to grab transaction journals from the database.
|
|
||||||
* This is useful because all three pages showing different kinds of transactions use
|
|
||||||
* the exact same query with only slight differences.
|
|
||||||
*
|
|
||||||
* @param array $parameters
|
|
||||||
*
|
|
||||||
* @return Builder
|
|
||||||
*/
|
|
||||||
public function journalQuery(array $parameters);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do some sorting, counting and ordering on the query and return a nicely formatted array
|
|
||||||
* that can be used by the DataTables JQuery plugin.
|
|
||||||
*
|
|
||||||
* @param array $parameters
|
|
||||||
* @param Builder $query
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function recurringTransactionsDataset(array $parameters, Builder $query);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a query that will pick up all recurring transactions from the database.
|
|
||||||
*
|
|
||||||
* @param array $parameters
|
|
||||||
*
|
|
||||||
* @return Builder
|
|
||||||
*/
|
|
||||||
public function recurringTransactionsQuery(array $parameters);
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Exception;
|
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
class Recurring implements RecurringInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns messages about the validation.
|
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function validate(array $data)
|
|
||||||
{
|
|
||||||
$errors = new MessageBag;
|
|
||||||
$warnings = new MessageBag;
|
|
||||||
$successes = new MessageBag;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Name:
|
|
||||||
*/
|
|
||||||
if (strlen($data['name']) == 0) {
|
|
||||||
$errors->add('name', 'The name should not be this short.');
|
|
||||||
}
|
|
||||||
if (strlen($data['name']) > 250) {
|
|
||||||
$errors->add('name', 'The name should not be this long.');
|
|
||||||
}
|
|
||||||
if (! isset($data['id'])) {
|
|
||||||
$count = \Auth::user()->recurringtransactions()->whereName($data['name'])->count();
|
|
||||||
} else {
|
|
||||||
$count = \Auth::user()->recurringtransactions()->whereName($data['name'])->where('id', '!=', $data['id'])->count();
|
|
||||||
}
|
|
||||||
if ($count > 0) {
|
|
||||||
$errors->add('name', 'A recurring transaction with this name already exists.');
|
|
||||||
}
|
|
||||||
if (count($errors->get('name')) == 0) {
|
|
||||||
$successes->add('name', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Match
|
|
||||||
*/
|
|
||||||
if (count(explode(',', $data['match'])) > 10) {
|
|
||||||
$warnings->add('match', 'This many matches is pretty pointless');
|
|
||||||
}
|
|
||||||
if (strlen($data['match']) == 0) {
|
|
||||||
$errors->add('match', 'Cannot match on nothing.');
|
|
||||||
}
|
|
||||||
if (count($errors->get('match')) == 0) {
|
|
||||||
$successes->add('match', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Amount
|
|
||||||
*/
|
|
||||||
if (floatval($data['amount_max']) == 0 && floatval($data['amount_min']) == 0) {
|
|
||||||
$errors->add('amount_min', 'Amount max and min cannot both be zero.');
|
|
||||||
$errors->add('amount_max', 'Amount max and min cannot both be zero.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (floatval($data['amount_max']) < floatval($data['amount_min'])) {
|
|
||||||
$errors->add('amount_max', 'Amount max must be more than amount min.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (floatval($data['amount_min']) > floatval($data['amount_max'])) {
|
|
||||||
$errors->add('amount_max', 'Amount min must be less than amount max.');
|
|
||||||
}
|
|
||||||
if (count($errors->get('amount_min')) == 0) {
|
|
||||||
$successes->add('amount_min', 'OK!');
|
|
||||||
}
|
|
||||||
if (count($errors->get('amount_max')) == 0) {
|
|
||||||
$successes->add('amount_max', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Date
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
$date = new Carbon($data['date']);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$errors->add('date', 'The date entered was invalid');
|
|
||||||
}
|
|
||||||
if (strlen($data['date']) == 0) {
|
|
||||||
$errors->add('date', 'The date entered was invalid');
|
|
||||||
}
|
|
||||||
if (!$errors->has('date')) {
|
|
||||||
$successes->add('date', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
$successes->add('active', 'OK!');
|
|
||||||
$successes->add('automatch', 'OK!');
|
|
||||||
|
|
||||||
if (intval($data['skip']) < 0) {
|
|
||||||
$errors->add('skip', 'Cannot be below zero.');
|
|
||||||
} else if (intval($data['skip']) > 31) {
|
|
||||||
$errors->add('skip', 'Cannot be above 31.');
|
|
||||||
}
|
|
||||||
if (count($errors->get('skip')) == 0) {
|
|
||||||
$successes->add('skip', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
$set = \Config::get('firefly.budget_periods');
|
|
||||||
if (!in_array($data['repeat_freq'], $set)) {
|
|
||||||
$errors->add('repeat_freq', 'Invalid value.');
|
|
||||||
}
|
|
||||||
if (count($errors->get('repeat_freq')) == 0) {
|
|
||||||
$successes->add('repeat_freq', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
|
|
||||||
interface RecurringInterface {
|
|
||||||
/**
|
|
||||||
* Returns messages about the validation.
|
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function validate(array $data);
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Search
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
class Search implements SearchInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchTransactions(array $words)
|
|
||||||
{
|
|
||||||
return \Auth::user()->transactionjournals()->withRelevantData()->where(
|
|
||||||
function ($q) use ($words) {
|
|
||||||
foreach ($words as $word) {
|
|
||||||
$q->orWhere('description', 'LIKE', '%' . e($word) . '%');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchAccounts(array $words)
|
|
||||||
{
|
|
||||||
return \Auth::user()->accounts()->with('accounttype')->where(
|
|
||||||
function ($q) use ($words) {
|
|
||||||
foreach ($words as $word) {
|
|
||||||
$q->orWhere('name', 'LIKE', '%' . e($word) . '%');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchCategories(array $words)
|
|
||||||
{
|
|
||||||
/** @var Collection $set */
|
|
||||||
$set = \Auth::user()->categories()->get();
|
|
||||||
$newSet = $set->filter(
|
|
||||||
function (\Category $c) use ($words) {
|
|
||||||
$found = 0;
|
|
||||||
foreach ($words as $word) {
|
|
||||||
if (!(strpos(strtolower($c->name), strtolower($word)) === false)) {
|
|
||||||
$found++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $found > 0;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return $newSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchBudgets(array $words)
|
|
||||||
{
|
|
||||||
/** @var Collection $set */
|
|
||||||
$set = \Auth::user()->budgets()->get();
|
|
||||||
$newSet = $set->filter(
|
|
||||||
function (\Budget $b) use ($words) {
|
|
||||||
$found = 0;
|
|
||||||
foreach ($words as $word) {
|
|
||||||
if (!(strpos(strtolower($b->name), strtolower($word)) === false)) {
|
|
||||||
$found++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $found > 0;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return $newSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function searchTags(array $words)
|
|
||||||
{
|
|
||||||
return new Collection;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface SearchInterface
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
interface SearchInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*/
|
|
||||||
public function searchTransactions(array $words);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*/
|
|
||||||
public function searchAccounts(array $words);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*/
|
|
||||||
public function searchCategories(array $words);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*/
|
|
||||||
public function searchBudgets(array $words);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $words
|
|
||||||
*/
|
|
||||||
public function searchTags(array $words);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,485 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Exception;
|
|
||||||
use Firefly\Exception\FireflyException;
|
|
||||||
use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
|
||||||
use Firefly\Storage\Budget\BudgetRepositoryInterface as BRI;
|
|
||||||
use Firefly\Storage\Category\CategoryRepositoryInterface as CRI;
|
|
||||||
use Firefly\Storage\Piggybank\PiggybankRepositoryInterface as PRI;
|
|
||||||
use Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface as TJRI;
|
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Transaction
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
class Transaction implements TransactionInterface
|
|
||||||
{
|
|
||||||
protected $_user = null;
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $_journals */
|
|
||||||
protected $_journals;
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Category\CategoryRepositoryInterface $_categories */
|
|
||||||
protected $_categories;
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $_budgets */
|
|
||||||
protected $_budgets;
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $_piggybanks */
|
|
||||||
protected $_piggybanks;
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $_accounts */
|
|
||||||
protected $_accounts;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param TJRI $journals
|
|
||||||
* @param CRI $categories
|
|
||||||
* @param BRI $budgets
|
|
||||||
* @param PRI $piggybanks
|
|
||||||
* @param ARI $accounts
|
|
||||||
*/
|
|
||||||
public function __construct(TJRI $journals, CRI $categories, BRI $budgets, PRI $piggybanks, ARI $accounts)
|
|
||||||
{
|
|
||||||
$this->_journals = $journals;
|
|
||||||
$this->_categories = $categories;
|
|
||||||
$this->_budgets = $budgets;
|
|
||||||
$this->_piggybanks = $piggybanks;
|
|
||||||
$this->_accounts = $accounts;
|
|
||||||
$this->overruleUser(\Auth::user());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed|void
|
|
||||||
*/
|
|
||||||
public function overruleUser(\User $user)
|
|
||||||
{
|
|
||||||
$this->_user = $user;
|
|
||||||
$this->_journals->overruleUser($user);
|
|
||||||
$this->_categories->overruleUser($user);
|
|
||||||
$this->_budgets->overruleUser($user);
|
|
||||||
$this->_piggybanks->overruleUser($user);
|
|
||||||
$this->_accounts->overruleUser($user);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \TransactionJournal $journal
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return MessageBag|\TransactionJournal
|
|
||||||
*/
|
|
||||||
public function update(\TransactionJournal $journal, array $data)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Update the journal using the repository.
|
|
||||||
*/
|
|
||||||
$journal = $this->_journals->update($journal, $data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If invalid, return the message bag:
|
|
||||||
*/
|
|
||||||
if (!$journal->validate()) {
|
|
||||||
return $journal->errors();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find budget using repository
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (isset($data['budget_id'])) {
|
|
||||||
$budget = $this->_budgets->find($data['budget_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find category using repository
|
|
||||||
*/
|
|
||||||
$category = $this->_categories->firstOrCreate($data['category']);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find piggy bank using repository:
|
|
||||||
*/
|
|
||||||
$piggybank = null;
|
|
||||||
if (isset($data['piggybank_id'])) {
|
|
||||||
$piggybank = $this->_piggybanks->find($data['piggybank_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* save accounts using repositories
|
|
||||||
* this depends on the kind of transaction and i've yet to fix this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (isset($data['account_id'])) {
|
|
||||||
$from = $this->_accounts->findAssetAccountById($data['account_id']);
|
|
||||||
}
|
|
||||||
if (isset($data['expense_account'])) {
|
|
||||||
$to = $this->_accounts->findExpenseAccountByName($data['expense_account']);
|
|
||||||
}
|
|
||||||
if (isset($data['revenue_account'])) {
|
|
||||||
$from = $this->_accounts->findRevenueAccountByName($data['revenue_account']);
|
|
||||||
$to = $this->_accounts->findAssetAccountById($data['account_id']);
|
|
||||||
}
|
|
||||||
if (isset($data['account_from_id'])) {
|
|
||||||
$from = $this->_accounts->findAssetAccountById($data['account_from_id']);
|
|
||||||
}
|
|
||||||
if (isset($data['account_to_id'])) {
|
|
||||||
$to = $this->_accounts->findAssetAccountById($data['account_to_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add a custom error when they are the same.
|
|
||||||
*/
|
|
||||||
if ($to->id == $from->id) {
|
|
||||||
$bag = new MessageBag;
|
|
||||||
$bag->add('account_from_id', 'The account from cannot be the same as the account to.');
|
|
||||||
return $bag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the transactions need new data:
|
|
||||||
*/
|
|
||||||
$transactions = $journal->transactions()->orderBy('amount', 'ASC')->get();
|
|
||||||
/** @var \Transaction $transaction */
|
|
||||||
foreach ($transactions as $index => $transaction) {
|
|
||||||
switch (true) {
|
|
||||||
case ($index == 0): // FROM account
|
|
||||||
$transaction->account()->associate($from);
|
|
||||||
$transaction->amount = floatval($data['amount']) * -1;
|
|
||||||
break;
|
|
||||||
case ($index == 1): // TO account.
|
|
||||||
$transaction->account()->associate($to);
|
|
||||||
$transaction->amount = floatval($data['amount']);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$transaction->save();
|
|
||||||
// either way, try to attach the piggy bank:
|
|
||||||
if (!is_null($piggybank)) {
|
|
||||||
if ($piggybank->account_id == $transaction->account_id) {
|
|
||||||
$transaction->piggybank()->associate($piggybank);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Connect budget and category:
|
|
||||||
*/
|
|
||||||
$budgetids = !isset($budget) || (isset($budget) && is_null($budget)) ? [] : [$budget->id];
|
|
||||||
$catids = is_null($category) ? [] : [$category->id];
|
|
||||||
$components = array_merge($budgetids,$catids);
|
|
||||||
$journal->components()->sync($components);
|
|
||||||
$journal->save();
|
|
||||||
|
|
||||||
if (isset($data['return_journal']) && $data['return_journal'] == true) {
|
|
||||||
return $journal;
|
|
||||||
}
|
|
||||||
return $journal->errors();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns messages about the validation.
|
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
* @return array
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public function validate(array $data)
|
|
||||||
{
|
|
||||||
$errors = new MessageBag;
|
|
||||||
$warnings = new MessageBag;
|
|
||||||
$successes = new MessageBag;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Description:
|
|
||||||
*/
|
|
||||||
if (strlen($data['description']) == 0) {
|
|
||||||
$errors->add('description', 'The description should not be this short.');
|
|
||||||
}
|
|
||||||
if (strlen($data['description']) > 250) {
|
|
||||||
$errors->add('description', 'The description should not be this long.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Amount
|
|
||||||
*/
|
|
||||||
if (floatval($data['amount']) <= 0) {
|
|
||||||
$errors->add('amount', 'The amount cannot be zero or less than zero.');
|
|
||||||
}
|
|
||||||
if (floatval($data['amount']) > 10000) {
|
|
||||||
$warnings->add('amount', 'OK, but that\'s a lot of money dude.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Date
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
$date = new Carbon($data['date']);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$errors->add('date', 'The date entered was invalid');
|
|
||||||
}
|
|
||||||
if (strlen($data['date']) == 0) {
|
|
||||||
$errors->add('date', 'The date entered was invalid');
|
|
||||||
}
|
|
||||||
if (!$errors->has('date')) {
|
|
||||||
$successes->add('date', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Category
|
|
||||||
*/
|
|
||||||
$category = $this->_categories->findByName($data['category']);
|
|
||||||
if (strlen($data['category']) == 0) {
|
|
||||||
$warnings->add('category', 'No category will be created.');
|
|
||||||
} else {
|
|
||||||
if (is_null($category)) {
|
|
||||||
$warnings->add('category', 'Will have to be created.');
|
|
||||||
} else {
|
|
||||||
$successes->add('category', 'OK!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($data['what']) {
|
|
||||||
default:
|
|
||||||
throw new FireflyException('Cannot validate a ' . $data['what']);
|
|
||||||
break;
|
|
||||||
case 'deposit':
|
|
||||||
/*
|
|
||||||
* Tests for deposit
|
|
||||||
*/
|
|
||||||
// asset account
|
|
||||||
$accountId = isset($data['account_id']) ? intval($data['account_id']) : 0;
|
|
||||||
$account = $this->_accounts->find($accountId);
|
|
||||||
if (is_null($account)) {
|
|
||||||
$errors->add('account_id', 'Cannot find this asset account.');
|
|
||||||
} else {
|
|
||||||
$successes->add('account_id', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
// revenue account:
|
|
||||||
if (strlen($data['revenue_account']) == 0) {
|
|
||||||
$warnings->add('revenue_account', 'Revenue account will be "cash".');
|
|
||||||
} else {
|
|
||||||
$exp = $this->_accounts->findRevenueAccountByName($data['revenue_account'], false);
|
|
||||||
if (is_null($exp)) {
|
|
||||||
$warnings->add('revenue_account', 'Expense account will be created.');
|
|
||||||
} else {
|
|
||||||
$successes->add('revenue_account', 'OK!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'transfer':
|
|
||||||
// account from
|
|
||||||
$accountId = isset($data['account_from_id']) ? intval($data['account_from_id']) : 0;
|
|
||||||
$account = $this->_accounts->find($accountId);
|
|
||||||
if (is_null($account)) {
|
|
||||||
$errors->add('account_from_id', 'Cannot find this asset account.');
|
|
||||||
} else {
|
|
||||||
$successes->add('account_from_id', 'OK!');
|
|
||||||
}
|
|
||||||
unset($accountId);
|
|
||||||
// account to
|
|
||||||
$accountId = isset($data['account_to_id']) ? intval($data['account_to_id']) : 0;
|
|
||||||
$account = $this->_accounts->find($accountId);
|
|
||||||
if (is_null($account)) {
|
|
||||||
$errors->add('account_to_id', 'Cannot find this asset account.');
|
|
||||||
} else {
|
|
||||||
$successes->add('account_to_id', 'OK!');
|
|
||||||
}
|
|
||||||
unset($accountId);
|
|
||||||
|
|
||||||
// piggy bank
|
|
||||||
$piggybankId = isset($data['piggybank_id']) ? intval($data['piggybank_id']) : 0;
|
|
||||||
$piggybank = $this->_piggybanks->find($piggybankId);
|
|
||||||
if (is_null($piggybank)) {
|
|
||||||
$warnings->add('piggybank_id', 'No piggy bank will be modified.');
|
|
||||||
} else {
|
|
||||||
$successes->add('piggybank_id', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'withdrawal':
|
|
||||||
/*
|
|
||||||
* Tests for withdrawal
|
|
||||||
*/
|
|
||||||
// asset account
|
|
||||||
$accountId = isset($data['account_id']) ? intval($data['account_id']) : 0;
|
|
||||||
$account = $this->_accounts->find($accountId);
|
|
||||||
if (is_null($account)) {
|
|
||||||
$errors->add('account_id', 'Cannot find this asset account.');
|
|
||||||
} else {
|
|
||||||
$successes->add('account_id', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
// expense account
|
|
||||||
if (strlen($data['expense_account']) == 0) {
|
|
||||||
$warnings->add('expense_account', 'Expense account will be "cash".');
|
|
||||||
} else {
|
|
||||||
$exp = $this->_accounts->findExpenseAccountByName($data['expense_account'], false);
|
|
||||||
if (is_null($exp)) {
|
|
||||||
$warnings->add('expense_account', 'Expense account will be created.');
|
|
||||||
} else {
|
|
||||||
$successes->add('expense_account', 'OK!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// budget
|
|
||||||
if (!isset($data['budget_id']) || (isset($data['budget_id']) && intval($data['budget_id']) == 0)) {
|
|
||||||
$warnings->add('budget_id', 'No budget selected.');
|
|
||||||
} else {
|
|
||||||
$budget = $this->_budgets->find(intval($data['budget_id']));
|
|
||||||
if (is_null($budget)) {
|
|
||||||
$errors->add('budget_id', 'This budget does not exist');
|
|
||||||
} else {
|
|
||||||
$successes->add('budget_id', 'OK!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($errors->get('description')) == 0) {
|
|
||||||
$successes->add('description', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($errors->get('amount')) == 0) {
|
|
||||||
$successes->add('amount', 'OK!');
|
|
||||||
}
|
|
||||||
|
|
||||||
return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
|
|
||||||
/*
|
|
||||||
* Tests for deposit
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Tests for transfer
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a full transaction journal and associated stuff
|
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return MessageBag|\TransactionJournal
|
|
||||||
*
|
|
||||||
* @SuppressWarnings(PHPMD.ShortVariable)
|
|
||||||
*/
|
|
||||||
public function store(array $data)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* save journal using repository
|
|
||||||
*/
|
|
||||||
$journal = $this->_journals->store($data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If invalid, return the message bag:
|
|
||||||
*/
|
|
||||||
if (!$journal->validate()) {
|
|
||||||
return $journal->errors();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find budget using repository
|
|
||||||
*/
|
|
||||||
if (isset($data['budget_id'])) {
|
|
||||||
$budget = $this->_budgets->find($data['budget_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find category using repository
|
|
||||||
*/
|
|
||||||
$category = $this->_categories->firstOrCreate($data['category']);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find piggy bank using repository:
|
|
||||||
*/
|
|
||||||
$piggybank = null;
|
|
||||||
if (isset($data['piggybank_id'])) {
|
|
||||||
$piggybank = $this->_piggybanks->find($data['piggybank_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* save accounts using repositories
|
|
||||||
* this depends on the kind of transaction and i've yet to fix this.
|
|
||||||
*/
|
|
||||||
if (isset($data['account_id'])) {
|
|
||||||
$from = $this->_accounts->findAssetAccountById($data['account_id']);
|
|
||||||
}
|
|
||||||
if (isset($data['expense_account'])) {
|
|
||||||
$to = $this->_accounts->findExpenseAccountByName($data['expense_account']);
|
|
||||||
|
|
||||||
}
|
|
||||||
if (isset($data['revenue_account'])) {
|
|
||||||
$from = $this->_accounts->findRevenueAccountByName($data['revenue_account']);
|
|
||||||
$to = $this->_accounts->findAssetAccountById($data['account_id']);
|
|
||||||
}
|
|
||||||
if (isset($data['account_from_id'])) {
|
|
||||||
$from = $this->_accounts->findAssetAccountById($data['account_from_id']);
|
|
||||||
}
|
|
||||||
if (isset($data['account_to_id'])) {
|
|
||||||
$to = $this->_accounts->findAssetAccountById($data['account_to_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add a custom error when they are the same.
|
|
||||||
*/
|
|
||||||
if ($to->id == $from->id) {
|
|
||||||
$bag = new MessageBag;
|
|
||||||
$bag->add('account_from_id', 'The account from cannot be the same as the account to.');
|
|
||||||
return $bag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Save transactions using repository. We try to connect the (possibly existing)
|
|
||||||
* piggy bank to either transaction, knowing it will only work with one of them.
|
|
||||||
*/
|
|
||||||
/** @var \Transaction $one */
|
|
||||||
$one = $this->_journals->saveTransaction($journal, $from, floatval($data['amount']) * -1);
|
|
||||||
$one->connectPiggybank($piggybank);
|
|
||||||
$two = $this->_journals->saveTransaction($journal, $to, floatval($data['amount']));
|
|
||||||
$two->connectPiggybank($piggybank);
|
|
||||||
/*
|
|
||||||
* Count for $journal is zero? Then there were errors!
|
|
||||||
*/
|
|
||||||
if ($journal->transactions()->count() < 2) {
|
|
||||||
/*
|
|
||||||
* Join message bags and return them:
|
|
||||||
*/
|
|
||||||
$bag = $one->errors();
|
|
||||||
$bag->merge($two->errors());
|
|
||||||
return $bag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Connect budget, category and piggy bank:
|
|
||||||
*/
|
|
||||||
if (isset($budget) && !is_null($budget)) {
|
|
||||||
$journal->budgets()->save($budget);
|
|
||||||
}
|
|
||||||
if (!is_null($category)) {
|
|
||||||
$journal->categories()->save($category);
|
|
||||||
}
|
|
||||||
$journal->completed = true;
|
|
||||||
$journal->save();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Trigger recurring transaction event.
|
|
||||||
*/
|
|
||||||
\Event::fire('journals.store',[$journal]);
|
|
||||||
|
|
||||||
if (isset($data['return_journal']) && $data['return_journal'] == true) {
|
|
||||||
return ['journal' => $journal, 'messagebag' => $journal->errors()];
|
|
||||||
}
|
|
||||||
return $journal->errors();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Controllers;
|
|
||||||
use Illuminate\Support\MessageBag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface TransactionInterface
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Controllers
|
|
||||||
*/
|
|
||||||
interface TransactionInterface {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a full transaction journal and associated stuff
|
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return MessageBag|\TransactionJournal
|
|
||||||
*/
|
|
||||||
public function store(array $data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns messages about the validation.
|
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function validate(array $data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \TransactionJournal $journal
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return MessageBag|\TransactionJournal
|
|
||||||
*/
|
|
||||||
public function update(\TransactionJournal $journal, array $data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrule the user used when the class is created.
|
|
||||||
*
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function overruleUser(\User $user);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Firefly\Helper\Email;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EmailHelper
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Email
|
|
||||||
*/
|
|
||||||
class EmailHelper implements EmailHelperInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed|void
|
|
||||||
*/
|
|
||||||
public function sendVerificationMail(\User $user)
|
|
||||||
{
|
|
||||||
|
|
||||||
$reset = \Str::random(32);
|
|
||||||
$user->reset = $reset;
|
|
||||||
$user->forceSave();
|
|
||||||
$email = $user->email;
|
|
||||||
$data = ['reset' => $reset];
|
|
||||||
|
|
||||||
\Mail::send(
|
|
||||||
['emails.user.verify-html', 'emails.user.verify-text'], $data, function ($message) use ($email) {
|
|
||||||
$message->to($email, $email)->subject('Verify your e-mail address.');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed|void
|
|
||||||
*/
|
|
||||||
public function sendPasswordMail(\User $user)
|
|
||||||
{
|
|
||||||
|
|
||||||
$password = \Str::random(12);
|
|
||||||
$user->password = $password;
|
|
||||||
$user->reset = \Str::random(32); // new one.
|
|
||||||
$user->forceSave();
|
|
||||||
$email = $user->email;
|
|
||||||
|
|
||||||
|
|
||||||
$data = ['password' => $password];
|
|
||||||
\Mail::send(
|
|
||||||
['emails.user.register-html', 'emails.user.register-text'], $data, function ($message) use ($email) {
|
|
||||||
$message->to($email, $email)->subject('Welcome to Firefly!');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed|void
|
|
||||||
*/
|
|
||||||
public function sendResetVerification(\User $user)
|
|
||||||
{
|
|
||||||
$reset = \Str::random(32);
|
|
||||||
$user->reset = $reset;
|
|
||||||
$user->forceSave();
|
|
||||||
$email = $user->email;
|
|
||||||
|
|
||||||
$data = ['reset' => $reset];
|
|
||||||
\Mail::send(
|
|
||||||
['emails.user.remindme-html', 'emails.user.remindme-text'], $data, function ($message) use ($email) {
|
|
||||||
$message->to($email, $email)->subject('Forgot your password?');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Firefly\Helper\Email;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface EmailHelperInterface
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper\Email
|
|
||||||
*/
|
|
||||||
interface EmailHelperInterface
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function sendVerificationMail(\User $user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function sendPasswordMail(\User $user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function sendResetVerification(\User $user);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Firefly\Helper;
|
|
||||||
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class HelperServiceProvider
|
|
||||||
*
|
|
||||||
* @package Firefly\Helper
|
|
||||||
*/
|
|
||||||
class HelperServiceProvider extends ServiceProvider
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered automatically by Laravel
|
|
||||||
*/
|
|
||||||
public function register()
|
|
||||||
{
|
|
||||||
// controllers:
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Controllers\AccountInterface',
|
|
||||||
'Firefly\Helper\Controllers\Account'
|
|
||||||
);
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Controllers\ChartInterface',
|
|
||||||
'Firefly\Helper\Controllers\Chart'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Controllers\JsonInterface',
|
|
||||||
'Firefly\Helper\Controllers\Json'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Controllers\RecurringInterface',
|
|
||||||
'Firefly\Helper\Controllers\Recurring'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Controllers\SearchInterface',
|
|
||||||
'Firefly\Helper\Controllers\Search'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Controllers\TransactionInterface',
|
|
||||||
'Firefly\Helper\Controllers\Transaction'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Controllers\CategoryInterface',
|
|
||||||
'Firefly\Helper\Controllers\Category'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Controllers\BudgetInterface',
|
|
||||||
'Firefly\Helper\Controllers\Budget'
|
|
||||||
);
|
|
||||||
|
|
||||||
// mail:
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Email\EmailHelperInterface',
|
|
||||||
'Firefly\Helper\Email\EmailHelper'
|
|
||||||
);
|
|
||||||
|
|
||||||
// settings:
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Preferences\PreferencesHelperInterface',
|
|
||||||
'Firefly\Helper\Preferences\PreferencesHelper'
|
|
||||||
);
|
|
||||||
// settings:
|
|
||||||
$this->app->bind(
|
|
||||||
'Firefly\Helper\Toolkit\ToolkitInterface',
|
|
||||||
'Firefly\Helper\Toolkit\Toolkit'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user