mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge pull request #7565 from firefly-iii/chore/cleanup
chore: code cleanup.
This commit is contained in:
commit
023a3fdade
24
.ci/php-cs-fixer/composer.lock
generated
24
.ci/php-cs-fixer/composer.lock
generated
@ -744,16 +744,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v6.2.10",
|
||||
"version": "v6.2.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "12288d9f4500f84a4d02254d4aa968b15488476f"
|
||||
"reference": "5aa03db8ef0a5457c316ec580e69562d97734c77"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/12288d9f4500f84a4d02254d4aa968b15488476f",
|
||||
"reference": "12288d9f4500f84a4d02254d4aa968b15488476f",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/5aa03db8ef0a5457c316ec580e69562d97734c77",
|
||||
"reference": "5aa03db8ef0a5457c316ec580e69562d97734c77",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -820,7 +820,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v6.2.10"
|
||||
"source": "https://github.com/symfony/console/tree/v6.2.11"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -836,7 +836,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-04-28T13:37:43+00:00"
|
||||
"time": "2023-05-26T08:16:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@ -1755,16 +1755,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v6.2.10",
|
||||
"version": "v6.2.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e"
|
||||
"reference": "97ae9721bead9d1a39b5650e2f4b7834b93b539c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e",
|
||||
"reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/97ae9721bead9d1a39b5650e2f4b7834b93b539c",
|
||||
"reference": "97ae9721bead9d1a39b5650e2f4b7834b93b539c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1796,7 +1796,7 @@
|
||||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v6.2.10"
|
||||
"source": "https://github.com/symfony/process/tree/v6.2.11"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1812,7 +1812,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-04-18T13:56:57+00:00"
|
||||
"time": "2023-05-19T07:42:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
|
@ -32,7 +32,10 @@ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
cd $SCRIPT_DIR/php-cs-fixer
|
||||
composer update
|
||||
rm -f .php-cs-fixer.cache
|
||||
echo 'Removed cache...'
|
||||
echo 'Running...'
|
||||
PHP_CS_FIXER_IGNORE_ENV=true ./vendor/bin/php-cs-fixer fix --config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php --allow-risky=yes
|
||||
echo 'Done!'
|
||||
cd $SCRIPT_DIR/..
|
||||
|
||||
exit 0
|
||||
|
@ -92,7 +92,11 @@ class AccountController extends Controller
|
||||
|
||||
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
|
||||
$balance = app('steam')->balance($account, $date);
|
||||
$nameWithBalance = sprintf('%s (%s)', $account->name, app('amount')->formatAnything($currency, $balance, false));
|
||||
$nameWithBalance = sprintf(
|
||||
'%s (%s)',
|
||||
$account->name,
|
||||
app('amount')->formatAnything($currency, $balance, false)
|
||||
);
|
||||
}
|
||||
|
||||
$return[] = [
|
||||
@ -113,10 +117,10 @@ class AccountController extends Controller
|
||||
usort(
|
||||
$return,
|
||||
function ($a, $b) use ($order) {
|
||||
$pos_a = array_search($a['type'], $order, true);
|
||||
$pos_b = array_search($b['type'], $order, true);
|
||||
$posA = array_search($a['type'], $order, true);
|
||||
$posB = array_search($b['type'], $order, true);
|
||||
|
||||
return $pos_a - $pos_b;
|
||||
return $posA - $posB;
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -74,6 +74,42 @@ abstract class Controller extends BaseController
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to help build URL's.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final protected function buildParams(): string
|
||||
{
|
||||
$return = '?';
|
||||
$params = [];
|
||||
foreach ($this->parameters as $key => $value) {
|
||||
if ('page' === $key) {
|
||||
continue;
|
||||
}
|
||||
if ($value instanceof Carbon) {
|
||||
$params[$key] = $value->format('Y-m-d');
|
||||
continue;
|
||||
}
|
||||
$params[$key] = $value;
|
||||
}
|
||||
|
||||
return $return.http_build_query($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Manager
|
||||
*/
|
||||
final protected function getManager(): Manager
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager();
|
||||
$baseUrl = request()->getSchemeAndHttpHost().'/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
return $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to grab all parameters from the URL.
|
||||
*
|
||||
@ -110,7 +146,13 @@ abstract class Controller extends BaseController
|
||||
$obj = Carbon::parse($date);
|
||||
} catch (InvalidDateException|InvalidFormatException $e) {
|
||||
// don't care
|
||||
app('log')->warning(sprintf('Ignored invalid date "%s" in API controller parameter check: %s', substr($date, 0, 20), $e->getMessage()));
|
||||
app('log')->warning(
|
||||
sprintf(
|
||||
'Ignored invalid date "%s" in API controller parameter check: %s',
|
||||
substr($date, 0, 20),
|
||||
$e->getMessage()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
$bag->set($field, $obj);
|
||||
@ -169,41 +211,4 @@ abstract class Controller extends BaseController
|
||||
|
||||
return $bag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to help build URL's.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final protected function buildParams(): string
|
||||
{
|
||||
$return = '?';
|
||||
$params = [];
|
||||
foreach ($this->parameters as $key => $value) {
|
||||
if ('page' === $key) {
|
||||
continue;
|
||||
}
|
||||
if ($value instanceof Carbon) {
|
||||
$params[$key] = $value->format('Y-m-d');
|
||||
continue;
|
||||
}
|
||||
$params[$key] = $value;
|
||||
}
|
||||
|
||||
return $return.http_build_query($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Manager
|
||||
*/
|
||||
final protected function getManager(): Manager
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager();
|
||||
$baseUrl = request()->getSchemeAndHttpHost().'/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
return $manager;
|
||||
}
|
||||
}
|
||||
|
@ -201,91 +201,6 @@ class DestroyController extends Controller
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyBudgets(): void
|
||||
{
|
||||
/** @var AvailableBudgetRepositoryInterface $abRepository */
|
||||
$abRepository = app(AvailableBudgetRepositoryInterface::class);
|
||||
$abRepository->destroyAll();
|
||||
|
||||
/** @var BudgetLimitRepositoryInterface $blRepository */
|
||||
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$blRepository->destroyAll();
|
||||
|
||||
/** @var BudgetRepositoryInterface $budgetRepository */
|
||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$budgetRepository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyBills(): void
|
||||
{
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyPiggyBanks(): void
|
||||
{
|
||||
/** @var PiggyBankRepositoryInterface $repository */
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyRules(): void
|
||||
{
|
||||
/** @var RuleGroupRepositoryInterface $repository */
|
||||
$repository = app(RuleGroupRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyRecurringTransactions(): void
|
||||
{
|
||||
/** @var RecurringRepositoryInterface $repository */
|
||||
$repository = app(RecurringRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyCategories(): void
|
||||
{
|
||||
/** @var CategoryRepositoryInterface $categoryRepos */
|
||||
$categoryRepos = app(CategoryRepositoryInterface::class);
|
||||
$categoryRepos->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyTags(): void
|
||||
{
|
||||
/** @var TagRepositoryInterface $tagRepository */
|
||||
$tagRepository = app(TagRepositoryInterface::class);
|
||||
$tagRepository->destroyAll();
|
||||
}
|
||||
|
||||
private function destroyObjectGroups(): void
|
||||
{
|
||||
/** @var ObjectGroupRepositoryInterface $repository */
|
||||
$repository = app(ObjectGroupRepositoryInterface::class);
|
||||
$repository->deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
*/
|
||||
@ -311,6 +226,91 @@ class DestroyController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyBills(): void
|
||||
{
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyBudgets(): void
|
||||
{
|
||||
/** @var AvailableBudgetRepositoryInterface $abRepository */
|
||||
$abRepository = app(AvailableBudgetRepositoryInterface::class);
|
||||
$abRepository->destroyAll();
|
||||
|
||||
/** @var BudgetLimitRepositoryInterface $blRepository */
|
||||
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$blRepository->destroyAll();
|
||||
|
||||
/** @var BudgetRepositoryInterface $budgetRepository */
|
||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$budgetRepository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyCategories(): void
|
||||
{
|
||||
/** @var CategoryRepositoryInterface $categoryRepos */
|
||||
$categoryRepos = app(CategoryRepositoryInterface::class);
|
||||
$categoryRepos->destroyAll();
|
||||
}
|
||||
|
||||
private function destroyObjectGroups(): void
|
||||
{
|
||||
/** @var ObjectGroupRepositoryInterface $repository */
|
||||
$repository = app(ObjectGroupRepositoryInterface::class);
|
||||
$repository->deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyPiggyBanks(): void
|
||||
{
|
||||
/** @var PiggyBankRepositoryInterface $repository */
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyRecurringTransactions(): void
|
||||
{
|
||||
/** @var RecurringRepositoryInterface $repository */
|
||||
$repository = app(RecurringRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyRules(): void
|
||||
{
|
||||
/** @var RuleGroupRepositoryInterface $repository */
|
||||
$repository = app(RuleGroupRepositoryInterface::class);
|
||||
$repository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function destroyTags(): void
|
||||
{
|
||||
/** @var TagRepositoryInterface $tagRepository */
|
||||
$tagRepository = app(TagRepositoryInterface::class);
|
||||
$tagRepository->destroyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
*/
|
||||
|
@ -69,34 +69,6 @@ class ExportController extends Controller
|
||||
return $this->returnExport('accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return LaravelResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function returnExport(string $key): LaravelResponse
|
||||
{
|
||||
$date = date('Y-m-d-H-i-s');
|
||||
$fileName = sprintf('%s-export-%s.csv', $date, $key);
|
||||
$data = $this->exporter->export();
|
||||
|
||||
/** @var LaravelResponse $response */
|
||||
$response = response($data[$key]);
|
||||
$response
|
||||
->header('Content-Description', 'File Transfer')
|
||||
->header('Content-Type', 'application/octet-stream')
|
||||
->header('Content-Disposition', 'attachment; filename='.$fileName)
|
||||
->header('Content-Transfer-Encoding', 'binary')
|
||||
->header('Connection', 'Keep-Alive')
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', (string)strlen($data[$key]));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportBills
|
||||
@ -228,4 +200,32 @@ class ExportController extends Controller
|
||||
|
||||
return $this->returnExport('transactions');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return LaravelResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function returnExport(string $key): LaravelResponse
|
||||
{
|
||||
$date = date('Y-m-d-H-i-s');
|
||||
$fileName = sprintf('%s-export-%s.csv', $date, $key);
|
||||
$data = $this->exporter->export();
|
||||
|
||||
/** @var LaravelResponse $response */
|
||||
$response = response($data[$key]);
|
||||
$response
|
||||
->header('Content-Description', 'File Transfer')
|
||||
->header('Content-Type', 'application/octet-stream')
|
||||
->header('Content-Disposition', 'attachment; filename='.$fileName)
|
||||
->header('Content-Transfer-Encoding', 'binary')
|
||||
->header('Connection', 'Keep-Alive')
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', (string)strlen($data[$key]));
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ class PurgeController extends Controller
|
||||
* TODO cleanup and use repositories.
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/purgeData
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function purge(): JsonResponse
|
||||
|
@ -29,8 +29,8 @@ use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
|
@ -34,8 +34,8 @@ use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
/**
|
||||
* Class StoreController
|
||||
|
@ -97,21 +97,6 @@ class ShowController extends Controller
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/getTransactionByJournal
|
||||
*
|
||||
* Show a single transaction, by transaction journal.
|
||||
*
|
||||
* @param TransactionJournal $transactionJournal
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function showJournal(TransactionJournal $transactionJournal): JsonResponse
|
||||
{
|
||||
return $this->show($transactionJournal->transactionGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/getTransaction
|
||||
@ -148,4 +133,19 @@ class ShowController extends Controller
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/getTransactionByJournal
|
||||
*
|
||||
* Show a single transaction, by transaction journal.
|
||||
*
|
||||
* @param TransactionJournal $transactionJournal
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function showJournal(TransactionJournal $transactionJournal): JsonResponse
|
||||
{
|
||||
return $this->show($transactionJournal->transactionGroup);
|
||||
}
|
||||
}
|
||||
|
@ -35,9 +35,9 @@ use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
|
@ -32,8 +32,8 @@ use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
|
@ -97,6 +97,35 @@ class UpdateController extends Controller
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/enableCurrency
|
||||
*
|
||||
* Enable a currency.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function enable(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$this->repository->enable($currency);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
|
||||
/** @var CurrencyTransformer $transformer */
|
||||
$transformer = app(CurrencyTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($currency, $transformer, 'currencies');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/defaultCurrency
|
||||
@ -128,35 +157,6 @@ class UpdateController extends Controller
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/enableCurrency
|
||||
*
|
||||
* Enable a currency.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function enable(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$this->repository->enable($currency);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
|
||||
/** @var CurrencyTransformer $transformer */
|
||||
$transformer = app(CurrencyTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($currency, $transformer, 'currencies');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/updateCurrency
|
||||
|
@ -32,10 +32,10 @@ use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
@ -61,6 +61,7 @@ class AccountController extends Controller
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/search/searchAccounts
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse|Response
|
||||
|
@ -121,6 +121,30 @@ class BasicController extends Controller
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if date is outside session range.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool // Validate a preference
|
||||
{
|
||||
$result = false;
|
||||
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
|
||||
$result = true;
|
||||
}
|
||||
// start and end in the past? use $end
|
||||
if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
@ -399,28 +423,4 @@ class BasicController extends Controller
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if date is outside session range.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool // Validate a preference
|
||||
{
|
||||
$result = false;
|
||||
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
|
||||
$result = true;
|
||||
}
|
||||
// start and end in the past? use $end
|
||||
if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -94,42 +94,6 @@ class ConfigurationController extends Controller
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all config values.
|
||||
*
|
||||
* @return array
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
private function getDynamicConfiguration(): array
|
||||
{
|
||||
$isDemoSite = app('fireflyconfig')->get('is_demo_site');
|
||||
$updateCheck = app('fireflyconfig')->get('permission_update_check');
|
||||
$lastCheck = app('fireflyconfig')->get('last_update_check');
|
||||
$singleUser = app('fireflyconfig')->get('single_user_mode');
|
||||
|
||||
return [
|
||||
'is_demo_site' => $isDemoSite?->data,
|
||||
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
|
||||
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
|
||||
'single_user_mode' => $singleUser?->data,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getStaticConfiguration(): array
|
||||
{
|
||||
$list = EitherConfigKey::$static;
|
||||
$return = [];
|
||||
foreach ($list as $key) {
|
||||
$return[$key] = config($key);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/configuration/getSingleConfiguration
|
||||
@ -200,4 +164,40 @@ class ConfigurationController extends Controller
|
||||
|
||||
return response()->json(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all config values.
|
||||
*
|
||||
* @return array
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
private function getDynamicConfiguration(): array
|
||||
{
|
||||
$isDemoSite = app('fireflyconfig')->get('is_demo_site');
|
||||
$updateCheck = app('fireflyconfig')->get('permission_update_check');
|
||||
$lastCheck = app('fireflyconfig')->get('last_update_check');
|
||||
$singleUser = app('fireflyconfig')->get('single_user_mode');
|
||||
|
||||
return [
|
||||
'is_demo_site' => $isDemoSite?->data,
|
||||
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
|
||||
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
|
||||
'single_user_mode' => $singleUser?->data,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getStaticConfiguration(): array
|
||||
{
|
||||
$list = EitherConfigKey::$static;
|
||||
$return = [];
|
||||
foreach ($list as $key) {
|
||||
$return[$key] = config($key);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ class ShowController extends Controller
|
||||
*
|
||||
* @param Webhook $webhook
|
||||
* @param TransactionGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function triggerTransaction(Webhook $webhook, TransactionGroup $group): JsonResponse
|
||||
@ -141,6 +142,7 @@ class ShowController extends Controller
|
||||
|
||||
// trigger event to send them:
|
||||
event(new RequestedSendWebhookMessages());
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ class MoveTransactionsRequest extends FormRequest
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function validateMove(Validator $validator): void
|
||||
|
@ -30,9 +30,9 @@ use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use FireflyIII\Validation\Api\Data\Bulk\ValidatesBulkTransactionQuery;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class TransactionRequest
|
||||
|
@ -82,28 +82,6 @@ class GenericRequest extends FormRequest
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseAccounts(): void
|
||||
{
|
||||
if (0 !== $this->accounts->count()) {
|
||||
return;
|
||||
}
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$array = $this->get('accounts');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $accountId) {
|
||||
$accountId = (int)$accountId;
|
||||
$account = $repository->find($accountId);
|
||||
if (null !== $account) {
|
||||
$this->accounts->push($account);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
@ -114,28 +92,6 @@ class GenericRequest extends FormRequest
|
||||
return $this->bills;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseBills(): void
|
||||
{
|
||||
if (0 !== $this->bills->count()) {
|
||||
return;
|
||||
}
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$array = $this->get('bills');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $billId) {
|
||||
$billId = (int)$billId;
|
||||
$bill = $repository->find($billId);
|
||||
if (null !== $bill) {
|
||||
$this->bills->push($bill);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
@ -146,28 +102,6 @@ class GenericRequest extends FormRequest
|
||||
return $this->budgets;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseBudgets(): void
|
||||
{
|
||||
if (0 !== $this->budgets->count()) {
|
||||
return;
|
||||
}
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$array = $this->get('budgets');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $budgetId) {
|
||||
$budgetId = (int)$budgetId;
|
||||
$budget = $repository->find($budgetId);
|
||||
if (null !== $budget) {
|
||||
$this->budgets->push($budget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
@ -178,28 +112,6 @@ class GenericRequest extends FormRequest
|
||||
return $this->categories;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseCategories(): void
|
||||
{
|
||||
if (0 !== $this->categories->count()) {
|
||||
return;
|
||||
}
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$array = $this->get('categories');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $categoryId) {
|
||||
$categoryId = (int)$categoryId;
|
||||
$category = $repository->find($categoryId);
|
||||
if (null !== $category) {
|
||||
$this->categories->push($category);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
@ -268,6 +180,114 @@ class GenericRequest extends FormRequest
|
||||
return $this->tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
// this is cheating, but it works to initialize the collections.
|
||||
$this->accounts = new Collection();
|
||||
$this->budgets = new Collection();
|
||||
$this->categories = new Collection();
|
||||
$this->bills = new Collection();
|
||||
$this->tags = new Collection();
|
||||
|
||||
return [
|
||||
'start' => 'required|date',
|
||||
'end' => 'required|date|after_or_equal:start',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseAccounts(): void
|
||||
{
|
||||
if (0 !== $this->accounts->count()) {
|
||||
return;
|
||||
}
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$array = $this->get('accounts');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $accountId) {
|
||||
$accountId = (int)$accountId;
|
||||
$account = $repository->find($accountId);
|
||||
if (null !== $account) {
|
||||
$this->accounts->push($account);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseBills(): void
|
||||
{
|
||||
if (0 !== $this->bills->count()) {
|
||||
return;
|
||||
}
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$array = $this->get('bills');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $billId) {
|
||||
$billId = (int)$billId;
|
||||
$bill = $repository->find($billId);
|
||||
if (null !== $bill) {
|
||||
$this->bills->push($bill);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseBudgets(): void
|
||||
{
|
||||
if (0 !== $this->budgets->count()) {
|
||||
return;
|
||||
}
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$array = $this->get('budgets');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $budgetId) {
|
||||
$budgetId = (int)$budgetId;
|
||||
$budget = $repository->find($budgetId);
|
||||
if (null !== $budget) {
|
||||
$this->budgets->push($budget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseCategories(): void
|
||||
{
|
||||
if (0 !== $this->categories->count()) {
|
||||
return;
|
||||
}
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$array = $this->get('categories');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $categoryId) {
|
||||
$categoryId = (int)$categoryId;
|
||||
$category = $repository->find($categoryId);
|
||||
if (null !== $category) {
|
||||
$this->categories->push($category);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -289,24 +309,4 @@ class GenericRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
// this is cheating, but it works to initialize the collections.
|
||||
$this->accounts = new Collection();
|
||||
$this->budgets = new Collection();
|
||||
$this->categories = new Collection();
|
||||
$this->bills = new Collection();
|
||||
$this->tags = new Collection();
|
||||
|
||||
return [
|
||||
'start' => 'required|date',
|
||||
'end' => 'required|date|after_or_equal:start',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ use FireflyIII\Support\Request\AppendsLocationData;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class UpdateRequest
|
||||
@ -77,6 +76,7 @@ class UpdateRequest extends FormRequest
|
||||
'liability_start_date' => ['liability_start_date', 'date'],
|
||||
];
|
||||
$data = $this->getAllData($fields);
|
||||
|
||||
return $this->appendLocationData($data, null);
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,8 @@ use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Validator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class StoreRequest
|
||||
@ -105,8 +105,8 @@ class StoreRequest extends FormRequest
|
||||
$validator->after(
|
||||
static function (Validator $validator) {
|
||||
$data = $validator->getData();
|
||||
$min = (string) ($data['amount_min'] ?? '0');
|
||||
$max = (string) ($data['amount_max'] ?? '0');
|
||||
$min = (string)($data['amount_min'] ?? '0');
|
||||
$max = (string)($data['amount_max'] ?? '0');
|
||||
|
||||
if (1 === bccomp($min, $max)) {
|
||||
$validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max'));
|
||||
|
@ -73,65 +73,6 @@ class StoreRequest extends FormRequest
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array|null $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return [];
|
||||
}
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return[] = $this->getSingleTransactionData($transaction);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the repetition data as it is found in the submitted data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getRepetitionData(): array
|
||||
{
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array|null $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return [];
|
||||
}
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$current = [];
|
||||
if (array_key_exists('type', $repetition)) {
|
||||
$current['type'] = $repetition['type'];
|
||||
}
|
||||
if (array_key_exists('moment', $repetition)) {
|
||||
$current['moment'] = $repetition['moment'];
|
||||
}
|
||||
if (array_key_exists('skip', $repetition)) {
|
||||
$current['skip'] = (int)$repetition['skip'];
|
||||
}
|
||||
if (array_key_exists('weekend', $repetition)) {
|
||||
$current['weekend'] = (int)$repetition['weekend'];
|
||||
}
|
||||
|
||||
$return[] = $current;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
@ -198,4 +139,63 @@ class StoreRequest extends FormRequest
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the repetition data as it is found in the submitted data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getRepetitionData(): array
|
||||
{
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array|null $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return [];
|
||||
}
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$current = [];
|
||||
if (array_key_exists('type', $repetition)) {
|
||||
$current['type'] = $repetition['type'];
|
||||
}
|
||||
if (array_key_exists('moment', $repetition)) {
|
||||
$current['moment'] = $repetition['moment'];
|
||||
}
|
||||
if (array_key_exists('skip', $repetition)) {
|
||||
$current['skip'] = (int)$repetition['skip'];
|
||||
}
|
||||
if (array_key_exists('weekend', $repetition)) {
|
||||
$current['weekend'] = (int)$repetition['weekend'];
|
||||
}
|
||||
|
||||
$return[] = $current;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array|null $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return [];
|
||||
}
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return[] = $this->getSingleTransactionData($transaction);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
@ -80,70 +80,6 @@ class UpdateRequest extends FormRequest
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the repetition data as it is found in the submitted data.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function getRepetitionData(): ?array
|
||||
{
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array|null $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return null;
|
||||
}
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$current = [];
|
||||
if (array_key_exists('type', $repetition)) {
|
||||
$current['type'] = $repetition['type'];
|
||||
}
|
||||
|
||||
if (array_key_exists('moment', $repetition)) {
|
||||
$current['moment'] = (string)$repetition['moment'];
|
||||
}
|
||||
|
||||
if (array_key_exists('skip', $repetition)) {
|
||||
$current['skip'] = (int)$repetition['skip'];
|
||||
}
|
||||
|
||||
if (array_key_exists('weekend', $repetition)) {
|
||||
$current['weekend'] = (int)$repetition['weekend'];
|
||||
}
|
||||
$return[] = $current;
|
||||
}
|
||||
if (0 === count($return)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function getTransactionData(): ?array
|
||||
{
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array|null $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return null;
|
||||
}
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return[] = $this->getSingleTransactionData($transaction);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
@ -212,4 +148,68 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the repetition data as it is found in the submitted data.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function getRepetitionData(): ?array
|
||||
{
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array|null $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return null;
|
||||
}
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$current = [];
|
||||
if (array_key_exists('type', $repetition)) {
|
||||
$current['type'] = $repetition['type'];
|
||||
}
|
||||
|
||||
if (array_key_exists('moment', $repetition)) {
|
||||
$current['moment'] = (string)$repetition['moment'];
|
||||
}
|
||||
|
||||
if (array_key_exists('skip', $repetition)) {
|
||||
$current['skip'] = (int)$repetition['skip'];
|
||||
}
|
||||
|
||||
if (array_key_exists('weekend', $repetition)) {
|
||||
$current['weekend'] = (int)$repetition['weekend'];
|
||||
}
|
||||
$return[] = $current;
|
||||
}
|
||||
if (0 === count($return)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function getTransactionData(): ?array
|
||||
{
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array|null $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return null;
|
||||
}
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return[] = $this->getSingleTransactionData($transaction);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
@ -67,48 +67,6 @@ class StoreRequest extends FormRequest
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRuleTriggers(): array
|
||||
{
|
||||
$triggers = $this->get('triggers');
|
||||
$return = [];
|
||||
if (is_array($triggers)) {
|
||||
foreach ($triggers as $trigger) {
|
||||
$return[] = [
|
||||
'type' => $trigger['type'],
|
||||
'value' => $trigger['value'],
|
||||
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
|
||||
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRuleActions(): array
|
||||
{
|
||||
$actions = $this->get('actions');
|
||||
$return = [];
|
||||
if (is_array($actions)) {
|
||||
foreach ($actions as $action) {
|
||||
$return[] = [
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'true')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
@ -162,21 +120,6 @@ class StoreRequest extends FormRequest
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no triggers in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneTrigger(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$triggers = $data['triggers'] ?? [];
|
||||
// need at least one trigger
|
||||
if (!is_countable($triggers) || 0 === count($triggers)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
@ -192,6 +135,35 @@ class StoreRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no ACTIVE actions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneActiveAction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? [];
|
||||
// need at least one trigger
|
||||
if (!is_countable($actions) || 0 === count($actions)) {
|
||||
return;
|
||||
}
|
||||
$allInactive = true;
|
||||
$inactiveIndex = 0;
|
||||
foreach ($actions as $index => $action) {
|
||||
$active = array_key_exists('active', $action) ? $action['active'] : true; // assume true
|
||||
if (true === $active) {
|
||||
$allInactive = false;
|
||||
}
|
||||
if (false === $active) {
|
||||
$inactiveIndex = $index;
|
||||
}
|
||||
}
|
||||
if (true === $allInactive) {
|
||||
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no ACTIVE triggers in the array of data.
|
||||
*
|
||||
@ -222,31 +194,59 @@ class StoreRequest extends FormRequest
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no ACTIVE actions in the array of data.
|
||||
* Adds an error to the validator when there are no triggers in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneActiveAction(Validator $validator): void
|
||||
protected function atLeastOneTrigger(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? [];
|
||||
$triggers = $data['triggers'] ?? [];
|
||||
// need at least one trigger
|
||||
if (!is_countable($actions) || 0 === count($actions)) {
|
||||
return;
|
||||
}
|
||||
$allInactive = true;
|
||||
$inactiveIndex = 0;
|
||||
foreach ($actions as $index => $action) {
|
||||
$active = array_key_exists('active', $action) ? $action['active'] : true; // assume true
|
||||
if (true === $active) {
|
||||
$allInactive = false;
|
||||
}
|
||||
if (false === $active) {
|
||||
$inactiveIndex = $index;
|
||||
if (!is_countable($triggers) || 0 === count($triggers)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
if (true === $allInactive) {
|
||||
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRuleActions(): array
|
||||
{
|
||||
$actions = $this->get('actions');
|
||||
$return = [];
|
||||
if (is_array($actions)) {
|
||||
foreach ($actions as $action) {
|
||||
$return[] = [
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'true')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRuleTriggers(): array
|
||||
{
|
||||
$triggers = $this->get('triggers');
|
||||
$return = [];
|
||||
if (is_array($triggers)) {
|
||||
foreach ($triggers as $trigger) {
|
||||
$return[] = [
|
||||
'type' => $trigger['type'],
|
||||
'value' => $trigger['value'],
|
||||
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
|
||||
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
@ -52,11 +52,24 @@ class TestRequest extends FormRequest
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @return array
|
||||
*/
|
||||
private function getPage(): int
|
||||
public function rules(): array
|
||||
{
|
||||
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'accounts' => '',
|
||||
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getAccounts(): array
|
||||
{
|
||||
return $this->get('accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,23 +83,10 @@ class TestRequest extends FormRequest
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @return int
|
||||
*/
|
||||
private function getAccounts(): array
|
||||
private function getPage(): int
|
||||
{
|
||||
return $this->get('accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'accounts' => '',
|
||||
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
|
||||
}
|
||||
}
|
||||
|
@ -49,24 +49,6 @@ class TriggerRequest extends FormRequest
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($this->query($field), 0, 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getAccounts(): array
|
||||
{
|
||||
return $this->get('accounts') ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
@ -79,4 +61,22 @@ class TriggerRequest extends FormRequest
|
||||
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getAccounts(): array
|
||||
{
|
||||
return $this->get('accounts') ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($this->query($field), 0, 10));
|
||||
}
|
||||
}
|
||||
|
@ -73,56 +73,6 @@ class UpdateRequest extends FormRequest
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
private function getRuleTriggers(): ?array
|
||||
{
|
||||
if (!$this->has('triggers')) {
|
||||
return null;
|
||||
}
|
||||
$triggers = $this->get('triggers');
|
||||
$return = [];
|
||||
if (is_array($triggers)) {
|
||||
foreach ($triggers as $trigger) {
|
||||
$active = array_key_exists('active', $trigger) ? $trigger['active'] : true;
|
||||
$stopProcessing = array_key_exists('stop_processing', $trigger) ? $trigger['stop_processing'] : false;
|
||||
$return[] = [
|
||||
'type' => $trigger['type'],
|
||||
'value' => $trigger['value'],
|
||||
'active' => $active,
|
||||
'stop_processing' => $stopProcessing,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
private function getRuleActions(): ?array
|
||||
{
|
||||
if (!$this->has('actions')) {
|
||||
return null;
|
||||
}
|
||||
$actions = $this->get('actions');
|
||||
$return = [];
|
||||
if (is_array($actions)) {
|
||||
foreach ($actions as $action) {
|
||||
$return[] = [
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
@ -180,6 +130,21 @@ class UpdateRequest extends FormRequest
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneAction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? null;
|
||||
// need at least one action
|
||||
if (is_array($actions) && 0 === count($actions)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
@ -195,6 +160,36 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneValidAction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? [];
|
||||
$allInactive = true;
|
||||
$inactiveIndex = 0;
|
||||
// need at least one action
|
||||
if (is_array($actions) && 0 === count($actions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($actions as $index => $action) {
|
||||
$active = array_key_exists('active', $action) ? $action['active'] : true; // assume true
|
||||
if (true === $active) {
|
||||
$allInactive = false;
|
||||
}
|
||||
if (false === $active) {
|
||||
$inactiveIndex = $index;
|
||||
}
|
||||
}
|
||||
if (true === $allInactive) {
|
||||
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
@ -225,47 +220,52 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @return array|null
|
||||
*/
|
||||
protected function atLeastOneAction(Validator $validator): void
|
||||
private function getRuleActions(): ?array
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? null;
|
||||
// need at least one action
|
||||
if (is_array($actions) && 0 === count($actions)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
||||
if (!$this->has('actions')) {
|
||||
return null;
|
||||
}
|
||||
$actions = $this->get('actions');
|
||||
$return = [];
|
||||
if (is_array($actions)) {
|
||||
foreach ($actions as $action) {
|
||||
$return[] = [
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @return array|null
|
||||
*/
|
||||
protected function atLeastOneValidAction(Validator $validator): void
|
||||
private function getRuleTriggers(): ?array
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? [];
|
||||
$allInactive = true;
|
||||
$inactiveIndex = 0;
|
||||
// need at least one action
|
||||
if (is_array($actions) && 0 === count($actions)) {
|
||||
return;
|
||||
if (!$this->has('triggers')) {
|
||||
return null;
|
||||
}
|
||||
$triggers = $this->get('triggers');
|
||||
$return = [];
|
||||
if (is_array($triggers)) {
|
||||
foreach ($triggers as $trigger) {
|
||||
$active = array_key_exists('active', $trigger) ? $trigger['active'] : true;
|
||||
$stopProcessing = array_key_exists('stop_processing', $trigger) ? $trigger['stop_processing'] : false;
|
||||
$return[] = [
|
||||
'type' => $trigger['type'],
|
||||
'value' => $trigger['value'],
|
||||
'active' => $active,
|
||||
'stop_processing' => $stopProcessing,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($actions as $index => $action) {
|
||||
$active = array_key_exists('active', $action) ? $action['active'] : true; // assume true
|
||||
if (true === $active) {
|
||||
$allInactive = false;
|
||||
}
|
||||
if (false === $active) {
|
||||
$inactiveIndex = $index;
|
||||
}
|
||||
}
|
||||
if (true === $allInactive) {
|
||||
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
@ -49,24 +49,6 @@ class TestRequest extends FormRequest
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getAccounts(): array
|
||||
{
|
||||
return $this->get('accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
@ -79,4 +61,22 @@ class TestRequest extends FormRequest
|
||||
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getAccounts(): array
|
||||
{
|
||||
return $this->get('accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
|
||||
}
|
||||
}
|
||||
|
@ -50,13 +50,14 @@ class TriggerRequest extends FormRequest
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
* @return array
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
public function rules(): array
|
||||
{
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,13 +69,12 @@ class TriggerRequest extends FormRequest
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function rules(): array
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
];
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ use FireflyIII\Validation\CurrencyValidation;
|
||||
use FireflyIII\Validation\GroupValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Validator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class StoreRequest
|
||||
@ -69,103 +69,6 @@ class StoreRequest extends FormRequest
|
||||
// TODO include location and ability to process it.
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transaction data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
$return = [];
|
||||
/**
|
||||
* @var array $transaction
|
||||
*/
|
||||
foreach ($this->get('transactions') as $transaction) {
|
||||
$object = new NullArrayObject($transaction);
|
||||
$return[] = [
|
||||
'type' => $this->clearString($object['type'], false),
|
||||
'date' => $this->dateFromValue($object['date']),
|
||||
'order' => $this->integerFromValue((string)$object['order']),
|
||||
|
||||
'currency_id' => $this->integerFromValue((string)$object['currency_id']),
|
||||
'currency_code' => $this->clearString((string)$object['currency_code'], false),
|
||||
|
||||
// foreign currency info:
|
||||
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
|
||||
'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code'], false),
|
||||
|
||||
// amount and foreign amount. Cannot be 0.
|
||||
'amount' => $this->clearString((string)$object['amount'], false),
|
||||
'foreign_amount' => $this->clearString((string)$object['foreign_amount'], false),
|
||||
|
||||
// description.
|
||||
'description' => $this->clearString($object['description'], false),
|
||||
|
||||
// source of transaction. If everything is null, assume cash account.
|
||||
'source_id' => $this->integerFromValue((string)$object['source_id']),
|
||||
'source_name' => $this->clearString((string)$object['source_name'], false),
|
||||
'source_iban' => $this->clearString((string)$object['source_iban'], false),
|
||||
'source_number' => $this->clearString((string)$object['source_number'], false),
|
||||
'source_bic' => $this->clearString((string)$object['source_bic'], false),
|
||||
|
||||
// destination of transaction. If everything is null, assume cash account.
|
||||
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
|
||||
'destination_name' => $this->clearString((string)$object['destination_name'], false),
|
||||
'destination_iban' => $this->clearString((string)$object['destination_iban'], false),
|
||||
'destination_number' => $this->clearString((string)$object['destination_number'], false),
|
||||
'destination_bic' => $this->clearString((string)$object['destination_bic'], false),
|
||||
|
||||
// budget info
|
||||
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
|
||||
'budget_name' => $this->clearString((string)$object['budget_name'], false),
|
||||
|
||||
// category info
|
||||
'category_id' => $this->integerFromValue((string)$object['category_id']),
|
||||
'category_name' => $this->clearString((string)$object['category_name'], false),
|
||||
|
||||
// journal bill reference. Optional. Will only work for withdrawals
|
||||
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
|
||||
'bill_name' => $this->clearString((string)$object['bill_name'], false),
|
||||
|
||||
// piggy bank reference. Optional. Will only work for transfers
|
||||
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
|
||||
'piggy_bank_name' => $this->clearString((string)$object['piggy_bank_name'], false),
|
||||
|
||||
// some other interesting properties
|
||||
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
|
||||
'notes' => $this->clearString((string)$object['notes']),
|
||||
'tags' => $this->arrayFromValue($object['tags']),
|
||||
|
||||
// all custom fields:
|
||||
'internal_reference' => $this->clearString((string)$object['internal_reference'], false),
|
||||
'external_id' => $this->clearString((string)$object['external_id'], false),
|
||||
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
|
||||
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
|
||||
'bunq_payment_id' => $this->clearString((string)$object['bunq_payment_id'], false),
|
||||
'external_url' => $this->clearString((string)$object['external_url'], false),
|
||||
|
||||
'sepa_cc' => $this->clearString((string)$object['sepa_cc'], false),
|
||||
'sepa_ct_op' => $this->clearString((string)$object['sepa_ct_op'], false),
|
||||
'sepa_ct_id' => $this->clearString((string)$object['sepa_ct_id'], false),
|
||||
'sepa_db' => $this->clearString((string)$object['sepa_db'], false),
|
||||
'sepa_country' => $this->clearString((string)$object['sepa_country'], false),
|
||||
'sepa_ep' => $this->clearString((string)$object['sepa_ep'], false),
|
||||
'sepa_ci' => $this->clearString((string)$object['sepa_ci'], false),
|
||||
'sepa_batch_id' => $this->clearString((string)$object['sepa_batch_id'], false),
|
||||
// custom date fields. Must be Carbon objects. Presence is optional.
|
||||
'interest_date' => $this->dateFromValue($object['interest_date']),
|
||||
'book_date' => $this->dateFromValue($object['book_date']),
|
||||
'process_date' => $this->dateFromValue($object['process_date']),
|
||||
'due_date' => $this->dateFromValue($object['due_date']),
|
||||
'payment_date' => $this->dateFromValue($object['payment_date']),
|
||||
'invoice_date' => $this->dateFromValue($object['invoice_date']),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
@ -294,4 +197,101 @@ class StoreRequest extends FormRequest
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transaction data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
$return = [];
|
||||
/**
|
||||
* @var array $transaction
|
||||
*/
|
||||
foreach ($this->get('transactions') as $transaction) {
|
||||
$object = new NullArrayObject($transaction);
|
||||
$return[] = [
|
||||
'type' => $this->clearString($object['type'], false),
|
||||
'date' => $this->dateFromValue($object['date']),
|
||||
'order' => $this->integerFromValue((string)$object['order']),
|
||||
|
||||
'currency_id' => $this->integerFromValue((string)$object['currency_id']),
|
||||
'currency_code' => $this->clearString((string)$object['currency_code'], false),
|
||||
|
||||
// foreign currency info:
|
||||
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
|
||||
'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code'], false),
|
||||
|
||||
// amount and foreign amount. Cannot be 0.
|
||||
'amount' => $this->clearString((string)$object['amount'], false),
|
||||
'foreign_amount' => $this->clearString((string)$object['foreign_amount'], false),
|
||||
|
||||
// description.
|
||||
'description' => $this->clearString($object['description'], false),
|
||||
|
||||
// source of transaction. If everything is null, assume cash account.
|
||||
'source_id' => $this->integerFromValue((string)$object['source_id']),
|
||||
'source_name' => $this->clearString((string)$object['source_name'], false),
|
||||
'source_iban' => $this->clearString((string)$object['source_iban'], false),
|
||||
'source_number' => $this->clearString((string)$object['source_number'], false),
|
||||
'source_bic' => $this->clearString((string)$object['source_bic'], false),
|
||||
|
||||
// destination of transaction. If everything is null, assume cash account.
|
||||
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
|
||||
'destination_name' => $this->clearString((string)$object['destination_name'], false),
|
||||
'destination_iban' => $this->clearString((string)$object['destination_iban'], false),
|
||||
'destination_number' => $this->clearString((string)$object['destination_number'], false),
|
||||
'destination_bic' => $this->clearString((string)$object['destination_bic'], false),
|
||||
|
||||
// budget info
|
||||
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
|
||||
'budget_name' => $this->clearString((string)$object['budget_name'], false),
|
||||
|
||||
// category info
|
||||
'category_id' => $this->integerFromValue((string)$object['category_id']),
|
||||
'category_name' => $this->clearString((string)$object['category_name'], false),
|
||||
|
||||
// journal bill reference. Optional. Will only work for withdrawals
|
||||
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
|
||||
'bill_name' => $this->clearString((string)$object['bill_name'], false),
|
||||
|
||||
// piggy bank reference. Optional. Will only work for transfers
|
||||
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
|
||||
'piggy_bank_name' => $this->clearString((string)$object['piggy_bank_name'], false),
|
||||
|
||||
// some other interesting properties
|
||||
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
|
||||
'notes' => $this->clearString((string)$object['notes']),
|
||||
'tags' => $this->arrayFromValue($object['tags']),
|
||||
|
||||
// all custom fields:
|
||||
'internal_reference' => $this->clearString((string)$object['internal_reference'], false),
|
||||
'external_id' => $this->clearString((string)$object['external_id'], false),
|
||||
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
|
||||
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
|
||||
'bunq_payment_id' => $this->clearString((string)$object['bunq_payment_id'], false),
|
||||
'external_url' => $this->clearString((string)$object['external_url'], false),
|
||||
|
||||
'sepa_cc' => $this->clearString((string)$object['sepa_cc'], false),
|
||||
'sepa_ct_op' => $this->clearString((string)$object['sepa_ct_op'], false),
|
||||
'sepa_ct_id' => $this->clearString((string)$object['sepa_ct_id'], false),
|
||||
'sepa_db' => $this->clearString((string)$object['sepa_db'], false),
|
||||
'sepa_country' => $this->clearString((string)$object['sepa_country'], false),
|
||||
'sepa_ep' => $this->clearString((string)$object['sepa_ep'], false),
|
||||
'sepa_ci' => $this->clearString((string)$object['sepa_ci'], false),
|
||||
'sepa_batch_id' => $this->clearString((string)$object['sepa_batch_id'], false),
|
||||
// custom date fields. Must be Carbon objects. Presence is optional.
|
||||
'interest_date' => $this->dateFromValue($object['interest_date']),
|
||||
'book_date' => $this->dateFromValue($object['book_date']),
|
||||
'process_date' => $this->dateFromValue($object['process_date']),
|
||||
'due_date' => $this->dateFromValue($object['due_date']),
|
||||
'payment_date' => $this->dateFromValue($object['payment_date']),
|
||||
'invoice_date' => $this->dateFromValue($object['invoice_date']),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,6 @@ class UpdateRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$this->integerFields = [
|
||||
'order',
|
||||
@ -165,7 +164,7 @@ class UpdateRequest extends FormRequest
|
||||
|
||||
/** @var array $transaction */
|
||||
foreach ($this->get('transactions') as $transaction) {
|
||||
if(!is_array($transaction)) {
|
||||
if (!is_array($transaction)) {
|
||||
throw new FireflyException('Invalid data submitted: transaction is not array.');
|
||||
}
|
||||
// default response is to update nothing in the transaction:
|
||||
@ -292,6 +291,7 @@ class UpdateRequest extends FormRequest
|
||||
/**
|
||||
* @param array $current
|
||||
* @param array $transaction
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getFloatData(array $current, array $transaction): array
|
||||
@ -319,6 +319,7 @@ class UpdateRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
|
||||
return [
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,1000',
|
||||
|
@ -64,9 +64,9 @@ class UpdateRequest extends FormRequest
|
||||
$linkType = $this->route()->parameter('linkType');
|
||||
|
||||
return [
|
||||
'name' => [Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1','max:1024'],
|
||||
'outward' => ['different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1','max:1024'],
|
||||
'inward' => ['different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1','max:1024'],
|
||||
'name' => [Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1', 'max:1024'],
|
||||
'outward' => ['different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1', 'max:1024'],
|
||||
'inward' => ['different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1', 'max:1024'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@ -43,8 +43,8 @@ class AccountController extends Controller
|
||||
{
|
||||
use AccountFilter;
|
||||
|
||||
private array $balanceTypes;
|
||||
private AdminAccountRepositoryInterface $adminRepository;
|
||||
private array $balanceTypes;
|
||||
private AccountRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
|
@ -53,6 +53,7 @@ class AccountController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@ -63,6 +64,7 @@ class AccountController extends Controller
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/charts/getChartAccountOverview
|
||||
*
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
|
@ -64,6 +64,54 @@ class Controller extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param LengthAwarePaginator $paginator
|
||||
* @param AbstractTransformer $transformer
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
final protected function jsonApiList(string $key, LengthAwarePaginator $paginator, AbstractTransformer $transformer): array
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = request()->getSchemeAndHttpHost().'/api/v2';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$objects = $paginator->getCollection();
|
||||
|
||||
// the transformer, at this point, needs to collect information that ALL items in the collection
|
||||
// require, like meta data and stuff like that, and save it for later.
|
||||
$transformer->collectMetaData($objects);
|
||||
|
||||
$resource = new FractalCollection($objects, $transformer, $key);
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return $manager->createData($resource)->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON API object and returns it.
|
||||
*
|
||||
* @param string $key
|
||||
* @param Model $object
|
||||
* @param AbstractTransformer $transformer
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
final protected function jsonApiObject(string $key, Model $object, AbstractTransformer $transformer): array
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager();
|
||||
$baseUrl = request()->getSchemeAndHttpHost().'/api/v2';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$transformer->collectMetaData(new Collection([$object]));
|
||||
|
||||
$resource = new Item($object, $transformer, $key);
|
||||
|
||||
return $manager->createData($resource)->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO duplicate from V1 controller
|
||||
* Method to grab all parameters from the URL.
|
||||
@ -131,49 +179,4 @@ class Controller extends BaseController
|
||||
|
||||
return $bag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param LengthAwarePaginator $paginator
|
||||
* @param AbstractTransformer $transformer
|
||||
* @return array
|
||||
*/
|
||||
final protected function jsonApiList(string $key, LengthAwarePaginator $paginator, AbstractTransformer $transformer): array
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = request()->getSchemeAndHttpHost().'/api/v2';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$objects = $paginator->getCollection();
|
||||
|
||||
// the transformer, at this point, needs to collect information that ALL items in the collection
|
||||
// require, like meta data and stuff like that, and save it for later.
|
||||
$transformer->collectMetaData($objects);
|
||||
|
||||
$resource = new FractalCollection($objects, $transformer, $key);
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return $manager->createData($resource)->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON API object and returns it.
|
||||
*
|
||||
* @param string $key
|
||||
* @param Model $object
|
||||
* @param AbstractTransformer $transformer
|
||||
* @return array
|
||||
*/
|
||||
final protected function jsonApiObject(string $key, Model $object, AbstractTransformer $transformer): array
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager();
|
||||
$baseUrl = request()->getSchemeAndHttpHost().'/api/v2';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$transformer->collectMetaData(new Collection([$object]));
|
||||
|
||||
$resource = new Item($object, $transformer, $key);
|
||||
return $manager->createData($resource)->toArray();
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ class SumController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@ -58,6 +59,7 @@ class SumController extends Controller
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/transactions-sum/getBillsPaidTrSum
|
||||
*
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function paid(DateRequest $request): JsonResponse
|
||||
@ -75,6 +77,7 @@ class SumController extends Controller
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/transactions-sum/getBillsUnpaidTrSum
|
||||
*
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function unpaid(DateRequest $request): JsonResponse
|
||||
|
@ -41,6 +41,7 @@ class ListController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@ -51,6 +52,7 @@ class ListController extends Controller
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/listBudgets
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
@ -61,6 +63,7 @@ class ListController extends Controller
|
||||
|
||||
$paginator = new LengthAwarePaginator($collection, $total, $this->pageSize, $this->parameters->get('page'));
|
||||
$transformer = new BudgetTransformer();
|
||||
|
||||
return response()
|
||||
->api($this->jsonApiList('budgets', $paginator, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
@ -48,6 +48,7 @@ class ShowController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
|
@ -48,6 +48,7 @@ class SumController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@ -58,6 +59,7 @@ class SumController extends Controller
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/getBudgetedForBudget
|
||||
*
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function budgeted(DateRequest $request): JsonResponse
|
||||
@ -72,7 +74,9 @@ class SumController extends Controller
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/getSpentForBudget
|
||||
*
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function spent(DateRequest $request): JsonResponse
|
||||
|
@ -42,6 +42,7 @@ class ListController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(BudgetLimitRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@ -60,6 +61,7 @@ class ListController extends Controller
|
||||
|
||||
$paginator = new LengthAwarePaginator($collection, $total, $this->pageSize, $this->parameters->get('page'));
|
||||
$transformer = new BudgetLimitTransformer();
|
||||
|
||||
return response()
|
||||
->api($this->jsonApiList('budget_limits', $paginator, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
@ -48,6 +48,7 @@ class NetWorthController extends Controller
|
||||
function ($request, $next) {
|
||||
$this->netWorth = app(NetWorthInterface::class);
|
||||
$this->netWorth->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@ -56,7 +57,9 @@ class NetWorthController extends Controller
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/net-worth/getNetWorth
|
||||
*
|
||||
* @param SingleDateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function get(SingleDateRequest $request): JsonResponse
|
||||
|
@ -37,7 +37,9 @@ class PreferencesController extends Controller
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/preferences/getPreference
|
||||
*
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function get(Preference $preference): JsonResponse
|
||||
|
@ -46,6 +46,7 @@ class AccountController extends Controller
|
||||
*
|
||||
* @param ListRequest $request
|
||||
* @param Account $account
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function listTransactions(ListRequest $request, Account $account): JsonResponse
|
||||
|
@ -60,6 +60,7 @@ class AutocompleteRequest extends FormRequest
|
||||
$array = array_diff($array, [AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION]);
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
return [
|
||||
'types' => $array,
|
||||
'query' => $this->convertString('query'),
|
||||
|
@ -31,6 +31,7 @@ use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class AutoSum
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
class AutoSum
|
||||
@ -39,6 +40,7 @@ class AutoSum
|
||||
* @param Collection $objects
|
||||
* @param Closure $getCurrency
|
||||
* @param Closure $getSum
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function autoSum(Collection $objects, Closure $getCurrency, Closure $getSum): array
|
||||
|
@ -91,6 +91,7 @@ class CorrectAmounts extends Command
|
||||
$count = $set->count();
|
||||
if (0 === $count) {
|
||||
$this->info('Correct: All auto budget amounts are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var AutoBudget $item */
|
||||
@ -110,6 +111,7 @@ class CorrectAmounts extends Command
|
||||
$count = $set->count();
|
||||
if (0 === $count) {
|
||||
$this->info('Correct: All available budget amounts are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var AvailableBudget $item */
|
||||
@ -129,6 +131,7 @@ class CorrectAmounts extends Command
|
||||
$count = $set->count();
|
||||
if (0 === $count) {
|
||||
$this->info('Correct: All bill amounts are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var Bill $item */
|
||||
@ -148,6 +151,7 @@ class CorrectAmounts extends Command
|
||||
$count = $set->count();
|
||||
if (0 === $count) {
|
||||
$this->info('Correct: All budget limit amounts are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var BudgetLimit $item */
|
||||
@ -167,6 +171,7 @@ class CorrectAmounts extends Command
|
||||
$count = $set->count();
|
||||
if (0 === $count) {
|
||||
$this->info('Correct: All currency exchange rates are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var BudgetLimit $item */
|
||||
@ -186,6 +191,7 @@ class CorrectAmounts extends Command
|
||||
$count = $set->count();
|
||||
if (0 === $count) {
|
||||
$this->info('Correct: All piggy bank amounts are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var PiggyBankRepetition $item */
|
||||
@ -207,6 +213,7 @@ class CorrectAmounts extends Command
|
||||
$count = $set->count();
|
||||
if (0 === $count) {
|
||||
$this->info('Correct: All recurring transaction amounts are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var PiggyBankRepetition $item */
|
||||
@ -227,6 +234,7 @@ class CorrectAmounts extends Command
|
||||
$count = $set->count();
|
||||
if (0 === $count) {
|
||||
$this->info('Correct: All piggy bank repetition amounts are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var PiggyBankRepetition $item */
|
||||
@ -255,6 +263,7 @@ class CorrectAmounts extends Command
|
||||
}
|
||||
if (0 === $fixed) {
|
||||
$this->info('Correct: All rule trigger amounts are positive.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->line(sprintf('Corrected %d rule trigger amount(s).', $fixed));
|
||||
|
@ -56,6 +56,7 @@ class CorrectDatabase extends Command
|
||||
// if table does not exist, return false
|
||||
if (!Schema::hasTable('users')) {
|
||||
$this->error('No "users"-table, will not continue.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
$commands = [
|
||||
|
@ -130,6 +130,7 @@ class CorrectOpeningBalanceCurrencies extends Command
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@ class FixIbans extends Command
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function countAndCorrectIbans(Collection $accounts): void
|
||||
@ -83,7 +84,8 @@ class FixIbans extends Command
|
||||
if (array_key_exists($iban, $set[$userId])) {
|
||||
// iban already in use! two exceptions exist:
|
||||
if (
|
||||
!(AccountType::EXPENSE === $set[$userId][$iban] && AccountType::REVENUE === $type) && // allowed combination
|
||||
!(AccountType::EXPENSE === $set[$userId][$iban] && AccountType::REVENUE === $type)
|
||||
&& // allowed combination
|
||||
!(AccountType::REVENUE === $set[$userId][$iban] && AccountType::EXPENSE === $type) // also allowed combination.
|
||||
) {
|
||||
$this->line(
|
||||
@ -108,6 +110,7 @@ class FixIbans extends Command
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function filterIbans(Collection $accounts): void
|
||||
|
@ -36,11 +36,13 @@ class TriggerCreditCalculation extends Command
|
||||
public function handle(): int
|
||||
{
|
||||
$this->processAccounts();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function processAccount(Account $account): void
|
||||
|
@ -53,6 +53,7 @@ class CreateGroupMemberships extends Command
|
||||
|
||||
/**
|
||||
* TODO move to helper.
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @throws FireflyException
|
||||
|
@ -85,6 +85,7 @@ class UpdateGroupInformation extends Command
|
||||
$group = $user->userGroup;
|
||||
if (null === $group) {
|
||||
$this->warn(sprintf('User "%s" has no group.', $user->email));
|
||||
|
||||
return;
|
||||
}
|
||||
$set = [
|
||||
@ -112,6 +113,7 @@ class UpdateGroupInformation extends Command
|
||||
* @param User $user
|
||||
* @param UserGroup $group
|
||||
* @param string $className
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function updateGroupInfoForObject(User $user, UserGroup $group, string $className): void
|
||||
@ -120,6 +122,7 @@ class UpdateGroupInformation extends Command
|
||||
$result = $className::where('user_id', $user->id)->where('user_group_id', null)->update(['user_group_id' => $group->id]);
|
||||
} catch (QueryException $e) {
|
||||
$this->error(sprintf('Could not update group information for "%s" because of error "%s"', $className, $e->getMessage()));
|
||||
|
||||
return;
|
||||
}
|
||||
if (0 !== $result) {
|
||||
|
@ -54,7 +54,8 @@ class ForceDecimalSize extends Command
|
||||
protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL and correct amounts (only MySQL).';
|
||||
protected $signature = 'firefly-iii:force-decimal-size';
|
||||
private string $cast;
|
||||
private array $classes = [
|
||||
private array $classes
|
||||
= [
|
||||
'accounts' => Account::class,
|
||||
'auto_budgets' => AutoBudget::class,
|
||||
'available_budgets' => AvailableBudget::class,
|
||||
@ -69,7 +70,8 @@ class ForceDecimalSize extends Command
|
||||
|
||||
private string $operator;
|
||||
private string $regularExpression;
|
||||
private array $tables = [
|
||||
private array $tables
|
||||
= [
|
||||
'accounts' => ['virtual_balance'],
|
||||
'auto_budgets' => ['amount'],
|
||||
'available_budgets' => ['amount'],
|
||||
@ -102,6 +104,7 @@ class ForceDecimalSize extends Command
|
||||
$this->updateDecimals();
|
||||
}
|
||||
$this->line('Done!');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -110,6 +113,7 @@ class ForceDecimalSize extends Command
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
* @param array $fields
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function correctAccountAmounts(TransactionCurrency $currency, array $fields): void
|
||||
@ -134,6 +138,7 @@ class ForceDecimalSize extends Command
|
||||
$result = $query->get(['accounts.*']);
|
||||
if (0 === $result->count()) {
|
||||
$this->line(sprintf('Correct: All accounts in %s', $currency->code));
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var Account $account */
|
||||
@ -164,12 +169,14 @@ class ForceDecimalSize extends Command
|
||||
DB::connection()->getPdo()->sqliteCreateFunction('REGEXP', function ($pattern, $value) {
|
||||
mb_regex_encoding('UTF-8');
|
||||
$pattern = trim($pattern, '"');
|
||||
return (false !== mb_ereg($pattern, (string) $value)) ? 1 : 0;
|
||||
|
||||
return (false !== mb_ereg($pattern, (string)$value)) ? 1 : 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (!in_array((string)config('database.default'), ['mysql', 'pgsql', 'sqlite'], true)) {
|
||||
$this->line(sprintf('Skip correcting amounts, does not support "%s"...', (string)config('database.default')));
|
||||
|
||||
return;
|
||||
}
|
||||
$this->correctAmountsByCurrency();
|
||||
@ -195,6 +202,7 @@ class ForceDecimalSize extends Command
|
||||
* This method loops the available tables that may need fixing, and calls for the right method that can fix them.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return void
|
||||
* @throws FireflyException
|
||||
*/
|
||||
@ -243,8 +251,10 @@ class ForceDecimalSize extends Command
|
||||
|
||||
/**
|
||||
* This method fixes all auto budgets in currency $currency.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
* @param string $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function correctGeneric(TransactionCurrency $currency, string $table): void
|
||||
@ -271,6 +281,7 @@ class ForceDecimalSize extends Command
|
||||
$result = $query->get(['*']);
|
||||
if (0 === $result->count()) {
|
||||
$this->line(sprintf('Correct: All %s in %s', $table, $currency->code));
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var Model $item */
|
||||
@ -294,6 +305,7 @@ class ForceDecimalSize extends Command
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
* @param array $fields
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function correctPiggyAmounts(TransactionCurrency $currency, array $fields): void
|
||||
@ -320,6 +332,7 @@ class ForceDecimalSize extends Command
|
||||
$result = $query->get(['piggy_banks.*']);
|
||||
if (0 === $result->count()) {
|
||||
$this->line(sprintf('Correct: All piggy banks in %s', $currency->code));
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var PiggyBank $item */
|
||||
@ -340,8 +353,10 @@ class ForceDecimalSize extends Command
|
||||
|
||||
/**
|
||||
* This method fixes all piggy bank events in currency $currency.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
* @param array $fields
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function correctPiggyEventAmounts(TransactionCurrency $currency, array $fields): void
|
||||
@ -369,6 +384,7 @@ class ForceDecimalSize extends Command
|
||||
$result = $query->get(['piggy_bank_events.*']);
|
||||
if (0 === $result->count()) {
|
||||
$this->line(sprintf('Correct: All piggy bank events in %s', $currency->code));
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var PiggyBankEvent $item */
|
||||
@ -392,6 +408,7 @@ class ForceDecimalSize extends Command
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
* @param array $fields
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function correctPiggyRepetitionAmounts(TransactionCurrency $currency, array $fields)
|
||||
@ -419,6 +436,7 @@ class ForceDecimalSize extends Command
|
||||
$result = $query->get(['piggy_bank_repetitions.*']);
|
||||
if (0 === $result->count()) {
|
||||
$this->line(sprintf('Correct: All piggy bank repetitions in %s', $currency->code));
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var PiggyBankRepetition $item */
|
||||
@ -441,6 +459,7 @@ class ForceDecimalSize extends Command
|
||||
* This method fixes all transactions in currency $currency.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function correctTransactionAmounts(TransactionCurrency $currency): void
|
||||
@ -482,6 +501,7 @@ class ForceDecimalSize extends Command
|
||||
$result = $query->get(['*']);
|
||||
if (0 === $result->count()) {
|
||||
$this->line(sprintf('Correct: All transactions in foreign currency %s', $currency->code));
|
||||
|
||||
return;
|
||||
}
|
||||
/** @var Transaction $item */
|
||||
@ -534,6 +554,7 @@ class ForceDecimalSize extends Command
|
||||
switch ($type) {
|
||||
default:
|
||||
$this->error(sprintf('Cannot handle database type "%s".', $type));
|
||||
|
||||
return;
|
||||
case 'pgsql':
|
||||
$query = sprintf('ALTER TABLE %s ALTER COLUMN %s TYPE DECIMAL(32,12);', $name, $field);
|
||||
|
@ -52,6 +52,7 @@ class ForceMigration extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function handle(): int
|
||||
@ -69,8 +70,10 @@ class ForceMigration extends Command
|
||||
$user = $this->getUser();
|
||||
Log::channel('audit')->info(sprintf('User #%d ("%s") forced migrations.', $user->id, $user->email));
|
||||
$this->forceMigration();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,7 @@ class VerifySecurityAlerts extends Command
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function saveSecurityAdvisory(array $array): void
|
||||
|
@ -153,6 +153,7 @@ class Cron extends Command
|
||||
/**
|
||||
* @param bool $force
|
||||
* @param Carbon|null $date
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
|
@ -165,6 +165,7 @@ class DecryptDatabase extends Command
|
||||
/**
|
||||
* @param string $table
|
||||
* @param array $fields
|
||||
*
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
|
@ -85,6 +85,7 @@ class UpgradeLiabilitiesEight extends Command
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function deleteCreditTransaction(Account $account): void
|
||||
@ -100,6 +101,7 @@ class UpgradeLiabilitiesEight extends Command
|
||||
$service = new TransactionGroupDestroyService();
|
||||
$service->destroy($group);
|
||||
Log::debug(sprintf('Deleted liability credit group #%d', $group->id));
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('No liability credit journal found.');
|
||||
@ -107,6 +109,7 @@ class UpgradeLiabilitiesEight extends Command
|
||||
|
||||
/**
|
||||
* @param $account
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function deleteTransactions($account): int
|
||||
@ -152,11 +155,13 @@ class UpgradeLiabilitiesEight extends Command
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function hasBadOpening(Account $account): bool
|
||||
@ -169,6 +174,7 @@ class UpgradeLiabilitiesEight extends Command
|
||||
->first(['transaction_journals.*']);
|
||||
if (null === $openingJournal) {
|
||||
Log::debug('Account has no opening balance and can be skipped.');
|
||||
|
||||
return false;
|
||||
}
|
||||
$liabilityJournal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
@ -177,10 +183,12 @@ class UpgradeLiabilitiesEight extends Command
|
||||
->first(['transaction_journals.*']);
|
||||
if (null === $liabilityJournal) {
|
||||
Log::debug('Account has no liability credit and can be skipped.');
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!$openingJournal->date->isSameDay($liabilityJournal->date)) {
|
||||
Log::debug('Account has opening/credit not on the same day.');
|
||||
|
||||
return false;
|
||||
}
|
||||
Log::debug('Account has bad opening balance data.');
|
||||
@ -213,6 +221,7 @@ class UpgradeLiabilitiesEight extends Command
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function reverseOpeningBalance(Account $account): void
|
||||
@ -235,6 +244,7 @@ class UpgradeLiabilitiesEight extends Command
|
||||
$source->save();
|
||||
$dest->save();
|
||||
Log::debug(sprintf('Opening balance transaction journal #%d reversed.', $openingJournal->id));
|
||||
|
||||
return;
|
||||
}
|
||||
Log::warning('Did not find opening balance.');
|
||||
|
@ -168,45 +168,6 @@ class GracefulNotFoundHandler extends ExceptionHandler
|
||||
return redirect(route('accounts.index', [$shortType]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Throwable $exception
|
||||
*
|
||||
* @return Response
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function handleGroup(Request $request, Throwable $exception)
|
||||
{
|
||||
Log::debug('404 page is probably a deleted group. Redirect to overview of group types.');
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$route = $request->route();
|
||||
$groupId = (int)$route->parameter('transactionGroup');
|
||||
|
||||
/** @var TransactionGroup|null $group */
|
||||
$group = $user->transactionGroups()->withTrashed()->find($groupId);
|
||||
if (null === $group) {
|
||||
Log::error(sprintf('Could not find group %d, so give big fat error.', $groupId));
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
/** @var TransactionJournal|null $journal */
|
||||
$journal = $group->transactionJournals()->withTrashed()->first();
|
||||
if (null === $journal) {
|
||||
Log::error(sprintf('Could not find journal for group %d, so give big fat error.', $groupId));
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
$type = $journal->transactionType->type;
|
||||
$request->session()->reflash();
|
||||
|
||||
if (TransactionType::RECONCILIATION === $type) {
|
||||
return redirect(route('accounts.index', ['asset']));
|
||||
}
|
||||
|
||||
return redirect(route('transactions.index', [strtolower($type)]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Throwable $exception
|
||||
@ -250,4 +211,43 @@ class GracefulNotFoundHandler extends ExceptionHandler
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Throwable $exception
|
||||
*
|
||||
* @return Response
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function handleGroup(Request $request, Throwable $exception)
|
||||
{
|
||||
Log::debug('404 page is probably a deleted group. Redirect to overview of group types.');
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$route = $request->route();
|
||||
$groupId = (int)$route->parameter('transactionGroup');
|
||||
|
||||
/** @var TransactionGroup|null $group */
|
||||
$group = $user->transactionGroups()->withTrashed()->find($groupId);
|
||||
if (null === $group) {
|
||||
Log::error(sprintf('Could not find group %d, so give big fat error.', $groupId));
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
/** @var TransactionJournal|null $journal */
|
||||
$journal = $group->transactionJournals()->withTrashed()->first();
|
||||
if (null === $journal) {
|
||||
Log::error(sprintf('Could not find journal for group %d, so give big fat error.', $groupId));
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
$type = $journal->transactionType->type;
|
||||
$request->session()->reflash();
|
||||
|
||||
if (TransactionType::RECONCILIATION === $type) {
|
||||
return redirect(route('accounts.index', ['asset']));
|
||||
}
|
||||
|
||||
return redirect(route('transactions.index', [strtolower($type)]));
|
||||
}
|
||||
}
|
||||
|
@ -225,23 +225,6 @@ class Handler extends ExceptionHandler
|
||||
parent::report($e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldntReportLocal(Throwable $e): bool
|
||||
{
|
||||
return !is_null(
|
||||
Arr::first(
|
||||
$this->dontReport,
|
||||
function ($type) use ($e) {
|
||||
return $e instanceof $type;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a validation exception into a response.
|
||||
*
|
||||
@ -280,4 +263,21 @@ class Handler extends ExceptionHandler
|
||||
|
||||
return null !== $previousHost && $previousHost === $safeHost ? $previous : $safe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldntReportLocal(Throwable $e): bool
|
||||
{
|
||||
return !is_null(
|
||||
Arr::first(
|
||||
$this->dontReport,
|
||||
function ($type) use ($e) {
|
||||
return $e instanceof $type;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ use FireflyIII\Services\Internal\Support\AccountServiceTrait;
|
||||
use FireflyIII\Services\Internal\Support\LocationServiceTrait;
|
||||
use FireflyIII\Services\Internal\Update\AccountUpdateService;
|
||||
use FireflyIII\User;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
|
||||
/**
|
||||
* Factory to create or return accounts.
|
||||
@ -69,6 +69,47 @@ class AccountFactory
|
||||
$this->validFields = config('firefly.valid_account_fields');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function create(array $data): Account
|
||||
{
|
||||
Log::debug('Now in AccountFactory::create()');
|
||||
$type = $this->getAccountType($data);
|
||||
$data['iban'] = $this->filterIban($data['iban'] ?? null);
|
||||
|
||||
// account may exist already:
|
||||
$return = $this->find($data['name'], $type->type);
|
||||
|
||||
if (null !== $return) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
$return = $this->createAccount($type, $data);
|
||||
|
||||
event(new StoredAccount($return));
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accountName
|
||||
* @param string $accountType
|
||||
*
|
||||
* @return Account|null
|
||||
*/
|
||||
public function find(string $accountName, string $accountType): ?Account
|
||||
{
|
||||
Log::debug(sprintf('Now in AccountFactory::find("%s", "%s")', $accountName, $accountType));
|
||||
$type = AccountType::whereType($accountType)->first();
|
||||
|
||||
return $this->user->accounts()->where('account_type_id', $type->id)->where('name', $accountName)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accountName
|
||||
* @param string $accountType
|
||||
@ -106,30 +147,12 @@ class AccountFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
* @param User $user
|
||||
*/
|
||||
public function create(array $data): Account
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
Log::debug('Now in AccountFactory::create()');
|
||||
$type = $this->getAccountType($data);
|
||||
$data['iban'] = $this->filterIban($data['iban'] ?? null);
|
||||
|
||||
// account may exist already:
|
||||
$return = $this->find($data['name'], $type->type);
|
||||
|
||||
if (null !== $return) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
$return = $this->createAccount($type, $data);
|
||||
|
||||
event(new StoredAccount($return));
|
||||
|
||||
return $return;
|
||||
$this->user = $user;
|
||||
$this->accountRepository->setUser($user);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,17 +191,32 @@ class AccountFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accountName
|
||||
* @param string $accountType
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account|null
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function find(string $accountName, string $accountType): ?Account
|
||||
private function cleanMetaDataArray(Account $account, array $data): array
|
||||
{
|
||||
Log::debug(sprintf('Now in AccountFactory::find("%s", "%s")', $accountName, $accountType));
|
||||
$type = AccountType::whereType($accountType)->first();
|
||||
$currencyId = array_key_exists('currency_id', $data) ? (int)$data['currency_id'] : 0;
|
||||
$currencyCode = array_key_exists('currency_code', $data) ? (string)$data['currency_code'] : '';
|
||||
$accountRole = array_key_exists('account_role', $data) ? (string)$data['account_role'] : null;
|
||||
$currency = $this->getCurrency($currencyId, $currencyCode);
|
||||
|
||||
return $this->user->accounts()->where('account_type_id', $type->id)->where('name', $accountName)->first();
|
||||
// only asset account may have a role:
|
||||
if ($account->accountType->type !== AccountType::ASSET) {
|
||||
$accountRole = '';
|
||||
}
|
||||
// only liability may have direction:
|
||||
if (array_key_exists('liability_direction', $data) && !in_array($account->accountType->type, config('firefly.valid_liabilities'), true)) {
|
||||
$data['liability_direction'] = null;
|
||||
}
|
||||
$data['account_role'] = $accountRole;
|
||||
$data['currency_id'] = $currency->id;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -254,29 +292,29 @@ class AccountFactory
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function cleanMetaDataArray(Account $account, array $data): array
|
||||
private function storeCreditLiability(Account $account, array $data)
|
||||
{
|
||||
$currencyId = array_key_exists('currency_id', $data) ? (int)$data['currency_id'] : 0;
|
||||
$currencyCode = array_key_exists('currency_code', $data) ? (string)$data['currency_code'] : '';
|
||||
$accountRole = array_key_exists('account_role', $data) ? (string)$data['account_role'] : null;
|
||||
$currency = $this->getCurrency($currencyId, $currencyCode);
|
||||
|
||||
// only asset account may have a role:
|
||||
if ($account->accountType->type !== AccountType::ASSET) {
|
||||
$accountRole = '';
|
||||
Log::debug('storeCreditLiability');
|
||||
$account->refresh();
|
||||
$accountType = $account->accountType->type;
|
||||
$direction = $this->accountRepository->getMetaValue($account, 'liability_direction');
|
||||
$valid = config('firefly.valid_liabilities');
|
||||
if (in_array($accountType, $valid, true)) {
|
||||
Log::debug('Is a liability with credit ("i am owed") direction.');
|
||||
if ($this->validOBData($data)) {
|
||||
Log::debug('Has valid CL data.');
|
||||
$openingBalance = $data['opening_balance'];
|
||||
$openingBalanceDate = $data['opening_balance_date'];
|
||||
// store credit transaction.
|
||||
$this->updateCreditTransaction($account, $direction, $openingBalance, $openingBalanceDate);
|
||||
}
|
||||
if (!$this->validOBData($data)) {
|
||||
Log::debug('Does NOT have valid CL data, deletr any CL transaction.');
|
||||
$this->deleteCreditTransaction($account);
|
||||
}
|
||||
// only liability may have direction:
|
||||
if (array_key_exists('liability_direction', $data) && !in_array($account->accountType->type, config('firefly.valid_liabilities'), true)) {
|
||||
$data['liability_direction'] = null;
|
||||
}
|
||||
$data['account_role'] = $accountRole;
|
||||
$data['currency_id'] = $currency->id;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,35 +382,6 @@ class AccountFactory
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function storeCreditLiability(Account $account, array $data)
|
||||
{
|
||||
Log::debug('storeCreditLiability');
|
||||
$account->refresh();
|
||||
$accountType = $account->accountType->type;
|
||||
$direction = $this->accountRepository->getMetaValue($account, 'liability_direction');
|
||||
$valid = config('firefly.valid_liabilities');
|
||||
if (in_array($accountType, $valid, true)) {
|
||||
Log::debug('Is a liability with credit ("i am owed") direction.');
|
||||
if ($this->validOBData($data)) {
|
||||
Log::debug('Has valid CL data.');
|
||||
$openingBalance = $data['opening_balance'];
|
||||
$openingBalanceDate = $data['opening_balance_date'];
|
||||
// store credit transaction.
|
||||
$this->updateCreditTransaction($account, $direction, $openingBalance, $openingBalanceDate);
|
||||
}
|
||||
if (!$this->validOBData($data)) {
|
||||
Log::debug('Does NOT have valid CL data, deletr any CL transaction.');
|
||||
$this->deleteCreditTransaction($account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
@ -396,13 +405,4 @@ class AccountFactory
|
||||
$updateService->setUser($account->user);
|
||||
$updateService->update($account, ['order' => $order]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->accountRepository->setUser($user);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,16 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
class AccountMetaFactory
|
||||
{
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return AccountMeta|null
|
||||
*/
|
||||
public function create(array $data): ?AccountMeta
|
||||
{
|
||||
return AccountMeta::create($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create update or delete meta data.
|
||||
*
|
||||
@ -68,14 +78,4 @@ class AccountMetaFactory
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return AccountMeta|null
|
||||
*/
|
||||
public function create(array $data): ?AccountMeta
|
||||
{
|
||||
return AccountMeta::create($data);
|
||||
}
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
||||
use FireflyIII\Services\Internal\Support\BillServiceTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\QueryException;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
|
||||
/**
|
||||
* Class BillFactory
|
||||
|
@ -36,6 +36,16 @@ class CategoryFactory
|
||||
{
|
||||
private User $user;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return Category|null
|
||||
*/
|
||||
public function findByName(string $name): ?Category
|
||||
{
|
||||
return $this->user->categories()->where('name', $name)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $categoryId
|
||||
* @param null|string $categoryName
|
||||
@ -83,16 +93,6 @@ class CategoryFactory
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return Category|null
|
||||
*/
|
||||
public function findByName(string $name): ?Category
|
||||
{
|
||||
return $this->user->categories()->where('name', $name)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
|
@ -25,7 +25,6 @@ namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
|
@ -29,9 +29,9 @@ use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Services\Internal\Support\RecurringTransactionTrait;
|
||||
use FireflyIII\Services\Internal\Support\TransactionTypeTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class RecurrenceFactory
|
||||
|
@ -35,6 +35,40 @@ class TagFactory
|
||||
{
|
||||
private User $user;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Tag|null
|
||||
*/
|
||||
public function create(array $data): ?Tag
|
||||
{
|
||||
$zoomLevel = 0 === (int)$data['zoom_level'] ? null : (int)$data['zoom_level'];
|
||||
$latitude = 0.0 === (float)$data['latitude'] ? null : (float)$data['latitude']; // intentional float
|
||||
$longitude = 0.0 === (float)$data['longitude'] ? null : (float)$data['longitude']; // intentional float
|
||||
$array = [
|
||||
'user_id' => $this->user->id,
|
||||
'tag' => trim($data['tag']),
|
||||
'tagMode' => 'nothing',
|
||||
'date' => $data['date'],
|
||||
'description' => $data['description'],
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoomLevel' => null,
|
||||
];
|
||||
$tag = Tag::create($array);
|
||||
if (null !== $tag && null !== $latitude && null !== $longitude) {
|
||||
// create location object.
|
||||
$location = new Location();
|
||||
$location->latitude = $latitude;
|
||||
$location->longitude = $longitude;
|
||||
$location->zoom_level = $zoomLevel;
|
||||
$location->locatable()->associate($tag);
|
||||
$location->save();
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tag
|
||||
*
|
||||
@ -72,40 +106,6 @@ class TagFactory
|
||||
return $newTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Tag|null
|
||||
*/
|
||||
public function create(array $data): ?Tag
|
||||
{
|
||||
$zoomLevel = 0 === (int)$data['zoom_level'] ? null : (int)$data['zoom_level'];
|
||||
$latitude = 0.0 === (float)$data['latitude'] ? null : (float)$data['latitude']; // intentional float
|
||||
$longitude = 0.0 === (float)$data['longitude'] ? null : (float)$data['longitude']; // intentional float
|
||||
$array = [
|
||||
'user_id' => $this->user->id,
|
||||
'tag' => trim($data['tag']),
|
||||
'tagMode' => 'nothing',
|
||||
'date' => $data['date'],
|
||||
'description' => $data['description'],
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoomLevel' => null,
|
||||
];
|
||||
$tag = Tag::create($array);
|
||||
if (null !== $tag && null !== $latitude && null !== $longitude) {
|
||||
// create location object.
|
||||
$location = new Location();
|
||||
$location->latitude = $latitude;
|
||||
$location->longitude = $longitude;
|
||||
$location->zoom_level = $zoomLevel;
|
||||
$location->locatable()->associate($tag);
|
||||
$location->save();
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
|
@ -80,6 +80,95 @@ class TransactionFactory
|
||||
return $this->create(app('steam')->negative($amount), $foreignAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create transaction with positive amount (for destination accounts).
|
||||
*
|
||||
* @param string $amount
|
||||
* @param string|null $foreignAmount
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function createPositive(string $amount, ?string $foreignAmount): Transaction
|
||||
{
|
||||
if ('' === $foreignAmount) {
|
||||
$foreignAmount = null;
|
||||
}
|
||||
if (null !== $foreignAmount) {
|
||||
$foreignAmount = app('steam')->positive($foreignAmount);
|
||||
}
|
||||
|
||||
return $this->create(app('steam')->positive($amount), $foreignAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
|
||||
*/
|
||||
public function setAccount(Account $account): void
|
||||
{
|
||||
$this->account = $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $accountInformation
|
||||
*/
|
||||
public function setAccountInformation(array $accountInformation): void
|
||||
{
|
||||
$this->accountInformation = $accountInformation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
|
||||
*/
|
||||
public function setCurrency(TransactionCurrency $currency): void
|
||||
{
|
||||
$this->currency = $currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency|null $foreignCurrency |null
|
||||
*
|
||||
|
||||
*/
|
||||
public function setForeignCurrency(?TransactionCurrency $foreignCurrency): void
|
||||
{
|
||||
$this->foreignCurrency = $foreignCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
|
||||
*/
|
||||
public function setJournal(TransactionJournal $journal): void
|
||||
{
|
||||
$this->journal = $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $reconciled
|
||||
*
|
||||
|
||||
*/
|
||||
public function setReconciled(bool $reconciled): void
|
||||
{
|
||||
$this->reconciled = $reconciled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*
|
||||
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
// empty function.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $amount
|
||||
* @param string|null $foreignAmount
|
||||
@ -171,93 +260,4 @@ class TransactionFactory
|
||||
$service = app(AccountUpdateService::class);
|
||||
$service->update($this->account, ['iban' => $this->accountInformation['iban']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create transaction with positive amount (for destination accounts).
|
||||
*
|
||||
* @param string $amount
|
||||
* @param string|null $foreignAmount
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function createPositive(string $amount, ?string $foreignAmount): Transaction
|
||||
{
|
||||
if ('' === $foreignAmount) {
|
||||
$foreignAmount = null;
|
||||
}
|
||||
if (null !== $foreignAmount) {
|
||||
$foreignAmount = app('steam')->positive($foreignAmount);
|
||||
}
|
||||
|
||||
return $this->create(app('steam')->positive($amount), $foreignAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
|
||||
*/
|
||||
public function setAccount(Account $account): void
|
||||
{
|
||||
$this->account = $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $accountInformation
|
||||
*/
|
||||
public function setAccountInformation(array $accountInformation): void
|
||||
{
|
||||
$this->accountInformation = $accountInformation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
|
||||
*/
|
||||
public function setCurrency(TransactionCurrency $currency): void
|
||||
{
|
||||
$this->currency = $currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency|null $foreignCurrency |null
|
||||
*
|
||||
|
||||
*/
|
||||
public function setForeignCurrency(?TransactionCurrency $foreignCurrency): void
|
||||
{
|
||||
$this->foreignCurrency = $foreignCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
|
||||
*/
|
||||
public function setJournal(TransactionJournal $journal): void
|
||||
{
|
||||
$this->journal = $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $reconciled
|
||||
*
|
||||
|
||||
*/
|
||||
public function setReconciled(bool $reconciled): void
|
||||
{
|
||||
$this->reconciled = $reconciled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*
|
||||
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
// empty function.
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\User;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
|
||||
/**
|
||||
* Class TransactionGroupFactory
|
||||
|
@ -48,8 +48,8 @@ use FireflyIII\Support\NullArrayObject;
|
||||
use FireflyIII\User;
|
||||
use FireflyIII\Validation\AccountValidator;
|
||||
use Illuminate\Support\Collection;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalFactory
|
||||
@ -143,6 +143,79 @@ class TransactionJournalFactory
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $errorOnHash
|
||||
*/
|
||||
public function setErrorOnHash(bool $errorOnHash): void
|
||||
{
|
||||
$this->errorOnHash = $errorOnHash;
|
||||
if (true === $errorOnHash) {
|
||||
Log::info('Will trigger duplication alert for this journal.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->currencyRepository->setUser($this->user);
|
||||
$this->tagFactory->setUser($user);
|
||||
$this->billRepository->setUser($this->user);
|
||||
$this->budgetRepository->setUser($this->user);
|
||||
$this->categoryRepository->setUser($this->user);
|
||||
$this->piggyRepository->setUser($this->user);
|
||||
$this->accountRepository->setUser($this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $data
|
||||
* @param string $field
|
||||
*/
|
||||
protected function storeMeta(TransactionJournal $journal, NullArrayObject $data, string $field): void
|
||||
{
|
||||
$set = [
|
||||
'journal' => $journal,
|
||||
'name' => $field,
|
||||
'data' => (string)($data[$field] ?? ''),
|
||||
];
|
||||
if ($data[$field] instanceof Carbon) {
|
||||
$data[$field]->setTimezone(config('app.timezone'));
|
||||
Log::debug(sprintf('%s Date: %s (%s)', $field, $data[$field], $data[$field]->timezone->getName()));
|
||||
$set['data'] = $data[$field]->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
Log::debug(sprintf('Going to store meta-field "%s", with value "%s".', $set['name'], $set['data']));
|
||||
|
||||
/** @var TransactionJournalMetaFactory $factory */
|
||||
$factory = app(TransactionJournalMetaFactory::class);
|
||||
$factory->updateOrCreate($set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set foreign currency to NULL if it's the same as the normal currency:
|
||||
*
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param TransactionCurrency|null $foreignCurrency
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
private function compareCurrencies(?TransactionCurrency $currency, ?TransactionCurrency $foreignCurrency): ?TransactionCurrency
|
||||
{
|
||||
if (null === $currency) {
|
||||
return null;
|
||||
}
|
||||
if (null !== $foreignCurrency && $foreignCurrency->id === $currency->id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $foreignCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NullArrayObject $row
|
||||
*
|
||||
@ -304,24 +377,6 @@ class TransactionJournalFactory
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NullArrayObject $row
|
||||
*
|
||||
* @return string
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function hashArray(NullArrayObject $row): string
|
||||
{
|
||||
$dataRow = $row->getArrayCopy();
|
||||
|
||||
unset($dataRow['import_hash_v2'], $dataRow['original_source']);
|
||||
$json = json_encode($dataRow, JSON_THROW_ON_ERROR);
|
||||
$hash = hash('sha256', $json);
|
||||
Log::debug(sprintf('The hash is: %s', $hash), $dataRow);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this transaction already exists, throw an error.
|
||||
*
|
||||
@ -354,6 +409,183 @@ class TransactionJournalFactory
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the deletion of an entire set of transaction journals and their meta object in case of
|
||||
* an error creating a group.
|
||||
*
|
||||
* @param Collection $collection
|
||||
*/
|
||||
private function forceDeleteOnError(Collection $collection): void
|
||||
{
|
||||
Log::debug(sprintf('forceDeleteOnError on collection size %d item(s)', $collection->count()));
|
||||
$service = app(JournalDestroyService::class);
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($collection as $journal) {
|
||||
Log::debug(sprintf('forceDeleteOnError on journal #%d', $journal->id));
|
||||
$service->destroy($journal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Transaction $transaction
|
||||
*/
|
||||
private function forceTrDelete(Transaction $transaction): void
|
||||
{
|
||||
$transaction->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $account
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function getCurrency(?TransactionCurrency $currency, Account $account): TransactionCurrency
|
||||
{
|
||||
Log::debug('Now in getCurrency()');
|
||||
/** @var Preference|null $preference */
|
||||
$preference = $this->accountRepository->getAccountCurrency($account);
|
||||
if (null === $preference && null === $currency) {
|
||||
// return user's default:
|
||||
return app('amount')->getDefaultCurrencyByUser($this->user);
|
||||
}
|
||||
$result = ($preference ?? $currency) ?? app('amount')->getSystemCurrency();
|
||||
Log::debug(sprintf('Currency is now #%d (%s) because of account #%d (%s)', $result->id, $result->code, $account->id, $account->name));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $source
|
||||
* @param Account $destination
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function getCurrencyByAccount(string $type, ?TransactionCurrency $currency, Account $source, Account $destination): TransactionCurrency
|
||||
{
|
||||
Log::debug('Now in getCurrencyByAccount()');
|
||||
|
||||
return match ($type) {
|
||||
default => $this->getCurrency($currency, $source),
|
||||
TransactionType::DEPOSIT => $this->getCurrency($currency, $destination),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getDescription(string $description): string
|
||||
{
|
||||
$description = '' === $description ? '(empty description)' : $description;
|
||||
|
||||
return substr($description, 0, 255);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param TransactionCurrency|null $foreignCurrency
|
||||
* @param Account $destination
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function getForeignByAccount(string $type, ?TransactionCurrency $foreignCurrency, Account $destination): ?TransactionCurrency
|
||||
{
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
return $this->getCurrency($foreignCurrency, $destination);
|
||||
}
|
||||
|
||||
return $foreignCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NullArrayObject $row
|
||||
*
|
||||
* @return string
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function hashArray(NullArrayObject $row): string
|
||||
{
|
||||
$dataRow = $row->getArrayCopy();
|
||||
|
||||
unset($dataRow['import_hash_v2'], $dataRow['original_source']);
|
||||
$json = json_encode($dataRow, JSON_THROW_ON_ERROR);
|
||||
$hash = hash('sha256', $json);
|
||||
Log::debug(sprintf('The hash is: %s', $hash), $dataRow);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account|null $sourceAccount
|
||||
* @param Account|null $destinationAccount
|
||||
* @return array
|
||||
*/
|
||||
private function reconciliationSanityCheck(?Account $sourceAccount, ?Account $destinationAccount): array
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
if (null !== $sourceAccount && null !== $destinationAccount) {
|
||||
Log::debug('Both accounts exist, simply return them.');
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
}
|
||||
if (null !== $sourceAccount && null === $destinationAccount) {
|
||||
Log::debug('Destination account is NULL, source account is not.');
|
||||
$account = $this->accountRepository->getReconciliation($sourceAccount);
|
||||
Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type));
|
||||
return [$sourceAccount, $account];
|
||||
}
|
||||
|
||||
if (null === $sourceAccount && null !== $destinationAccount) {
|
||||
Log::debug('Source account is NULL, destination account is not.');
|
||||
$account = $this->accountRepository->getReconciliation($destinationAccount);
|
||||
Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type));
|
||||
return [$account, $destinationAccount];
|
||||
}
|
||||
Log::debug('Unused fallback');
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $transaction
|
||||
*/
|
||||
private function storeMetaFields(TransactionJournal $journal, NullArrayObject $transaction): void
|
||||
{
|
||||
foreach ($this->fields as $field) {
|
||||
$this->storeMeta($journal, $transaction, $field);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a piggy bank to this journal.
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $data
|
||||
*/
|
||||
private function storePiggyEvent(TransactionJournal $journal, NullArrayObject $data): void
|
||||
{
|
||||
Log::debug('Will now store piggy event.');
|
||||
|
||||
$piggyBank = $this->piggyRepository->findPiggyBank((int)$data['piggy_bank_id'], $data['piggy_bank_name']);
|
||||
|
||||
if (null !== $piggyBank) {
|
||||
$this->piggyEventFactory->create($journal, $piggyBank);
|
||||
Log::debug('Create piggy event.');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('Create no piggy event');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NullArrayObject $data
|
||||
*
|
||||
@ -395,236 +627,4 @@ class TransactionJournalFactory
|
||||
throw new FireflyException(sprintf('Destination: %s', $this->accountValidator->destError));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->currencyRepository->setUser($this->user);
|
||||
$this->tagFactory->setUser($user);
|
||||
$this->billRepository->setUser($this->user);
|
||||
$this->budgetRepository->setUser($this->user);
|
||||
$this->categoryRepository->setUser($this->user);
|
||||
$this->piggyRepository->setUser($this->user);
|
||||
$this->accountRepository->setUser($this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account|null $sourceAccount
|
||||
* @param Account|null $destinationAccount
|
||||
* @return array
|
||||
*/
|
||||
private function reconciliationSanityCheck(?Account $sourceAccount, ?Account $destinationAccount): array
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
if (null !== $sourceAccount && null !== $destinationAccount) {
|
||||
Log::debug('Both accounts exist, simply return them.');
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
}
|
||||
if (null !== $sourceAccount && null === $destinationAccount) {
|
||||
Log::debug('Destination account is NULL, source account is not.');
|
||||
$account = $this->accountRepository->getReconciliation($sourceAccount);
|
||||
Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type));
|
||||
return [$sourceAccount, $account];
|
||||
}
|
||||
|
||||
if (null === $sourceAccount && null !== $destinationAccount) {
|
||||
Log::debug('Source account is NULL, destination account is not.');
|
||||
$account = $this->accountRepository->getReconciliation($destinationAccount);
|
||||
Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type));
|
||||
return [$account, $destinationAccount];
|
||||
}
|
||||
Log::debug('Unused fallback');
|
||||
return [$sourceAccount, $destinationAccount];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $source
|
||||
* @param Account $destination
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function getCurrencyByAccount(string $type, ?TransactionCurrency $currency, Account $source, Account $destination): TransactionCurrency
|
||||
{
|
||||
Log::debug('Now in getCurrencyByAccount()');
|
||||
|
||||
return match ($type) {
|
||||
default => $this->getCurrency($currency, $source),
|
||||
TransactionType::DEPOSIT => $this->getCurrency($currency, $destination),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $account
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function getCurrency(?TransactionCurrency $currency, Account $account): TransactionCurrency
|
||||
{
|
||||
Log::debug('Now in getCurrency()');
|
||||
/** @var Preference|null $preference */
|
||||
$preference = $this->accountRepository->getAccountCurrency($account);
|
||||
if (null === $preference && null === $currency) {
|
||||
// return user's default:
|
||||
return app('amount')->getDefaultCurrencyByUser($this->user);
|
||||
}
|
||||
$result = ($preference ?? $currency) ?? app('amount')->getSystemCurrency();
|
||||
Log::debug(sprintf('Currency is now #%d (%s) because of account #%d (%s)', $result->id, $result->code, $account->id, $account->name));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set foreign currency to NULL if it's the same as the normal currency:
|
||||
*
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param TransactionCurrency|null $foreignCurrency
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
private function compareCurrencies(?TransactionCurrency $currency, ?TransactionCurrency $foreignCurrency): ?TransactionCurrency
|
||||
{
|
||||
if (null === $currency) {
|
||||
return null;
|
||||
}
|
||||
if (null !== $foreignCurrency && $foreignCurrency->id === $currency->id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $foreignCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param TransactionCurrency|null $foreignCurrency
|
||||
* @param Account $destination
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function getForeignByAccount(string $type, ?TransactionCurrency $foreignCurrency, Account $destination): ?TransactionCurrency
|
||||
{
|
||||
if (TransactionType::TRANSFER === $type) {
|
||||
return $this->getCurrency($foreignCurrency, $destination);
|
||||
}
|
||||
|
||||
return $foreignCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getDescription(string $description): string
|
||||
{
|
||||
$description = '' === $description ? '(empty description)' : $description;
|
||||
|
||||
return substr($description, 0, 255);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the deletion of an entire set of transaction journals and their meta object in case of
|
||||
* an error creating a group.
|
||||
*
|
||||
* @param Collection $collection
|
||||
*/
|
||||
private function forceDeleteOnError(Collection $collection): void
|
||||
{
|
||||
Log::debug(sprintf('forceDeleteOnError on collection size %d item(s)', $collection->count()));
|
||||
$service = app(JournalDestroyService::class);
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($collection as $journal) {
|
||||
Log::debug(sprintf('forceDeleteOnError on journal #%d', $journal->id));
|
||||
$service->destroy($journal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Transaction $transaction
|
||||
*/
|
||||
private function forceTrDelete(Transaction $transaction): void
|
||||
{
|
||||
$transaction->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a piggy bank to this journal.
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $data
|
||||
*/
|
||||
private function storePiggyEvent(TransactionJournal $journal, NullArrayObject $data): void
|
||||
{
|
||||
Log::debug('Will now store piggy event.');
|
||||
|
||||
$piggyBank = $this->piggyRepository->findPiggyBank((int)$data['piggy_bank_id'], $data['piggy_bank_name']);
|
||||
|
||||
if (null !== $piggyBank) {
|
||||
$this->piggyEventFactory->create($journal, $piggyBank);
|
||||
Log::debug('Create piggy event.');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('Create no piggy event');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $transaction
|
||||
*/
|
||||
private function storeMetaFields(TransactionJournal $journal, NullArrayObject $transaction): void
|
||||
{
|
||||
foreach ($this->fields as $field) {
|
||||
$this->storeMeta($journal, $transaction, $field);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $data
|
||||
* @param string $field
|
||||
*/
|
||||
protected function storeMeta(TransactionJournal $journal, NullArrayObject $data, string $field): void
|
||||
{
|
||||
$set = [
|
||||
'journal' => $journal,
|
||||
'name' => $field,
|
||||
'data' => (string)($data[$field] ?? ''),
|
||||
];
|
||||
if ($data[$field] instanceof Carbon) {
|
||||
$data[$field]->setTimezone(config('app.timezone'));
|
||||
Log::debug(sprintf('%s Date: %s (%s)', $field, $data[$field], $data[$field]->timezone->getName()));
|
||||
$set['data'] = $data[$field]->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
Log::debug(sprintf('Going to store meta-field "%s", with value "%s".', $set['name'], $set['data']));
|
||||
|
||||
/** @var TransactionJournalMetaFactory $factory */
|
||||
$factory = app(TransactionJournalMetaFactory::class);
|
||||
$factory->updateOrCreate($set);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $errorOnHash
|
||||
*/
|
||||
public function setErrorOnHash(bool $errorOnHash): void
|
||||
{
|
||||
$this->errorOnHash = $errorOnHash;
|
||||
if (true === $errorOnHash) {
|
||||
Log::info('Will trigger duplication alert for this journal.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,16 +68,6 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the preferred period.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function preferredPeriod(): string
|
||||
{
|
||||
return 'day';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set accounts.
|
||||
*
|
||||
@ -169,4 +159,14 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the preferred period.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function preferredPeriod(): string
|
||||
{
|
||||
return 'day';
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
|
@ -82,6 +82,34 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved accounts.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setAccounts(Collection $accounts): ReportGeneratorInterface
|
||||
{
|
||||
$this->accounts = $accounts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved budgets.
|
||||
*
|
||||
* @param Collection $budgets
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setBudgets(Collection $budgets): ReportGeneratorInterface
|
||||
{
|
||||
$this->budgets = $budgets;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused category setter.
|
||||
*
|
||||
@ -172,32 +200,4 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
|
||||
return $journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved budgets.
|
||||
*
|
||||
* @param Collection $budgets
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setBudgets(Collection $budgets): ReportGeneratorInterface
|
||||
{
|
||||
$this->budgets = $budgets;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved accounts.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setAccounts(Collection $accounts): ReportGeneratorInterface
|
||||
{
|
||||
$this->accounts = $accounts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +82,20 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved accounts.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setAccounts(Collection $accounts): ReportGeneratorInterface
|
||||
{
|
||||
$this->accounts = $accounts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty budget setter.
|
||||
*
|
||||
@ -94,6 +108,20 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the categories involved in this report.
|
||||
*
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setCategories(Collection $categories): ReportGeneratorInterface
|
||||
{
|
||||
$this->categories = $categories;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the end date for this report.
|
||||
*
|
||||
@ -171,34 +199,6 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the categories involved in this report.
|
||||
*
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setCategories(Collection $categories): ReportGeneratorInterface
|
||||
{
|
||||
$this->categories = $categories;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the involved accounts.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setAccounts(Collection $accounts): ReportGeneratorInterface
|
||||
{
|
||||
$this->accounts = $accounts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the income for this report.
|
||||
*
|
||||
|
@ -37,8 +37,8 @@ use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
@ -81,38 +81,62 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getVersion(): int
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $objects
|
||||
*/
|
||||
public function setObjects(Collection $objects): void
|
||||
{
|
||||
$this->objects = $objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $trigger
|
||||
*/
|
||||
public function setTrigger(int $trigger): void
|
||||
{
|
||||
$this->trigger = $trigger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setWebhooks(Collection $webhooks): void
|
||||
{
|
||||
$this->webhooks = $webhooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function getWebhooks(): Collection
|
||||
private function collectAccounts(TransactionGroup $transactionGroup): Collection
|
||||
{
|
||||
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
|
||||
$accounts = new Collection();
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($transactionGroup->transactionJournals as $journal) {
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journal->transactions as $transaction) {
|
||||
$accounts->push($transaction->account);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function run(): void
|
||||
{
|
||||
Log::debug('Now in StandardMessageGenerator::run');
|
||||
/** @var Webhook $webhook */
|
||||
foreach ($this->webhooks as $webhook) {
|
||||
$this->runWebhook($webhook);
|
||||
}
|
||||
Log::debug('Done with StandardMessageGenerator::run');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Webhook $webhook
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function runWebhook(Webhook $webhook): void
|
||||
{
|
||||
Log::debug(sprintf('Now in runWebhook(#%d)', $webhook->id));
|
||||
/** @var Model $object */
|
||||
foreach ($this->objects as $object) {
|
||||
$this->generateMessage($webhook, $object);
|
||||
}
|
||||
return $accounts->unique();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -188,30 +212,38 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return Collection
|
||||
*/
|
||||
public function getVersion(): int
|
||||
private function getWebhooks(): Collection
|
||||
{
|
||||
return $this->version;
|
||||
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function collectAccounts(TransactionGroup $transactionGroup): Collection
|
||||
private function run(): void
|
||||
{
|
||||
$accounts = new Collection();
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($transactionGroup->transactionJournals as $journal) {
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journal->transactions as $transaction) {
|
||||
$accounts->push($transaction->account);
|
||||
Log::debug('Now in StandardMessageGenerator::run');
|
||||
/** @var Webhook $webhook */
|
||||
foreach ($this->webhooks as $webhook) {
|
||||
$this->runWebhook($webhook);
|
||||
}
|
||||
Log::debug('Done with StandardMessageGenerator::run');
|
||||
}
|
||||
|
||||
return $accounts->unique();
|
||||
/**
|
||||
* @param Webhook $webhook
|
||||
* @throws FireflyException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function runWebhook(Webhook $webhook): void
|
||||
{
|
||||
Log::debug(sprintf('Now in runWebhook(#%d)', $webhook->id));
|
||||
/** @var Model $object */
|
||||
foreach ($this->objects as $object) {
|
||||
$this->generateMessage($webhook, $object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -231,36 +263,4 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
$webhookMessage->save();
|
||||
Log::debug(sprintf('Stored new webhook message #%d', $webhookMessage->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $objects
|
||||
*/
|
||||
public function setObjects(Collection $objects): void
|
||||
{
|
||||
$this->objects = $objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $trigger
|
||||
*/
|
||||
public function setTrigger(int $trigger): void
|
||||
{
|
||||
$this->trigger = $trigger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setWebhooks(Collection $webhooks): void
|
||||
{
|
||||
$this->webhooks = $webhooks;
|
||||
}
|
||||
}
|
||||
|
@ -26,9 +26,9 @@ namespace FireflyIII\Handlers\Events;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Notifications\User\NewAccessToken;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Laravel\Passport\Events\AccessTokenCreated;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class APIEventHandler
|
||||
|
@ -29,8 +29,8 @@ use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Notifications\User\TransactionCreation;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
/**
|
||||
* Class AutomationHandler
|
||||
|
@ -52,16 +52,6 @@ class BudgetLimitHandler
|
||||
$this->updateAvailableBudget($event->budgetLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Updated $event
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Updated $event): void
|
||||
{
|
||||
Log::debug(sprintf('BudgetLimitHandler::updated(#%s)', $event->budgetLimit->id));
|
||||
$this->updateAvailableBudget($event->budgetLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Deleted $event
|
||||
* @return void
|
||||
@ -74,6 +64,16 @@ class BudgetLimitHandler
|
||||
$this->updateAvailableBudget($event->budgetLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Updated $event
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Updated $event): void
|
||||
{
|
||||
Log::debug(sprintf('BudgetLimitHandler::updated(#%s)', $event->budgetLimit->id));
|
||||
$this->updateAvailableBudget($event->budgetLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AvailableBudget $availableBudget
|
||||
* @return void
|
||||
@ -182,7 +182,7 @@ class BudgetLimitHandler
|
||||
$end = app('navigation')->startOfPeriod($budgetLimit->end_date, $viewRange);
|
||||
$end = app('navigation')->endOfPeriod($end, $viewRange);
|
||||
$budget = Budget::find($budgetLimit->budget_id);
|
||||
if(null === $budget) {
|
||||
if (null === $budget) {
|
||||
Log::warning('Budget is null, cannot continue.');
|
||||
$budgetLimit->forceDelete();
|
||||
return;
|
||||
|
@ -47,8 +47,8 @@ use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Auth\Events\Login;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Mail;
|
||||
|
||||
/**
|
||||
|
@ -32,9 +32,9 @@ use Illuminate\Contracts\Encryption\EncryptException;
|
||||
use Illuminate\Contracts\Filesystem\Filesystem;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
/**
|
||||
@ -211,6 +211,39 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a model already has this file attached.
|
||||
*
|
||||
* @param UploadedFile $file
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasFile(UploadedFile $file, Model $model): bool
|
||||
{
|
||||
$md5 = md5_file($file->getRealPath());
|
||||
$name = $file->getClientOriginalName();
|
||||
$class = get_class($model);
|
||||
$count = 0;
|
||||
// ignore lines about polymorphic calls.
|
||||
if ($model instanceof PiggyBank) {
|
||||
$count = $model->account->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count();
|
||||
}
|
||||
if ($model instanceof PiggyBank) {
|
||||
$count = $model->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(
|
||||
); // @phpstan-ignore-line
|
||||
}
|
||||
$result = false;
|
||||
if ($count > 0) {
|
||||
$msg = (string)trans('validation.file_already_attached', ['name' => $name]);
|
||||
$this->errors->add('attachments', $msg);
|
||||
Log::error($msg);
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the upload of a file.
|
||||
*
|
||||
@ -268,39 +301,6 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
return $attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if the file was uploaded correctly.
|
||||
*
|
||||
* @param UploadedFile $file
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateUpload(UploadedFile $file, Model $model): bool
|
||||
{
|
||||
Log::debug('Now in validateUpload()');
|
||||
$result = true;
|
||||
if (!$this->validMime($file)) {
|
||||
$result = false;
|
||||
}
|
||||
if (0 === $file->getSize()) {
|
||||
Log::error('Cannot upload empty file.');
|
||||
$result = false;
|
||||
}
|
||||
|
||||
|
||||
// can't seem to reach this point.
|
||||
if (true === $result && !$this->validSize($file)) {
|
||||
$result = false;
|
||||
}
|
||||
|
||||
if (true === $result && $this->hasFile($file, $model)) {
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if the mime of a file is valid.
|
||||
*
|
||||
@ -353,33 +353,33 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a model already has this file attached.
|
||||
* Verify if the file was uploaded correctly.
|
||||
*
|
||||
* @param UploadedFile $file
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasFile(UploadedFile $file, Model $model): bool
|
||||
protected function validateUpload(UploadedFile $file, Model $model): bool
|
||||
{
|
||||
$md5 = md5_file($file->getRealPath());
|
||||
$name = $file->getClientOriginalName();
|
||||
$class = get_class($model);
|
||||
$count = 0;
|
||||
// ignore lines about polymorphic calls.
|
||||
if ($model instanceof PiggyBank) {
|
||||
$count = $model->account->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count();
|
||||
}
|
||||
if ($model instanceof PiggyBank) {
|
||||
$count = $model->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(
|
||||
); // @phpstan-ignore-line
|
||||
}
|
||||
$result = false;
|
||||
if ($count > 0) {
|
||||
$msg = (string)trans('validation.file_already_attached', ['name' => $name]);
|
||||
$this->errors->add('attachments', $msg);
|
||||
Log::error($msg);
|
||||
Log::debug('Now in validateUpload()');
|
||||
$result = true;
|
||||
if (!$this->validMime($file)) {
|
||||
$result = false;
|
||||
}
|
||||
if (0 === $file->getSize()) {
|
||||
Log::error('Cannot upload empty file.');
|
||||
$result = false;
|
||||
}
|
||||
|
||||
|
||||
// can't seem to reach this point.
|
||||
if (true === $result && !$this->validSize($file)) {
|
||||
$result = false;
|
||||
}
|
||||
|
||||
if (true === $result && $this->hasFile($file, $model)) {
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
@ -53,25 +53,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include bill name + ID, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withBillInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasBillInformation) {
|
||||
// join bill table
|
||||
$this->query->leftJoin('bills', 'bills.id', '=', 'transaction_journals.bill_id');
|
||||
// add fields
|
||||
$this->fields[] = 'bills.id as bill_id';
|
||||
$this->fields[] = 'bills.name as bill_name';
|
||||
$this->hasBillInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude a specific budget.
|
||||
*
|
||||
@ -91,27 +72,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include budget ID + name, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withBudgetInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasBudgetInformation) {
|
||||
// join link table
|
||||
$this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
// join cat table
|
||||
$this->query->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id');
|
||||
// add fields
|
||||
$this->fields[] = 'budgets.id as budget_id';
|
||||
$this->fields[] = 'budgets.name as budget_name';
|
||||
$this->hasBudgetInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@ -144,27 +104,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include category ID + name, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withCategoryInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasCatInformation) {
|
||||
// join link table
|
||||
$this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
// join cat table
|
||||
$this->query->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id');
|
||||
// add fields
|
||||
$this->fields[] = 'categories.id as category_id';
|
||||
$this->fields[] = 'categories.name as category_name';
|
||||
$this->hasCatInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude a specific category.
|
||||
*
|
||||
@ -196,19 +135,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join table to get tag information.
|
||||
*/
|
||||
protected function joinMetaDataTables(): void
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$this->hasJoinedMetaTables = true;
|
||||
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
|
||||
$this->fields[] = 'journal_meta.name as meta_name';
|
||||
$this->fields[] = 'journal_meta.data as meta_data';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@ -425,37 +351,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withTagInformation(): GroupCollectorInterface
|
||||
{
|
||||
$this->fields[] = 'tags.id as tag_id';
|
||||
$this->fields[] = 'tags.tag as tag_name';
|
||||
$this->fields[] = 'tags.date as tag_date';
|
||||
$this->fields[] = 'tags.description as tag_description';
|
||||
$this->fields[] = 'tags.latitude as tag_latitude';
|
||||
$this->fields[] = 'tags.longitude as tag_longitude';
|
||||
$this->fields[] = 'tags.zoomLevel as tag_zoom_level';
|
||||
|
||||
$this->joinTagTables();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join table to get tag information.
|
||||
*/
|
||||
protected function joinTagTables(): void
|
||||
{
|
||||
if (false === $this->hasJoinedTagTables) {
|
||||
// join some extra tables:
|
||||
$this->hasJoinedTagTables = true;
|
||||
$this->query->leftJoin('tag_transaction_journal', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
$this->query->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@ -541,29 +436,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withNotes(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasNotesInformation) {
|
||||
// join bill table
|
||||
$this->query->leftJoin(
|
||||
'notes',
|
||||
static function (JoinClause $join) {
|
||||
$join->on('notes.noteable_id', '=', 'transaction_journals.id');
|
||||
$join->where('notes.noteable_type', '=', 'FireflyIII\Models\TransactionJournal');
|
||||
$join->whereNull('notes.deleted_at');
|
||||
}
|
||||
);
|
||||
// add fields
|
||||
$this->fields[] = 'notes.text as notes';
|
||||
$this->hasNotesInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
@ -906,6 +778,25 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include bill name + ID, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withBillInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasBillInformation) {
|
||||
// join bill table
|
||||
$this->query->leftJoin('bills', 'bills.id', '=', 'transaction_journals.bill_id');
|
||||
// add fields
|
||||
$this->fields[] = 'bills.id as bill_id';
|
||||
$this->fields[] = 'bills.name as bill_name';
|
||||
$this->hasBillInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a transactions without a budget..
|
||||
*
|
||||
@ -919,6 +810,27 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include budget ID + name, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withBudgetInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasBudgetInformation) {
|
||||
// join link table
|
||||
$this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
// join cat table
|
||||
$this->query->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id');
|
||||
// add fields
|
||||
$this->fields[] = 'budgets.id as budget_id';
|
||||
$this->fields[] = 'budgets.name as budget_name';
|
||||
$this->hasBudgetInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a transactions without a category.
|
||||
*
|
||||
@ -932,6 +844,27 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include category ID + name, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withCategoryInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasCatInformation) {
|
||||
// join link table
|
||||
$this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
// join cat table
|
||||
$this->query->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id');
|
||||
// add fields
|
||||
$this->fields[] = 'categories.id as category_id';
|
||||
$this->fields[] = 'categories.name as category_name';
|
||||
$this->hasCatInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@ -956,6 +889,47 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withNotes(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasNotesInformation) {
|
||||
// join bill table
|
||||
$this->query->leftJoin(
|
||||
'notes',
|
||||
static function (JoinClause $join) {
|
||||
$join->on('notes.noteable_id', '=', 'transaction_journals.id');
|
||||
$join->where('notes.noteable_type', '=', 'FireflyIII\Models\TransactionJournal');
|
||||
$join->whereNull('notes.deleted_at');
|
||||
}
|
||||
);
|
||||
// add fields
|
||||
$this->fields[] = 'notes.text as notes';
|
||||
$this->hasNotesInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withTagInformation(): GroupCollectorInterface
|
||||
{
|
||||
$this->fields[] = 'tags.id as tag_id';
|
||||
$this->fields[] = 'tags.tag as tag_name';
|
||||
$this->fields[] = 'tags.date as tag_date';
|
||||
$this->fields[] = 'tags.description as tag_description';
|
||||
$this->fields[] = 'tags.latitude as tag_latitude';
|
||||
$this->fields[] = 'tags.longitude as tag_longitude';
|
||||
$this->fields[] = 'tags.zoomLevel as tag_zoom_level';
|
||||
|
||||
$this->joinTagTables();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a transactions without a bill.
|
||||
*
|
||||
@ -1062,4 +1036,30 @@ trait MetaCollection
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join table to get tag information.
|
||||
*/
|
||||
protected function joinMetaDataTables(): void
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$this->hasJoinedMetaTables = true;
|
||||
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
|
||||
$this->fields[] = 'journal_meta.name as meta_name';
|
||||
$this->fields[] = 'journal_meta.data as meta_data';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Join table to get tag information.
|
||||
*/
|
||||
protected function joinTagTables(): void
|
||||
{
|
||||
if (false === $this->hasJoinedTagTables) {
|
||||
// join some extra tables:
|
||||
$this->hasJoinedTagTables = true;
|
||||
$this->query->leftJoin('tag_transaction_journal', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
$this->query->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,18 +102,6 @@ trait TimeCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withMetaDate(string $field): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$this->query->where('journal_meta.name', '=', $field);
|
||||
$this->query->whereNotNull('journal_meta.data');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
@ -798,6 +786,18 @@ trait TimeCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withMetaDate(string $field): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$this->query->where('journal_meta.name', '=', $field);
|
||||
$this->query->whereNotNull('journal_meta.data');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $year
|
||||
* @return GroupCollectorInterface
|
||||
|
@ -504,6 +504,312 @@ class GroupCollector implements GroupCollectorInterface
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as getGroups but everything is in a paginator.
|
||||
*
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function getPaginatedGroups(): LengthAwarePaginator
|
||||
{
|
||||
$set = $this->getGroups();
|
||||
if (0 === $this->limit) {
|
||||
$this->setLimit(50);
|
||||
}
|
||||
|
||||
return new LengthAwarePaginator($set, $this->total, $this->limit, $this->page);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isNotReconciled(): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('source.reconciled', 0)->where('destination.reconciled', 0);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isReconciled(): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('source.reconciled', 1)->where('destination.reconciled', 1);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a specific currency, either foreign or normal one.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where(
|
||||
static function (EloquentBuilder $q) use ($currency) {
|
||||
$q->where('source.transaction_currency_id', $currency->id);
|
||||
$q->orWhere('source.foreign_currency_id', $currency->id);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setForeignCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('source.foreign_currency_id', $currency->id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result to a set of specific transaction groups.
|
||||
*
|
||||
* @param array $groupIds
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setIds(array $groupIds): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereIn('transaction_groups.id', $groupIds);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result to a set of specific journals.
|
||||
*
|
||||
* @param array $journalIds
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setJournalIds(array $journalIds): GroupCollectorInterface
|
||||
{
|
||||
if (0 !== count($journalIds)) {
|
||||
// make all integers.
|
||||
$integerIDs = array_map('intval', $journalIds);
|
||||
|
||||
|
||||
$this->query->whereIn('transaction_journals.id', $integerIDs);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of returned entries.
|
||||
*
|
||||
* @param int $limit
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setLimit(int $limit): GroupCollectorInterface
|
||||
{
|
||||
$this->limit = $limit;
|
||||
app('log')->debug(sprintf('GroupCollector: The limit is now %d', $limit));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the page to get.
|
||||
*
|
||||
* @param int $page
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setPage(int $page): GroupCollectorInterface
|
||||
{
|
||||
$page = 0 === $page ? 1 : $page;
|
||||
$this->page = $page;
|
||||
app('log')->debug(sprintf('GroupCollector: page is now %d', $page));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for words in descriptions.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setSearchWords(array $array): GroupCollectorInterface
|
||||
{
|
||||
if (0 === count($array)) {
|
||||
return $this;
|
||||
}
|
||||
$this->query->where(
|
||||
static function (EloquentBuilder $q) use ($array) {
|
||||
$q->where(
|
||||
static function (EloquentBuilder $q1) use ($array) {
|
||||
foreach ($array as $word) {
|
||||
$keyword = sprintf('%%%s%%', $word);
|
||||
$q1->where('transaction_journals.description', 'LIKE', $keyword);
|
||||
}
|
||||
}
|
||||
);
|
||||
$q->orWhere(
|
||||
static function (EloquentBuilder $q2) use ($array) {
|
||||
foreach ($array as $word) {
|
||||
$keyword = sprintf('%%%s%%', $word);
|
||||
$q2->where('transaction_groups.title', 'LIKE', $keyword);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the search to one specific transaction group.
|
||||
*
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setTransactionGroup(TransactionGroup $transactionGroup): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('transaction_groups.id', $transactionGroup->id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the included transaction types.
|
||||
*
|
||||
* @param array $types
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setTypes(array $types): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereIn('transaction_types.type', $types);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user object and start the query.
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setUser(User $user): GroupCollectorInterface
|
||||
{
|
||||
if (null === $this->user) {
|
||||
$this->user = $user;
|
||||
$this->startQuery();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically include all stuff required to make API calls work.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withAPIInformation(): GroupCollectorInterface
|
||||
{
|
||||
// include source + destination account name and type.
|
||||
$this->withAccountInformation()
|
||||
// include category ID + name (if any)
|
||||
->withCategoryInformation()
|
||||
// include budget ID + name (if any)
|
||||
->withBudgetInformation()
|
||||
// include bill ID + name (if any)
|
||||
->withBillInformation();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a selected set of fields to arrays.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function convertToInteger(array $array): array
|
||||
{
|
||||
foreach ($this->integerFields as $field) {
|
||||
$array[$field] = array_key_exists($field, $array) ? (int)$array[$field] : null;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
private function convertToStrings(array $array): array
|
||||
{
|
||||
foreach ($this->stringFields as $field) {
|
||||
$array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string)$array[$field] : null;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $existingJournal
|
||||
* @param TransactionJournal $newJournal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeAttachments(array $existingJournal, TransactionJournal $newJournal): array
|
||||
{
|
||||
$newArray = $newJournal->toArray();
|
||||
if (array_key_exists('attachment_id', $newArray)) {
|
||||
$attachmentId = (int)$newJournal['attachment_id'];
|
||||
|
||||
$existingJournal['attachments'][$attachmentId] = [
|
||||
'id' => $attachmentId,
|
||||
];
|
||||
}
|
||||
|
||||
return $existingJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $existingJournal
|
||||
* @param TransactionJournal $newJournal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeTags(array $existingJournal, TransactionJournal $newJournal): array
|
||||
{
|
||||
$newArray = $newJournal->toArray();
|
||||
if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well.
|
||||
$tagId = (int)$newJournal['tag_id'];
|
||||
|
||||
$tagDate = null;
|
||||
try {
|
||||
$tagDate = Carbon::parse($newArray['tag_date']);
|
||||
} catch (InvalidFormatException $e) {
|
||||
Log::debug(sprintf('Could not parse date: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
$existingJournal['tags'][$tagId] = [
|
||||
'id' => (int)$newArray['tag_id'],
|
||||
'name' => $newArray['tag_name'],
|
||||
'date' => $tagDate,
|
||||
'description' => $newArray['tag_description'],
|
||||
];
|
||||
}
|
||||
|
||||
return $existingJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
*
|
||||
@ -645,85 +951,6 @@ class GroupCollector implements GroupCollectorInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a selected set of fields to arrays.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function convertToInteger(array $array): array
|
||||
{
|
||||
foreach ($this->integerFields as $field) {
|
||||
$array[$field] = array_key_exists($field, $array) ? (int)$array[$field] : null;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
private function convertToStrings(array $array): array
|
||||
{
|
||||
foreach ($this->stringFields as $field) {
|
||||
$array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string)$array[$field] : null;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $existingJournal
|
||||
* @param TransactionJournal $newJournal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeTags(array $existingJournal, TransactionJournal $newJournal): array
|
||||
{
|
||||
$newArray = $newJournal->toArray();
|
||||
if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well.
|
||||
$tagId = (int)$newJournal['tag_id'];
|
||||
|
||||
$tagDate = null;
|
||||
try {
|
||||
$tagDate = Carbon::parse($newArray['tag_date']);
|
||||
} catch (InvalidFormatException $e) {
|
||||
Log::debug(sprintf('Could not parse date: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
$existingJournal['tags'][$tagId] = [
|
||||
'id' => (int)$newArray['tag_id'],
|
||||
'name' => $newArray['tag_name'],
|
||||
'date' => $tagDate,
|
||||
'description' => $newArray['tag_description'],
|
||||
];
|
||||
}
|
||||
|
||||
return $existingJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $existingJournal
|
||||
* @param TransactionJournal $newJournal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeAttachments(array $existingJournal, TransactionJournal $newJournal): array
|
||||
{
|
||||
$newArray = $newJournal->toArray();
|
||||
if (array_key_exists('attachment_id', $newArray)) {
|
||||
$attachmentId = (int)$newJournal['attachment_id'];
|
||||
|
||||
$existingJournal['attachments'][$attachmentId] = [
|
||||
'id' => $attachmentId,
|
||||
];
|
||||
}
|
||||
|
||||
return $existingJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $groups
|
||||
*
|
||||
@ -801,214 +1028,6 @@ class GroupCollector implements GroupCollectorInterface
|
||||
return $currentCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as getGroups but everything is in a paginator.
|
||||
*
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function getPaginatedGroups(): LengthAwarePaginator
|
||||
{
|
||||
$set = $this->getGroups();
|
||||
if (0 === $this->limit) {
|
||||
$this->setLimit(50);
|
||||
}
|
||||
|
||||
return new LengthAwarePaginator($set, $this->total, $this->limit, $this->page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of returned entries.
|
||||
*
|
||||
* @param int $limit
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setLimit(int $limit): GroupCollectorInterface
|
||||
{
|
||||
$this->limit = $limit;
|
||||
app('log')->debug(sprintf('GroupCollector: The limit is now %d', $limit));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isNotReconciled(): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('source.reconciled', 0)->where('destination.reconciled', 0);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isReconciled(): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('source.reconciled', 1)->where('destination.reconciled', 1);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a specific currency, either foreign or normal one.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where(
|
||||
static function (EloquentBuilder $q) use ($currency) {
|
||||
$q->where('source.transaction_currency_id', $currency->id);
|
||||
$q->orWhere('source.foreign_currency_id', $currency->id);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setForeignCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('source.foreign_currency_id', $currency->id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result to a set of specific transaction groups.
|
||||
*
|
||||
* @param array $groupIds
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setIds(array $groupIds): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereIn('transaction_groups.id', $groupIds);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result to a set of specific journals.
|
||||
*
|
||||
* @param array $journalIds
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setJournalIds(array $journalIds): GroupCollectorInterface
|
||||
{
|
||||
if (0 !== count($journalIds)) {
|
||||
// make all integers.
|
||||
$integerIDs = array_map('intval', $journalIds);
|
||||
|
||||
|
||||
$this->query->whereIn('transaction_journals.id', $integerIDs);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the page to get.
|
||||
*
|
||||
* @param int $page
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setPage(int $page): GroupCollectorInterface
|
||||
{
|
||||
$page = 0 === $page ? 1 : $page;
|
||||
$this->page = $page;
|
||||
app('log')->debug(sprintf('GroupCollector: page is now %d', $page));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for words in descriptions.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setSearchWords(array $array): GroupCollectorInterface
|
||||
{
|
||||
if (0 === count($array)) {
|
||||
return $this;
|
||||
}
|
||||
$this->query->where(
|
||||
static function (EloquentBuilder $q) use ($array) {
|
||||
$q->where(
|
||||
static function (EloquentBuilder $q1) use ($array) {
|
||||
foreach ($array as $word) {
|
||||
$keyword = sprintf('%%%s%%', $word);
|
||||
$q1->where('transaction_journals.description', 'LIKE', $keyword);
|
||||
}
|
||||
}
|
||||
);
|
||||
$q->orWhere(
|
||||
static function (EloquentBuilder $q2) use ($array) {
|
||||
foreach ($array as $word) {
|
||||
$keyword = sprintf('%%%s%%', $word);
|
||||
$q2->where('transaction_groups.title', 'LIKE', $keyword);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the search to one specific transaction group.
|
||||
*
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setTransactionGroup(TransactionGroup $transactionGroup): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('transaction_groups.id', $transactionGroup->id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the included transaction types.
|
||||
*
|
||||
* @param array $types
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setTypes(array $types): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereIn('transaction_types.type', $types);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user object and start the query.
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setUser(User $user): GroupCollectorInterface
|
||||
{
|
||||
if (null === $this->user) {
|
||||
$this->user = $user;
|
||||
$this->startQuery();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the query.
|
||||
*/
|
||||
@ -1051,23 +1070,4 @@ class GroupCollector implements GroupCollectorInterface
|
||||
->orderBy('transaction_journals.description', 'DESC')
|
||||
->orderBy('source.amount', 'DESC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically include all stuff required to make API calls work.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withAPIInformation(): GroupCollectorInterface
|
||||
{
|
||||
// include source + destination account name and type.
|
||||
$this->withAccountInformation()
|
||||
// include category ID + name (if any)
|
||||
->withCategoryInformation()
|
||||
// include budget ID + name (if any)
|
||||
->withBudgetInformation()
|
||||
// include bill ID + name (if any)
|
||||
->withBillInformation();
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace FireflyIII\Helpers\Fiscal;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Update;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Services\FireflyIIIOrg\Update\UpdateRequestInterface;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
|
@ -25,8 +25,8 @@ namespace FireflyIII\Helpers\Webhook;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\WebhookMessage;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
|
||||
/**
|
||||
* Class Sha3SignatureGenerator
|
||||
|
@ -34,8 +34,8 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -32,9 +32,9 @@ use FireflyIII\Support\Http\Controllers\BasicDataSupport;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -38,9 +38,9 @@ use FireflyIII\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use JsonException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -29,8 +29,8 @@ use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Requests\ConfigurationRequest;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -33,8 +33,8 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -32,8 +32,8 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* Class LinkController.
|
||||
|
@ -36,8 +36,8 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -31,8 +31,8 @@ use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -38,8 +38,8 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
@ -128,37 +128,6 @@ class LoginController extends Controller
|
||||
$this->sendFailedLoginResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the login username to be used by the controller.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function username()
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failed login response instance.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function sendFailedLoginResponse(Request $request)
|
||||
{
|
||||
$exception = ValidationException::withMessages(
|
||||
[
|
||||
$this->username() => [trans('auth.failed')],
|
||||
]
|
||||
);
|
||||
$exception->redirectTo = route('login');
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the user out of the application.
|
||||
*
|
||||
@ -244,4 +213,35 @@ class LoginController extends Controller
|
||||
|
||||
return view('auth.login', compact('allowRegistration', 'email', 'remember', 'allowReset', 'title', 'usernameField'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the login username to be used by the controller.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function username()
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failed login response instance.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function sendFailedLoginResponse(Request $request)
|
||||
{
|
||||
$exception = ValidationException::withMessages(
|
||||
[
|
||||
$this->username() => [trans('auth.failed')],
|
||||
]
|
||||
);
|
||||
$exception->redirectTo = route('login');
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
@ -35,9 +35,9 @@ use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
@ -117,30 +117,6 @@ class RegisterController extends Controller
|
||||
return redirect($this->redirectPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws FireflyException
|
||||
*/
|
||||
protected function allowedToRegister(): bool
|
||||
{
|
||||
// is allowed to register?
|
||||
$allowRegistration = true;
|
||||
try {
|
||||
$singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
|
||||
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
|
||||
$singleUserMode = true;
|
||||
}
|
||||
$userCount = User::count();
|
||||
$guard = config('auth.defaults.guard');
|
||||
if (true === $singleUserMode && $userCount > 0 && 'web' === $guard) {
|
||||
$allowRegistration = false;
|
||||
}
|
||||
if ('web' !== $guard) {
|
||||
$allowRegistration = false;
|
||||
}
|
||||
return $allowRegistration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application registration form if the invitation code is valid.
|
||||
*
|
||||
@ -201,4 +177,28 @@ class RegisterController extends Controller
|
||||
|
||||
return view('auth.register', compact('isDemoSite', 'email', 'pageTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws FireflyException
|
||||
*/
|
||||
protected function allowedToRegister(): bool
|
||||
{
|
||||
// is allowed to register?
|
||||
$allowRegistration = true;
|
||||
try {
|
||||
$singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
|
||||
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
|
||||
$singleUserMode = true;
|
||||
}
|
||||
$userCount = User::count();
|
||||
$guard = config('auth.defaults.guard');
|
||||
if (true === $singleUserMode && $userCount > 0 && 'web' === $guard) {
|
||||
$allowRegistration = false;
|
||||
}
|
||||
if ('web' !== $guard) {
|
||||
$allowRegistration = false;
|
||||
}
|
||||
return $allowRegistration;
|
||||
}
|
||||
}
|
||||
|
@ -99,26 +99,20 @@ class TwoFactorController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Each MFA history has a timestamp and a code, saving the MFA entries for 5 minutes. So if the
|
||||
* submitted MFA code has been submitted in the last 5 minutes, it won't work despite being valid.
|
||||
*
|
||||
* @param string $mfaCode
|
||||
* @param array $mfaHistory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function inMFAHistory(string $mfaCode, array $mfaHistory): bool
|
||||
private function addToMFAHistory(string $mfaCode): void
|
||||
{
|
||||
$now = time();
|
||||
foreach ($mfaHistory as $entry) {
|
||||
$time = $entry['time'];
|
||||
$code = $entry['code'];
|
||||
if ($code === $mfaCode && $now - $time <= 300) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/** @var array $mfaHistory */
|
||||
$mfaHistory = Preferences::get('mfa_history', [])->data;
|
||||
$entry = [
|
||||
'time' => time(),
|
||||
'code' => $mfaCode,
|
||||
];
|
||||
$mfaHistory[] = $entry;
|
||||
|
||||
return false;
|
||||
Preferences::set('mfa_history', $mfaHistory);
|
||||
$this->filterMFAHistory();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,20 +138,26 @@ class TwoFactorController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Each MFA history has a timestamp and a code, saving the MFA entries for 5 minutes. So if the
|
||||
* submitted MFA code has been submitted in the last 5 minutes, it won't work despite being valid.
|
||||
*
|
||||
* @param string $mfaCode
|
||||
* @param array $mfaHistory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function addToMFAHistory(string $mfaCode): void
|
||||
private function inMFAHistory(string $mfaCode, array $mfaHistory): bool
|
||||
{
|
||||
/** @var array $mfaHistory */
|
||||
$mfaHistory = Preferences::get('mfa_history', [])->data;
|
||||
$entry = [
|
||||
'time' => time(),
|
||||
'code' => $mfaCode,
|
||||
];
|
||||
$mfaHistory[] = $entry;
|
||||
$now = time();
|
||||
foreach ($mfaHistory as $entry) {
|
||||
$time = $entry['time'];
|
||||
$code = $entry['code'];
|
||||
if ($code === $mfaCode && $now - $time <= 300) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Preferences::set('mfa_history', $mfaHistory);
|
||||
$this->filterMFAHistory();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,49 +135,26 @@ class IndexController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $bills
|
||||
* Set the order of a bill.
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
private function getSums(array $bills): array
|
||||
public function setOrder(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$sums = [];
|
||||
$range = app('navigation')->getViewRange(false);
|
||||
|
||||
/** @var array $group */
|
||||
foreach ($bills as $groupOrder => $group) {
|
||||
/** @var array $bill */
|
||||
foreach ($group['bills'] as $bill) {
|
||||
if (false === $bill['active']) {
|
||||
continue;
|
||||
$objectGroupTitle = (string)$request->get('objectGroupTitle');
|
||||
$newOrder = (int)$request->get('order');
|
||||
$this->repository->setOrder($bill, $newOrder);
|
||||
if ('' !== $objectGroupTitle) {
|
||||
$this->repository->setObjectGroup($bill, $objectGroupTitle);
|
||||
}
|
||||
if ('' === $objectGroupTitle) {
|
||||
$this->repository->removeObjectGroup($bill);
|
||||
}
|
||||
|
||||
$currencyId = $bill['currency_id'];
|
||||
$sums[$groupOrder][$currencyId] = $sums[$groupOrder][$currencyId] ?? [
|
||||
'currency_id' => $currencyId,
|
||||
'currency_code' => $bill['currency_code'],
|
||||
'currency_name' => $bill['currency_name'],
|
||||
'currency_symbol' => $bill['currency_symbol'],
|
||||
'currency_decimal_places' => $bill['currency_decimal_places'],
|
||||
'avg' => '0',
|
||||
'period' => $range,
|
||||
'per_period' => '0',
|
||||
];
|
||||
// only fill in avg when bill is active.
|
||||
if (count($bill['pay_dates']) > 0) {
|
||||
$avg = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2');
|
||||
$avg = bcmul($avg, (string)count($bill['pay_dates']));
|
||||
$sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg);
|
||||
}
|
||||
// fill in per period regardless:
|
||||
$sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range));
|
||||
}
|
||||
}
|
||||
|
||||
return $sums;
|
||||
return response()->json(['data' => 'OK']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -227,6 +204,52 @@ class IndexController extends Controller
|
||||
return $perPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $bills
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
private function getSums(array $bills): array
|
||||
{
|
||||
$sums = [];
|
||||
$range = app('navigation')->getViewRange(false);
|
||||
|
||||
/** @var array $group */
|
||||
foreach ($bills as $groupOrder => $group) {
|
||||
/** @var array $bill */
|
||||
foreach ($group['bills'] as $bill) {
|
||||
if (false === $bill['active']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$currencyId = $bill['currency_id'];
|
||||
$sums[$groupOrder][$currencyId] = $sums[$groupOrder][$currencyId] ?? [
|
||||
'currency_id' => $currencyId,
|
||||
'currency_code' => $bill['currency_code'],
|
||||
'currency_name' => $bill['currency_name'],
|
||||
'currency_symbol' => $bill['currency_symbol'],
|
||||
'currency_decimal_places' => $bill['currency_decimal_places'],
|
||||
'avg' => '0',
|
||||
'period' => $range,
|
||||
'per_period' => '0',
|
||||
];
|
||||
// only fill in avg when bill is active.
|
||||
if (count($bill['pay_dates']) > 0) {
|
||||
$avg = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2');
|
||||
$avg = bcmul($avg, (string)count($bill['pay_dates']));
|
||||
$sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg);
|
||||
}
|
||||
// fill in per period regardless:
|
||||
$sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range));
|
||||
}
|
||||
}
|
||||
|
||||
return $sums;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sums
|
||||
*
|
||||
@ -264,27 +287,4 @@ class IndexController extends Controller
|
||||
|
||||
return $totals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order of a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function setOrder(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$objectGroupTitle = (string)$request->get('objectGroupTitle');
|
||||
$newOrder = (int)$request->get('order');
|
||||
$this->repository->setOrder($bill, $newOrder);
|
||||
if ('' !== $objectGroupTitle) {
|
||||
$this->repository->setObjectGroup($bill, $objectGroupTitle);
|
||||
}
|
||||
if ('' === $objectGroupTitle) {
|
||||
$this->repository->removeObjectGroup($bill);
|
||||
}
|
||||
|
||||
return response()->json(['data' => 'OK']);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ namespace FireflyIII\Http\Controllers\Budget;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
@ -41,8 +40,8 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
*
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user