mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Clean up old tests.
This commit is contained in:
parent
a05d006fa7
commit
81f5224b11
@ -26,10 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\DateRequest;
|
||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ApiSupport;
|
||||
@ -44,8 +43,7 @@ class AccountController extends Controller
|
||||
use ApiSupport;
|
||||
|
||||
private CurrencyRepositoryInterface $currencyRepository;
|
||||
|
||||
private AccountRepositoryInterface $repository;
|
||||
private AccountRepositoryInterface $repository;
|
||||
|
||||
|
||||
/**
|
||||
@ -71,92 +69,6 @@ class AccountController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
* @deprecated
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function expenseOverview(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for chart:
|
||||
$dates = $request->getAll();
|
||||
/** @var Carbon $start */
|
||||
$start = $dates['start'];
|
||||
/** @var Carbon $end */
|
||||
$end = $dates['end'];
|
||||
|
||||
$start->subDay();
|
||||
|
||||
// prep some vars:
|
||||
$currencies = [];
|
||||
$chartData = [];
|
||||
$tempData = [];
|
||||
|
||||
// grab all accounts and names
|
||||
$accounts = $this->repository->getAccountsByType([AccountType::EXPENSE]);
|
||||
$accountNames = $this->extractNames($accounts);
|
||||
$startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start);
|
||||
$endBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $end);
|
||||
|
||||
// loop the end balances. This is an array for each account ($expenses)
|
||||
foreach ($endBalances as $accountId => $expenses) {
|
||||
$accountId = (int) $accountId;
|
||||
// loop each expense entry (each entry can be a different currency).
|
||||
foreach ($expenses as $currencyId => $endAmount) {
|
||||
$currencyId = (int) $currencyId;
|
||||
|
||||
// see if there is an accompanying start amount.
|
||||
// grab the difference and find the currency.
|
||||
$startAmount = $startBalances[$accountId][$currencyId] ?? '0';
|
||||
$diff = bcsub($endAmount, $startAmount);
|
||||
$currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId);
|
||||
if (0 !== bccomp($diff, '0')) {
|
||||
// store the values in a temporary array.
|
||||
$tempData[] = [
|
||||
'name' => $accountNames[$accountId],
|
||||
'difference' => $diff,
|
||||
'diff_float' => (float) $diff,
|
||||
'currency_id' => $currencyId,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort temp array by amount.
|
||||
$amounts = array_column($tempData, 'diff_float');
|
||||
array_multisort($amounts, SORT_DESC, $tempData);
|
||||
|
||||
// loop all found currencies and build the data array for the chart.
|
||||
/**
|
||||
* @var int $currencyId
|
||||
* @var TransactionCurrency $currency
|
||||
*/
|
||||
foreach ($currencies as $currencyId => $currency) {
|
||||
$currentSet = [
|
||||
'label' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $this->expandNames($tempData),
|
||||
];
|
||||
$chartData[$currencyId] = $currentSet;
|
||||
}
|
||||
|
||||
// loop temp data and place data in correct array:
|
||||
foreach ($tempData as $entry) {
|
||||
$currencyId = $entry['currency_id'];
|
||||
$name = $entry['name'];
|
||||
$chartData[$currencyId]['entries'][$name] = round((float) $entry['difference'], $chartData[$currencyId]['currency_decimal_places']);
|
||||
}
|
||||
$chartData = array_values($chartData);
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
@ -193,7 +105,7 @@ class AccountController extends Controller
|
||||
}
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_id' => (string)$currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
@ -206,11 +118,11 @@ class AccountController extends Controller
|
||||
/** @var Carbon $currentStart */
|
||||
$currentStart = clone $start;
|
||||
$range = app('steam')->balanceInRange($account, $start, clone $end);
|
||||
$previous = round((float) array_values($range)[0], 12);
|
||||
$previous = round((float)array_values($range)[0], 12);
|
||||
while ($currentStart <= $end) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->format('Y-m-d');
|
||||
$balance = array_key_exists($format, $range) ? round((float) $range[$format], 12) : $previous;
|
||||
$balance = array_key_exists($format, $range) ? round((float)$range[$format], 12) : $previous;
|
||||
$previous = $balance;
|
||||
$currentStart->addDay();
|
||||
$currentSet['entries'][$label] = $balance;
|
||||
@ -220,91 +132,4 @@ class AccountController extends Controller
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
* @deprecated
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function revenueOverview(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for chart:
|
||||
$dates = $request->getAll();
|
||||
/** @var Carbon $start */
|
||||
$start = $dates['start'];
|
||||
/** @var Carbon $end */
|
||||
$end = $dates['end'];
|
||||
|
||||
$start->subDay();
|
||||
|
||||
// prep some vars:
|
||||
$currencies = [];
|
||||
$chartData = [];
|
||||
$tempData = [];
|
||||
|
||||
// grab all accounts and names
|
||||
$accounts = $this->repository->getAccountsByType([AccountType::REVENUE]);
|
||||
$accountNames = $this->extractNames($accounts);
|
||||
$startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start);
|
||||
$endBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $end);
|
||||
|
||||
// loop the end balances. This is an array for each account ($expenses)
|
||||
foreach ($endBalances as $accountId => $expenses) {
|
||||
$accountId = (int) $accountId;
|
||||
// loop each expense entry (each entry can be a different currency).
|
||||
foreach ($expenses as $currencyId => $endAmount) {
|
||||
$currencyId = (int) $currencyId;
|
||||
|
||||
// see if there is an accompanying start amount.
|
||||
// grab the difference and find the currency.
|
||||
$startAmount = $startBalances[$accountId][$currencyId] ?? '0';
|
||||
$diff = bcsub($endAmount, $startAmount);
|
||||
$currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId);
|
||||
if (0 !== bccomp($diff, '0')) {
|
||||
// store the values in a temporary array.
|
||||
$tempData[] = [
|
||||
'name' => $accountNames[$accountId],
|
||||
'difference' => bcmul($diff, '-1'),
|
||||
// For some reason this line is never covered in code coverage:
|
||||
'diff_float' => ((float) $diff) * -1, // @codeCoverageIgnore
|
||||
'currency_id' => $currencyId,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort temp array by amount.
|
||||
$amounts = array_column($tempData, 'diff_float');
|
||||
array_multisort($amounts, SORT_DESC, $tempData);
|
||||
|
||||
// loop all found currencies and build the data array for the chart.
|
||||
/**
|
||||
* @var int $currencyId
|
||||
* @var TransactionCurrency $currency
|
||||
*/
|
||||
foreach ($currencies as $currencyId => $currency) {
|
||||
$currentSet = [
|
||||
'label' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $this->expandNames($tempData),
|
||||
];
|
||||
$chartData[$currencyId] = $currentSet;
|
||||
}
|
||||
|
||||
// loop temp data and place data in correct array:
|
||||
foreach ($tempData as $entry) {
|
||||
$currencyId = $entry['currency_id'];
|
||||
$name = $entry['name'];
|
||||
$chartData[$currencyId]['entries'][$name] = round((float) $entry['difference'], $chartData[$currencyId]['currency_decimal_places']);
|
||||
}
|
||||
$chartData = array_values($chartData);
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,115 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AvailableBudgetController.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\Controllers\Chart;
|
||||
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class AvailableBudgetController
|
||||
*/
|
||||
class AvailableBudgetController extends Controller
|
||||
{
|
||||
private OperationsRepositoryInterface $opsRepository;
|
||||
private BudgetRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* AvailableBudgetController constructor.
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->opsRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AvailableBudget $availableBudget
|
||||
* @deprecated
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function overview(AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$currency = $availableBudget->transactionCurrency;
|
||||
$budgets = $this->repository->getActiveBudgets();
|
||||
$newBudgetInformation = $this->opsRepository->sumExpenses($availableBudget->start_date, $availableBudget->end_date, null, $budgets);
|
||||
$spent = '0';
|
||||
|
||||
foreach ($newBudgetInformation as $currencyId => $info) {
|
||||
if ($currencyId === (int) $availableBudget->transaction_currency_id) {
|
||||
$spent = $info['sum'];
|
||||
}
|
||||
}
|
||||
|
||||
$left = bcadd($availableBudget->amount, $spent);
|
||||
// left less than zero? Set to zero.
|
||||
if (-1 === bccomp($left, '0')) {
|
||||
$left = '0';
|
||||
}
|
||||
|
||||
$chartData = [
|
||||
[
|
||||
'label' => trans('firefly.spent'),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'pie',
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [$spent * -1],
|
||||
],
|
||||
[
|
||||
'label' => trans('firefly.left'),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'line', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [round((float) $left, $currency->decimal_places)],
|
||||
],
|
||||
];
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetController.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\DateRequest;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class BudgetController
|
||||
*/
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
private BudgetLimitRepositoryInterface $blRepository;
|
||||
|
||||
private OperationsRepositoryInterface $opsRepository;
|
||||
|
||||
private BudgetRepositoryInterface $repository;
|
||||
|
||||
|
||||
/**
|
||||
* BudgetController constructor.
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* [
|
||||
* 'label' => 'label for entire set'
|
||||
* 'currency_id' => 0,
|
||||
* 'currency_code' => 'EUR',
|
||||
* 'currency_symbol' => '$',
|
||||
* 'currency_decimal_places' => 2,
|
||||
* 'type' => 'bar', // line, area or bar
|
||||
* 'yAxisID' => 0, // 0, 1, 2
|
||||
* 'entries' => ['a' => 1, 'b' => 4],
|
||||
* ],
|
||||
*
|
||||
* @param DateRequest $request
|
||||
* @deprecated
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
{
|
||||
$dates = $request->getAll();
|
||||
$budgets = $this->repository->getActiveBudgets();
|
||||
$budgetNames = [];
|
||||
$currencyNames = [];
|
||||
$sets = [];
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
$expenses = $this->getExpenses($budget, $dates['start'], $dates['end']);
|
||||
$expenses = $this->filterNulls($expenses);
|
||||
foreach ($expenses as $set) {
|
||||
$budgetNames[] = $set['budget_name'];
|
||||
$currencyNames[] = $set['currency_name'];
|
||||
$sets[] = $set;
|
||||
}
|
||||
}
|
||||
$budgetNames = array_unique($budgetNames);
|
||||
$currencyNames = array_unique($currencyNames);
|
||||
$basic = $this->createSets($budgetNames, $currencyNames);
|
||||
$filled = $this->fillSets($basic, $sets);
|
||||
$keys = array_values($filled);
|
||||
|
||||
return response()->json($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $limits
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
protected function getExpenses(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
|
||||
if (0 === $limits->count()) {
|
||||
return $this->getExpenseInRange($budget, $start, $end);
|
||||
}
|
||||
$arr = [];
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
$arr[] = $this->getExpensesForLimit($limit);
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
private function getExpenseInRange(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$budget]), null);
|
||||
$return = [];
|
||||
/** @var array $set */
|
||||
foreach ($spent as $set) {
|
||||
$current = [
|
||||
'label' => sprintf('%s (%s)', $budget->name, $set['currency_name']),
|
||||
'budget_name' => $budget->name,
|
||||
'start_date' => $start->format('Y-m-d'),
|
||||
'end_date' => $end->format('Y-m-d'),
|
||||
'currency_id' => (int) $set['currency_id'],
|
||||
'currency_code' => $set['currency_code'],
|
||||
'currency_name' => $set['currency_name'],
|
||||
'currency_symbol' => $set['currency_symbol'],
|
||||
'currency_decimal_places' => (int) $set['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar,
|
||||
'entries' => [],
|
||||
];
|
||||
$sumSpent = bcmul($set['sum'], '-1'); // spent
|
||||
$current['entries']['spent'] = $sumSpent;
|
||||
$current['entries']['amount'] = '0';
|
||||
$current['entries']['spent_capped'] = $sumSpent;
|
||||
$current['entries']['left'] = '0';
|
||||
$current['entries']['overspent'] = '0';
|
||||
$return[] = $current;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BudgetLimit $limit
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
private function getExpensesForLimit(BudgetLimit $limit): array
|
||||
{
|
||||
$budget = $limit->budget;
|
||||
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $limit->transactionCurrency);
|
||||
$currency = $limit->transactionCurrency;
|
||||
// when limited to a currency, the count is always one. Or it's empty.
|
||||
$set = array_shift($spent);
|
||||
if (null === $set) {
|
||||
return [];
|
||||
}
|
||||
$return = [
|
||||
'label' => sprintf('%s (%s)', $budget->name, $set['currency_name']),
|
||||
'budget_name' => $budget->name,
|
||||
'start_date' => $limit->start_date->format('Y-m-d'),
|
||||
'end_date' => $limit->end_date->format('Y-m-d'),
|
||||
'currency_id' => (int) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => (int) $currency->decimal_places,
|
||||
'type' => 'bar', // line, area or bar,
|
||||
'entries' => [],
|
||||
];
|
||||
$sumSpent = bcmul($set['sum'], '-1'); // spent
|
||||
$return['entries']['spent'] = $sumSpent;
|
||||
$return['entries']['amount'] = $limit->amount;
|
||||
$return['entries']['spent_capped'] = 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent;
|
||||
$return['entries']['left'] = 1 === bccomp($limit->amount, $sumSpent) ? bcadd($set['sum'], $limit->amount) : '0'; // left
|
||||
$return['entries']['overspent'] = 1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($set['sum'], $limit->amount), '-1'); // overspent
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $expenses
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
private function filterNulls(array $expenses): array
|
||||
{
|
||||
$return = [];
|
||||
/** @var array|null $arr */
|
||||
foreach ($expenses as $arr) {
|
||||
if ([] !== $arr) {
|
||||
$return[] = $arr;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $budgetNames
|
||||
* @param array $currencyNames
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
private function createSets(array $budgetNames, array $currencyNames): array
|
||||
{
|
||||
$return = [];
|
||||
foreach ($currencyNames as $currencyName) {
|
||||
$entries = [];
|
||||
foreach ($budgetNames as $budgetName) {
|
||||
$label = sprintf('%s (%s)', $budgetName, $currencyName);
|
||||
$entries[$label] = '0';
|
||||
}
|
||||
|
||||
// left
|
||||
$return['left'] = [
|
||||
'label' => sprintf('%s (%s)', trans('firefly.left'), $currencyName),
|
||||
'data_type' => 'left',
|
||||
'currency_name' => $currencyName,
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $entries,
|
||||
];
|
||||
|
||||
// spent_capped
|
||||
$return['spent_capped'] = [
|
||||
'label' => sprintf('%s (%s)', trans('firefly.spent'), $currencyName),
|
||||
'data_type' => 'spent_capped',
|
||||
'currency_name' => $currencyName,
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $entries,
|
||||
];
|
||||
|
||||
// overspent
|
||||
$return['overspent'] = [
|
||||
'label' => sprintf('%s (%s)', trans('firefly.overspent'), $currencyName),
|
||||
'data_type' => 'overspent',
|
||||
'currency_name' => $currencyName,
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $entries,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $basic
|
||||
* @param array $sets
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
private function fillSets(array $basic, array $sets): array
|
||||
{
|
||||
foreach ($sets as $set) {
|
||||
$label = $set['label'];
|
||||
$basic['spent_capped']['entries'][$label] = $set['entries']['spent_capped'];
|
||||
$basic['left']['entries'][$label] = $set['entries']['left'];
|
||||
$basic['overspent']['entries'][$label] = $set['entries']['overspent'];
|
||||
}
|
||||
|
||||
return $basic;
|
||||
}
|
||||
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CategoryController.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\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\DateRequest;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\NoCategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\OperationsRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class CategoryController
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
private CategoryRepositoryInterface $categoryRepository;
|
||||
private NoCategoryRepositoryInterface $noCatRepository;
|
||||
private OperationsRepositoryInterface $opsRepository;
|
||||
private array $categories;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->categoryRepository = app(CategoryRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$this->noCatRepository = app(NoCategoryRepositoryInterface::class);
|
||||
$this->categories = [];
|
||||
$this->categoryRepository->setUser($user);
|
||||
$this->opsRepository->setUser($user);
|
||||
$this->noCatRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
* @deprecated
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for chart:
|
||||
$dates = $request->getAll();
|
||||
/** @var Carbon $start */
|
||||
$start = $dates['start'];
|
||||
/** @var Carbon $end */
|
||||
$end = $dates['end'];
|
||||
|
||||
$tempData = [];
|
||||
$spentWith = $this->opsRepository->listExpenses($start, $end);
|
||||
$spentWithout = $this->noCatRepository->listExpenses($start, $end);
|
||||
|
||||
/** @var array $set */
|
||||
foreach ([$spentWith, $spentWithout,] as $set) {
|
||||
$tempData = $this->processArray($tempData, $set);
|
||||
}
|
||||
|
||||
$chartData = $this->sortArray($tempData);
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tempData
|
||||
* @param array $set
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
private function processArray(array $tempData, array $set): array
|
||||
{
|
||||
foreach ($set as $currency) {
|
||||
foreach ($currency['categories'] as $category) {
|
||||
$this->categories[] = $category['name'];
|
||||
$outKey = sprintf('%d-e', $currency['currency_id']);
|
||||
$tempData[$outKey] = $tempData[$outKey] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'currency_code' => $currency['currency_code'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [],
|
||||
];
|
||||
|
||||
foreach ($category['transaction_journals'] as $journal) {
|
||||
// is it expense or income?
|
||||
$currentKey = sprintf('%d-%s', $currency['currency_id'], 'e');
|
||||
$name = $category['name'];
|
||||
$tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
|
||||
$tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $tempData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tempData
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
private function sortArray(array $tempData): array
|
||||
{
|
||||
// re-sort every spent array and add 0 for missing entries.
|
||||
foreach ($tempData as $index => $set) {
|
||||
$oldSet = $set['entries'];
|
||||
$newSet = [];
|
||||
foreach ($this->categories as $category) {
|
||||
$value = $oldSet[$category] ?? '0';
|
||||
$value = -1 === bccomp($value, '0') ? bcmul($value, '-1') : $value;
|
||||
$newSet[$category] = $value;
|
||||
}
|
||||
$tempData[$index]['entries'] = $newSet;
|
||||
}
|
||||
|
||||
return array_values($tempData);
|
||||
}
|
||||
}
|
@ -73,14 +73,14 @@ class UpdateController extends Controller
|
||||
public function update(UpdateRequest $request, Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$category = $this->repository->update($recurrence, $data);
|
||||
$recurrence = $this->repository->update($recurrence, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'recurrences');
|
||||
$resource = new Item($recurrence, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
||||
|
@ -43,7 +43,6 @@ class UpdateRequest extends FormRequest
|
||||
use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData, ChecksLogin;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
@ -51,46 +50,46 @@ class UpdateRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = null;
|
||||
$applyRules = null;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
// this is the way:
|
||||
$fields = [
|
||||
'title' => ['title', 'string'],
|
||||
'description' => ['description', 'string'],
|
||||
'first_date' => ['first_date', 'date'],
|
||||
'repeat_until' => ['repeat_until', 'date'],
|
||||
'nr_of_repetitions' => ['nr_of_repetitions', 'integer'],
|
||||
'apply_rules' => ['apply_rules', 'boolean'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'notes' => ['notes', 'string'],
|
||||
];
|
||||
$reps = $this->getRepetitionData();
|
||||
$transactions = $this->getTransactionData();
|
||||
$return = [
|
||||
'recurrence' => $this->getAllData($fields),
|
||||
];
|
||||
if (null !== $reps) {
|
||||
$return['repetitions'] = $reps;
|
||||
}
|
||||
if (null !== $this->get('apply_rules')) {
|
||||
$applyRules = $this->boolean('apply_rules');
|
||||
if (null !== $transactions) {
|
||||
$return['transactions'] = $transactions;
|
||||
}
|
||||
|
||||
return [
|
||||
'recurrence' => [
|
||||
'type' => $this->nullableString('type'),
|
||||
'title' => $this->nullableString('title'),
|
||||
'description' => $this->nullableString('description'),
|
||||
'first_date' => $this->date('first_date'),
|
||||
'notes' => $this->nullableNlString('notes'),
|
||||
'repeat_until' => $this->date('repeat_until'),
|
||||
'nr_of_repetitions' => $this->nullableInteger('nr_of_repetitions'),
|
||||
'apply_rules' => $applyRules,
|
||||
'active' => $active,
|
||||
],
|
||||
'transactions' => $this->getTransactionData(),
|
||||
'repetitions' => $this->getRepetitionData(),
|
||||
];
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
||||
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||
*
|
||||
* @return array
|
||||
* @return array|null
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
private function getTransactionData(): ?array
|
||||
{
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return [];
|
||||
return null;
|
||||
}
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
@ -103,25 +102,36 @@ class UpdateRequest extends FormRequest
|
||||
/**
|
||||
* Returns the repetition data as it is found in the submitted data.
|
||||
*
|
||||
* @return array
|
||||
* @return array|null
|
||||
*/
|
||||
private function getRepetitionData(): array
|
||||
private function getRepetitionData(): ?array
|
||||
{
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return [];
|
||||
return null;
|
||||
}
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$return[] = [
|
||||
'type' => $repetition['type'],
|
||||
'moment' => $repetition['moment'],
|
||||
'skip' => (int) $repetition['skip'],
|
||||
'weekend' => (int) $repetition['weekend'],
|
||||
];
|
||||
$current = [];
|
||||
if(array_key_exists('type', $repetition)) {
|
||||
$current['type'] = $repetition['type'];
|
||||
}
|
||||
|
||||
if(array_key_exists('moment', $repetition)) {
|
||||
$current['moment'] = $repetition['moment'];
|
||||
}
|
||||
|
||||
if(array_key_exists('skip', $repetition)) {
|
||||
$current['skip'] = (int)$repetition['skip'];
|
||||
}
|
||||
|
||||
if(array_key_exists('weekend', $repetition)) {
|
||||
$current['weekend'] = (int) $repetition['weekend'];
|
||||
}
|
||||
$return[] = $current;
|
||||
}
|
||||
|
||||
return $return;
|
||||
@ -138,7 +148,6 @@ class UpdateRequest extends FormRequest
|
||||
$recurrence = $this->route()->parameter('recurrence');
|
||||
|
||||
return [
|
||||
'type' => 'in:withdrawal,transfer,deposit',
|
||||
'title' => sprintf('between:1,255|uniqueObjectForUser:recurrences,title,%d', $recurrence->id),
|
||||
'description' => 'between:1,65000',
|
||||
'first_date' => 'date',
|
||||
@ -148,11 +157,11 @@ class UpdateRequest extends FormRequest
|
||||
'nr_of_repetitions' => 'numeric|between:1,31',
|
||||
'repetitions.*.type' => 'in:daily,weekly,ndom,monthly,yearly',
|
||||
'repetitions.*.moment' => 'between:0,10',
|
||||
'repetitions.*.skip' => 'required|numeric|between:0,31',
|
||||
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
|
||||
'repetitions.*.skip' => 'numeric|between:0,31',
|
||||
'repetitions.*.weekend' => 'numeric|min:1|max:4',
|
||||
|
||||
'transactions.*.description' => 'required|between:1,255',
|
||||
'transactions.*.amount' => 'required|numeric|gt:0',
|
||||
'transactions.*.description' => 'between:1,255',
|
||||
'transactions.*.amount' => 'numeric|gt:0',
|
||||
'transactions.*.foreign_amount' => 'numeric|gt:0',
|
||||
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
@ -186,9 +195,9 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->validateOneRecurrenceTransaction($validator);
|
||||
$this->validateOneRepetitionUpdate($validator);
|
||||
$this->validateRecurrenceRepetition($validator);
|
||||
//$this->validateOneRecurrenceTransaction($validator);
|
||||
//$this->validateOneRepetitionUpdate($validator);
|
||||
//$this->validateRecurrenceRepetition($validator);
|
||||
$this->validateRepetitionMoment($validator);
|
||||
$this->validateForeignCurrencyInformation($validator);
|
||||
$this->valUpdateAccountInfo($validator);
|
||||
|
@ -42,7 +42,7 @@ class MigrateRecurrenceType extends Command
|
||||
|
||||
$this->migrateTypes();
|
||||
|
||||
//$this->markAsExecuted();
|
||||
$this->markAsExecuted();
|
||||
|
||||
$end = round(microtime(true) - $start, 2);
|
||||
$this->info(sprintf('Update recurring transaction types in %s seconds.', $end));
|
||||
|
@ -570,7 +570,6 @@ class RecurringRepository implements RecurringRepositoryInterface
|
||||
{
|
||||
/** @var RecurrenceUpdateService $service */
|
||||
$service = app(RecurrenceUpdateService::class);
|
||||
|
||||
return $service->update($recurrence, $data);
|
||||
}
|
||||
|
||||
|
@ -108,31 +108,31 @@ class AccountUpdateService
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function updateLocation(Account $account, array $data): void
|
||||
private function updateAccount(Account $account, array $data): Account
|
||||
{
|
||||
$updateLocation = $data['update_location'] ?? false;
|
||||
// location must be updated?
|
||||
if (true === $updateLocation) {
|
||||
// if all set to NULL, delete
|
||||
if (null === $data['latitude'] && null === $data['longitude'] && null === $data['zoom_level']) {
|
||||
$account->locations()->delete();
|
||||
}
|
||||
// update the account itself:
|
||||
$account->name = $data['name'] ?? $account->name;
|
||||
$account->active = $data['active'] ?? $account->active;
|
||||
$account->iban = $data['iban'] ?? $account->iban;
|
||||
|
||||
// otherwise, update or create.
|
||||
if (!(null === $data['latitude'] && null === $data['longitude'] && null === $data['zoom_level'])) {
|
||||
$location = $this->accountRepository->getLocation($account);
|
||||
if (null === $location) {
|
||||
$location = new Location;
|
||||
$location->locatable()->associate($account);
|
||||
}
|
||||
|
||||
$location->latitude = $data['latitude'] ?? config('firefly.default_location.latitude');
|
||||
$location->longitude = $data['longitude'] ?? config('firefly.default_location.longitude');
|
||||
$location->zoom_level = $data['zoom_level'] ?? config('firefly.default_location.zoom_level');
|
||||
$location->save();
|
||||
}
|
||||
// liability stuff:
|
||||
$liabilityType = $data['liability_type'] ?? '';
|
||||
if ($this->isLiability($account) && $this->isLiabilityType($liabilityType)) {
|
||||
$type = $this->getAccountType($liabilityType);
|
||||
$account->account_type_id = $type->id;
|
||||
}
|
||||
|
||||
// update virtual balance (could be set to zero if empty string).
|
||||
if (null !== $data['virtual_balance']) {
|
||||
$account->virtual_balance = '' === trim($data['virtual_balance']) ? '0' : $data['virtual_balance'];
|
||||
}
|
||||
|
||||
$account->save();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,93 +169,6 @@ class AccountUpdateService
|
||||
return AccountType::whereType($type)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function updateAccount(Account $account, array $data): Account
|
||||
{
|
||||
// update the account itself:
|
||||
$account->name = $data['name'] ?? $account->name;
|
||||
$account->active = $data['active'] ?? $account->active;
|
||||
$account->iban = $data['iban'] ?? $account->iban;
|
||||
|
||||
// liability stuff:
|
||||
$liabilityType = $data['liability_type'] ?? '';
|
||||
if ($this->isLiability($account) && $this->isLiabilityType($liabilityType)) {
|
||||
$type = $this->getAccountType($liabilityType);
|
||||
$account->account_type_id = $type->id;
|
||||
}
|
||||
|
||||
// update virtual balance (could be set to zero if empty string).
|
||||
if (null !== $data['virtual_balance']) {
|
||||
$account->virtual_balance = '' === trim($data['virtual_balance']) ? '0' : $data['virtual_balance'];
|
||||
}
|
||||
|
||||
$account->save();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
private function updatePreferences(Account $account, array $data): void
|
||||
{
|
||||
Log::debug(sprintf('Now in updatePreferences(#%d)', $account->id));
|
||||
if (array_key_exists('active', $data) && (false === $data['active'] || 0 === $data['active'])) {
|
||||
Log::debug('Account was marked as inactive.');
|
||||
$preference = app('preferences')->getForUser($account->user, 'frontpageAccounts');
|
||||
if (null !== $preference) {
|
||||
$removeAccountId = (int)$account->id;
|
||||
$array = $preference->data;
|
||||
Log::debug('Current list of accounts: ', $array);
|
||||
Log::debug(sprintf('Going to remove account #%d', $removeAccountId));
|
||||
$filtered = array_filter(
|
||||
$array, function ($accountId) use ($removeAccountId) {
|
||||
return (int)$accountId !== $removeAccountId;
|
||||
}
|
||||
);
|
||||
Log::debug('Left with accounts', array_values($filtered));
|
||||
app('preferences')->setForUser($account->user, 'frontpageAccounts', array_values($filtered));
|
||||
app('preferences')->forget($account->user, 'frontpageAccounts');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug("Found no frontpageAccounts preference, do nothing.");
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('Account was not marked as inactive, do nothing.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
private function updateOpeningBalance(Account $account, array $data): void
|
||||
{
|
||||
|
||||
// has valid initial balance (IB) data?
|
||||
$type = $account->accountType;
|
||||
// if it can have a virtual balance, it can also have an opening balance.
|
||||
|
||||
if (in_array($type->type, $this->canHaveVirtual, true)) {
|
||||
|
||||
// check if is submitted as empty, that makes it valid:
|
||||
if ($this->validOBData($data) && !$this->isEmptyOBData($data)) {
|
||||
$this->updateOBGroup($account, $data);
|
||||
}
|
||||
|
||||
if (!$this->validOBData($data) && $this->isEmptyOBData($data)) {
|
||||
$this->deleteOBGroup($account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
@ -314,4 +227,91 @@ class AccountUpdateService
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
private function updateLocation(Account $account, array $data): void
|
||||
{
|
||||
$updateLocation = $data['update_location'] ?? false;
|
||||
// location must be updated?
|
||||
if (true === $updateLocation) {
|
||||
// if all set to NULL, delete
|
||||
if (null === $data['latitude'] && null === $data['longitude'] && null === $data['zoom_level']) {
|
||||
$account->locations()->delete();
|
||||
}
|
||||
|
||||
// otherwise, update or create.
|
||||
if (!(null === $data['latitude'] && null === $data['longitude'] && null === $data['zoom_level'])) {
|
||||
$location = $this->accountRepository->getLocation($account);
|
||||
if (null === $location) {
|
||||
$location = new Location;
|
||||
$location->locatable()->associate($account);
|
||||
}
|
||||
|
||||
$location->latitude = $data['latitude'] ?? config('firefly.default_location.latitude');
|
||||
$location->longitude = $data['longitude'] ?? config('firefly.default_location.longitude');
|
||||
$location->zoom_level = $data['zoom_level'] ?? config('firefly.default_location.zoom_level');
|
||||
$location->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
private function updateOpeningBalance(Account $account, array $data): void
|
||||
{
|
||||
|
||||
// has valid initial balance (IB) data?
|
||||
$type = $account->accountType;
|
||||
// if it can have a virtual balance, it can also have an opening balance.
|
||||
|
||||
if (in_array($type->type, $this->canHaveVirtual, true)) {
|
||||
|
||||
// check if is submitted as empty, that makes it valid:
|
||||
if ($this->validOBData($data) && !$this->isEmptyOBData($data)) {
|
||||
$this->updateOBGroup($account, $data);
|
||||
}
|
||||
|
||||
if (!$this->validOBData($data) && $this->isEmptyOBData($data)) {
|
||||
$this->deleteOBGroup($account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
private function updatePreferences(Account $account, array $data): void
|
||||
{
|
||||
Log::debug(sprintf('Now in updatePreferences(#%d)', $account->id));
|
||||
if (array_key_exists('active', $data) && (false === $data['active'] || 0 === $data['active'])) {
|
||||
Log::debug('Account was marked as inactive.');
|
||||
$preference = app('preferences')->getForUser($account->user, 'frontpageAccounts');
|
||||
if (null !== $preference) {
|
||||
$removeAccountId = (int)$account->id;
|
||||
$array = $preference->data;
|
||||
Log::debug('Current list of accounts: ', $array);
|
||||
Log::debug(sprintf('Going to remove account #%d', $removeAccountId));
|
||||
$filtered = array_filter(
|
||||
$array, function ($accountId) use ($removeAccountId) {
|
||||
return (int)$accountId !== $removeAccountId;
|
||||
}
|
||||
);
|
||||
Log::debug('Left with accounts', array_values($filtered));
|
||||
app('preferences')->setForUser($account->user, 'frontpageAccounts', array_values($filtered));
|
||||
app('preferences')->forget($account->user, 'frontpageAccounts');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug("Found no frontpageAccounts preference, do nothing.");
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('Account was not marked as inactive, do nothing.');
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +136,69 @@ class BillUpdateService
|
||||
return $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param array $data
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
private function updateBillProperties(Bill $bill, array $data): Bill
|
||||
{
|
||||
|
||||
if (isset($data['name']) && '' !== (string)$data['name']) {
|
||||
$bill->name = $data['name'];
|
||||
}
|
||||
|
||||
if (isset($data['amount_min']) && '' !== (string)$data['amount_min']) {
|
||||
$bill->amount_min = $data['amount_min'];
|
||||
}
|
||||
if (isset($data['amount_max']) && '' !== (string)$data['amount_max']) {
|
||||
$bill->amount_max = $data['amount_max'];
|
||||
}
|
||||
if (isset($data['date']) && '' !== (string)$data['date']) {
|
||||
$bill->date = $data['date'];
|
||||
}
|
||||
if (isset($data['repeat_freq']) && '' !== (string)$data['repeat_freq']) {
|
||||
$bill->repeat_freq = $data['repeat_freq'];
|
||||
}
|
||||
if (isset($data['skip']) && '' !== (string)$data['skip']) {
|
||||
$bill->skip = $data['skip'];
|
||||
}
|
||||
if (isset($data['active']) && is_bool($data['active'])) {
|
||||
$bill->active = $data['active'];
|
||||
}
|
||||
|
||||
$bill->match = 'EMPTY';
|
||||
$bill->automatch = true;
|
||||
$bill->save();
|
||||
|
||||
return $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param int $oldOrder
|
||||
* @param int $newOrder
|
||||
*/
|
||||
private function updateOrder(Bill $bill, int $oldOrder, int $newOrder): void
|
||||
{
|
||||
if ($newOrder > $oldOrder) {
|
||||
$this->user->bills()->where('order', '<=', $newOrder)->where('order', '>', $oldOrder)
|
||||
->where('bills.id', '!=', $bill->id)
|
||||
->update(['order' => DB::raw('bills.order-1')]);
|
||||
$bill->order = $newOrder;
|
||||
$bill->save();
|
||||
}
|
||||
if ($newOrder < $oldOrder) {
|
||||
$this->user->bills()->where('order', '>=', $newOrder)->where('order', '<', $oldOrder)
|
||||
->where('bills.id', '!=', $bill->id)
|
||||
->update(['order' => DB::raw('bills.order+1')]);
|
||||
$bill->order = $newOrder;
|
||||
$bill->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param array $oldData
|
||||
@ -195,7 +258,6 @@ class BillUpdateService
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Rule $rule
|
||||
* @param string $key
|
||||
@ -206,67 +268,4 @@ class BillUpdateService
|
||||
{
|
||||
return $rule->ruleTriggers()->where('trigger_type', $key)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param int $oldOrder
|
||||
* @param int $newOrder
|
||||
*/
|
||||
private function updateOrder(Bill $bill, int $oldOrder, int $newOrder): void
|
||||
{
|
||||
if ($newOrder > $oldOrder) {
|
||||
$this->user->bills()->where('order', '<=', $newOrder)->where('order', '>', $oldOrder)
|
||||
->where('bills.id', '!=', $bill->id)
|
||||
->update(['order' => DB::raw('bills.order-1')]);
|
||||
$bill->order = $newOrder;
|
||||
$bill->save();
|
||||
}
|
||||
if ($newOrder < $oldOrder) {
|
||||
$this->user->bills()->where('order', '>=', $newOrder)->where('order', '<', $oldOrder)
|
||||
->where('bills.id', '!=', $bill->id)
|
||||
->update(['order' => DB::raw('bills.order+1')]);
|
||||
$bill->order = $newOrder;
|
||||
$bill->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param array $data
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
private function updateBillProperties(Bill $bill, array $data): Bill
|
||||
{
|
||||
|
||||
if (isset($data['name']) && '' !== (string)$data['name']) {
|
||||
$bill->name = $data['name'];
|
||||
}
|
||||
|
||||
if (isset($data['amount_min']) && '' !== (string)$data['amount_min']) {
|
||||
$bill->amount_min = $data['amount_min'];
|
||||
}
|
||||
if (isset($data['amount_max']) && '' !== (string)$data['amount_max']) {
|
||||
$bill->amount_max = $data['amount_max'];
|
||||
}
|
||||
if (isset($data['date']) && '' !== (string)$data['date']) {
|
||||
$bill->date = $data['date'];
|
||||
}
|
||||
if (isset($data['repeat_freq']) && '' !== (string)$data['repeat_freq']) {
|
||||
$bill->repeat_freq = $data['repeat_freq'];
|
||||
}
|
||||
if (isset($data['skip']) && '' !== (string)$data['skip']) {
|
||||
$bill->skip = $data['skip'];
|
||||
}
|
||||
if (isset($data['active']) && is_bool($data['active'])) {
|
||||
$bill->active = $data['active'];
|
||||
}
|
||||
|
||||
$bill->match = 'EMPTY';
|
||||
$bill->automatch = true;
|
||||
$bill->save();
|
||||
|
||||
return $bill;
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Internal\Update;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\RecurrenceTransactionMeta;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use Log;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class CategoryUpdateService
|
||||
@ -54,6 +54,14 @@ class CategoryUpdateService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $user
|
||||
*/
|
||||
public function setUser($user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param array $data
|
||||
@ -75,27 +83,6 @@ class CategoryUpdateService
|
||||
return $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $oldName
|
||||
* @param string $newName
|
||||
*/
|
||||
private function updateRuleActions(string $oldName, string $newName): void
|
||||
{
|
||||
$types = ['set_category',];
|
||||
$actions = RuleAction::leftJoin('rules', 'rules.id', '=', 'rule_actions.rule_id')
|
||||
->where('rules.user_id', $this->user->id)
|
||||
->whereIn('rule_actions.action_type', $types)
|
||||
->where('rule_actions.action_value', $oldName)
|
||||
->get(['rule_actions.*']);
|
||||
Log::debug(sprintf('Found %d actions to update.', $actions->count()));
|
||||
/** @var RuleAction $action */
|
||||
foreach ($actions as $action) {
|
||||
$action->action_value = $newName;
|
||||
$action->save();
|
||||
Log::debug(sprintf('Updated action %d: %s', $action->id, $action->action_value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $oldName
|
||||
* @param string $newName
|
||||
@ -118,11 +105,24 @@ class CategoryUpdateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $user
|
||||
* @param string $oldName
|
||||
* @param string $newName
|
||||
*/
|
||||
public function setUser($user): void
|
||||
private function updateRuleActions(string $oldName, string $newName): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$types = ['set_category',];
|
||||
$actions = RuleAction::leftJoin('rules', 'rules.id', '=', 'rule_actions.rule_id')
|
||||
->where('rules.user_id', $this->user->id)
|
||||
->whereIn('rule_actions.action_type', $types)
|
||||
->where('rule_actions.action_value', $oldName)
|
||||
->get(['rule_actions.*']);
|
||||
Log::debug(sprintf('Found %d actions to update.', $actions->count()));
|
||||
/** @var RuleAction $action */
|
||||
foreach ($actions as $action) {
|
||||
$action->action_value = $newName;
|
||||
$action->save();
|
||||
Log::debug(sprintf('Updated action %d: %s', $action->id, $action->action_value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,7 +145,7 @@ class CategoryUpdateService
|
||||
* @param Category $category
|
||||
* @param array $data
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
private function updateNotes(Category $category, array $data): void
|
||||
{
|
||||
|
@ -108,16 +108,15 @@ class GroupCloneService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournalMeta $meta
|
||||
* @param TransactionJournal $newJournal
|
||||
* @param Transaction $transaction
|
||||
* @param TransactionJournal $newJournal
|
||||
*/
|
||||
private function cloneMeta(TransactionJournalMeta $meta, TransactionJournal $newJournal): void
|
||||
private function cloneTransaction(Transaction $transaction, TransactionJournal $newJournal): void
|
||||
{
|
||||
$newMeta = $meta->replicate();
|
||||
$newMeta->transaction_journal_id = $newJournal->id;
|
||||
if ('recurrence_id' !== $newMeta->name) {
|
||||
$newMeta->save();
|
||||
}
|
||||
$newTransaction = $transaction->replicate();
|
||||
$newTransaction->transaction_journal_id = $newJournal->id;
|
||||
$newTransaction->reconciled = false;
|
||||
$newTransaction->save();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,15 +136,16 @@ class GroupCloneService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Transaction $transaction
|
||||
* @param TransactionJournal $newJournal
|
||||
* @param TransactionJournalMeta $meta
|
||||
* @param TransactionJournal $newJournal
|
||||
*/
|
||||
private function cloneTransaction(Transaction $transaction, TransactionJournal $newJournal): void
|
||||
private function cloneMeta(TransactionJournalMeta $meta, TransactionJournal $newJournal): void
|
||||
{
|
||||
$newTransaction = $transaction->replicate();
|
||||
$newTransaction->transaction_journal_id = $newJournal->id;
|
||||
$newTransaction->reconciled = false;
|
||||
$newTransaction->save();
|
||||
$newMeta = $meta->replicate();
|
||||
$newMeta->transaction_journal_id = $newJournal->id;
|
||||
if ('recurrence_id' !== $newMeta->name) {
|
||||
$newMeta->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,37 +96,6 @@ class GroupUpdateService
|
||||
return $transactionGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionGroup $transactionGroup
|
||||
* @param array $data
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function createTransactionJournal(TransactionGroup $transactionGroup, array $data): void
|
||||
{
|
||||
|
||||
$submission = [
|
||||
'transactions' => [
|
||||
$data,
|
||||
],
|
||||
];
|
||||
/** @var TransactionJournalFactory $factory */
|
||||
$factory = app(TransactionJournalFactory::class);
|
||||
$factory->setUser($transactionGroup->user);
|
||||
try {
|
||||
$collection = $factory->create($submission);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
throw new FireflyException(sprintf('Could not create new transaction journal: %s', $e->getMessage()));
|
||||
}
|
||||
$collection->each(
|
||||
function (TransactionJournal $journal) use ($transactionGroup) {
|
||||
$transactionGroup->transactionJournals()->save($journal);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update single journal.
|
||||
*
|
||||
@ -191,4 +160,35 @@ class GroupUpdateService
|
||||
return $updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionGroup $transactionGroup
|
||||
* @param array $data
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function createTransactionJournal(TransactionGroup $transactionGroup, array $data): void
|
||||
{
|
||||
|
||||
$submission = [
|
||||
'transactions' => [
|
||||
$data,
|
||||
],
|
||||
];
|
||||
/** @var TransactionJournalFactory $factory */
|
||||
$factory = app(TransactionJournalFactory::class);
|
||||
$factory->setUser($transactionGroup->user);
|
||||
try {
|
||||
$collection = $factory->create($submission);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
throw new FireflyException(sprintf('Could not create new transaction journal: %s', $e->getMessage()));
|
||||
}
|
||||
$collection->each(
|
||||
function (TransactionJournal $journal) use ($transactionGroup) {
|
||||
$transactionGroup->transactionJournals()->save($journal);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -161,47 +161,61 @@ class JournalUpdateService
|
||||
}
|
||||
|
||||
/**
|
||||
* Get destination transaction.
|
||||
*
|
||||
* @return Transaction
|
||||
* @return bool
|
||||
*/
|
||||
private function getDestinationTransaction(): Transaction
|
||||
private function hasValidAccounts(): bool
|
||||
{
|
||||
if (null === $this->destinationTransaction) {
|
||||
$this->destinationTransaction = $this->transactionJournal->transactions()->where('amount', '>', 0)->first();
|
||||
}
|
||||
|
||||
return $this->destinationTransaction;
|
||||
return $this->hasValidSourceAccount() && $this->hasValidDestinationAccount();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the current or expected type of the journal (in case of a change) based on the data in the array.
|
||||
*
|
||||
* If the array contains key 'type' and the value is correct, this is returned. Otherwise, the original type is returned.
|
||||
*
|
||||
* @return string
|
||||
* @return bool
|
||||
*/
|
||||
private function getExpectedType(): string
|
||||
private function hasValidSourceAccount(): bool
|
||||
{
|
||||
Log::debug('Now in getExpectedType()');
|
||||
if ($this->hasFields(['type'])) {
|
||||
return ucfirst('opening-balance' === $this->data['type'] ? 'opening balance' : $this->data['type']);
|
||||
Log::debug('Now in hasValidSourceAccount().');
|
||||
$sourceId = $this->data['source_id'] ?? null;
|
||||
$sourceName = $this->data['source_name'] ?? null;
|
||||
|
||||
if (!$this->hasFields(['source_id', 'source_name'])) {
|
||||
$origSourceAccount = $this->getOriginalSourceAccount();
|
||||
$sourceId = $origSourceAccount->id;
|
||||
$sourceName = $origSourceAccount->name;
|
||||
}
|
||||
|
||||
return $this->transactionJournal->transactionType->type;
|
||||
// make new account validator.
|
||||
$expectedType = $this->getExpectedType();
|
||||
Log::debug(sprintf('Expected type (new or unchanged) is %s', $expectedType));
|
||||
|
||||
// make a new validator.
|
||||
/** @var AccountValidator $validator */
|
||||
$validator = app(AccountValidator::class);
|
||||
$validator->setTransactionType($expectedType);
|
||||
$validator->setUser($this->transactionJournal->user);
|
||||
|
||||
$result = $validator->validateSource($sourceId, $sourceName, null);
|
||||
Log::debug(sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true)));
|
||||
|
||||
// TODO typeOverrule: the account validator may have another opinion on the transaction type.
|
||||
|
||||
// validate submitted info:
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account
|
||||
* @param array $fields
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function getOriginalDestinationAccount(): Account
|
||||
private function hasFields(array $fields): bool
|
||||
{
|
||||
if (null === $this->destinationAccount) {
|
||||
$destination = $this->getDestinationTransaction();
|
||||
$this->destinationAccount = $destination->account;
|
||||
foreach ($fields as $field) {
|
||||
if (array_key_exists($field, $this->data)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->destinationAccount;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -231,96 +245,20 @@ class JournalUpdateService
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a validation and returns the destination account. This method will break if the dest isn't really valid.
|
||||
* This method returns the current or expected type of the journal (in case of a change) based on the data in the array.
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function getValidDestinationAccount(): Account
|
||||
{
|
||||
Log::debug('Now in getValidDestinationAccount().');
|
||||
|
||||
if (!$this->hasFields(['destination_id', 'destination_name'])) {
|
||||
return $this->getOriginalDestinationAccount();
|
||||
}
|
||||
|
||||
$destInfo = [
|
||||
'id' => (int)($this->data['destination_id'] ?? null),
|
||||
'name' => $this->data['destination_name'] ?? null,
|
||||
'iban' => $this->data['destination_iban'] ?? null,
|
||||
'number' => $this->data['destination_number'] ?? null,
|
||||
'bic' => $this->data['destination_bic'] ?? null,
|
||||
];
|
||||
|
||||
// make new account validator.
|
||||
$expectedType = $this->getExpectedType();
|
||||
Log::debug(sprintf('Expected type (new or unchanged) is %s', $expectedType));
|
||||
try {
|
||||
$result = $this->getAccount($expectedType, 'destination', $destInfo);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error(sprintf('getValidDestinationAccount() threw unexpected error: %s', $e->getMessage()));
|
||||
$result = $this->getOriginalDestinationAccount();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a validation and returns the source account. This method will break if the source isn't really valid.
|
||||
* If the array contains key 'type' and the value is correct, this is returned. Otherwise, the original type is returned.
|
||||
*
|
||||
* @return Account
|
||||
* @return string
|
||||
*/
|
||||
private function getValidSourceAccount(): Account
|
||||
private function getExpectedType(): string
|
||||
{
|
||||
Log::debug('Now in getValidSourceAccount().');
|
||||
|
||||
if (!$this->hasFields(['source_id', 'source_name'])) {
|
||||
return $this->getOriginalSourceAccount();
|
||||
Log::debug('Now in getExpectedType()');
|
||||
if ($this->hasFields(['type'])) {
|
||||
return ucfirst('opening-balance' === $this->data['type'] ? 'opening balance' : $this->data['type']);
|
||||
}
|
||||
|
||||
$sourceInfo = [
|
||||
'id' => (int)($this->data['source_id'] ?? null),
|
||||
'name' => $this->data['source_name'] ?? null,
|
||||
'iban' => $this->data['source_iban'] ?? null,
|
||||
'number' => $this->data['source_number'] ?? null,
|
||||
'bic' => $this->data['source_bic'] ?? null,
|
||||
];
|
||||
|
||||
$expectedType = $this->getExpectedType();
|
||||
try {
|
||||
$result = $this->getAccount($expectedType, 'source', $sourceInfo);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error(sprintf('Cant get the valid source account: %s', $e->getMessage()));
|
||||
|
||||
$result = $this->getOriginalSourceAccount();
|
||||
}
|
||||
|
||||
Log::debug(sprintf('getValidSourceAccount() will return #%d ("%s")', $result->id, $result->name));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function hasFields(array $fields): bool
|
||||
{
|
||||
foreach ($fields as $field) {
|
||||
if (array_key_exists($field, $this->data)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function hasValidAccounts(): bool
|
||||
{
|
||||
return $this->hasValidSourceAccount() && $this->hasValidDestinationAccount();
|
||||
return $this->transactionJournal->transactionType->type;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -361,36 +299,64 @@ class JournalUpdateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @return Account
|
||||
*/
|
||||
private function hasValidSourceAccount(): bool
|
||||
private function getOriginalDestinationAccount(): Account
|
||||
{
|
||||
Log::debug('Now in hasValidSourceAccount().');
|
||||
$sourceId = $this->data['source_id'] ?? null;
|
||||
$sourceName = $this->data['source_name'] ?? null;
|
||||
|
||||
if (!$this->hasFields(['source_id', 'source_name'])) {
|
||||
$origSourceAccount = $this->getOriginalSourceAccount();
|
||||
$sourceId = $origSourceAccount->id;
|
||||
$sourceName = $origSourceAccount->name;
|
||||
if (null === $this->destinationAccount) {
|
||||
$destination = $this->getDestinationTransaction();
|
||||
$this->destinationAccount = $destination->account;
|
||||
}
|
||||
|
||||
// make new account validator.
|
||||
return $this->destinationAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get destination transaction.
|
||||
*
|
||||
* @return Transaction
|
||||
*/
|
||||
private function getDestinationTransaction(): Transaction
|
||||
{
|
||||
if (null === $this->destinationTransaction) {
|
||||
$this->destinationTransaction = $this->transactionJournal->transactions()->where('amount', '>', 0)->first();
|
||||
}
|
||||
|
||||
return $this->destinationTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a validation and returns the source account. This method will break if the source isn't really valid.
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function getValidSourceAccount(): Account
|
||||
{
|
||||
Log::debug('Now in getValidSourceAccount().');
|
||||
|
||||
if (!$this->hasFields(['source_id', 'source_name'])) {
|
||||
return $this->getOriginalSourceAccount();
|
||||
}
|
||||
|
||||
$sourceInfo = [
|
||||
'id' => (int)($this->data['source_id'] ?? null),
|
||||
'name' => $this->data['source_name'] ?? null,
|
||||
'iban' => $this->data['source_iban'] ?? null,
|
||||
'number' => $this->data['source_number'] ?? null,
|
||||
'bic' => $this->data['source_bic'] ?? null,
|
||||
];
|
||||
|
||||
$expectedType = $this->getExpectedType();
|
||||
Log::debug(sprintf('Expected type (new or unchanged) is %s', $expectedType));
|
||||
try {
|
||||
$result = $this->getAccount($expectedType, 'source', $sourceInfo);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error(sprintf('Cant get the valid source account: %s', $e->getMessage()));
|
||||
|
||||
// make a new validator.
|
||||
/** @var AccountValidator $validator */
|
||||
$validator = app(AccountValidator::class);
|
||||
$validator->setTransactionType($expectedType);
|
||||
$validator->setUser($this->transactionJournal->user);
|
||||
$result = $this->getOriginalSourceAccount();
|
||||
}
|
||||
|
||||
$result = $validator->validateSource($sourceId, $sourceName, null);
|
||||
Log::debug(sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true)));
|
||||
Log::debug(sprintf('getValidSourceAccount() will return #%d ("%s")', $result->id, $result->name));
|
||||
|
||||
// TODO typeOverrule: the account validator may have another opinion on the transaction type.
|
||||
|
||||
// validate submitted info:
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -427,36 +393,68 @@ class JournalUpdateService
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a validation and returns the destination account. This method will break if the dest isn't really valid.
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function updateAmount(): void
|
||||
private function getValidDestinationAccount(): Account
|
||||
{
|
||||
if (!$this->hasFields(['amount'])) {
|
||||
return;
|
||||
Log::debug('Now in getValidDestinationAccount().');
|
||||
|
||||
if (!$this->hasFields(['destination_id', 'destination_name'])) {
|
||||
return $this->getOriginalDestinationAccount();
|
||||
}
|
||||
|
||||
$value = $this->data['amount'] ?? '';
|
||||
$destInfo = [
|
||||
'id' => (int)($this->data['destination_id'] ?? null),
|
||||
'name' => $this->data['destination_name'] ?? null,
|
||||
'iban' => $this->data['destination_iban'] ?? null,
|
||||
'number' => $this->data['destination_number'] ?? null,
|
||||
'bic' => $this->data['destination_bic'] ?? null,
|
||||
];
|
||||
|
||||
// make new account validator.
|
||||
$expectedType = $this->getExpectedType();
|
||||
Log::debug(sprintf('Expected type (new or unchanged) is %s', $expectedType));
|
||||
try {
|
||||
$amount = $this->getAmount($value);
|
||||
$result = $this->getAccount($expectedType, 'destination', $destInfo);
|
||||
} catch (FireflyException $e) {
|
||||
Log::debug(sprintf('getAmount("%s") returns error: %s', $value, $e->getMessage()));
|
||||
Log::error(sprintf('getValidDestinationAccount() threw unexpected error: %s', $e->getMessage()));
|
||||
$result = $this->getOriginalDestinationAccount();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates journal transaction type.
|
||||
*/
|
||||
private function updateType(): void
|
||||
{
|
||||
Log::debug('Now in updateType()');
|
||||
if ($this->hasFields(['type'])) {
|
||||
$type = 'opening-balance' === $this->data['type'] ? 'opening balance' : $this->data['type'];
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Trying to change journal #%d from a %s to a %s.',
|
||||
$this->transactionJournal->id, $this->transactionJournal->transactionType->type, $type
|
||||
)
|
||||
);
|
||||
|
||||
/** @var TransactionTypeFactory $typeFactory */
|
||||
$typeFactory = app(TransactionTypeFactory::class);
|
||||
$result = $typeFactory->find($this->data['type']);
|
||||
if (null !== $result) {
|
||||
Log::debug('Changed transaction type!');
|
||||
$this->transactionJournal->transaction_type_id = $result->id;
|
||||
$this->transactionJournal->save();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
$origSourceTransaction = $this->getSourceTransaction();
|
||||
$origSourceTransaction->amount = app('steam')->negative($amount);
|
||||
$origSourceTransaction->save();
|
||||
|
||||
|
||||
$destTransaction = $this->getDestinationTransaction();
|
||||
$destTransaction->amount = app('steam')->positive($amount);
|
||||
$destTransaction->save();
|
||||
|
||||
|
||||
// refresh transactions.
|
||||
$this->sourceTransaction->refresh();
|
||||
$this->destinationTransaction->refresh();
|
||||
Log::debug(sprintf('Updated amount to "%s"', $amount));
|
||||
Log::debug('No type field present.');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -479,6 +477,47 @@ class JournalUpdateService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update journal generic field. Cannot be set to NULL.
|
||||
*
|
||||
* @param string $fieldName
|
||||
*/
|
||||
private function updateField(string $fieldName): void
|
||||
{
|
||||
if (array_key_exists($fieldName, $this->data) && '' !== (string)$this->data[$fieldName]) {
|
||||
$value = $this->data[$fieldName];
|
||||
|
||||
if ('date' === $fieldName) {
|
||||
if ($value instanceof Carbon) {
|
||||
// update timezone.
|
||||
$value->setTimezone(config('app.timezone'));
|
||||
}
|
||||
if (!($value instanceof Carbon)) {
|
||||
$value = new Carbon($value);
|
||||
}
|
||||
// do some parsing.
|
||||
Log::debug(sprintf('Create date value from string "%s".', $value));
|
||||
}
|
||||
|
||||
|
||||
$this->transactionJournal->$fieldName = $value;
|
||||
Log::debug(sprintf('Updated %s', $fieldName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateCategory(): void
|
||||
{
|
||||
// update category
|
||||
if ($this->hasFields(['category_id', 'category_name'])) {
|
||||
Log::debug('Will update category.');
|
||||
|
||||
$this->storeCategory($this->transactionJournal, new NullArrayObject($this->data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -494,13 +533,103 @@ class JournalUpdateService
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateCategory(): void
|
||||
private function updateTags(): void
|
||||
{
|
||||
// update category
|
||||
if ($this->hasFields(['category_id', 'category_name'])) {
|
||||
Log::debug('Will update category.');
|
||||
if ($this->hasFields(['tags'])) {
|
||||
Log::debug('Will update tags.');
|
||||
$tags = $this->data['tags'] ?? null;
|
||||
$this->storeTags($this->transactionJournal, $tags);
|
||||
}
|
||||
}
|
||||
|
||||
$this->storeCategory($this->transactionJournal, new NullArrayObject($this->data));
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateReconciled(): void
|
||||
{
|
||||
if (array_key_exists('reconciled', $this->data) && is_bool($this->data['reconciled'])) {
|
||||
$this->transactionJournal->transactions()->update(['reconciled' => $this->data['reconciled']]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateNotes(): void
|
||||
{
|
||||
// update notes.
|
||||
if ($this->hasFields(['notes'])) {
|
||||
$notes = '' === (string)$this->data['notes'] ? null : $this->data['notes'];
|
||||
$this->storeNotes($this->transactionJournal, $notes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateMeta(): void
|
||||
{
|
||||
// update meta fields.
|
||||
// first string
|
||||
if ($this->hasFields($this->metaString)) {
|
||||
Log::debug('Meta string fields are present.');
|
||||
$this->updateMetaFields();
|
||||
}
|
||||
|
||||
// then date fields.
|
||||
if ($this->hasFields($this->metaDate)) {
|
||||
Log::debug('Meta date fields are present.');
|
||||
$this->updateMetaDateFields();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateMetaFields(): void
|
||||
{
|
||||
/** @var TransactionJournalMetaFactory $factory */
|
||||
$factory = app(TransactionJournalMetaFactory::class);
|
||||
|
||||
foreach ($this->metaString as $field) {
|
||||
if ($this->hasFields([$field])) {
|
||||
$value = '' === $this->data[$field] ? null : $this->data[$field];
|
||||
Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value));
|
||||
$set = [
|
||||
'journal' => $this->transactionJournal,
|
||||
'name' => $field,
|
||||
'data' => $value,
|
||||
];
|
||||
$factory->updateOrCreate($set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateMetaDateFields(): void
|
||||
{
|
||||
/** @var TransactionJournalMetaFactory $factory */
|
||||
$factory = app(TransactionJournalMetaFactory::class);
|
||||
|
||||
foreach ($this->metaDate as $field) {
|
||||
if ($this->hasFields([$field])) {
|
||||
try {
|
||||
$value = '' === (string)$this->data[$field] ? null : new Carbon($this->data[$field]);
|
||||
} catch (Exception $e) {
|
||||
Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage()));
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value));
|
||||
$set = [
|
||||
'journal' => $this->transactionJournal,
|
||||
'name' => $field,
|
||||
'data' => $value,
|
||||
];
|
||||
$factory->updateOrCreate($set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,33 +666,37 @@ class JournalUpdateService
|
||||
}
|
||||
|
||||
/**
|
||||
* Update journal generic field. Cannot be set to NULL.
|
||||
*
|
||||
* @param string $fieldName
|
||||
*/
|
||||
private function updateField(string $fieldName): void
|
||||
private function updateAmount(): void
|
||||
{
|
||||
if (array_key_exists($fieldName, $this->data) && '' !== (string)$this->data[$fieldName]) {
|
||||
$value = $this->data[$fieldName];
|
||||
|
||||
if ('date' === $fieldName) {
|
||||
if ($value instanceof Carbon) {
|
||||
// update timezone.
|
||||
$value->setTimezone(config('app.timezone'));
|
||||
}
|
||||
if (!($value instanceof Carbon)) {
|
||||
$value = new Carbon($value);
|
||||
}
|
||||
// do some parsing.
|
||||
Log::debug(sprintf('Create date value from string "%s".', $value));
|
||||
}
|
||||
|
||||
|
||||
$this->transactionJournal->$fieldName = $value;
|
||||
Log::debug(sprintf('Updated %s', $fieldName));
|
||||
if (!$this->hasFields(['amount'])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$value = $this->data['amount'] ?? '';
|
||||
try {
|
||||
$amount = $this->getAmount($value);
|
||||
} catch (FireflyException $e) {
|
||||
Log::debug(sprintf('getAmount("%s") returns error: %s', $value, $e->getMessage()));
|
||||
|
||||
return;
|
||||
}
|
||||
$origSourceTransaction = $this->getSourceTransaction();
|
||||
$origSourceTransaction->amount = app('steam')->negative($amount);
|
||||
$origSourceTransaction->save();
|
||||
|
||||
|
||||
$destTransaction = $this->getDestinationTransaction();
|
||||
$destTransaction->amount = app('steam')->positive($amount);
|
||||
$destTransaction->save();
|
||||
|
||||
|
||||
// refresh transactions.
|
||||
$this->sourceTransaction->refresh();
|
||||
$this->destinationTransaction->refresh();
|
||||
Log::debug(sprintf('Updated amount to "%s"', $amount));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@ -628,138 +761,4 @@ class JournalUpdateService
|
||||
$this->sourceTransaction->refresh();
|
||||
$this->destinationTransaction->refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateMeta(): void
|
||||
{
|
||||
// update meta fields.
|
||||
// first string
|
||||
if ($this->hasFields($this->metaString)) {
|
||||
Log::debug('Meta string fields are present.');
|
||||
$this->updateMetaFields();
|
||||
}
|
||||
|
||||
// then date fields.
|
||||
if ($this->hasFields($this->metaDate)) {
|
||||
Log::debug('Meta date fields are present.');
|
||||
$this->updateMetaDateFields();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateMetaDateFields(): void
|
||||
{
|
||||
/** @var TransactionJournalMetaFactory $factory */
|
||||
$factory = app(TransactionJournalMetaFactory::class);
|
||||
|
||||
foreach ($this->metaDate as $field) {
|
||||
if ($this->hasFields([$field])) {
|
||||
try {
|
||||
$value = '' === (string)$this->data[$field] ? null : new Carbon($this->data[$field]);
|
||||
} catch (Exception $e) {
|
||||
Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage()));
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value));
|
||||
$set = [
|
||||
'journal' => $this->transactionJournal,
|
||||
'name' => $field,
|
||||
'data' => $value,
|
||||
];
|
||||
$factory->updateOrCreate($set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateMetaFields(): void
|
||||
{
|
||||
/** @var TransactionJournalMetaFactory $factory */
|
||||
$factory = app(TransactionJournalMetaFactory::class);
|
||||
|
||||
foreach ($this->metaString as $field) {
|
||||
if ($this->hasFields([$field])) {
|
||||
$value = '' === $this->data[$field] ? null : $this->data[$field];
|
||||
Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value));
|
||||
$set = [
|
||||
'journal' => $this->transactionJournal,
|
||||
'name' => $field,
|
||||
'data' => $value,
|
||||
];
|
||||
$factory->updateOrCreate($set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateNotes(): void
|
||||
{
|
||||
// update notes.
|
||||
if ($this->hasFields(['notes'])) {
|
||||
$notes = '' === (string)$this->data['notes'] ? null : $this->data['notes'];
|
||||
$this->storeNotes($this->transactionJournal, $notes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateTags(): void
|
||||
{
|
||||
if ($this->hasFields(['tags'])) {
|
||||
Log::debug('Will update tags.');
|
||||
$tags = $this->data['tags'] ?? null;
|
||||
$this->storeTags($this->transactionJournal, $tags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates journal transaction type.
|
||||
*/
|
||||
private function updateType(): void
|
||||
{
|
||||
Log::debug('Now in updateType()');
|
||||
if ($this->hasFields(['type'])) {
|
||||
$type = 'opening-balance' === $this->data['type'] ? 'opening balance' : $this->data['type'];
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Trying to change journal #%d from a %s to a %s.',
|
||||
$this->transactionJournal->id, $this->transactionJournal->transactionType->type, $type
|
||||
)
|
||||
);
|
||||
|
||||
/** @var TransactionTypeFactory $typeFactory */
|
||||
$typeFactory = app(TransactionTypeFactory::class);
|
||||
$result = $typeFactory->find($this->data['type']);
|
||||
if (null !== $result) {
|
||||
Log::debug('Changed transaction type!');
|
||||
$this->transactionJournal->transaction_type_id = $result->id;
|
||||
$this->transactionJournal->save();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('No type field present.');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateReconciled(): void
|
||||
{
|
||||
if (array_key_exists('reconciled', $this->data) && is_bool($this->data['reconciled'])) {
|
||||
$this->transactionJournal->transactions()->update(['reconciled' => $this->data['reconciled']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ use Exception;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceRepetition;
|
||||
use FireflyIII\Services\Internal\Support\RecurringTransactionTrait;
|
||||
use FireflyIII\Services\Internal\Support\TransactionTypeTrait;
|
||||
use FireflyIII\User;
|
||||
@ -56,53 +57,55 @@ class RecurrenceUpdateService
|
||||
*/
|
||||
public function update(Recurrence $recurrence, array $data): Recurrence
|
||||
{
|
||||
$this->user = $recurrence->user;
|
||||
$transactionType = $recurrence->transactionType;
|
||||
if (isset($data['recurrence']['type'])) {
|
||||
$transactionType = $this->findTransactionType(ucfirst($data['recurrence']['type']));
|
||||
}
|
||||
$this->user = $recurrence->user;
|
||||
// update basic fields first:
|
||||
$recurrence->transaction_type_id = $transactionType->id;
|
||||
$recurrence->title = $data['recurrence']['title'] ?? $recurrence->title;
|
||||
$recurrence->description = $data['recurrence']['description'] ?? $recurrence->description;
|
||||
$recurrence->first_date = $data['recurrence']['first_date'] ?? $recurrence->first_date;
|
||||
$recurrence->repeat_until = $data['recurrence']['repeat_until'] ?? $recurrence->repeat_until;
|
||||
$recurrence->repetitions = $data['recurrence']['nr_of_repetitions'] ?? $recurrence->repetitions;
|
||||
$recurrence->apply_rules = $data['recurrence']['apply_rules'] ?? $recurrence->apply_rules;
|
||||
$recurrence->active = $data['recurrence']['active'] ?? $recurrence->active;
|
||||
|
||||
// if nr_of_repetitions is set, then drop the "repeat_until" field.
|
||||
if (0 !== $recurrence->repetitions) {
|
||||
$recurrence->repeat_until = null;
|
||||
}
|
||||
|
||||
if (isset($data['recurrence']['repetition_end'])) {
|
||||
if (in_array($data['recurrence']['repetition_end'], ['forever', 'until_date'])) {
|
||||
$recurrence->repetitions = 0;
|
||||
if (array_key_exists('recurrence', $data)) {
|
||||
$info = $data['recurrence'];
|
||||
if (array_key_exists('title', $info)) {
|
||||
$recurrence->title = $info['title'];
|
||||
}
|
||||
if (in_array($data['recurrence']['repetition_end'], ['forever', 'times'])) {
|
||||
$recurrence->repeat_until = null;
|
||||
if (array_key_exists('description', $info)) {
|
||||
$recurrence->description = $info['description'];
|
||||
}
|
||||
if (array_key_exists('first_date', $info)) {
|
||||
$recurrence->first_date = $info['first_date'];
|
||||
}
|
||||
if (array_key_exists('repeat_until', $info)) {
|
||||
$recurrence->repeat_until = $info['repeat_until'];
|
||||
$recurrence->repetitions = 0;
|
||||
}
|
||||
if (array_key_exists('nr_of_repetitions', $info)) {
|
||||
if (0 !== (int)$info['nr_of_repetitions']) {
|
||||
$recurrence->repeat_until = null;
|
||||
}
|
||||
$recurrence->repetitions = $info['nr_of_repetitions'];
|
||||
}
|
||||
if (array_key_exists('apply_rules', $info)) {
|
||||
$recurrence->apply_rules = $info['apply_rules'];
|
||||
}
|
||||
if (array_key_exists('active', $info)) {
|
||||
$recurrence->active = $info['active'];
|
||||
}
|
||||
// update all meta data:
|
||||
if (array_key_exists('notes', $info)) {
|
||||
$this->setNoteText($recurrence, $info['notes']);
|
||||
}
|
||||
}
|
||||
$recurrence->save();
|
||||
|
||||
// update all meta data:
|
||||
|
||||
if (isset($data['recurrence']['notes']) && null !== $data['recurrence']['notes']) {
|
||||
$this->setNoteText($recurrence, $data['recurrence']['notes']);
|
||||
}
|
||||
|
||||
// update all repetitions
|
||||
if (null !== $data['repetitions']) {
|
||||
$this->deleteRepetitions($recurrence);
|
||||
$this->createRepetitions($recurrence, $data['repetitions'] ?? []);
|
||||
if (array_key_exists('repetitions', $data)) {
|
||||
Log::debug('Will update repetitions array');
|
||||
// update each repetition or throw error yay
|
||||
$this->updateRepetitions($recurrence, $data['repetitions'] ?? []);
|
||||
}
|
||||
|
||||
// update all transactions (and associated meta-data)
|
||||
if (null !== $data['transactions']) {
|
||||
$this->deleteTransactions($recurrence);
|
||||
$this->createTransactions($recurrence, $data['transactions'] ?? []);
|
||||
}
|
||||
// // update all transactions (and associated meta-data)
|
||||
// if (array_key_exists('transactions', $data)) {
|
||||
// $this->deleteTransactions($recurrence);
|
||||
// $this->createTransactions($recurrence, $data['transactions'] ?? []);
|
||||
// }
|
||||
|
||||
return $recurrence;
|
||||
}
|
||||
@ -133,4 +136,76 @@ class RecurrenceUpdateService
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Recurrence $recurrence
|
||||
* @param array $repetitions
|
||||
*/
|
||||
private function updateRepetitions(Recurrence $recurrence, array $repetitions): void
|
||||
{
|
||||
$originalCount = $recurrence->recurrenceRepetitions()->count();
|
||||
if (0 === count($repetitions)) {
|
||||
// wont drop repetition, rather avoid.
|
||||
return;
|
||||
}
|
||||
// user added or removed repetitions, delete all and recreate:
|
||||
if ($originalCount !== count($repetitions)) {
|
||||
Log::debug('Del + recreate');
|
||||
$this->deleteRepetitions($recurrence);
|
||||
$this->createRepetitions($recurrence, $repetitions);
|
||||
|
||||
return;
|
||||
}
|
||||
// loop all and try to match them:
|
||||
if ($originalCount === count($repetitions)) {
|
||||
Log::debug('Loop and find');
|
||||
foreach ($repetitions as $current) {
|
||||
$match = $this->matchRepetition($recurrence, $current);
|
||||
if (null === $match) {
|
||||
throw new FireflyException('Cannot match recurring repetition to existing repetition. Not sure what to do. Break.');
|
||||
}
|
||||
$fields = [
|
||||
'type' => 'repetition_type',
|
||||
'moment' => 'repetition_moment',
|
||||
'skip' => 'repetition_skip',
|
||||
'weekend' => 'weekend',];
|
||||
foreach ($fields as $field => $column) {
|
||||
if (array_key_exists($field, $current)) {
|
||||
$match->$column = $current[$field];
|
||||
$match->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return RecurrenceRepetition|null
|
||||
*/
|
||||
private function matchRepetition(Recurrence $recurrence, array $data): ?RecurrenceRepetition
|
||||
{
|
||||
$originalCount = $recurrence->recurrenceRepetitions()->count();
|
||||
if (1 === $originalCount) {
|
||||
Log::debug('Return the first one');
|
||||
return $recurrence->recurrenceRepetitions()->first();
|
||||
}
|
||||
// find it:
|
||||
$fields = ['id' => 'id',
|
||||
'type' => 'repetition_type',
|
||||
'moment' => 'repetition_moment',
|
||||
'skip' => 'repetition_skip',
|
||||
'weekend' => 'weekend',
|
||||
];
|
||||
$query = $recurrence->recurrenceRepetitions();
|
||||
foreach ($fields as $field => $column) {
|
||||
if (array_key_exists($field, $data)) {
|
||||
$query->where($column, $data[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
return $query->first();
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +154,10 @@ trait RecurrenceValidation
|
||||
* @var array $repetition
|
||||
*/
|
||||
foreach ($repetitions as $index => $repetition) {
|
||||
if(null === $repetition['moment']) {
|
||||
if (!array_key_exists('moment', $repetition)) {
|
||||
continue;
|
||||
}
|
||||
if (null === $repetition['moment']) {
|
||||
$repetition['moment'] = '';
|
||||
}
|
||||
$repetition['moment'] = $repetition['moment'] ?? 'invalid';
|
||||
|
63
tests/Api/Autocomplete/AccountControllerTest.php
Normal file
63
tests/Api/Autocomplete/AccountControllerTest.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* AccountControllerTest.php
|
||||
* Copyright (c) 2021 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Tests\Api\Autocomplete;
|
||||
|
||||
|
||||
use Tests\TestCase;
|
||||
use Laravel\Passport\Passport;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class AccountControllerTest
|
||||
*/
|
||||
class AccountControllerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
Passport::actingAs($this->user());
|
||||
Log::info(sprintf('Now in %s.', get_class($this)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testBasic(): void
|
||||
{
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Api\V1\Controllers\Autocomplete\AccountController
|
||||
*/
|
||||
public function testAccounts(): void
|
||||
{
|
||||
// test API
|
||||
$response = $this->get(route('api.v1.autocomplete.accounts'), ['Accept' => 'application/json']);
|
||||
$response->assertStatus(200);
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* CorrectOpeningBalanceCurrenciesTest.php
|
||||
* Copyright (c) 2021 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);
|
||||
/*
|
||||
* CorrectOpeningBalanceCurrenciesTest.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class CorrectOpeningBalanceCurrenciesTest
|
||||
*
|
||||
* @package Tests\Feature\Console\Commands\Correction
|
||||
*/
|
||||
class CorrectOpeningBalanceCurrenciesTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\CorrectOpeningBalanceCurrencies
|
||||
*/
|
||||
public function testBasic(): void
|
||||
{
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\CorrectOpeningBalanceCurrencies
|
||||
*/
|
||||
public function testHandleOK(): void
|
||||
{
|
||||
// run command
|
||||
$this->artisan('firefly-iii:fix-ob-currencies')
|
||||
->expectsOutput('There was nothing to fix in the opening balance transactions.')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\CorrectOpeningBalanceCurrencies
|
||||
*/
|
||||
public function testHandleBroken(): void
|
||||
{
|
||||
// create opening balance journal for test. Is enough to trigger this test.
|
||||
TransactionJournal::factory()->openingBalance()->create();
|
||||
|
||||
// run command
|
||||
$this->artisan('firefly-iii:fix-ob-currencies')
|
||||
->expectsOutput('Corrected 1 opening balance transaction(s).')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\CorrectOpeningBalanceCurrencies
|
||||
*/
|
||||
public function testHandleNoAccount(): void
|
||||
{
|
||||
Log::debug('Now in testHandleNoAccount');
|
||||
// create opening balance journal for test. Is enough to trigger this test.
|
||||
$journal = TransactionJournal::factory()->brokenOpeningBalance()->create();
|
||||
|
||||
// run command
|
||||
$this->artisan('firefly-iii:fix-ob-currencies')
|
||||
->expectsOutput(sprintf('Transaction journal #%d has no valid account. Cant fix this line.', $journal->id))
|
||||
//->expectsOutput('Cant fix this line.')
|
||||
->assertExitCode(0);
|
||||
|
||||
$journal->forceDelete();
|
||||
}
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* CreateAccessTokensTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\Preference;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class CreateAccessTokensTest
|
||||
*/
|
||||
class CreateAccessTokensTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\CreateAccessTokens
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// remove preferences so token will be generated
|
||||
Preference::where('name', 'access_token')->delete();
|
||||
|
||||
$this->artisan('firefly-iii:create-access-tokens')
|
||||
->expectsOutput(sprintf('Generated access token for user %s', $this->user()->email))
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\CreateAccessTokens
|
||||
*/
|
||||
public function testHandlePrefExists(): void
|
||||
{
|
||||
$preference = new Preference;
|
||||
$preference->data = '123';
|
||||
$preference->name = 'access_token';
|
||||
$preference->user_id = $this->user()->id;
|
||||
$preference->save();
|
||||
|
||||
$this->artisan('firefly-iii:create-access-tokens')
|
||||
->expectsOutput('All access tokens OK!')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* CreateLinkTypesTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\LinkType;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class CreateLinkTypesTest
|
||||
*/
|
||||
class CreateLinkTypesTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\CreateLinkTypes
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// delete all other link types:
|
||||
LinkType::whereNotIn('name', ['Related', 'Refund', 'Paid', 'Reimbursement'])->forceDelete();
|
||||
|
||||
// delete link type:
|
||||
LinkType::where('name', 'Reimbursement')->forceDelete();
|
||||
$this->assertCount(3, LinkType::get());
|
||||
|
||||
// run command, expect output:
|
||||
$this->artisan('firefly-iii:create-link-types')
|
||||
->expectsOutput('Created missing link type "Reimbursement"')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertCount(4, LinkType::get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\CreateLinkTypes
|
||||
*/
|
||||
public function testHandleNothing(): void
|
||||
{
|
||||
$this->assertCount(4, LinkType::get());
|
||||
|
||||
// run command, expect output:
|
||||
$this->artisan('firefly-iii:create-link-types')
|
||||
->expectsOutput('All link types OK!')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertCount(4, LinkType::get());
|
||||
}
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* DeleteEmptyGroupsTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class DeleteEmptyGroupsTest
|
||||
*/
|
||||
class DeleteEmptyGroupsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteEmptyGroups
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// assume there are no empty groups..
|
||||
$this->artisan('firefly-iii:delete-empty-groups')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteEmptyGroups
|
||||
*/
|
||||
public function testHandleWithGroup(): void
|
||||
{
|
||||
// create new group:
|
||||
$group = TransactionGroup::create(['user_id' => 1]);
|
||||
|
||||
// command should delete it.
|
||||
$this->artisan('firefly-iii:delete-empty-groups')
|
||||
->expectsOutput('Deleted 1 empty transaction group(s).')
|
||||
->assertExitCode(0);
|
||||
|
||||
// should not be able to find it:
|
||||
$this->assertCount(0, TransactionGroup::where('id', $group->id)->whereNull('deleted_at')->get());
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* DeleteEmptyJournalsTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class DeleteEmptyJournalsTest
|
||||
*/
|
||||
class DeleteEmptyJournalsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteEmptyJournals
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// assume there are no empty journals or uneven journals
|
||||
$this->artisan('firefly-iii:delete-empty-journals')
|
||||
->expectsOutput('No uneven transaction journals.')
|
||||
->expectsOutput('No empty transaction journals.')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteEmptyJournals
|
||||
*/
|
||||
public function testHandleEmptyJournals(): void
|
||||
{
|
||||
// create empty journal:
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => 1,
|
||||
'description' => 'Hello',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$this->artisan('firefly-iii:delete-empty-journals')
|
||||
->expectsOutput('No uneven transaction journals.')
|
||||
->expectsOutput(sprintf('Deleted empty transaction journal #%d', $journal->id))
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify its indeed gone
|
||||
$this->assertCount(0, TransactionJournal::where('id', $journal->id)->whereNull('deleted_at')->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteEmptyJournals
|
||||
*/
|
||||
public function testHandleUnevenJournals(): void
|
||||
{
|
||||
// create empty journal:
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => 1,
|
||||
'description' => 'Hello',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
|
||||
// link empty transaction
|
||||
$transaction = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => 1,
|
||||
'amount' => '5',
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
$this->artisan('firefly-iii:delete-empty-journals')
|
||||
->expectsOutput(sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $journal->id))
|
||||
->expectsOutput('No empty transaction journals.')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify both are gone
|
||||
$this->assertCount(0, TransactionJournal::where('id', $journal->id)->whereNull('deleted_at')->get());
|
||||
$this->assertCount(0, Transaction::where('id', $transaction->id)->whereNull('deleted_at')->get());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* DeleteOrphanedTransactionsTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class DeleteOrphanedTransactionsTest
|
||||
*/
|
||||
class DeleteOrphanedTransactionsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteOrphanedTransactions
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// assume there are no orphaned transactions.
|
||||
$this->artisan('firefly-iii:delete-orphaned-transactions')
|
||||
->expectsOutput('No orphaned transactions.')
|
||||
->expectsOutput('No orphaned accounts.')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testHandleOrphanedAccounts(): void
|
||||
{
|
||||
|
||||
// create deleted account:
|
||||
$account = Account::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'name' => 'Some account',
|
||||
'account_type_id' => 1,
|
||||
|
||||
]
|
||||
);
|
||||
$account->delete();
|
||||
|
||||
// create NOT deleted journal + transaction.
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => 1,
|
||||
'description' => 'Hello',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
|
||||
$transaction = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $account->id,
|
||||
'amount' => '5',
|
||||
]
|
||||
);
|
||||
|
||||
$this->artisan('firefly-iii:delete-orphaned-transactions')
|
||||
->expectsOutput('No orphaned transactions.')
|
||||
->expectsOutput(sprintf('Deleted transaction journal #%d because account #%d was already deleted.',
|
||||
$journal->id, $account->id))
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify bad objects are gone.
|
||||
$this->assertCount(0, Transaction::where('id', $transaction->id)->whereNull('deleted_at')->get());
|
||||
$this->assertCount(0, TransactionJournal::where('id', $journal->id)->whereNull('deleted_at')->get());
|
||||
$this->assertCount(0, Account::where('id', $account->id)->whereNull('deleted_at')->get());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteOrphanedTransactions
|
||||
*/
|
||||
public function testHandleOrphanedTransactions(): void
|
||||
{
|
||||
// create deleted journal:
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => 1,
|
||||
'description' => 'Hello',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$journal->delete();
|
||||
|
||||
// create NOT deleted transaction.
|
||||
$transaction = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => 1,
|
||||
'amount' => '5',
|
||||
]
|
||||
);
|
||||
|
||||
$this->artisan('firefly-iii:delete-orphaned-transactions')
|
||||
->expectsOutput(sprintf('Transaction #%d (part of deleted transaction journal #%d) has been deleted as well.',
|
||||
$transaction->id, $journal->id))
|
||||
->expectsOutput('No orphaned accounts.')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify objects are gone.
|
||||
$this->assertCount(0, TransactionJournal::where('id', $journal->id)->whereNull('deleted_at')->get());
|
||||
$this->assertCount(0, Transaction::where('id', $transaction->id)->whereNull('deleted_at')->get());
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* DeleteZeroAmountTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class DeleteZeroAmountTest
|
||||
*/
|
||||
class DeleteZeroAmountTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteZeroAmount
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// assume there are no transactions with a zero amount.
|
||||
$this->artisan('firefly-iii:delete-zero-amount')
|
||||
->expectsOutput('No zero-amount transaction journals.')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\DeleteZeroAmount
|
||||
*/
|
||||
public function testHandleTransactions(): void
|
||||
{
|
||||
$account = $this->getRandomAsset();
|
||||
// create NOT deleted journal + transaction.
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => 1,
|
||||
'description' => 'Hello',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
|
||||
$transaction = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $account->id,
|
||||
'amount' => '0',
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
// assume there are no transactions with a zero amount.
|
||||
$this->artisan('firefly-iii:delete-zero-amount')
|
||||
->expectsOutput(sprintf('Deleted transaction journal #%d because the amount is zero (0.00).', $journal->id))
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify objects are gone.
|
||||
$this->assertCount(0, Transaction::where('id', $transaction->id)->whereNull('deleted_at')->get());
|
||||
$this->assertCount(0, TransactionJournal::where('id', $journal->id)->whereNull('deleted_at')->get());
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* EnableCurrenciesTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class EnableCurrenciesTest
|
||||
*/
|
||||
class EnableCurrenciesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\EnableCurrencies
|
||||
*/
|
||||
public function testHandleEnabled(): void
|
||||
{
|
||||
$count = TransactionCurrency::where('enabled', 1)->count();
|
||||
|
||||
$this->artisan('firefly-iii:enable-currencies')
|
||||
->expectsOutput('All currencies are correctly enabled or disabled.')
|
||||
->assertExitCode(0);
|
||||
|
||||
|
||||
$this->assertCount($count, TransactionCurrency::where('enabled', 1)->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\EnableCurrencies
|
||||
*/
|
||||
public function testHandleDisabled(): void
|
||||
{
|
||||
// find a disabled currency, update a budget limit with it.
|
||||
$currency = TransactionCurrency::where('enabled', 0)->first();
|
||||
$budget = $this->getRandomBudget();
|
||||
$budgetLimit = new BudgetLimit;
|
||||
$budgetLimit->transaction_currency_id = $currency->id;
|
||||
$budgetLimit->budget_id = $budget->id;
|
||||
$budgetLimit->start_date = '2020-01-01';
|
||||
$budgetLimit->end_date = '2020-01-02';
|
||||
$budgetLimit->amount = '4';
|
||||
$budgetLimit->save();
|
||||
|
||||
// assume the current database is intact.
|
||||
$count = TransactionCurrency::where('enabled', 1)->count();
|
||||
$this->artisan('firefly-iii:enable-currencies')
|
||||
->expectsOutput(sprintf('%d were (was) still disabled. This has been corrected.', 1))
|
||||
->assertExitCode(0);
|
||||
|
||||
// assume its been enabled.
|
||||
$this->assertCount($count + 1, TransactionCurrency::where('enabled', 1)->get());
|
||||
$budgetLimit->forceDelete();
|
||||
}
|
||||
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* FixAccountOrderTest.php
|
||||
* Copyright (c) 2021 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);
|
||||
/*
|
||||
* FixAccountOrderTest.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use Tests\TestCase;
|
||||
|
||||
class FixAccountOrderTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixAccountOrder
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
|
||||
// reset all asset accounts accounts:
|
||||
Account::select()->update(['order' => 0]);
|
||||
|
||||
$this->artisan('firefly-iii:fix-account-order')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertCount(0, Account::where('order', '=',0)->get());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,364 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* FixAccountTypesTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class FixAccountTypesTest
|
||||
*/
|
||||
class FixAccountTypesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixAccountTypes
|
||||
*/
|
||||
public function testHandleUneven(): void
|
||||
{
|
||||
$source = $this->getRandomDebt();
|
||||
$type = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => $type->id,
|
||||
'description' => 'Test',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$one = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $source->id,
|
||||
'amount' => '-10',
|
||||
]
|
||||
);
|
||||
|
||||
// assume there's nothing to fix.
|
||||
$this->artisan('firefly-iii:fix-account-types')
|
||||
->expectsOutput(sprintf('Cannot inspect transaction journal #%d because it has 1 transaction(s) instead of 2.', $journal->id))
|
||||
->assertExitCode(0);
|
||||
$one->forceDelete();
|
||||
$journal->forceDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixAccountTypes
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// assume there's nothing to fix.
|
||||
$this->artisan('firefly-iii:fix-account-types')
|
||||
->expectsOutput('All account types are OK!')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to fix a withdrawal that goes from a loan to another loan.
|
||||
*
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixAccountTypes
|
||||
*/
|
||||
public function testHandleWithdrawalLoanLoan(): void
|
||||
{
|
||||
$source = $this->getRandomLoan();
|
||||
$destination = $this->getRandomLoan($source->id);
|
||||
$type = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => $type->id,
|
||||
'description' => 'Test',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$one = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $source->id,
|
||||
'amount' => '-10',
|
||||
]
|
||||
);
|
||||
$two = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $destination->id,
|
||||
'amount' => '10',
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
$this->artisan('firefly-iii:fix-account-types')
|
||||
->expectsOutput(sprintf('The source account of %s #%d cannot be of type "%s".', $type->type, $journal->id, 'Loan'))
|
||||
->expectsOutput(sprintf('The destination account of %s #%d cannot be of type "%s".', $type->type, $journal->id, 'Loan'))
|
||||
->expectsOutput('Acted on 1 transaction(s)!')
|
||||
->assertExitCode(0);
|
||||
|
||||
// since system cant handle this problem, dont look for changed transactions.
|
||||
$one->forceDelete();
|
||||
$two->forceDelete();
|
||||
$journal->forceDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transferring from an asset to a loan should be a withdrawal, not a transfer
|
||||
*/
|
||||
public function testHandleTransferAssetLoan(): void
|
||||
{
|
||||
$source = $this->getRandomAsset();
|
||||
$destination = $this->getRandomLoan();
|
||||
$type = TransactionType::where('type', TransactionType::TRANSFER)->first();
|
||||
$withdrawal = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => $type->id,
|
||||
'description' => 'Test',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$one = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $source->id,
|
||||
'amount' => '-10',
|
||||
]
|
||||
);
|
||||
$two = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $destination->id,
|
||||
'amount' => '10',
|
||||
]
|
||||
);
|
||||
|
||||
$this->artisan('firefly-iii:fix-account-types')
|
||||
->expectsOutput(sprintf('Converted transaction #%d from a transfer to a withdrawal.', $journal->id))
|
||||
->expectsOutput('Acted on 1 transaction(s)!')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify the change has been made.
|
||||
$this->assertCount(1, TransactionJournal::where('id', $journal->id)->where('transaction_type_id', $withdrawal->id)->get());
|
||||
$this->assertCount(0, TransactionJournal::where('id', $journal->id)->where('transaction_type_id', $type->id)->get());
|
||||
|
||||
$one->forceDelete();
|
||||
$two->forceDelete();
|
||||
$journal->forceDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transferring from a loan to an asset should be a deposit, not a transfer
|
||||
*/
|
||||
public function testHandleTransferLoanAsset(): void
|
||||
{
|
||||
$source = $this->getRandomLoan();
|
||||
$destination = $this->getRandomAsset();
|
||||
$type = TransactionType::where('type', TransactionType::TRANSFER)->first();
|
||||
$deposit = TransactionType::where('type', TransactionType::DEPOSIT)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => $type->id,
|
||||
'description' => 'Test',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$one = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $source->id,
|
||||
'amount' => '-10',
|
||||
]
|
||||
);
|
||||
$two = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $destination->id,
|
||||
'amount' => '10',
|
||||
]
|
||||
);
|
||||
|
||||
$this->artisan('firefly-iii:fix-account-types')
|
||||
->expectsOutput(sprintf('Converted transaction #%d from a transfer to a deposit.', $journal->id))
|
||||
->expectsOutput('Acted on 1 transaction(s)!')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify the change has been made.
|
||||
$this->assertCount(1, TransactionJournal::where('id', $journal->id)->where('transaction_type_id', $deposit->id)->get());
|
||||
$this->assertCount(0, TransactionJournal::where('id', $journal->id)->where('transaction_type_id', $type->id)->get());
|
||||
|
||||
$one->forceDelete();
|
||||
$two->forceDelete();
|
||||
$journal->forceDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdrawal with a revenue account as a destination must be converted.
|
||||
*/
|
||||
public function testHandleWithdrawalAssetRevenue(): void
|
||||
{
|
||||
$source = $this->getRandomAsset();
|
||||
$destination = $this->getRandomRevenue(); // is revenue account.
|
||||
$withdrawal = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => $withdrawal->id,
|
||||
'description' => 'Test',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$one = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $source->id,
|
||||
'amount' => '-10',
|
||||
]
|
||||
);
|
||||
$two = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $destination->id, // revenue cannot be destination.
|
||||
'amount' => '10',
|
||||
]
|
||||
);
|
||||
|
||||
// create expense account with the same name:
|
||||
$expense = AccountType::where('type', AccountType::EXPENSE)->first();
|
||||
$newDestination = Account::create(
|
||||
[
|
||||
'name' => $destination->name,
|
||||
'account_type_id' => $expense->id,
|
||||
'user_id' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
// asset we find bad destination.
|
||||
$this->assertCount(0, Transaction::where('id', $two->id)->where('account_id', $newDestination->id)->get());
|
||||
$this->assertCount(1, Transaction::where('id', $two->id)->where('account_id', $destination->id)->get());
|
||||
|
||||
// Transaction journal #137, destination account changed from #1 ("Checking Account") to #29 ("Land lord").
|
||||
$this->artisan('firefly-iii:fix-account-types')
|
||||
->expectsOutput(
|
||||
sprintf(
|
||||
'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").',
|
||||
$journal->id,
|
||||
$destination->id, $destination->name,
|
||||
$newDestination->id, $newDestination->name
|
||||
)
|
||||
)
|
||||
->expectsOutput('Acted on 1 transaction(s)!')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify the change has been made
|
||||
$this->assertCount(1, Transaction::where('id', $two->id)->where('account_id', $newDestination->id)->get());
|
||||
$this->assertCount(0, Transaction::where('id', $two->id)->where('account_id', $destination->id)->get());
|
||||
|
||||
$one->forceDelete();
|
||||
$two->forceDelete();
|
||||
$journal->forceDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deposit with an expense account as a source instead of a revenue account must be converted.
|
||||
*/
|
||||
public function testHandleDepositAssetExpense(): void
|
||||
{
|
||||
$source = $this->getRandomExpense(); // expense account
|
||||
//$newSource = $this->getRandomRevenue();
|
||||
$destination = $this->getRandomAsset();
|
||||
|
||||
$deposit = TransactionType::where('type', TransactionType::DEPOSIT)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => $deposit->id,
|
||||
'description' => 'Test',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$one = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $source->id, // expense account cannot be source.
|
||||
'amount' => '-10',
|
||||
]
|
||||
);
|
||||
$two = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $destination->id,
|
||||
'amount' => '10',
|
||||
]
|
||||
);
|
||||
// create revenue account with the same name:
|
||||
$revenue = AccountType::where('type', AccountType::REVENUE)->first();
|
||||
$newSource = Account::create(
|
||||
[
|
||||
'name' => $source->name,
|
||||
'account_type_id' => $revenue->id,
|
||||
'user_id' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertCount(0, Transaction::where('id', $one->id)->where('account_id', $newSource->id)->get());
|
||||
$this->assertCount(1, Transaction::where('id', $one->id)->where('account_id', $source->id)->get());
|
||||
|
||||
|
||||
// Transaction journal #137, destination account changed from #1 ("Checking Account") to #29 ("Land lord").
|
||||
$this->artisan('firefly-iii:fix-account-types')
|
||||
->expectsOutput(
|
||||
sprintf(
|
||||
'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").',
|
||||
$journal->id,
|
||||
$destination->id, $destination->name,
|
||||
$newSource->id, $newSource->name
|
||||
)
|
||||
)
|
||||
->expectsOutput('Acted on 1 transaction(s)!')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertCount(1, Transaction::where('id', $one->id)->where('account_id', $newSource->id)->get());
|
||||
$this->assertCount(0, Transaction::where('id', $one->id)->where('account_id', $source->id)->get());
|
||||
|
||||
$one->forceDelete();
|
||||
$two->forceDelete();
|
||||
$journal->forceDelete();
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* FixGroupAccountsTest.php
|
||||
* Copyright (c) 2021 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);
|
||||
/*
|
||||
* FixGroupAccountsTest.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class FixGroupAccountsTest
|
||||
*/
|
||||
class FixGroupAccountsTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixGroupAccounts
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// basic group with multiple journals, should trigger event.
|
||||
$this->artisan('firefly-iii:unify-group-accounts')
|
||||
->expectsOutput('Updated inconsistent transaction groups.')
|
||||
->assertExitCode(0);
|
||||
|
||||
// This just triggers the events. No real test.
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* FixLongDescriptionsTest.php
|
||||
* Copyright (c) 2021 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);
|
||||
/*
|
||||
* FixLongDescriptionsTest.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class FixLongDescriptionsTest
|
||||
*/
|
||||
class FixLongDescriptionsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixLongDescriptions
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
$journal = $this->getRandomWithdrawal();
|
||||
$original = $journal->description;
|
||||
$journal->description = str_repeat('ABCDEF123456x', 200);
|
||||
$journal->save();
|
||||
|
||||
|
||||
$this->artisan('firefly-iii:fix-long-descriptions')
|
||||
->expectsOutput(sprintf('Truncated description of transaction journal #%d', $journal->id))
|
||||
->expectsOutput('Verified all transaction group and journal title lengths.')
|
||||
->assertExitCode(0);
|
||||
|
||||
$journal->description = $original;
|
||||
$journal->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixLongDescriptions
|
||||
*/
|
||||
public function testHandleGroup(): void
|
||||
{
|
||||
$journal = $this->getRandomWithdrawal();
|
||||
$group = $journal->transactionGroup;
|
||||
$original = $group->title;
|
||||
$group->title = str_repeat('ABCDEF123456x', 200);
|
||||
$group->save();
|
||||
|
||||
|
||||
$this->artisan('firefly-iii:fix-long-descriptions')
|
||||
->expectsOutput(sprintf('Truncated description of transaction group #%d', $group->id))
|
||||
->expectsOutput('Verified all transaction group and journal title lengths.')
|
||||
->assertExitCode(0);
|
||||
|
||||
$group->title = $original;
|
||||
$group->save();
|
||||
}
|
||||
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* FixPiggiesTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class FixPiggiesTest
|
||||
*/
|
||||
class FixPiggiesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Null event.
|
||||
*
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixPiggies
|
||||
*/
|
||||
public function testHandleNull(): void
|
||||
{
|
||||
/** @var PiggyBank $piggy */
|
||||
$piggy = $this->user()->piggyBanks()->inRandomOrder()->first();
|
||||
|
||||
// create event to trigger console commands.
|
||||
$event = PiggyBankEvent::create(
|
||||
[
|
||||
'piggy_bank_id' => $piggy->id,
|
||||
'date' => '2019-01-01',
|
||||
'amount' => 5,
|
||||
]
|
||||
);
|
||||
|
||||
// assume there's nothing to fix.
|
||||
$this->artisan('firefly-iii:fix-piggies')
|
||||
->expectsOutput('All piggy bank events are correct.')
|
||||
->assertExitCode(0);
|
||||
$event->forceDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdrawal instead of transfer
|
||||
*
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixPiggies
|
||||
*/
|
||||
public function testHandleBadJournal(): void
|
||||
{
|
||||
/** @var PiggyBank $piggy */
|
||||
$piggy = $this->user()->piggyBanks()->inRandomOrder()->first();
|
||||
$withdrawal = $this->getRandomWithdrawal();
|
||||
// create event to trigger console commands.
|
||||
$event = PiggyBankEvent::create(
|
||||
[
|
||||
'piggy_bank_id' => $piggy->id,
|
||||
'date' => '2019-01-01',
|
||||
'amount' => 5,
|
||||
'transaction_journal_id' => $withdrawal->id,
|
||||
]
|
||||
);
|
||||
|
||||
// assume there's nothing to fix.
|
||||
$this->artisan('firefly-iii:fix-piggies')
|
||||
->expectsOutput(sprintf('Piggy bank #%d was referenced by an invalid event. This has been fixed.', $piggy->id))
|
||||
->expectsOutput('Fixed 1 piggy bank event(s).')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify update
|
||||
$this->assertCount(0, PiggyBankEvent::where('id', $event->id)->where('transaction_journal_id', $withdrawal->id)->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdrawal instead of transfer
|
||||
*
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixPiggies
|
||||
*/
|
||||
public function testHandleDeletedJournal(): void
|
||||
{
|
||||
/** @var PiggyBank $piggy */
|
||||
$piggy = $this->user()->piggyBanks()->inRandomOrder()->first();
|
||||
$transfer = $this->getRandomTransfer();
|
||||
$event = PiggyBankEvent::create(
|
||||
[
|
||||
'piggy_bank_id' => $piggy->id,
|
||||
'date' => '2019-01-01',
|
||||
'amount' => 5,
|
||||
'transaction_journal_id' => $transfer->id,
|
||||
]
|
||||
);
|
||||
$transfer->deleted_at = '2019-01-01 12:00:00';
|
||||
$transfer->save();
|
||||
$transfer->refresh();
|
||||
|
||||
$this->artisan('firefly-iii:fix-piggies')
|
||||
->expectsOutput('Fixed 1 piggy bank event(s).')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify update
|
||||
$this->assertCount(0, PiggyBankEvent::where('id', $event->id)->where('transaction_journal_id', $transfer->id)->get());
|
||||
$event->forceDelete();
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* FixRecurringTransactionsTest.php
|
||||
* Copyright (c) 2021 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);
|
||||
/*
|
||||
* FixRecurringTransactionsTest.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class FixRecurringTransactionsTest
|
||||
*/
|
||||
class FixRecurringTransactionsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixRecurringTransactions
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// test DB contains a broken recurring transaction.
|
||||
$recurring = Recurrence::whereTitle('broken_recurrence')->first();
|
||||
|
||||
|
||||
$this->artisan('firefly-iii:fix-recurring-transactions')
|
||||
->expectsOutput(sprintf('Recurring transaction #%d should be a "%s" but is a "%s" and will be corrected.',
|
||||
$recurring->id, 'Withdrawal','Transfer',
|
||||
))
|
||||
->assertExitCode(0);
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* FixTransactionTypesTest.php
|
||||
* Copyright (c) 2021 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);
|
||||
/*
|
||||
* FixTransactionTypesTest.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class FixTransactionTypesTest
|
||||
*/
|
||||
class FixTransactionTypesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixTransactionTypes
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
$this->artisan('firefly-iii:fix-transaction-types')
|
||||
//->expectsOutput()
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* FixUnevenAmountTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class FixUnevenAmountTest
|
||||
*/
|
||||
class FixUnevenAmountTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixUnevenAmount
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// assume there's nothing to fix.
|
||||
$this->artisan('firefly-iii:fix-uneven-amount')
|
||||
->expectsOutput('Amount integrity OK!')
|
||||
->assertExitCode(0);
|
||||
|
||||
// dont verify anything
|
||||
}
|
||||
|
||||
/**
|
||||
* Create uneven journal
|
||||
* @covers \FireflyIII\Console\Commands\Correction\FixUnevenAmount
|
||||
*/
|
||||
public function testHandleUneven(): void
|
||||
{
|
||||
$asset = $this->getRandomAsset();
|
||||
$expense = $this->getRandomExpense();
|
||||
$withdrawal = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => 1,
|
||||
'transaction_currency_id' => 1,
|
||||
'transaction_type_id' => $withdrawal->id,
|
||||
'description' => 'Test',
|
||||
'tag_count' => 0,
|
||||
'date' => '2019-01-01',
|
||||
]
|
||||
);
|
||||
$one = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $asset->id,
|
||||
'amount' => '-10',
|
||||
]
|
||||
);
|
||||
$two = Transaction::create(
|
||||
[
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'account_id' => $expense->id,
|
||||
'amount' => '12',
|
||||
]
|
||||
);
|
||||
|
||||
$this->artisan('firefly-iii:fix-uneven-amount')
|
||||
->expectsOutput(sprintf('Corrected amount in transaction journal #%d', $journal->id))
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify change.
|
||||
$this->assertCount(1, Transaction::where('id', $one->id)->where('amount', '-10')->get());
|
||||
$this->assertCount(1, Transaction::where('id', $two->id)->where('amount', '10')->get());
|
||||
}
|
||||
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* RemoveBillsTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class RemoveBillsTest
|
||||
*/
|
||||
class RemoveBillsTest extends TestCase
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\RemoveBills
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
// assume there's nothing to fix.
|
||||
$this->artisan('firefly-iii:remove-bills')
|
||||
->expectsOutput('All transaction journals have correct bill information.')
|
||||
->assertExitCode(0);
|
||||
|
||||
// dont verify anything
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\RemoveBills
|
||||
*/
|
||||
public function testHandleWithdrawal(): void
|
||||
{
|
||||
$bill = $this->getRandomBill();
|
||||
$journal = $this->getRandomDeposit();
|
||||
|
||||
$journal->bill_id = $bill->id;
|
||||
$journal->save();
|
||||
|
||||
$this->artisan('firefly-iii:remove-bills')
|
||||
->expectsOutput(sprintf('Transaction journal #%d should not be linked to bill #%d.', $journal->id, $bill->id))
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify change
|
||||
$this->assertCount(0, TransactionJournal::where('id', $journal->id)->whereNotNull('bill_id')->get());
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* RenameMetaFieldsTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class RenameMetaFieldsTest
|
||||
*/
|
||||
class RenameMetaFieldsTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\RenameMetaFields
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
$this->artisan('firefly-iii:rename-meta-fields')
|
||||
->expectsOutput('All meta fields are correct.')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\RenameMetaFields
|
||||
*/
|
||||
public function testHandleFixed(): void
|
||||
{
|
||||
$withdrawal = $this->getRandomWithdrawal();
|
||||
$entry = TransactionJournalMeta::create(
|
||||
[
|
||||
'transaction_journal_id' => $withdrawal->id,
|
||||
'name' => 'importHashV2',
|
||||
'data' => 'Fake data',
|
||||
|
||||
]
|
||||
);
|
||||
|
||||
$this->artisan('firefly-iii:rename-meta-fields')
|
||||
->expectsOutput('Renamed 1 meta field(s).')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify update
|
||||
$this->assertCount(1, TransactionJournalMeta::where('id', $entry->id)->where('name', 'import_hash_v2')->get());
|
||||
}
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* TransferBudgetsTest.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 Tests\Feature\Console\Commands\Correction;
|
||||
|
||||
|
||||
use Log;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class TransferBudgetsTest
|
||||
*/
|
||||
class TransferBudgetsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\TransferBudgets
|
||||
*/
|
||||
public function testHandle(): void
|
||||
{
|
||||
$this->artisan('firefly-iii:fix-transfer-budgets')
|
||||
->expectsOutput('No invalid budget/journal entries.')
|
||||
->assertExitCode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \FireflyIII\Console\Commands\Correction\TransferBudgets
|
||||
*/
|
||||
public function testHandleBudget(): void
|
||||
{
|
||||
$deposit = $this->getRandomDeposit();
|
||||
$budget = $this->getRandomBudget();
|
||||
|
||||
$deposit->budgets()->save($budget);
|
||||
|
||||
$this->artisan('firefly-iii:fix-transfer-budgets')
|
||||
->expectsOutput(sprintf('Transaction journal #%d is a %s, so has no longer a budget.', $deposit->id, $deposit->transactionType->type))
|
||||
->expectsOutput('Corrected 1 invalid budget/journal entries (entry).')
|
||||
->assertExitCode(0);
|
||||
|
||||
// verify change
|
||||
$this->assertCount(0, $deposit->budgets()->get());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user