Merge branch 'develop' into CSV-ING

This commit is contained in:
James Cole 2020-03-18 19:56:50 +00:00 committed by GitHub
commit ae967c027b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
710 changed files with 13527 additions and 17584 deletions

View File

@ -16,3 +16,4 @@ sv_SE
zh-hans_CN zh-hans_CN
zh-hant_CN zh-hant_CN
fi_FI fi_FI
vi_VN

View File

@ -104,7 +104,7 @@ class AccountController extends Controller
// types to get, page size: // types to get, page size:
$types = $this->mapAccountTypes($this->parameters->get('type')); $types = $this->mapAccountTypes($this->parameters->get('type'));
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it. // get list of accounts. Count it and split it.
$collection = $this->repository->getAccountsByType($types); $collection = $this->repository->getAccountsByType($types);
@ -142,7 +142,7 @@ class AccountController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->repository->getPiggyBanks($account); $collection = $this->repository->getPiggyBanks($account);
@ -218,7 +218,7 @@ class AccountController extends Controller
*/ */
public function transactions(Request $request, Account $account): JsonResponse public function transactions(Request $request, Account $account): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);
@ -227,10 +227,8 @@ class AccountController extends Controller
if (null !== $limit && $limit > 0) { if (null !== $limit && $limit > 0) {
$pageSize = $limit; $pageSize = $limit;
} }
$types = $this->mapTransactionTypes($this->parameters->get('type')); $types = $this->mapTransactionTypes($this->parameters->get('type'));
$manager = $this->getManager(); $manager = $this->getManager();
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
@ -240,7 +238,6 @@ class AccountController extends Controller
$collector->setUser($admin)->setAccounts(new Collection([$account])) $collector->setUser($admin)->setAccounts(new Collection([$account]))
->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types); ->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types);
// set range if necessary:
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); $collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
} }

View File

@ -92,8 +92,8 @@ class AttachmentController extends Controller
* @param Attachment $attachment * @param Attachment $attachment
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @return LaravelResponse
* @throws FireflyException * @throws FireflyException
* @return LaravelResponse
*/ */
public function download(Attachment $attachment): LaravelResponse public function download(Attachment $attachment): LaravelResponse
{ {
@ -108,7 +108,7 @@ class AttachmentController extends Controller
if ('' === $content) { if ('' === $content) {
throw new FireflyException('200002: File is empty (zero bytes).'); throw new FireflyException('200002: File is empty (zero bytes).');
} }
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\')); $quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
/** @var LaravelResponse $response */ /** @var LaravelResponse $response */
$response = response($content); $response = response($content);
@ -139,7 +139,7 @@ class AttachmentController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it. // get list of accounts. Count it and split it.
$collection = $this->repository->get(); $collection = $this->repository->get();
@ -184,8 +184,8 @@ class AttachmentController extends Controller
* *
* @param AttachmentStoreRequest $request * @param AttachmentStoreRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function store(AttachmentStoreRequest $request): JsonResponse public function store(AttachmentStoreRequest $request): JsonResponse
{ {

View File

@ -92,7 +92,7 @@ class AvailableBudgetController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$start = $this->parameters->get('start'); $start = $this->parameters->get('start');
$end = $this->parameters->get('end'); $end = $this->parameters->get('end');

View File

@ -85,7 +85,7 @@ class BillController extends Controller
public function attachments(Bill $bill): JsonResponse public function attachments(Bill $bill): JsonResponse
{ {
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAttachments($bill); $collection = $this->repository->getAttachments($bill);
$count = $collection->count(); $count = $collection->count();
@ -130,7 +130,7 @@ class BillController extends Controller
{ {
$bills = $this->repository->getBills(); $bills = $this->repository->getBills();
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$count = $bills->count(); $count = $bills->count();
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
@ -158,7 +158,7 @@ class BillController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->repository->getRulesForBill($bill); $collection = $this->repository->getRulesForBill($bill);
@ -206,8 +206,8 @@ class BillController extends Controller
* *
* @param BillRequest $request * @param BillRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function store(BillRequest $request): JsonResponse public function store(BillRequest $request): JsonResponse
{ {
@ -235,7 +235,7 @@ class BillController extends Controller
*/ */
public function transactions(Request $request, Bill $bill): JsonResponse public function transactions(Request $request, Bill $bill): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);

View File

@ -25,7 +25,8 @@ namespace FireflyIII\Api\V1\Controllers;
use Exception; use Exception;
use FireflyIII\Api\V1\Requests\BudgetLimitRequest; use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
use FireflyIII\Api\V1\Requests\BudgetRequest; use FireflyIII\Api\V1\Requests\BudgetStoreRequest;
use FireflyIII\Api\V1\Requests\BudgetUpdateRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
@ -89,7 +90,7 @@ class BudgetController extends Controller
public function budgetLimits(Budget $budget): JsonResponse public function budgetLimits(Budget $budget): JsonResponse
{ {
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$this->parameters->set('budget_id', $budget->id); $this->parameters->set('budget_id', $budget->id);
$collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end')); $collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
$count = $collection->count(); $count = $collection->count();
@ -134,7 +135,7 @@ class BudgetController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->repository->getBudgets(); $collection = $this->repository->getBudgets();
@ -179,13 +180,13 @@ class BudgetController extends Controller
/** /**
* Store a budget. * Store a budget.
* *
* @param BudgetRequest $request * @param BudgetStoreRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* *
* @return JsonResponse
*/ */
public function store(BudgetRequest $request): JsonResponse public function store(BudgetStoreRequest $request): JsonResponse
{ {
$budget = $this->repository->store($request->getAll()); $budget = $this->repository->store($request->getAll());
$manager = $this->getManager(); $manager = $this->getManager();
@ -205,8 +206,8 @@ class BudgetController extends Controller
* @param BudgetLimitRequest $request * @param BudgetLimitRequest $request
* @param Budget $budget * @param Budget $budget
* *
* @return JsonResponse
* @throws Exception * @throws Exception
* @return JsonResponse
*/ */
public function storeBudgetLimit(BudgetLimitRequest $request, Budget $budget): JsonResponse public function storeBudgetLimit(BudgetLimitRequest $request, Budget $budget): JsonResponse
{ {
@ -236,7 +237,7 @@ class BudgetController extends Controller
*/ */
public function transactions(Request $request, Budget $budget): JsonResponse public function transactions(Request $request, Budget $budget): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// user can overrule page size with limit parameter. // user can overrule page size with limit parameter.
$limit = $this->parameters->get('limit'); $limit = $this->parameters->get('limit');
@ -291,12 +292,12 @@ class BudgetController extends Controller
/** /**
* Update a budget. * Update a budget.
* *
* @param BudgetRequest $request * @param BudgetUpdateRequest $request
* @param Budget $budget * @param Budget $budget
* *
* @return JsonResponse * @return JsonResponse
*/ */
public function update(BudgetRequest $request, Budget $budget): JsonResponse public function update(BudgetUpdateRequest $request, Budget $budget): JsonResponse
{ {
$data = $request->getAll(); $data = $request->getAll();
$budget = $this->repository->update($budget, $data); $budget = $this->repository->update($budget, $data);

View File

@ -102,9 +102,9 @@ class BudgetLimitController extends Controller
public function index(Request $request): JsonResponse public function index(Request $request): JsonResponse
{ {
$manager = $this->getManager(); $manager = $this->getManager();
$budgetId = (int)($request->get('budget_id') ?? 0); $budgetId = (int) ($request->get('budget_id') ?? 0);
$budget = $this->repository->findNull($budgetId); $budget = $this->repository->findNull($budgetId);
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$this->parameters->set('budget_id', $budgetId); $this->parameters->set('budget_id', $budgetId);
$collection = new Collection; $collection = new Collection;
@ -156,16 +156,16 @@ class BudgetLimitController extends Controller
* *
* @param BudgetLimitRequest $request * @param BudgetLimitRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* *
* @return JsonResponse
*/ */
public function store(BudgetLimitRequest $request): JsonResponse public function store(BudgetLimitRequest $request): JsonResponse
{ {
$data = $request->getAll(); $data = $request->getAll();
$budget = $this->repository->findNull($data['budget_id']); $budget = $this->repository->findNull($data['budget_id']);
if (null === $budget) { if (null === $budget) {
throw new FireflyException('200004: Budget does not exist.'); throw new FireflyException('200004: Budget does not exist.'); // @codeCoverageIgnore
} }
$data['budget'] = $budget; $data['budget'] = $budget;
$budgetLimit = $this->blRepository->storeBudgetLimit($data); $budgetLimit = $this->blRepository->storeBudgetLimit($data);
@ -191,7 +191,7 @@ class BudgetLimitController extends Controller
*/ */
public function transactions(Request $request, BudgetLimit $budgetLimit): JsonResponse public function transactions(Request $request, BudgetLimit $budgetLimit): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);

View File

@ -97,7 +97,7 @@ class CategoryController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->repository->getCategories(); $collection = $this->repository->getCategories();
@ -146,13 +146,13 @@ class CategoryController extends Controller
* *
* @param CategoryRequest $request * @param CategoryRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function store(CategoryRequest $request): JsonResponse public function store(CategoryRequest $request): JsonResponse
{ {
$category = $this->repository->store($request->getAll()); $category = $this->repository->store($request->getAll());
$manager = $this->getManager(); $manager = $this->getManager();
/** @var CategoryTransformer $transformer */ /** @var CategoryTransformer $transformer */
$transformer = app(CategoryTransformer::class); $transformer = app(CategoryTransformer::class);
@ -175,7 +175,7 @@ class CategoryController extends Controller
*/ */
public function transactions(Request $request, Category $category): JsonResponse public function transactions(Request $request, Category $category): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);

View File

@ -99,10 +99,10 @@ class AccountController extends Controller
// loop the end balances. This is an array for each account ($expenses) // loop the end balances. This is an array for each account ($expenses)
foreach ($endBalances as $accountId => $expenses) { foreach ($endBalances as $accountId => $expenses) {
$accountId = (int)$accountId; $accountId = (int) $accountId;
// loop each expense entry (each entry can be a different currency). // loop each expense entry (each entry can be a different currency).
foreach ($expenses as $currencyId => $endAmount) { foreach ($expenses as $currencyId => $endAmount) {
$currencyId = (int)$currencyId; $currencyId = (int) $currencyId;
// see if there is an accompanying start amount. // see if there is an accompanying start amount.
// grab the difference and find the currency. // grab the difference and find the currency.
@ -114,7 +114,7 @@ class AccountController extends Controller
$tempData[] = [ $tempData[] = [
'name' => $accountNames[$accountId], 'name' => $accountNames[$accountId],
'difference' => $diff, 'difference' => $diff,
'diff_float' => (float)$diff, 'diff_float' => (float) $diff,
'currency_id' => $currencyId, 'currency_id' => $currencyId,
]; ];
} }
@ -247,10 +247,10 @@ class AccountController extends Controller
// loop the end balances. This is an array for each account ($expenses) // loop the end balances. This is an array for each account ($expenses)
foreach ($endBalances as $accountId => $expenses) { foreach ($endBalances as $accountId => $expenses) {
$accountId = (int)$accountId; $accountId = (int) $accountId;
// loop each expense entry (each entry can be a different currency). // loop each expense entry (each entry can be a different currency).
foreach ($expenses as $currencyId => $endAmount) { foreach ($expenses as $currencyId => $endAmount) {
$currencyId = (int)$currencyId; $currencyId = (int) $currencyId;
// see if there is an accompanying start amount. // see if there is an accompanying start amount.
// grab the difference and find the currency. // grab the difference and find the currency.
@ -263,7 +263,7 @@ class AccountController extends Controller
'name' => $accountNames[$accountId], 'name' => $accountNames[$accountId],
'difference' => bcmul($diff, '-1'), 'difference' => bcmul($diff, '-1'),
// For some reason this line is never covered in code coverage: // For some reason this line is never covered in code coverage:
'diff_float' => ((float)$diff) * -1, // @codeCoverageIgnore 'diff_float' => ((float) $diff) * -1, // @codeCoverageIgnore
'currency_id' => $currencyId, 'currency_id' => $currencyId,
]; ];
} }

View File

@ -83,9 +83,9 @@ class AvailableBudgetController extends Controller
$spent = $spentInfo['amount']; $spent = $spentInfo['amount'];
} }
} }
$left = bcadd($availableBudget->amount, (string)$spent); $left = bcadd($availableBudget->amount, (string) $spent);
// left less than zero? Set to zero. // left less than zero? Set to zero.
if (bccomp($left, '0') === -1) { if (-1 === bccomp($left, '0')) {
$left = '0'; $left = '0';
} }

View File

@ -90,8 +90,8 @@ class CategoryController extends Controller
$tempData = []; $tempData = [];
$spentWith = $this->opsRepository->listExpenses($start, $end); $spentWith = $this->opsRepository->listExpenses($start, $end);
$earnedWith = $this->opsRepository->listIncome($start, $end); $earnedWith = $this->opsRepository->listIncome($start, $end);
$spentWithout = $this->noCatRepository->listExpenses($start, $end); // refactored $spentWithout = $this->noCatRepository->listExpenses($start, $end);
$earnedWithout = $this->noCatRepository->listIncome($start, $end); // refactored $earnedWithout = $this->noCatRepository->listIncome($start, $end);
$categories = []; $categories = [];
@ -104,7 +104,7 @@ class CategoryController extends Controller
// make data arrays if not yet present. // make data arrays if not yet present.
$tempData[$inKey] = $tempData[$inKey] ?? [ $tempData[$inKey] = $tempData[$inKey] ?? [
'currency_id' => $currency['currency_id'], 'currency_id' => $currency['currency_id'],
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]), 'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'], 'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'], 'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'], 'currency_decimal_places' => $currency['currency_decimal_places'],
@ -117,7 +117,7 @@ class CategoryController extends Controller
]; ];
$tempData[$outKey] = $tempData[$outKey] ?? [ $tempData[$outKey] = $tempData[$outKey] ?? [
'currency_id' => $currency['currency_id'], 'currency_id' => $currency['currency_id'],
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]), 'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'], 'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'], 'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'], 'currency_decimal_places' => $currency['currency_decimal_places'],
@ -141,48 +141,48 @@ class CategoryController extends Controller
} }
} }
// foreach ([] as $set) { // foreach ([] as $set) {
// foreach ($set as $currency) { // foreach ($set as $currency) {
// $inKey = sprintf('%d-i', $currency['currency_id']); // $inKey = sprintf('%d-i', $currency['currency_id']);
// $outKey = sprintf('%d-e', $currency['currency_id']); // $outKey = sprintf('%d-e', $currency['currency_id']);
// $categories[] = (string)trans('firefly.no_category'); // $categories[] = (string)trans('firefly.no_category');
// // make data arrays if not yet present. // // make data arrays if not yet present.
// $tempData[$inKey] = $tempData[$inKey] ?? [ // $tempData[$inKey] = $tempData[$inKey] ?? [
// 'currency_id' => $currency['currency_id'], // 'currency_id' => $currency['currency_id'],
// 'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]), // 'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
// 'currency_code' => $currency['currency_code'], // 'currency_code' => $currency['currency_code'],
// 'currency_symbol' => $currency['currency_symbol'], // 'currency_symbol' => $currency['currency_symbol'],
// 'currency_decimal_places' => $currency['currency_decimal_places'], // 'currency_decimal_places' => $currency['currency_decimal_places'],
// 'type' => 'bar', // line, area or bar // 'type' => 'bar', // line, area or bar
// 'yAxisID' => 0, // 0, 1, 2 // 'yAxisID' => 0, // 0, 1, 2
// 'entries' => [ // 'entries' => [
// // per category: // // per category:
// // "category" => 5, // // "category" => 5,
// ], // ],
// ]; // ];
// $tempData[$outKey] = $tempData[$outKey] ?? [ // $tempData[$outKey] = $tempData[$outKey] ?? [
// 'currency_id' => $currency['currency_id'], // 'currency_id' => $currency['currency_id'],
// 'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]), // 'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
// 'currency_code' => $currency['currency_code'], // 'currency_code' => $currency['currency_code'],
// 'currency_symbol' => $currency['currency_symbol'], // 'currency_symbol' => $currency['currency_symbol'],
// 'currency_decimal_places' => $currency['currency_decimal_places'], // 'currency_decimal_places' => $currency['currency_decimal_places'],
// 'type' => 'bar', // line, area or bar // 'type' => 'bar', // line, area or bar
// 'yAxisID' => 0, // 0, 1, 2 // 'yAxisID' => 0, // 0, 1, 2
// 'entries' => [ // 'entries' => [
// // per category: // // per category:
// // "category" => 5, // // "category" => 5,
// ], // ],
// ]; // ];
// foreach ($currency['transaction_journals'] as $journal) { // foreach ($currency['transaction_journals'] as $journal) {
// // is it expense or income? // // is it expense or income?
// $letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i'; // $letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
// $currentKey = sprintf('%d-%s', $currency['currency_id'], $letter); // $currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
// $name = (string)trans('firefly.no_category'); // $name = (string)trans('firefly.no_category');
// $tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0'; // $tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
// $tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']); // $tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
// } // }
// } // }
// } // }
// re-sort every spent array and add 0 for missing entries. // re-sort every spent array and add 0 for missing entries.
foreach ($tempData as $index => $set) { foreach ($tempData as $index => $set) {

View File

@ -51,7 +51,6 @@ class ConfigurationController extends Controller
parent::__construct(); parent::__construct();
$this->middleware( $this->middleware(
function ($request, $next) { function ($request, $next) {
/** @noinspection UnusedConstructorDependenciesInspection */
$this->repository = app(UserRepositoryInterface::class); $this->repository = app(UserRepositoryInterface::class);
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
@ -109,13 +108,12 @@ class ConfigurationController extends Controller
$lastCheck = app('fireflyconfig')->get('last_update_check'); $lastCheck = app('fireflyconfig')->get('last_update_check');
/** @var Configuration $singleUser */ /** @var Configuration $singleUser */
$singleUser = app('fireflyconfig')->get('single_user_mode'); $singleUser = app('fireflyconfig')->get('single_user_mode');
$data = [
return [
'is_demo_site' => null === $isDemoSite ? null : $isDemoSite->data, 'is_demo_site' => null === $isDemoSite ? null : $isDemoSite->data,
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data, 'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data,
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data, 'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data,
'single_user_mode' => null === $singleUser ? null : $singleUser->data, 'single_user_mode' => null === $singleUser ? null : $singleUser->data,
]; ];
return $data;
} }
} }

View File

@ -104,7 +104,7 @@ class Controller extends BaseController
private function getParameters(): ParameterBag private function getParameters(): ParameterBag
{ {
$bag = new ParameterBag; $bag = new ParameterBag;
$page = (int)request()->get('page'); $page = (int) request()->get('page');
if (0 === $page) { if (0 === $page) {
$page = 1; $page = 1;
} }
@ -131,7 +131,7 @@ class Controller extends BaseController
foreach ($integers as $integer) { foreach ($integers as $integer) {
$value = request()->query->get($integer); $value = request()->query->get($integer);
if (null !== $value) { if (null !== $value) {
$bag->set($integer, (int)$value); $bag->set($integer, (int) $value);
} }
} }

View File

@ -116,7 +116,7 @@ class CurrencyController extends Controller
// types to get, page size: // types to get, page size:
$types = $this->mapAccountTypes($this->parameters->get('type')); $types = $this->mapAccountTypes($this->parameters->get('type'));
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it. // get list of accounts. Count it and split it.
/** @var AccountRepositoryInterface $accountRepository */ /** @var AccountRepositoryInterface $accountRepository */
@ -126,7 +126,7 @@ class CurrencyController extends Controller
// filter list on currency preference: // filter list on currency preference:
$collection = $unfiltered->filter( $collection = $unfiltered->filter(
static function (Account $account) use ($currency, $accountRepository) { static function (Account $account) use ($currency, $accountRepository) {
$currencyId = (int)$accountRepository->getMetaValue($account, 'currency_id'); $currencyId = (int) $accountRepository->getMetaValue($account, 'currency_id');
return $currencyId === $currency->id; return $currencyId === $currency->id;
} }
@ -165,7 +165,7 @@ class CurrencyController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of available budgets. Count it and split it. // get list of available budgets. Count it and split it.
@ -209,7 +209,7 @@ class CurrencyController extends Controller
/** @var BillRepositoryInterface $repository */ /** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class); $repository = app(BillRepositoryInterface::class);
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$unfiltered = $repository->getBills(); $unfiltered = $repository->getBills();
// filter and paginate list: // filter and paginate list:
@ -249,7 +249,7 @@ class CurrencyController extends Controller
$blRepository = app(BudgetLimitRepositoryInterface::class); $blRepository = app(BudgetLimitRepositoryInterface::class);
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $blRepository->getAllBudgetLimitsByCurrency($currency, $this->parameters->get('start'), $this->parameters->get('end')); $collection = $blRepository->getAllBudgetLimitsByCurrency($currency, $this->parameters->get('start'), $this->parameters->get('end'));
$count = $collection->count(); $count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
@ -278,7 +278,7 @@ class CurrencyController extends Controller
{ {
// create some objects: // create some objects:
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getExchangeRates($currency); $collection = $this->repository->getExchangeRates($currency);
@ -302,9 +302,9 @@ class CurrencyController extends Controller
* *
* @param TransactionCurrency $currency * @param TransactionCurrency $currency
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @codeCoverageIgnore * @codeCoverageIgnore
* @return JsonResponse
*/ */
public function delete(TransactionCurrency $currency): JsonResponse public function delete(TransactionCurrency $currency): JsonResponse
{ {
@ -391,7 +391,7 @@ class CurrencyController extends Controller
*/ */
public function index(): JsonResponse public function index(): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$collection = $this->repository->getAll(); $collection = $this->repository->getAll();
$count = $collection->count(); $count = $collection->count();
// slice them: // slice them:
@ -455,7 +455,7 @@ class CurrencyController extends Controller
{ {
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
/** @var RecurringRepositoryInterface $repository */ /** @var RecurringRepositoryInterface $repository */
@ -506,7 +506,7 @@ class CurrencyController extends Controller
public function rules(TransactionCurrency $currency): JsonResponse public function rules(TransactionCurrency $currency): JsonResponse
{ {
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
/** @var RuleRepositoryInterface $repository */ /** @var RuleRepositoryInterface $repository */
@ -572,8 +572,8 @@ class CurrencyController extends Controller
* *
* @param CurrencyRequest $request * @param CurrencyRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function store(CurrencyRequest $request): JsonResponse public function store(CurrencyRequest $request): JsonResponse
{ {
@ -607,7 +607,7 @@ class CurrencyController extends Controller
*/ */
public function transactions(Request $request, TransactionCurrency $currency): JsonResponse public function transactions(Request $request, TransactionCurrency $currency): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);

View File

@ -69,8 +69,8 @@ class CurrencyExchangeRateController extends Controller
* *
* @param Request $request * @param Request $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function index(Request $request): JsonResponse public function index(Request $request): JsonResponse
{ {

View File

@ -40,6 +40,9 @@ use League\Fractal\Resource\Item;
/** /**
* Class ImportController * Class ImportController
*
* @deprecated
* @codeCoverageIgnore
*/ */
class ImportController extends Controller class ImportController extends Controller
{ {
@ -75,7 +78,7 @@ class ImportController extends Controller
{ {
// create some objects: // create some objects:
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it. // get list of accounts. Count it and split it.
$collection = $this->repository->get(); $collection = $this->repository->get();
@ -125,7 +128,7 @@ class ImportController extends Controller
*/ */
public function transactions(Request $request, ImportJob $importJob): JsonResponse public function transactions(Request $request, ImportJob $importJob): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);

View File

@ -79,9 +79,9 @@ class LinkTypeController extends Controller
* *
* @param LinkType $linkType * @param LinkType $linkType
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @codeCoverageIgnore * @codeCoverageIgnore
* @return JsonResponse
*/ */
public function delete(LinkType $linkType): JsonResponse public function delete(LinkType $linkType): JsonResponse
{ {
@ -103,7 +103,7 @@ class LinkTypeController extends Controller
{ {
// create some objects: // create some objects:
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it. // get list of accounts. Count it and split it.
$collection = $this->repository->get(); $collection = $this->repository->get();
@ -151,8 +151,8 @@ class LinkTypeController extends Controller
* *
* @param LinkTypeRequest $request * @param LinkTypeRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function store(LinkTypeRequest $request): JsonResponse public function store(LinkTypeRequest $request): JsonResponse
{ {
@ -187,7 +187,7 @@ class LinkTypeController extends Controller
*/ */
public function transactions(Request $request, LinkType $linkType): JsonResponse public function transactions(Request $request, LinkType $linkType): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);
@ -241,8 +241,8 @@ class LinkTypeController extends Controller
* @param LinkTypeRequest $request * @param LinkTypeRequest $request
* @param LinkType $linkType * @param LinkType $linkType
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse
{ {

View File

@ -93,7 +93,7 @@ class PiggyBankController extends Controller
{ {
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->repository->getPiggyBanks(); $collection = $this->repository->getPiggyBanks();
@ -126,7 +126,7 @@ class PiggyBankController extends Controller
public function piggyBankEvents(PiggyBank $piggyBank): JsonResponse public function piggyBankEvents(PiggyBank $piggyBank): JsonResponse
{ {
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = $this->getManager(); $manager = $this->getManager();
$collection = $this->repository->getEvents($piggyBank); $collection = $this->repository->getEvents($piggyBank);
@ -175,13 +175,13 @@ class PiggyBankController extends Controller
* *
* @param PiggyBankRequest $request * @param PiggyBankRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function store(PiggyBankRequest $request): JsonResponse public function store(PiggyBankRequest $request): JsonResponse
{ {
$piggyBank = $this->repository->store($request->getAll()); $piggyBank = $this->repository->store($request->getAll());
$manager = $this->getManager(); $manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);

View File

@ -147,10 +147,10 @@ class PreferenceController extends Controller
$newValue = explode(',', $data['data']); $newValue = explode(',', $data['data']);
break; break;
case 'listPageSize': case 'listPageSize':
$newValue = (int)$data['data']; $newValue = (int) $data['data'];
break; break;
case 'customFiscalYear': case 'customFiscalYear':
$newValue = 1 === (int)$data['data']; $newValue = 1 === (int) $data['data'];
break; break;
} }
$result = app('preferences')->set($preference->name, $newValue); $result = app('preferences')->set($preference->name, $newValue);

View File

@ -99,7 +99,7 @@ class RecurrenceController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->repository->getAll(); $collection = $this->repository->getAll();
@ -149,8 +149,8 @@ class RecurrenceController extends Controller
* *
* @param RecurrenceStoreRequest $request * @param RecurrenceStoreRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function store(RecurrenceStoreRequest $request): JsonResponse public function store(RecurrenceStoreRequest $request): JsonResponse
{ {
@ -178,7 +178,7 @@ class RecurrenceController extends Controller
*/ */
public function transactions(Request $request, Recurrence $recurrence): JsonResponse public function transactions(Request $request, Recurrence $recurrence): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);
@ -224,9 +224,9 @@ class RecurrenceController extends Controller
} }
/** /**
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @codeCoverageIgnore * @codeCoverageIgnore
* @return JsonResponse
*/ */
public function trigger(): JsonResponse public function trigger(): JsonResponse
{ {

View File

@ -105,7 +105,7 @@ class RuleController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->ruleRepository->getAll(); $collection = $this->ruleRepository->getAll();
@ -214,12 +214,12 @@ class RuleController extends Controller
* @param RuleTestRequest $request * @param RuleTestRequest $request
* @param Rule $rule * @param Rule $rule
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function testRule(RuleTestRequest $request, Rule $rule): JsonResponse public function testRule(RuleTestRequest $request, Rule $rule): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$parameters = $request->getTestParameters(); $parameters = $request->getTestParameters();
/** @var Rule $rule */ /** @var Rule $rule */
Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title)); Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title));

View File

@ -106,7 +106,7 @@ class RuleGroupController extends Controller
{ {
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of rule groups. Count it and split it. // get list of rule groups. Count it and split it.
$collection = $this->ruleGroupRepository->get(); $collection = $this->ruleGroupRepository->get();
@ -177,7 +177,7 @@ class RuleGroupController extends Controller
{ {
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->ruleGroupRepository->getRules($group); $collection = $this->ruleGroupRepository->getRules($group);
@ -246,13 +246,13 @@ class RuleGroupController extends Controller
* @param RuleGroupTestRequest $request * @param RuleGroupTestRequest $request
* @param RuleGroup $group * @param RuleGroup $group
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* *
* @return JsonResponse
*/ */
public function testGroup(RuleGroupTestRequest $request, RuleGroup $group): JsonResponse public function testGroup(RuleGroupTestRequest $request, RuleGroup $group): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
Log::debug('Now in testGroup()'); Log::debug('Now in testGroup()');
/** @var Collection $rules */ /** @var Collection $rules */
$rules = $this->ruleGroupRepository->getActiveRules($group); $rules = $this->ruleGroupRepository->getActiveRules($group);
@ -305,8 +305,8 @@ class RuleGroupController extends Controller
* @param RuleGroupTriggerRequest $request * @param RuleGroupTriggerRequest $request
* @param RuleGroup $group * @param RuleGroup $group
* *
* @return JsonResponse
* @throws Exception * @throws Exception
* @return JsonResponse
*/ */
public function triggerGroup(RuleGroupTriggerRequest $request, RuleGroup $group): JsonResponse public function triggerGroup(RuleGroupTriggerRequest $request, RuleGroup $group): JsonResponse
{ {

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
/** /**
* AccountController.php * AccountController.php
* Copyright (c) 2019 james@firefly-iii.org * Copyright (c) 2019 james@firefly-iii.org
@ -21,7 +22,6 @@
namespace FireflyIII\Api\V1\Controllers\Search; namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Search\AccountSearch; use FireflyIII\Support\Search\AccountSearch;
@ -97,5 +97,4 @@ class AccountController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
} }
}
}

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
/** /**
* TransactionController.php * TransactionController.php
* Copyright (c) 2019 james@firefly-iii.org * Copyright (c) 2019 james@firefly-iii.org
@ -21,13 +22,8 @@
namespace FireflyIII\Api\V1\Controllers\Search; namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Support\Search\SearchInterface;
use FireflyIII\Support\Search\TransactionSearch;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response;
/** /**
* Class TransactionController * Class TransactionController
@ -35,13 +31,13 @@ use Illuminate\Http\Response;
class TransactionController extends Controller class TransactionController extends Controller
{ {
/** @var string */ /** @var string */
const SEARCH_ALL = 'all'; public const SEARCH_ALL = 'all';
/** @var string */ /** @var string */
const SEARCH_DESCRIPTION = 'description'; public const SEARCH_DESCRIPTION = 'description';
/** @var string */ /** @var string */
const SEARCH_NOTES = 'notes'; public const SEARCH_NOTES = 'notes';
/** @var string */ /** @var string */
const SEARCH_ACCOUNTS = 'accounts'; public const SEARCH_ACCOUNTS = 'accounts';
/** @var array */ /** @var array */
private $validFields; private $validFields;
@ -59,11 +55,10 @@ class TransactionController extends Controller
/** /**
* @param Request $request * @param Request $request
* *
* @return JsonResponse|Response * @return void
*/ */
public function search(Request $request) public function search(Request $request): void
{ {
die('the route is present but nobody\'s home.'); die('the route is present but nobody\'s home.');
} }
}
}

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
/** /**
* TransferController.php * TransferController.php
* Copyright (c) 2019 james@firefly-iii.org * Copyright (c) 2019 james@firefly-iii.org
@ -21,16 +22,13 @@
namespace FireflyIII\Api\V1\Controllers\Search; namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Search\TransferRequest; use FireflyIII\Api\V1\Requests\Search\TransferRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Support\Search\TransferSearch; use FireflyIII\Support\Search\TransferSearch;
use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Collection as FractalCollection;
@ -41,10 +39,9 @@ use League\Fractal\Resource\Collection as FractalCollection;
class TransferController extends Controller class TransferController extends Controller
{ {
/** /**
* @param Request $request * @param TransferRequest $request
* *
* @return JsonResponse|Response * @return JsonResponse|Response
* @throws FireflyException
*/ */
public function search(TransferRequest $request) public function search(TransferRequest $request)
{ {
@ -82,7 +79,7 @@ class TransferController extends Controller
} }
// collector to return results. // collector to return results.
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = $this->getManager(); $manager = $this->getManager();
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
@ -113,4 +110,4 @@ class TransferController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
} }
} }

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers; namespace FireflyIII\Api\V1\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use Exception; use Exception;
use FireflyIII\Api\V1\Requests\DateRequest; use FireflyIII\Api\V1\Requests\DateRequest;
@ -42,7 +41,6 @@ use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
/** /**
* Class SummaryController * Class SummaryController
@ -98,8 +96,8 @@ class SummaryController extends Controller
/** /**
* @param DateRequest $request * @param DateRequest $request
* *
* @return JsonResponse
* @throws Exception * @throws Exception
* @return JsonResponse
*/ */
public function basic(DateRequest $request): JsonResponse public function basic(DateRequest $request): JsonResponse
{ {
@ -125,7 +123,6 @@ class SummaryController extends Controller
} }
return response()->json($return); return response()->json($return);
} }
/** /**
@ -152,25 +149,6 @@ class SummaryController extends Controller
return $result; return $result;
} }
/**
* This method will scroll through the results of the spentInPeriodMc() array and return the correct info.
*
* @param array $spentInfo
* @param TransactionCurrency $currency
*
* @return string
*/
private function findInSpentArray(array $spentInfo, TransactionCurrency $currency): string
{
foreach ($spentInfo as $array) {
if ($array['currency_id'] === $currency->id) {
return (string)$array['amount'];
}
}
return '0'; // @codeCoverageIgnore
}
/** /**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
@ -198,8 +176,7 @@ class SummaryController extends Controller
$set = $collector->getExtractedJournals(); $set = $collector->getExtractedJournals();
/** @var array $transactionJournal */ /** @var array $transactionJournal */
foreach ($set as $transactionJournal) { foreach ($set as $transactionJournal) {
$currencyId = (int) $transactionJournal['currency_id'];
$currencyId = (int)$transactionJournal['currency_id'];
$incomes[$currencyId] = $incomes[$currencyId] ?? '0'; $incomes[$currencyId] = $incomes[$currencyId] ?? '0';
$incomes[$currencyId] = bcadd($incomes[$currencyId], bcmul($transactionJournal['amount'], '-1')); $incomes[$currencyId] = bcadd($incomes[$currencyId], bcmul($transactionJournal['amount'], '-1'));
$sums[$currencyId] = $sums[$currencyId] ?? '0'; $sums[$currencyId] = $sums[$currencyId] ?? '0';
@ -221,7 +198,7 @@ class SummaryController extends Controller
/** @var array $transactionJournal */ /** @var array $transactionJournal */
foreach ($set as $transactionJournal) { foreach ($set as $transactionJournal) {
$currencyId = (int)$transactionJournal['currency_id']; $currencyId = (int) $transactionJournal['currency_id'];
$expenses[$currencyId] = $expenses[$currencyId] ?? '0'; $expenses[$currencyId] = $expenses[$currencyId] ?? '0';
$expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']); $expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']);
$sums[$currencyId] = $sums[$currencyId] ?? '0'; $sums[$currencyId] = $sums[$currencyId] ?? '0';
@ -295,7 +272,7 @@ class SummaryController extends Controller
$return = []; $return = [];
foreach ($paidAmount as $currencyId => $amount) { foreach ($paidAmount as $currencyId => $amount) {
$amount = bcmul($amount, '-1'); $amount = bcmul($amount, '-1');
$currency = $this->currencyRepos->findNull((int)$currencyId); $currency = $this->currencyRepos->findNull((int) $currencyId);
if (null === $currency) { if (null === $currency) {
continue; continue;
} }
@ -315,7 +292,7 @@ class SummaryController extends Controller
foreach ($unpaidAmount as $currencyId => $amount) { foreach ($unpaidAmount as $currencyId => $amount) {
$amount = bcmul($amount, '-1'); $amount = bcmul($amount, '-1');
$currency = $this->currencyRepos->findNull((int)$currencyId); $currency = $this->currencyRepos->findNull((int) $currencyId);
if (null === $currency) { if (null === $currency) {
continue; continue;
} }
@ -340,8 +317,8 @@ class SummaryController extends Controller
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* *
* @return array
* @throws Exception * @throws Exception
* @return array
*/ */
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
{ {
@ -360,7 +337,7 @@ class SummaryController extends Controller
$days = $today->diffInDays($end) + 1; $days = $today->diffInDays($end) + 1;
$perDay = '0'; $perDay = '0';
if (0 !== $days && bccomp($leftToSpend, '0') > -1) { if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
$perDay = bcdiv($leftToSpend, (string)$days); $perDay = bcdiv($leftToSpend, (string) $days);
} }
$return[] = [ $return[] = [
@ -373,14 +350,18 @@ class SummaryController extends Controller
'currency_decimal_places' => $row['currency_decimal_places'], 'currency_decimal_places' => $row['currency_decimal_places'],
'value_parsed' => app('amount')->formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $leftToSpend, false), 'value_parsed' => app('amount')->formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $leftToSpend, false),
'local_icon' => 'money', 'local_icon' => 'money',
'sub_title' => (string)trans( 'sub_title' => (string) trans(
'firefly.box_spend_per_day', ['amount' => app('amount')->formatFlat( 'firefly.box_spend_per_day',
$row['currency_symbol'], $row['currency_decimal_places'], $perDay, false ['amount' => app('amount')->formatFlat(
)] $row['currency_symbol'],
$row['currency_decimal_places'],
$perDay,
false
)]
), ),
]; ];
} }
return $return; return $return;
} }
@ -443,5 +424,4 @@ class SummaryController extends Controller
return $return; return $return;
} }
} }

View File

@ -25,8 +25,8 @@ namespace FireflyIII\Api\V1\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Api\V1\Requests\DateRequest; use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Api\V1\Requests\TagUpdateRequest;
use FireflyIII\Api\V1\Requests\TagStoreRequest; use FireflyIII\Api\V1\Requests\TagStoreRequest;
use FireflyIII\Api\V1\Requests\TagUpdateRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface;
@ -117,7 +117,7 @@ class TagController extends Controller
{ {
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->repository->get(); $collection = $this->repository->get();
@ -190,7 +190,7 @@ class TagController extends Controller
*/ */
public function transactions(Request $request, Tag $tag): JsonResponse public function transactions(Request $request, Tag $tag): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);
@ -236,7 +236,7 @@ class TagController extends Controller
* Update a rule. * Update a rule.
* *
* @param TagUpdateRequest $request * @param TagUpdateRequest $request
* @param Tag $tag * @param Tag $tag
* *
* @return JsonResponse * @return JsonResponse
*/ */
@ -288,8 +288,8 @@ class TagController extends Controller
]; ];
/** @var Tag $tag */ /** @var Tag $tag */
foreach ($tags as $tag) { foreach ($tags as $tag) {
$earned = (float)$this->repository->earnedInPeriod($tag, $start, $end); $earned = (float) $this->repository->earnedInPeriod($tag, $start, $end);
$spent = (float)$this->repository->spentInPeriod($tag, $start, $end); $spent = (float) $this->repository->spentInPeriod($tag, $start, $end);
$size = ($spent * -1) + $earned; $size = ($spent * -1) + $earned;
$min = $min ?? $size; $min = $min ?? $size;
if ($size > 0) { if ($size > 0) {

View File

@ -110,7 +110,6 @@ class TransactionController extends Controller
$resource = new FractalCollection($attachments, $transformer, 'attachments'); $resource = new FractalCollection($attachments, $transformer, 'attachments');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
} }
/** /**
@ -153,7 +152,7 @@ class TransactionController extends Controller
*/ */
public function index(Request $request): JsonResponse public function index(Request $request): JsonResponse
{ {
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$type = $request->get('type') ?? 'default'; $type = $request->get('type') ?? 'default';
$this->parameters->set('type', $type); $this->parameters->set('type', $type);
@ -215,7 +214,6 @@ class TransactionController extends Controller
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events'); $resource = new FractalCollection($events, $transformer, 'piggy_bank_events');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
} }
/** /**
@ -296,7 +294,7 @@ class TransactionController extends Controller
]; ];
return response()->json($response, 422); return response()->json($response, 422);
} catch(FireflyException $e) { } catch (FireflyException $e) {
Log::warning('Caught an exception. Return error message.'); Log::warning('Caught an exception. Return error message.');
Log::error($e->getMessage()); Log::error($e->getMessage());
// return bad validation message. // return bad validation message.
@ -304,7 +302,7 @@ class TransactionController extends Controller
$response = [ $response = [
'message' => 'The given data was invalid.', 'message' => 'The given data was invalid.',
'errors' => [ 'errors' => [
'transactions.0.description' => [sprintf('Internal exception: %s',$e->getMessage())], 'transactions.0.description' => [sprintf('Internal exception: %s', $e->getMessage())],
], ],
]; ];
@ -379,6 +377,5 @@ class TransactionController extends Controller
$resource = new Item($selectedGroup, $transformer, 'transactions'); $resource = new Item($selectedGroup, $transformer, 'transactions');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
} }
} }

View File

@ -105,7 +105,7 @@ class TransactionLinkController extends Controller
$name = $request->get('name'); $name = $request->get('name');
// types to get, page size: // types to get, page size:
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$linkType = $this->repository->findByName($name); $linkType = $this->repository->findByName($name);
// get list of transaction links. Count it and split it. // get list of transaction links. Count it and split it.
@ -155,8 +155,8 @@ class TransactionLinkController extends Controller
* *
* @param TransactionLinkRequest $request * @param TransactionLinkRequest $request
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function store(TransactionLinkRequest $request): JsonResponse public function store(TransactionLinkRequest $request): JsonResponse
{ {
@ -186,8 +186,8 @@ class TransactionLinkController extends Controller
* @param TransactionLinkRequest $request * @param TransactionLinkRequest $request
* @param TransactionJournalLink $journalLink * @param TransactionJournalLink $journalLink
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @return JsonResponse
*/ */
public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse
{ {

View File

@ -70,9 +70,9 @@ class UserController extends Controller
* *
* @param User $user * @param User $user
* *
* @return JsonResponse
* @throws FireflyException * @throws FireflyException
* @codeCoverageIgnore * @codeCoverageIgnore
* @return JsonResponse
*/ */
public function delete(User $user): JsonResponse public function delete(User $user): JsonResponse
{ {
@ -95,7 +95,7 @@ class UserController extends Controller
public function index(): JsonResponse public function index(): JsonResponse
{ {
// user preferences // user preferences
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = $this->getManager(); $manager = $this->getManager();
// build collection // build collection

View File

@ -126,7 +126,7 @@ class AccountStoreRequest extends Request
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly', 'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',
'notes' => 'min:0|max:65536', 'notes' => 'min:0|max:65536',
]; ];
$rules = Location::requestRules($rules); $rules = Location::requestRules($rules);
return $rules; return $rules;
} }

View File

@ -105,7 +105,7 @@ class AccountUpdateRequest extends Request
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); $types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$rules = [ $rules = [
'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id), 'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id),
'type' => sprintf('in:%s', $types), 'type' => sprintf('in:%s', $types),
'iban' => 'iban|nullable', 'iban' => 'iban|nullable',

View File

@ -64,15 +64,13 @@ class AvailableBudgetRequest extends Request
*/ */
public function rules(): array public function rules(): array
{ {
$rules = [ return [
'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'amount' => 'required|numeric|more:0', 'amount' => 'required|numeric|more:0',
'start' => 'required|date|before:end', 'start' => 'required|date|before:end',
'end' => 'required|date|after:start', 'end' => 'required|date|after:start',
]; ];
return $rules;
} }

View File

@ -60,7 +60,7 @@ class BillRequest extends Request
$active = $this->boolean('active'); $active = $this->boolean('active');
} }
$data = [ return [
'name' => $this->string('name'), 'name' => $this->string('name'),
'amount_min' => $this->string('amount_min'), 'amount_min' => $this->string('amount_min'),
'amount_max' => $this->string('amount_max'), 'amount_max' => $this->string('amount_max'),
@ -72,8 +72,6 @@ class BillRequest extends Request
'active' => $active, 'active' => $active,
'notes' => $this->nlString('notes'), 'notes' => $this->nlString('notes'),
]; ];
return $data;
} }
/** /**
@ -121,10 +119,10 @@ class BillRequest extends Request
$validator->after( $validator->after(
static function (Validator $validator) { static function (Validator $validator) {
$data = $validator->getData(); $data = $validator->getData();
$min = (float)($data['amount_min'] ?? 0); $min = (float) ($data['amount_min'] ?? 0);
$max = (float)($data['amount_max'] ?? 0); $max = (float) ($data['amount_max'] ?? 0);
if ($min > $max) { if ($min > $max) {
$validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max')); $validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max'));
} }
} }
); );

View File

@ -1,91 +0,0 @@
<?php
/**
* BudgetRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Budget;
use FireflyIII\Rules\IsBoolean;
/**
* Class BudgetRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/
class BudgetRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$active = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
return [
'name' => $this->string('name'),
'active' => $active,
'order' => 0,
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$rules = [
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
'active' => [new IsBoolean],
];
switch ($this->method()) {
default:
break;
case 'PUT':
case 'PATCH':
/** @var Budget $budget */
$budget = $this->route()->parameter('budget');
$rules['name'] = sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id);
break;
}
return $rules;
}
}

View File

@ -0,0 +1,106 @@
<?php
/**
* BudgetStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use Illuminate\Validation\Validator;
/**
* Class BudgetStoreRequest
*
* @codeCoverageIgnore
*/
class BudgetStoreRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$active = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
return [
'name' => $this->string('name'),
'active' => $active,
'order' => 0,
'auto_budget_type' => $this->string('auto_budget_type'),
'transaction_currency_id' => $this->integer('auto_budget_currency_id'),
'transaction_currency_code' => $this->string('auto_budget_currency_code'),
'auto_budget_amount' => $this->string('auto_budget_amount'),
'auto_budget_period' => $this->string('auto_budget_period'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
return [
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
'active' => [new IsBoolean],
'auto_budget_type' => 'in:reset,rollover,none',
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
'auto_budget_amount' => 'min:0|max:1000000000',
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
];
}
/**
* Configure the validator instance with special rules for after the basic validation rules.
*
* @param Validator $validator
*
* @return void
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator) {
// validate all account info
$this->validateAutoBudgetAmount($validator);
}
);
}
}

View File

@ -0,0 +1,107 @@
<?php
/**
* BudgetUpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use Illuminate\Validation\Validator;
/**
* Class BudgetUpdateRequest
*
* @codeCoverageIgnore
*/
class BudgetUpdateRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
$active = true;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
return [
'name' => $this->string('name'),
'active' => $active,
'order' => 0,
'auto_budget_type' => $this->string('auto_budget_type'),
'transaction_currency_id' => $this->integer('auto_budget_currency_id'),
'transaction_currency_code' => $this->string('auto_budget_currency_code'),
'auto_budget_amount' => $this->string('auto_budget_amount'),
'auto_budget_period' => $this->string('auto_budget_period'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$budget = $this->route()->parameter('budget');
return [
'name' => sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id),
'active' => [new IsBoolean],
'auto_budget_type' => 'in:reset,rollover,none',
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
'auto_budget_currency_code' => 'exists:transaction_currencies,code',
'auto_budget_amount' => 'min:0|max:1000000000',
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
];
}
/**
* Configure the validator instance with special rules for after the basic validation rules.
*
* @param Validator $validator
*
* @return void
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator) {
// validate all account info
$this->validateAutoBudgetAmount($validator);
}
);
}
}

View File

@ -63,7 +63,8 @@ class RecurrenceStoreRequest extends Request
if (null !== $this->get('apply_rules')) { if (null !== $this->get('apply_rules')) {
$applyRules = $this->boolean('apply_rules'); $applyRules = $this->boolean('apply_rules');
} }
$return = [
return [
'recurrence' => [ 'recurrence' => [
'type' => $this->string('type'), 'type' => $this->string('type'),
'title' => $this->string('title'), 'title' => $this->string('title'),
@ -77,8 +78,6 @@ class RecurrenceStoreRequest extends Request
'transactions' => $this->getTransactionData(), 'transactions' => $this->getTransactionData(),
'repetitions' => $this->getRepetitionData(), 'repetitions' => $this->getRepetitionData(),
]; ];
return $return;
} }
/** /**
@ -168,8 +167,8 @@ class RecurrenceStoreRequest extends Request
$return[] = [ $return[] = [
'type' => $repetition['type'], 'type' => $repetition['type'],
'moment' => $repetition['moment'], 'moment' => $repetition['moment'],
'skip' => (int)$repetition['skip'], 'skip' => (int) $repetition['skip'],
'weekend' => (int)$repetition['weekend'], 'weekend' => (int) $repetition['weekend'],
]; ];
} }
@ -195,25 +194,25 @@ class RecurrenceStoreRequest extends Request
foreach ($transactions as $transaction) { foreach ($transactions as $transaction) {
$return[] = [ $return[] = [
'amount' => $transaction['amount'], 'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, 'currency_id' => isset($transaction['currency_id']) ? (int) $transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null, 'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null, 'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, 'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int) $transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, 'source_id' => isset($transaction['source_id']) ? (int) $transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, 'source_name' => isset($transaction['source_name']) ? (string) $transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, 'destination_id' => isset($transaction['destination_id']) ? (int) $transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, 'destination_name' => isset($transaction['destination_name']) ? (string) $transaction['destination_name'] : null,
'description' => $transaction['description'], 'description' => $transaction['description'],
'type' => $this->string('type'), 'type' => $this->string('type'),
// new and updated fields: // new and updated fields:
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int)$transaction['piggy_bank_id'] : null, 'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int) $transaction['piggy_bank_id'] : null,
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null, 'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
'tags' => $transaction['tags'] ?? [], 'tags' => $transaction['tags'] ?? [],
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, 'budget_id' => isset($transaction['budget_id']) ? (int) $transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null, 'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, 'category_id' => isset($transaction['category_id']) ? (int) $transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null, 'category_name' => $transaction['category_name'] ?? null,
]; ];
} }

View File

@ -63,7 +63,8 @@ class RecurrenceUpdateRequest extends Request
if (null !== $this->get('apply_rules')) { if (null !== $this->get('apply_rules')) {
$applyRules = $this->boolean('apply_rules'); $applyRules = $this->boolean('apply_rules');
} }
$return = [
return [
'recurrence' => [ 'recurrence' => [
'type' => $this->nullableString('type'), 'type' => $this->nullableString('type'),
'title' => $this->nullableString('title'), 'title' => $this->nullableString('title'),
@ -78,8 +79,6 @@ class RecurrenceUpdateRequest extends Request
'transactions' => $this->getTransactionData(), 'transactions' => $this->getTransactionData(),
'repetitions' => $this->getRepetitionData(), 'repetitions' => $this->getRepetitionData(),
]; ];
return $return;
} }
/** /**
@ -170,14 +169,46 @@ class RecurrenceUpdateRequest extends Request
$return[] = [ $return[] = [
'type' => $repetition['type'], 'type' => $repetition['type'],
'moment' => $repetition['moment'], 'moment' => $repetition['moment'],
'skip' => (int)$repetition['skip'], 'skip' => (int) $repetition['skip'],
'weekend' => (int)$repetition['weekend'], 'weekend' => (int) $repetition['weekend'],
]; ];
} }
return $return; return $return;
} }
/**
* @param array $transaction
*
* @return array
*/
private function getSingleData(array $transaction): array
{
return [
'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int) $transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int) $transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int) $transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string) $transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int) $transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string) $transaction['destination_name'] : null,
'description' => $transaction['description'],
'type' => $this->string('type'),
// new and updated fields:
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int) $transaction['piggy_bank_id'] : null,
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
'tags' => $transaction['tags'] ?? [],
'budget_id' => isset($transaction['budget_id']) ? (int) $transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int) $transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null,
];
}
/** /**
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code * 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. * standards but it just has a lot of ??-statements because of the fields that may or may not exist.
@ -195,29 +226,7 @@ class RecurrenceUpdateRequest extends Request
} }
/** @var array $transaction */ /** @var array $transaction */
foreach ($transactions as $transaction) { foreach ($transactions as $transaction) {
$return[] = [ $return[] = $this->getSingleData($transaction);
'amount' => $transaction['amount'],
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
'currency_code' => $transaction['currency_code'] ?? null,
'foreign_amount' => $transaction['foreign_amount'] ?? null,
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
'description' => $transaction['description'],
'type' => $this->string('type'),
// new and updated fields:
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int)$transaction['piggy_bank_id'] : null,
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
'tags' => $transaction['tags'] ?? [],
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
'budget_name' => $transaction['budget_name'] ?? null,
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
'category_name' => $transaction['category_name'] ?? null,
];
} }
return $return; return $return;

View File

@ -34,4 +34,5 @@ use FireflyIII\Http\Requests\Request as FireflyIIIRequest;
*/ */
class Request extends FireflyIIIRequest class Request extends FireflyIIIRequest
{ {
} }

View File

@ -54,7 +54,7 @@ class RuleGroupTestRequest extends Request
*/ */
public function getTestParameters(): array public function getTestParameters(): array
{ {
$return = [ return [
'page' => $this->getPage(), 'page' => $this->getPage(),
'start_date' => $this->getDate('start_date'), 'start_date' => $this->getDate('start_date'),
'end_date' => $this->getDate('end_date'), 'end_date' => $this->getDate('end_date'),
@ -62,9 +62,6 @@ class RuleGroupTestRequest extends Request
'trigger_limit' => $this->getTriggerLimit(), 'trigger_limit' => $this->getTriggerLimit(),
'accounts' => $this->getAccounts(), 'accounts' => $this->getAccounts(),
]; ];
return $return;
} }
/** /**
@ -80,7 +77,7 @@ class RuleGroupTestRequest extends Request
*/ */
private function getAccounts(): Collection private function getAccounts(): Collection
{ {
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts')); $accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection; $accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */ /** @var AccountRepositoryInterface $accountRepository */
@ -88,7 +85,7 @@ class RuleGroupTestRequest extends Request
foreach ($accountList as $accountId) { foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId); $account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) { if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */ /** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
@ -117,7 +114,7 @@ class RuleGroupTestRequest extends Request
*/ */
private function getPage(): int private function getPage(): int
{ {
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page'); return 0 === (int) $this->query('page') ? 1 : (int) $this->query('page');
} }
@ -126,7 +123,7 @@ class RuleGroupTestRequest extends Request
*/ */
private function getSearchLimit(): int private function getSearchLimit(): int
{ {
return 0 === (int)$this->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$this->query('search_limit'); return 0 === (int) $this->query('search_limit') ? (int) config('firefly.test-triggers.limit') : (int) $this->query('search_limit');
} }
/** /**
@ -134,7 +131,7 @@ class RuleGroupTestRequest extends Request
*/ */
private function getTriggerLimit(): int private function getTriggerLimit(): int
{ {
return 0 === (int)$this->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$this->query('triggered_limit'); return 0 === (int) $this->query('triggered_limit') ? (int) config('firefly.test-triggers.range') : (int) $this->query('triggered_limit');
} }
/** /**

View File

@ -54,14 +54,11 @@ class RuleGroupTriggerRequest extends Request
*/ */
public function getTriggerParameters(): array public function getTriggerParameters(): array
{ {
$return = [ return [
'start_date' => $this->getDate('start_date'), 'start_date' => $this->getDate('start_date'),
'end_date' => $this->getDate('end_date'), 'end_date' => $this->getDate('end_date'),
'accounts' => $this->getAccounts(), 'accounts' => $this->getAccounts(),
]; ];
return $return;
} }
/** /**
@ -80,7 +77,7 @@ class RuleGroupTriggerRequest extends Request
*/ */
private function getAccounts(): Collection private function getAccounts(): Collection
{ {
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts')); $accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection; $accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */ /** @var AccountRepositoryInterface $accountRepository */
@ -88,7 +85,7 @@ class RuleGroupTriggerRequest extends Request
foreach ($accountList as $accountId) { foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId); $account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) { if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */ /** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));

View File

@ -65,7 +65,7 @@ class RuleStoreRequest extends Request
$stopProcessing = $this->boolean('stop_processing'); $stopProcessing = $this->boolean('stop_processing');
} }
$data = [ return [
'title' => $this->string('title'), 'title' => $this->string('title'),
'description' => $this->string('description'), 'description' => $this->string('description'),
'rule_group_id' => $this->integer('rule_group_id'), 'rule_group_id' => $this->integer('rule_group_id'),
@ -77,8 +77,6 @@ class RuleStoreRequest extends Request
'triggers' => $this->getRuleTriggers(), 'triggers' => $this->getRuleTriggers(),
'actions' => $this->getRuleActions(), 'actions' => $this->getRuleActions(),
]; ];
return $data;
} }
/** /**
@ -94,7 +92,8 @@ class RuleStoreRequest extends Request
// some triggers and actions require text: // some triggers and actions require text:
$contextTriggers = implode(',', config('firefly.context-rule-triggers')); $contextTriggers = implode(',', config('firefly.context-rule-triggers'));
$contextActions = implode(',', config('firefly.context-rule-actions')); $contextActions = implode(',', config('firefly.context-rule-actions'));
$rules = [
return [
'title' => 'required|between:1,100|uniqueObjectForUser:rules,title', 'title' => 'required|between:1,100|uniqueObjectForUser:rules,title',
'description' => 'between:1,5000|nullable', 'description' => 'between:1,5000|nullable',
'rule_group_id' => 'required|belongsToUser:rule_groups|required_without:rule_group_title', 'rule_group_id' => 'required|belongsToUser:rule_groups|required_without:rule_group_title',
@ -112,8 +111,6 @@ class RuleStoreRequest extends Request
'stop_processing' => [new IsBoolean], 'stop_processing' => [new IsBoolean],
'active' => [new IsBoolean], 'active' => [new IsBoolean],
]; ];
return $rules;
} }
/** /**
@ -144,7 +141,7 @@ class RuleStoreRequest extends Request
$actions = $data['actions'] ?? []; $actions = $data['actions'] ?? [];
// need at least one trigger // need at least one trigger
if (0 === count($actions)) { if (0 === count($actions)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_action')); $validator->errors()->add('title', (string) trans('validation.at_least_one_action'));
} }
} }
@ -159,7 +156,7 @@ class RuleStoreRequest extends Request
$triggers = $data['triggers'] ?? []; $triggers = $data['triggers'] ?? [];
// need at least one trigger // need at least one trigger
if (0 === count($triggers)) { if (0 === count($triggers)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger')); $validator->errors()->add('title', (string) trans('validation.at_least_one_trigger'));
} }
} }
@ -175,8 +172,8 @@ class RuleStoreRequest extends Request
$return[] = [ $return[] = [
'type' => $action['type'], 'type' => $action['type'],
'value' => $action['value'], 'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')), 'active' => $this->convertBoolean((string) ($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')), 'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')),
]; ];
} }
} }
@ -196,8 +193,8 @@ class RuleStoreRequest extends Request
$return[] = [ $return[] = [
'type' => $trigger['type'], 'type' => $trigger['type'],
'value' => $trigger['value'], 'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')), 'active' => $this->convertBoolean((string) ($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')), 'stop_processing' => $this->convertBoolean((string) ($trigger['stop_processing'] ?? 'false')),
]; ];
} }
} }

View File

@ -54,7 +54,7 @@ class RuleTestRequest extends Request
*/ */
public function getTestParameters(): array public function getTestParameters(): array
{ {
$return = [ return [
'page' => $this->getPage(), 'page' => $this->getPage(),
'start_date' => $this->getDate('start_date'), 'start_date' => $this->getDate('start_date'),
'end_date' => $this->getDate('end_date'), 'end_date' => $this->getDate('end_date'),
@ -62,9 +62,6 @@ class RuleTestRequest extends Request
'trigger_limit' => $this->getTriggerLimit(), 'trigger_limit' => $this->getTriggerLimit(),
'accounts' => $this->getAccounts(), 'accounts' => $this->getAccounts(),
]; ];
return $return;
} }
/** /**
@ -80,7 +77,7 @@ class RuleTestRequest extends Request
*/ */
private function getAccounts(): Collection private function getAccounts(): Collection
{ {
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts')); $accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection; $accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */ /** @var AccountRepositoryInterface $accountRepository */
@ -88,7 +85,7 @@ class RuleTestRequest extends Request
foreach ($accountList as $accountId) { foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId); $account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) { if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */ /** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
@ -117,7 +114,7 @@ class RuleTestRequest extends Request
*/ */
private function getPage(): int private function getPage(): int
{ {
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page'); return 0 === (int) $this->query('page') ? 1 : (int) $this->query('page');
} }
@ -126,7 +123,7 @@ class RuleTestRequest extends Request
*/ */
private function getSearchLimit(): int private function getSearchLimit(): int
{ {
return 0 === (int)$this->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$this->query('search_limit'); return 0 === (int) $this->query('search_limit') ? (int) config('firefly.test-triggers.limit') : (int) $this->query('search_limit');
} }
/** /**
@ -134,7 +131,7 @@ class RuleTestRequest extends Request
*/ */
private function getTriggerLimit(): int private function getTriggerLimit(): int
{ {
return 0 === (int)$this->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$this->query('triggered_limit'); return 0 === (int) $this->query('triggered_limit') ? (int) config('firefly.test-triggers.range') : (int) $this->query('triggered_limit');
} }
/** /**

View File

@ -53,14 +53,11 @@ class RuleTriggerRequest extends Request
*/ */
public function getTriggerParameters(): array public function getTriggerParameters(): array
{ {
$return = [ return [
'start_date' => $this->getDate('start_date'), 'start_date' => $this->getDate('start_date'),
'end_date' => $this->getDate('end_date'), 'end_date' => $this->getDate('end_date'),
'accounts' => $this->getAccounts(), 'accounts' => $this->getAccounts(),
]; ];
return $return;
} }
/** /**
@ -79,7 +76,7 @@ class RuleTriggerRequest extends Request
*/ */
private function getAccounts(): Collection private function getAccounts(): Collection
{ {
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts')); $accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts'));
$accounts = new Collection; $accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */ /** @var AccountRepositoryInterface $accountRepository */
@ -87,7 +84,7 @@ class RuleTriggerRequest extends Request
foreach ($accountList as $accountId) { foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int)$accountId); $account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) { if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */ /** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));

View File

@ -65,7 +65,7 @@ class RuleUpdateRequest extends Request
$stopProcessing = $this->boolean('stop_processing'); $stopProcessing = $this->boolean('stop_processing');
} }
$data = [ return [
'title' => $this->nullableString('title'), 'title' => $this->nullableString('title'),
'description' => $this->nullableString('description'), 'description' => $this->nullableString('description'),
'rule_group_id' => $this->nullableInteger('rule_group_id'), 'rule_group_id' => $this->nullableInteger('rule_group_id'),
@ -77,8 +77,6 @@ class RuleUpdateRequest extends Request
'triggers' => $this->getRuleTriggers(), 'triggers' => $this->getRuleTriggers(),
'actions' => $this->getRuleActions(), 'actions' => $this->getRuleActions(),
]; ];
return $data;
} }
/** /**
@ -95,7 +93,8 @@ class RuleUpdateRequest extends Request
// some triggers and actions require text: // some triggers and actions require text:
$contextTriggers = implode(',', config('firefly.context-rule-triggers')); $contextTriggers = implode(',', config('firefly.context-rule-triggers'));
$contextActions = implode(',', config('firefly.context-rule-actions')); $contextActions = implode(',', config('firefly.context-rule-actions'));
$rules = [
return [
'title' => sprintf('between:1,100|uniqueObjectForUser:rules,title,%d', $rule->id), 'title' => sprintf('between:1,100|uniqueObjectForUser:rules,title,%d', $rule->id),
'description' => 'between:1,5000|nullable', 'description' => 'between:1,5000|nullable',
'rule_group_id' => 'belongsToUser:rule_groups', 'rule_group_id' => 'belongsToUser:rule_groups',
@ -113,8 +112,6 @@ class RuleUpdateRequest extends Request
'stop_processing' => [new IsBoolean], 'stop_processing' => [new IsBoolean],
'active' => [new IsBoolean], 'active' => [new IsBoolean],
]; ];
return $rules;
} }
/** /**
@ -145,7 +142,7 @@ class RuleUpdateRequest extends Request
$actions = $data['actions'] ?? null; $actions = $data['actions'] ?? null;
// need at least one action // need at least one action
if (is_array($actions) && 0 === count($actions)) { if (is_array($actions) && 0 === count($actions)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_action')); $validator->errors()->add('title', (string) trans('validation.at_least_one_action'));
} }
} }
@ -160,7 +157,7 @@ class RuleUpdateRequest extends Request
$triggers = $data['triggers'] ?? null; $triggers = $data['triggers'] ?? null;
// need at least one trigger // need at least one trigger
if (is_array($triggers) && 0 === count($triggers)) { if (is_array($triggers) && 0 === count($triggers)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger')); $validator->errors()->add('title', (string) trans('validation.at_least_one_trigger'));
} }
} }
@ -179,8 +176,8 @@ class RuleUpdateRequest extends Request
$return[] = [ $return[] = [
'type' => $action['type'], 'type' => $action['type'],
'value' => $action['value'], 'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')), 'active' => $this->convertBoolean((string) ($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')), 'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')),
]; ];
} }
} }
@ -203,8 +200,8 @@ class RuleUpdateRequest extends Request
$return[] = [ $return[] = [
'type' => $trigger['type'], 'type' => $trigger['type'],
'value' => $trigger['value'], 'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')), 'active' => $this->convertBoolean((string) ($trigger['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')), 'stop_processing' => $this->convertBoolean((string) ($trigger['stop_processing'] ?? 'false')),
]; ];
} }
} }

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
/** /**
* TransferRequest.php * TransferRequest.php
* Copyright (c) 2019 james@firefly-iii.org * Copyright (c) 2019 james@firefly-iii.org
@ -21,7 +22,6 @@
namespace FireflyIII\Api\V1\Requests\Search; namespace FireflyIII\Api\V1\Requests\Search;
use FireflyIII\Api\V1\Requests\Request; use FireflyIII\Api\V1\Requests\Request;
use FireflyIII\Rules\IsTransferAccount; use FireflyIII\Rules\IsTransferAccount;
@ -54,5 +54,4 @@ class TransferRequest extends Request
'date' => 'required|date', 'date' => 'required|date',
]; ];
} }
}
}

View File

@ -110,8 +110,8 @@ class TransactionLinkRequest extends Request
$journalRepos->setUser($user); $journalRepos->setUser($user);
$data = $validator->getData(); $data = $validator->getData();
$inwardId = (int)($data['inward_id'] ?? 0); $inwardId = (int) ($data['inward_id'] ?? 0);
$outwardId = (int)($data['outward_id'] ?? 0); $outwardId = (int) ($data['outward_id'] ?? 0);
$inward = $journalRepos->findNull($inwardId); $inward = $journalRepos->findNull($inwardId);
$outward = $journalRepos->findNull($outwardId); $outward = $journalRepos->findNull($outwardId);

View File

@ -60,14 +60,13 @@ class TransactionStoreRequest extends Request
public function getAll(): array public function getAll(): array
{ {
Log::debug('get all data in TransactionStoreRequest'); Log::debug('get all data in TransactionStoreRequest');
$data = [
return [
'group_title' => $this->string('group_title'), 'group_title' => $this->string('group_title'),
'error_if_duplicate_hash' => $this->boolean('error_if_duplicate_hash'), 'error_if_duplicate_hash' => $this->boolean('error_if_duplicate_hash'),
'apply_rules' => $this->boolean('apply_rules', true), 'apply_rules' => $this->boolean('apply_rules', true),
'transactions' => $this->getTransactionData(), 'transactions' => $this->getTransactionData(),
]; ];
return $data;
} }
/** /**
@ -78,7 +77,8 @@ class TransactionStoreRequest extends Request
public function rules(): array public function rules(): array
{ {
Log::debug('Collect rules of TransactionStoreRequest'); Log::debug('Collect rules of TransactionStoreRequest');
$rules = [
return [
// basic fields for group: // basic fields for group:
'group_title' => 'between:1,1000|nullable', 'group_title' => 'between:1,1000|nullable',
'error_if_duplicate_hash' => [new IsBoolean], 'error_if_duplicate_hash' => [new IsBoolean],
@ -156,8 +156,6 @@ class TransactionStoreRequest extends Request
'transactions.*.invoice_date' => 'date|nullable', 'transactions.*.invoice_date' => 'date|nullable',
]; ];
return $rules;
} }
@ -214,63 +212,63 @@ class TransactionStoreRequest extends Request
$return[] = [ $return[] = [
'type' => $this->stringFromValue($object['type']), 'type' => $this->stringFromValue($object['type']),
'date' => $this->dateFromValue($object['date']), 'date' => $this->dateFromValue($object['date']),
'order' => $this->integerFromValue((string)$object['order']), 'order' => $this->integerFromValue((string) $object['order']),
'currency_id' => $this->integerFromValue((string)$object['currency_id']), 'currency_id' => $this->integerFromValue((string) $object['currency_id']),
'currency_code' => $this->stringFromValue($object['currency_code']), 'currency_code' => $this->stringFromValue($object['currency_code']),
// foreign currency info: // foreign currency info:
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']), 'foreign_currency_id' => $this->integerFromValue((string) $object['foreign_currency_id']),
'foreign_currency_code' => $this->stringFromValue($object['foreign_currency_code']), 'foreign_currency_code' => $this->stringFromValue($object['foreign_currency_code']),
// amount and foreign amount. Cannot be 0. // amount and foreign amount. Cannot be 0.
'amount' => $this->stringFromValue((string)$object['amount']), 'amount' => $this->stringFromValue((string) $object['amount']),
'foreign_amount' => $this->stringFromValue((string)$object['foreign_amount']), 'foreign_amount' => $this->stringFromValue((string) $object['foreign_amount']),
// description. // description.
'description' => $this->stringFromValue($object['description']), 'description' => $this->stringFromValue($object['description']),
// source of transaction. If everything is null, assume cash account. // source of transaction. If everything is null, assume cash account.
'source_id' => $this->integerFromValue((string)$object['source_id']), 'source_id' => $this->integerFromValue((string) $object['source_id']),
'source_name' => $this->stringFromValue($object['source_name']), 'source_name' => $this->stringFromValue($object['source_name']),
'source_iban' => $this->stringFromValue($object['source_iban']), 'source_iban' => $this->stringFromValue($object['source_iban']),
'source_number' => $this->stringFromValue($object['source_number']), 'source_number' => $this->stringFromValue($object['source_number']),
'source_bic' => $this->stringFromValue($object['source_bic']), 'source_bic' => $this->stringFromValue($object['source_bic']),
// destination of transaction. If everything is null, assume cash account. // destination of transaction. If everything is null, assume cash account.
'destination_id' => $this->integerFromValue((string)$object['destination_id']), 'destination_id' => $this->integerFromValue((string) $object['destination_id']),
'destination_name' => $this->stringFromValue($object['destination_name']), 'destination_name' => $this->stringFromValue($object['destination_name']),
'destination_iban' => $this->stringFromValue($object['destination_iban']), 'destination_iban' => $this->stringFromValue($object['destination_iban']),
'destination_number' => $this->stringFromValue($object['destination_number']), 'destination_number' => $this->stringFromValue($object['destination_number']),
'destination_bic' => $this->stringFromValue($object['destination_bic']), 'destination_bic' => $this->stringFromValue($object['destination_bic']),
// budget info // budget info
'budget_id' => $this->integerFromValue((string)$object['budget_id']), 'budget_id' => $this->integerFromValue((string) $object['budget_id']),
'budget_name' => $this->stringFromValue($object['budget_name']), 'budget_name' => $this->stringFromValue($object['budget_name']),
// category info // category info
'category_id' => $this->integerFromValue((string)$object['category_id']), 'category_id' => $this->integerFromValue((string) $object['category_id']),
'category_name' => $this->stringFromValue($object['category_name']), 'category_name' => $this->stringFromValue($object['category_name']),
// journal bill reference. Optional. Will only work for withdrawals // journal bill reference. Optional. Will only work for withdrawals
'bill_id' => $this->integerFromValue((string)$object['bill_id']), 'bill_id' => $this->integerFromValue((string) $object['bill_id']),
'bill_name' => $this->stringFromValue($object['bill_name']), 'bill_name' => $this->stringFromValue($object['bill_name']),
// piggy bank reference. Optional. Will only work for transfers // piggy bank reference. Optional. Will only work for transfers
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']), 'piggy_bank_id' => $this->integerFromValue((string) $object['piggy_bank_id']),
'piggy_bank_name' => $this->stringFromValue($object['piggy_bank_name']), 'piggy_bank_name' => $this->stringFromValue($object['piggy_bank_name']),
// some other interesting properties // some other interesting properties
'reconciled' => $this->convertBoolean((string)$object['reconciled']), 'reconciled' => $this->convertBoolean((string) $object['reconciled']),
'notes' => $this->nlStringFromValue($object['notes']), 'notes' => $this->nlStringFromValue($object['notes']),
'tags' => $this->arrayFromValue($object['tags']), 'tags' => $this->arrayFromValue($object['tags']),
// all custom fields: // all custom fields:
'internal_reference' => $this->stringFromValue((string)$object['internal_reference']), 'internal_reference' => $this->stringFromValue((string) $object['internal_reference']),
'external_id' => $this->stringFromValue((string)$object['external_id']), 'external_id' => $this->stringFromValue((string) $object['external_id']),
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')), 'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
'recurrence_id' => $this->integerFromValue($object['recurrence_id']), 'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
'bunq_payment_id' => $this->stringFromValue((string)$object['bunq_payment_id']), 'bunq_payment_id' => $this->stringFromValue((string) $object['bunq_payment_id']),
'sepa_cc' => $this->stringFromValue($object['sepa_cc']), 'sepa_cc' => $this->stringFromValue($object['sepa_cc']),
'sepa_ct_op' => $this->stringFromValue($object['sepa_ct_op']), 'sepa_ct_op' => $this->stringFromValue($object['sepa_ct_op']),

View File

@ -154,7 +154,7 @@ class TransactionUpdateRequest extends Request
*/ */
public function rules(): array public function rules(): array
{ {
$rules = [ return [
// basic fields for group: // basic fields for group:
'group_title' => 'between:1,1000', 'group_title' => 'between:1,1000',
'apply_rules' => [new IsBoolean], 'apply_rules' => [new IsBoolean],
@ -222,8 +222,6 @@ class TransactionUpdateRequest extends Request
'transactions.*.payment_date' => 'date|nullable', 'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable', 'transactions.*.invoice_date' => 'date|nullable',
]; ];
return $rules;
} }
/** /**
@ -279,6 +277,111 @@ class TransactionUpdateRequest extends Request
); );
} }
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getArrayData(array $current, array $transaction): array
{
foreach ($this->arrayFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getBooleanData(array $current, array $transaction): array
{
foreach ($this->booleanFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getDateData(array $current, array $transaction): array
{
foreach ($this->dateFields as $fieldName) {
Log::debug(sprintf('Now at date field %s', $fieldName));
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
Log::debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
}
}
return $current;
}
/**
* For each field, add it to the array if a reference is present in the request:
*
* @param array $current
*
* @return array
*/
private function getIntegerData(array $current, array $transaction): array
{
foreach ($this->integerFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getNlStringData(array $current, array $transaction): array
{
foreach ($this->textareaFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->nlStringFromValue((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array $current
* @param array $transaction
*
* @return array
*/
private function getStringData(array $current, array $transaction): array
{
foreach ($this->stringFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->stringFromValue((string) $transaction[$fieldName]);
}
}
return $current;
}
/** /**
* Get transaction data. * Get transaction data.
* *
@ -292,48 +395,15 @@ class TransactionUpdateRequest extends Request
* @var int $index * @var int $index
* @var array $transaction * @var array $transaction
*/ */
foreach ($this->get('transactions') as $index => $transaction) { foreach ($this->get('transactions') as $transaction) {
// default response is to update nothing in the transaction: // default response is to update nothing in the transaction:
$current = []; $current = [];
$current = $this->getIntegerData($current, $transaction);
// for each field, add it to the array if a reference is present in the request: $current = $this->getStringData($current, $transaction);
foreach ($this->integerFields as $fieldName) { $current = $this->getNlStringData($current, $transaction);
if (array_key_exists($fieldName, $transaction)) { $current = $this->getDateData($current, $transaction);
$current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]); $current = $this->getBooleanData($current, $transaction);
} $current = $this->getArrayData($current, $transaction);
}
foreach ($this->stringFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->stringFromValue((string)$transaction[$fieldName]);
}
}
foreach ($this->textareaFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->nlStringFromValue((string)$transaction[$fieldName]);
}
}
foreach ($this->dateFields as $fieldName) {
Log::debug(sprintf('Now at date field %s', $fieldName));
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]);
Log::debug(sprintf('New value: "%s"', (string)$transaction[$fieldName]));
}
}
foreach ($this->booleanFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]);
}
}
foreach ($this->arrayFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]);
}
}
$return[] = $current; $return[] = $current;
} }

View File

@ -69,14 +69,13 @@ class UserStoreRequest extends Request
if (null !== $this->get('blocked')) { if (null !== $this->get('blocked')) {
$blocked = $this->boolean('blocked'); $blocked = $this->boolean('blocked');
} }
$data = [
return [
'email' => $this->string('email'), 'email' => $this->string('email'),
'blocked' => $blocked, 'blocked' => $blocked,
'blocked_code' => $this->string('blocked_code'), 'blocked_code' => $this->string('blocked_code'),
'role' => $this->string('role'), 'role' => $this->string('role'),
]; ];
return $data;
} }
/** /**

View File

@ -69,14 +69,13 @@ class UserUpdateRequest extends Request
if (null !== $this->get('blocked')) { if (null !== $this->get('blocked')) {
$blocked = $this->boolean('blocked'); $blocked = $this->boolean('blocked');
} }
$data = [
return [
'email' => $this->string('email'), 'email' => $this->string('email'),
'blocked' => $blocked, 'blocked' => $blocked,
'blocked_code' => $this->string('blocked_code'), 'blocked_code' => $this->string('blocked_code'),
'role' => $this->string('role'), 'role' => $this->string('role'),
]; ];
return $data;
} }
/** /**
@ -86,15 +85,14 @@ class UserUpdateRequest extends Request
*/ */
public function rules(): array public function rules(): array
{ {
$user = $this->route()->parameter('user'); $user = $this->route()->parameter('user');
$rules = [
return [
'email' => sprintf('email|unique:users,email,%d', $user->id), 'email' => sprintf('email|unique:users,email,%d', $user->id),
'blocked' => [new IsBoolean], 'blocked' => [new IsBoolean],
'blocked_code' => 'in:email_changed', 'blocked_code' => 'in:email_changed',
'role' => 'in:owner,demo,', 'role' => 'in:owner,demo,',
]; ];
return $rules;
} }
} }

View File

@ -30,6 +30,7 @@ use Schema;
/** /**
* Class CorrectDatabase * Class CorrectDatabase
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
class CorrectDatabase extends Command class CorrectDatabase extends Command
@ -73,7 +74,7 @@ class CorrectDatabase extends Command
'firefly-iii:fix-ob-currencies', 'firefly-iii:fix-ob-currencies',
'firefly-iii:fix-long-descriptions', 'firefly-iii:fix-long-descriptions',
'firefly-iii:fix-recurring-transactions', 'firefly-iii:fix-recurring-transactions',
'firefly-iii:restore-oauth-keys' 'firefly-iii:restore-oauth-keys',
]; ];
foreach ($commands as $command) { foreach ($commands as $command) {
$this->line(sprintf('Now executing %s', $command)); $this->line(sprintf('Now executing %s', $command));

View File

@ -111,15 +111,12 @@ class CorrectOpeningBalanceCurrencies extends Command
*/ */
private function getAccount(TransactionJournal $journal): ?Account private function getAccount(TransactionJournal $journal): ?Account
{ {
$excluded = [];
$transactions = $journal->transactions()->with(['account', 'account.accountType'])->get(); $transactions = $journal->transactions()->with(['account', 'account.accountType'])->get();
/** @var Transaction $transaction */ /** @var Transaction $transaction */
foreach ($transactions as $transaction) { foreach ($transactions as $transaction) {
$account = $transaction->account; $account = $transaction->account;
if (null !== $account) { if ((null !== $account) && AccountType::INITIAL_BALANCE !== $account->accountType->type) {
if (AccountType::INITIAL_BALANCE !== $account->accountType->type) { return $account;
return $account;
}
} }
} }

View File

@ -50,8 +50,8 @@ class CreateAccessTokens extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int
* @throws Exception * @throws Exception
* @return int
*/ */
public function handle(): int public function handle(): int
{ {

View File

@ -25,7 +25,6 @@ namespace FireflyIII\Console\Commands\Correction;
use Exception; use Exception;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Log; use Log;
@ -50,16 +49,16 @@ class DeleteEmptyGroups extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @return mixed
* @throws Exception; * @throws Exception;
* @return mixed
*/ */
public function handle(): int public function handle(): int
{ {
Log::debug(sprintf('Now in %s', __METHOD__)); Log::debug(sprintf('Now in %s', __METHOD__));
$start = microtime(true); $start = microtime(true);
$groupIds = $groupIds
TransactionGroup = TransactionGroup
::leftJoin('transaction_journals','transaction_groups.id','=','transaction_journals.transaction_group_id') ::leftJoin('transaction_journals', 'transaction_groups.id', '=', 'transaction_journals.transaction_group_id')
->whereNull('transaction_journals.id')->get(['transaction_groups.id'])->pluck('id')->toArray(); ->whereNull('transaction_journals.id')->get(['transaction_groups.id'])->pluck('id')->toArray();
$total = count($groupIds); $total = count($groupIds);

View File

@ -101,18 +101,18 @@ class DeleteEmptyJournals extends Command
->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']); ->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']);
$total = 0; $total = 0;
foreach ($set as $row) { foreach ($set as $row) {
$count = (int)$row->the_count; $count = (int) $row->the_count;
if (1 === $count % 2) { if (1 === $count % 2) {
// uneven number, delete journal and transactions: // uneven number, delete journal and transactions:
try { try {
TransactionJournal::find((int)$row->transaction_journal_id)->delete(); TransactionJournal::find((int) $row->transaction_journal_id)->delete();
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
} catch (Exception $e) { } catch (Exception $e) {
Log::info(sprintf('Could not delete journal: %s', $e->getMessage())); Log::info(sprintf('Could not delete journal: %s', $e->getMessage()));
} }
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
Transaction::where('transaction_journal_id', (int)$row->transaction_journal_id)->delete(); Transaction::where('transaction_journal_id', (int) $row->transaction_journal_id)->delete();
$this->info(sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $row->transaction_journal_id)); $this->info(sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $row->transaction_journal_id));
$total++; $total++;
} }

View File

@ -51,8 +51,8 @@ class DeleteOrphanedTransactions extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int
* @throws Exception * @throws Exception
* @return int
*/ */
public function handle(): int public function handle(): int
{ {
@ -79,7 +79,7 @@ class DeleteOrphanedTransactions extends Command
/** @var Transaction $transaction */ /** @var Transaction $transaction */
foreach ($set as $transaction) { foreach ($set as $transaction) {
// delete journals // delete journals
$journal = TransactionJournal::find((int)$transaction->transaction_journal_id); $journal = TransactionJournal::find((int) $transaction->transaction_journal_id);
if ($journal) { if ($journal) {
try { try {
$journal->delete(); $journal->delete();
@ -89,10 +89,13 @@ class DeleteOrphanedTransactions extends Command
} }
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
} }
Transaction::where('transaction_journal_id', (int)$transaction->transaction_journal_id)->delete(); Transaction::where('transaction_journal_id', (int) $transaction->transaction_journal_id)->delete();
$this->line( $this->line(
sprintf('Deleted transaction journal #%d because account #%d was already deleted.', sprintf(
$transaction->transaction_journal_id, $transaction->account_id) 'Deleted transaction journal #%d because account #%d was already deleted.',
$transaction->transaction_journal_id,
$transaction->account_id
)
); );
$count++; $count++;
} }
@ -120,7 +123,7 @@ class DeleteOrphanedTransactions extends Command
); );
/** @var stdClass $entry */ /** @var stdClass $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
$transaction = Transaction::find((int)$entry->transaction_id); $transaction = Transaction::find((int) $entry->transaction_id);
$transaction->delete(); $transaction->delete();
$this->info( $this->info(
sprintf( sprintf(
@ -134,6 +137,5 @@ class DeleteOrphanedTransactions extends Command
if (0 === $count) { if (0 === $count) {
$this->info('No orphaned transactions.'); $this->info('No orphaned transactions.');
} }
} }
} }

View File

@ -49,6 +49,7 @@ class DeleteZeroAmount extends Command
/** /**
* Execute the console command. * Execute the console command.
*
* @return int * @return int
*/ */
public function handle(): int public function handle(): int

View File

@ -62,28 +62,28 @@ class EnableCurrencies extends Command
/** @var Collection $meta */ /** @var Collection $meta */
$meta = AccountMeta::where('name', 'currency_id')->groupBy('data')->get(['data']); $meta = AccountMeta::where('name', 'currency_id')->groupBy('data')->get(['data']);
foreach ($meta as $entry) { foreach ($meta as $entry) {
$found[] = (int)$entry->data; $found[] = (int) $entry->data;
} }
// get all from journals: // get all from journals:
/** @var Collection $journals */ /** @var Collection $journals */
$journals = TransactionJournal::groupBy('transaction_currency_id')->get(['transaction_currency_id']); $journals = TransactionJournal::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
foreach ($journals as $entry) { foreach ($journals as $entry) {
$found[] = (int)$entry->transaction_currency_id; $found[] = (int) $entry->transaction_currency_id;
} }
// get all from transactions // get all from transactions
/** @var Collection $transactions */ /** @var Collection $transactions */
$transactions = Transaction::groupBy('transaction_currency_id')->get(['transaction_currency_id']); $transactions = Transaction::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
foreach ($transactions as $entry) { foreach ($transactions as $entry) {
$found[] = (int)$entry->transaction_currency_id; $found[] = (int) $entry->transaction_currency_id;
} }
// get all from budget limits // get all from budget limits
/** @var Collection $limits */ /** @var Collection $limits */
$limits = BudgetLimit::groupBy('transaction_currency_id')->get(['transaction_currency_id']); $limits = BudgetLimit::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
foreach ($limits as $entry) { foreach ($limits as $entry) {
$found[] = (int)$entry->transaction_currency_id; $found[] = (int) $entry->transaction_currency_id;
} }
$found = array_unique($found); $found = array_unique($found);

View File

@ -49,20 +49,20 @@ class FixAccountTypes extends Command
* @var string * @var string
*/ */
protected $signature = 'firefly-iii:fix-account-types'; protected $signature = 'firefly-iii:fix-account-types';
/** @var int */
private $count;
/** @var array */ /** @var array */
private $expected; private $expected;
/** @var AccountFactory */ /** @var AccountFactory */
private $factory; private $factory;
/** @var array */ /** @var array */
private $fixable; private $fixable;
/** @var int */
private $count;
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int
* @throws FireflyException * @throws FireflyException
* @return int
*/ */
public function handle(): int public function handle(): int
{ {
@ -109,23 +109,12 @@ class FixAccountTypes extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
}
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param string $type * @param string $type
* @param Transaction $source * @param Transaction $source
* @param Transaction $dest * @param Transaction $dest
*
* @throws FireflyException * @throws FireflyException
*/ */
private function fixJournal(TransactionJournal $journal, string $type, Transaction $source, Transaction $dest): void private function fixJournal(TransactionJournal $journal, string $type, Transaction $source, Transaction $dest): void
@ -167,9 +156,12 @@ class FixAccountTypes extends Command
$dest->save(); $dest->save();
$this->info( $this->info(
sprintf( sprintf(
'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").', $journal->id, 'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").',
$oldDest->id, $oldDest->name, $journal->id,
$result->id, $result->name $oldDest->id,
$oldDest->name,
$result->id,
$result->name
) )
); );
$this->inspectJournal($journal); $this->inspectJournal($journal);
@ -184,9 +176,12 @@ class FixAccountTypes extends Command
$source->save(); $source->save();
$this->info( $this->info(
sprintf( sprintf(
'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").', $journal->id, 'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").',
$oldSource->id, $oldSource->name, $journal->id,
$result->id, $result->name $oldSource->id,
$oldSource->name,
$result->id,
$result->name
) )
); );
$this->inspectJournal($journal); $this->inspectJournal($journal);
@ -198,7 +193,6 @@ class FixAccountTypes extends Command
break; break;
} }
} }
/** /**
@ -274,4 +268,15 @@ class FixAccountTypes extends Command
} }
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
}
} }

View File

@ -51,7 +51,7 @@ class FixLongDescriptions extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$start = microtime(true); $start = microtime(true);
$journals = TransactionJournal::get(['id', 'description']); $journals = TransactionJournal::get(['id', 'description']);
/** @var TransactionJournal $journal */ /** @var TransactionJournal $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
@ -73,6 +73,7 @@ class FixLongDescriptions extends Command
} }
$end = round(microtime(true) - $start, 2); $end = round(microtime(true) - $start, 2);
$this->info(sprintf('Verified all transaction group and journal title lengths in %s seconds.', $end)); $this->info(sprintf('Verified all transaction group and journal title lengths in %s seconds.', $end));
return 0; return 0;
} }
} }

View File

@ -51,16 +51,6 @@ class FixRecurringTransactions extends Command
/** @var UserRepositoryInterface */ /** @var UserRepositoryInterface */
private $userRepos; private $userRepos;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
* *

View File

@ -63,8 +63,8 @@ class FixUnevenAmount extends Command
->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]); ->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]);
/** @var stdClass $entry */ /** @var stdClass $entry */
foreach ($journals as $entry) { foreach ($journals as $entry) {
if (0 !== bccomp((string)$entry->the_sum, '0')) { if (0 !== bccomp((string) $entry->the_sum, '0')) {
$this->fixJournal((int)$entry->transaction_journal_id); $this->fixJournal((int) $entry->transaction_journal_id);
$count++; $count++;
} }
} }
@ -94,7 +94,8 @@ class FixUnevenAmount extends Command
if (null === $source) { if (null === $source) {
$this->error( $this->error(
sprintf( sprintf(
'Journal #%d ("%s") has no source transaction. It will be deleted to maintain database consistency.', $journal->id ?? 0, 'Journal #%d ("%s") has no source transaction. It will be deleted to maintain database consistency.',
$journal->id ?? 0,
$journal->description ?? '' $journal->description ?? ''
) )
); );
@ -104,7 +105,7 @@ class FixUnevenAmount extends Command
return; return;
} }
$amount = bcmul('-1', (string)$source->amount); $amount = bcmul('-1', (string) $source->amount);
// fix amount of destination: // fix amount of destination:
/** @var Transaction $destination */ /** @var Transaction $destination */
@ -113,7 +114,8 @@ class FixUnevenAmount extends Command
if (null === $destination) { if (null === $destination) {
$this->error( $this->error(
sprintf( sprintf(
'Journal #%d ("%s") has no destination transaction. It will be deleted to maintain database consistency.', $journal->id ?? 0, 'Journal #%d ("%s") has no destination transaction. It will be deleted to maintain database consistency.',
$journal->id ?? 0,
$journal->description ?? '' $journal->description ?? ''
) )
); );

View File

@ -54,8 +54,8 @@ class DecryptDatabase extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int
* @throws FireflyException * @throws FireflyException
* @return int
*/ */
public function handle(): int public function handle(): int
{ {
@ -92,11 +92,11 @@ class DecryptDatabase extends Command
// A separate routine for preferences: // A separate routine for preferences:
if ('preferences' === $table) { if ('preferences' === $table) {
// try to json_decrypt the value. // try to json_decrypt the value.
$value = json_decode($value, true) ?? $value; $value = json_decode($value, true, 512, JSON_THROW_ON_ERROR) ?? $value;
Log::debug(sprintf('Decrypted field "%s" "%s" to "%s" in table "%s" (row #%d)', $field, $original, print_r($value, true), $table, $id)); Log::debug(sprintf('Decrypted field "%s" "%s" to "%s" in table "%s" (row #%d)', $field, $original, print_r($value, true), $table, $id));
/** @var Preference $object */ /** @var Preference $object */
$object = Preference::find((int)$id); $object = Preference::find((int) $id);
if (null !== $object) { if (null !== $object) {
$object->data = $value; $object->data = $value;
$object->save(); $object->save();
@ -131,7 +131,7 @@ class DecryptDatabase extends Command
$configName = sprintf('is_decrypted_%s', $table); $configName = sprintf('is_decrypted_%s', $table);
$configVar = app('fireflyconfig')->get($configName, false); $configVar = app('fireflyconfig')->get($configName, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; return false;
@ -142,8 +142,9 @@ class DecryptDatabase extends Command
* Tries to decrypt data. Will only throw an exception when the MAC is invalid. * Tries to decrypt data. Will only throw an exception when the MAC is invalid.
* *
* @param $value * @param $value
* @return string *
* @throws FireflyException * @throws FireflyException
* @return string
*/ */
private function tryDecrypt($value) private function tryDecrypt($value)
{ {

View File

@ -22,6 +22,7 @@
namespace FireflyIII\Console\Commands\Export; namespace FireflyIII\Console\Commands\Export;
use Carbon\Carbon; use Carbon\Carbon;
use Exception;
use FireflyIII\Console\Commands\VerifiesAccessToken; use FireflyIII\Console\Commands\VerifiesAccessToken;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
@ -32,6 +33,7 @@ use FireflyIII\User;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use InvalidArgumentException; use InvalidArgumentException;
use League\Csv\CannotInsertRecord;
use Log; use Log;
/** /**
@ -76,21 +78,12 @@ class ExportData extends Command
/** @var User */ /** @var User */
private $user; private $user;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int
* @throws FireflyException * @throws FireflyException
* @throws CannotInsertRecord
* @return int
*/ */
public function handle(): int public function handle(): int
{ {
@ -171,8 +164,8 @@ class ExportData extends Command
} }
/** /**
* @return Collection
* @throws FireflyException * @throws FireflyException
* @return Collection
*/ */
private function getAccountsParameter(): Collection private function getAccountsParameter(): Collection
{ {
@ -180,7 +173,7 @@ class ExportData extends Command
$accounts = new Collection; $accounts = new Collection;
$accountList = $this->option('accounts'); $accountList = $this->option('accounts');
$types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]; $types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
if (null !== $accountList && '' !== (string)$accountList) { if (null !== $accountList && '' !== (string) $accountList) {
$accountIds = explode(',', $accountList); $accountIds = explode(',', $accountList);
$accounts = $this->accountRepository->getAccountsById($accountIds); $accounts = $this->accountRepository->getAccountsById($accountIds);
} }
@ -204,8 +197,9 @@ class ExportData extends Command
/** /**
* @param string $field * @param string $field
* *
* @return Carbon
* @throws FireflyException * @throws FireflyException
* @throws Exception
* @return Carbon
*/ */
private function getDateParameter(string $field): Carbon private function getDateParameter(string $field): Carbon
{ {
@ -239,8 +233,8 @@ class ExportData extends Command
} }
/** /**
* @return string
* @throws FireflyException * @throws FireflyException
* @return string
*/ */
private function getExportDirectory(): string private function getExportDirectory(): string
{ {
@ -256,8 +250,8 @@ class ExportData extends Command
} }
/** /**
* @return array
* @throws FireflyException * @throws FireflyException
* @return array
*/ */
private function parseOptions(): array private function parseOptions(): array
{ {

View File

@ -39,6 +39,9 @@ use Log;
/** /**
* Class CreateCSVImport. * Class CreateCSVImport.
*
* @deprecated
* @codeCoverageIgnore
*/ */
class CreateCSVImport extends Command class CreateCSVImport extends Command
{ {
@ -60,12 +63,12 @@ class CreateCSVImport extends Command
{configuration? : The configuration file to use for the import.} {configuration? : The configuration file to use for the import.}
{--user=1 : The user ID that the import should import for.} {--user=1 : The user ID that the import should import for.}
{--token= : The user\'s access token.}'; {--token= : The user\'s access token.}';
/** @var UserRepositoryInterface */
private $userRepository;
/** @var ImportJobRepositoryInterface */
private $importRepository;
/** @var ImportJob */ /** @var ImportJob */
private $importJob; private $importJob;
/** @var ImportJobRepositoryInterface */
private $importRepository;
/** @var UserRepositoryInterface */
private $userRepository;
/** /**
* Run the command. * Run the command.
@ -87,13 +90,13 @@ class CreateCSVImport extends Command
} }
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
/** @var User $user */ /** @var User $user */
$user = $this->userRepository->findNull((int)$this->option('user')); $user = $this->userRepository->findNull((int) $this->option('user'));
$file = (string)$this->argument('file'); $file = (string) $this->argument('file');
$configuration = (string)$this->argument('configuration'); $configuration = (string) $this->argument('configuration');
$this->importRepository->setUser($user); $this->importRepository->setUser($user);
$configurationData = json_decode(file_get_contents($configuration), true); $configurationData = json_decode(file_get_contents($configuration), true, 512, JSON_THROW_ON_ERROR);
$this->importJob = $this->importRepository->create('file'); $this->importJob = $this->importRepository->create('file');
@ -147,21 +150,9 @@ class CreateCSVImport extends Command
} }
/** /**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is * @param string $message
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->userRepository = app(UserRepositoryInterface::class);
$this->importRepository = app(ImportJobRepositoryInterface::class);
}
/**
* @param string $message
* @param array|null $data * @param array|null $data
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
private function errorLine(string $message, array $data = null): void private function errorLine(string $message, array $data = null): void
@ -171,9 +162,34 @@ class CreateCSVImport extends Command
} }
/**
*
*/
private function giveFeedback(): void
{
$this->infoLine('Job has finished.');
if (null !== $this->importJob->tag) {
$this->infoLine(sprintf('%d transaction(s) have been imported.', $this->importJob->tag->transactionJournals->count()));
$this->infoLine(sprintf('You can find your transactions under tag "%s"', $this->importJob->tag->tag));
}
if (null === $this->importJob->tag) {
$this->errorLine('No transactions have been imported :(.');
}
if (count($this->importJob->errors) > 0) {
$this->infoLine(sprintf('%d error(s) occurred:', count($this->importJob->errors)));
foreach ($this->importJob->errors as $err) {
$this->errorLine('- ' . $err);
}
}
}
/** /**
* @param string $message * @param string $message
* @param array $data * @param array $data
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
private function infoLine(string $message, array $data = null): void private function infoLine(string $message, array $data = null): void
@ -182,65 +198,6 @@ class CreateCSVImport extends Command
$this->line($message); $this->line($message);
} }
/**
* Verify user inserts correct arguments.
*
* @noinspection MultipleReturnStatementsInspection
* @return bool
* @codeCoverageIgnore
*/
private function validArguments(): bool
{
$file = (string)$this->argument('file');
$configuration = (string)$this->argument('configuration');
$cwd = getcwd();
$enabled = (bool)config('import.enabled.file');
if (false === $enabled) {
$this->errorLine('CSV Provider is not enabled.');
return false;
}
if (!file_exists($file)) {
$this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
return false;
}
if (!file_exists($configuration)) {
$this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
return false;
}
$configurationData = json_decode(file_get_contents($configuration), true);
if (null === $configurationData) {
$this->errorLine(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
return false;
}
return true;
}
/**
* Store the supplied file as an attachment to this job.
*
* @param string $file
* @throws FireflyException
*/
private function storeFile(string $file): void
{
// store file as attachment.
if ('' !== $file) {
$messages = $this->importRepository->storeCLIUpload($this->importJob, 'import_file', $file);
if ($messages->count() > 0) {
throw new FireflyException($messages->first());
}
}
}
/** /**
* Keep repeating import call until job lands on "provider_finished". * Keep repeating import call until job lands on "provider_finished".
* *
@ -307,26 +264,75 @@ class CreateCSVImport extends Command
} }
/** /**
* Store the supplied file as an attachment to this job.
* *
* @param string $file
*
* @throws FireflyException
*/ */
private function giveFeedback(): void private function storeFile(string $file): void
{ {
$this->infoLine('Job has finished.'); // store file as attachment.
if ('' !== $file) {
$messages = $this->importRepository->storeCLIUpload($this->importJob, 'import_file', $file);
if (null !== $this->importJob->tag) { if ($messages->count() > 0) {
$this->infoLine(sprintf('%d transaction(s) have been imported.', $this->importJob->tag->transactionJournals->count())); throw new FireflyException($messages->first());
$this->infoLine(sprintf('You can find your transactions under tag "%s"', $this->importJob->tag->tag));
}
if (null === $this->importJob->tag) {
$this->errorLine('No transactions have been imported :(.');
}
if (count($this->importJob->errors) > 0) {
$this->infoLine(sprintf('%d error(s) occurred:', count($this->importJob->errors)));
foreach ($this->importJob->errors as $err) {
$this->errorLine('- ' . $err);
} }
} }
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->userRepository = app(UserRepositoryInterface::class);
$this->importRepository = app(ImportJobRepositoryInterface::class);
}
/**
* Verify user inserts correct arguments.
*
* @noinspection MultipleReturnStatementsInspection
* @return bool
* @codeCoverageIgnore
*/
private function validArguments(): bool
{
$file = (string) $this->argument('file');
$configuration = (string) $this->argument('configuration');
$cwd = getcwd();
$enabled = (bool) config('import.enabled.file');
if (false === $enabled) {
$this->errorLine('CSV Provider is not enabled.');
return false;
}
if (!file_exists($file)) {
$this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
return false;
}
if (!file_exists($configuration)) {
$this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
return false;
}
$configurationData = json_decode(file_get_contents($configuration), true, 512, JSON_THROW_ON_ERROR);
if (null === $configurationData) {
$this->errorLine(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
return false;
}
return true;
}
} }

View File

@ -30,6 +30,7 @@ use Schema;
/** /**
* Class ReportIntegrity * Class ReportIntegrity
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
class ReportIntegrity extends Command class ReportIntegrity extends Command

View File

@ -69,7 +69,7 @@ class ReportSum extends Command
/** @var User $user */ /** @var User $user */
foreach ($userRepository->all() as $user) { foreach ($userRepository->all() as $user) {
$sum = (string)$user->transactions()->sum('amount'); $sum = (string) $user->transactions()->sum('amount');
if (0 !== bccomp($sum, '0')) { if (0 !== bccomp($sum, '0')) {
$message = sprintf('Error: Transactions for user #%d (%s) are off by %s!', $user->id, $user->email, $sum); $message = sprintf('Error: Transactions for user #%d (%s) are off by %s!', $user->id, $user->email, $sum);
$this->error($message); $this->error($message);

View File

@ -21,8 +21,6 @@
namespace FireflyIII\Console\Commands\Integrity; namespace FireflyIII\Console\Commands\Integrity;
use Artisan;
use Crypt;
use FireflyIII\Support\System\OAuthKeys; use FireflyIII\Support\System\OAuthKeys;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@ -122,4 +120,4 @@ class RestoreOAuthKeys extends Command
{ {
OAuthKeys::storeKeysInDB(); OAuthKeys::storeKeysInDB();
} }
} }

View File

@ -63,8 +63,7 @@ class ScanAttachments extends Command
$disk = Storage::disk('upload'); $disk = Storage::disk('upload');
/** @var Attachment $attachment */ /** @var Attachment $attachment */
foreach ($attachments as $attachment) { foreach ($attachments as $attachment) {
$fileName = $attachment->fileName(); $fileName = $attachment->fileName();
$decryptedContent = '';
try { try {
$encryptedContent = $disk->get($fileName); $encryptedContent = $disk->get($fileName);
} catch (FileNotFoundException $e) { } catch (FileNotFoundException $e) {

View File

@ -43,16 +43,6 @@ class SetLatestVersion extends Command
*/ */
protected $signature = 'firefly-iii:set-latest-version {--james-is-cool}'; protected $signature = 'firefly-iii:set-latest-version {--james-is-cool}';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
* *

View File

@ -68,35 +68,32 @@ class ApplyRules extends Command
{--all_rules : If set, will overrule both settings and simply apply ALL of your rules.} {--all_rules : If set, will overrule both settings and simply apply ALL of your rules.}
{--start_date= : The date of the earliest transaction to be included (inclusive). If omitted, will be your very first transaction ever. Format: YYYY-MM-DD} {--start_date= : The date of the earliest transaction to be included (inclusive). If omitted, will be your very first transaction ever. Format: YYYY-MM-DD}
{--end_date= : The date of the latest transaction to be included (inclusive). If omitted, will be your latest transaction ever. Format: YYYY-MM-DD}'; {--end_date= : The date of the latest transaction to be included (inclusive). If omitted, will be your latest transaction ever. Format: YYYY-MM-DD}';
/** @var Collection */
private $accounts;
/** @var array */ /** @var array */
private $acceptedAccounts; private $acceptedAccounts;
/** @var Collection */
private $accounts;
/** @var bool */
private $allRules;
/** @var Carbon */ /** @var Carbon */
private $endDate; private $endDate;
/** @var Collection */
private $groups;
/** @var RuleGroupRepositoryInterface */
private $ruleGroupRepository;
/** @var array */ /** @var array */
private $ruleGroupSelection; private $ruleGroupSelection;
/** @var RuleRepositoryInterface */
private $ruleRepository;
/** @var array */ /** @var array */
private $ruleSelection; private $ruleSelection;
/** @var Carbon */ /** @var Carbon */
private $startDate; private $startDate;
/** @var Collection */
private $groups;
/** @var bool */
private $allRules;
/** @var RuleRepositoryInterface */
private $ruleRepository;
/** @var RuleGroupRepositoryInterface */
private $ruleGroupRepository;
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int
* @throws FireflyException * @throws FireflyException
* @return int
*/ */
public function handle(): int public function handle(): int
{ {
@ -169,6 +166,49 @@ class ApplyRules extends Command
return 0; return 0;
} }
/**
* @return array
*/
private function getRulesToApply(): array
{
$rulesToApply = [];
/** @var RuleGroup $group */
foreach ($this->groups as $group) {
$rules = $this->ruleGroupRepository->getActiveStoreRules($group);
/** @var Rule $rule */
foreach ($rules as $rule) {
// if in rule selection, or group in selection or all rules, it's included.
$test = $this->includeRule($rule, $group);
if (true === $test) {
Log::debug(sprintf('Will include rule #%d "%s"', $rule->id, $rule->title));
$rulesToApply[] = $rule->id;
}
}
}
return $rulesToApply;
}
/**
*/
private function grabAllRules(): void
{
$this->groups = $this->ruleGroupRepository->getActiveGroups();
}
/**
* @param Rule $rule
* @param RuleGroup $group
*
* @return bool
*/
private function includeRule(Rule $rule, RuleGroup $group): bool
{
return in_array($group->id, $this->ruleGroupSelection, true)
|| in_array($rule->id, $this->ruleSelection, true)
|| $this->allRules;
}
/** /**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is * Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should * executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
@ -189,8 +229,8 @@ class ApplyRules extends Command
} }
/** /**
* @return bool
* @throws FireflyException * @throws FireflyException
* @return bool
*/ */
private function verifyInput(): bool private function verifyInput(): bool
{ {
@ -212,8 +252,8 @@ class ApplyRules extends Command
} }
/** /**
* @return bool
* @throws FireflyException * @throws FireflyException
* @return bool
*/ */
private function verifyInputAccounts(): bool private function verifyInputAccounts(): bool
{ {
@ -240,7 +280,7 @@ class ApplyRules extends Command
foreach ($accountList as $accountId) { foreach ($accountList as $accountId) {
$accountId = (int)$accountId; $accountId = (int) $accountId;
$account = $accountRepository->findNull($accountId); $account = $accountRepository->findNull($accountId);
if (null !== $account && in_array($account->accountType->type, $this->acceptedAccounts, true)) { if (null !== $account && in_array($account->accountType->type, $this->acceptedAccounts, true)) {
$finalList->push($account); $finalList->push($account);
@ -258,66 +298,6 @@ class ApplyRules extends Command
} }
/**
* @return bool
*/
private function verifyInputRuleGroups(): bool
{
$ruleGroupString = $this->option('rule_groups');
if (null === $ruleGroupString || '' === $ruleGroupString) {
// can be empty.
return true;
}
$ruleGroupList = explode(',', $ruleGroupString);
// @codeCoverageIgnoreStart
if (0 === count($ruleGroupList)) {
// can be empty.
return true;
}
// @codeCoverageIgnoreEnd
foreach ($ruleGroupList as $ruleGroupId) {
$ruleGroup = $this->ruleGroupRepository->find((int)$ruleGroupId);
if ($ruleGroup->active) {
$this->ruleGroupSelection[] = $ruleGroup->id;
}
if (false === $ruleGroup->active) {
$this->warn(sprintf('Will ignore inactive rule group #%d ("%s")', $ruleGroup->id, $ruleGroup->title));
}
}
return true;
}
/**
* @return bool
*/
private function verifyInputRules(): bool
{
$ruleString = $this->option('rules');
if (null === $ruleString || '' === $ruleString) {
// can be empty.
return true;
}
$ruleList = explode(',', $ruleString);
// @codeCoverageIgnoreStart
if (0 === count($ruleList)) {
// can be empty.
return true;
}
// @codeCoverageIgnoreEnd
foreach ($ruleList as $ruleId) {
$rule = $this->ruleRepository->find((int)$ruleId);
if (null !== $rule && $rule->active) {
$this->ruleSelection[] = $rule->id;
}
}
return true;
}
/** /**
* @throws FireflyException * @throws FireflyException
*/ */
@ -355,44 +335,62 @@ class ApplyRules extends Command
} }
/** /**
*/
private function grabAllRules(): void
{
$this->groups = $this->ruleGroupRepository->getActiveGroups();
}
/**
* @param Rule $rule
* @param RuleGroup $group
* @return bool * @return bool
*/ */
private function includeRule(Rule $rule, RuleGroup $group): bool private function verifyInputRuleGroups(): bool
{ {
return in_array($group->id, $this->ruleGroupSelection, true) || $ruleGroupString = $this->option('rule_groups');
in_array($rule->id, $this->ruleSelection, true) || if (null === $ruleGroupString || '' === $ruleGroupString) {
$this->allRules; // can be empty.
} return true;
}
/** $ruleGroupList = explode(',', $ruleGroupString);
* @return array // @codeCoverageIgnoreStart
*/ if (0 === count($ruleGroupList)) {
private function getRulesToApply(): array // can be empty.
{ return true;
$rulesToApply = []; }
/** @var RuleGroup $group */ // @codeCoverageIgnoreEnd
foreach ($this->groups as $group) { foreach ($ruleGroupList as $ruleGroupId) {
$rules = $this->ruleGroupRepository->getActiveStoreRules($group); $ruleGroup = $this->ruleGroupRepository->find((int) $ruleGroupId);
/** @var Rule $rule */ if ($ruleGroup->active) {
foreach ($rules as $rule) { $this->ruleGroupSelection[] = $ruleGroup->id;
// if in rule selection, or group in selection or all rules, it's included. }
$test = $this->includeRule($rule, $group); if (false === $ruleGroup->active) {
if (true === $test) { $this->warn(sprintf('Will ignore inactive rule group #%d ("%s")', $ruleGroup->id, $ruleGroup->title));
Log::debug(sprintf('Will include rule #%d "%s"', $rule->id, $rule->title));
$rulesToApply[] = $rule->id;
}
} }
} }
return $rulesToApply; return true;
}
/**
* @return bool
*/
private function verifyInputRules(): bool
{
$ruleString = $this->option('rules');
if (null === $ruleString || '' === $ruleString) {
// can be empty.
return true;
}
$ruleList = explode(',', $ruleString);
// @codeCoverageIgnoreStart
if (0 === count($ruleList)) {
// can be empty.
return true;
}
// @codeCoverageIgnoreEnd
foreach ($ruleList as $ruleId) {
$rule = $this->ruleRepository->find((int) $ruleId);
if (null !== $rule && $rule->active) {
$this->ruleSelection[] = $rule->id;
}
}
return true;
} }
} }

View File

@ -27,9 +27,11 @@ namespace FireflyIII\Console\Commands\Tools;
use Carbon\Carbon; use Carbon\Carbon;
use Exception; use Exception;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Support\Cronjobs\AutoBudgetCronjob;
use FireflyIII\Support\Cronjobs\RecurringCronjob; use FireflyIII\Support\Cronjobs\RecurringCronjob;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use InvalidArgumentException; use InvalidArgumentException;
use Log;
/** /**
* Class Cron * Class Cron
@ -56,39 +58,38 @@ class Cron extends Command
/** /**
* @return int * @return int
* @throws Exception
*/ */
public function handle(): int public function handle(): int
{ {
$date = null; $date = null;
try { try {
$date = new Carbon($this->option('date')); $date = new Carbon($this->option('date'));
} catch (InvalidArgumentException $e) { } catch (InvalidArgumentException|Exception $e) {
$this->error(sprintf('"%s" is not a valid date', $this->option('date'))); $this->error(sprintf('"%s" is not a valid date', $this->option('date')));
$e->getMessage(); $e->getMessage();
} }
$force = (bool) $this->option('force');
/*
$recurring = new RecurringCronjob; * Fire recurring transaction cron job.
$recurring->setForce($this->option('force')); */
// set date in cron job:
if (null !== $date) {
$recurring->setDate($date);
}
try { try {
$result = $recurring->fire(); $this->recurringCronJob($force, $date);
} catch (FireflyException $e) { } catch (FireflyException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$this->error($e->getMessage()); $this->error($e->getMessage());
}
return 0; /*
} * Fire auto-budget cron job:
if (false === $result) { */
$this->line('The recurring transaction cron job did not fire.'); try {
} $this->autoBudgetCronJob($force, $date);
if (true === $result) { } catch (FireflyException $e) {
$this->line('The recurring transaction cron job fired successfully.'); Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$this->error($e->getMessage());
} }
$this->info('More feedback on the cron jobs can be found in the log files.'); $this->info('More feedback on the cron jobs can be found in the log files.');
@ -96,5 +97,56 @@ class Cron extends Command
return 0; return 0;
} }
/**
* @param bool $force
* @param Carbon|null $date
*
* @throws FireflyException
* @throws Exception
*/
private function autoBudgetCronJob(bool $force, ?Carbon $date): void
{
$autoBudget = new AutoBudgetCronjob;
$autoBudget->setForce($force);
// set date in cron job:
if (null !== $date) {
$autoBudget->setDate($date);
}
$result = $autoBudget->fire();
if (false === $result) {
$this->line('The auto budget cron job did not fire.');
}
if (true === $result) {
$this->line('The auto budget cron job fired successfully.');
}
}
/**
* @param bool $force
* @param Carbon|null $date
*
* @throws FireflyException
*/
private function recurringCronJob(bool $force, ?Carbon $date): void
{
$recurring = new RecurringCronjob;
$recurring->setForce($force);
// set date in cron job:
if (null !== $date) {
$recurring->setDate($date);
}
$result = $recurring->fire();
if (false === $result) {
$this->line('The recurring transaction cron job did not fire.');
}
if (true === $result) {
$this->line('The recurring transaction cron job fired successfully.');
}
}
} }

View File

@ -54,10 +54,10 @@ class AccountCurrencies extends Command
protected $signature = 'firefly-iii:account-currencies {--F|force : Force the execution of this command.}'; protected $signature = 'firefly-iii:account-currencies {--F|force : Force the execution of this command.}';
/** @var AccountRepositoryInterface */ /** @var AccountRepositoryInterface */
private $accountRepos; private $accountRepos;
/** @var UserRepositoryInterface */
private $userRepos;
/** @var int */ /** @var int */
private $count; private $count;
/** @var UserRepositoryInterface */
private $userRepos;
/** /**
* Each (asset) account must have a reference to a preferred currency. If the account does not have one, it's forced upon the account. * Each (asset) account must have a reference to a preferred currency. If the account does not have one, it's forced upon the account.
@ -90,6 +90,27 @@ class AccountCurrencies extends Command
return 0; return 0;
} }
/**
* @return bool
*/
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool) $configVar->data;
}
return false; // @codeCoverageIgnore
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
/** /**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is * Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should * executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
@ -105,29 +126,7 @@ class AccountCurrencies extends Command
} }
/** /**
* @return bool * @param Account $account
*/
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
}
return false; // @codeCoverageIgnore
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
/**
* @param Account $account
* @param TransactionCurrency $currency * @param TransactionCurrency $currency
*/ */
private function updateAccount(Account $account, TransactionCurrency $currency): void private function updateAccount(Account $account, TransactionCurrency $currency): void
@ -135,13 +134,13 @@ class AccountCurrencies extends Command
Log::debug(sprintf('Now in updateAccount(%d, %s)', $account->id, $currency->code)); Log::debug(sprintf('Now in updateAccount(%d, %s)', $account->id, $currency->code));
$this->accountRepos->setUser($account->user); $this->accountRepos->setUser($account->user);
$accountCurrency = (int)$this->accountRepos->getMetaValue($account, 'currency_id'); $accountCurrency = (int) $this->accountRepos->getMetaValue($account, 'currency_id');
Log::debug(sprintf('Account currency is #%d', $accountCurrency)); Log::debug(sprintf('Account currency is #%d', $accountCurrency));
$openingBalance = $this->accountRepos->getOpeningBalance($account); $openingBalance = $this->accountRepos->getOpeningBalance($account);
$obCurrency = 0; $obCurrency = 0;
if (null !== $openingBalance) { if (null !== $openingBalance) {
$obCurrency = (int)$openingBalance->transaction_currency_id; $obCurrency = (int) $openingBalance->transaction_currency_id;
Log::debug('Account has opening balance.'); Log::debug('Account has opening balance.');
} }
Log::debug(sprintf('Account OB currency is #%d.', $obCurrency)); Log::debug(sprintf('Account OB currency is #%d.', $obCurrency));
@ -178,7 +177,8 @@ class AccountCurrencies extends Command
static function (Transaction $transaction) use ($accountCurrency) { static function (Transaction $transaction) use ($accountCurrency) {
$transaction->transaction_currency_id = $accountCurrency; $transaction->transaction_currency_id = $accountCurrency;
$transaction->save(); $transaction->save();
}); }
);
$this->line(sprintf('Account #%d ("%s") now has a correct currency for opening balance.', $account->id, $account->name)); $this->line(sprintf('Account #%d ("%s") now has a correct currency for opening balance.', $account->id, $account->name));
$this->count++; $this->count++;
@ -194,7 +194,7 @@ class AccountCurrencies extends Command
{ {
Log::debug('Now in updateAccountCurrencies()'); Log::debug('Now in updateAccountCurrencies()');
$users = $this->userRepos->all(); $users = $this->userRepos->all();
$defaultCurrencyCode = (string)config('firefly.default_currency', 'EUR'); $defaultCurrencyCode = (string) config('firefly.default_currency', 'EUR');
Log::debug(sprintf('Default currency is %s', $defaultCurrencyCode)); Log::debug(sprintf('Default currency is %s', $defaultCurrencyCode));
foreach ($users as $user) { foreach ($users as $user) {
$this->updateCurrenciesForUser($user, $defaultCurrencyCode); $this->updateCurrenciesForUser($user, $defaultCurrencyCode);
@ -202,7 +202,7 @@ class AccountCurrencies extends Command
} }
/** /**
* @param User $user * @param User $user
* @param string $systemCurrencyCode * @param string $systemCurrencyCode
*/ */
private function updateCurrenciesForUser(User $user, string $systemCurrencyCode): void private function updateCurrenciesForUser(User $user, string $systemCurrencyCode): void

View File

@ -111,9 +111,9 @@ class BackToJournals extends Command
$chunks = array_chunk($transactions, 500); $chunks = array_chunk($transactions, 500);
foreach ($chunks as $chunk) { foreach ($chunks as $chunk) {
$set = DB::table('transactions') $set = DB::table('transactions')
->whereIn('transactions.id', $chunk) ->whereIn('transactions.id', $chunk)
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray(); ->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
/** @noinspection SlowArrayOperationsInLoopInspection */ /** @noinspection SlowArrayOperationsInLoopInspection */
$array = array_merge($array, $set); $array = array_merge($array, $set);
} }
@ -128,7 +128,7 @@ class BackToJournals extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore
@ -141,7 +141,7 @@ class BackToJournals extends Command
{ {
$configVar = app('fireflyconfig')->get(MigrateToGroups::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(MigrateToGroups::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore
@ -212,7 +212,7 @@ class BackToJournals extends Command
// both have a budget, but they don't match. // both have a budget, but they don't match.
if (null !== $budget && null !== $journalBudget && $budget->id !== $journalBudget->id) { if (null !== $budget && null !== $journalBudget && $budget->id !== $journalBudget->id) {
// sync to journal: // sync to journal:
$journal->budgets()->sync([(int)$budget->id]); $journal->budgets()->sync([(int) $budget->id]);
return; return;
} }
@ -220,7 +220,7 @@ class BackToJournals extends Command
// transaction has a budget, but the journal doesn't. // transaction has a budget, but the journal doesn't.
if (null !== $budget && null === $journalBudget) { if (null !== $budget && null === $journalBudget) {
// sync to journal: // sync to journal:
$journal->budgets()->sync([(int)$budget->id]); $journal->budgets()->sync([(int) $budget->id]);
} }
} }
@ -271,12 +271,12 @@ class BackToJournals extends Command
// both have a category, but they don't match. // both have a category, but they don't match.
if (null !== $category && null !== $journalCategory && $category->id !== $journalCategory->id) { if (null !== $category && null !== $journalCategory && $category->id !== $journalCategory->id) {
// sync to journal: // sync to journal:
$journal->categories()->sync([(int)$category->id]); $journal->categories()->sync([(int) $category->id]);
} }
// transaction has a category, but the journal doesn't. // transaction has a category, but the journal doesn't.
if (null !== $category && null === $journalCategory) { if (null !== $category && null === $journalCategory) {
$journal->categories()->sync([(int)$category->id]); $journal->categories()->sync([(int) $category->id]);
} }
} }
} }

View File

@ -102,7 +102,7 @@ class BudgetLimitCurrency extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore

View File

@ -101,7 +101,7 @@ class CCLiabilities extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore

View File

@ -71,7 +71,7 @@ class MigrateAttachments extends Command
foreach ($attachments as $att) { foreach ($attachments as $att) {
// move description: // move description:
$description = (string)$att->description; $description = (string) $att->description;
if ('' !== $description) { if ('' !== $description) {
// find or create note: // find or create note:
@ -111,7 +111,7 @@ class MigrateAttachments extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore

View File

@ -110,7 +110,7 @@ class MigrateJournalNotes extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore

View File

@ -81,7 +81,7 @@ class MigrateRecurrenceMeta extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore
@ -103,7 +103,7 @@ class MigrateRecurrenceMeta extends Command
*/ */
private function migrateEntry(RecurrenceMeta $meta): int private function migrateEntry(RecurrenceMeta $meta): int
{ {
$recurrence = $meta->recurrence; $recurrence = $meta->recurrence;
if (null === $recurrence) { if (null === $recurrence) {
return 0; return 0;
} }
@ -115,7 +115,7 @@ class MigrateRecurrenceMeta extends Command
if ('tags' === $meta->name) { if ('tags' === $meta->name) {
$array = explode(',', $meta->value); $array = explode(',', $meta->value);
$value = json_encode($array); $value = json_encode($array, JSON_THROW_ON_ERROR, 512);
} }
RecurrenceTransactionMeta::create( RecurrenceTransactionMeta::create(

View File

@ -84,7 +84,7 @@ class MigrateTagLocations extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore

View File

@ -59,21 +59,21 @@ class MigrateToGroups extends Command
* @var string * @var string
*/ */
protected $signature = 'firefly-iii:migrate-to-groups {--F|force : Force the migration, even if it fired before.}'; protected $signature = 'firefly-iii:migrate-to-groups {--F|force : Force the migration, even if it fired before.}';
/** @var JournalCLIRepositoryInterface */
private $cliRepository;
private $count;
/** @var TransactionGroupFactory */ /** @var TransactionGroupFactory */
private $groupFactory; private $groupFactory;
/** @var JournalRepositoryInterface */ /** @var JournalRepositoryInterface */
private $journalRepository; private $journalRepository;
/** @var JournalCLIRepositoryInterface */
private $cliRepository;
/** @var JournalDestroyService */ /** @var JournalDestroyService */
private $service; private $service;
private $count;
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int
* @throws Exception * @throws Exception
* @return int
*/ */
public function handle(): int public function handle(): int
{ {
@ -116,25 +116,9 @@ class MigrateToGroups extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->journalRepository = app(JournalRepositoryInterface::class);
$this->service = app(JournalDestroyService::class);
$this->groupFactory = app(TransactionGroupFactory::class);
$this->cliRepository = app(JournalCLIRepositoryInterface::class);
}
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param Transaction $transaction * @param Transaction $transaction
* *
* @return Transaction|null * @return Transaction|null
*/ */
@ -142,7 +126,7 @@ class MigrateToGroups extends Command
{ {
$set = $journal->transactions->filter( $set = $journal->transactions->filter(
static function (Transaction $subject) use ($transaction) { static function (Transaction $subject) use ($transaction) {
$amount = (float)$transaction->amount * -1 === (float)$subject->amount; $amount = (float) $transaction->amount * -1 === (float) $subject->amount;
$identifier = $transaction->identifier === $subject->identifier; $identifier = $transaction->identifier === $subject->identifier;
Log::debug(sprintf('Amount the same? %s', var_export($amount, true))); Log::debug(sprintf('Amount the same? %s', var_export($amount, true)));
Log::debug(sprintf('ID the same? %s', var_export($identifier, true))); Log::debug(sprintf('ID the same? %s', var_export($identifier, true)));
@ -168,6 +152,72 @@ class MigrateToGroups extends Command
); );
} }
/**
* @param Transaction $left
* @param Transaction $right
*
* @return int|null
*/
private function getTransactionBudget(Transaction $left, Transaction $right): ?int
{
Log::debug('Now in getTransactionBudget()');
// try to get a budget ID from the left transaction:
/** @var Budget $budget */
$budget = $left->budgets()->first();
if (null !== $budget) {
Log::debug(sprintf('Return budget #%d, from transaction #%d', $budget->id, $left->id));
return (int) $budget->id;
}
// try to get a budget ID from the right transaction:
/** @var Budget $budget */
$budget = $right->budgets()->first();
if (null !== $budget) {
Log::debug(sprintf('Return budget #%d, from transaction #%d', $budget->id, $right->id));
return (int) $budget->id;
}
Log::debug('Neither left or right have a budget, return NULL');
// if all fails, return NULL.
return null;
}
/**
* @param Transaction $left
* @param Transaction $right
*
* @return int|null
*/
private function getTransactionCategory(Transaction $left, Transaction $right): ?int
{
Log::debug('Now in getTransactionCategory()');
// try to get a category ID from the left transaction:
/** @var Category $category */
$category = $left->categories()->first();
if (null !== $category) {
Log::debug(sprintf('Return category #%d, from transaction #%d', $category->id, $left->id));
return (int) $category->id;
}
// try to get a category ID from the left transaction:
/** @var Category $category */
$category = $right->categories()->first();
if (null !== $category) {
Log::debug(sprintf('Return category #%d, from transaction #%d', $category->id, $category->id));
return (int) $category->id;
}
Log::debug('Neither left or right have a category, return NULL');
// if all fails, return NULL.
return null;
}
/** /**
* @param array $array * @param array $array
*/ */
@ -192,7 +242,7 @@ class MigrateToGroups extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore
@ -302,7 +352,8 @@ class MigrateToGroups extends Command
$this->error( $this->error(
sprintf( sprintf(
'Journal #%d has no opposing transaction for transaction #%d. Cannot upgrade this entry.', 'Journal #%d has no opposing transaction for transaction #%d. Cannot upgrade this entry.',
$journal->id, $transaction->id $journal->id,
$transaction->id
) )
); );
continue; continue;
@ -365,81 +416,23 @@ class MigrateToGroups extends Command
// report on result: // report on result:
Log::debug( Log::debug(
sprintf('Migrated journal #%d into group #%d with these journals: #%s', sprintf(
$journal->id, $group->id, implode(', #', $group->transactionJournals->pluck('id')->toArray())) 'Migrated journal #%d into group #%d with these journals: #%s',
$journal->id,
$group->id,
implode(', #', $group->transactionJournals->pluck('id')->toArray())
)
); );
$this->line( $this->line(
sprintf('Migrated journal #%d into group #%d with these journals: #%s', sprintf(
$journal->id, $group->id, implode(', #', $group->transactionJournals->pluck('id')->toArray())) 'Migrated journal #%d into group #%d with these journals: #%s',
$journal->id,
$group->id,
implode(', #', $group->transactionJournals->pluck('id')->toArray())
)
); );
} }
/**
* @param Transaction $left
* @param Transaction $right
*
* @return int|null
*/
private function getTransactionBudget(Transaction $left, Transaction $right): ?int
{
Log::debug('Now in getTransactionBudget()');
// try to get a budget ID from the left transaction:
/** @var Budget $budget */
$budget = $left->budgets()->first();
if (null !== $budget) {
Log::debug(sprintf('Return budget #%d, from transaction #%d', $budget->id, $left->id));
return (int)$budget->id;
}
// try to get a budget ID from the right transaction:
/** @var Budget $budget */
$budget = $right->budgets()->first();
if (null !== $budget) {
Log::debug(sprintf('Return budget #%d, from transaction #%d', $budget->id, $right->id));
return (int)$budget->id;
}
Log::debug('Neither left or right have a budget, return NULL');
// if all fails, return NULL.
return null;
}
/**
* @param Transaction $left
* @param Transaction $right
*
* @return int|null
*/
private function getTransactionCategory(Transaction $left, Transaction $right): ?int
{
Log::debug('Now in getTransactionCategory()');
// try to get a category ID from the left transaction:
/** @var Category $category */
$category = $left->categories()->first();
if (null !== $category) {
Log::debug(sprintf('Return category #%d, from transaction #%d', $category->id, $left->id));
return (int)$category->id;
}
// try to get a category ID from the left transaction:
/** @var Category $category */
$category = $right->categories()->first();
if (null !== $category) {
Log::debug(sprintf('Return category #%d, from transaction #%d', $category->id, $category->id));
return (int)$category->id;
}
Log::debug('Neither left or right have a category, return NULL');
// if all fails, return NULL.
return null;
}
/** /**
* *
*/ */
@ -448,4 +441,19 @@ class MigrateToGroups extends Command
app('fireflyconfig')->set(self::CONFIG_NAME, true); app('fireflyconfig')->set(self::CONFIG_NAME, true);
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->journalRepository = app(JournalRepositoryInterface::class);
$this->service = app(JournalDestroyService::class);
$this->groupFactory = app(TransactionGroupFactory::class);
$this->cliRepository = app(JournalCLIRepositoryInterface::class);
}
} }

View File

@ -53,22 +53,21 @@ class MigrateToRules extends Command
* @var string * @var string
*/ */
protected $signature = 'firefly-iii:bills-to-rules {--F|force : Force the execution of this command.}'; protected $signature = 'firefly-iii:bills-to-rules {--F|force : Force the execution of this command.}';
/** @var UserRepositoryInterface */
private $userRepository;
/** @var RuleGroupRepositoryInterface */
private $ruleGroupRepository;
/** @var BillRepositoryInterface */ /** @var BillRepositoryInterface */
private $billRepository; private $billRepository;
private $count;
/** @var RuleGroupRepositoryInterface */
private $ruleGroupRepository;
/** @var RuleRepositoryInterface */ /** @var RuleRepositoryInterface */
private $ruleRepository; private $ruleRepository;
private $count; /** @var UserRepositoryInterface */
private $userRepository;
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int
* @throws FireflyException * @throws FireflyException
* @return int
*/ */
public function handle(): int public function handle(): int
{ {
@ -103,22 +102,6 @@ class MigrateToRules extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->userRepository = app(UserRepositoryInterface::class);
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
$this->ruleRepository = app(RuleRepositoryInterface::class);
}
/** /**
* @return bool * @return bool
*/ */
@ -126,7 +109,7 @@ class MigrateToRules extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore
@ -141,45 +124,9 @@ class MigrateToRules extends Command
} }
/** /**
* Migrate bills to new rule structure for a specific user. * @param RuleGroup $ruleGroup
* * @param Bill $bill
* @param User $user * @param Preference $language
* @throws FireflyException
*/
private function migrateUser(User $user): void
{
$this->ruleGroupRepository->setUser($user);
$this->billRepository->setUser($user);
$this->ruleRepository->setUser($user);
/** @var Preference $lang */
$lang = app('preferences')->getForUser($user, 'language', 'en_US');
$groupTitle = (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data);
$ruleGroup = $this->ruleGroupRepository->findByTitle($groupTitle);
//$currency = $this->getCurrency($user);
if (null === $ruleGroup) {
$ruleGroup = $this->ruleGroupRepository->store(
[
'title' => (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data),
'description' => (string)trans('firefly.rulegroup_for_bills_description', [], $lang->data),
'active' => true,
]
);
}
$bills = $this->billRepository->getBills();
/** @var Bill $bill */
foreach ($bills as $bill) {
$this->migrateBill($ruleGroup, $bill, $lang);
}
}
/**
* @param RuleGroup $ruleGroup
* @param Bill $bill
* @throws FireflyException
*/ */
private function migrateBill(RuleGroup $ruleGroup, Bill $bill, Preference $language): void private function migrateBill(RuleGroup $ruleGroup, Bill $bill, Preference $language): void
{ {
@ -194,8 +141,8 @@ class MigrateToRules extends Command
'active' => true, 'active' => true,
'strict' => false, 'strict' => false,
'stop_processing' => false, // field is no longer used. 'stop_processing' => false, // field is no longer used.
'title' => (string)trans('firefly.rule_for_bill_title', ['name' => $bill->name], $language->data), 'title' => (string) trans('firefly.rule_for_bill_title', ['name' => $bill->name], $language->data),
'description' => (string)trans('firefly.rule_for_bill_description', ['name' => $bill->name], $language->data), 'description' => (string) trans('firefly.rule_for_bill_description', ['name' => $bill->name], $language->data),
'trigger' => 'store-journal', 'trigger' => 'store-journal',
'triggers' => [ 'triggers' => [
[ [
@ -246,4 +193,57 @@ class MigrateToRules extends Command
$this->billRepository->update($bill, $newBillData); $this->billRepository->update($bill, $newBillData);
$this->count++; $this->count++;
} }
/**
* Migrate bills to new rule structure for a specific user.
*
* @param User $user
*
* @throws FireflyException
*/
private function migrateUser(User $user): void
{
$this->ruleGroupRepository->setUser($user);
$this->billRepository->setUser($user);
$this->ruleRepository->setUser($user);
/** @var Preference $lang */
$lang = app('preferences')->getForUser($user, 'language', 'en_US');
$groupTitle = (string) trans('firefly.rulegroup_for_bills_title', [], $lang->data);
$ruleGroup = $this->ruleGroupRepository->findByTitle($groupTitle);
//$currency = $this->getCurrency($user);
if (null === $ruleGroup) {
$ruleGroup = $this->ruleGroupRepository->store(
[
'title' => (string) trans('firefly.rulegroup_for_bills_title', [], $lang->data),
'description' => (string) trans('firefly.rulegroup_for_bills_description', [], $lang->data),
'active' => true,
]
);
}
$bills = $this->billRepository->getBills();
/** @var Bill $bill */
foreach ($bills as $bill) {
$this->migrateBill($ruleGroup, $bill, $lang);
}
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->userRepository = app(UserRepositoryInterface::class);
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
$this->ruleRepository = app(RuleRepositoryInterface::class);
}
} }

View File

@ -40,7 +40,6 @@ use Illuminate\Console\Command;
*/ */
class OtherCurrenciesCorrections extends Command class OtherCurrenciesCorrections extends Command
{ {
public const CONFIG_NAME = '480_other_currencies'; public const CONFIG_NAME = '480_other_currencies';
/** /**
* The console command description. * The console command description.
@ -58,14 +57,14 @@ class OtherCurrenciesCorrections extends Command
private $accountCurrencies; private $accountCurrencies;
/** @var AccountRepositoryInterface */ /** @var AccountRepositoryInterface */
private $accountRepos; private $accountRepos;
/** @var CurrencyRepositoryInterface */
private $currencyRepos;
/** @var JournalRepositoryInterface */
private $journalRepos;
/** @var JournalCLIRepositoryInterface */ /** @var JournalCLIRepositoryInterface */
private $cliRepos; private $cliRepos;
/** @var int */ /** @var int */
private $count; private $count;
/** @var CurrencyRepositoryInterface */
private $currencyRepos;
/** @var JournalRepositoryInterface */
private $journalRepos;
/** /**
* Execute the console command. * Execute the console command.
@ -94,23 +93,6 @@ class OtherCurrenciesCorrections extends Command
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->accountCurrencies = [];
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->journalRepos = app(JournalRepositoryInterface::class);
$this->cliRepos = app(JournalCLIRepositoryInterface::class);
}
/** /**
* @param Account $account * @param Account $account
* *
@ -136,110 +118,6 @@ class OtherCurrenciesCorrections extends Command
$this->accountCurrencies[$accountId] = $currency; $this->accountCurrencies[$accountId] = $currency;
return $currency; return $currency;
}
/**
* @return bool
*/
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool)$configVar->data;
}
return false; // @codeCoverageIgnore
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
/**
* @param TransactionJournal $journal
*/
private function updateJournalCurrency(TransactionJournal $journal): void
{
$this->accountRepos->setUser($journal->user);
$this->journalRepos->setUser($journal->user);
$this->currencyRepos->setUser($journal->user);
$this->cliRepos->setUser($journal->user);
$leadTransaction = $this->getLeadTransaction($journal);
if (null === $leadTransaction) {
// @codeCoverageIgnoreStart
$this->error(sprintf('Could not reliably determine which transaction is in the lead for transaction journal #%d.', $journal->id));
return;
// @codeCoverageIgnoreEnd
}
/** @var Account $account */
$account = $leadTransaction->account;
$currency = $this->getCurrency($account);
if (null === $currency) {
// @codeCoverageIgnoreStart
$this->error(sprintf('Account #%d ("%s") has no currency preference, so transaction journal #%d can\'t be corrected',
$account->id, $account->name, $journal->id));
$this->count++;
return;
// @codeCoverageIgnoreEnd
}
// fix each transaction:
$journal->transactions->each(
static function (Transaction $transaction) use ($currency) {
if (null === $transaction->transaction_currency_id) {
$transaction->transaction_currency_id = $currency->id;
$transaction->save();
}
// when mismatch in transaction:
if (!((int)$transaction->transaction_currency_id === (int)$currency->id)) {
$transaction->foreign_currency_id = (int)$transaction->transaction_currency_id;
$transaction->foreign_amount = $transaction->amount;
$transaction->transaction_currency_id = $currency->id;
$transaction->save();
}
}
);
// also update the journal, of course:
$journal->transaction_currency_id = $currency->id;
$this->count++;
$journal->save();
}
/**
* This routine verifies that withdrawals, deposits and opening balances have the correct currency settings for
* the accounts they are linked to.
*
* Both source and destination must match the respective currency preference of the related asset account.
* So FF3 must verify all transactions.
*
*/
private function updateOtherJournalsCurrencies(): void
{
$set =
$this->cliRepos->getAllJournals(
[
TransactionType::WITHDRAWAL,
TransactionType::DEPOSIT,
TransactionType::OPENING_BALANCE,
TransactionType::RECONCILIATION,
]
);
/** @var TransactionJournal $journal */
foreach ($set as $journal) {
$this->updateJournalCurrency($journal);
}
} }
/** /**
@ -281,4 +159,129 @@ class OtherCurrenciesCorrections extends Command
return $lead; return $lead;
} }
/**
* @return bool
*/
private function isExecuted(): bool
{
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) {
return (bool) $configVar->data;
}
return false; // @codeCoverageIgnore
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->count = 0;
$this->accountCurrencies = [];
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->journalRepos = app(JournalRepositoryInterface::class);
$this->cliRepos = app(JournalCLIRepositoryInterface::class);
}
/**
* @param TransactionJournal $journal
*/
private function updateJournalCurrency(TransactionJournal $journal): void
{
$this->accountRepos->setUser($journal->user);
$this->journalRepos->setUser($journal->user);
$this->currencyRepos->setUser($journal->user);
$this->cliRepos->setUser($journal->user);
$leadTransaction = $this->getLeadTransaction($journal);
if (null === $leadTransaction) {
// @codeCoverageIgnoreStart
$this->error(sprintf('Could not reliably determine which transaction is in the lead for transaction journal #%d.', $journal->id));
return;
// @codeCoverageIgnoreEnd
}
/** @var Account $account */
$account = $leadTransaction->account;
$currency = $this->getCurrency($account);
if (null === $currency) {
// @codeCoverageIgnoreStart
$this->error(
sprintf(
'Account #%d ("%s") has no currency preference, so transaction journal #%d can\'t be corrected',
$account->id,
$account->name,
$journal->id
)
);
$this->count++;
return;
// @codeCoverageIgnoreEnd
}
// fix each transaction:
$journal->transactions->each(
static function (Transaction $transaction) use ($currency) {
if (null === $transaction->transaction_currency_id) {
$transaction->transaction_currency_id = $currency->id;
$transaction->save();
}
// when mismatch in transaction:
if (!((int) $transaction->transaction_currency_id === (int) $currency->id)) {
$transaction->foreign_currency_id = (int) $transaction->transaction_currency_id;
$transaction->foreign_amount = $transaction->amount;
$transaction->transaction_currency_id = $currency->id;
$transaction->save();
}
}
);
// also update the journal, of course:
$journal->transaction_currency_id = $currency->id;
$this->count++;
$journal->save();
}
/**
* This routine verifies that withdrawals, deposits and opening balances have the correct currency settings for
* the accounts they are linked to.
*
* Both source and destination must match the respective currency preference of the related asset account.
* So FF3 must verify all transactions.
*
*/
private function updateOtherJournalsCurrencies(): void
{
$set
= $this->cliRepos->getAllJournals(
[
TransactionType::WITHDRAWAL,
TransactionType::DEPOSIT,
TransactionType::OPENING_BALANCE,
TransactionType::RECONCILIATION,
]
);
/** @var TransactionJournal $journal */
foreach ($set as $journal) {
$this->updateJournalCurrency($journal);
}
}
} }

View File

@ -76,7 +76,7 @@ class RenameAccountMeta extends Command
$count += AccountMeta::where('name', $old)->update(['name' => $new]); $count += AccountMeta::where('name', $old)->update(['name' => $new]);
// delete empty entries while we're at it. // delete empty entries while we're at it.
AccountMeta::where('name', $new)->where('data','""')->delete(); AccountMeta::where('name', $new)->where('data', '""')->delete();
} }
$this->markAsExecuted(); $this->markAsExecuted();
@ -101,7 +101,7 @@ class RenameAccountMeta extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore

View File

@ -50,15 +50,12 @@ class TransactionIdentifier extends Command
* @var string * @var string
*/ */
protected $signature = 'firefly-iii:transaction-identifiers {--F|force : Force the execution of this command.}'; protected $signature = 'firefly-iii:transaction-identifiers {--F|force : Force the execution of this command.}';
/** @var JournalRepositoryInterface */
private $journalRepository;
/** @var JournalCLIRepositoryInterface */ /** @var JournalCLIRepositoryInterface */
private $cliRepository; private $cliRepository;
/** @var int */ /** @var int */
private $count; private $count;
/** @var JournalRepositoryInterface */
private $journalRepository;
/** /**
* This method gives all transactions which are part of a split journal (so more than 2) a sort of "order" so they are easier * This method gives all transactions which are part of a split journal (so more than 2) a sort of "order" so they are easier
@ -108,17 +105,36 @@ class TransactionIdentifier extends Command
} }
/** /**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is * @param Transaction $transaction
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should * @param array $exclude
* be called from the handle method instead of using the constructor to initialize the command.
* *
* @codeCoverageIgnore * @return Transaction|null
*/ */
private function stupidLaravel(): void private function findOpposing(Transaction $transaction, array $exclude): ?Transaction
{ {
$this->journalRepository = app(JournalRepositoryInterface::class); // find opposing:
$this->cliRepository = app(JournalCLIRepositoryInterface::class); $amount = bcmul((string) $transaction->amount, '-1');
$this->count = 0;
try {
/** @var Transaction $opposing */
$opposing = Transaction::where('transaction_journal_id', $transaction->transaction_journal_id)
->where('amount', $amount)->where('identifier', '=', 0)
->whereNotIn('id', $exclude)
->first();
// @codeCoverageIgnoreStart
} catch (QueryException $e) {
Log::error($e->getMessage());
$this->error('Firefly III could not find the "identifier" field in the "transactions" table.');
$this->error(sprintf('This field is required for Firefly III version %s to run.', config('firefly.version')));
$this->error('Please run "php artisan migrate" to add this field to the table.');
$this->info('Then, run "php artisan firefly:upgrade-database" to try again.');
return null;
}
// @codeCoverageIgnoreEnd
return $opposing;
} }
/** /**
@ -128,7 +144,7 @@ class TransactionIdentifier extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore
@ -142,6 +158,20 @@ class TransactionIdentifier extends Command
app('fireflyconfig')->set(self::CONFIG_NAME, true); app('fireflyconfig')->set(self::CONFIG_NAME, true);
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->journalRepository = app(JournalRepositoryInterface::class);
$this->cliRepository = app(JournalCLIRepositoryInterface::class);
$this->count = 0;
}
/** /**
* Grab all positive transactions from this journal that are not deleted. for each one, grab the negative opposing one * Grab all positive transactions from this journal that are not deleted. for each one, grab the negative opposing one
* which has 0 as an identifier and give it the same identifier. * which has 0 as an identifier and give it the same identifier.
@ -171,36 +201,4 @@ class TransactionIdentifier extends Command
} }
} }
/**
* @param Transaction $transaction
* @param array $exclude
* @return Transaction|null
*/
private function findOpposing(Transaction $transaction, array $exclude): ?Transaction
{
// find opposing:
$amount = bcmul((string)$transaction->amount, '-1');
try {
/** @var Transaction $opposing */
$opposing = Transaction::where('transaction_journal_id', $transaction->transaction_journal_id)
->where('amount', $amount)->where('identifier', '=', 0)
->whereNotIn('id', $exclude)
->first();
// @codeCoverageIgnoreStart
} catch (QueryException $e) {
Log::error($e->getMessage());
$this->error('Firefly III could not find the "identifier" field in the "transactions" table.');
$this->error(sprintf('This field is required for Firefly III version %s to run.', config('firefly.version')));
$this->error('Please run "php artisan migrate" to add this field to the table.');
$this->info('Then, run "php artisan firefly:upgrade-database" to try again.');
return null;
}
// @codeCoverageIgnoreEnd
return $opposing;
}
} }

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Upgrade; namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
@ -41,7 +40,6 @@ use Log;
*/ */
class TransferCurrenciesCorrections extends Command class TransferCurrenciesCorrections extends Command
{ {
public const CONFIG_NAME = '480_transfer_currencies'; public const CONFIG_NAME = '480_transfer_currencies';
/** /**
* The console command description. * The console command description.
@ -59,27 +57,26 @@ class TransferCurrenciesCorrections extends Command
private $accountCurrencies; private $accountCurrencies;
/** @var AccountRepositoryInterface */ /** @var AccountRepositoryInterface */
private $accountRepos; private $accountRepos;
/** @var CurrencyRepositoryInterface */
private $currencyRepos;
/** @var JournalRepositoryInterface */
private $journalRepos;
/** @var JournalCLIRepositoryInterface */ /** @var JournalCLIRepositoryInterface */
private $cliRepos; private $cliRepos;
/** @var int */ /** @var int */
private $count; private $count;
/** @var CurrencyRepositoryInterface */
/** @var Transaction The source transaction of the current journal. */ private $currencyRepos;
private $sourceTransaction;
/** @var Account The source account of the current journal. */
private $sourceAccount;
/** @var TransactionCurrency The currency preference of the source account of the current journal. */
private $sourceCurrency;
/** @var Transaction The destination transaction of the current journal. */
private $destinationTransaction;
/** @var Account The destination account of the current journal. */ /** @var Account The destination account of the current journal. */
private $destinationAccount; private $destinationAccount;
/** @var TransactionCurrency The currency preference of the destination account of the current journal. */ /** @var TransactionCurrency The currency preference of the destination account of the current journal. */
private $destinationCurrency; private $destinationCurrency;
/** @var Transaction The destination transaction of the current journal. */
private $destinationTransaction;
/** @var JournalRepositoryInterface */
private $journalRepos;
/** @var Account The source account of the current journal. */
private $sourceAccount;
/** @var TransactionCurrency The currency preference of the source account of the current journal. */
private $sourceCurrency;
/** @var Transaction The source transaction of the current journal. */
private $sourceTransaction;
/** /**
* Execute the console command. * Execute the console command.
@ -118,21 +115,216 @@ class TransferCurrenciesCorrections extends Command
} }
/** /**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is * The destination transaction must have a currency. If not, it will be added by
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should * taking it from the destination account's preference.
* be called from the handle method instead of using the constructor to initialize the command.
*
* @codeCoverageIgnore
*/ */
private function stupidLaravel(): void private function fixDestNoCurrency(): void
{ {
$this->count = 0; if (null === $this->destinationTransaction->transaction_currency_id && null !== $this->destinationCurrency) {
$this->accountRepos = app(AccountRepositoryInterface::class); $this->destinationTransaction
$this->currencyRepos = app(CurrencyRepositoryInterface::class); ->transaction_currency_id
$this->journalRepos = app(JournalRepositoryInterface::class); = (int) $this->destinationCurrency->id;
$this->cliRepos = app(JournalCLIRepositoryInterface::class); $message = sprintf(
$this->accountCurrencies = []; 'Transaction #%d has no currency setting, now set to %s.',
$this->resetInformation(); $this->destinationTransaction->id,
$this->destinationCurrency->code
);
Log::debug($message);
$this->line($message);
$this->count++;
$this->destinationTransaction->save();
}
}
/**
* If the foreign amount of the destination transaction is null, but that of the other isn't, use this piece of code
* to restore it.
*/
private function fixDestNullForeignAmount(): void
{
if (null === $this->destinationTransaction->foreign_amount && null !== $this->sourceTransaction->foreign_amount) {
$this->destinationTransaction->foreign_amount = bcmul((string) $this->sourceTransaction->foreign_amount, '-1');
$this->destinationTransaction->save();
$this->count++;
Log::debug(
sprintf(
'Restored foreign amount of destination transaction #%d to %s',
$this->destinationTransaction->id,
$this->destinationTransaction->foreign_amount
)
);
}
}
/**
* The destination transaction must have the correct currency. If not, it will be set by
* taking it from the destination account's preference.
*/
private function fixDestinationUnmatchedCurrency(): void
{
if (null !== $this->destinationCurrency
&& null === $this->destinationTransaction->foreign_amount
&& (int) $this->destinationTransaction->transaction_currency_id !== (int) $this->destinationCurrency->id
) {
$message = sprintf(
'Transaction #%d has a currency setting #%d that should be #%d. Amount remains %s, currency is changed.',
$this->destinationTransaction->id,
$this->destinationTransaction->transaction_currency_id,
$this->destinationAccount->id,
$this->destinationTransaction->amount
);
Log::debug($message);
$this->line($message);
$this->count++;
$this->destinationTransaction->transaction_currency_id = (int) $this->destinationCurrency->id;
$this->destinationTransaction->save();
}
}
/**
* If the destination account currency is the same as the source currency,
* both foreign_amount and foreign_currency_id fields must be NULL
* for both transactions (because foreign currency info would not make sense)
*
*/
private function fixInvalidForeignCurrency(): void
{
if ((int) $this->destinationCurrency->id === (int) $this->sourceCurrency->id) {
// update both transactions to match:
$this->sourceTransaction->foreign_amount = null;
$this->sourceTransaction->foreign_currency_id = null;
$this->destinationTransaction->foreign_amount = null;
$this->destinationTransaction->foreign_currency_id = null;
$this->sourceTransaction->save();
$this->destinationTransaction->save();
Log::debug(
sprintf(
'Currency for account "%s" is %s, and currency for account "%s" is also
%s, so transactions #%d and #%d has been verified to be to %s exclusively.',
$this->destinationAccount->name,
$this->destinationCurrency->code,
$this->sourceAccount->name,
$this->sourceCurrency->code,
$this->sourceTransaction->id,
$this->destinationTransaction->id,
$this->sourceCurrency->code
)
);
}
}
/**
* If destination account currency is different from source account currency,
* then both transactions must get the source account's currency as normal currency
* and the opposing account's currency as foreign currency.
*/
private function fixMismatchedForeignCurrency(): void
{
if ((int) $this->sourceCurrency->id !== (int) $this->destinationCurrency->id) {
$this->sourceTransaction->transaction_currency_id = $this->sourceCurrency->id;
$this->sourceTransaction->foreign_currency_id = $this->destinationCurrency->id;
$this->destinationTransaction->transaction_currency_id = $this->sourceCurrency->id;
$this->destinationTransaction->foreign_currency_id = $this->destinationCurrency->id;
$this->sourceTransaction->save();
$this->destinationTransaction->save();
$this->count++;
Log::debug(sprintf('Verified foreign currency ID of transaction #%d and #%d', $this->sourceTransaction->id, $this->destinationTransaction->id));
}
}
/**
* The source transaction must have a currency. If not, it will be added by
* taking it from the source account's preference.
*/
private function fixSourceNoCurrency(): void
{
if (null === $this->sourceTransaction->transaction_currency_id && null !== $this->sourceCurrency) {
$this->sourceTransaction
->transaction_currency_id
= (int) $this->sourceCurrency->id;
$message = sprintf(
'Transaction #%d has no currency setting, now set to %s.',
$this->sourceTransaction->id,
$this->sourceCurrency->code
);
Log::debug($message);
$this->line($message);
$this->count++;
$this->sourceTransaction->save();
}
}
/**
* If the foreign amount of the source transaction is null, but that of the other isn't, use this piece of code
* to restore it.
*/
private function fixSourceNullForeignAmount(): void
{
if (null === $this->sourceTransaction->foreign_amount && null !== $this->destinationTransaction->foreign_amount) {
$this->sourceTransaction->foreign_amount = bcmul((string) $this->destinationTransaction->foreign_amount, '-1');
$this->sourceTransaction->save();
$this->count++;
Log::debug(
sprintf(
'Restored foreign amount of source transaction #%d to %s',
$this->sourceTransaction->id,
$this->sourceTransaction->foreign_amount
)
);
}
}
/**
* The source transaction must have the correct currency. If not, it will be set by
* taking it from the source account's preference.
*/
private function fixSourceUnmatchedCurrency(): void
{
if (null !== $this->sourceCurrency
&& null === $this->sourceTransaction->foreign_amount
&& (int) $this->sourceTransaction->transaction_currency_id !== (int) $this->sourceCurrency->id
) {
$message = sprintf(
'Transaction #%d has a currency setting #%d that should be #%d. Amount remains %s, currency is changed.',
$this->sourceTransaction->id,
$this->sourceTransaction->transaction_currency_id,
$this->sourceAccount->id,
$this->sourceTransaction->amount
);
Log::debug($message);
$this->line($message);
$this->count++;
$this->sourceTransaction->transaction_currency_id = (int) $this->sourceCurrency->id;
$this->sourceTransaction->save();
}
}
/**
* This method makes sure that the transaction journal uses the currency given in the source transaction.
*
* @param TransactionJournal $journal
*/
private function fixTransactionJournalCurrency(TransactionJournal $journal): void
{
if ((int) $journal->transaction_currency_id !== (int) $this->sourceCurrency->id) {
$oldCurrencyCode = $journal->transactionCurrency->code ?? '(nothing)';
$journal->transaction_currency_id = $this->sourceCurrency->id;
$message = sprintf(
'Transfer #%d ("%s") has been updated to use %s instead of %s.',
$journal->id,
$journal->description,
$this->sourceCurrency->code,
$oldCurrencyCode
);
$this->count++;
$this->line($message);
Log::debug($message);
$journal->save();
}
} }
/** /**
@ -150,7 +342,7 @@ class TransferCurrenciesCorrections extends Command
return $this->accountCurrencies[$accountId]; // @codeCoverageIgnore return $this->accountCurrencies[$accountId]; // @codeCoverageIgnore
} }
// TODO we can use getAccountCurrency() instead // TODO we can use getAccountCurrency() instead
$currencyId = (int)$this->accountRepos->getMetaValue($account, 'currency_id'); $currencyId = (int) $this->accountRepos->getMetaValue($account, 'currency_id');
$result = $this->currencyRepos->findNull($currencyId); $result = $this->currencyRepos->findNull($currencyId);
if (null === $result) { if (null === $result) {
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
@ -162,8 +354,20 @@ class TransferCurrenciesCorrections extends Command
$this->accountCurrencies[$accountId] = $result; $this->accountCurrencies[$accountId] = $result;
return $result; return $result;
}
/**
* Extract destination transaction, destination account + destination account currency from the journal.
*
* @param TransactionJournal $journal
*
* @codeCoverageIgnore
*/
private function getDestinationInformation(TransactionJournal $journal): void
{
$this->destinationTransaction = $this->getDestinationTransaction($journal);
$this->destinationAccount = null === $this->destinationTransaction ? null : $this->destinationTransaction->account;
$this->destinationCurrency = null === $this->destinationAccount ? null : $this->getCurrency($this->destinationAccount);
} }
/** /**
@ -177,6 +381,20 @@ class TransferCurrenciesCorrections extends Command
return $transfer->transactions()->where('amount', '>', 0)->first(); return $transfer->transactions()->where('amount', '>', 0)->first();
} }
/**
* Extract source transaction, source account + source account currency from the journal.
*
* @param TransactionJournal $journal
*
* @codeCoverageIgnore
*/
private function getSourceInformation(TransactionJournal $journal): void
{
$this->sourceTransaction = $this->getSourceTransaction($journal);
$this->sourceAccount = null === $this->sourceTransaction ? null : $this->sourceTransaction->account;
$this->sourceCurrency = null === $this->sourceAccount ? null : $this->getCurrency($this->sourceAccount);
}
/** /**
* @param TransactionJournal $transfer * @param TransactionJournal $transfer
* *
@ -188,6 +406,19 @@ class TransferCurrenciesCorrections extends Command
return $transfer->transactions()->where('amount', '<', 0)->first(); return $transfer->transactions()->where('amount', '<', 0)->first();
} }
/**
* Is either the source or destination transaction NULL?
*
* @return bool
* @codeCoverageIgnore
*/
private function isEmptyTransactions(): bool
{
return null === $this->sourceTransaction || null === $this->destinationTransaction
|| null === $this->sourceAccount
|| null === $this->destinationAccount;
}
/** /**
* @return bool * @return bool
*/ */
@ -195,12 +426,56 @@ class TransferCurrenciesCorrections extends Command
{ {
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
if (null !== $configVar) { if (null !== $configVar) {
return (bool)$configVar->data; return (bool) $configVar->data;
} }
return false; // @codeCoverageIgnore return false; // @codeCoverageIgnore
} }
/**
* @return bool
* @codeCoverageIgnore
*/
private function isNoCurrencyPresent(): bool
{
// source account must have a currency preference.
if (null === $this->sourceCurrency) {
$message = sprintf('Account #%d ("%s") must have currency preference but has none.', $this->sourceAccount->id, $this->sourceAccount->name);
Log::error($message);
$this->error($message);
return true;
}
// destination account must have a currency preference.
if (null === $this->destinationCurrency) {
$message = sprintf(
'Account #%d ("%s") must have currency preference but has none.',
$this->destinationAccount->id,
$this->destinationAccount->name
);
Log::error($message);
$this->error($message);
return true;
}
return false;
}
/**
* Is this a split transaction journal?
*
* @param TransactionJournal $transfer
*
* @return bool
* @codeCoverageIgnore
*/
private function isSplitJournal(TransactionJournal $transfer): bool
{
return $transfer->transactions->count() > 2;
}
/** /**
* *
*/ */
@ -210,27 +485,18 @@ class TransferCurrenciesCorrections extends Command
} }
/** /**
* This method makes sure that the transaction journal uses the currency given in the source transaction. * Reset all the class fields for the current transfer.
* *
* @param TransactionJournal $journal * @codeCoverageIgnore
*/ */
private function fixTransactionJournalCurrency(TransactionJournal $journal): void private function resetInformation(): void
{ {
if ((int)$journal->transaction_currency_id !== (int)$this->sourceCurrency->id) { $this->sourceTransaction = null;
$oldCurrencyCode = $journal->transactionCurrency->code ?? '(nothing)'; $this->sourceAccount = null;
$journal->transaction_currency_id = $this->sourceCurrency->id; $this->sourceCurrency = null;
$message = sprintf( $this->destinationTransaction = null;
'Transfer #%d ("%s") has been updated to use %s instead of %s.', $this->destinationAccount = null;
$journal->id, $this->destinationCurrency = null;
$journal->description,
$this->sourceCurrency->code,
$oldCurrencyCode
);
$this->count++;
$this->line($message);
Log::debug($message);
$journal->save();
}
} }
/** /**
@ -253,43 +519,21 @@ class TransferCurrenciesCorrections extends Command
} }
/** /**
* Reset all the class fields for the current transfer. * Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* @codeCoverageIgnore * executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
*/ * be called from the handle method instead of using the constructor to initialize the command.
private function resetInformation(): void
{
$this->sourceTransaction = null;
$this->sourceAccount = null;
$this->sourceCurrency = null;
$this->destinationTransaction = null;
$this->destinationAccount = null;
$this->destinationCurrency = null;
}
/**
* Extract source transaction, source account + source account currency from the journal.
* *
* @param TransactionJournal $journal
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
private function getSourceInformation(TransactionJournal $journal): void private function stupidLaravel(): void
{ {
$this->sourceTransaction = $this->getSourceTransaction($journal); $this->count = 0;
$this->sourceAccount = null === $this->sourceTransaction ? null : $this->sourceTransaction->account; $this->accountRepos = app(AccountRepositoryInterface::class);
$this->sourceCurrency = null === $this->sourceAccount ? null : $this->getCurrency($this->sourceAccount); $this->currencyRepos = app(CurrencyRepositoryInterface::class);
} $this->journalRepos = app(JournalRepositoryInterface::class);
$this->cliRepos = app(JournalCLIRepositoryInterface::class);
/** $this->accountCurrencies = [];
* Extract destination transaction, destination account + destination account currency from the journal. $this->resetInformation();
*
* @param TransactionJournal $journal
* @codeCoverageIgnore
*/
private function getDestinationInformation(TransactionJournal $journal): void
{
$this->destinationTransaction = $this->getDestinationTransaction($journal);
$this->destinationAccount = null === $this->destinationTransaction ? null : $this->destinationTransaction->account;
$this->destinationCurrency = null === $this->destinationAccount ? null : $this->getCurrency($this->destinationAccount);
} }
/** /**
@ -297,7 +541,6 @@ class TransferCurrenciesCorrections extends Command
*/ */
private function updateTransferCurrency(TransactionJournal $transfer): void private function updateTransferCurrency(TransactionJournal $transfer): void
{ {
$this->resetInformation(); $this->resetInformation();
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
@ -325,7 +568,8 @@ class TransferCurrenciesCorrections extends Command
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
if ($this->isNoCurrencyPresent()) { if ($this->isNoCurrencyPresent()) {
$this->error( $this->error(
sprintf('Source or destination accounts for transaction journal #%d have no currency information. Cannot fix this one.', $transfer->id)); sprintf('Source or destination accounts for transaction journal #%d have no currency information. Cannot fix this one.', $transfer->id)
);
return; return;
} }
@ -355,225 +599,5 @@ class TransferCurrenciesCorrections extends Command
// fix journal itself: // fix journal itself:
$this->fixTransactionJournalCurrency($transfer); $this->fixTransactionJournalCurrency($transfer);
} }
/**
* The source transaction must have a currency. If not, it will be added by
* taking it from the source account's preference.
*/
private function fixSourceNoCurrency(): void
{
if (null === $this->sourceTransaction->transaction_currency_id && null !== $this->sourceCurrency) {
$this->sourceTransaction
->transaction_currency_id = (int)$this->sourceCurrency->id;
$message = sprintf('Transaction #%d has no currency setting, now set to %s.',
$this->sourceTransaction->id, $this->sourceCurrency->code);
Log::debug($message);
$this->line($message);
$this->count++;
$this->sourceTransaction->save();
}
}
/**
* The destination transaction must have a currency. If not, it will be added by
* taking it from the destination account's preference.
*/
private function fixDestNoCurrency(): void
{
if (null === $this->destinationTransaction->transaction_currency_id && null !== $this->destinationCurrency) {
$this->destinationTransaction
->transaction_currency_id = (int)$this->destinationCurrency->id;
$message = sprintf('Transaction #%d has no currency setting, now set to %s.',
$this->destinationTransaction->id, $this->destinationCurrency->code);
Log::debug($message);
$this->line($message);
$this->count++;
$this->destinationTransaction->save();
}
}
/**
* The source transaction must have the correct currency. If not, it will be set by
* taking it from the source account's preference.
*/
private function fixSourceUnmatchedCurrency(): void
{
if (null !== $this->sourceCurrency &&
null === $this->sourceTransaction->foreign_amount &&
(int)$this->sourceTransaction->transaction_currency_id !== (int)$this->sourceCurrency->id
) {
$message = sprintf(
'Transaction #%d has a currency setting #%d that should be #%d. Amount remains %s, currency is changed.',
$this->sourceTransaction->id,
$this->sourceTransaction->transaction_currency_id,
$this->sourceAccount->id,
$this->sourceTransaction->amount
);
Log::debug($message);
$this->line($message);
$this->count++;
$this->sourceTransaction->transaction_currency_id = (int)$this->sourceCurrency->id;
$this->sourceTransaction->save();
}
}
/**
* The destination transaction must have the correct currency. If not, it will be set by
* taking it from the destination account's preference.
*/
private function fixDestinationUnmatchedCurrency(): void
{
if (null !== $this->destinationCurrency &&
null === $this->destinationTransaction->foreign_amount &&
(int)$this->destinationTransaction->transaction_currency_id !== (int)$this->destinationCurrency->id
) {
$message = sprintf(
'Transaction #%d has a currency setting #%d that should be #%d. Amount remains %s, currency is changed.',
$this->destinationTransaction->id,
$this->destinationTransaction->transaction_currency_id,
$this->destinationAccount->id,
$this->destinationTransaction->amount
);
Log::debug($message);
$this->line($message);
$this->count++;
$this->destinationTransaction->transaction_currency_id = (int)$this->destinationCurrency->id;
$this->destinationTransaction->save();
}
}
/**
* Is this a split transaction journal?
*
* @param TransactionJournal $transfer
* @return bool
* @codeCoverageIgnore
*/
private function isSplitJournal(TransactionJournal $transfer): bool
{
return $transfer->transactions->count() > 2;
}
/**
* Is either the source or destination transaction NULL?
* @return bool
* @codeCoverageIgnore
*/
private function isEmptyTransactions(): bool
{
return null === $this->sourceTransaction || null === $this->destinationTransaction ||
null === $this->sourceAccount || null === $this->destinationAccount;
}
/**
* If the destination account currency is the same as the source currency,
* both foreign_amount and foreign_currency_id fields must be NULL
* for both transactions (because foreign currency info would not make sense)
*
*/
private function fixInvalidForeignCurrency(): void
{
if ((int)$this->destinationCurrency->id === (int)$this->sourceCurrency->id) {
// update both transactions to match:
$this->sourceTransaction->foreign_amount = null;
$this->sourceTransaction->foreign_currency_id = null;
$this->destinationTransaction->foreign_amount = null;
$this->destinationTransaction->foreign_currency_id = null;
$this->sourceTransaction->save();
$this->destinationTransaction->save();
Log::debug(
sprintf(
'Currency for account "%s" is %s, and currency for account "%s" is also
%s, so transactions #%d and #%d has been verified to be to %s exclusively.',
$this->destinationAccount->name, $this->destinationCurrency->code,
$this->sourceAccount->name, $this->sourceCurrency->code,
$this->sourceTransaction->id, $this->destinationTransaction->id, $this->sourceCurrency->code
)
);
}
}
/**
* If destination account currency is different from source account currency,
* then both transactions must get the source account's currency as normal currency
* and the opposing account's currency as foreign currency.
*/
private function fixMismatchedForeignCurrency(): void
{
if ((int)$this->sourceCurrency->id !== (int)$this->destinationCurrency->id) {
$this->sourceTransaction->transaction_currency_id = $this->sourceCurrency->id;
$this->sourceTransaction->foreign_currency_id = $this->destinationCurrency->id;
$this->destinationTransaction->transaction_currency_id = $this->sourceCurrency->id;
$this->destinationTransaction->foreign_currency_id = $this->destinationCurrency->id;
$this->sourceTransaction->save();
$this->destinationTransaction->save();
$this->count++;
Log::debug(sprintf('Verified foreign currency ID of transaction #%d and #%d', $this->sourceTransaction->id, $this->destinationTransaction->id));
}
}
/**
* If the foreign amount of the source transaction is null, but that of the other isn't, use this piece of code
* to restore it.
*/
private function fixSourceNullForeignAmount(): void
{
if (null === $this->sourceTransaction->foreign_amount && null !== $this->destinationTransaction->foreign_amount) {
$this->sourceTransaction->foreign_amount = bcmul((string)$this->destinationTransaction->foreign_amount, '-1');
$this->sourceTransaction->save();
$this->count++;
Log::debug(sprintf('Restored foreign amount of source transaction #%d to %s',
$this->sourceTransaction->id, $this->sourceTransaction->foreign_amount));
}
}
/**
* If the foreign amount of the destination transaction is null, but that of the other isn't, use this piece of code
* to restore it.
*/
private function fixDestNullForeignAmount(): void
{
if (null === $this->destinationTransaction->foreign_amount && null !== $this->sourceTransaction->foreign_amount) {
$this->destinationTransaction->foreign_amount = bcmul((string)$this->sourceTransaction->foreign_amount, '-1');
$this->destinationTransaction->save();
$this->count++;
Log::debug(sprintf('Restored foreign amount of destination transaction #%d to %s',
$this->destinationTransaction->id, $this->destinationTransaction->foreign_amount));
}
}
/**
* @return bool
* @codeCoverageIgnore
*/
private function isNoCurrencyPresent(): bool
{
// source account must have a currency preference.
if (null === $this->sourceCurrency) {
$message = sprintf('Account #%d ("%s") must have currency preference but has none.', $this->sourceAccount->id, $this->sourceAccount->name);
Log::error($message);
$this->error($message);
return true;
}
// destination account must have a currency preference.
if (null === $this->destinationCurrency) {
$message = sprintf('Account #%d ("%s") must have currency preference but has none.',
$this->destinationAccount->id, $this->destinationAccount->name);
Log::error($message);
$this->error($message);
return true;
}
return false;
}
} }

View File

@ -30,6 +30,7 @@ use Illuminate\Console\Command;
/** /**
* Class UpgradeDatabase * Class UpgradeDatabase
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
class UpgradeDatabase extends Command class UpgradeDatabase extends Command
@ -112,9 +113,9 @@ class UpgradeDatabase extends Command
echo $result; echo $result;
} }
// set new DB version. // set new DB version.
app('fireflyconfig')->set('db_version', (int)config('firefly.db_version')); app('fireflyconfig')->set('db_version', (int) config('firefly.db_version'));
// index will set FF3 version. // index will set FF3 version.
app('fireflyconfig')->set('ff3_version', (string)config('firefly.version')); app('fireflyconfig')->set('ff3_version', (string) config('firefly.version'));
return 0; return 0;
} }

View File

@ -50,10 +50,10 @@ class UpgradeFireflyInstructions extends Command
*/ */
public function handle(): int public function handle(): int
{ {
if ('update' === (string)$this->argument('task')) { if ('update' === (string) $this->argument('task')) {
$this->updateInstructions(); $this->updateInstructions();
} }
if ('install' === (string)$this->argument('task')) { if ('install' === (string) $this->argument('task')) {
$this->installInstructions(); $this->installInstructions();
} }

View File

@ -38,12 +38,12 @@ use Log;
trait VerifiesAccessToken trait VerifiesAccessToken
{ {
/** /**
* @return User
* @throws FireflyException * @throws FireflyException
* @return User
*/ */
public function getUser(): User public function getUser(): User
{ {
$userId = (int)$this->option('user'); $userId = (int) $this->option('user');
/** @var UserRepositoryInterface $repository */ /** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class); $repository = app(UserRepositoryInterface::class);
$user = $repository->findNull($userId); $user = $repository->findNull($userId);
@ -70,8 +70,8 @@ trait VerifiesAccessToken
*/ */
protected function verifyAccessToken(): bool protected function verifyAccessToken(): bool
{ {
$userId = (int)$this->option('user'); $userId = (int) $this->option('user');
$token = (string)$this->option('token'); $token = (string) $this->option('token');
/** @var UserRepositoryInterface $repository */ /** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class); $repository = app(UserRepositoryInterface::class);
$user = $repository->findNull($userId); $user = $repository->findNull($userId);

View File

@ -55,7 +55,7 @@ class RequestedReportOnJournals
public function __construct(int $userId, Collection $groups) public function __construct(int $userId, Collection $groups)
{ {
Log::debug('In event RequestedReportOnJournals.'); Log::debug('In event RequestedReportOnJournals.');
$this->userId = $userId; $this->userId = $userId;
$this->groups = $groups; $this->groups = $groups;
} }

View File

@ -20,6 +20,7 @@
*/ */
namespace FireflyIII\Exceptions; namespace FireflyIII\Exceptions;
use Exception; use Exception;
/** /**
@ -27,5 +28,4 @@ use Exception;
*/ */
class DuplicateTransactionException extends Exception class DuplicateTransactionException extends Exception
{ {
}
}

View File

@ -28,6 +28,7 @@ use Exception;
/** /**
* Class FireflyException. * Class FireflyException.
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
class FireflyException extends Exception class FireflyException extends Exception

View File

@ -33,8 +33,11 @@ use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Log; use Log;
use Symfony\Component\HttpFoundation\Response;
/** /**
* Class GracefulNotFoundHandler * Class GracefulNotFoundHandler
@ -134,7 +137,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
* @param Request $request * @param Request $request
* @param Exception $exception * @param Exception $exception
* *
* @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response * @return \Illuminate\Http\Response|Response
*/ */
private function handleAccount($request, Exception $exception) private function handleAccount($request, Exception $exception)
{ {
@ -142,7 +145,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
$route = $request->route(); $route = $request->route();
$accountId = (int)$route->parameter('account'); $accountId = (int) $route->parameter('account');
/** @var Account $account */ /** @var Account $account */
$account = $user->accounts()->with(['accountType'])->withTrashed()->find($accountId); $account = $user->accounts()->with(['accountType'])->withTrashed()->find($accountId);
if (null === $account) { if (null === $account) {
@ -163,7 +166,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
$route = $request->route(); $route = $request->route();
$attachmentId = (int)$route->parameter('attachment'); $attachmentId = (int) $route->parameter('attachment');
/** @var Attachment $attachment */ /** @var Attachment $attachment */
$attachment = $user->attachments()->withTrashed()->find($attachmentId); $attachment = $user->attachments()->withTrashed()->find($attachmentId);
if (null === $attachment) { if (null === $attachment) {
@ -199,7 +202,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
* @param $request * @param $request
* @param Exception $exception * @param Exception $exception
* *
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Routing\Redirector|\Symfony\Component\HttpFoundation\Response * @return RedirectResponse|\Illuminate\Http\Response|Redirector|Response
*/ */
private function handleGroup($request, Exception $exception) private function handleGroup($request, Exception $exception)
{ {
@ -207,7 +210,7 @@ class GracefulNotFoundHandler extends ExceptionHandler
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
$route = $request->route(); $route = $request->route();
$groupId = (int)$route->parameter('transactionGroup'); $groupId = (int) $route->parameter('transactionGroup');
/** @var TransactionGroup $group */ /** @var TransactionGroup $group */
$group = $user->transactionGroups()->withTrashed()->find($groupId); $group = $user->transactionGroups()->withTrashed()->find($groupId);

View File

@ -82,15 +82,17 @@ class Handler extends ExceptionHandler
'line' => $exception->getLine(), 'line' => $exception->getLine(),
'file' => $exception->getFile(), 'file' => $exception->getFile(),
'trace' => $exception->getTrace(), 'trace' => $exception->getTrace(),
], 500 ],
500
); );
} }
return response()->json(['message' => 'Internal Firefly III Exception. See log files.', 'exception' => get_class($exception)], 500); return response()->json(['message' => 'Internal Firefly III Exception. See log files.', 'exception' => get_class($exception)], 500);
} }
if($exception instanceof NotFoundHttpException) { if ($exception instanceof NotFoundHttpException) {
$handler = app(GracefulNotFoundHandler::class); $handler = app(GracefulNotFoundHandler::class);
return $handler->render($request, $exception); return $handler->render($request, $exception);
} }
@ -113,13 +115,12 @@ class Handler extends ExceptionHandler
* *
* @param Exception $exception * @param Exception $exception
* *
* @throws Exception
* @return mixed|void * @return mixed|void
* *
* @throws Exception
*/ */
public function report(Exception $exception) public function report(Exception $exception)
{ {
$doMailError = config('firefly.send_error_message'); $doMailError = config('firefly.send_error_message');
// if the user wants us to mail: // if the user wants us to mail:
if (true === $doMailError if (true === $doMailError
@ -149,7 +150,7 @@ class Handler extends ExceptionHandler
// create job that will mail. // create job that will mail.
$ipAddress = Request::ip() ?? '0.0.0.0'; $ipAddress = Request::ip() ?? '0.0.0.0';
$job = new MailError($userData, (string)config('firefly.site_owner'), $ipAddress, $data); $job = new MailError($userData, (string) config('firefly.site_owner'), $ipAddress, $data);
dispatch($job); dispatch($job);
} }

View File

@ -28,6 +28,7 @@ use Exception;
/** /**
* Class NotImplementedException. * Class NotImplementedException.
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
class NotImplementedException extends Exception class NotImplementedException extends Exception

View File

@ -28,6 +28,7 @@ use Exception;
/** /**
* Class ValidationExceptions. * Class ValidationExceptions.
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
class ValidationException extends Exception class ValidationException extends Exception

View File

@ -27,7 +27,6 @@ namespace FireflyIII\Factory;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Location;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Services\Internal\Support\AccountServiceTrait; use FireflyIII\Services\Internal\Support\AccountServiceTrait;
use FireflyIII\Services\Internal\Support\LocationServiceTrait; use FireflyIII\Services\Internal\Support\LocationServiceTrait;
@ -45,18 +44,16 @@ class AccountFactory
/** @var AccountRepositoryInterface */ /** @var AccountRepositoryInterface */
protected $accountRepository; protected $accountRepository;
/** @var User */
private $user;
/** @var array */
private $canHaveVirtual;
/** @var array */ /** @var array */
protected $validAssetFields = ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth']; protected $validAssetFields = ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'];
/** @var array */ /** @var array */
protected $validCCFields = ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth']; protected $validCCFields = ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'];
/** @var array */ /** @var array */
protected $validFields = ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth']; protected $validFields = ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth'];
/** @var array */
private $canHaveVirtual;
/** @var User */
private $user;
/** /**
* AccountFactory constructor. * AccountFactory constructor.
@ -75,8 +72,8 @@ class AccountFactory
/** /**
* @param array $data * @param array $data
* *
* @return Account
* @throws FireflyException * @throws FireflyException
* @return Account
*/ */
public function create(array $data): Account public function create(array $data): Account
{ {
@ -106,7 +103,7 @@ class AccountFactory
'iban' => $data['iban'], 'iban' => $data['iban'],
]; ];
$currency = $this->getCurrency((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null)); $currency = $this->getCurrency((int) ($data['currency_id'] ?? null), (string) ($data['currency_code'] ?? null));
unset($data['currency_code']); unset($data['currency_code']);
$data['currency_id'] = $currency->id; $data['currency_id'] = $currency->id;
@ -159,8 +156,8 @@ class AccountFactory
* @param string $accountName * @param string $accountName
* @param string $accountType * @param string $accountType
* *
* @return Account
* @throws FireflyException * @throws FireflyException
* @return Account
*/ */
public function findOrCreate(string $accountName, string $accountType): Account public function findOrCreate(string $accountName, string $accountType): Account
{ {
@ -197,7 +194,7 @@ class AccountFactory
} }
/** /**
* @param int|null $accountTypeId * @param int|null $accountTypeId
* @param null|string $accountType * @param null|string $accountType
* *
* @return AccountType|null * @return AccountType|null
@ -205,7 +202,7 @@ class AccountFactory
*/ */
protected function getAccountType(?int $accountTypeId, ?string $accountType): ?AccountType protected function getAccountType(?int $accountTypeId, ?string $accountType): ?AccountType
{ {
$accountTypeId = (int)$accountTypeId; $accountTypeId = (int) $accountTypeId;
$result = null; $result = null;
if ($accountTypeId > 0) { if ($accountTypeId > 0) {
$result = AccountType::find($accountTypeId); $result = AccountType::find($accountTypeId);

View File

@ -36,6 +36,7 @@ class AccountMetaFactory
{ {
/** /**
* Constructor. * Constructor.
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function __construct() public function __construct()

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