mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
Merge branch 'release/4.7.5.1'
This commit is contained in:
@@ -16,8 +16,8 @@ mkdir -p $FIREFLY_PATH/storage/upload
|
||||
|
||||
|
||||
# make sure we own the volumes:
|
||||
chown -R www-data:www-data -R $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/logs $FIREFLY_PATH/storage/framework/cache
|
||||
chmod -R 775 $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/logs $FIREFLY_PATH/storage/framework/cache
|
||||
chown -R www-data:www-data -R $FIREFLY_PATH/storage
|
||||
chmod -R 775 $FIREFLY_PATH/storage
|
||||
|
||||
# remove any lingering files that may break upgrades:
|
||||
rm -f $FIREFLY_PATH/storage/logs/laravel.log
|
||||
|
@@ -1,4 +1,3 @@
|
||||
# Ignore composer specific files and vendor folder
|
||||
composer.phar
|
||||
composer.lock
|
||||
vendor
|
||||
|
@@ -1,3 +1,12 @@
|
||||
# 4.7.5.1
|
||||
- [Issue 1531](https://github.com/firefly-iii/firefly-iii/issues/1531), the database routine incorrectly reports empty categories.
|
||||
- [Issue 1532](https://github.com/firefly-iii/firefly-iii/issues/1532), broken dropdown for autosuggest things.
|
||||
- [Issue 1533](https://github.com/firefly-iii/firefly-iii/issues/1533), fix where the import could not import category names.
|
||||
- [Issue 1538](https://github.com/firefly-iii/firefly-iii/issues/1538), fix a bug where Spectre would not work when ignoring rules.
|
||||
- [Issue 1542](https://github.com/firefly-iii/firefly-iii/issues/1542), fix a bug where the importer was incapable of generating new currencies.
|
||||
- [Issue 1541](https://github.com/firefly-iii/firefly-iii/issues/1541), no longer ignore composer.lock in Docker ignore.
|
||||
- Bills are stored inactive.
|
||||
|
||||
# 4.7.5
|
||||
- A new feature called "recurring transactions" that will make Firefly III automatically create transactions for you.
|
||||
- New API end points for attachments, available budgets, budgets, budget limits, categories, configuration, currency exchange rates, journal links, link types, piggy banks, preferences, recurring transactions, rules, rule groups and tags.
|
||||
|
@@ -16,7 +16,7 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
manifest = (
|
||||
appTitle = (defaultText = "Firefly III"),
|
||||
appVersion = 14,
|
||||
appMarketingVersion = (defaultText = "4.7.5"),
|
||||
appMarketingVersion = (defaultText = "4.7.5.1"),
|
||||
|
||||
actions = [
|
||||
# Define your "new document" handlers here.
|
||||
|
@@ -35,7 +35,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
/**
|
||||
* Returns basic information about this installation.
|
||||
*
|
||||
* Class AboutController
|
||||
* Class AboutController.
|
||||
*/
|
||||
class AboutController extends Controller
|
||||
{
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AccountController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -41,13 +40,15 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
* Class AccountController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class AccountController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface */
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $currencyRepository;
|
||||
/** @var AccountRepositoryInterface */
|
||||
/** @var AccountRepositoryInterface The account repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
@@ -125,6 +126,8 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Show single instance.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
*
|
||||
@@ -146,6 +149,8 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new instance.
|
||||
*
|
||||
* @param AccountRequest $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
@@ -197,52 +202,25 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* All the available types.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mapTypes(string $type): array
|
||||
{
|
||||
$types = [
|
||||
'all' => [
|
||||
AccountType::DEFAULT,
|
||||
AccountType::CASH,
|
||||
AccountType::ASSET,
|
||||
AccountType::EXPENSE,
|
||||
AccountType::REVENUE,
|
||||
AccountType::INITIAL_BALANCE,
|
||||
AccountType::BENEFICIARY,
|
||||
AccountType::IMPORT,
|
||||
AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,
|
||||
],
|
||||
'asset' => [
|
||||
AccountType::DEFAULT,
|
||||
AccountType::ASSET,
|
||||
],
|
||||
'cash' => [
|
||||
AccountType::CASH,
|
||||
],
|
||||
'expense' => [
|
||||
AccountType::EXPENSE,
|
||||
AccountType::BENEFICIARY,
|
||||
],
|
||||
'revenue' => [
|
||||
AccountType::REVENUE,
|
||||
],
|
||||
'special' => [
|
||||
AccountType::CASH,
|
||||
AccountType::INITIAL_BALANCE,
|
||||
AccountType::IMPORT,
|
||||
AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,
|
||||
],
|
||||
'hidden' => [
|
||||
AccountType::INITIAL_BALANCE,
|
||||
AccountType::IMPORT,
|
||||
AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,
|
||||
],
|
||||
$types = [
|
||||
'all' => [AccountType::DEFAULT, AccountType::CASH, AccountType::ASSET, AccountType::EXPENSE, AccountType::REVENUE,
|
||||
AccountType::INITIAL_BALANCE, AccountType::BENEFICIARY, AccountType::IMPORT, AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,],
|
||||
'asset' => [AccountType::DEFAULT, AccountType::ASSET,],
|
||||
'cash' => [AccountType::CASH,],
|
||||
'expense' => [AccountType::EXPENSE, AccountType::BENEFICIARY,],
|
||||
'revenue' => [AccountType::REVENUE,],
|
||||
'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,],
|
||||
'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION, AccountType::LOAN,],
|
||||
AccountType::DEFAULT => [AccountType::DEFAULT],
|
||||
AccountType::CASH => [AccountType::CASH],
|
||||
AccountType::ASSET => [AccountType::ASSET],
|
||||
@@ -254,10 +232,11 @@ class AccountController extends Controller
|
||||
AccountType::RECONCILIATION => [AccountType::RECONCILIATION],
|
||||
AccountType::LOAN => [AccountType::LOAN],
|
||||
];
|
||||
$return = $types['all'];
|
||||
if (isset($types[$type])) {
|
||||
return $types[$type];
|
||||
$return = $types[$type];
|
||||
}
|
||||
|
||||
return $types['all']; // @codeCoverageIgnore
|
||||
return $return; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
@@ -41,11 +41,13 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class AttachmentController
|
||||
* Class AttachmentController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class AttachmentController extends Controller
|
||||
{
|
||||
/** @var AttachmentRepositoryInterface */
|
||||
/** @var AttachmentRepositoryInterface The attachment repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
@@ -81,6 +83,8 @@ class AttachmentController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Download an attachment.
|
||||
*
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return LaravelResponse
|
||||
@@ -88,7 +92,7 @@ class AttachmentController extends Controller
|
||||
*/
|
||||
public function download(Attachment $attachment): LaravelResponse
|
||||
{
|
||||
if ($attachment->uploaded === false) {
|
||||
if (false === $attachment->uploaded) {
|
||||
throw new FireflyException('No file has been uploaded for this attachment (yet).');
|
||||
}
|
||||
if ($this->repository->exists($attachment)) {
|
||||
@@ -211,6 +215,8 @@ class AttachmentController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload an attachment.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\AvailableBudgetRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
@@ -39,13 +40,15 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class AvailableBudgetController
|
||||
* Class AvailableBudgetController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class AvailableBudgetController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface */
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $currencyRepository;
|
||||
/** @var BudgetRepositoryInterface */
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
@@ -144,11 +147,15 @@ class AvailableBudgetController extends Controller
|
||||
* @param AvailableBudgetRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(AvailableBudgetRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$currency = $this->currencyRepository->findNull($data['transaction_currency_id']);
|
||||
$data = $request->getAll();
|
||||
$currency = $this->currencyRepository->findNull($data['transaction_currency_id']);
|
||||
if (null === $currency) {
|
||||
throw new FireflyException('Could not find the indicated currency.');
|
||||
}
|
||||
$availableBudget = $this->repository->setAvailableBudget($currency, $data['start_date'], $data['end_date'], $data['amount']);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -39,11 +40,11 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class BillController
|
||||
* Class BillController.
|
||||
*/
|
||||
class BillController extends Controller
|
||||
{
|
||||
/** @var BillRepositoryInterface */
|
||||
/** @var BillRepositoryInterface The bill repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
@@ -54,9 +55,12 @@ class BillController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BillRepositoryInterface repository */
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -103,6 +107,8 @@ class BillController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Show the specified bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
@@ -124,6 +130,8 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a bill.
|
||||
*
|
||||
* @param BillRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
@@ -147,6 +155,8 @@ class BillController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Update a bill.
|
||||
*
|
||||
* @param BillRequest $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Transformers\BudgetTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@@ -38,11 +39,13 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class BudgetController
|
||||
* Class BudgetController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
/** @var BudgetRepositoryInterface */
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
@@ -53,9 +56,12 @@ class BudgetController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BudgetRepositoryInterface repository */
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -111,6 +117,8 @@ class BudgetController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Show a budget.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
@@ -132,6 +140,8 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a budget.
|
||||
*
|
||||
* @param BudgetRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
@@ -154,6 +164,8 @@ class BudgetController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Update a budget.
|
||||
*
|
||||
* @param BudgetRequest $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
|
@@ -24,8 +24,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use FireflyIII\Api\V1\Requests\AvailableBudgetRequest;
|
||||
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
@@ -43,16 +41,15 @@ use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class BudgetLimitController
|
||||
* Class BudgetLimitController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class BudgetLimitController extends Controller
|
||||
{
|
||||
///** @var CurrencyRepositoryInterface */
|
||||
//private $currencyRepository;
|
||||
/** @var BudgetRepositoryInterface */
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
@@ -66,7 +63,6 @@ class BudgetLimitController extends Controller
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
//$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
@@ -97,40 +93,30 @@ class BudgetLimitController extends Controller
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// read budget from request
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$start = null;
|
||||
$end = null;
|
||||
$budgetId = (int)($request->get('budget_id') ?? 0);
|
||||
$budget = null;
|
||||
if ($budgetId > 0) {
|
||||
$budget = $this->repository->findNull($budgetId);
|
||||
}
|
||||
// read start date from request
|
||||
$start = null;
|
||||
$budget = $this->repository->findNull($budgetId);
|
||||
$this->parameters->set('budget_id', $budgetId);
|
||||
|
||||
try {
|
||||
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
|
||||
$this->parameters->set('start', $start->format('Y-m-d'));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::debug(sprintf('Could not parse start date "%s": %s', $request->get('start'), $e->getMessage()));
|
||||
|
||||
Log::debug(sprintf('Invalid date: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
// read end date from request
|
||||
$end = null;
|
||||
try {
|
||||
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
|
||||
$this->parameters->set('end', $end->format('Y-m-d'));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::debug(sprintf('Could not parse end date "%s": %s', $request->get('end'), $e->getMessage()));
|
||||
Log::debug(sprintf('Invalid date: %s', $e->getMessage()));
|
||||
}
|
||||
$this->parameters->set('budget_id', $budgetId);
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of budget limits. Count it and split it.
|
||||
$collection = new Collection;
|
||||
if (null === $budget) {
|
||||
$collection = $this->repository->getAllBudgetLimits($start, $end);
|
||||
@@ -141,12 +127,9 @@ class BudgetLimitController extends Controller
|
||||
|
||||
$count = $collection->count();
|
||||
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($budgetLimits, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
@@ -206,8 +189,8 @@ class BudgetLimitController extends Controller
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param AvailableBudgetRequest $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
* @param BudgetLimitRequest $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Transformers\CategoryTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@@ -38,11 +39,13 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class CategoryController
|
||||
* Class CategoryController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
/** @var CategoryRepositoryInterface */
|
||||
/** @var CategoryRepositoryInterface The category repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
@@ -53,9 +56,12 @@ class CategoryController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CategoryRepositoryInterface repository */
|
||||
$this->repository = app(CategoryRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -111,6 +117,8 @@ class CategoryController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Show the category.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Category $category
|
||||
*
|
||||
@@ -132,6 +140,8 @@ class CategoryController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new category.
|
||||
*
|
||||
* @param CategoryRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
@@ -154,6 +164,8 @@ class CategoryController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Update the category.
|
||||
*
|
||||
* @param CategoryRequest $request
|
||||
* @param Category $category
|
||||
*
|
||||
|
@@ -25,39 +25,66 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Class ConfigurationController
|
||||
* Class ConfigurationController.
|
||||
*/
|
||||
class ConfigurationController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
* BudgetController constructor.
|
||||
*/
|
||||
public function index()
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @noinspection UnusedConstructorDependenciesInspection */
|
||||
$this->repository = app(UserRepositoryInterface::class);
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->repository->hasRole($admin, 'owner')) {
|
||||
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all configuration.
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
if (!auth()->user()->hasRole('owner')) {
|
||||
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
||||
}
|
||||
$configData = $this->getConfigData();
|
||||
|
||||
return response()->json(['data' => $configData], 200)->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the configuration.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function update(Request $request): JsonResponse
|
||||
{
|
||||
if (!auth()->user()->hasRole('owner')) {
|
||||
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
||||
}
|
||||
$name = $request->get('name');
|
||||
$value = $request->get('value');
|
||||
$valid = ['is_demo_site', 'permission_update_check', 'single_user_mode'];
|
||||
@@ -68,7 +95,7 @@ class ConfigurationController extends Controller
|
||||
switch ($name) {
|
||||
case 'is_demo_site':
|
||||
case 'single_user_mode':
|
||||
$configValue = $value === 'true';
|
||||
$configValue = 'true' === $value;
|
||||
break;
|
||||
case 'permission_update_check':
|
||||
$configValue = (int)$value >= -1 && (int)$value <= 1 ? (int)$value : -1;
|
||||
@@ -81,7 +108,10 @@ class ConfigurationController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all config values.
|
||||
*
|
||||
* @return array
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
private function getConfigData(): array
|
||||
{
|
||||
|
@@ -37,12 +37,13 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
* Class Controller.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
||||
*/
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
|
||||
/** @var ParameterBag */
|
||||
/** @var ParameterBag Parameters from the URI are stored here. */
|
||||
protected $parameters;
|
||||
|
||||
/**
|
||||
@@ -56,39 +57,42 @@ class Controller extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to help build URI's.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
protected function buildParams(): string
|
||||
{
|
||||
$return = '?';
|
||||
$params = [];
|
||||
foreach ($this->parameters as $key => $value) {
|
||||
if ($key === 'page') {
|
||||
if ('page' === $key) {
|
||||
continue;
|
||||
}
|
||||
if ($value instanceof Carbon) {
|
||||
$params[$key] = $value->format('Y-m-d');
|
||||
continue;
|
||||
}
|
||||
if (!$value instanceof Carbon) {
|
||||
$params[$key] = $value;
|
||||
}
|
||||
$params[$key] = $value;
|
||||
}
|
||||
$return .= http_build_query($params);
|
||||
if (\strlen($return) === 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to grab all parameters from the URI.
|
||||
*
|
||||
* @return ParameterBag
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
private function getParameters(): ParameterBag
|
||||
{
|
||||
$bag = new ParameterBag;
|
||||
$page = (int)request()->get('page');
|
||||
if ($page === 0) {
|
||||
if (0 === $page) {
|
||||
$page = 1;
|
||||
}
|
||||
$bag->set('page', $page);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Transformers\CurrencyTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@@ -40,29 +41,32 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class CurrencyController
|
||||
* Class CurrencyController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class CurrencyController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface */
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $repository;
|
||||
/** @var UserRepositoryInterface */
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
private $userRepository;
|
||||
|
||||
/**
|
||||
* CurrencyRepository constructor.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CurrencyRepositoryInterface repository */
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -79,7 +83,10 @@ class CurrencyController extends Controller
|
||||
*/
|
||||
public function delete(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
if (!$this->userRepository->hasRole(auth()->user(), 'owner')) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
// access denied:
|
||||
throw new FireflyException('No access to method, user is not owner.'); // @codeCoverageIgnore
|
||||
}
|
||||
@@ -123,6 +130,8 @@ class CurrencyController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Show a currency.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
@@ -146,6 +155,8 @@ class CurrencyController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new currency.
|
||||
*
|
||||
* @param CurrencyRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
@@ -155,11 +166,11 @@ class CurrencyController extends Controller
|
||||
{
|
||||
$currency = $this->repository->store($request->getAll());
|
||||
|
||||
if ($request->boolean('default') === true) {
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
}
|
||||
if (null !== $currency) {
|
||||
if (true === $request->boolean('default')) {
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
}
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
@@ -176,6 +187,8 @@ class CurrencyController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Update a currency.
|
||||
*
|
||||
* @param CurrencyRequest $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
@@ -186,7 +199,7 @@ class CurrencyController extends Controller
|
||||
$data = $request->getAll();
|
||||
$currency = $this->repository->update($currency, $data);
|
||||
|
||||
if ($request->boolean('default') === true) {
|
||||
if (true === $request->boolean('default')) {
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
}
|
||||
|
@@ -28,20 +28,19 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Services\Currency\ExchangeRateInterface;
|
||||
use FireflyIII\Transformers\CurrencyExchangeRateTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use InvalidArgumentException;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Log;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class CurrencyExchangeRateController
|
||||
*/
|
||||
class CurrencyExchangeRateController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface */
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
@@ -52,8 +51,11 @@ class CurrencyExchangeRateController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -62,6 +64,8 @@ class CurrencyExchangeRateController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an exchange rate.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
@@ -72,8 +76,8 @@ class CurrencyExchangeRateController extends Controller
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// currencies
|
||||
$fromCurrency = $this->repository->findByCodeNull($request->get('from') ?? 'EUR');
|
||||
$toCurrency = $this->repository->findByCodeNull($request->get('to') ?? 'USD');
|
||||
|
||||
@@ -84,27 +88,19 @@ class CurrencyExchangeRateController extends Controller
|
||||
throw new FireflyException('Unknown destination currency.');
|
||||
}
|
||||
|
||||
$dateObj = new Carbon;
|
||||
try {
|
||||
$dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d'));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::debug($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
$dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d'));
|
||||
$this->parameters->set('from', $fromCurrency->code);
|
||||
$this->parameters->set('to', $toCurrency->code);
|
||||
$this->parameters->set('date', $dateObj->format('Y-m-d'));
|
||||
|
||||
// get the exchange rate.
|
||||
$rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj);
|
||||
if (null === $rate) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
// create service:
|
||||
/** @var ExchangeRateInterface $service */
|
||||
$service = app(ExchangeRateInterface::class);
|
||||
$service->setUser(auth()->user());
|
||||
|
||||
// get rate:
|
||||
$service->setUser($admin);
|
||||
$rate = $service->getRate($fromCurrency, $toCurrency, $dateObj);
|
||||
}
|
||||
|
||||
|
@@ -39,13 +39,21 @@ use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class JournalLinkController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class JournalLinkController extends Controller
|
||||
{
|
||||
/** @var JournalRepositoryInterface */
|
||||
/** @var JournalRepositoryInterface The journal repository */
|
||||
private $journalRepository;
|
||||
/** @var LinkTypeRepositoryInterface */
|
||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* JournalLinkController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -175,6 +183,8 @@ class JournalLinkController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object.
|
||||
*
|
||||
* @param JournalLinkRequest $request
|
||||
* @param TransactionJournalLink $journalLink
|
||||
*
|
||||
|
@@ -40,17 +40,21 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class LinkTypeController.
|
||||
*
|
||||
* Class LinkTypeController
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class LinkTypeController extends Controller
|
||||
{
|
||||
/** @var LinkTypeRepositoryInterface */
|
||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||
private $repository;
|
||||
|
||||
/** @var UserRepositoryInterface */
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
private $userRepository;
|
||||
|
||||
/**
|
||||
* LinkTypeController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -77,7 +81,7 @@ class LinkTypeController extends Controller
|
||||
*/
|
||||
public function delete(LinkType $linkType): JsonResponse
|
||||
{
|
||||
if ($linkType->editable === false) {
|
||||
if (false === $linkType->editable) {
|
||||
throw new FireflyException(sprintf('You cannot delete this link type (#%d, "%s")', $linkType->id, $linkType->name));
|
||||
}
|
||||
$this->repository->destroy($linkType, null);
|
||||
@@ -151,7 +155,10 @@ class LinkTypeController extends Controller
|
||||
*/
|
||||
public function store(LinkTypeRequest $request): JsonResponse
|
||||
{
|
||||
if (!$this->userRepository->hasRole(auth()->user(), 'owner')) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
throw new FireflyException('You need the "owner"-role to do this.');
|
||||
}
|
||||
$data = $request->getAll();
|
||||
@@ -168,6 +175,8 @@ class LinkTypeController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object.
|
||||
*
|
||||
* @param LinkTypeRequest $request
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
@@ -176,10 +185,14 @@ class LinkTypeController extends Controller
|
||||
*/
|
||||
public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse
|
||||
{
|
||||
if ($linkType->editable === false) {
|
||||
if (false === $linkType->editable) {
|
||||
throw new FireflyException(sprintf('You cannot edit this link type (#%d, "%s")', $linkType->id, $linkType->name));
|
||||
}
|
||||
if (!$this->userRepository->hasRole(auth()->user(), 'owner')) {
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
throw new FireflyException('You need the "owner"-role to do this.');
|
||||
}
|
||||
|
||||
|
@@ -39,24 +39,30 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* TODO order up and down.
|
||||
* Class PiggyBankController
|
||||
* Class PiggyBankController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class PiggyBankController extends Controller
|
||||
{
|
||||
|
||||
/** @var PiggyBankRepositoryInterface */
|
||||
/** @var PiggyBankRepositoryInterface The piggy bank repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* PiggyBankController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
$this->repository = app(PiggyBankRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -160,6 +166,8 @@ class PiggyBankController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Update piggy bank.
|
||||
*
|
||||
* @param PiggyBankRequest $request
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
|
@@ -42,20 +42,6 @@ use Preferences;
|
||||
*/
|
||||
class PreferenceController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
// todo add local repositories.
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
@@ -116,10 +102,13 @@ class PreferenceController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a preference.
|
||||
*
|
||||
* @param PreferenceRequest $request
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function update(PreferenceRequest $request, Preference $preference): JsonResponse
|
||||
{
|
||||
@@ -138,7 +127,7 @@ class PreferenceController extends Controller
|
||||
break;
|
||||
case 'customFiscalYear':
|
||||
case 'twoFactorAuthEnabled':
|
||||
$newValue = (int)$data['data'] === 1;
|
||||
$newValue = 1 === (int)$data['data'];
|
||||
break;
|
||||
}
|
||||
$result = Preferences::set($preference->name, $newValue);
|
||||
|
@@ -38,14 +38,16 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class RecurrenceController
|
||||
*/
|
||||
class RecurrenceController extends Controller
|
||||
{
|
||||
/** @var RecurringRepositoryInterface */
|
||||
/** @var RecurringRepositoryInterface The recurring transaction repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* RecurrenceController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -155,6 +157,8 @@ class RecurrenceController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Update single recurrence.
|
||||
*
|
||||
* @param RecurrenceRequest $request
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
@@ -163,9 +167,6 @@ class RecurrenceController extends Controller
|
||||
public function update(RecurrenceRequest $request, Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
|
||||
//
|
||||
|
||||
$category = $this->repository->update($recurrence, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
@@ -42,9 +42,12 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class RuleController extends Controller
|
||||
{
|
||||
/** @var RuleRepositoryInterface */
|
||||
/** @var RuleRepositoryInterface The rule repository */
|
||||
private $ruleRepository;
|
||||
|
||||
/**
|
||||
* RuleController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -136,7 +139,7 @@ class RuleController extends Controller
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param RuleRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
@@ -153,6 +156,8 @@ class RuleController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a rule.
|
||||
*
|
||||
* @param RuleRequest $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
@@ -160,9 +165,9 @@ class RuleController extends Controller
|
||||
*/
|
||||
public function update(RuleRequest $request, Rule $rule): JsonResponse
|
||||
{
|
||||
$rule = $this->ruleRepository->update($rule, $request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$rule = $this->ruleRepository->update($rule, $request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
||||
|
@@ -38,11 +38,17 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
|
||||
/**
|
||||
* Class RuleGroupController
|
||||
*/
|
||||
class RuleGroupController extends Controller
|
||||
{
|
||||
/** @var RuleGroupRepositoryInterface */
|
||||
/** @var RuleGroupRepositoryInterface The rule group repository */
|
||||
private $ruleGroupRepository;
|
||||
|
||||
/**
|
||||
* RuleGroupController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
@@ -62,7 +68,7 @@ class RuleGroupController extends Controller
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param string $object
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
@@ -151,8 +157,10 @@ class RuleGroupController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param string $object
|
||||
* Update a rule group.
|
||||
*
|
||||
* @param RuleGroupRequest $request
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\TransactionRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Helpers\Filter\NegativeAmountFilter;
|
||||
@@ -33,36 +34,39 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class TransactionController
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class TransactionController extends Controller
|
||||
{
|
||||
|
||||
/** @var JournalRepositoryInterface */
|
||||
/** @var JournalRepositoryInterface The journal repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* TransactionController constructor.
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var JournalRepositoryInterface repository */
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -74,9 +78,9 @@ class TransactionController extends Controller
|
||||
*
|
||||
* @param \FireflyIII\Models\Transaction $transaction
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(Transaction $transaction)
|
||||
public function delete(Transaction $transaction): JsonResponse
|
||||
{
|
||||
$journal = $transaction->transactionJournal;
|
||||
$this->repository->destroy($journal);
|
||||
@@ -85,33 +89,32 @@ class TransactionController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// read type from URI
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
// types to get, page size:
|
||||
$types = $this->mapTypes($this->parameters->get('type'));
|
||||
|
||||
$types = $this->mapTypes($this->parameters->get('type'));
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// collect transactions using the journal collector
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
|
||||
// remove internal transfer filter:
|
||||
if (\in_array(TransactionType::TRANSFER, $types)) {
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
@@ -124,7 +127,6 @@ class TransactionController extends Controller
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
@@ -133,13 +135,15 @@ class TransactionController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Show a single transaction.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Transaction $transaction
|
||||
* @param string $include
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Transaction $transaction, string $include = null)
|
||||
public function show(Request $request, Transaction $transaction, string $include = null): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
@@ -173,13 +177,16 @@ class TransactionController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new transaction.
|
||||
*
|
||||
* @param TransactionRequest $request
|
||||
*
|
||||
* @param JournalRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws FireflyException
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(TransactionRequest $request, JournalRepositoryInterface $repository)
|
||||
public function store(TransactionRequest $request, JournalRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user()->id;
|
||||
@@ -217,23 +224,21 @@ class TransactionController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Update a transaction.
|
||||
*
|
||||
* @param TransactionRequest $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
* @param Transaction $transaction
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction)
|
||||
public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user()->id;
|
||||
|
||||
Log::debug('Inside transaction update');
|
||||
|
||||
$journal = $repository->update($transaction->transactionJournal, $data);
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$journal = $repository->update($transaction->transactionJournal, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
@@ -265,72 +270,38 @@ class TransactionController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* All the types you can request.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mapTypes(string $type): array
|
||||
{
|
||||
$types = [
|
||||
'all' => [
|
||||
TransactionType::WITHDRAWAL,
|
||||
TransactionType::DEPOSIT,
|
||||
TransactionType::TRANSFER,
|
||||
TransactionType::OPENING_BALANCE,
|
||||
TransactionType::RECONCILIATION,
|
||||
],
|
||||
'withdrawal' => [
|
||||
TransactionType::WITHDRAWAL,
|
||||
],
|
||||
'withdrawals' => [
|
||||
TransactionType::WITHDRAWAL,
|
||||
],
|
||||
'expense' => [
|
||||
TransactionType::WITHDRAWAL,
|
||||
],
|
||||
'income' => [
|
||||
TransactionType::DEPOSIT,
|
||||
],
|
||||
'deposit' => [
|
||||
TransactionType::DEPOSIT,
|
||||
],
|
||||
'deposits' => [
|
||||
TransactionType::DEPOSIT,
|
||||
],
|
||||
'transfer' => [
|
||||
TransactionType::TRANSFER,
|
||||
],
|
||||
'transfers' => [
|
||||
TransactionType::TRANSFER,
|
||||
],
|
||||
'opening_balance' => [
|
||||
TransactionType::OPENING_BALANCE,
|
||||
],
|
||||
'reconciliation' => [
|
||||
TransactionType::RECONCILIATION,
|
||||
],
|
||||
'reconciliations' => [
|
||||
TransactionType::RECONCILIATION,
|
||||
],
|
||||
'special' => [
|
||||
TransactionType::OPENING_BALANCE,
|
||||
TransactionType::RECONCILIATION,
|
||||
],
|
||||
'specials' => [
|
||||
TransactionType::OPENING_BALANCE,
|
||||
TransactionType::RECONCILIATION,
|
||||
],
|
||||
'default' => [
|
||||
TransactionType::WITHDRAWAL,
|
||||
TransactionType::DEPOSIT,
|
||||
TransactionType::TRANSFER,
|
||||
],
|
||||
$types = [
|
||||
'all' => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE,
|
||||
TransactionType::RECONCILIATION,],
|
||||
'withdrawal' => [TransactionType::WITHDRAWAL,],
|
||||
'withdrawals' => [TransactionType::WITHDRAWAL,],
|
||||
'expense' => [TransactionType::WITHDRAWAL,],
|
||||
'income' => [TransactionType::DEPOSIT,],
|
||||
'deposit' => [TransactionType::DEPOSIT,],
|
||||
'deposits' => [TransactionType::DEPOSIT,],
|
||||
'transfer' => [TransactionType::TRANSFER,],
|
||||
'transfers' => [TransactionType::TRANSFER,],
|
||||
'opening_balance' => [TransactionType::OPENING_BALANCE,],
|
||||
'reconciliation' => [TransactionType::RECONCILIATION,],
|
||||
'reconciliations' => [TransactionType::RECONCILIATION,],
|
||||
'special' => [TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,],
|
||||
'specials' => [TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,],
|
||||
'default' => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER,],
|
||||
];
|
||||
$return = $types['default'];
|
||||
if (isset($types[$type])) {
|
||||
return $types[$type];
|
||||
$return = $types[$type];
|
||||
}
|
||||
|
||||
return $types['default']; // @codeCoverageIgnore
|
||||
return $return;
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Transformers\UserTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
@@ -39,18 +40,18 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
|
||||
/**
|
||||
* Class UserController
|
||||
* Class UserController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class UserController extends Controller
|
||||
{
|
||||
|
||||
/** @var UserRepositoryInterface */
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* UserController constructor.
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -70,12 +71,14 @@ class UserController extends Controller
|
||||
*
|
||||
* @param \FireflyIII\User $user
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function delete(User $user)
|
||||
public function delete(User $user): JsonResponse
|
||||
{
|
||||
if (auth()->user()->hasRole('owner')) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
if ($this->repository->hasRole($admin, 'owner')) {
|
||||
$this->repository->destroy($user);
|
||||
|
||||
return response()->json([], 204);
|
||||
@@ -88,9 +91,9 @@ class UserController extends Controller
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// user preferences
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
@@ -117,12 +120,14 @@ class UserController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a single user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, User $user)
|
||||
public function show(Request $request, User $user): JsonResponse
|
||||
{
|
||||
// make manager
|
||||
$manager = new Manager();
|
||||
@@ -140,11 +145,13 @@ class UserController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new user.
|
||||
*
|
||||
* @param UserRequest $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(UserRequest $request)
|
||||
public function store(UserRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$user = $this->repository->store($data);
|
||||
@@ -165,12 +172,14 @@ class UserController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a user.
|
||||
*
|
||||
* @param UserRequest $request
|
||||
* @param User $user
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(UserRequest $request, User $user)
|
||||
public function update(UserRequest $request, User $user): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$user = $this->repository->update($user, $data);
|
||||
|
@@ -23,7 +23,6 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
/**
|
||||
* Class AccountRequest
|
||||
*/
|
||||
@@ -31,6 +30,8 @@ class AccountRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -40,6 +41,8 @@ class AccountRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -67,6 +70,8 @@ class AccountRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -26,7 +26,6 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Rules\IsBase64;
|
||||
use FireflyIII\Rules\IsValidAttachmentModel;
|
||||
|
||||
/**
|
||||
@@ -35,6 +34,8 @@ use FireflyIII\Rules\IsValidAttachmentModel;
|
||||
class AttachmentRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -44,6 +45,8 @@ class AttachmentRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -58,6 +61,8 @@ class AttachmentRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -29,6 +29,8 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
class AvailableBudgetRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -38,6 +40,8 @@ class AvailableBudgetRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -51,6 +55,9 @@ class AvailableBudgetRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO must also accept currency code.
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -33,6 +33,8 @@ class BillRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -42,6 +44,8 @@ class BillRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -64,6 +68,8 @@ class BillRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -30,6 +30,8 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
class BudgetLimitRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -39,6 +41,8 @@ class BudgetLimitRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -52,6 +56,8 @@ class BudgetLimitRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -31,6 +31,8 @@ use FireflyIII\Models\Budget;
|
||||
class BudgetRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -40,6 +42,8 @@ class BudgetRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -52,6 +56,8 @@ class BudgetRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -31,6 +31,8 @@ use FireflyIII\Models\Category;
|
||||
class CategoryRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -40,6 +42,8 @@ class CategoryRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -51,6 +55,8 @@ class CategoryRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -30,6 +30,8 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
class CurrencyRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -39,6 +41,8 @@ class CurrencyRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -53,6 +57,8 @@ class CurrencyRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
@@ -62,7 +68,7 @@ class CurrencyRequest extends Request
|
||||
'code' => 'required|between:3,3|unique:transaction_currencies,code',
|
||||
'symbol' => 'required|between:1,5|unique:transaction_currencies,symbol',
|
||||
'decimal_places' => 'required|between:0,20|numeric|min:0|max:20',
|
||||
'default' => 'in:true,false',
|
||||
'default' => 'boolean',
|
||||
];
|
||||
|
||||
switch ($this->method()) {
|
||||
|
@@ -31,6 +31,8 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
class JournalLinkRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -40,6 +42,8 @@ class JournalLinkRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -53,6 +57,11 @@ class JournalLinkRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO include link-type name as optional parameter.
|
||||
* TODO be consistent and remove notes from this object.
|
||||
*
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -33,6 +33,8 @@ use Illuminate\Validation\Rule;
|
||||
class LinkTypeRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -42,6 +44,8 @@ class LinkTypeRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -56,6 +60,8 @@ class LinkTypeRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -33,6 +33,8 @@ use FireflyIII\Rules\IsAssetAccountId;
|
||||
class PiggyBankRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -42,6 +44,8 @@ class PiggyBankRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -58,6 +62,8 @@ class PiggyBankRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -32,6 +32,8 @@ class PreferenceRequest extends Request
|
||||
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -40,6 +42,11 @@ class PreferenceRequest extends Request
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
@@ -47,6 +54,11 @@ class PreferenceRequest extends Request
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
|
@@ -24,20 +24,21 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Validation\RecurrenceValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Validation\Validator;
|
||||
use InvalidArgumentException;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RecurrenceRequest
|
||||
*/
|
||||
class RecurrenceRequest extends Request
|
||||
{
|
||||
use RecurrenceValidation, TransactionValidation;
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -47,6 +48,8 @@ class RecurrenceRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -67,55 +70,16 @@ class RecurrenceRequest extends Request
|
||||
'piggy_bank_name' => $this->string('piggy_bank_name'),
|
||||
'tags' => explode(',', $this->string('tags')),
|
||||
],
|
||||
'transactions' => [],
|
||||
'repetitions' => [],
|
||||
'transactions' => $this->getTransactionData(),
|
||||
'repetitions' => $this->getRepetitionData(),
|
||||
];
|
||||
|
||||
// repetition data:
|
||||
/** @var array $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$return['repetitions'][] = [
|
||||
'type' => $repetition['type'],
|
||||
'moment' => $repetition['moment'],
|
||||
'skip' => (int)$repetition['skip'],
|
||||
'weekend' => (int)$repetition['weekend'],
|
||||
];
|
||||
}
|
||||
// transaction data:
|
||||
/** @var array $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return['transactions'][] = [
|
||||
'amount' => $transaction['amount'],
|
||||
|
||||
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
|
||||
'currency_code' => $transaction['currency_code'] ?? null,
|
||||
|
||||
'foreign_amount' => $transaction['foreign_amount'] ?? null,
|
||||
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
|
||||
|
||||
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
|
||||
'budget_name' => $transaction['budget_name'] ?? null,
|
||||
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
|
||||
'category_name' => $transaction['category_name'] ?? null,
|
||||
|
||||
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
|
||||
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
|
||||
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
|
||||
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
|
||||
|
||||
'description' => $transaction['description'],
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
@@ -132,18 +96,12 @@ class RecurrenceRequest extends Request
|
||||
'nr_of_repetitions' => 'numeric|between:1,31',
|
||||
'apply_rules' => 'required|boolean',
|
||||
'active' => 'required|boolean',
|
||||
|
||||
// rules for meta values:
|
||||
'tags' => 'between:1,64000',
|
||||
'piggy_bank_id' => 'numeric',
|
||||
|
||||
// rules for repetitions.
|
||||
'repetitions.*.type' => 'required|in:daily,weekly,ndom,monthly,yearly',
|
||||
'repetitions.*.moment' => 'between:0,10',
|
||||
'repetitions.*.skip' => 'required|numeric|between:0,31',
|
||||
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
|
||||
|
||||
// rules for transactions.
|
||||
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code',
|
||||
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id',
|
||||
'transactions.*.foreign_amount' => 'numeric|more:0',
|
||||
@@ -171,312 +129,76 @@ class RecurrenceRequest extends Request
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->atLeastOneTransaction($validator);
|
||||
$this->atLeastOneRepetition($validator);
|
||||
$this->validRepeatsUntil($validator);
|
||||
$this->validRepetitionMoment($validator);
|
||||
$this->foreignCurrencyInformation($validator);
|
||||
$this->validateOneTransaction($validator);
|
||||
$this->validateOneRepetition($validator);
|
||||
$this->validateRecurrenceRepetition($validator);
|
||||
$this->validateRepetitionMoment($validator);
|
||||
$this->validateForeignCurrencyInformation($validator);
|
||||
$this->validateAccountInformation($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws an error when this asset account is invalid.
|
||||
* Returns the repetition data as it is found in the submitted data.
|
||||
*
|
||||
* @noinspection MoreThanThreeArgumentsInspection
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param int|null $accountId
|
||||
* @param null|string $accountName
|
||||
* @param string $idField
|
||||
* @param string $nameField
|
||||
*
|
||||
* @return null|Account
|
||||
* @return array
|
||||
*/
|
||||
protected function assetAccountExists(Validator $validator, ?int $accountId, ?string $accountName, string $idField, string $nameField): ?Account
|
||||
private function getRepetitionData(): array
|
||||
{
|
||||
$accountId = (int)$accountId;
|
||||
$accountName = (string)$accountName;
|
||||
// both empty? hard exit.
|
||||
if ($accountId < 1 && '' === $accountName) {
|
||||
$validator->errors()->add($idField, trans('validation.filled', ['attribute' => $idField]));
|
||||
|
||||
return null;
|
||||
}
|
||||
// ID belongs to user and is asset account:
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$set = $repository->getAccountsById([$accountId]);
|
||||
Log::debug(sprintf('Count of accounts found by ID %d is: %d', $accountId, $set->count()));
|
||||
if ($set->count() === 1) {
|
||||
/** @var Account $first */
|
||||
$first = $set->first();
|
||||
if ($first->accountType->type !== AccountType::ASSET) {
|
||||
$validator->errors()->add($idField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// we ignore the account name at this point.
|
||||
return $first;
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$return[] = [
|
||||
'type' => $repetition['type'],
|
||||
'moment' => $repetition['moment'],
|
||||
'skip' => (int)$repetition['skip'],
|
||||
'weekend' => (int)$repetition['weekend'],
|
||||
];
|
||||
}
|
||||
|
||||
$account = $repository->findByName($accountName, [AccountType::ASSET]);
|
||||
if (null === $account) {
|
||||
$validator->errors()->add($nameField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $account;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
||||
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @return array
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
protected function atLeastOneRepetition(Validator $validator): void
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$repetitions = $data['repetitions'] ?? [];
|
||||
// need at least one transaction
|
||||
if (\count($repetitions) === 0) {
|
||||
$validator->errors()->add('description', trans('validation.at_least_one_repetition'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no transactions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneTransaction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
// need at least one transaction
|
||||
if (\count($transactions) === 0) {
|
||||
$validator->errors()->add('description', trans('validation.at_least_one_transaction'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO can be made a rule?
|
||||
* If the transactions contain foreign amounts, there must also be foreign currency information.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function foreignCurrencyInformation(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
// must have currency info.
|
||||
if (isset($transaction['foreign_amount'])
|
||||
&& !(isset($transaction['foreign_currency_id'])
|
||||
|| isset($transaction['foreign_currency_code']))) {
|
||||
$validator->errors()->add(
|
||||
'transactions.' . $index . '.foreign_amount',
|
||||
trans('validation.require_currency_info')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error when the given opposing account (of type $type) is invalid.
|
||||
* Empty data is allowed, system will default to cash.
|
||||
*
|
||||
* @noinspection MoreThanThreeArgumentsInspection
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param string $type
|
||||
* @param int|null $accountId
|
||||
* @param null|string $accountName
|
||||
* @param string $idField
|
||||
*
|
||||
* @return null|Account
|
||||
*/
|
||||
protected function opposingAccountExists(Validator $validator, string $type, ?int $accountId, ?string $accountName, string $idField): ?Account
|
||||
{
|
||||
$accountId = (int)$accountId;
|
||||
$accountName = (string)$accountName;
|
||||
// both empty? done!
|
||||
if ($accountId < 1 && \strlen($accountName) === 0) {
|
||||
return null;
|
||||
}
|
||||
if ($accountId !== 0) {
|
||||
// ID belongs to user and is $type account:
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$set = $repository->getAccountsById([$accountId]);
|
||||
if ($set->count() === 1) {
|
||||
/** @var Account $first */
|
||||
$first = $set->first();
|
||||
if ($first->accountType->type !== $type) {
|
||||
$validator->errors()->add($idField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// we ignore the account name at this point.
|
||||
return $first;
|
||||
}
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return[] = [
|
||||
'amount' => $transaction['amount'],
|
||||
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
|
||||
'currency_code' => $transaction['currency_code'] ?? null,
|
||||
'foreign_amount' => $transaction['foreign_amount'] ?? null,
|
||||
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
|
||||
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
|
||||
'budget_name' => $transaction['budget_name'] ?? null,
|
||||
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
|
||||
'category_name' => $transaction['category_name'] ?? null,
|
||||
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
|
||||
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
|
||||
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
|
||||
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
|
||||
'description' => $transaction['description'],
|
||||
];
|
||||
}
|
||||
|
||||
// not having an opposing account by this name is NOT a problem.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO can be a rule?
|
||||
*
|
||||
* Validates the given account information. Switches on given transaction type.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function validateAccountInformation(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
$idField = 'description';
|
||||
$transactionType = $data['type'] ?? 'false';
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$sourceId = isset($transaction['source_id']) ? (int)$transaction['source_id'] : null;
|
||||
$sourceName = $transaction['source_name'] ?? null;
|
||||
$destinationId = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null;
|
||||
$destinationName = $transaction['destination_name'] ?? null;
|
||||
$sourceAccount = null;
|
||||
$destinationAccount = null;
|
||||
switch ($transactionType) {
|
||||
case 'withdrawal':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$nameField = 'transactions.' . $index . '.source_name';
|
||||
$sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField);
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$destinationAccount = $this->opposingAccountExists($validator, AccountType::EXPENSE, $destinationId, $destinationName, $idField);
|
||||
break;
|
||||
case 'deposit':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$sourceAccount = $this->opposingAccountExists($validator, AccountType::REVENUE, $sourceId, $sourceName, $idField);
|
||||
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$nameField = 'transactions.' . $index . '.destination_name';
|
||||
$destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField);
|
||||
break;
|
||||
case 'transfer':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$nameField = 'transactions.' . $index . '.source_name';
|
||||
$sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField);
|
||||
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$nameField = 'transactions.' . $index . '.destination_name';
|
||||
$destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField);
|
||||
break;
|
||||
default:
|
||||
$validator->errors()->add($idField, trans('validation.invalid_account_info'));
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
// add some errors in case of same account submitted:
|
||||
if (null !== $sourceAccount && null !== $destinationAccount && $sourceAccount->id === $destinationAccount->id) {
|
||||
$validator->errors()->add($idField, trans('validation.source_equals_destination'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
*/
|
||||
private function validRepeatsUntil(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$repetitions = $data['nr_of_repetitions'] ?? null;
|
||||
$repeatUntil = $data['repeat_until'] ?? null;
|
||||
if (null !== $repetitions && null !== $repeatUntil) {
|
||||
// expect a date OR count:
|
||||
$validator->errors()->add('repeat_until', trans('validation.require_repeat_until'));
|
||||
$validator->errors()->add('nr_of_repetitions', trans('validation.require_repeat_until'));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO merge this in a rule somehow.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
private function validRepetitionMoment(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$repetitions = $data['repetitions'] ?? [];
|
||||
/**
|
||||
* @var int $index
|
||||
* @var array $repetition
|
||||
*/
|
||||
foreach ($repetitions as $index => $repetition) {
|
||||
switch ($repetition['type']) {
|
||||
default:
|
||||
$validator->errors()->add(sprintf('repetitions.%d.type', $index), trans('validation.valid_recurrence_rep_type'));
|
||||
|
||||
return;
|
||||
case 'daily':
|
||||
if ('' !== (string)$repetition['moment']) {
|
||||
$validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment'));
|
||||
}
|
||||
|
||||
return;
|
||||
case 'monthly':
|
||||
$dayOfMonth = (int)$repetition['moment'];
|
||||
if ($dayOfMonth < 1 || $dayOfMonth > 31) {
|
||||
$validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment'));
|
||||
}
|
||||
|
||||
return;
|
||||
case 'ndom':
|
||||
$parameters = explode(',', $repetition['moment']);
|
||||
if (\count($parameters) !== 2) {
|
||||
$validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment'));
|
||||
|
||||
return;
|
||||
}
|
||||
$nthDay = (int)($parameters[0] ?? 0.0);
|
||||
$dayOfWeek = (int)($parameters[1] ?? 0.0);
|
||||
if ($nthDay < 1 || $nthDay > 5) {
|
||||
$validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment'));
|
||||
|
||||
return;
|
||||
}
|
||||
if ($dayOfWeek < 1 || $dayOfWeek > 7) {
|
||||
$validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
case 'weekly':
|
||||
$dayOfWeek = (int)$repetition['moment'];
|
||||
if ($dayOfWeek < 1 || $dayOfWeek > 7) {
|
||||
$validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment'));
|
||||
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'yearly':
|
||||
try {
|
||||
Carbon::createFromFormat('Y-m-d', $repetition['moment']);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment'));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
}
|
@@ -28,6 +28,10 @@ use FireflyIII\Http\Requests\Request as FireflyIIIRequest;
|
||||
|
||||
/**
|
||||
* Class Request.
|
||||
*
|
||||
* Technically speaking this class does not have to be extended like this but who knows what the future brings.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
||||
*/
|
||||
class Request extends FireflyIIIRequest
|
||||
{
|
||||
|
@@ -33,6 +33,8 @@ use FireflyIII\Models\RuleGroup;
|
||||
class RuleGroupRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -42,6 +44,8 @@ class RuleGroupRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -54,6 +58,8 @@ class RuleGroupRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -32,6 +32,8 @@ use Illuminate\Validation\Validator;
|
||||
class RuleRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -41,6 +43,8 @@ class RuleRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -62,14 +66,14 @@ class RuleRequest extends Request
|
||||
$data['rule-triggers'][] = [
|
||||
'name' => $trigger['name'],
|
||||
'value' => $trigger['value'],
|
||||
'stop-processing' => (int)($trigger['stop-processing'] ?? 0) === 1,
|
||||
'stop-processing' => 1 === (int)($trigger['stop-processing'] ?? 0),
|
||||
];
|
||||
}
|
||||
foreach ($this->get('rule-actions') as $action) {
|
||||
$data['rule-actions'][] = [
|
||||
'name' => $action['name'],
|
||||
'value' => $action['value'],
|
||||
'stop-processing' => (int)($action['stop-processing'] ?? 0) === 1,
|
||||
'stop-processing' => 1 === (int)($action['stop-processing'] ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -77,6 +81,8 @@ class RuleRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
@@ -134,7 +140,7 @@ class RuleRequest extends Request
|
||||
$data = $validator->getData();
|
||||
$repetitions = $data['rule-actions'] ?? [];
|
||||
// need at least one transaction
|
||||
if (\count($repetitions) === 0) {
|
||||
if (0 === \count($repetitions)) {
|
||||
$validator->errors()->add('title', trans('validation.at_least_one_action'));
|
||||
}
|
||||
}
|
||||
@@ -149,7 +155,7 @@ class RuleRequest extends Request
|
||||
$data = $validator->getData();
|
||||
$repetitions = $data['rule-triggers'] ?? [];
|
||||
// need at least one transaction
|
||||
if (\count($repetitions) === 0) {
|
||||
if (0 === \count($repetitions)) {
|
||||
$validator->errors()->add('title', trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
|
@@ -24,12 +24,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
|
||||
@@ -38,7 +34,11 @@ use Illuminate\Validation\Validator;
|
||||
*/
|
||||
class TransactionRequest extends Request
|
||||
{
|
||||
use TransactionValidation;
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -48,12 +48,15 @@ class TransactionRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data. Is pretty complex because of all the ??-statements.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$data = [
|
||||
// basic fields for journal:
|
||||
'type' => $this->string('type'),
|
||||
'date' => $this->date('date'),
|
||||
'description' => $this->string('description'),
|
||||
@@ -62,8 +65,6 @@ class TransactionRequest extends Request
|
||||
'bill_id' => $this->integer('bill_id'),
|
||||
'bill_name' => $this->string('bill_name'),
|
||||
'tags' => explode(',', $this->string('tags')),
|
||||
|
||||
// then, custom fields for journal
|
||||
'interest_date' => $this->date('interest_date'),
|
||||
'book_date' => $this->date('book_date'),
|
||||
'process_date' => $this->date('process_date'),
|
||||
@@ -72,39 +73,17 @@ class TransactionRequest extends Request
|
||||
'invoice_date' => $this->date('invoice_date'),
|
||||
'internal_reference' => $this->string('internal_reference'),
|
||||
'notes' => $this->string('notes'),
|
||||
|
||||
// then, transactions (see below).
|
||||
'transactions' => [],
|
||||
|
||||
'transactions' => $this->getTransactionData(),
|
||||
];
|
||||
foreach ($this->get('transactions') as $index => $transaction) {
|
||||
$array = [
|
||||
'description' => $transaction['description'] ?? null,
|
||||
'amount' => $transaction['amount'],
|
||||
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
|
||||
'currency_code' => $transaction['currency_code'] ?? null,
|
||||
'foreign_amount' => $transaction['foreign_amount'] ?? null,
|
||||
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
|
||||
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
|
||||
'budget_name' => $transaction['budget_name'] ?? null,
|
||||
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
|
||||
'category_name' => $transaction['category_name'] ?? null,
|
||||
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
|
||||
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
|
||||
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
|
||||
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
|
||||
'reconciled' => $transaction['reconciled'] ?? false,
|
||||
'identifier' => $index,
|
||||
];
|
||||
$data['transactions'][] = $array;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
@@ -149,13 +128,8 @@ class TransactionRequest extends Request
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
];
|
||||
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']);
|
||||
break;
|
||||
if ('PUT' === $this->method()) {
|
||||
unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
@@ -174,11 +148,11 @@ class TransactionRequest extends Request
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->atLeastOneTransaction($validator);
|
||||
$this->checkValidDescriptions($validator);
|
||||
$this->equalToJournalDescription($validator);
|
||||
$this->emptySplitDescriptions($validator);
|
||||
$this->foreignCurrencyInformation($validator);
|
||||
$this->validateOneTransaction($validator);
|
||||
$this->validateDescriptions($validator);
|
||||
$this->validateJournalDescription($validator);
|
||||
$this->validateSplitDescriptions($validator);
|
||||
$this->validateForeignCurrencyInformation($validator);
|
||||
$this->validateAccountInformation($validator);
|
||||
$this->validateSplitAccounts($validator);
|
||||
}
|
||||
@@ -186,335 +160,37 @@ class TransactionRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error when this asset account is invalid.
|
||||
* Get transaction data.
|
||||
*
|
||||
* @noinspection MoreThanThreeArgumentsInspection
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param int|null $accountId
|
||||
* @param null|string $accountName
|
||||
* @param string $idField
|
||||
* @param string $nameField
|
||||
*
|
||||
* @return null|Account
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @return array
|
||||
*/
|
||||
protected function assetAccountExists(Validator $validator, ?int $accountId, ?string $accountName, string $idField, string $nameField): ?Account
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
|
||||
$accountId = (int)$accountId;
|
||||
$accountName = (string)$accountName;
|
||||
// both empty? hard exit.
|
||||
if ($accountId < 1 && \strlen($accountName) === 0) {
|
||||
$validator->errors()->add($idField, trans('validation.filled', ['attribute' => $idField]));
|
||||
|
||||
return null;
|
||||
}
|
||||
// ID belongs to user and is asset account:
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$set = $repository->getAccountsById([$accountId]);
|
||||
if ($set->count() === 1) {
|
||||
/** @var Account $first */
|
||||
$first = $set->first();
|
||||
if ($first->accountType->type !== AccountType::ASSET) {
|
||||
$validator->errors()->add($idField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// we ignore the account name at this point.
|
||||
return $first;
|
||||
$return = [];
|
||||
foreach ($this->get('transactions') as $index => $transaction) {
|
||||
$return[] = [
|
||||
'description' => $transaction['description'] ?? null,
|
||||
'amount' => $transaction['amount'],
|
||||
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
|
||||
'currency_code' => $transaction['currency_code'] ?? null,
|
||||
'foreign_amount' => $transaction['foreign_amount'] ?? null,
|
||||
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
|
||||
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
|
||||
'budget_name' => $transaction['budget_name'] ?? null,
|
||||
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
|
||||
'category_name' => $transaction['category_name'] ?? null,
|
||||
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
|
||||
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
|
||||
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
|
||||
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
|
||||
'reconciled' => $transaction['reconciled'] ?? false,
|
||||
'identifier' => $index,
|
||||
];
|
||||
}
|
||||
|
||||
$account = $repository->findByName($accountName, [AccountType::ASSET]);
|
||||
if (null === $account) {
|
||||
$validator->errors()->add($nameField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $account;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no transactions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneTransaction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
// need at least one transaction
|
||||
if (\count($transactions) === 0) {
|
||||
$validator->errors()->add('description', trans('validation.at_least_one_transaction'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the "description" field when the user has submitted no descriptions and no
|
||||
* journal description.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function checkValidDescriptions(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
$journalDescription = (string)($data['description'] ?? '');
|
||||
$validDescriptions = 0;
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
if (\strlen((string)($transaction['description'] ?? '')) > 0) {
|
||||
$validDescriptions++;
|
||||
}
|
||||
}
|
||||
|
||||
// no valid descriptions and empty journal description? error.
|
||||
if ($validDescriptions === 0 && \strlen($journalDescription) === 0) {
|
||||
$validator->errors()->add('description', trans('validation.filled', ['attribute' => trans('validation.attributes.description')]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when the user submits a split transaction (more than 1 transactions)
|
||||
* but does not give them a description.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function emptySplitDescriptions(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$description = (string)($transaction['description'] ?? '');
|
||||
// filled description is mandatory for split transactions.
|
||||
if (\count($transactions) > 1 && \strlen($description) === 0) {
|
||||
$validator->errors()->add(
|
||||
'transactions.' . $index . '.description',
|
||||
trans('validation.filled', ['attribute' => trans('validation.attributes.transaction_description')])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when any transaction descriptions are equal to the journal description.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function equalToJournalDescription(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
$journalDescription = (string)($data['description'] ?? '');
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$description = (string)($transaction['description'] ?? '');
|
||||
// description cannot be equal to journal description.
|
||||
if ($description === $journalDescription) {
|
||||
$validator->errors()->add('transactions.' . $index . '.description', trans('validation.equal_description'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO can be made a rule?
|
||||
*
|
||||
* If the transactions contain foreign amounts, there must also be foreign currency information.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function foreignCurrencyInformation(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
// must have currency info.
|
||||
if (isset($transaction['foreign_amount'])
|
||||
&& !(isset($transaction['foreign_currency_id'])
|
||||
|| isset($transaction['foreign_currency_code']))) {
|
||||
$validator->errors()->add(
|
||||
'transactions.' . $index . '.foreign_amount',
|
||||
trans('validation.require_currency_info')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error when the given opposing account (of type $type) is invalid.
|
||||
* Empty data is allowed, system will default to cash.
|
||||
*
|
||||
* @noinspection MoreThanThreeArgumentsInspection
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param string $type
|
||||
* @param int|null $accountId
|
||||
* @param null|string $accountName
|
||||
* @param string $idField
|
||||
*
|
||||
* @return null|Account
|
||||
*/
|
||||
protected function opposingAccountExists(Validator $validator, string $type, ?int $accountId, ?string $accountName, string $idField): ?Account
|
||||
{
|
||||
$accountId = (int)$accountId;
|
||||
$accountName = (string)$accountName;
|
||||
// both empty? done!
|
||||
if ($accountId < 1 && \strlen($accountName) === 0) {
|
||||
return null;
|
||||
}
|
||||
if ($accountId !== 0) {
|
||||
// ID belongs to user and is $type account:
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$set = $repository->getAccountsById([$accountId]);
|
||||
if ($set->count() === 1) {
|
||||
/** @var Account $first */
|
||||
$first = $set->first();
|
||||
if ($first->accountType->type !== $type) {
|
||||
$validator->errors()->add($idField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// we ignore the account name at this point.
|
||||
return $first;
|
||||
}
|
||||
}
|
||||
|
||||
// not having an opposing account by this name is NOT a problem.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given account information. Switches on given transaction type.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
protected function validateAccountInformation(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
if (!isset($data['type'])) {
|
||||
// the journal may exist in the request:
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $this->route()->parameter('transaction');
|
||||
if (null === $transaction) {
|
||||
return; // @codeCoverageIgnore
|
||||
}
|
||||
$data['type'] = strtolower($transaction->transactionJournal->transactionType->type);
|
||||
}
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$sourceId = isset($transaction['source_id']) ? (int)$transaction['source_id'] : null;
|
||||
$sourceName = $transaction['source_name'] ?? null;
|
||||
$destinationId = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null;
|
||||
$destinationName = $transaction['destination_name'] ?? null;
|
||||
$sourceAccount = null;
|
||||
$destinationAccount = null;
|
||||
switch ($data['type']) {
|
||||
case 'withdrawal':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$nameField = 'transactions.' . $index . '.source_name';
|
||||
$sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField);
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$destinationAccount = $this->opposingAccountExists($validator, AccountType::EXPENSE, $destinationId, $destinationName, $idField);
|
||||
break;
|
||||
case 'deposit':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$sourceAccount = $this->opposingAccountExists($validator, AccountType::REVENUE, $sourceId, $sourceName, $idField);
|
||||
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$nameField = 'transactions.' . $index . '.destination_name';
|
||||
$destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField);
|
||||
break;
|
||||
case 'transfer':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$nameField = 'transactions.' . $index . '.source_name';
|
||||
$sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField);
|
||||
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$nameField = 'transactions.' . $index . '.destination_name';
|
||||
$destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField);
|
||||
break;
|
||||
default:
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new FireflyException(
|
||||
sprintf('The validator cannot handle transaction type "%s" in validateAccountInformation().', $data['type'])
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
// add some errors in case of same account submitted:
|
||||
if (null !== $sourceAccount && null !== $destinationAccount && $sourceAccount->id === $destinationAccount->id) {
|
||||
$validator->errors()->add($idField, trans('validation.source_equals_destination'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
protected function validateSplitAccounts(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$count = isset($data['transactions']) ? \count($data['transactions']) : 0;
|
||||
if ($count < 2) {
|
||||
return;
|
||||
}
|
||||
// this is pretty much impossible:
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!isset($data['type'])) {
|
||||
// the journal may exist in the request:
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $this->route()->parameter('transaction');
|
||||
if (null === $transaction) {
|
||||
return;
|
||||
}
|
||||
$data['type'] = strtolower($transaction->transactionJournal->transactionType->type);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// collect all source ID's and destination ID's, if present:
|
||||
$sources = [];
|
||||
$destinations = [];
|
||||
|
||||
foreach ($data['transactions'] as $transaction) {
|
||||
$sources[] = isset($transaction['source_id']) ? (int)$transaction['source_id'] : 0;
|
||||
$destinations[] = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : 0;
|
||||
}
|
||||
$destinations = array_unique($destinations);
|
||||
$sources = array_unique($sources);
|
||||
// switch on type:
|
||||
switch ($data['type']) {
|
||||
case 'withdrawal':
|
||||
if (\count($sources) > 1) {
|
||||
$validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal'));
|
||||
}
|
||||
break;
|
||||
case 'deposit':
|
||||
if (\count($destinations) > 1) {
|
||||
$validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal'));
|
||||
}
|
||||
break;
|
||||
case 'transfer':
|
||||
if (\count($sources) > 1 || \count($destinations) > 1) {
|
||||
$validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal'));
|
||||
$validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal'));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new FireflyException(
|
||||
sprintf('The validator cannot handle transaction type "%s" in validateSplitAccounts().', $data['type'])
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
|
||||
|
||||
@@ -33,24 +34,32 @@ use FireflyIII\User;
|
||||
class UserRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
$result = false;
|
||||
// Only allow authenticated users
|
||||
if (!auth()->check()) {
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
if (!$user->hasRole('owner')) {
|
||||
return false; // @codeCoverageIgnore
|
||||
if (auth()->check()) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var UserRepositoryInterface $repository */
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
|
||||
if ($repository->hasRole($user, 'owner')) {
|
||||
$result = true; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
@@ -65,6 +74,8 @@ class UserRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CreateExport.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,6 +19,8 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
@@ -42,6 +43,7 @@ use Storage;
|
||||
class CreateExport extends Command
|
||||
{
|
||||
use VerifiesAccessToken;
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
@@ -64,9 +66,11 @@ class CreateExport extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
* @return int
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): int
|
||||
{
|
||||
if (!$this->verifyAccessToken()) {
|
||||
$this->error('Invalid access token.');
|
||||
@@ -86,6 +90,9 @@ class CreateExport extends Command
|
||||
|
||||
// set user
|
||||
$user = $userRepository->findNull((int)$this->option('user'));
|
||||
if (null === $user) {
|
||||
return 1;
|
||||
}
|
||||
$jobRepository->setUser($user);
|
||||
$journalRepository->setUser($user);
|
||||
$accountRepository->setUser($user);
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CreateImport.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,6 +19,8 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
@@ -81,10 +82,15 @@ class CreateImport extends Command
|
||||
$configuration = (string)$this->argument('configuration');
|
||||
$user = $userRepository->findNull((int)$this->option('user'));
|
||||
$cwd = getcwd();
|
||||
$type = strtolower((string)$this->option('type'));
|
||||
$provider = strtolower((string)$this->option('provider'));
|
||||
$configurationData = [];
|
||||
|
||||
if (null === $user) {
|
||||
$this->errorLine('User is NULL.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!$this->validArguments()) {
|
||||
$this->errorLine('Invalid arguments.');
|
||||
|
||||
@@ -182,7 +188,7 @@ class CreateImport extends Command
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
if ($importJob->status === 'provider_finished') {
|
||||
if ('provider_finished' === $importJob->status) {
|
||||
$this->infoLine('Import has finished. Please wait for storage of data.');
|
||||
// set job to be storing data:
|
||||
$jobRepository->setStatus($importJob, 'storing_data');
|
||||
@@ -274,19 +280,19 @@ class CreateImport extends Command
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($provider === 'file' && !\in_array($type, $validTypes, true)) {
|
||||
if ('file' === $provider && !\in_array($type, $validTypes, true)) {
|
||||
$this->errorLine(sprintf('Cannot import file of type "%s"', $type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($provider === 'file' && !file_exists($file)) {
|
||||
if ('file' === $provider && !file_exists($file)) {
|
||||
$this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($provider === 'file' && !file_exists($configuration)) {
|
||||
if ('file' === $provider && !file_exists($configuration)) {
|
||||
$this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
return false;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DecryptAttachment.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,6 +19,8 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
@@ -51,11 +52,12 @@ class DecryptAttachment extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five its fine.
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): int
|
||||
{
|
||||
/** @var AttachmentRepositoryInterface $repository */
|
||||
$repository = app(AttachmentRepositoryInterface::class);
|
||||
@@ -67,28 +69,28 @@ class DecryptAttachment extends Command
|
||||
$this->error(sprintf('No attachment with id #%d', $attachmentId));
|
||||
Log::error(sprintf('DecryptAttachment: No attachment with id #%d', $attachmentId));
|
||||
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($attachmentName !== $attachment->filename) {
|
||||
$this->error('File name does not match.');
|
||||
Log::error('DecryptAttachment: File name does not match.');
|
||||
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!is_dir($storagePath)) {
|
||||
$this->error(sprintf('Path "%s" is not a directory.', $storagePath));
|
||||
Log::error(sprintf('DecryptAttachment: Path "%s" is not a directory.', $storagePath));
|
||||
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!is_writable($storagePath)) {
|
||||
$this->error(sprintf('Path "%s" is not writable.', $storagePath));
|
||||
Log::error(sprintf('DecryptAttachment: Path "%s" is not writable.', $storagePath));
|
||||
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
$fullPath = $storagePath . DIRECTORY_SEPARATOR . $attachment->filename;
|
||||
@@ -98,9 +100,10 @@ class DecryptAttachment extends Command
|
||||
if (false === $result) {
|
||||
$this->error('Could not write to file.');
|
||||
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
$this->info(sprintf('%d bytes written. Exiting now..', $result));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* EncryptFile.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Import.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,6 +19,9 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
@@ -27,8 +29,8 @@ namespace FireflyIII\Console\Commands;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Import\Routine\RoutineInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\Tag;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
@@ -52,10 +54,12 @@ class Import extends Command
|
||||
|
||||
/**
|
||||
* Run the import routine.
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
Log::debug('Start start-import command');
|
||||
$jobKey = $this->argument('key');
|
||||
@@ -83,21 +87,30 @@ class Import extends Command
|
||||
|
||||
/** @var RoutineInterface $routine */
|
||||
$routine = app($className);
|
||||
$routine->setJob($job);
|
||||
$routine->setImportJob($job);
|
||||
$routine->run();
|
||||
|
||||
/** @var MessageBag $error */
|
||||
foreach ($routine->getErrors() as $index => $error) {
|
||||
/**
|
||||
* @var int $index
|
||||
* @var string $error
|
||||
*/
|
||||
foreach ($job->errors as $index => $error) {
|
||||
$this->errorLine(sprintf('Error importing line #%d: %s', $index, $error));
|
||||
}
|
||||
|
||||
$this->infoLine(
|
||||
sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->getJournals()->count(), $routine->getLines())
|
||||
);
|
||||
/** @var Tag $tag */
|
||||
$tag = $job->tag()->first();
|
||||
$count = 0;
|
||||
if (null === $tag) {
|
||||
$count = $tag->transactionJournals()->count();
|
||||
}
|
||||
|
||||
$this->infoLine(sprintf('The import has finished. %d transactions have been imported.', $count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an error.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array|null $data
|
||||
*/
|
||||
@@ -109,6 +122,8 @@ class Import extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an informational message.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $data
|
||||
*/
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ScanAttachments.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,6 +19,8 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
@@ -53,7 +54,7 @@ class ScanAttachments extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
$attachments = Attachment::get();
|
||||
$disk = Storage::disk('upload');
|
||||
@@ -63,13 +64,13 @@ class ScanAttachments extends Command
|
||||
try {
|
||||
$content = $disk->get($fileName);
|
||||
} catch (FileNotFoundException $e) {
|
||||
$this->error(sprintf('Could not find data for attachment #%d', $attachment->id));
|
||||
$this->error(sprintf('Could not find data for attachment #%d: %s', $attachment->id, $e->getMessage()));
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$decrypted = Crypt::decrypt($content);
|
||||
} catch (DecryptException $e) {
|
||||
$this->error(sprintf('Could not decrypt data of attachment #%d', $attachment->id));
|
||||
$this->error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage()));
|
||||
continue;
|
||||
}
|
||||
$tmpfname = tempnam(sys_get_temp_dir(), 'FireflyIII');
|
||||
|
@@ -20,6 +20,10 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
/** @noinspection PhpStaticAsDynamicMethodCallInspection */
|
||||
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
@@ -42,7 +46,9 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\QueryException;
|
||||
@@ -50,14 +56,14 @@ use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Schema;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Class UpgradeDatabase.
|
||||
*
|
||||
* Upgrade user database.
|
||||
*
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // it just touches a lot of things.
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class UpgradeDatabase extends Command
|
||||
{
|
||||
@@ -77,7 +83,7 @@ class UpgradeDatabase extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
$this->setTransactionIdentifier();
|
||||
$this->updateAccountCurrencies();
|
||||
@@ -93,7 +99,14 @@ class UpgradeDatabase extends Command
|
||||
$this->info('Firefly III database is up to date.');
|
||||
}
|
||||
|
||||
public function migrateBillsToRules()
|
||||
/**
|
||||
* Since it is one routine these warnings make sense and should be supressed.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
*/
|
||||
public function migrateBillsToRules(): void
|
||||
{
|
||||
foreach (User::get() as $user) {
|
||||
/** @var Preference $lang */
|
||||
@@ -101,12 +114,20 @@ class UpgradeDatabase extends Command
|
||||
$groupName = (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data);
|
||||
$ruleGroup = $user->ruleGroups()->where('title', $groupName)->first();
|
||||
$currencyPreference = Preferences::getForUser($user, 'currencyPreference', config('firefly.default_currency', 'EUR'));
|
||||
$currency = TransactionCurrency::where('code', $currencyPreference->data)->first();
|
||||
|
||||
if (null === $currencyPreference) {
|
||||
$this->error('User has no currency preference. Impossible.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$currency = TransactionCurrency::where('code', $currencyPreference->data)->first();
|
||||
if (null === $currency) {
|
||||
$this->line('Fall back to default currency in migrateBillsToRules().');
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
}
|
||||
|
||||
if ($ruleGroup === null) {
|
||||
if (null === $ruleGroup) {
|
||||
$array = RuleGroup::get(['order'])->pluck('order')->toArray();
|
||||
$order = \count($array) > 0 ? max($array) + 1 : 1;
|
||||
$ruleGroup = RuleGroup::create(
|
||||
@@ -126,7 +147,7 @@ class UpgradeDatabase extends Command
|
||||
$collection = $user->bills()->get();
|
||||
/** @var Bill $bill */
|
||||
foreach ($collection as $bill) {
|
||||
if ($bill->match !== 'MIGRATED_TO_RULES') {
|
||||
if ('MIGRATED_TO_RULES' !== $bill->match) {
|
||||
$rule = Rule::create(
|
||||
[
|
||||
'user_id' => $user->id,
|
||||
@@ -260,23 +281,29 @@ class UpgradeDatabase extends Command
|
||||
/**
|
||||
* Each (asset) account must have a reference to a preferred currency. If the account does not have one, it's forced upon the account.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's seven but it can't really be helped.
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function updateAccountCurrencies(): void
|
||||
{
|
||||
$accounts = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->whereIn('account_types.type', [AccountType::DEFAULT, AccountType::ASSET])->get(['accounts.*']);
|
||||
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$accounts->each(
|
||||
function (Account $account) {
|
||||
function (Account $account) use ($repository) {
|
||||
$repository->setUser($account->user);
|
||||
// get users preference, fall back to system pref.
|
||||
$defaultCurrencyCode = Preferences::getForUser($account->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data;
|
||||
$defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first();
|
||||
$accountCurrency = (int)$account->getMeta('currency_id');
|
||||
$accountCurrency = (int)$repository->getMetaValue($account, 'currency_id');
|
||||
$openingBalance = $account->getOpeningBalance();
|
||||
$obCurrency = (int)$openingBalance->transaction_currency_id;
|
||||
|
||||
if (null === $defaultCurrency) {
|
||||
throw new UnexpectedValueException('The default currency is NULL, and this is more or less impossible.');
|
||||
}
|
||||
|
||||
// both 0? set to default currency:
|
||||
if (0 === $accountCurrency && 0 === $obCurrency) {
|
||||
AccountMeta::where('account_id', $account->id)->where('name', 'currency_id')->forceDelete();
|
||||
@@ -317,19 +344,22 @@ class UpgradeDatabase extends Command
|
||||
* Both source and destination must match the respective currency preference of the related asset account.
|
||||
* So FF3 must verify all transactions.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function updateOtherCurrencies(): void
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$set = TransactionJournal
|
||||
/** @var AccountRepositoryInterface $accountRepos */
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->whereIn('transaction_types.type', [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE])
|
||||
->get(['transaction_journals.*']);
|
||||
|
||||
$set->each(
|
||||
function (TransactionJournal $journal) use ($repository) {
|
||||
function (TransactionJournal $journal) use ($repository, $accountRepos) {
|
||||
// get the transaction with the asset account in it:
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $journal->transactions()
|
||||
@@ -339,9 +369,13 @@ class UpgradeDatabase extends Command
|
||||
if (null === $transaction) {
|
||||
return;
|
||||
}
|
||||
$accountRepos->setUser($journal->user);
|
||||
/** @var Account $account */
|
||||
$account = $transaction->account;
|
||||
$currency = $repository->find((int)$account->getMeta('currency_id'));
|
||||
$account = $transaction->account;
|
||||
$currency = $repository->findNull((int)$accountRepos->getMetaValue($account, 'currency_id'));
|
||||
if (null === $currency) {
|
||||
return;
|
||||
}
|
||||
$transactions = $journal->transactions()->get();
|
||||
$transactions->each(
|
||||
function (Transaction $transaction) use ($currency) {
|
||||
@@ -377,7 +411,7 @@ class UpgradeDatabase extends Command
|
||||
* Both source and destination must match the respective currency preference. So FF3 must verify ALL
|
||||
* transactions.
|
||||
*/
|
||||
public function updateTransferCurrencies()
|
||||
public function updateTransferCurrencies(): void
|
||||
{
|
||||
$set = TransactionJournal
|
||||
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
@@ -449,6 +483,7 @@ class UpgradeDatabase extends Command
|
||||
*/
|
||||
private function migrateNotes(): void
|
||||
{
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$set = TransactionJournalMeta::whereName('notes')->get();
|
||||
/** @var TransactionJournalMeta $meta */
|
||||
foreach ($set as $meta) {
|
||||
@@ -479,8 +514,15 @@ class UpgradeDatabase extends Command
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$currency = $repository->find((int)$transaction->account->getMeta('currency_id'));
|
||||
$journal = $transaction->transactionJournal;
|
||||
/** @var AccountRepositoryInterface $accountRepos */
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
$accountRepos->setUser($transaction->account->user);
|
||||
$currency = $repository->findNull((int)$accountRepos->getMetaValue($transaction->account, 'currency_id'));
|
||||
$journal = $transaction->transactionJournal;
|
||||
|
||||
if (null === $currency) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!((int)$currency->id === (int)$journal->transaction_currency_id)) {
|
||||
$this->line(
|
||||
@@ -549,11 +591,11 @@ class UpgradeDatabase extends Command
|
||||
*
|
||||
* The transaction that is sent to this function MUST be the source transaction (amount negative).
|
||||
*
|
||||
* Method is long and complex bit I'm taking it for granted.
|
||||
* Method is long and complex but I'll allow it. https://imgur.com/gallery/dVDJiez
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*
|
||||
* @param Transaction $transaction
|
||||
*/
|
||||
@@ -561,7 +603,14 @@ class UpgradeDatabase extends Command
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$currency = $repository->findNull((int)$transaction->account->getMeta('currency_id'));
|
||||
/** @var AccountRepositoryInterface $accountRepos */
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
/** @var JournalRepositoryInterface $journalRepos */
|
||||
$journalRepos = app(JournalRepositoryInterface::class);
|
||||
|
||||
$accountRepos->setUser($transaction->account->user);
|
||||
$journalRepos->setUser($transaction->account->user);
|
||||
$currency = $repository->findNull((int)$accountRepos->getMetaValue($transaction->account, 'currency_id'));
|
||||
|
||||
if (null === $currency) {
|
||||
Log::error(sprintf('Account #%d ("%s") must have currency preference but has none.', $transaction->account->id, $transaction->account->name));
|
||||
@@ -597,7 +646,7 @@ class UpgradeDatabase extends Command
|
||||
$journal = $transaction->transactionJournal;
|
||||
/** @var Transaction $opposing */
|
||||
$opposing = $journal->transactions()->where('amount', '>', 0)->where('identifier', $transaction->identifier)->first();
|
||||
$opposingCurrency = $repository->findNull((int)$opposing->account->getMeta('currency_id'));
|
||||
$opposingCurrency = $repository->findNull((int)$accountRepos->getMetaValue($opposing->account, 'currency_id'));
|
||||
|
||||
if (null === $opposingCurrency) {
|
||||
Log::error(sprintf('Account #%d ("%s") must have currency preference but has none.', $opposing->account->id, $opposing->account->name));
|
||||
@@ -653,7 +702,7 @@ class UpgradeDatabase extends Command
|
||||
|
||||
// when both are zero, try to grab it from journal:
|
||||
if (null === $opposing->foreign_amount && null === $transaction->foreign_amount) {
|
||||
$foreignAmount = $journal->getMeta('foreign_amount');
|
||||
$foreignAmount = $journalRepos->getMetaField($journal, 'foreign_amount');
|
||||
if (null === $foreignAmount) {
|
||||
Log::debug(sprintf('Journal #%d has missing foreign currency data, forced to do 1:1 conversion :(.', $transaction->transaction_journal_id));
|
||||
$transaction->foreign_amount = bcmul((string)$transaction->amount, '-1');
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* UpgradeFireflyInstructions.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -47,7 +46,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
if ('update' === $this->argument('task')) {
|
||||
$this->updateInstructions();
|
||||
@@ -62,7 +61,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
*
|
||||
* @param string $text
|
||||
*/
|
||||
private function boxed(string $text)
|
||||
private function boxed(string $text): void
|
||||
{
|
||||
$parts = explode("\n", wordwrap($text));
|
||||
foreach ($parts as $string) {
|
||||
@@ -75,7 +74,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
*
|
||||
* @param string $text
|
||||
*/
|
||||
private function boxedInfo(string $text)
|
||||
private function boxedInfo(string $text): void
|
||||
{
|
||||
$parts = explode("\n", wordwrap($text));
|
||||
foreach ($parts as $string) {
|
||||
@@ -86,7 +85,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
/**
|
||||
* Render instructions.
|
||||
*/
|
||||
private function installInstructions()
|
||||
private function installInstructions(): void
|
||||
{
|
||||
/** @var string $version */
|
||||
$version = config('firefly.version');
|
||||
@@ -94,8 +93,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
$text = '';
|
||||
foreach (array_keys($config) as $compare) {
|
||||
// if string starts with:
|
||||
$len = \strlen($compare);
|
||||
if (substr($version, 0, $len) === $compare) {
|
||||
if (0 === strpos($version, $compare)) {
|
||||
$text = $config[$compare];
|
||||
}
|
||||
}
|
||||
@@ -120,7 +118,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
/**
|
||||
* Show a line.
|
||||
*/
|
||||
private function showLine()
|
||||
private function showLine(): void
|
||||
{
|
||||
$line = '+';
|
||||
for ($i = 0; $i < 78; ++$i) {
|
||||
@@ -133,7 +131,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
/**
|
||||
* Render upgrade instructions.
|
||||
*/
|
||||
private function updateInstructions()
|
||||
private function updateInstructions(): void
|
||||
{
|
||||
/** @var string $version */
|
||||
$version = config('firefly.version');
|
||||
@@ -141,8 +139,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
$text = '';
|
||||
foreach (array_keys($config) as $compare) {
|
||||
// if string starts with:
|
||||
$len = \strlen($compare);
|
||||
if (substr($version, 0, $len) === $compare) {
|
||||
if (0 === strpos($version, $compare)) {
|
||||
$text = $config[$compare];
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* UseEncryption.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -48,12 +47,12 @@ class UseEncryption extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
if (config('firefly.encryption') === true) {
|
||||
if (true === config('firefly.encryption')) {
|
||||
$this->info('Firefly III configuration calls for encrypted data.');
|
||||
}
|
||||
if (config('firefly.encryption') === false) {
|
||||
if (false === config('firefly.encryption')) {
|
||||
$this->info('Firefly III configuration calls for unencrypted data.');
|
||||
}
|
||||
$this->handleObjects('Account', 'name', 'encrypted');
|
||||
@@ -72,18 +71,21 @@ class UseEncryption extends Command
|
||||
* @param string $field
|
||||
* @param string $indicator
|
||||
*/
|
||||
public function handleObjects(string $class, string $field, string $indicator)
|
||||
public function handleObjects(string $class, string $field, string $indicator): void
|
||||
{
|
||||
$fqn = sprintf('FireflyIII\Models\%s', $class);
|
||||
$encrypt = config('firefly.encryption') === true ? 0 : 1;
|
||||
$set = $fqn::where($indicator, $encrypt)->get();
|
||||
$encrypt = true === config('firefly.encryption') ? 0 : 1;
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$set = $fqn::where($indicator, $encrypt)->get();
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$newName = $entry->$field;
|
||||
$entry->$field = $newName;
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$entry->save();
|
||||
}
|
||||
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$this->line(sprintf('Updated %d %s.', $set->count(), strtolower(Str::plural($class))));
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* VerifiesAccessToken.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* VerifyDatabase.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,6 +19,8 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
@@ -29,6 +30,7 @@ use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Transaction;
|
||||
@@ -39,6 +41,7 @@ use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Schema;
|
||||
use stdClass;
|
||||
@@ -46,6 +49,7 @@ use stdClass;
|
||||
/**
|
||||
* Class VerifyDatabase.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class VerifyDatabase extends Command
|
||||
@@ -66,15 +70,15 @@ class VerifyDatabase extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
// if table does not exist, return false
|
||||
if (!Schema::hasTable('users')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->reportObject('budget');
|
||||
$this->reportObject('category');
|
||||
$this->reportEmptyBudgets();
|
||||
$this->reportEmptyCategories();
|
||||
$this->reportObject('tag');
|
||||
$this->reportAccounts();
|
||||
$this->reportBudgetLimits();
|
||||
@@ -145,9 +149,10 @@ class VerifyDatabase extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the situation where the matching transactions
|
||||
* of a journal somehow have non-matching categories
|
||||
* or budgets
|
||||
* Fix the situation where the matching transactions of a journal somehow have non-matching categories or budgets.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
private function fixBadMeta(): void
|
||||
{
|
||||
@@ -208,6 +213,12 @@ class VerifyDatabase extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure amounts are stored correctly.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
private function fixDoubleAmounts(): void
|
||||
{
|
||||
$count = 0;
|
||||
@@ -257,7 +268,7 @@ class VerifyDatabase extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Removes bills from journals that should not have bills.
|
||||
*/
|
||||
private function removeBills(): void
|
||||
{
|
||||
@@ -305,7 +316,7 @@ class VerifyDatabase extends Command
|
||||
/**
|
||||
* Reports on accounts with no transactions.
|
||||
*/
|
||||
private function reportAccounts()
|
||||
private function reportAccounts(): void
|
||||
{
|
||||
$set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
->leftJoin('users', 'accounts.user_id', '=', 'users.id')
|
||||
@@ -378,6 +389,82 @@ class VerifyDatabase extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on budgets with no transactions or journals.
|
||||
*/
|
||||
private function reportEmptyBudgets(): void
|
||||
{
|
||||
$set = Budget::leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull('budget_transaction_journal.budget_id')
|
||||
->whereNull('budgets.deleted_at')
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$objName = $entry->name;
|
||||
try {
|
||||
$objName = Crypt::decrypt($objName);
|
||||
} catch (DecryptException $e) {
|
||||
// it probably was not encrypted.
|
||||
Log::debug(sprintf('Not a problem: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
// also count the transactions:
|
||||
$countTransactions = DB::table('budget_transaction')->where('budget_id', $entry->id)->count();
|
||||
|
||||
if (0 === $countTransactions) {
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has budget #%d ("%s") which has no transactions.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$objName
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on categories with no transactions or journals.
|
||||
*/
|
||||
private function reportEmptyCategories(): void
|
||||
{
|
||||
$set = Category::leftJoin('category_transaction_journal', 'categories.id', '=', 'category_transaction_journal.category_id')
|
||||
->leftJoin('users', 'categories.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull('category_transaction_journal.category_id')
|
||||
->whereNull('categories.deleted_at')
|
||||
->get(['categories.id', 'categories.name', 'categories.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$objName = $entry->name;
|
||||
try {
|
||||
$objName = Crypt::decrypt($objName);
|
||||
} catch (DecryptException $e) {
|
||||
// it probably was not encrypted.
|
||||
Log::debug(sprintf('Not a problem: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
// also count the transactions:
|
||||
$countTransactions = DB::table('category_transaction')->where('category_id', $entry->id)->count();
|
||||
|
||||
if (0 === $countTransactions) {
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has category #%d ("%s") which has no transactions.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$objName
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on journals with bad account types linked to them.
|
||||
*/
|
||||
@@ -483,12 +570,13 @@ class VerifyDatabase extends Command
|
||||
$plural = str_plural($name);
|
||||
$class = sprintf('FireflyIII\Models\%s', ucfirst($name));
|
||||
$field = 'tag' === $name ? 'tag' : 'name';
|
||||
$set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id')
|
||||
->leftJoin('users', $plural . '.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull($name . '_transaction_journal.' . $name . '_id')
|
||||
->whereNull($plural . '.deleted_at')
|
||||
->get([$plural . '.id', $plural . '.' . $field . ' as name', $plural . '.user_id', 'users.email']);
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id')
|
||||
->leftJoin('users', $plural . '.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull($name . '_transaction_journal.' . $name . '_id')
|
||||
->whereNull($plural . '.deleted_at')
|
||||
->get([$plural . '.id', $plural . '.' . $field . ' as name', $plural . '.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
@@ -497,6 +585,7 @@ class VerifyDatabase extends Command
|
||||
$objName = Crypt::decrypt($objName);
|
||||
} catch (DecryptException $e) {
|
||||
// it probably was not encrypted.
|
||||
Log::debug(sprintf('Not a problem: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
$line = sprintf(
|
||||
@@ -524,7 +613,8 @@ class VerifyDatabase extends Command
|
||||
$sum = (string)$user->transactions()->sum('amount');
|
||||
if (0 !== bccomp($sum, '0')) {
|
||||
$this->error('Error: Transactions for user #' . $user->id . ' (' . $user->email . ') are off by ' . $sum . '!');
|
||||
} else {
|
||||
}
|
||||
if (0 === bccomp($sum, '0')) {
|
||||
$this->info(sprintf('Amount integrity OK for user #%d', $user->id));
|
||||
}
|
||||
}
|
||||
@@ -554,7 +644,7 @@ class VerifyDatabase extends Command
|
||||
/**
|
||||
* Report on transfers that have budgets.
|
||||
*/
|
||||
private function reportTransfersBudgets()
|
||||
private function reportTransfersBudgets(): void
|
||||
{
|
||||
$set = TransactionJournal::distinct()
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
|
@@ -34,15 +34,6 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
*/
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* The Artisan commands provided by your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands
|
||||
= [
|
||||
];
|
||||
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*/
|
||||
@@ -50,6 +41,7 @@ class Kernel extends ConsoleKernel
|
||||
{
|
||||
$this->load(__DIR__ . '/Commands');
|
||||
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
|
||||
|
@@ -35,13 +35,9 @@ class AdminRequestedTestMessage extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string The users IP address */
|
||||
public $ipAddress;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
/** @var User The user */
|
||||
public $user;
|
||||
|
||||
/**
|
||||
|
@@ -34,13 +34,9 @@ class RegisteredUser extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string The users IP address */
|
||||
public $ipAddress;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
/** @var User The user */
|
||||
public $user;
|
||||
|
||||
/**
|
||||
|
@@ -34,18 +34,12 @@ class RequestedNewPassword extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string The users IP address */
|
||||
public $ipAddress;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $token;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
/** @var User The user */
|
||||
public $user;
|
||||
/** @var string The token */
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* Create a new event instance. This event is triggered when a users tries to reset his or her password.
|
||||
|
@@ -1,4 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* RequestedReportOnJournals.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
@@ -16,9 +35,9 @@ class RequestedReportOnJournals
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
/** @var Collection */
|
||||
/** @var Collection The journals to report on. */
|
||||
public $journals;
|
||||
/** @var int */
|
||||
/** @var int The ID of the user. */
|
||||
public $userId;
|
||||
|
||||
/**
|
||||
|
@@ -35,9 +35,7 @@ class RequestedVersionCheckStatus extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
/** @var User The user */
|
||||
public $user;
|
||||
|
||||
/**
|
||||
|
@@ -28,16 +28,17 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* Class StoredTransactionJournal.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class StoredTransactionJournal extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/** @var TransactionJournal */
|
||||
/** @var TransactionJournal The journal that was stored. */
|
||||
public $journal;
|
||||
/** @var int */
|
||||
/** @var int The piggy bank ID. */
|
||||
public $piggyBankId;
|
||||
|
||||
/**
|
||||
|
@@ -37,7 +37,7 @@ class UpdatedTransactionJournal extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/** @var TransactionJournal */
|
||||
/** @var TransactionJournal The journal. */
|
||||
public $journal;
|
||||
|
||||
/**
|
||||
|
@@ -34,13 +34,13 @@ class UserChangedEmail extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/** @var string */
|
||||
/** @var string The user's IP address */
|
||||
public $ipAddress;
|
||||
/** @var string */
|
||||
/** @var string The user's new email address */
|
||||
public $newEmail;
|
||||
/** @var string */
|
||||
/** @var string The user's old email address */
|
||||
public $oldEmail;
|
||||
/** @var User */
|
||||
/** @var User The user itself */
|
||||
public $user;
|
||||
|
||||
/**
|
||||
|
@@ -20,6 +20,8 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
@@ -39,32 +41,16 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
*/
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of the inputs that are never flashed for validation exceptions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dontFlash
|
||||
= [
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dontReport
|
||||
= [
|
||||
];
|
||||
|
||||
/**
|
||||
* Render an exception into an HTTP response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Exception $exception
|
||||
* @param Request $request
|
||||
* @param Exception $exception
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($request, Exception $exception)
|
||||
{
|
||||
@@ -130,18 +116,10 @@ class Handler extends ExceptionHandler
|
||||
{
|
||||
|
||||
$doMailError = env('SEND_ERROR_MESSAGE', true);
|
||||
if (
|
||||
// if the user wants us to mail:
|
||||
$doMailError === true
|
||||
&& (
|
||||
// and if is one of these error instances
|
||||
$exception instanceof FireflyException
|
||||
|| $exception instanceof ErrorException
|
||||
|| $exception instanceof OAuthServerException
|
||||
|
||||
)
|
||||
) {
|
||||
// then, send email
|
||||
// if the user wants us to mail:
|
||||
if (true === $doMailError
|
||||
// and if is one of these error instances
|
||||
&& ($exception instanceof FireflyException || $exception instanceof ErrorException || $exception instanceof OAuthServerException)) {
|
||||
$userData = [
|
||||
'id' => 0,
|
||||
'email' => 'unknown@example.com',
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AttachmentCollector.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -29,6 +28,7 @@ use Crypt;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Storage;
|
||||
@@ -38,15 +38,15 @@ use Storage;
|
||||
*/
|
||||
class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
{
|
||||
/** @var Carbon */
|
||||
/** @var Carbon The end date of the range. */
|
||||
private $end;
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem File system */
|
||||
private $exportDisk;
|
||||
/** @var AttachmentRepositoryInterface */
|
||||
/** @var AttachmentRepositoryInterface Attachment repository */
|
||||
private $repository;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon Start date of range */
|
||||
private $start;
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem Disk with uploads on it */
|
||||
private $uploadDisk;
|
||||
|
||||
/**
|
||||
@@ -64,6 +64,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the routine.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function run(): bool
|
||||
@@ -80,6 +82,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the start and end date.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*/
|
||||
@@ -89,7 +93,10 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
/**
|
||||
* Export attachments.
|
||||
*
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return bool
|
||||
@@ -101,13 +108,13 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
if ($this->uploadDisk->exists($file)) {
|
||||
try {
|
||||
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
|
||||
} catch (DecryptException $e) {
|
||||
} catch (FileNotFoundException|DecryptException $e) {
|
||||
Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($decrypted === false) {
|
||||
if (false === $decrypted) {
|
||||
return false;
|
||||
}
|
||||
$exportFile = $this->exportFileName($attachment);
|
||||
@@ -130,6 +137,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function getAttachments(): Collection
|
||||
|
@@ -33,11 +33,11 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class BasicCollector
|
||||
{
|
||||
/** @var ExportJob */
|
||||
/** @var ExportJob The job to export. */
|
||||
protected $job;
|
||||
/** @var User */
|
||||
/** @var User The user */
|
||||
protected $user;
|
||||
/** @var Collection */
|
||||
/** @var Collection All the entries. */
|
||||
private $entries;
|
||||
|
||||
/**
|
||||
@@ -49,6 +49,8 @@ class BasicCollector
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all entries.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getEntries(): Collection
|
||||
@@ -57,26 +59,32 @@ class BasicCollector
|
||||
}
|
||||
|
||||
/**
|
||||
* Set entries.
|
||||
*
|
||||
* @param Collection $entries
|
||||
*/
|
||||
public function setEntries(Collection $entries)
|
||||
public function setEntries(Collection $entries): void
|
||||
{
|
||||
$this->entries = $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set export job.
|
||||
*
|
||||
* @param ExportJob $job
|
||||
*/
|
||||
public function setJob(ExportJob $job)
|
||||
public function setJob(ExportJob $job): void
|
||||
{
|
||||
$this->job = $job;
|
||||
$this->user = $job->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user)
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
@@ -33,21 +33,29 @@ use Illuminate\Support\Collection;
|
||||
interface CollectorInterface
|
||||
{
|
||||
/**
|
||||
* Get entries.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getEntries(): Collection;
|
||||
|
||||
/**
|
||||
* Run the collector.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function run(): bool;
|
||||
|
||||
/**
|
||||
* Set entries.
|
||||
*
|
||||
* @param Collection $entries
|
||||
*/
|
||||
public function setEntries(Collection $entries);
|
||||
|
||||
/**
|
||||
* Set export job.
|
||||
*
|
||||
* @param ExportJob $job
|
||||
*
|
||||
* @return mixed
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* UploadCollector.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -84,7 +83,10 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
/**
|
||||
* Process new file uploads.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
|
@@ -46,137 +46,65 @@ use FireflyIII\Models\Transaction;
|
||||
*/
|
||||
final class Entry
|
||||
{
|
||||
// @formatter:off
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
/** @var int ID of the journal */
|
||||
public $journal_id;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
/** @var int ID of the transaction */
|
||||
public $transaction_id = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string The date. */
|
||||
public $date;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string The description */
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string The currency code. */
|
||||
public $currency_code;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string The amount. */
|
||||
public $amount;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string The foreign currency code */
|
||||
public $foreign_currency_code = '';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Foreign amount */
|
||||
public $foreign_amount = '0';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Transaction type */
|
||||
public $transaction_type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Asset account ID */
|
||||
public $asset_account_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Asset account name */
|
||||
public $asset_account_name;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Asset account IBAN */
|
||||
public $asset_account_iban;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Asset account BIC */
|
||||
public $asset_account_bic;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Asset account number */
|
||||
public $asset_account_number;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Asset account currency code */
|
||||
public $asset_currency_code;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Opposing account ID */
|
||||
public $opposing_account_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Opposing account name */
|
||||
public $opposing_account_name;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Opposing account IBAN */
|
||||
public $opposing_account_iban;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Opposing account BIC */
|
||||
public $opposing_account_bic;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Opposing account number */
|
||||
public $opposing_account_number;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Opposing account code */
|
||||
public $opposing_currency_code;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Budget ID */
|
||||
public $budget_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Budget name */
|
||||
public $budget_name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Category ID */
|
||||
public $category_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Category name */
|
||||
public $category_name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Bill ID */
|
||||
public $bill_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Bill name */
|
||||
public $bill_name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Notes */
|
||||
public $notes;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string Tags */
|
||||
public $tags;
|
||||
|
||||
|
||||
// @formatter:on
|
||||
|
||||
/**
|
||||
* Entry constructor.
|
||||
*/
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ExpandedProcessor.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,6 +19,8 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Export;
|
||||
@@ -50,23 +51,23 @@ use ZipArchive;
|
||||
*/
|
||||
class ExpandedProcessor implements ProcessorInterface
|
||||
{
|
||||
/** @var Collection */
|
||||
/** @var Collection All accounts */
|
||||
public $accounts;
|
||||
/** @var string */
|
||||
/** @var string The export format*/
|
||||
public $exportFormat;
|
||||
/** @var bool */
|
||||
/** @var bool Should include attachments */
|
||||
public $includeAttachments;
|
||||
/** @var bool */
|
||||
/** @var bool Should include old uploads */
|
||||
public $includeOldUploads;
|
||||
/** @var ExportJob */
|
||||
/** @var ExportJob The export job itself */
|
||||
public $job;
|
||||
/** @var array */
|
||||
/** @var array The settings*/
|
||||
public $settings;
|
||||
/** @var Collection */
|
||||
/** @var Collection The entries to export. */
|
||||
private $exportEntries;
|
||||
/** @var Collection */
|
||||
/** @var Collection The files to export */
|
||||
private $files;
|
||||
/** @var Collection */
|
||||
/** @var Collection The journals. */
|
||||
private $journals;
|
||||
|
||||
/**
|
||||
@@ -80,6 +81,8 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all attachments
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function collectAttachments(): bool
|
||||
@@ -143,6 +146,8 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get old oploads.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function collectOldUploads(): bool
|
||||
@@ -158,6 +163,8 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert journals to export objects.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function convertJournals(): bool
|
||||
@@ -173,6 +180,8 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ZIP file.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws FireflyException
|
||||
@@ -204,6 +213,8 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the journals.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exportJournals(): bool
|
||||
@@ -219,6 +230,8 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get files.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getFiles(): Collection
|
||||
@@ -231,7 +244,7 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
*
|
||||
* @param array $settings
|
||||
*/
|
||||
public function setSettings(array $settings)
|
||||
public function setSettings(array $settings): void
|
||||
{
|
||||
// save settings
|
||||
$this->settings = $settings;
|
||||
@@ -243,9 +256,9 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Delete files.
|
||||
*/
|
||||
private function deleteFiles()
|
||||
private function deleteFiles():void
|
||||
{
|
||||
$disk = Storage::disk('export');
|
||||
foreach ($this->getFiles() as $file) {
|
||||
@@ -254,6 +267,8 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get currencies.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
|
@@ -32,9 +32,9 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class BasicExporter
|
||||
{
|
||||
/** @var ExportJob */
|
||||
/** @var ExportJob The export job */
|
||||
protected $job;
|
||||
/** @var Collection */
|
||||
/** @var Collection The entries */
|
||||
private $entries;
|
||||
|
||||
/**
|
||||
@@ -46,6 +46,8 @@ class BasicExporter
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all entries.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getEntries(): Collection
|
||||
@@ -54,17 +56,21 @@ class BasicExporter
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all entries.
|
||||
*
|
||||
* @param Collection $entries
|
||||
*/
|
||||
public function setEntries(Collection $entries)
|
||||
public function setEntries(Collection $entries): void
|
||||
{
|
||||
$this->entries = $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the job.
|
||||
*
|
||||
* @param ExportJob $job
|
||||
*/
|
||||
public function setJob(ExportJob $job)
|
||||
public function setJob(ExportJob $job): void
|
||||
{
|
||||
$this->job = $job;
|
||||
}
|
||||
|
@@ -33,10 +33,12 @@ use Storage;
|
||||
*/
|
||||
class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
{
|
||||
/** @var string */
|
||||
/** @var string Filename */
|
||||
private $fileName;
|
||||
|
||||
/**
|
||||
* Get file name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName(): string
|
||||
@@ -45,6 +47,8 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Run collector.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
@@ -83,6 +87,9 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a temp file.
|
||||
*/
|
||||
private function tempFile()
|
||||
{
|
||||
$this->fileName = $this->job->key . '-records.csv';
|
||||
|
@@ -33,26 +33,36 @@ use Illuminate\Support\Collection;
|
||||
interface ExporterInterface
|
||||
{
|
||||
/**
|
||||
* Get entries.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getEntries(): Collection;
|
||||
|
||||
/**
|
||||
* Get file name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName(): string;
|
||||
|
||||
/**
|
||||
* Run exporter.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function run(): bool;
|
||||
|
||||
/**
|
||||
* Set entries.
|
||||
*
|
||||
* @param Collection $entries
|
||||
*/
|
||||
public function setEntries(Collection $entries);
|
||||
|
||||
/**
|
||||
* Set job.
|
||||
*
|
||||
* @param ExportJob $job
|
||||
*/
|
||||
public function setJob(ExportJob $job);
|
||||
|
@@ -37,41 +37,57 @@ interface ProcessorInterface
|
||||
public function __construct();
|
||||
|
||||
/**
|
||||
* Collect all attachments.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function collectAttachments(): bool;
|
||||
|
||||
/**
|
||||
* Collect all journals.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function collectJournals(): bool;
|
||||
|
||||
/**
|
||||
* Collect old uploads.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function collectOldUploads(): bool;
|
||||
|
||||
/**
|
||||
* Convert all journals.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function convertJournals(): bool;
|
||||
|
||||
/**
|
||||
* Create a zip file.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createZipFile(): bool;
|
||||
|
||||
/**
|
||||
* Export journals.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exportJournals(): bool;
|
||||
|
||||
/**
|
||||
* Get all files.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getFiles(): Collection;
|
||||
|
||||
/**
|
||||
* Set the settings.
|
||||
*
|
||||
* @param array $settings
|
||||
*/
|
||||
public function setSettings(array $settings);
|
||||
|
@@ -20,10 +20,14 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Services\Internal\Support\AccountServiceTrait;
|
||||
@@ -44,56 +48,63 @@ class AccountFactory
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function create(array $data): Account
|
||||
{
|
||||
$type = $this->getAccountType($data['account_type_id'], $data['accountType']);
|
||||
$type = $this->getAccountType($data['account_type_id'], $data['accountType']);
|
||||
|
||||
if (null === $type) {
|
||||
throw new FireflyException(
|
||||
sprintf('AccountFactory::create() was unable to find account type #%d ("%s").', $data['account_type_id'], $data['accountType'])
|
||||
);
|
||||
}
|
||||
|
||||
$data['iban'] = $this->filterIban($data['iban']);
|
||||
|
||||
|
||||
// account may exist already:
|
||||
$existingAccount = $this->find($data['name'], $type->type);
|
||||
if (null !== $existingAccount) {
|
||||
return $existingAccount;
|
||||
$return = $this->find($data['name'], $type->type);
|
||||
|
||||
|
||||
if (null === $return) {
|
||||
// create it:
|
||||
$databaseData
|
||||
= [
|
||||
'user_id' => $this->user->id,
|
||||
'account_type_id' => $type->id,
|
||||
'name' => $data['name'],
|
||||
'virtual_balance' => $data['virtualBalance'] ?? '0',
|
||||
'active' => true === $data['active'],
|
||||
'iban' => $data['iban'],
|
||||
];
|
||||
|
||||
// remove virtual balance when not an asset account:
|
||||
if ($type->type !== AccountType::ASSET) {
|
||||
$databaseData['virtual_balance'] = '0';
|
||||
}
|
||||
|
||||
// fix virtual balance when it's empty
|
||||
if ('' === $databaseData['virtual_balance']) {
|
||||
$databaseData['virtual_balance'] = '0';
|
||||
}
|
||||
|
||||
$return = Account::create($databaseData);
|
||||
$this->updateMetaData($return, $data);
|
||||
|
||||
if ($type->type === AccountType::ASSET) {
|
||||
if ($this->validIBData($data)) {
|
||||
$this->updateIB($return, $data);
|
||||
}
|
||||
if (!$this->validIBData($data)) {
|
||||
$this->deleteIB($return);
|
||||
}
|
||||
}
|
||||
$this->updateNote($return, $data['notes'] ?? '');
|
||||
}
|
||||
|
||||
|
||||
// create it:
|
||||
$databaseData
|
||||
= [
|
||||
'user_id' => $this->user->id,
|
||||
'account_type_id' => $type->id,
|
||||
'name' => $data['name'],
|
||||
'virtual_balance' => $data['virtualBalance'] ?? '0',
|
||||
'active' => true === $data['active'],
|
||||
'iban' => $data['iban'],
|
||||
];
|
||||
|
||||
// remove virtual balance when not an asset account:
|
||||
if ($type->type !== AccountType::ASSET) {
|
||||
$databaseData['virtual_balance'] = '0';
|
||||
}
|
||||
|
||||
// fix virtual balance when it's empty
|
||||
if ($databaseData['virtual_balance'] === '') {
|
||||
$databaseData['virtual_balance'] = '0';
|
||||
}
|
||||
|
||||
$newAccount = Account::create($databaseData);
|
||||
$this->updateMetaData($newAccount, $data);
|
||||
|
||||
if ($this->validIBData($data) && $type->type === AccountType::ASSET) {
|
||||
$this->updateIB($newAccount, $data);
|
||||
}
|
||||
if (!$this->validIBData($data) && $type->type === AccountType::ASSET) {
|
||||
$this->deleteIB($newAccount);
|
||||
}
|
||||
// update note:
|
||||
if (isset($data['notes'])) {
|
||||
$this->updateNote($newAccount, $data['notes']);
|
||||
}
|
||||
|
||||
return $newAccount;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,15 +117,16 @@ class AccountFactory
|
||||
{
|
||||
$type = AccountType::whereType($accountType)->first();
|
||||
$accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']);
|
||||
|
||||
$return = null;
|
||||
/** @var Account $object */
|
||||
foreach ($accounts as $object) {
|
||||
if ($object->name === $accountName) {
|
||||
return $object;
|
||||
$return = $object;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,30 +134,35 @@ class AccountFactory
|
||||
* @param string $accountType
|
||||
*
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function findOrCreate(string $accountName, string $accountType): Account
|
||||
{
|
||||
$type = AccountType::whereType($accountType)->first();
|
||||
$accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']);
|
||||
|
||||
$return = null;
|
||||
/** @var Account $object */
|
||||
foreach ($accounts as $object) {
|
||||
if ($object->name === $accountName) {
|
||||
return $object;
|
||||
$return = $object;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (null === $return) {
|
||||
$return = $this->create(
|
||||
[
|
||||
'user_id' => $this->user->id,
|
||||
'name' => $accountName,
|
||||
'account_type_id' => $type->id,
|
||||
'accountType' => null,
|
||||
'virtualBalance' => '0',
|
||||
'iban' => null,
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $this->create(
|
||||
[
|
||||
'user_id' => $this->user->id,
|
||||
'name' => $accountName,
|
||||
'account_type_id' => $type->id,
|
||||
'accountType' => null,
|
||||
'virtualBalance' => '0',
|
||||
'iban' => null,
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,18 +178,23 @@ class AccountFactory
|
||||
* @param null|string $accountType
|
||||
*
|
||||
* @return AccountType|null
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
protected function getAccountType(?int $accountTypeId, ?string $accountType): ?AccountType
|
||||
{
|
||||
$accountTypeId = (int)$accountTypeId;
|
||||
$result = null;
|
||||
if ($accountTypeId > 0) {
|
||||
return AccountType::find($accountTypeId);
|
||||
$result = AccountType::find($accountTypeId);
|
||||
}
|
||||
$type = config('firefly.accountTypeByIdentifier.' . (string)$accountType);
|
||||
$result = AccountType::whereType($type)->first();
|
||||
if (null === $result && null !== $accountType) {
|
||||
// try as full name:
|
||||
$result = AccountType::whereType($accountType)->first();
|
||||
if (null === $result) {
|
||||
/** @var string $type */
|
||||
$type = (string)config('firefly.accountTypeByIdentifier.' . (string)$accountType);
|
||||
$result = AccountType::whereType($type)->first();
|
||||
if (null === $result && null !== $accountType) {
|
||||
// try as full name:
|
||||
$result = AccountType::whereType($accountType)->first();
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
@@ -81,25 +81,19 @@ class BillFactory
|
||||
{
|
||||
$billId = (int)$billId;
|
||||
$billName = (string)$billName;
|
||||
|
||||
$bill = null;
|
||||
// first find by ID:
|
||||
if ($billId > 0) {
|
||||
/** @var Bill $bill */
|
||||
$bill = $this->user->bills()->find($billId);
|
||||
if (null !== $bill) {
|
||||
return $bill;
|
||||
}
|
||||
}
|
||||
|
||||
// then find by name:
|
||||
if (\strlen($billName) > 0) {
|
||||
if (null === $bill && \strlen($billName) > 0) {
|
||||
$bill = $this->findByName($billName);
|
||||
if (null !== $bill) {
|
||||
return $bill;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return $bill;
|
||||
|
||||
}
|
||||
|
||||
@@ -112,22 +106,24 @@ class BillFactory
|
||||
{
|
||||
/** @var Collection $collection */
|
||||
$collection = $this->user->bills()->get();
|
||||
$return = null;
|
||||
/** @var Bill $bill */
|
||||
foreach ($collection as $bill) {
|
||||
Log::debug(sprintf('"%s" vs. "%s"', $bill->name, $name));
|
||||
if ($bill->name === $name) {
|
||||
return $bill;
|
||||
$return = $bill;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Bill::Find by name returns NULL based on "%s"', $name));
|
||||
Log::debug(sprintf('Bill::find("%s") by name returns null? %s', $name, var_export($return, true)));
|
||||
|
||||
return null;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user)
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* BudgetFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -19,7 +18,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
@@ -30,7 +29,7 @@ use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class BudgetFactory
|
||||
* Class BudgetFactory.
|
||||
*/
|
||||
class BudgetFactory
|
||||
{
|
||||
@@ -43,13 +42,14 @@ class BudgetFactory
|
||||
* @param null|string $budgetName
|
||||
*
|
||||
* @return Budget|null
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function find(?int $budgetId, ?string $budgetName): ?Budget
|
||||
{
|
||||
$budgetId = (int)$budgetId;
|
||||
$budgetName = (string)$budgetName;
|
||||
|
||||
if (\strlen($budgetName) === 0 && $budgetId === 0) {
|
||||
if (0 === $budgetId && '' === $budgetName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class BudgetFactory
|
||||
}
|
||||
}
|
||||
|
||||
if (\strlen($budgetName) > 0) {
|
||||
if ('' !== $budgetName) {
|
||||
$budget = $this->findByName($budgetName);
|
||||
if (null !== $budget) {
|
||||
return $budget;
|
||||
@@ -94,7 +94,7 @@ class BudgetFactory
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user)
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CategoryFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -19,7 +18,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
@@ -64,6 +63,7 @@ class CategoryFactory
|
||||
* @param null|string $categoryName
|
||||
*
|
||||
* @return Category|null
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function findOrCreate(?int $categoryId, ?string $categoryName): ?Category
|
||||
{
|
||||
@@ -72,7 +72,7 @@ class CategoryFactory
|
||||
|
||||
Log::debug(sprintf('Going to find category with ID %d and name "%s"', $categoryId, $categoryName));
|
||||
|
||||
if ('' === $categoryName && $categoryId === 0) {
|
||||
if ('' === $categoryName && 0 === $categoryId) {
|
||||
return null;
|
||||
}
|
||||
// first by ID:
|
||||
@@ -104,7 +104,7 @@ class CategoryFactory
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user)
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PiggyBankEventFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -19,7 +18,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
@@ -43,6 +42,7 @@ class PiggyBankEventFactory
|
||||
* @param PiggyBank|null $piggyBank
|
||||
*
|
||||
* @return PiggyBankEvent|null
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function create(TransactionJournal $journal, ?PiggyBank $piggyBank): ?PiggyBankEvent
|
||||
{
|
||||
@@ -51,7 +51,6 @@ class PiggyBankEventFactory
|
||||
return null;
|
||||
}
|
||||
|
||||
// is a transfer?
|
||||
if (!(TransactionType::TRANSFER === $journal->transactionType->type)) {
|
||||
Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id));
|
||||
|
||||
@@ -62,7 +61,6 @@ class PiggyBankEventFactory
|
||||
$piggyRepos = app(PiggyBankRepositoryInterface::class);
|
||||
$piggyRepos->setUser($journal->user);
|
||||
|
||||
// repetition exists?
|
||||
$repetition = $piggyRepos->getRepetition($piggyBank);
|
||||
if (null === $repetition) {
|
||||
Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d')));
|
||||
@@ -70,7 +68,6 @@ class PiggyBankEventFactory
|
||||
return null;
|
||||
}
|
||||
|
||||
// get the amount
|
||||
$amount = $piggyRepos->getExactAmount($piggyBank, $repetition, $journal);
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
Log::debug('Amount is zero, will not create event.');
|
||||
@@ -78,10 +75,8 @@ class PiggyBankEventFactory
|
||||
return null;
|
||||
}
|
||||
|
||||
// update amount
|
||||
$piggyRepos->addAmountToRepetition($repetition, $amount);
|
||||
$event = $piggyRepos->createEventWithJournal($piggyBank, $amount, $journal);
|
||||
|
||||
Log::debug(sprintf('Created piggy bank event #%d', $event->id));
|
||||
|
||||
return $event;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PiggyBankFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -19,7 +18,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
@@ -41,12 +40,13 @@ class PiggyBankFactory
|
||||
* @param null|string $piggyBankName
|
||||
*
|
||||
* @return PiggyBank|null
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank
|
||||
{
|
||||
$piggyBankId = (int)$piggyBankId;
|
||||
$piggyBankName = (string)$piggyBankName;
|
||||
if (\strlen($piggyBankName) === 0 && $piggyBankId === 0) {
|
||||
if ('' === $piggyBankName && 0 === $piggyBankId) {
|
||||
return null;
|
||||
}
|
||||
// first find by ID:
|
||||
@@ -92,7 +92,7 @@ class PiggyBankFactory
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user)
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
|
@@ -18,12 +18,14 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Services\Internal\Support\RecurringTransactionTrait;
|
||||
@@ -56,6 +58,9 @@ class RecurrenceFactory
|
||||
|
||||
return null;
|
||||
}
|
||||
/** @var Carbon $firstDate */
|
||||
$firstDate = $data['recurrence']['first_date'];
|
||||
|
||||
$repetitions = (int)$data['recurrence']['repetitions'];
|
||||
$recurrence = new Recurrence(
|
||||
[
|
||||
@@ -63,7 +68,7 @@ class RecurrenceFactory
|
||||
'transaction_type_id' => $type->id,
|
||||
'title' => $data['recurrence']['title'],
|
||||
'description' => $data['recurrence']['description'],
|
||||
'first_date' => $data['recurrence']['first_date']->format('Y-m-d'),
|
||||
'first_date' => $firstDate->format('Y-m-d'),
|
||||
'repeat_until' => $repetitions > 0 ? null : $data['recurrence']['repeat_until'],
|
||||
'latest_date' => null,
|
||||
'repetitions' => $data['recurrence']['repetitions'],
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TagFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -19,6 +18,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TransactionCurrencyFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,6 +19,10 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
@@ -63,13 +66,14 @@ class TransactionCurrencyFactory
|
||||
* @param null|string $currencyCode
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function find(?int $currencyId, ?string $currencyCode): ?TransactionCurrency
|
||||
{
|
||||
$currencyCode = (string)$currencyCode;
|
||||
$currencyId = (int)$currencyId;
|
||||
|
||||
if ('' === $currencyCode && $currencyId === 0) {
|
||||
if ('' === $currencyCode && 0 === $currencyId) {
|
||||
Log::warning('Cannot find anything on empty currency code and empty currency ID!');
|
||||
|
||||
return null;
|
||||
|
@@ -50,6 +50,7 @@ class TransactionFactory
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function create(array $data): ?Transaction
|
||||
{
|
||||
@@ -89,37 +90,41 @@ class TransactionFactory
|
||||
*
|
||||
* @return Collection
|
||||
* @throws FireflyException
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function createPair(TransactionJournal $journal, array $data): Collection
|
||||
{
|
||||
Log::debug('Start of TransactionFactory::createPair()');
|
||||
Log::debug('Start of TransactionFactory::createPair()', $data);
|
||||
// all this data is the same for both transactions:
|
||||
$currency = $this->findCurrency($data['currency_id'], $data['currency_code']);
|
||||
$description = $journal->description === $data['description'] ? null : $data['description'];
|
||||
|
||||
// type of source account depends on journal type:
|
||||
$sourceType = $this->accountType($journal, 'source');
|
||||
Log::debug(sprintf('Expect source account to be of type %s', $sourceType));
|
||||
$sourceAccount = $this->findAccount($sourceType, $data['source_id'], $data['source_name']);
|
||||
|
||||
// same for destination account:
|
||||
// type of source account and destination account depends on journal type:
|
||||
$sourceType = $this->accountType($journal, 'source');
|
||||
$destinationType = $this->accountType($journal, 'destination');
|
||||
Log::debug(sprintf('Expect source destination to be of type %s', $destinationType));
|
||||
|
||||
Log::debug(sprintf('Expect source account to be of type "%s"', $sourceType));
|
||||
Log::debug(sprintf('Expect source destination to be of type "%s"', $destinationType));
|
||||
|
||||
// find source and destination account:
|
||||
$sourceAccount = $this->findAccount($sourceType, $data['source_id'], $data['source_name']);
|
||||
$destinationAccount = $this->findAccount($destinationType, $data['destination_id'], $data['destination_name']);
|
||||
|
||||
if (null === $sourceAccount || null === $destinationAccount) {
|
||||
throw new FireflyException('Could not determine source or destination account.');
|
||||
}
|
||||
|
||||
Log::debug(sprintf('Source type is "%s", destination type is "%s"', $sourceAccount->accountType->type, $destinationAccount->accountType->type));
|
||||
// throw big fat error when source type === dest type
|
||||
if ($sourceAccount->accountType->type === $destinationAccount->accountType->type
|
||||
&& ($journal->transactionType->type !== TransactionType::TRANSFER
|
||||
&& $journal->transactionType->type !== TransactionType::RECONCILIATION)
|
||||
) {
|
||||
// throw big fat error when source type === dest type and it's not a transfer or reconciliation.
|
||||
if ($sourceAccount->accountType->type === $destinationAccount->accountType->type && $journal->transactionType->type !== TransactionType::TRANSFER) {
|
||||
throw new FireflyException(sprintf('Source and destination account cannot be both of the type "%s"', $destinationAccount->accountType->type));
|
||||
}
|
||||
if ($sourceAccount->accountType->type !== AccountType::ASSET && $destinationAccount->accountType->type !== AccountType::ASSET) {
|
||||
throw new FireflyException('At least one of the accounts must be an asset account.');
|
||||
}
|
||||
|
||||
// first make a "negative" (source) transaction based on the data in the array.
|
||||
$source = $this->create(
|
||||
[
|
||||
'description' => $description,
|
||||
@@ -132,8 +137,7 @@ class TransactionFactory
|
||||
'identifier' => $data['identifier'],
|
||||
]
|
||||
);
|
||||
// then make a "positive" transaction based on the data in the array.
|
||||
$dest = $this->create(
|
||||
$dest = $this->create(
|
||||
[
|
||||
'description' => $description,
|
||||
'amount' => app('steam')->positive((string)$data['amount']),
|
||||
@@ -145,6 +149,9 @@ class TransactionFactory
|
||||
'identifier' => $data['identifier'],
|
||||
]
|
||||
);
|
||||
if (null === $source || null === $dest) {
|
||||
throw new FireflyException('Could not create transactions.');
|
||||
}
|
||||
|
||||
// set foreign currency
|
||||
$foreign = $this->findCurrency($data['foreign_currency_id'], $data['foreign_currency_code']);
|
||||
@@ -178,7 +185,7 @@ class TransactionFactory
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user)
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
@@ -37,14 +37,18 @@ use Log;
|
||||
class TransactionJournalFactory
|
||||
{
|
||||
use JournalServiceTrait, TransactionTypeTrait;
|
||||
/** @var User */
|
||||
/** @var User The user */
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* Store a new transaction journal.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionJournal
|
||||
* @throws FireflyException
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function create(array $data): TransactionJournal
|
||||
{
|
||||
@@ -124,6 +128,8 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a piggy bank to this journal.
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
* @param array $data
|
||||
*/
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TransactionJournalMetaFactory.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -19,6 +18,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
@@ -38,6 +38,8 @@ class TransactionJournalMetaFactory
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionJournalMeta|null
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function updateOrCreate(array $data): ?TransactionJournalMeta
|
||||
{
|
||||
@@ -57,7 +59,7 @@ class TransactionJournalMetaFactory
|
||||
if ($data['data'] instanceof Carbon) {
|
||||
$value = $data['data']->toW3cString();
|
||||
}
|
||||
if ((string)$value === '') {
|
||||
if ('' === (string)$value) {
|
||||
// don't store blank strings.
|
||||
if (null !== $entry) {
|
||||
try {
|
||||
|
@@ -19,6 +19,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
@@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Generator\Chart\Basic;
|
||||
|
||||
use FireflyIII\Support\ChartColour;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class ChartJsGenerator.
|
||||
@@ -90,7 +89,7 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
if (isset($set['currency_symbol'])) {
|
||||
$currentSet['currency_symbol'] = $set['currency_symbol'];
|
||||
}
|
||||
if(isset($set['backgroundColor'])) {
|
||||
if (isset($set['backgroundColor'])) {
|
||||
$currentSet['backgroundColor'] = $set['backgroundColor'];
|
||||
}
|
||||
$chartData['datasets'][] = $currentSet;
|
||||
@@ -130,7 +129,7 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
$index = 0;
|
||||
foreach ($data as $key => $value) {
|
||||
// make larger than 0
|
||||
$chartData['datasets'][0]['data'][] = (float)Steam::positive($value);
|
||||
$chartData['datasets'][0]['data'][] = (float)app('steam')->positive($value);
|
||||
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
|
||||
$chartData['labels'][] = $key;
|
||||
++$index;
|
||||
|
@@ -31,17 +31,20 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class MonthReportGenerator implements ReportGeneratorInterface
|
||||
{
|
||||
/** @var Collection */
|
||||
/** @var Collection The accounts involved in the report. */
|
||||
private $accounts;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon The end date */
|
||||
private $end;
|
||||
/** @var Collection */
|
||||
/** @var Collection The expense accounts. */
|
||||
private $expense;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon The start date. */
|
||||
private $start;
|
||||
|
||||
/**
|
||||
* Generate the report.
|
||||
*
|
||||
* @return string
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
@@ -57,6 +60,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set accounts.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -69,6 +74,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set budgets.
|
||||
*
|
||||
* @param Collection $budgets
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -79,6 +86,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set categories.
|
||||
*
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -89,6 +98,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set end date.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -101,6 +112,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set expense collection.
|
||||
*
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -113,6 +126,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set start date.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -125,6 +140,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set collection of tags.
|
||||
*
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -135,6 +152,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the preferred period.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function preferredPeriod(): string
|
||||
|
@@ -27,9 +27,9 @@ namespace FireflyIII\Generator\Report\Account;
|
||||
*/
|
||||
class MultiYearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
|
||||
/**
|
||||
* Returns the preferred period.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function preferredPeriod(): string
|
||||
|
@@ -27,9 +27,9 @@ namespace FireflyIII\Generator\Report\Account;
|
||||
*/
|
||||
class YearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
|
||||
/**
|
||||
* Returns the preferred period.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function preferredPeriod(): string
|
||||
|
@@ -18,33 +18,40 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Audit;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class MonthReportGenerator.
|
||||
*/
|
||||
class MonthReportGenerator implements ReportGeneratorInterface
|
||||
{
|
||||
/** @var Collection */
|
||||
/** @var Collection The accounts used. */
|
||||
private $accounts;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon End date of the report. */
|
||||
private $end;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon Start date of the report. */
|
||||
private $start;
|
||||
|
||||
/**
|
||||
* Generates the report.
|
||||
*
|
||||
* @return string
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
@@ -77,6 +84,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Account collection setter.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -89,6 +98,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Budget collection setter.
|
||||
*
|
||||
* @param Collection $budgets
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -99,6 +110,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Category collection setter.
|
||||
*
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -109,6 +122,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* End date setter.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -121,6 +136,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Expenses collection setter.
|
||||
*
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -131,6 +148,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Start date collection setter.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -143,6 +162,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Tags collection setter.
|
||||
*
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -153,26 +174,37 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the audit report.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // not that long
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getAuditReport(Account $account, Carbon $date): array
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface $currencyRepos */
|
||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$accountRepository->setUser($account->user);
|
||||
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end);
|
||||
$journals = $collector->getJournals();
|
||||
$journals = $journals->reverse();
|
||||
$dayBeforeBalance = Steam::balance($account, $date);
|
||||
$dayBeforeBalance = app('steam')->balance($account, $date);
|
||||
$startBalance = $dayBeforeBalance;
|
||||
$currency = $currencyRepos->find((int)$account->getMeta('currency_id'));
|
||||
$currency = $currencyRepos->findNull((int)$accountRepository->getMetaValue($account, 'currency_id'));
|
||||
|
||||
if (null === $currency) {
|
||||
throw new FireflyException('Unexpected NULL value in account currency preference.');
|
||||
}
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journals as $transaction) {
|
||||
@@ -183,17 +215,16 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
$transactionAmount = $transaction->transaction_foreign_amount;
|
||||
}
|
||||
|
||||
$newBalance = bcadd($startBalance, $transactionAmount);
|
||||
$transaction->after = $newBalance;
|
||||
$startBalance = $newBalance;
|
||||
$transaction->currency = $currency;
|
||||
$newBalance = bcadd($startBalance, $transactionAmount);
|
||||
$transaction->after = $newBalance;
|
||||
$startBalance = $newBalance;
|
||||
}
|
||||
|
||||
$return = [
|
||||
'journals' => $journals->reverse(),
|
||||
'exists' => $journals->count() > 0,
|
||||
'end' => $this->end->formatLocalized((string)trans('config.month_and_day')),
|
||||
'endBalance' => Steam::balance($account, $this->end),
|
||||
'endBalance' => app('steam')->balance($account, $this->end),
|
||||
'dayBefore' => $date->formatLocalized((string)trans('config.month_and_day')),
|
||||
'dayBeforeBalance' => $dayBeforeBalance,
|
||||
];
|
||||
|
@@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Audit;
|
||||
*/
|
||||
class MultiYearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
}
|
||||
|
@@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Audit;
|
||||
*/
|
||||
class YearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Budget;
|
||||
@@ -39,17 +41,15 @@ use Log;
|
||||
*/
|
||||
class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
{
|
||||
/** @var Collection */
|
||||
/** @var Collection The accounts in the report. */
|
||||
private $accounts;
|
||||
/** @var Collection */
|
||||
/** @var Collection The budgets in the report. */
|
||||
private $budgets;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon The end date. */
|
||||
private $end;
|
||||
/** @var Collection */
|
||||
/** @var Collection The expenses in the report. */
|
||||
private $expenses;
|
||||
/** @var Collection */
|
||||
private $income;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon The start date. */
|
||||
private $start;
|
||||
|
||||
/**
|
||||
@@ -57,12 +57,14 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->income = new Collection;
|
||||
$this->expenses = new Collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the report.
|
||||
*
|
||||
* @return string
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
@@ -83,6 +85,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved accounts.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -95,6 +99,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved budgets.
|
||||
*
|
||||
* @param Collection $budgets
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -107,6 +113,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused category setter.
|
||||
*
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -117,6 +125,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the end date of the report.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -129,6 +139,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused expense setter.
|
||||
*
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -139,6 +151,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the start date of the report.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -151,6 +165,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused tags setter.
|
||||
*
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -161,6 +177,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the expenses.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
protected function getExpenses(): Collection
|
||||
@@ -188,6 +206,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize a collection by its budget.
|
||||
*
|
||||
* @param Collection $collection
|
||||
*
|
||||
* @return array
|
||||
|
@@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Budget;
|
||||
*/
|
||||
class MultiYearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
}
|
||||
|
@@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Budget;
|
||||
*/
|
||||
class YearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** @noinspection MultipleReturnStatementsInspection */
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Category;
|
||||
@@ -40,17 +42,17 @@ use Log;
|
||||
*/
|
||||
class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
{
|
||||
/** @var Collection */
|
||||
/** @var Collection The included accounts */
|
||||
private $accounts;
|
||||
/** @var Collection */
|
||||
/** @var Collection The included categories */
|
||||
private $categories;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon The end date */
|
||||
private $end;
|
||||
/** @var Collection */
|
||||
/** @var Collection The expenses */
|
||||
private $expenses;
|
||||
/** @var Collection */
|
||||
/** @var Collection The income in the report. */
|
||||
private $income;
|
||||
/** @var Carbon */
|
||||
/** @var Carbon The start date. */
|
||||
private $start;
|
||||
|
||||
/**
|
||||
@@ -63,7 +65,10 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the report.
|
||||
*
|
||||
* @return string
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
@@ -101,6 +106,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved accounts.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -113,6 +120,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty budget setter.
|
||||
*
|
||||
* @param Collection $budgets
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -123,6 +132,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the categories involved in this report.
|
||||
*
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -135,6 +146,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the end date for this report.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -147,6 +160,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expenses involved in this report.
|
||||
*
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -157,6 +172,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the start date for this report.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -169,6 +186,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused tag setter.
|
||||
*
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
@@ -179,6 +198,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the expenses for this report.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
protected function getExpenses(): Collection
|
||||
@@ -206,6 +227,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the income for this report.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
protected function getIncome(): Collection
|
||||
@@ -230,6 +253,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize the category.
|
||||
*
|
||||
* @param Collection $collection
|
||||
*
|
||||
* @return array
|
||||
|
@@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Category;
|
||||
*/
|
||||
class MultiYearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
}
|
||||
|
@@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Category;
|
||||
*/
|
||||
class YearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user