mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-23 19:51:24 +00:00
Compare commits
85 Commits
5.3.0-beta
...
5.3.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
106f097b45 | ||
|
|
fafb7f5e49 | ||
|
|
e54c08e2d3 | ||
|
|
03a63d0119 | ||
|
|
e2b698f166 | ||
|
|
f14ac5928f | ||
|
|
cd65d4d4c5 | ||
|
|
7aa3cd5ba4 | ||
|
|
0fe17d5458 | ||
|
|
aaa3cc3d19 | ||
|
|
c80d1d3402 | ||
|
|
254b004587 | ||
|
|
d813d0b7c2 | ||
|
|
53909fdd8a | ||
|
|
0ba03be9a3 | ||
|
|
7aac446cf2 | ||
|
|
f2dcb108e8 | ||
|
|
c0e5d6dd68 | ||
|
|
0b966ed541 | ||
|
|
8219b51e47 | ||
|
|
9b102d1cf4 | ||
|
|
ac607483aa | ||
|
|
3ef46a59e9 | ||
|
|
5529fa7124 | ||
|
|
7a30bc4ff6 | ||
|
|
8a9f6b1896 | ||
|
|
da77bcde04 | ||
|
|
c4979bdd27 | ||
|
|
0c9a25a073 | ||
|
|
e24c2491a6 | ||
|
|
72a2718a93 | ||
|
|
54d92f5b39 | ||
|
|
86600d4fcf | ||
|
|
5cfe02edf6 | ||
|
|
22cb9dfbe0 | ||
|
|
3782388e45 | ||
|
|
5821256590 | ||
|
|
14e06bfedd | ||
|
|
886475740a | ||
|
|
32e0a5bd80 | ||
|
|
26d19fab32 | ||
|
|
4271dc1638 | ||
|
|
a56cefda7d | ||
|
|
4d4d91bf84 | ||
|
|
54dfb35007 | ||
|
|
3893f59773 | ||
|
|
7d8786a620 | ||
|
|
f48bc8d299 | ||
|
|
d33c87c565 | ||
|
|
5a28479788 | ||
|
|
fabd7b1bfd | ||
|
|
e57cd13145 | ||
|
|
515ee0a503 | ||
|
|
cacbef4f75 | ||
|
|
2772275e62 | ||
|
|
34fd66c835 | ||
|
|
45f5a38512 | ||
|
|
6874d6469d | ||
|
|
979c1ad305 | ||
|
|
80de6c78dc | ||
|
|
5009cb5d55 | ||
|
|
0c90171a49 | ||
|
|
d282cb4e34 | ||
|
|
976f79b5a6 | ||
|
|
6693a5166f | ||
|
|
7b9906d493 | ||
|
|
f927e61b37 | ||
|
|
430b498caf | ||
|
|
983508e291 | ||
|
|
104a2379f3 | ||
|
|
e337bcf8bd | ||
|
|
029774687c | ||
|
|
be58545999 | ||
|
|
d774b4e2e3 | ||
|
|
cb65999124 | ||
|
|
77e7af75dc | ||
|
|
714184867c | ||
|
|
fad2331d80 | ||
|
|
bb5de8bf7e | ||
|
|
6f78c96cee | ||
|
|
883342b2c8 | ||
|
|
6232858b85 | ||
|
|
4e4b44d41d | ||
|
|
daf74e11ed | ||
|
|
3e2c2e6395 |
@@ -17,7 +17,7 @@ APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
#
|
||||
# Firefly III will launch using this language (for new users and unauthenticated visitors)
|
||||
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/master/resources/lang
|
||||
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang
|
||||
#
|
||||
# If text is still in English, remember that not everything may have been translated.
|
||||
DEFAULT_LANGUAGE=en_US
|
||||
@@ -57,7 +57,9 @@ APP_LOG_LEVEL=notice
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq
|
||||
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||
# Use "pgsql" for PostgreSQL and MariaDB. Use "sqlite" for SQLite.
|
||||
# Use "pgsql" for PostgreSQL
|
||||
# Use "mysql" for MySQL and MariaDB.
|
||||
# Use "sqlite" for SQLite.
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=fireflyiiidb
|
||||
DB_PORT=3306
|
||||
|
||||
2
.github/contributing.md
vendored
2
.github/contributing.md
vendored
@@ -8,7 +8,7 @@ I am always interested in expanding Firefly III's many features. Just open a tic
|
||||
|
||||
## Pull requests
|
||||
|
||||
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `master` branch.
|
||||
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `main` branch.
|
||||
|
||||
## Translations :us: :fr: :de:
|
||||
|
||||
|
||||
26
.github/dependabot.yml
vendored
Normal file
26
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
# composer updates
|
||||
- package-ecosystem: "composer"
|
||||
directory: "/" # Location of package manifests
|
||||
target-branch: develop
|
||||
labels: bug
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
# yarn / JS updates
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
target-branch: develop
|
||||
labels: bug
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
# yarn / JS updates for new frontend
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/frontend"
|
||||
target-branch: develop
|
||||
labels: bug
|
||||
schedule:
|
||||
interval: "daily"
|
||||
5
.github/pull_request_template.md
vendored
5
.github/pull_request_template.md
vendored
@@ -1,8 +1,9 @@
|
||||
<!--
|
||||
Before you create a new PR, please consider the following two considerations.
|
||||
Before you create a new PR, please consider:
|
||||
|
||||
1) Pull request for the MASTER branch will be closed.
|
||||
1) Pull requests for the MAIN branch will be closed.
|
||||
2) We cannot accept pull requests to add new currencies.
|
||||
3) DO NOT include translations in your PR. Only English US sentences.
|
||||
|
||||
Thanks.
|
||||
-->
|
||||
|
||||
50
.github/security.md
vendored
50
.github/security.md
vendored
@@ -1,12 +1,54 @@
|
||||
# Security Policy
|
||||
|
||||
Firefly III is an application to manage your personal finances. As such, the developer has adopted this security disclosure and response policy to ensure that critical issues are responsibly handled.
|
||||
|
||||
## Supported Versions
|
||||
Only the latest Firefly III release is maintained. Applicable fixes, including security fixes, will not backported to older release branches. Please refer to [releases.md](https://github.com/firefly-iii/firefly-iii/blob/main/releases.md) for details.
|
||||
|
||||
Only the latest version of Firefly III is supported. If you're not running the latest version of Firefly III, please upgrade at your earliest convenience.
|
||||
## Reporting a Vulnerability - Private Disclosure Process
|
||||
Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to Firefly III privately, to minimize attacks against current users of Firefly III before they are fixed. Vulnerabilities will be investigated and patched on the next patch (or minor) release as soon as possible. This information could be kept entirely internal to the project.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
If you know of a publicly disclosed security vulnerability for Firefly III, please **IMMEDIATELY** contact james@firefly-iii.org to inform the Firefly III developer. You can use my [GPG key](https://keybase.io/jc5) for extra security.
|
||||
|
||||
If you find something that compromises the security of Firefly III, you should [send me a message](mailto:james@firefly-iii.org) as soon as possible. These issues will be fixed immediately. You can also open an issue, but if you feel the issue is sensitive, please drop me a message instead.
|
||||
**IMPORTANT: Do not file public issues on GitHub for security vulnerabilities**
|
||||
|
||||
You can use my [GPG key](https://keybase.io/jc5) for extra security. My [GitHub commits](https://github.com/firefly-iii/firefly-iii/commits/master) are almost always signed with this key.
|
||||
To report a vulnerability or a security-related issue, please email the private address james@firefly-iii.org with the details of the vulnerability. The email will be received by the developer of Firefly III. Emails will be addressed within 3 business days, including a detailed plan to investigate the issue and any potential workarounds to perform in the meantime. Do not report non-security-impacting bugs through this channel. Use [GitHub issues](https://github.com/firefly-iii/firefly-iii/issues/new/choose) instead.
|
||||
|
||||
### Proposed Email Content
|
||||
Provide a descriptive subject line and in the body of the email include the following information:
|
||||
* Basic identity information, such as your name and your affiliation or company.
|
||||
* Detailed steps to reproduce the vulnerability (POC scripts, screenshots, and compressed packet captures are all helpful to us).
|
||||
* Description of the effects of the vulnerability on Firefly III and the related hardware and software configurations, so that the developer can reproduce it.
|
||||
* How the vulnerability affects Firefly III usage and an estimation of the attack surface, if there is one.
|
||||
* List other projects or dependencies that were used in conjunction with Firefly III to produce the vulnerability.
|
||||
|
||||
## When to report a vulnerability
|
||||
* When you think Firefly III has a potential security vulnerability.
|
||||
* When you suspect a potential vulnerability but you are unsure that it impacts Firefly III.
|
||||
* When you know of or suspect a potential vulnerability on another project that is used by Firefly III. For example Firefly III has a dependency on Docker, MySQL, etc.
|
||||
|
||||
## Patch, Release, and Disclosure
|
||||
The Firefly III developer will respond to vulnerability reports as follows:
|
||||
|
||||
1. The developer will investigate the vulnerability and determine its effects and criticality.
|
||||
2. If the issue is not deemed to be a vulnerability, the developer will follow up with a detailed reason for rejection.
|
||||
3. The developer will initiate a conversation with the reporter within 3 business days.
|
||||
4. If a vulnerability is acknowledged and the timeline for a fix is determined, the developer will work on a plan to communicate with the appropriate community, including identifying mitigating steps that affected users can take to protect themselves until the fix is rolled out.
|
||||
5. The developer will also create a [CVSS](https://www.first.org/cvss/specification-document) using the [CVSS Calculator](https://www.first.org/cvss/calculator/3.0). The developer makes the final call on the calculated CVSS; it is better to move quickly than making the CVSS perfect. Issues may also be reported to [Mitre](https://cve.mitre.org/) using this [scoring calculator](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator). The CVE will initially be set to private.
|
||||
6. The developer will work on fixing the vulnerability and perform internal testing before preparing to roll out the fix.
|
||||
7. A public disclosure date is negotiated by the Firefly III developer and the bug submitter. We prefer to fully disclose the bug as soon as possible once a user mitigation or patch is available. It is reasonable to delay disclosure when the bug or the fix is not yet fully understood, the solution is not well-tested, or for distributor coordination. The timeframe for disclosure is from immediate (especially if it’s already publicly known) to a few weeks. For a critical vulnerability with a straightforward mitigation, we expect report date to public disclosure date to be on the order of 14 business days. The Firefly III developer holds the final say when setting a public disclosure date.
|
||||
9. Once the fix is confirmed, the developer will patch the vulnerability in the next patch or minor release. Upon release of the patched version of Firefly III, we will follow the **Public Disclosure Process**.
|
||||
|
||||
### Public Disclosure Process
|
||||
The developer publishes a public [advisory](https://github.com/firefly-iii/firefly-iii/security/advisories) to the Firefly III community via GitHub. In most cases, additional communication via Twitter, reddit and other channels will assist in educating Firefly III users and rolling out the patched release to affected users.
|
||||
|
||||
The develop will also publish any mitigating steps users can take until the fix can be applied to their Firefly III instances.
|
||||
|
||||
## Confidentiality, integrity and availability
|
||||
We consider vulnerabilities leading to the compromise of data confidentiality, elevation of privilege, or integrity to be our highest priority concerns. Availability, in particular in areas relating to DoS and resource exhaustion, is also a serious security concern. The Firefly III developer takes all vulnerabilities, potential vulnerabilities, and suspected vulnerabilities seriously and will investigate them in an urgent and expeditious manner.
|
||||
|
||||
Note that we do not currently consider the default settings for Firefly III to be secure-by-default. It is necessary for operators to explicitly configure settings, role based access control, and other resource related features in Firefly III to provide a hardened Firefly III environment. We will not act on any security disclosure that relates to a lack of safe defaults. Over time, we will work towards improved safe-by-default configuration, taking into account backwards compatibility.
|
||||
|
||||
## Credits
|
||||
|
||||
This security policy is based on [Harbor](https://github.com/goharbor/harbor)'s security policy.
|
||||
|
||||
6
app.json
6
app.json
@@ -3,7 +3,7 @@
|
||||
"description": "A free and open source personal finances manager",
|
||||
"repository": "https://github.com/firefly-iii/firefly-iii",
|
||||
"website": "https://firefly-iii.org/",
|
||||
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/master/public/mstile-150x150.png",
|
||||
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/public/mstile-150x150.png",
|
||||
"keywords": [
|
||||
"finance",
|
||||
"finances",
|
||||
@@ -41,7 +41,7 @@
|
||||
{
|
||||
"plan": "heroku-postgresql",
|
||||
"options": {
|
||||
"version": "9.5"
|
||||
"version": "12"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -58,7 +58,7 @@
|
||||
],
|
||||
"env": {
|
||||
"APP_KEY": {
|
||||
"description": "This key is used to encrypt your data.",
|
||||
"description": "This key is used to create app cookies en secure attachments.",
|
||||
"value": "base64:If1gJN4pyycXTq+WS5TjneDympKuu+8SKvTl6RZnhJg="
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,8 @@ use Illuminate\Http\JsonResponse;
|
||||
class AccountController extends Controller
|
||||
{
|
||||
use ApiSupport;
|
||||
/** @var CurrencyRepositoryInterface */
|
||||
private $currencyRepository;
|
||||
/** @var AccountRepositoryInterface */
|
||||
private $repository;
|
||||
private CurrencyRepositoryInterface $currencyRepository;
|
||||
private AccountRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
@@ -196,6 +194,8 @@ class AccountController extends Controller
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'start_date' => $start->format('Y-m-d'),
|
||||
'end_date' => $end->format('Y-m-d'),
|
||||
'type' => 'line', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [],
|
||||
|
||||
298
app/Api/V1/Controllers/Chart/BudgetController.php
Normal file
298
app/Api/V1/Controllers/Chart/BudgetController.php
Normal file
@@ -0,0 +1,298 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\DateRequest;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class BudgetController
|
||||
*/
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
private BudgetLimitRepositoryInterface $blRepository;
|
||||
private OperationsRepositoryInterface $opsRepository;
|
||||
private BudgetRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* BudgetController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
//$this->generator = app(GeneratorInterface::class);
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
|
||||
//$this->nbRepository = app(NoBudgetRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* [
|
||||
* 'label' => 'label for entire set'
|
||||
* 'currency_id' => 0,
|
||||
* 'currency_code' => 'EUR',
|
||||
* 'currency_symbol' => '$',
|
||||
* 'currency_decimal_places' => 2,
|
||||
* 'type' => 'bar', // line, area or bar
|
||||
* 'yAxisID' => 0, // 0, 1, 2
|
||||
* 'entries' => ['a' => 1, 'b' => 4],
|
||||
* ],
|
||||
*
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
{
|
||||
$dates = $request->getAll();
|
||||
$budgets = $this->repository->getActiveBudgets();
|
||||
$budgetNames = [];
|
||||
$currencyNames = [];
|
||||
$sets = [];
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
$expenses = $this->getExpenses($budget, $dates['start'], $dates['end']);
|
||||
$expenses = $this->filterNulls($expenses);
|
||||
foreach ($expenses as $set) {
|
||||
$budgetNames[] = $set['budget_name'];
|
||||
$currencyNames[] = $set['currency_name'];
|
||||
$sets[] = $set;
|
||||
}
|
||||
}
|
||||
$budgetNames = array_unique($budgetNames);
|
||||
$currencyNames = array_unique($currencyNames);
|
||||
$basic = $this->createSets($budgetNames, $currencyNames);
|
||||
$filled = $this->fillSets($basic, $sets);
|
||||
$keys = array_values($filled);
|
||||
|
||||
return response()->json($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $limits
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getExpenses(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
|
||||
if (0 === $limits->count()) {
|
||||
return $this->getExpenseInRange($budget, $start, $end);
|
||||
}
|
||||
$arr = [];
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
$arr[] = $this->getExpensesForLimit($limit);
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $budgetNames
|
||||
* @param array $currencyNames
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function createSets(array $budgetNames, array $currencyNames): array
|
||||
{
|
||||
$return = [];
|
||||
foreach ($currencyNames as $currencyName) {
|
||||
$entries = [];
|
||||
foreach ($budgetNames as $budgetName) {
|
||||
$label = sprintf('%s (%s)', $budgetName, $currencyName);
|
||||
$entries[$label] = '0';
|
||||
}
|
||||
|
||||
// left
|
||||
$return['left'] = [
|
||||
'label' => sprintf('%s (%s)', trans('firefly.left'), $currencyName),
|
||||
'data_type' => 'left',
|
||||
'currency_name' => $currencyName,
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $entries,
|
||||
];
|
||||
|
||||
// spent_capped
|
||||
$return['spent_capped'] = [
|
||||
'label' => sprintf('%s (%s)', trans('firefly.spent'), $currencyName),
|
||||
'data_type' => 'spent_capped',
|
||||
'currency_name' => $currencyName,
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $entries,
|
||||
];
|
||||
|
||||
// overspent
|
||||
$return['overspent'] = [
|
||||
'label' => sprintf('%s (%s)', trans('firefly.overspent'), $currencyName),
|
||||
'data_type' => 'overspent',
|
||||
'currency_name' => $currencyName,
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $entries,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $basic
|
||||
* @param array $sets
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function fillSets(array $basic, array $sets): array
|
||||
{
|
||||
foreach ($sets as $set) {
|
||||
$label = $set['label'];
|
||||
//$basic['spent']['entries'][$label] = $set['entries']['spent'];
|
||||
$basic['spent_capped']['entries'][$label] = $set['entries']['spent_capped'];
|
||||
$basic['left']['entries'][$label] = $set['entries']['left'];
|
||||
$basic['overspent']['entries'][$label] = $set['entries']['overspent'];
|
||||
}
|
||||
|
||||
return $basic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $expenses
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function filterNulls(array $expenses): array
|
||||
{
|
||||
$return = [];
|
||||
/** @var array|null $arr */
|
||||
foreach ($expenses as $arr) {
|
||||
if (null !== $arr) {
|
||||
$return[] = $arr;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getExpenseInRange(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$budget]), null);
|
||||
$return = [];
|
||||
/** @var array $set */
|
||||
foreach ($spent as $set) {
|
||||
$current = [
|
||||
'label' => sprintf('%s (%s)', $budget->name, $set['currency_name']),
|
||||
'budget_name' => $budget->name,
|
||||
'start_date' => $start->format('Y-m-d'),
|
||||
'end_date' => $end->format('Y-m-d'),
|
||||
'currency_id' => (int) $set['currency_id'],
|
||||
'currency_code' => $set['currency_code'],
|
||||
'currency_name' => $set['currency_name'],
|
||||
'currency_symbol' => $set['currency_symbol'],
|
||||
'currency_decimal_places' => (int) $set['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar,
|
||||
'entries' => [],
|
||||
];
|
||||
$sumSpent = bcmul($set['sum'], '-1'); // spent
|
||||
$current['entries']['spent'] = $sumSpent;
|
||||
$current['entries']['amount'] = '0';
|
||||
$current['entries']['spent_capped'] = $sumSpent;
|
||||
$current['entries']['left'] = '0';
|
||||
$current['entries']['overspent'] = '0';
|
||||
$return[] = $current;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BudgetLimit $limit
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function getExpensesForLimit(BudgetLimit $limit): ?array
|
||||
{
|
||||
$budget = $limit->budget;
|
||||
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $limit->transactionCurrency);
|
||||
$currency = $limit->transactionCurrency;
|
||||
// when limited to a currency, the count is always one. Or it's empty.
|
||||
$set = array_shift($spent);
|
||||
if (null === $set) {
|
||||
return null;
|
||||
}
|
||||
$return = [
|
||||
'label' => sprintf('%s (%s)', $budget->name, $set['currency_name']),
|
||||
'budget_name' => $budget->name,
|
||||
'start_date' => $limit->start_date->format('Y-m-d'),
|
||||
'end_date' => $limit->end_date->format('Y-m-d'),
|
||||
'currency_id' => (int) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => (int) $currency->decimal_places,
|
||||
'type' => 'bar', // line, area or bar,
|
||||
'entries' => [],
|
||||
];
|
||||
$sumSpent = bcmul($set['sum'], '-1'); // spent
|
||||
$return['entries']['spent'] = $sumSpent;
|
||||
$return['entries']['amount'] = $limit->amount;
|
||||
$return['entries']['spent_capped'] = 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent;
|
||||
$return['entries']['left'] = 1 === bccomp($limit->amount, $sumSpent) ? bcadd($set['sum'], $limit->amount) : '0'; // left
|
||||
$return['entries']['overspent'] = 1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($set['sum'], $limit->amount), '-1'); // overspent
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -74,8 +74,6 @@ class CategoryController extends Controller
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*
|
||||
* TODO after 4.8,0, simplify
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
{
|
||||
@@ -89,32 +87,15 @@ class CategoryController extends Controller
|
||||
|
||||
$tempData = [];
|
||||
$spentWith = $this->opsRepository->listExpenses($start, $end);
|
||||
$earnedWith = $this->opsRepository->listIncome($start, $end);
|
||||
$spentWithout = $this->noCatRepository->listExpenses($start, $end);
|
||||
$earnedWithout = $this->noCatRepository->listIncome($start, $end);
|
||||
$categories = [];
|
||||
|
||||
|
||||
foreach ([$spentWith, $earnedWith, $spentWithout, $earnedWithout] as $set) {
|
||||
foreach ([$spentWith, $spentWithout,] as $set) {
|
||||
foreach ($set as $currency) {
|
||||
foreach ($currency['categories'] as $category) {
|
||||
$categories[] = $category['name'];
|
||||
$inKey = sprintf('%d-i', $currency['currency_id']);
|
||||
$outKey = sprintf('%d-e', $currency['currency_id']);
|
||||
// make data arrays if not yet present.
|
||||
$tempData[$inKey] = $tempData[$inKey] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'currency_code' => $currency['currency_code'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [
|
||||
// per category:
|
||||
// "category" => 5,
|
||||
],
|
||||
];
|
||||
$tempData[$outKey] = $tempData[$outKey] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
|
||||
@@ -123,16 +104,12 @@ class CategoryController extends Controller
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [
|
||||
// per category:
|
||||
// "category" => 5,
|
||||
],
|
||||
'entries' => [],
|
||||
];
|
||||
|
||||
foreach ($category['transaction_journals'] as $journal) {
|
||||
// is it expense or income?
|
||||
$letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
|
||||
$currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
|
||||
$currentKey = sprintf('%d-%s', $currency['currency_id'], 'e');
|
||||
$name = $category['name'];
|
||||
$tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
|
||||
$tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
|
||||
|
||||
278
app/Api/V1/Controllers/Data/DestroyController.php
Normal file
278
app/Api/V1/Controllers/Data/DestroyController.php
Normal file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
/**
|
||||
* DestroyController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Data;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\DataDestroyRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
|
||||
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class DestroyController
|
||||
*/
|
||||
class DestroyController extends Controller
|
||||
{
|
||||
/**
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function destroy(DataDestroyRequest $request): JsonResponse
|
||||
{
|
||||
$objects = $request->getObjects();
|
||||
|
||||
switch ($objects) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('This endpoint can\'t handle object "%s"', $objects));
|
||||
case 'budgets':
|
||||
$this->destroyBudgets();
|
||||
break;
|
||||
case 'bills':
|
||||
$this->destroyBills();
|
||||
break;
|
||||
case 'piggy_banks':
|
||||
$this->destroyPiggyBanks();
|
||||
break;
|
||||
case 'rules':
|
||||
$this->destroyRules();
|
||||
break;
|
||||
case 'recurring':
|
||||
$this->destroyRecurringTransactions();
|
||||
break;
|
||||
case 'categories':
|
||||
$this->destroyCategories();
|
||||
break;
|
||||
case 'tags':
|
||||
$this->destroyTags();
|
||||
break;
|
||||
case 'object_groups':
|
||||
$this->destroyObjectGroups();
|
||||
break;
|
||||
case 'accounts':
|
||||
$this->destroyAccounts(
|
||||
[
|
||||
AccountType::ASSET, AccountType::DEFAULT,
|
||||
AccountType::BENEFICIARY, AccountType::EXPENSE,
|
||||
AccountType::REVENUE, AccountType::INITIAL_BALANCE,
|
||||
AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'asset_accounts':
|
||||
$this->destroyAccounts(
|
||||
[
|
||||
AccountType::ASSET, AccountType::DEFAULT,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'expense_accounts':
|
||||
$this->destroyAccounts(
|
||||
[
|
||||
AccountType::BENEFICIARY, AccountType::EXPENSE,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'revenue_accounts':
|
||||
$this->destroyAccounts(
|
||||
[
|
||||
AccountType::REVENUE,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'liabilities':
|
||||
$this->destroyAccounts(
|
||||
[
|
||||
AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'transactions':
|
||||
$this->destroyTransactions(
|
||||
[
|
||||
TransactionType::WITHDRAWAL,
|
||||
TransactionType::DEPOSIT,
|
||||
TransactionType::TRANSFER,
|
||||
TransactionType::RECONCILIATION,
|
||||
TransactionType::OPENING_BALANCE,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'withdrawals':
|
||||
$this->destroyTransactions(
|
||||
[
|
||||
TransactionType::WITHDRAWAL,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'deposits':
|
||||
$this->destroyTransactions(
|
||||
[
|
||||
TransactionType::DEPOSIT,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'transfers':
|
||||
$this->destroyTransactions(
|
||||
[
|
||||
TransactionType::TRANSFER,
|
||||
]
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
*/
|
||||
private function destroyAccounts(array $types): void
|
||||
{
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$collection = $repository->getAccountsByType($types);
|
||||
$service = app(AccountDestroyService::class);
|
||||
/** @var Account $account */
|
||||
foreach ($collection as $account) {
|
||||
$service->destroy($account, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyBills(): void
|
||||
{
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyBudgets(): void
|
||||
{
|
||||
/** @var AvailableBudgetRepositoryInterface $abRepository */
|
||||
$abRepository = app(AvailableBudgetRepositoryInterface::class);
|
||||
$abRepository->destroyAll();
|
||||
|
||||
/** @var BudgetLimitRepositoryInterface $blRepository */
|
||||
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$blRepository->destroyAll();
|
||||
|
||||
/** @var BudgetRepositoryInterface $budgetRepository */
|
||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$budgetRepository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyCategories(): void
|
||||
{
|
||||
/** @var CategoryRepositoryInterface $categoryRepos */
|
||||
$categoryRepos = app(CategoryRepositoryInterface::class);
|
||||
$categoryRepos->destroyAll();
|
||||
}
|
||||
|
||||
private function destroyObjectGroups(): void
|
||||
{
|
||||
/** @var ObjectGroupRepositoryInterface $repository */
|
||||
$repository = app(ObjectGroupRepositoryInterface::class);
|
||||
$repository->deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyPiggyBanks(): void
|
||||
{
|
||||
/** @var PiggyBankRepositoryInterface $repository */
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyRecurringTransactions(): void
|
||||
{
|
||||
/** @var RecurringRepositoryInterface $repository */
|
||||
$repository = app(RecurringRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyRules(): void
|
||||
{
|
||||
/** @var RuleGroupRepositoryInterface $repository */
|
||||
$repository = app(RuleGroupRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyTags(): void
|
||||
{
|
||||
/** @var TagRepositoryInterface $tagRepository */
|
||||
$tagRepository = app(TagRepositoryInterface::class);
|
||||
$tagRepository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
*/
|
||||
private function destroyTransactions(array $types): void
|
||||
{
|
||||
/** @var JournalRepositoryInterface $repository */
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$journals = $repository->findByType($types);
|
||||
$service = app(JournalDestroyService::class);
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach($journals as $journal) {
|
||||
$service->destroy($journal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -241,7 +241,6 @@ class PiggyBankController extends Controller
|
||||
$this->repository->setCurrentAmount($piggyBank, $data['current_amount']);
|
||||
}
|
||||
|
||||
|
||||
$manager = $this->getManager();
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AccountController.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Search;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
@@ -41,8 +43,7 @@ class AccountController extends Controller
|
||||
{
|
||||
use AccountFilter;
|
||||
|
||||
/** @var array */
|
||||
private $validFields;
|
||||
private array $validFields;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionController.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,45 +20,51 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Search;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Support\Search\SearchInterface;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection;
|
||||
|
||||
/**
|
||||
* Class TransactionController
|
||||
*/
|
||||
class TransactionController extends Controller
|
||||
{
|
||||
/** @var string */
|
||||
public const SEARCH_ALL = 'all';
|
||||
/** @var string */
|
||||
public const SEARCH_DESCRIPTION = 'description';
|
||||
/** @var string */
|
||||
public const SEARCH_NOTES = 'notes';
|
||||
/** @var string */
|
||||
public const SEARCH_ACCOUNTS = 'accounts';
|
||||
/** @var array */
|
||||
private $validFields;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->validFields = [
|
||||
self::SEARCH_ALL,
|
||||
self::SEARCH_DESCRIPTION,
|
||||
self::SEARCH_NOTES,
|
||||
self::SEARCH_ACCOUNTS,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param SearchInterface $searcher
|
||||
*
|
||||
* @return void
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function search(Request $request): void
|
||||
public function search(Request $request, SearchInterface $searcher): JsonResponse
|
||||
{
|
||||
die('the route is present but nobody\'s home.');
|
||||
$manager = $this->getManager();
|
||||
$fullQuery = (string) $request->get('query');
|
||||
$page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page');
|
||||
|
||||
$searcher->parseQuery($fullQuery);
|
||||
$searcher->setPage($page);
|
||||
$searcher->setLimit((int) config('firefly.search_result_limit'));
|
||||
$groups = $searcher->searchTransactions();
|
||||
$parameters = ['search' => $fullQuery];
|
||||
$url = route('api.v1.search.transactions') . '?' . http_build_query($parameters);
|
||||
$groups->setPath($url);
|
||||
$transactions = $groups->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Collection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($groups));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* TransferController.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Search;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Search\TransferRequest;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Support\Search\TransferSearch;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
|
||||
/**
|
||||
* Class TransferController
|
||||
*/
|
||||
class TransferController extends Controller
|
||||
{
|
||||
/**
|
||||
* @param TransferRequest $request
|
||||
*
|
||||
* @return JsonResponse|Response
|
||||
*/
|
||||
public function search(TransferRequest $request)
|
||||
{
|
||||
// configure transfer search to search for a > b
|
||||
$search = app(TransferSearch::class);
|
||||
$search->setSource($request->get('source'));
|
||||
$search->setDestination($request->get('destination'));
|
||||
$search->setAmount($request->get('amount'));
|
||||
$search->setDescription($request->get('description'));
|
||||
$search->setDate($request->get('date'));
|
||||
|
||||
$left = $search->search();
|
||||
|
||||
// configure transfer search to search for b > a
|
||||
$search->setSource($request->get('destination'));
|
||||
$search->setDestination($request->get('source'));
|
||||
$search->setAmount($request->get('amount'));
|
||||
$search->setDescription($request->get('description'));
|
||||
$search->setDate($request->get('date'));
|
||||
|
||||
$right = $search->search();
|
||||
|
||||
// add parameters to URL:
|
||||
$this->parameters->set('source', $request->get('source'));
|
||||
$this->parameters->set('destination', $request->get('destination'));
|
||||
$this->parameters->set('amount', $request->get('amount'));
|
||||
$this->parameters->set('description', $request->get('description'));
|
||||
$this->parameters->set('date', $request->get('date'));
|
||||
|
||||
// get all journal ID's.
|
||||
$total = $left->merge($right)->unique('id')->pluck('id')->toArray();
|
||||
if (0 === count($total)) {
|
||||
// forces search to be empty.
|
||||
$total = [-1];
|
||||
}
|
||||
|
||||
// collector to return results.
|
||||
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$manager = $this->getManager();
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage(1)
|
||||
->setJournalIds($total);
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.search.transfers') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class AccountStoreRequest extends Request
|
||||
'opening_balance' => $this->string('opening_balance'),
|
||||
'opening_balance_date' => $this->date('opening_balance_date'),
|
||||
'cc_type' => $this->string('credit_card_type'),
|
||||
'cc_Monthly_payment_date' => $this->string('monthly_payment_date'),
|
||||
'cc_monthly_payment_date' => $this->string('monthly_payment_date'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'interest' => $this->string('interest'),
|
||||
'interest_period' => $this->string('interest_period'),
|
||||
|
||||
@@ -75,7 +75,7 @@ class AccountUpdateRequest extends Request
|
||||
'opening_balance' => $this->nullableString('opening_balance'),
|
||||
'opening_balance_date' => $this->date('opening_balance_date'),
|
||||
'cc_type' => $this->nullableString('credit_card_type'),
|
||||
'cc_Monthly_payment_date' => $this->nullableString('monthly_payment_date'),
|
||||
'cc_monthly_payment_date' => $this->nullableString('monthly_payment_date'),
|
||||
'notes' => $this->nullableNlString('notes'),
|
||||
'interest' => $this->nullableString('interest'),
|
||||
'interest_period' => $this->nullableString('interest_period'),
|
||||
|
||||
@@ -67,7 +67,7 @@ class AvailableBudgetRequest extends Request
|
||||
return [
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'amount' => 'required|numeric|more:0',
|
||||
'amount' => 'required|numeric|gt:0',
|
||||
'start' => 'required|date|before:end',
|
||||
'end' => 'required|date|after:start',
|
||||
];
|
||||
|
||||
@@ -70,6 +70,7 @@ class BillRequest extends Request
|
||||
'repeat_freq' => $this->string('repeat_freq'),
|
||||
'skip' => $this->integer('skip'),
|
||||
'active' => $active,
|
||||
'order' => $this->integer('order'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
];
|
||||
}
|
||||
@@ -83,13 +84,13 @@ class BillRequest extends Request
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
|
||||
'amount_min' => 'required|numeric|more:0',
|
||||
'amount_max' => 'required|numeric|more:0',
|
||||
'name' => 'between:1,255|uniqueObjectForUser:bills,name',
|
||||
'amount_min' => 'numeric|gt:0',
|
||||
'amount_max' => 'numeric|gt:0',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'date' => 'required|date',
|
||||
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
||||
'date' => 'date',
|
||||
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
|
||||
'skip' => 'between:0,31',
|
||||
'active' => [new IsBoolean],
|
||||
'notes' => 'between:1,65536',
|
||||
|
||||
@@ -70,7 +70,7 @@ class BudgetLimitRequest extends Request
|
||||
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
|
||||
'start' => 'required|before:end|date',
|
||||
'end' => 'required|after:start|date',
|
||||
'amount' => 'required|more:0',
|
||||
'amount' => 'required|gt:0',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
];
|
||||
|
||||
66
app/Api/V1/Requests/DataDestroyRequest.php
Normal file
66
app/Api/V1/Requests/DataDestroyRequest.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* DataDestroyRequest.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
/**
|
||||
* Class DataDestroyRequest
|
||||
*/
|
||||
class DataDestroyRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check() && !auth()->user()->hasRole('demo');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getObjects(): string
|
||||
{
|
||||
return $this->get('objects') ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups' .
|
||||
',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers';
|
||||
|
||||
return [
|
||||
'objects' => sprintf('min:1|string|in:%s', $valid),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,7 @@ class PiggyBankRequest extends Request
|
||||
'startdate' => $this->date('start_date'),
|
||||
'targetdate' => $this->date('target_date'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'order' => $this->integer('order'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -90,7 +91,7 @@ class PiggyBankRequest extends Request
|
||||
$piggyBank = $this->route()->parameter('piggyBank');
|
||||
$rules['name'] = 'between:1,255|uniquePiggyBankForUser:' . $piggyBank->id;
|
||||
$rules['account_id'] = ['belongsToUser:accounts', new IsAssetAccountId];
|
||||
$rules['target_amount'] = 'numeric|more:0';
|
||||
$rules['target_amount'] = 'numeric|gt:0';
|
||||
$rules['current_amount'] = ['numeric', new ZeroOrMore, new LessThanPiggyTarget];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@ class RecurrenceStoreRequest extends Request
|
||||
'repetitions.*.skip' => 'required|numeric|between:0,31',
|
||||
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
|
||||
'transactions.*.description' => 'required|between:1,255',
|
||||
'transactions.*.amount' => 'required|numeric|more:0',
|
||||
'transactions.*.foreign_amount' => 'numeric|more:0',
|
||||
'transactions.*.amount' => 'required|numeric|gt:0',
|
||||
'transactions.*.foreign_amount' => 'numeric|gt:0',
|
||||
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
|
||||
@@ -107,8 +107,8 @@ class RecurrenceUpdateRequest extends Request
|
||||
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
|
||||
|
||||
'transactions.*.description' => 'required|between:1,255',
|
||||
'transactions.*.amount' => 'required|numeric|more:0',
|
||||
'transactions.*.foreign_amount' => 'numeric|more:0',
|
||||
'transactions.*.amount' => 'required|numeric|gt:0',
|
||||
'transactions.*.foreign_amount' => 'numeric|gt:0',
|
||||
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransferRequest.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Search;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\Request;
|
||||
@@ -49,7 +51,7 @@ class TransferRequest extends Request
|
||||
return [
|
||||
'source' => ['required', new IsTransferAccount],
|
||||
'destination' => ['required', new IsTransferAccount],
|
||||
'amount' => 'required|numeric|more:0',
|
||||
'amount' => 'required|numeric|gt:0',
|
||||
'description' => 'required|min:1',
|
||||
'date' => 'required|date',
|
||||
];
|
||||
|
||||
@@ -98,7 +98,7 @@ class TransactionStoreRequest extends Request
|
||||
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code|nullable',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => 'required|numeric|more:0',
|
||||
'transactions.*.amount' => 'required|numeric|gt:0',
|
||||
'transactions.*.foreign_amount' => 'numeric',
|
||||
|
||||
// description
|
||||
@@ -221,7 +221,7 @@ class TransactionStoreRequest extends Request
|
||||
|
||||
// foreign currency info:
|
||||
'foreign_currency_id' => $this->integerFromValue((string) $object['foreign_currency_id']),
|
||||
'foreign_currency_code' => $this->stringFromValue($object['foreign_currency_code']),
|
||||
'foreign_currency_code' => $this->stringFromValue((string) $object['foreign_currency_code']),
|
||||
|
||||
// amount and foreign amount. Cannot be 0.
|
||||
'amount' => $this->stringFromValue((string) $object['amount']),
|
||||
@@ -232,37 +232,37 @@ class TransactionStoreRequest extends Request
|
||||
|
||||
// source of transaction. If everything is null, assume cash account.
|
||||
'source_id' => $this->integerFromValue((string) $object['source_id']),
|
||||
'source_name' => $this->stringFromValue($object['source_name']),
|
||||
'source_iban' => $this->stringFromValue($object['source_iban']),
|
||||
'source_number' => $this->stringFromValue($object['source_number']),
|
||||
'source_bic' => $this->stringFromValue($object['source_bic']),
|
||||
'source_name' => $this->stringFromValue((string) $object['source_name']),
|
||||
'source_iban' => $this->stringFromValue((string) $object['source_iban']),
|
||||
'source_number' => $this->stringFromValue((string) $object['source_number']),
|
||||
'source_bic' => $this->stringFromValue((string) $object['source_bic']),
|
||||
|
||||
// destination of transaction. If everything is null, assume cash account.
|
||||
'destination_id' => $this->integerFromValue((string) $object['destination_id']),
|
||||
'destination_name' => $this->stringFromValue($object['destination_name']),
|
||||
'destination_iban' => $this->stringFromValue($object['destination_iban']),
|
||||
'destination_number' => $this->stringFromValue($object['destination_number']),
|
||||
'destination_bic' => $this->stringFromValue($object['destination_bic']),
|
||||
'destination_name' => $this->stringFromValue((string) $object['destination_name']),
|
||||
'destination_iban' => $this->stringFromValue((string) $object['destination_iban']),
|
||||
'destination_number' => $this->stringFromValue((string) $object['destination_number']),
|
||||
'destination_bic' => $this->stringFromValue((string) $object['destination_bic']),
|
||||
|
||||
// budget info
|
||||
'budget_id' => $this->integerFromValue((string) $object['budget_id']),
|
||||
'budget_name' => $this->stringFromValue($object['budget_name']),
|
||||
'budget_name' => $this->stringFromValue((string) $object['budget_name']),
|
||||
|
||||
// category info
|
||||
'category_id' => $this->integerFromValue((string) $object['category_id']),
|
||||
'category_name' => $this->stringFromValue($object['category_name']),
|
||||
'category_name' => $this->stringFromValue((string) $object['category_name']),
|
||||
|
||||
// journal bill reference. Optional. Will only work for withdrawals
|
||||
'bill_id' => $this->integerFromValue((string) $object['bill_id']),
|
||||
'bill_name' => $this->stringFromValue($object['bill_name']),
|
||||
'bill_name' => $this->stringFromValue((string) $object['bill_name']),
|
||||
|
||||
// piggy bank reference. Optional. Will only work for transfers
|
||||
'piggy_bank_id' => $this->integerFromValue((string) $object['piggy_bank_id']),
|
||||
'piggy_bank_name' => $this->stringFromValue($object['piggy_bank_name']),
|
||||
'piggy_bank_name' => $this->stringFromValue((string) $object['piggy_bank_name']),
|
||||
|
||||
// some other interesting properties
|
||||
'reconciled' => $this->convertBoolean((string) $object['reconciled']),
|
||||
'notes' => $this->nlStringFromValue($object['notes']),
|
||||
'notes' => $this->nlStringFromValue((string) $object['notes']),
|
||||
'tags' => $this->arrayFromValue($object['tags']),
|
||||
|
||||
// all custom fields:
|
||||
|
||||
@@ -172,7 +172,7 @@ class TransactionUpdateRequest extends Request
|
||||
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => 'numeric|more:0|max:100000000000',
|
||||
'transactions.*.amount' => 'numeric|gt:0|max:100000000000',
|
||||
'transactions.*.foreign_amount' => 'numeric|gte:0',
|
||||
|
||||
// description
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CorrectOpeningBalanceCurrencies.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
81
app/Console/Commands/Correction/FixGroupAccounts.php
Normal file
81
app/Console/Commands/Correction/FixGroupAccounts.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* FixGroupAccounts.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Handlers\Events\UpdatedGroupEventHandler;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class FixGroupAccounts
|
||||
*/
|
||||
class FixGroupAccounts extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Unify the source / destination accounts of split groups.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:unify-group-accounts';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
// select transaction_group_id, count(transaction_group_id) as the_count from transaction_journals group by transaction_group_id having the_count > 1
|
||||
$groups = [];
|
||||
$res = TransactionJournal
|
||||
::groupBy('transaction_group_id')
|
||||
->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')]);
|
||||
foreach ($res as $journal) {
|
||||
if ((int) $journal->the_count > 1) {
|
||||
$groups[] = (int) $journal->transaction_group_id;
|
||||
}
|
||||
}
|
||||
$handler = new UpdatedGroupEventHandler;
|
||||
foreach($groups as $groupId) {
|
||||
$group = TransactionGroup::find($groupId);
|
||||
$event = new UpdatedTransactionGroup($group);
|
||||
$handler->unifyAccounts($event);
|
||||
}
|
||||
|
||||
$this->line('Updated inconsistent transaction groups.');
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* FixLongDescriptions.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* FixRecurringTransactions.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\Recurrence;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
/**
|
||||
* CreateDatabase.php
|
||||
@@ -22,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ExportData.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Export;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* RestoreOAuthKeys.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Integrity;
|
||||
|
||||
use FireflyIII\Support\System\OAuthKeys;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SetLatestVersion.php
|
||||
@@ -21,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* MigrateRecurrenceMeta.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Upgrade;
|
||||
|
||||
use FireflyIII\Models\RecurrenceMeta;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* MigrateTagLocations.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Upgrade;
|
||||
|
||||
use FireflyIII\Models\Location;
|
||||
|
||||
@@ -76,7 +76,7 @@ class UpgradeDatabase extends Command
|
||||
'firefly-iii:migrate-recurrence-meta',
|
||||
'firefly-iii:migrate-tag-locations',
|
||||
|
||||
// there are 16 verify commands.
|
||||
// there are 15 verify commands.
|
||||
'firefly-iii:fix-piggies',
|
||||
'firefly-iii:create-link-types',
|
||||
'firefly-iii:create-access-tokens',
|
||||
@@ -93,6 +93,7 @@ class UpgradeDatabase extends Command
|
||||
'firefly-iii:fix-ob-currencies',
|
||||
'firefly-iii:fix-long-descriptions',
|
||||
'firefly-iii:fix-recurring-transactions',
|
||||
'firefly-iii:unify-group-accounts',
|
||||
|
||||
// two report commands
|
||||
'firefly-iii:report-empty-objects',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* DuplicateTransactionException.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace FireflyIII\Factory;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
||||
use FireflyIII\Services\Internal\Support\BillServiceTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\QueryException;
|
||||
@@ -37,7 +38,7 @@ use Log;
|
||||
*/
|
||||
class BillFactory
|
||||
{
|
||||
use BillServiceTrait;
|
||||
use BillServiceTrait, CreatesObjectGroups;
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
@@ -97,6 +98,24 @@ class BillFactory
|
||||
$this->updateNote($bill, $data['notes']);
|
||||
}
|
||||
|
||||
$objectGroupTitle = $data['object_group'] ?? '';
|
||||
if ('' !== $objectGroupTitle) {
|
||||
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
|
||||
if (null !== $objectGroup) {
|
||||
$bill->objectGroups()->sync([$objectGroup->id]);
|
||||
$bill->save();
|
||||
}
|
||||
}
|
||||
// try also with ID:
|
||||
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
|
||||
if (0 !== $objectGroupId) {
|
||||
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
||||
if (null !== $objectGroup) {
|
||||
$bill->objectGroups()->sync([$objectGroup->id]);
|
||||
$bill->save();
|
||||
}
|
||||
}
|
||||
|
||||
return $bill;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,14 +23,58 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngine;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class UpdatedGroupEventHandler
|
||||
*/
|
||||
class UpdatedGroupEventHandler
|
||||
{
|
||||
/**
|
||||
* This method will make sure all source / destination accounts are the same.
|
||||
*
|
||||
* @param UpdatedTransactionGroup $updatedGroupEvent
|
||||
*/
|
||||
public function unifyAccounts(UpdatedTransactionGroup $updatedGroupEvent): void
|
||||
{
|
||||
$group = $updatedGroupEvent->transactionGroup;
|
||||
if (1 === $group->transactionJournals->count()) {
|
||||
return;
|
||||
}
|
||||
Log::debug(sprintf('Correct inconsistent accounts in group #%d', $group->id));
|
||||
// first journal:
|
||||
/** @var TransactionJournal $first */
|
||||
$first = $group->transactionJournals()
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->orderBy('transaction_journals.description', 'DESC')
|
||||
->first();
|
||||
$all = $group->transactionJournals()->get()->pluck('id')->toArray();
|
||||
/** @var Account $sourceAccount */
|
||||
$sourceAccount = $first->transactions()->where('amount', '<', '0')->first()->account;
|
||||
/** @var Account $destAccount */
|
||||
$destAccount = $first->transactions()->where('amount', '>', '0')->first()->account;
|
||||
|
||||
$type = $first->transactionType->type;
|
||||
if (TransactionType::TRANSFER === $type || TransactionType::WITHDRAWAL === $type) {
|
||||
// set all source transactions to source account:
|
||||
Transaction::whereIn('transaction_journal_id', $all)
|
||||
->where('amount', '<', 0)->update(['account_id' => $sourceAccount->id]);
|
||||
}
|
||||
if (TransactionType::TRANSFER === $type || TransactionType::DEPOSIT === $type) {
|
||||
// set all destination transactions to destination account:
|
||||
Transaction::whereIn('transaction_journal_id', $all)
|
||||
->where('amount', '>', 0)->update(['account_id' => $destAccount->id]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will check all the rules when a journal is updated.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AccountCollection.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collector\Extensions;
|
||||
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AmountCollection.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collector\Extensions;
|
||||
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CollectorProperties.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collector\Extensions;
|
||||
|
||||
use FireflyIII\User;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* MetaCollection.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collector\Extensions;
|
||||
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TimeCollection.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Collector\Extensions;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
@@ -554,9 +554,9 @@ class GroupCollector implements GroupCollectorInterface
|
||||
$result['updated_at'] = new Carbon($result['updated_at'], 'UTC');
|
||||
|
||||
// this is going to happen a lot:
|
||||
$result['date']->setTimezone(env('TZ'));
|
||||
$result['created_at']->setTimezone(env('TZ'));
|
||||
$result['updated_at']->setTimezone(env('TZ'));
|
||||
$result['date']->setTimezone(config('app.timezone'));
|
||||
$result['created_at']->setTimezone(config('app.timezone'));
|
||||
$result['updated_at']->setTimezone(config('app.timezone'));
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ class Help implements HelpInterface
|
||||
*/
|
||||
public function getFromGitHub(string $route, string $language): string
|
||||
{
|
||||
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route);
|
||||
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/main/%s/%s.md', $language, $route);
|
||||
Log::debug(sprintf('Trying to get %s...', $uri));
|
||||
$opt = ['headers' => ['User-Agent' => $this->userAgent]];
|
||||
$content = '';
|
||||
|
||||
@@ -44,7 +44,8 @@ trait UpdateTrait
|
||||
Log::debug('Now in getLatestRelease()');
|
||||
/** @var UpdateRequestInterface $checker */
|
||||
$checker = app(UpdateRequestInterface::class);
|
||||
$channel = app('fireflyconfig')->get('update_channel', 'stable')->data;
|
||||
$channelConfig = app('fireflyconfig')->get('update_channel', 'stable');
|
||||
$channel = $channelConfig ? $channelConfig->data : 'stable';
|
||||
|
||||
return $checker->getUpdateInformation($channel);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ class IndexController extends Controller
|
||||
$account->startBalance = $this->isInArray($startBalances, $account->id);
|
||||
$account->endBalance = $this->isInArray($endBalances, $account->id);
|
||||
$account->difference = bcsub($account->endBalance, $account->startBalance);
|
||||
$account->interest = round($this->repository->getMetaValue($account, 'interest'), 6);
|
||||
$account->interest = number_format((float) $this->repository->getMetaValue($account, 'interest'), 6, '.', '');
|
||||
$account->interestPeriod = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')));
|
||||
$account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type));
|
||||
}
|
||||
@@ -115,6 +115,14 @@ class IndexController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Contracts\Foundation\Application|Factory|View
|
||||
*/
|
||||
public function emptyIndex(?string $objectType = null)
|
||||
{
|
||||
return view('accounts.empty-index', compact('objectType'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show list of accounts.
|
||||
*
|
||||
@@ -125,6 +133,11 @@ class IndexController extends Controller
|
||||
*/
|
||||
public function index(Request $request, string $objectType)
|
||||
{
|
||||
// temp catch for layout.
|
||||
if ('v2' === config('firefly.layout')) {
|
||||
return $this->emptyIndex($objectType);
|
||||
}
|
||||
|
||||
$objectType = $objectType ?? 'asset';
|
||||
$subTitle = (string) trans(sprintf('firefly.%s_accounts', $objectType));
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType));
|
||||
@@ -155,7 +168,7 @@ class IndexController extends Controller
|
||||
$account->startBalance = $this->isInArray($startBalances, $account->id);
|
||||
$account->endBalance = $this->isInArray($endBalances, $account->id);
|
||||
$account->difference = bcsub($account->endBalance, $account->startBalance);
|
||||
$account->interest = round($this->repository->getMetaValue($account, 'interest'), 6);
|
||||
$account->interest = number_format((float) $this->repository->getMetaValue($account, 'interest'), 6, '.', '');
|
||||
$account->interestPeriod = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')));
|
||||
$account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type));
|
||||
$account->location = $this->repository->getLocation($account);
|
||||
|
||||
@@ -129,8 +129,8 @@ class ReconcileController extends Controller
|
||||
|
||||
$startDate = clone $start;
|
||||
$startDate->subDay();
|
||||
$startBalance = round(app('steam')->balance($account, $startDate), $currency->decimal_places);
|
||||
$endBalance = round(app('steam')->balance($account, $end), $currency->decimal_places);
|
||||
$startBalance = number_format((float) app('steam')->balance($account, $startDate), $currency->decimal_places, '.', '');
|
||||
$endBalance = number_format((float) app('steam')->balance($account, $end), $currency->decimal_places, '.', '');
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
|
||||
$subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]);
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ class ShowController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Show an account.
|
||||
*
|
||||
@@ -89,6 +90,13 @@ class ShowController extends Controller
|
||||
*/
|
||||
public function show(Request $request, Account $account, Carbon $start = null, Carbon $end = null)
|
||||
{
|
||||
$objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type));
|
||||
|
||||
// temp catch for layout.
|
||||
if ('v2' === config('firefly.layout')) {
|
||||
return view('accounts.empty-index', compact('objectType'));
|
||||
}
|
||||
|
||||
if (!$this->isEditableAccount($account)) {
|
||||
return $this->redirectAccountToAccount($account); // @codeCoverageIgnore
|
||||
}
|
||||
@@ -103,7 +111,6 @@ class ShowController extends Controller
|
||||
}
|
||||
$location = $this->repository->getLocation($account);
|
||||
$attachments = $this->repository->getAttachments($account);
|
||||
$objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type));
|
||||
$today = new Carbon;
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
|
||||
$page = (int) $request->get('page');
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TelemetryController.php
|
||||
* Copyright (c) 2020 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
/**
|
||||
* ConfirmPasswordController.php
|
||||
@@ -22,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
|
||||
130
app/Http/Controllers/Bill/CreateController.php
Normal file
130
app/Http/Controllers/Bill/CreateController.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CreateController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Bill;
|
||||
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\BillStoreRequest;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Class CreateController
|
||||
*/
|
||||
class CreateController extends Controller
|
||||
{
|
||||
private AttachmentHelperInterface $attachments;
|
||||
private BillRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* BillController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new bill.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$periods = [];
|
||||
/** @var array $billPeriods */
|
||||
$billPeriods = config('firefly.bill_periods');
|
||||
foreach ($billPeriods as $current) {
|
||||
$periods[$current] = strtolower((string) trans('firefly.repeat_freq_' . $current));
|
||||
}
|
||||
$subTitle = (string) trans('firefly.create_new_bill');
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (true !== session('bills.create.fromStore')) {
|
||||
$this->rememberPreviousUri('bills.create.uri');
|
||||
}
|
||||
$request->session()->forget('bills.create.fromStore');
|
||||
|
||||
return view('bills.create', compact('periods', 'subTitle', 'defaultCurrency'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new bill.
|
||||
*
|
||||
* @param BillStoreRequest $request
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*
|
||||
*/
|
||||
public function store(BillStoreRequest $request): RedirectResponse
|
||||
{
|
||||
$billData = $request->getBillData();
|
||||
$billData['active'] = true;
|
||||
try {
|
||||
$bill = $this->repository->store($billData);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
$request->session()->flash('error', (string) trans('firefly.bill_store_error'));
|
||||
|
||||
return redirect(route('bills.create'))->withInput();
|
||||
}
|
||||
$request->session()->flash('success', (string) trans('firefly.stored_new_bill', ['name' => $bill->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var array $files */
|
||||
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||
if (null !== $files && !auth()->user()->hasRole('demo')) {
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
session()->flash('info', (string) trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return redirect(route('rules.create-from-bill', [$bill->id]));
|
||||
}
|
||||
}
|
||||
99
app/Http/Controllers/Bill/DeleteController.php
Normal file
99
app/Http/Controllers/Bill/DeleteController.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DeleteController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Bill;
|
||||
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* Class DeleteController
|
||||
*/
|
||||
class DeleteController extends Controller
|
||||
{
|
||||
private BillRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* BillController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
app('view')->share('showBudget', true);
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Delete a bill.
|
||||
*
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function delete(Bill $bill)
|
||||
{
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('bills.delete.uri');
|
||||
$subTitle = (string) trans('firefly.delete_bill', ['name' => $bill->name]);
|
||||
|
||||
return view('bills.delete', compact('bill', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return RedirectResponse|Redirector
|
||||
*/
|
||||
public function destroy(Request $request, Bill $bill)
|
||||
{
|
||||
$name = $bill->name;
|
||||
$this->repository->destroy($bill);
|
||||
|
||||
$request->session()->flash('success', (string) trans('firefly.deleted_bill', ['name' => $name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
return redirect($this->getPreviousUri('bills.delete.uri'));
|
||||
}
|
||||
}
|
||||
155
app/Http/Controllers/Bill/EditController.php
Normal file
155
app/Http/Controllers/Bill/EditController.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* EditController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Bill;
|
||||
|
||||
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\BillUpdateRequest;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Class EditController
|
||||
*/
|
||||
class EditController extends Controller
|
||||
{
|
||||
private AttachmentHelperInterface $attachments;
|
||||
private BillRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* BillController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Edit a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function edit(Request $request, Bill $bill)
|
||||
{
|
||||
$periods = [];
|
||||
/** @var array $billPeriods */
|
||||
$billPeriods = config('firefly.bill_periods');
|
||||
|
||||
foreach ($billPeriods as $current) {
|
||||
$periods[$current] = (string) trans('firefly.' . $current);
|
||||
}
|
||||
|
||||
$subTitle = (string) trans('firefly.edit_bill', ['name' => $bill->name]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('bills.edit.fromUpdate')) {
|
||||
$this->rememberPreviousUri('bills.edit.uri');
|
||||
}
|
||||
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
$bill->amount_min = round((float) $bill->amount_min, $currency->decimal_places);
|
||||
$bill->amount_max = round((float) $bill->amount_max, $currency->decimal_places);
|
||||
$rules = $this->repository->getRulesForBill($bill);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
|
||||
// code to handle active-checkboxes
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
|
||||
$preFilled = [
|
||||
'notes' => $this->repository->getNoteText($bill),
|
||||
'transaction_currency_id' => $bill->transaction_currency_id,
|
||||
'active' => $hasOldInput ? (bool) $request->old('active') : $bill->active,
|
||||
'object_group' => $bill->objectGroups->first() ? $bill->objectGroups->first()->title : '',
|
||||
];
|
||||
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
$request->session()->forget('bills.edit.fromUpdate');
|
||||
|
||||
return view('bills.edit', compact('subTitle', 'periods', 'rules', 'bill', 'defaultCurrency', 'preFilled'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update a bill.
|
||||
*
|
||||
* @param BillUpdateRequest $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(BillUpdateRequest $request, Bill $bill): RedirectResponse
|
||||
{
|
||||
$billData = $request->getBillData();
|
||||
$bill = $this->repository->update($bill, $billData);
|
||||
|
||||
$request->session()->flash('success', (string) trans('firefly.updated_bill', ['name' => $bill->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var array $files */
|
||||
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||
if (null !== $files && !auth()->user()->hasRole('demo')) {
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
session()->flash('info',(string)trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
// flash messages
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
|
||||
}
|
||||
$redirect = redirect($this->getPreviousUri('bills.edit.uri'));
|
||||
|
||||
if (1 === (int) $request->get('return_to_edit')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('bills.edit.fromUpdate', true);
|
||||
|
||||
$redirect = redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return $redirect;
|
||||
}
|
||||
}
|
||||
253
app/Http/Controllers/Bill/IndexController.php
Normal file
253
app/Http/Controllers/Bill/IndexController.php
Normal file
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* IndexController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Bill;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
/**
|
||||
* Class IndexController
|
||||
*/
|
||||
class IndexController extends Controller
|
||||
{
|
||||
use OrganisesObjectGroups;
|
||||
private BillRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* BillController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all bills.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->cleanupObjectGroups();
|
||||
$this->repository->correctOrder();
|
||||
|
||||
|
||||
$start = session('start');
|
||||
$end = session('end');
|
||||
$collection = $this->repository->getBills();
|
||||
$total = $collection->count();
|
||||
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$parameters = new ParameterBag;
|
||||
$parameters->set('start', $start);
|
||||
$parameters->set('end', $end);
|
||||
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($parameters);
|
||||
|
||||
// loop all bills, convert to array and add rules and stuff.
|
||||
$rules = $this->repository->getRulesForBills($collection);
|
||||
|
||||
// make bill groups:
|
||||
$bills = [
|
||||
0 => [ // the index is the order, not the ID.
|
||||
'object_group_id' => 0,
|
||||
'object_group_title' => (string) trans('firefly.default_group_title_name'),
|
||||
'bills' => [],
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($collection as $bill) {
|
||||
$array = $transformer->transform($bill);
|
||||
$groupOrder = (int) $array['object_group_order'];
|
||||
// make group array if necessary:
|
||||
$bills[$groupOrder] = $bills[$groupOrder] ?? [
|
||||
'object_group_id' => $array['object_group_id'],
|
||||
'object_group_title' => $array['object_group_title'],
|
||||
'bills' => [],
|
||||
];
|
||||
|
||||
// expected today? default:
|
||||
$array['next_expected_match_diff'] = trans('firefly.not_expected_period');
|
||||
$nextExpectedMatch = new Carbon($array['next_expected_match']);
|
||||
if ($nextExpectedMatch->isToday()) {
|
||||
$array['next_expected_match_diff'] = trans('firefly.today');
|
||||
}
|
||||
$current = $array['pay_dates'][0] ?? null;
|
||||
if (null !== $current && !$nextExpectedMatch->isToday()) {
|
||||
$currentExpectedMatch = Carbon::createFromFormat('!Y-m-d', $current);
|
||||
$array['next_expected_match_diff'] = $currentExpectedMatch->diffForHumans(today(), Carbon::DIFF_RELATIVE_TO_NOW);
|
||||
}
|
||||
|
||||
$currency = $bill->transactionCurrency ?? $defaultCurrency;
|
||||
$array['currency_id'] = $currency->id;
|
||||
$array['currency_name'] = $currency->name;
|
||||
$array['currency_symbol'] = $currency->symbol;
|
||||
$array['currency_code'] = $currency->code;
|
||||
$array['currency_decimal_places'] = $currency->decimal_places;
|
||||
$array['attachments'] = $this->repository->getAttachments($bill);
|
||||
$array['rules'] = $rules[$bill['id']] ?? [];
|
||||
$bills[$groupOrder]['bills'][] = $array;
|
||||
}
|
||||
|
||||
// order by key
|
||||
ksort($bills);
|
||||
|
||||
// summarise per currency / per group.
|
||||
$sums = $this->getSums($bills);
|
||||
|
||||
return view('bills.index', compact('bills', 'sums', 'total'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $bills
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSums(array $bills): array
|
||||
{
|
||||
$sums = [];
|
||||
$range = app('preferences')->get('viewRange', '1M')->data;
|
||||
|
||||
/** @var array $group */
|
||||
foreach ($bills as $groupOrder => $group) {
|
||||
/** @var array $bill */
|
||||
foreach ($group['bills'] as $bill) {
|
||||
if (false === $bill['active']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currencyId = $bill['currency_id'];
|
||||
$sums[$groupOrder][$currencyId] = $sums[$groupOrder][$currencyId] ?? [
|
||||
'currency_id' => $currencyId,
|
||||
'currency_code' => $bill['currency_code'],
|
||||
'currency_name' => $bill['currency_name'],
|
||||
'currency_symbol' => $bill['currency_symbol'],
|
||||
'currency_decimal_places' => $bill['currency_decimal_places'],
|
||||
'avg' => '0',
|
||||
'period' => $range,
|
||||
'per_period' => '0',
|
||||
];
|
||||
// only fill in avg when bill is active.
|
||||
if (count($bill['pay_dates']) > 0) {
|
||||
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
|
||||
$avg = bcmul($avg, (string) count($bill['pay_dates']));
|
||||
$sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg);
|
||||
}
|
||||
// fill in per period regardless:
|
||||
$sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range));
|
||||
}
|
||||
}
|
||||
|
||||
return $sums;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $bill
|
||||
* @param string $range
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function amountPerPeriod(array $bill, string $range): string
|
||||
{
|
||||
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
|
||||
|
||||
Log::debug(sprintf('Amount per period for bill #%d "%s"', $bill['id'], $bill['name']));
|
||||
Log::debug(sprintf(sprintf('Average is %s', $avg)));
|
||||
// calculate amount per year:
|
||||
$multiplies = [
|
||||
'yearly' => '1',
|
||||
'half-year' => '2',
|
||||
'quarterly' => '4',
|
||||
'monthly' => '12',
|
||||
'weekly' => '52.17',
|
||||
];
|
||||
$yearAmount = bcmul($avg, $multiplies[$bill['repeat_freq']]);
|
||||
Log::debug(sprintf('Amount per year is %s (%s * %s)', $yearAmount, $avg, $multiplies[$bill['repeat_freq']]));
|
||||
|
||||
// per period:
|
||||
$division = [
|
||||
'1Y' => '1',
|
||||
'6M' => '2',
|
||||
'3M' => '4',
|
||||
'1M' => '12',
|
||||
'1W' => '52.16',
|
||||
'1D' => '365.24',
|
||||
];
|
||||
$perPeriod = bcdiv($yearAmount, $division[$range]);
|
||||
|
||||
Log::debug(sprintf('Amount per %s is %s (%s / %s)', $range, $perPeriod, $yearAmount, $division[$range]));
|
||||
|
||||
return $perPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order of a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function setOrder(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$objectGroupTitle = (string)$request->get('objectGroupTitle');
|
||||
$newOrder = (int) $request->get('order');
|
||||
$this->repository->setOrder($bill, $newOrder);
|
||||
if ('' !== $objectGroupTitle) {
|
||||
$this->repository->setObjectGroup($bill, $objectGroupTitle);
|
||||
}
|
||||
if ('' === $objectGroupTitle) {
|
||||
$this->repository->removeObjectGroup($bill);
|
||||
}
|
||||
|
||||
return response()->json(['data' => 'OK']);
|
||||
}
|
||||
}
|
||||
195
app/Http/Controllers/Bill/ShowController.php
Normal file
195
app/Http/Controllers/Bill/ShowController.php
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/**
|
||||
* ShowController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Bill;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\View\View;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\DataArraySerializer;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
/**
|
||||
* Class ShowController
|
||||
*/
|
||||
class ShowController extends Controller
|
||||
{
|
||||
private BillRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* BillController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
app('view')->share('showBudget', true);
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Rescan bills for transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @return RedirectResponse|Redirector
|
||||
*/
|
||||
public function rescan(Request $request, Bill $bill)
|
||||
{
|
||||
$total = 0;
|
||||
if (false === $bill->active) {
|
||||
$request->session()->flash('warning', (string) trans('firefly.cannot_scan_inactive_bill'));
|
||||
|
||||
return redirect(route('bills.show', [$bill->id]));
|
||||
}
|
||||
$set = new Collection;
|
||||
if (true === $bill->active) {
|
||||
$set = $this->repository->getRulesForBill($bill);
|
||||
$total = 0;
|
||||
}
|
||||
if (0 === $set->count()) {
|
||||
$request->session()->flash('error', (string) trans('firefly.no_rules_for_bill'));
|
||||
|
||||
return redirect(route('bills.show', [$bill->id]));
|
||||
}
|
||||
|
||||
// unlink all journals:
|
||||
$this->repository->unlinkAll($bill);
|
||||
|
||||
foreach ($set as $rule) {
|
||||
// simply fire off all rules?
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
$matcher->setSearchLimit(100000); // large upper limit
|
||||
$matcher->setTriggeredLimit(100000); // large upper limit
|
||||
$matcher->setRule($rule);
|
||||
$matchingTransactions = $matcher->findTransactionsByRule();
|
||||
$total += count($matchingTransactions);
|
||||
$this->repository->linkCollectionToBill($bill, $matchingTransactions);
|
||||
}
|
||||
|
||||
|
||||
$request->session()->flash('success', (string) trans_choice('firefly.rescanned_bill', $total));
|
||||
app('preferences')->mark();
|
||||
|
||||
return redirect(route('bills.show', [$bill->id]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Show a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function show(Request $request, Bill $bill)
|
||||
{
|
||||
// add info about rules:
|
||||
$rules = $this->repository->getRulesForBill($bill);
|
||||
$subTitle = $bill->name;
|
||||
/** @var Carbon $start */
|
||||
$start = session('start');
|
||||
/** @var Carbon $end */
|
||||
$end = session('end');
|
||||
$year = $start->year;
|
||||
$page = (int) $request->get('page');
|
||||
$pageSize = (int) app('preferences')->get('listPageSize', 50)->data;
|
||||
$yearAverage = $this->repository->getYearAverage($bill, $start);
|
||||
$overallAverage = $this->repository->getOverallAverage($bill);
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new DataArraySerializer());
|
||||
$manager->parseIncludes(['attachments', 'notes']);
|
||||
|
||||
// Make a resource out of the data and
|
||||
$parameters = new ParameterBag();
|
||||
$parameters->set('start', $start);
|
||||
$parameters->set('end', $end);
|
||||
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($parameters);
|
||||
|
||||
$resource = new Item($bill, $transformer, 'bill');
|
||||
$object = $manager->createData($resource)->toArray();
|
||||
$object['data']['currency'] = $bill->transactionCurrency;
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setBill($bill)->setLimit($pageSize)->setPage($page)->withBudgetInformation()
|
||||
->withCategoryInformation()->withAccountInformation();
|
||||
$groups = $collector->getPaginatedGroups();
|
||||
$groups->setPath(route('bills.show', [$bill->id]));
|
||||
|
||||
// transform any attachments as well.
|
||||
$collection = $this->repository->getAttachments($bill);
|
||||
$attachments = new Collection;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($collection->count() > 0) {
|
||||
/** @var AttachmentTransformer $transformer */
|
||||
$transformer = app(AttachmentTransformer::class);
|
||||
$attachments = $collection->each(
|
||||
static function (Attachment $attachment) use ($transformer) {
|
||||
return $transformer->transform($attachment);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
return view('bills.show', compact('attachments', 'groups', 'rules', 'yearAverage', 'overallAverage', 'year', 'object', 'bill', 'subTitle'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,483 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* BillController.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Http\Requests\BillFormRequest;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\View\View;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\DataArraySerializer;
|
||||
use Log;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
/**
|
||||
* Class BillController.
|
||||
*
|
||||
*/
|
||||
class BillController extends Controller
|
||||
{
|
||||
/** @var AttachmentHelperInterface Helper for attachments. */
|
||||
private $attachments;
|
||||
/** @var BillRepositoryInterface Bill repository */
|
||||
private $billRepository;
|
||||
|
||||
/**
|
||||
* BillController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
app('view')->share('showBudget', true);
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
$this->billRepository = app(BillRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new bill.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$periods = [];
|
||||
/** @var array $billPeriods */
|
||||
$billPeriods = config('firefly.bill_periods');
|
||||
foreach ($billPeriods as $current) {
|
||||
$periods[$current] = strtolower((string) trans('firefly.repeat_freq_' . $current));
|
||||
}
|
||||
$subTitle = (string) trans('firefly.create_new_bill');
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (true !== session('bills.create.fromStore')) {
|
||||
$this->rememberPreviousUri('bills.create.uri');
|
||||
}
|
||||
$request->session()->forget('bills.create.fromStore');
|
||||
|
||||
return view('bills.create', compact('periods', 'subTitle', 'defaultCurrency'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a bill.
|
||||
*
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function delete(Bill $bill)
|
||||
{
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('bills.delete.uri');
|
||||
$subTitle = (string) trans('firefly.delete_bill', ['name' => $bill->name]);
|
||||
|
||||
return view('bills.delete', compact('bill', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return RedirectResponse|Redirector
|
||||
*/
|
||||
public function destroy(Request $request, Bill $bill)
|
||||
{
|
||||
$name = $bill->name;
|
||||
$this->billRepository->destroy($bill);
|
||||
|
||||
$request->session()->flash('success', (string) trans('firefly.deleted_bill', ['name' => $name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
return redirect($this->getPreviousUri('bills.delete.uri'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function edit(Request $request, Bill $bill)
|
||||
{
|
||||
$periods = [];
|
||||
/** @var array $billPeriods */
|
||||
$billPeriods = config('firefly.bill_periods');
|
||||
|
||||
foreach ($billPeriods as $current) {
|
||||
$periods[$current] = (string) trans('firefly.' . $current);
|
||||
}
|
||||
|
||||
$subTitle = (string) trans('firefly.edit_bill', ['name' => $bill->name]);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('bills.edit.fromUpdate')) {
|
||||
$this->rememberPreviousUri('bills.edit.uri');
|
||||
}
|
||||
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
$bill->amount_min = round((float) $bill->amount_min, $currency->decimal_places);
|
||||
$bill->amount_max = round((float) $bill->amount_max, $currency->decimal_places);
|
||||
$rules = $this->billRepository->getRulesForBill($bill);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
|
||||
// code to handle active-checkboxes
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
|
||||
$preFilled = [
|
||||
'notes' => $this->billRepository->getNoteText($bill),
|
||||
'transaction_currency_id' => $bill->transaction_currency_id,
|
||||
'active' => $hasOldInput ? (bool) $request->old('active') : $bill->active,
|
||||
];
|
||||
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
$request->session()->forget('bills.edit.fromUpdate');
|
||||
|
||||
return view('bills.edit', compact('subTitle', 'periods', 'rules', 'bill', 'defaultCurrency', 'preFilled'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all bills.
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$start = session('start');
|
||||
$end = session('end');
|
||||
$unfiltered = $this->billRepository->getBills();
|
||||
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$parameters = new ParameterBag();
|
||||
$parameters->set('start', $start);
|
||||
$parameters->set('end', $end);
|
||||
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($parameters);
|
||||
|
||||
/** @var Collection $bills */
|
||||
$bills = $unfiltered->map(
|
||||
function (Bill $bill) use ($transformer, $defaultCurrency) {
|
||||
$return = $transformer->transform($bill);
|
||||
$nextExpectedMatch = new Carbon($return['next_expected_match']);
|
||||
$return['next_expected_match_diff'] = $nextExpectedMatch->isToday()
|
||||
? trans('firefly.today')
|
||||
: $nextExpectedMatch->diffForHumans(
|
||||
today(), Carbon::DIFF_RELATIVE_TO_NOW
|
||||
);
|
||||
$currency = $bill->transactionCurrency ?? $defaultCurrency;
|
||||
$return['currency_id'] = $currency->id;
|
||||
$return['currency_name'] = $currency->name;
|
||||
$return['currency_symbol'] = $currency->symbol;
|
||||
$return['currency_code'] = $currency->code;
|
||||
$return['currency_decimal_places'] = $currency->decimal_places;
|
||||
$return['attachments'] = $this->billRepository->getAttachments($bill);
|
||||
|
||||
return $return;
|
||||
}
|
||||
);
|
||||
|
||||
// add info about rules:
|
||||
$rules = $this->billRepository->getRulesForBills($unfiltered);
|
||||
$bills = $bills->map(
|
||||
static function (array $bill) use ($rules) {
|
||||
$bill['rules'] = $rules[$bill['id']] ?? [];
|
||||
|
||||
return $bill;
|
||||
}
|
||||
);
|
||||
|
||||
// summarise per currency:
|
||||
$sums = $this->getSums($bills);
|
||||
|
||||
return view('bills.index', compact('bills', 'sums'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rescan bills for transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @return RedirectResponse|Redirector
|
||||
*/
|
||||
public function rescan(Request $request, Bill $bill)
|
||||
{
|
||||
$total = 0;
|
||||
if (false === $bill->active) {
|
||||
$request->session()->flash('warning', (string) trans('firefly.cannot_scan_inactive_bill'));
|
||||
|
||||
return redirect(route('bills.show', [$bill->id]));
|
||||
}
|
||||
$set = new Collection;
|
||||
if (true === $bill->active) {
|
||||
$set = $this->billRepository->getRulesForBill($bill);
|
||||
$total = 0;
|
||||
}
|
||||
if (0 === $set->count()) {
|
||||
$request->session()->flash('error', (string) trans('firefly.no_rules_for_bill'));
|
||||
|
||||
return redirect(route('bills.show', [$bill->id]));
|
||||
}
|
||||
|
||||
// unlink all journals:
|
||||
$this->billRepository->unlinkAll($bill);
|
||||
|
||||
foreach ($set as $rule) {
|
||||
// simply fire off all rules?
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
$matcher->setSearchLimit(100000); // large upper limit
|
||||
$matcher->setTriggeredLimit(100000); // large upper limit
|
||||
$matcher->setRule($rule);
|
||||
$matchingTransactions = $matcher->findTransactionsByRule();
|
||||
$total += count($matchingTransactions);
|
||||
$this->billRepository->linkCollectionToBill($bill, $matchingTransactions);
|
||||
}
|
||||
|
||||
|
||||
$request->session()->flash('success', (string) trans_choice('firefly.rescanned_bill', $total));
|
||||
app('preferences')->mark();
|
||||
|
||||
return redirect(route('bills.show', [$bill->id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function show(Request $request, Bill $bill)
|
||||
{
|
||||
// add info about rules:
|
||||
$rules = $this->billRepository->getRulesForBill($bill);
|
||||
$subTitle = $bill->name;
|
||||
/** @var Carbon $start */
|
||||
$start = session('start');
|
||||
/** @var Carbon $end */
|
||||
$end = session('end');
|
||||
$year = $start->year;
|
||||
$page = (int) $request->get('page');
|
||||
$pageSize = (int) app('preferences')->get('listPageSize', 50)->data;
|
||||
$yearAverage = $this->billRepository->getYearAverage($bill, $start);
|
||||
$overallAverage = $this->billRepository->getOverallAverage($bill);
|
||||
$manager = new Manager();
|
||||
$manager->setSerializer(new DataArraySerializer());
|
||||
$manager->parseIncludes(['attachments', 'notes']);
|
||||
|
||||
// Make a resource out of the data and
|
||||
$parameters = new ParameterBag();
|
||||
$parameters->set('start', $start);
|
||||
$parameters->set('end', $end);
|
||||
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($parameters);
|
||||
|
||||
$resource = new Item($bill, $transformer, 'bill');
|
||||
$object = $manager->createData($resource)->toArray();
|
||||
$object['data']['currency'] = $bill->transactionCurrency;
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setBill($bill)->setLimit($pageSize)->setPage($page)->withBudgetInformation()
|
||||
->withCategoryInformation()->withAccountInformation();
|
||||
$groups = $collector->getPaginatedGroups();
|
||||
$groups->setPath(route('bills.show', [$bill->id]));
|
||||
|
||||
// transform any attachments as well.
|
||||
$collection = $this->billRepository->getAttachments($bill);
|
||||
$attachments = new Collection;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($collection->count() > 0) {
|
||||
/** @var AttachmentTransformer $transformer */
|
||||
$transformer = app(AttachmentTransformer::class);
|
||||
$attachments = $collection->each(
|
||||
static function (Attachment $attachment) use ($transformer) {
|
||||
return $transformer->transform($attachment);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
return view('bills.show', compact('attachments', 'groups', 'rules', 'yearAverage', 'overallAverage', 'year', 'object', 'bill', 'subTitle'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a new bill.
|
||||
*
|
||||
* @param BillFormRequest $request
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*
|
||||
*/
|
||||
public function store(BillFormRequest $request): RedirectResponse
|
||||
{
|
||||
$billData = $request->getBillData();
|
||||
$billData['active'] = true;
|
||||
try {
|
||||
$bill = $this->billRepository->store($billData);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
$request->session()->flash('error', (string) trans('firefly.bill_store_error'));
|
||||
|
||||
return redirect(route('bills.create'))->withInput();
|
||||
}
|
||||
$request->session()->flash('success', (string) trans('firefly.stored_new_bill', ['name' => $bill->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var array $files */
|
||||
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||
if (null !== $files && !auth()->user()->hasRole('demo')) {
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
session()->flash('info',(string)trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return redirect(route('rules.create-from-bill', [$bill->id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a bill.
|
||||
*
|
||||
* @param BillFormRequest $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(BillFormRequest $request, Bill $bill): RedirectResponse
|
||||
{
|
||||
$billData = $request->getBillData();
|
||||
$bill = $this->billRepository->update($bill, $billData);
|
||||
|
||||
$request->session()->flash('success', (string) trans('firefly.updated_bill', ['name' => $bill->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var array $files */
|
||||
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||
if (null !== $files && !auth()->user()->hasRole('demo')) {
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
session()->flash('info',(string)trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
// flash messages
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
|
||||
}
|
||||
$redirect = redirect($this->getPreviousUri('bills.edit.uri'));
|
||||
|
||||
if (1 === (int) $request->get('return_to_edit')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->put('bills.edit.fromUpdate', true);
|
||||
|
||||
$redirect = redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return $redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $bills
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSums(Collection $bills): array
|
||||
{
|
||||
$sums = [];
|
||||
|
||||
/** @var array $bill */
|
||||
foreach ($bills as $bill) {
|
||||
if (false === $bill['active']) {
|
||||
continue;
|
||||
}
|
||||
if (0 === count($bill['pay_dates'])) {
|
||||
continue;
|
||||
}
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currencyId = $bill['currency_id'];
|
||||
$sums[$currencyId] = $sums[$currencyId] ?? [
|
||||
'currency_id' => $currencyId,
|
||||
'currency_code' => $bill['currency_code'],
|
||||
'currency_name' => $bill['currency_name'],
|
||||
'currency_symbol' => $bill['currency_symbol'],
|
||||
'currency_decimal_places' => $bill['currency_decimal_places'],
|
||||
'avg' => '0',
|
||||
];
|
||||
|
||||
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
|
||||
$avg = bcmul($avg, (string) count($bill['pay_dates']));
|
||||
$sums[$currencyId]['avg'] = bcadd($sums[$currencyId]['avg'], $avg);
|
||||
}
|
||||
|
||||
return $sums;
|
||||
}
|
||||
}
|
||||
@@ -157,7 +157,7 @@ class AvailableBudgetController extends Controller
|
||||
*/
|
||||
public function edit(AvailableBudget $availableBudget, Carbon $start, Carbon $end)
|
||||
{
|
||||
$availableBudget->amount = round($availableBudget->amount, $availableBudget->transactionCurrency->decimal_places);
|
||||
$availableBudget->amount = number_format((float) $availableBudget->amount, $availableBudget->transactionCurrency->decimal_places, '.', '');
|
||||
return view('budgets.available-budgets.edit', compact('availableBudget', 'start', 'end'));
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ class BudgetLimitController extends Controller
|
||||
$array['left_per_day'] = bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
|
||||
|
||||
// left per day formatted.
|
||||
$array['amount'] = round($limit['amount'], $limit->transactionCurrency->decimal_places);
|
||||
$array['amount'] = number_format((float) $limit['amount'], $limit->transactionCurrency->decimal_places, '.', '');
|
||||
$array['left_per_day_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $array['left_per_day']);
|
||||
|
||||
return response()->json($array);
|
||||
|
||||
@@ -174,7 +174,7 @@ class IndexController extends Controller
|
||||
$currency = $limit->transactionCurrency ?? $defaultCurrency;
|
||||
$array['budgeted'][] = [
|
||||
'id' => $limit->id,
|
||||
'amount' => round($limit->amount, $currency->decimal_places),
|
||||
'amount' => number_format((float) $limit->amount, $currency->decimal_places, '.', ''),
|
||||
'start_date' => $limit->start_date->formatLocalized($this->monthAndDayFormat),
|
||||
'end_date' => $limit->end_date->formatLocalized($this->monthAndDayFormat),
|
||||
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),
|
||||
|
||||
@@ -84,8 +84,6 @@ class ShowController extends Controller
|
||||
*/
|
||||
public function noBudget(Request $request, Carbon $start = null, Carbon $end = null)
|
||||
{
|
||||
|
||||
|
||||
/** @var Carbon $start */
|
||||
$start = $start ?? session('start');
|
||||
/** @var Carbon $end */
|
||||
@@ -211,7 +209,7 @@ class ShowController extends Controller
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
|
||||
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date)
|
||||
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date)->withAccountInformation()
|
||||
->setBudget($budget)->setLimit($pageSize)->setPage($page)->withBudgetInformation()->withCategoryInformation();
|
||||
$groups = $collector->getPaginatedGroups();
|
||||
$groups->setPath(route('budgets.show', [$budget->id, $budgetLimit->id]));
|
||||
|
||||
@@ -126,8 +126,8 @@ class BillController extends Controller
|
||||
);
|
||||
|
||||
$chartData = [
|
||||
['type' => 'line', 'label' => (string) trans('firefly.max-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol, 'entries' => []],
|
||||
['type' => 'line', 'label' => (string) trans('firefly.min-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol, 'entries' => []],
|
||||
['type' => 'line', 'label' => (string) trans('firefly.max-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol, 'entries' => []],
|
||||
['type' => 'bar', 'label' => (string) trans('firefly.journal-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol, 'entries' => []],
|
||||
];
|
||||
|
||||
|
||||
@@ -216,7 +216,6 @@ class BudgetController extends Controller
|
||||
$cache->addProperty($budget->id);
|
||||
$cache->addProperty($budgetLimitId);
|
||||
$cache->addProperty('chart.budget.expense-asset');
|
||||
$collector->setRange(session()->get('start'), session()->get('end'));
|
||||
$start = session()->get('start');
|
||||
$end = session()->get('end');
|
||||
if (null !== $budgetLimit) {
|
||||
@@ -230,6 +229,7 @@ class BudgetController extends Controller
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setBudget($budget);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$result = [];
|
||||
@@ -282,13 +282,12 @@ class BudgetController extends Controller
|
||||
$cache->addProperty($budget->id);
|
||||
$cache->addProperty($budgetLimitId);
|
||||
$cache->addProperty('chart.budget.expense-category');
|
||||
$collector->setRange(session()->get('start'), session()->get('end'));
|
||||
$start = session()->get('start');
|
||||
$end = session()->get('end');
|
||||
if (null !== $budgetLimit) {
|
||||
$start = $budgetLimit->start_date;
|
||||
$end = $budgetLimit->end_date;
|
||||
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date)->setCurrency($budgetLimit->transactionCurrency);
|
||||
$collector->setCurrency($budgetLimit->transactionCurrency);
|
||||
}
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
@@ -296,6 +295,7 @@ class BudgetController extends Controller
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setBudget($budget)->withCategoryInformation();
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$result = [];
|
||||
@@ -345,7 +345,6 @@ class BudgetController extends Controller
|
||||
$cache->addProperty($budget->id);
|
||||
$cache->addProperty($budgetLimitId);
|
||||
$cache->addProperty('chart.budget.expense-expense');
|
||||
$collector->setRange(session()->get('start'), session()->get('end'));
|
||||
$start = session()->get('start');
|
||||
$end = session()->get('end');
|
||||
if (null !== $budgetLimit) {
|
||||
@@ -359,7 +358,7 @@ class BudgetController extends Controller
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$collector->setRange($start, $end);
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL])->setBudget($budget)->withAccountInformation();
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$result = [];
|
||||
@@ -413,7 +412,7 @@ class BudgetController extends Controller
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('chart.budget.frontpage');
|
||||
if ($cache->has()) {
|
||||
// return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$budgets = $this->repository->getActiveBudgets();
|
||||
$chartData = [
|
||||
|
||||
@@ -111,7 +111,7 @@ class CategoryController extends Controller
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('chart.category.frontpage');
|
||||
if ($cache->has()) {
|
||||
// return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$frontPageGenerator = new FrontpageChartGenerator($start, $end);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionController.php
|
||||
* Copyright (c) 2020 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
@@ -55,7 +55,8 @@ class Controller extends BaseController
|
||||
public function __construct()
|
||||
{
|
||||
// is site a demo site?
|
||||
$isDemoSite = app('fireflyconfig')->get('is_demo_site', config('firefly.configuration.is_demo_site', false,),)->data;
|
||||
$isDemoSiteConfig = app('fireflyconfig')->get('is_demo_site', config('firefly.configuration.is_demo_site', false,),);
|
||||
$isDemoSite = $isDemoSiteConfig ? $isDemoSiteConfig->data : false;
|
||||
app('view')->share('IS_DEMO_SITE', $isDemoSite,);
|
||||
app('view')->share('DEMO_USERNAME', config('firefly.demo_username'));
|
||||
app('view')->share('DEMO_PASSWORD', config('firefly.demo_password'));
|
||||
|
||||
@@ -122,7 +122,8 @@ class DebugController extends Controller
|
||||
$replace = ['\~', '# '];
|
||||
|
||||
$now = Carbon::now()->format('Y-m-d H:i:s e');
|
||||
$installationId = app('fireflyconfig')->get('installation_id', '')->data;
|
||||
$installationIdConfig = app('fireflyconfig')->get('installation_id', '');
|
||||
$installationId = $installationIdConfig ? $installationIdConfig->data : '';
|
||||
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
||||
$phpOs = str_replace($search, $replace, PHP_OS);
|
||||
$interface = PHP_SAPI;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* IndexController.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Export;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BudgetController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Json;
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DeleteController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\ObjectGroup;
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* EditController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\ObjectGroup;
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* IndexController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\ObjectGroup;
|
||||
@@ -43,6 +64,7 @@ class IndexController extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->repository->deleteEmpty();
|
||||
$this->repository->sort();
|
||||
$subTitle = (string) trans('firefly.object_groups_index');
|
||||
$objectGroups = $this->repository->get();
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AmountController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\PiggyBank;
|
||||
@@ -155,8 +176,7 @@ class AmountController extends Controller
|
||||
|
||||
return redirect(route('piggy-banks.index'));
|
||||
}
|
||||
|
||||
$amount = (string) round($request->get('amount'), 12);
|
||||
$amount = number_format((float) $request->get('amount'), 12, '.', '');
|
||||
|
||||
session()->flash(
|
||||
'error',
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CreateController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\PiggyBank;
|
||||
@@ -7,7 +28,7 @@ namespace FireflyIII\Http\Controllers\PiggyBank;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\PiggyBankFormRequest;
|
||||
use FireflyIII\Http\Requests\PiggyBankStoreRequest;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
@@ -67,11 +88,11 @@ class CreateController extends Controller
|
||||
/**
|
||||
* Store a new piggy bank.
|
||||
*
|
||||
* @param PiggyBankFormRequest $request
|
||||
* @param PiggyBankStoreRequest $request
|
||||
*
|
||||
* @return RedirectResponse|Redirector
|
||||
*/
|
||||
public function store(PiggyBankFormRequest $request)
|
||||
public function store(PiggyBankStoreRequest $request)
|
||||
{
|
||||
$data = $request->getPiggyBankData();
|
||||
if (null === $data['startdate']) {
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DeleteController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\PiggyBank;
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* EditController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\PiggyBank;
|
||||
@@ -6,7 +27,7 @@ namespace FireflyIII\Http\Controllers\PiggyBank;
|
||||
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\PiggyBankFormRequest;
|
||||
use FireflyIII\Http\Requests\PiggyBankUpdateRequest;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
@@ -89,12 +110,12 @@ class EditController extends Controller
|
||||
/**
|
||||
* Update a piggy bank.
|
||||
*
|
||||
* @param PiggyBankFormRequest $request
|
||||
* @param PiggyBankUpdateRequest $request
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return RedirectResponse|Redirector
|
||||
*/
|
||||
public function update(PiggyBankFormRequest $request, PiggyBank $piggyBank)
|
||||
public function update(PiggyBankUpdateRequest $request, PiggyBank $piggyBank)
|
||||
{
|
||||
$data = $request->getPiggyBankData();
|
||||
$piggyBank = $this->piggyRepos->update($piggyBank, $data);
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* IndexController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\PiggyBank;
|
||||
@@ -174,7 +195,7 @@ class IndexController extends Controller
|
||||
*/
|
||||
public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$objectGroupTitle = $request->get('objectGroupTitle');
|
||||
$objectGroupTitle = (string) $request->get('objectGroupTitle');
|
||||
$newOrder = (int) $request->get('order');
|
||||
$this->piggyRepos->setOrder($piggyBank, $newOrder);
|
||||
if ('' !== $objectGroupTitle) {
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ShowController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\PiggyBank;
|
||||
|
||||
@@ -67,6 +67,7 @@ class PreferencesController extends Controller
|
||||
public function index(AccountRepositoryInterface $repository)
|
||||
{
|
||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]);
|
||||
$isDocker = env('IS_DOCKER', false);
|
||||
|
||||
// group accounts
|
||||
$groupedAccounts = [];
|
||||
@@ -122,6 +123,7 @@ class PreferencesController extends Controller
|
||||
compact(
|
||||
'language',
|
||||
'groupedAccounts',
|
||||
'isDocker',
|
||||
'frontPageAccounts',
|
||||
'languages',
|
||||
'locales',
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* DataController.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Profile;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
/**
|
||||
* Class DataController
|
||||
*/
|
||||
class DataController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function deleteBudgets(): RedirectResponse
|
||||
{
|
||||
/** @var AvailableBudgetRepositoryInterface $abRepository */
|
||||
$abRepository = app(AvailableBudgetRepositoryInterface::class);
|
||||
$abRepository->destroyAll();
|
||||
|
||||
/** @var BudgetLimitRepositoryInterface $blRepository */
|
||||
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$blRepository->destroyAll();
|
||||
|
||||
/** @var BudgetRepositoryInterface $budgetRepository */
|
||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$budgetRepository->destroyAll();
|
||||
|
||||
session()->flash('success', trans('firefly.deleted_all_budgets'));
|
||||
|
||||
return redirect(route('profile.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function deleteCategories(): RedirectResponse
|
||||
{
|
||||
/** @var CategoryRepositoryInterface $categoryRepos */
|
||||
$categoryRepos = app(CategoryRepositoryInterface::class);
|
||||
$categoryRepos->destroyAll();
|
||||
|
||||
session()->flash('success', trans('firefly.deleted_all_categories'));
|
||||
|
||||
return redirect(route('profile.index'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function deleteTags(): RedirectResponse
|
||||
{
|
||||
/** @var TagRepositoryInterface $tagRepository */
|
||||
$tagRepository = app(TagRepositoryInterface::class);
|
||||
$tagRepository->destroyAll();
|
||||
|
||||
session()->flash('success', trans('firefly.deleted_all_tags'));
|
||||
|
||||
return redirect(route('profile.index'));
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class ProfileController extends Controller
|
||||
);
|
||||
$loginProvider = config('firefly.login_provider');
|
||||
$authGuard = config('firefly.authentication_guard');
|
||||
$this->externalIdentity = 'eloquent' === $loginProvider || 'remote_user_guard' === $authGuard;
|
||||
$this->externalIdentity = 'eloquent' !== $loginProvider || 'web' !== $authGuard;
|
||||
|
||||
$this->middleware(IsDemoUser::class)->except(['index']);
|
||||
}
|
||||
|
||||
@@ -31,9 +31,7 @@ use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laravel\Passport\Passport;
|
||||
use Log;
|
||||
@@ -106,6 +104,7 @@ class InstallController extends Controller
|
||||
'firefly-iii:fix-ob-currencies' => [],
|
||||
'firefly-iii:fix-long-descriptions' => [],
|
||||
'firefly-iii:fix-recurring-transactions' => [],
|
||||
'firefly-iii:unify-group-accounts' => [],
|
||||
|
||||
// final command to set latest version in DB
|
||||
'firefly-iii:set-latest-version' => ['--james-is-cool' => true],
|
||||
|
||||
@@ -285,7 +285,7 @@ class TagController extends Controller
|
||||
$periods = [];
|
||||
$subTitle = (string) trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]);
|
||||
$start = $this->repository->firstUseDate($tag) ?? new Carbon;
|
||||
$end = new Carbon;
|
||||
$end = $this->repository->lastUseDate($tag) ?? new Carbon;
|
||||
$attachments = $this->repository->getAttachments($tag);
|
||||
$path = route('tags.show', [$tag->id, 'all']);
|
||||
$location = $this->repository->getLocation($tag);
|
||||
|
||||
@@ -114,7 +114,8 @@ class Range
|
||||
// ignore preference. set the range to be the current month:
|
||||
if (!app('session')->has('start') && !app('session')->has('end')) {
|
||||
$viewRange = app('preferences')->get('viewRange', '1M')->data;
|
||||
$start = app('navigation')->updateStartDate($viewRange, new Carbon);
|
||||
$today = today(config('app.timezone'));
|
||||
$start = app('navigation')->updateStartDate($viewRange, $today);
|
||||
$end = app('navigation')->updateEndDate($viewRange, $start);
|
||||
|
||||
app('session')->put('start', $start);
|
||||
@@ -124,7 +125,7 @@ class Range
|
||||
/** @var JournalRepositoryInterface $repository */
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$journal = $repository->firstNull();
|
||||
$first = Carbon::now()->startOfYear();
|
||||
$first = today(config('app.timezone'))->startOfYear();
|
||||
|
||||
if (null !== $journal) {
|
||||
$first = $journal->date ?? $first;
|
||||
|
||||
81
app/Http/Requests/BillStoreRequest.php
Normal file
81
app/Http/Requests/BillStoreRequest.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* BillStoreRequest.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
/**
|
||||
* Class BillStoreRequest.
|
||||
*/
|
||||
class BillStoreRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Verify the request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow logged in users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data required by the controller.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBillData(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'amount_min' => $this->string('amount_min'),
|
||||
'currency_id' => $this->integer('transaction_currency_id'),
|
||||
'currency_code' => '',
|
||||
'amount_max' => $this->string('amount_max'),
|
||||
'date' => $this->date('date'),
|
||||
'repeat_freq' => $this->string('repeat_freq'),
|
||||
'skip' => $this->integer('skip'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'active' => $this->boolean('active'),
|
||||
'object_group' => $this->string('object_group'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rules for this request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
|
||||
'amount_min' => 'required|numeric|gt:0|max:1000000000',
|
||||
'amount_max' => 'required|numeric|gt:0|max:1000000000',
|
||||
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
||||
'date' => 'required|date',
|
||||
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
||||
'skip' => 'required|between:0,31',
|
||||
'active' => 'boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* BillFormRequest.php
|
||||
* BillUpdateRequest.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
@@ -25,9 +25,9 @@ namespace FireflyIII\Http\Requests;
|
||||
use FireflyIII\Models\Bill;
|
||||
|
||||
/**
|
||||
* Class BillFormRequest.
|
||||
* Class BillUpdateRequest.
|
||||
*/
|
||||
class BillFormRequest extends Request
|
||||
class BillUpdateRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Verify the request.
|
||||
@@ -58,6 +58,7 @@ class BillFormRequest extends Request
|
||||
'skip' => $this->integer('skip'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'active' => $this->boolean('active'),
|
||||
'object_group' => $this->string('object_group'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -68,24 +69,18 @@ class BillFormRequest extends Request
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$nameRule = 'required|between:1,255|uniqueObjectForUser:bills,name';
|
||||
/** @var Bill $bill */
|
||||
$bill = $this->route()->parameter('bill');
|
||||
if (null !== $bill) {
|
||||
$nameRule = 'required|between:1,255|uniqueObjectForUser:bills,name,' . $bill->id;
|
||||
}
|
||||
// is OK
|
||||
$rules = [
|
||||
'name' => $nameRule,
|
||||
'amount_min' => 'required|numeric|more:0|max:1000000000',
|
||||
'amount_max' => 'required|numeric|more:0|max:1000000000',
|
||||
|
||||
return [
|
||||
'name' => sprintf('required|between:1,255|uniqueObjectForUser:bills,name,%d', $bill->id),
|
||||
'amount_min' => 'required|numeric|gt:0|max:1000000000',
|
||||
'amount_max' => 'required|numeric|gt:0|max:1000000000',
|
||||
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
||||
'date' => 'required|date',
|
||||
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
||||
'skip' => 'required|between:0,31',
|
||||
'active' => 'boolean',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
76
app/Http/Requests/PiggyBankStoreRequest.php
Normal file
76
app/Http/Requests/PiggyBankStoreRequest.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* PiggyBankStoreRequest.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
/**
|
||||
* Class PiggyBankStoreRequest.
|
||||
*/
|
||||
class PiggyBankStoreRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Verify the request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow logged in users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data required by the controller.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPiggyBankData(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'startdate' => $this->date('startdate'),
|
||||
'account_id' => $this->integer('account_id'),
|
||||
'targetamount' => $this->string('targetamount'),
|
||||
'targetdate' => $this->date('targetdate'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'object_group' => $this->string('object_group'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rules for this request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:1,255|uniquePiggyBankForUser',
|
||||
'account_id' => 'required|belongsToUser:accounts',
|
||||
'targetamount' => 'required|numeric|gte:0.01|max:1000000000',
|
||||
'startdate' => 'date',
|
||||
'targetdate' => 'date|nullable',
|
||||
'order' => 'integer|min:1',
|
||||
'object_group' => 'min:0|max:255',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* PiggyBankFormRequest.php
|
||||
* PiggyBankUpdateRequest.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
@@ -27,7 +27,7 @@ use FireflyIII\Models\PiggyBank;
|
||||
/**
|
||||
* Class PiggyBankFormRequest.
|
||||
*/
|
||||
class PiggyBankFormRequest extends Request
|
||||
class PiggyBankUpdateRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Verify the request.
|
||||
@@ -65,24 +65,17 @@ class PiggyBankFormRequest extends Request
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$nameRule = 'required|between:1,255|uniquePiggyBankForUser';
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
$piggy = $this->route()->parameter('piggyBank');
|
||||
|
||||
if (null !== $piggy) {
|
||||
$nameRule = 'required|between:1,255|uniquePiggyBankForUser:' . $piggy->id;
|
||||
}
|
||||
|
||||
$rules = [
|
||||
'name' => $nameRule,
|
||||
return [
|
||||
'name' => sprintf('required|between:1,255|uniquePiggyBankForUser:%d', $piggy->id),
|
||||
'account_id' => 'required|belongsToUser:accounts',
|
||||
'targetamount' => 'required|numeric|gte:0.01|max:1000000000',
|
||||
'startdate' => 'date',
|
||||
'targetdate' => 'date|nullable',
|
||||
'order' => 'integer|min:1',
|
||||
'object_group' => 'min:0|max:255',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ class RecurrenceFormRequest extends Request
|
||||
'transaction_description' => 'required|between:1,255',
|
||||
'transaction_type' => 'required|in:withdrawal,deposit,transfer',
|
||||
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
||||
'amount' => 'numeric|required|more:0|max:1000000000',
|
||||
'amount' => 'numeric|required|gt:0|max:1000000000',
|
||||
// mandatory account info:
|
||||
'source_id' => 'numeric|belongsToUser:accounts,id|nullable',
|
||||
'source_name' => 'between:1,255|nullable',
|
||||
@@ -168,7 +168,7 @@ class RecurrenceFormRequest extends Request
|
||||
'destination_name' => 'between:1,255|nullable',
|
||||
|
||||
// foreign amount data:
|
||||
'foreign_amount' => 'nullable|more:0|max:1000000000',
|
||||
'foreign_amount' => 'nullable|gt:0|max:1000000000',
|
||||
|
||||
// optional fields:
|
||||
'budget_id' => 'mustExist:budgets,id|belongsToUser:budgets,id|nullable',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CreateAutoBudgetLimits.php
|
||||
* Copyright (c) 2020 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Jobs;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SubmitTelemetryData.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Jobs;
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AutoBudget.php
|
||||
* Copyright (c) 2020 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Eloquent;
|
||||
|
||||
@@ -161,6 +161,14 @@ class Bill extends Model
|
||||
return $this->morphMany(Note::class, 'noteable');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the tags for the post.
|
||||
*/
|
||||
public function objectGroups()
|
||||
{
|
||||
return $this->morphToMany(ObjectGroup::class, 'object_groupable');
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Location.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ObjectGroup.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
@@ -56,6 +77,14 @@ class ObjectGroup extends Model
|
||||
return $this->morphedByMany(PiggyBank::class, 'object_groupable');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
public function bills()
|
||||
{
|
||||
return $this->morphedByMany(Bill::class, 'object_groupable');
|
||||
}
|
||||
|
||||
/**
|
||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||
*
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Telemetry.php
|
||||
* Copyright (c) 2020 thegrumpydictator@gmail.com
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ class EventServiceProvider extends ServiceProvider
|
||||
],
|
||||
// is a Transaction Journal related event.
|
||||
UpdatedTransactionGroup::class => [
|
||||
'FireflyIII\Handlers\Events\UpdatedGroupEventHandler@unifyAccounts',
|
||||
'FireflyIII\Handlers\Events\UpdatedGroupEventHandler@processRules',
|
||||
],
|
||||
// API related events:
|
||||
|
||||
@@ -32,6 +32,7 @@ use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
||||
use FireflyIII\Services\Internal\Destroy\BillDestroyService;
|
||||
use FireflyIII\Services\Internal\Update\BillUpdateService;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
@@ -48,8 +49,8 @@ use Storage;
|
||||
*/
|
||||
class BillRepository implements BillRepositoryInterface
|
||||
{
|
||||
/** @var User */
|
||||
private $user;
|
||||
use CreatesObjectGroups;
|
||||
private User $user;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -190,7 +191,10 @@ class BillRepository implements BillRepositoryInterface
|
||||
public function getBills(): Collection
|
||||
{
|
||||
/** @var Collection $set */
|
||||
return $this->user->bills()->orderBy('active', 'DESC')->orderBy('name', 'ASC')->get();
|
||||
return $this->user->bills()
|
||||
->orderBy('order', 'ASC')
|
||||
->orderBy('active', 'DESC')
|
||||
->orderBy('name', 'ASC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -711,4 +715,60 @@ class BillRepository implements BillRepositoryInterface
|
||||
{
|
||||
$this->user->transactionJournals()->where('bill_id', $bill->id)->update(['bill_id' => null]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct order of piggies in case of issues.
|
||||
*/
|
||||
public function correctOrder(): void
|
||||
{
|
||||
$set = $this->user->bills()->orderBy('order', 'ASC')->get();
|
||||
$current = 1;
|
||||
foreach ($set as $bill) {
|
||||
if ((int) $bill->order !== $current) {
|
||||
$bill->order = $current;
|
||||
$bill->save();
|
||||
}
|
||||
$current++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill
|
||||
{
|
||||
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
|
||||
if (null !== $objectGroup) {
|
||||
$bill->objectGroups()->sync([$objectGroup->id]);
|
||||
}
|
||||
|
||||
return $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function removeObjectGroup(Bill $bill): Bill
|
||||
{
|
||||
$bill->objectGroups()->sync([]);
|
||||
|
||||
return $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setOrder(Bill $bill, int $order): void
|
||||
{
|
||||
$bill->order = $order;
|
||||
$bill->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function destroyAll(): void
|
||||
{
|
||||
$this->user->bills()->delete();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user