mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-11-03 20:55:05 +00:00 
			
		
		
		
	Compare commits
	
		
			51 Commits
		
	
	
		
			branch-v6.
			...
			branch-v6.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					32e5efec7c | ||
| 
						 | 
					36457455ca | ||
| 
						 | 
					062c148e43 | ||
| 
						 | 
					2314ce8004 | ||
| 
						 | 
					a3ff73903a | ||
| 
						 | 
					7c8445707e | ||
| 
						 | 
					291e73da4b | ||
| 
						 | 
					286a29ca3e | ||
| 
						 | 
					71cf6c6a5e | ||
| 
						 | 
					1e8f0adaf8 | ||
| 
						 | 
					33531244aa | ||
| 
						 | 
					06049a9a28 | ||
| 
						 | 
					d313f5fdf5 | ||
| 
						 | 
					f4868126c1 | ||
| 
						 | 
					00147e98dd | ||
| 
						 | 
					6d22663ca2 | ||
| 
						 | 
					756bb9cf5e | ||
| 
						 | 
					399d7968f5 | ||
| 
						 | 
					966b68f42e | ||
| 
						 | 
					134c551c12 | ||
| 
						 | 
					9aeca15355 | ||
| 
						 | 
					6c6d31830b | ||
| 
						 | 
					e8cc321898 | ||
| 
						 | 
					e73fe06f7e | ||
| 
						 | 
					98b579c042 | ||
| 
						 | 
					7b3a5c1afd | ||
| 
						 | 
					7e2e49e129 | ||
| 
						 | 
					e8ef630424 | ||
| 
						 | 
					8805bcf6f6 | ||
| 
						 | 
					ff5c9a3aa0 | ||
| 
						 | 
					3a274dcaa7 | ||
| 
						 | 
					ddfededf02 | ||
| 
						 | 
					e1785898ba | ||
| 
						 | 
					ae09200f42 | ||
| 
						 | 
					847984f678 | ||
| 
						 | 
					42305672ac | ||
| 
						 | 
					25a56d9f72 | ||
| 
						 | 
					8f9f08b96f | ||
| 
						 | 
					3c65b46aa5 | ||
| 
						 | 
					1cf9c76329 | ||
| 
						 | 
					c0499df4ec | ||
| 
						 | 
					d90ac519f7 | ||
| 
						 | 
					a0e92b6969 | ||
| 
						 | 
					df49dd23e2 | ||
| 
						 | 
					d4525da6bc | ||
| 
						 | 
					25b11bd20b | ||
| 
						 | 
					705aac419a | ||
| 
						 | 
					f6e642f72e | ||
| 
						 | 
					565bd87959 | ||
| 
						 | 
					5751f7e5a3 | ||
| 
						 | 
					f5a755d4fc | 
@@ -30,6 +30,7 @@ use FireflyIII\Exceptions\FireflyException;
 | 
			
		||||
use FireflyIII\Models\Account;
 | 
			
		||||
use FireflyIII\Models\AccountType;
 | 
			
		||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
 | 
			
		||||
use FireflyIII\Support\Facades\Steam;
 | 
			
		||||
use FireflyIII\Support\Http\Api\AccountFilter;
 | 
			
		||||
use FireflyIII\User;
 | 
			
		||||
use Illuminate\Http\JsonResponse;
 | 
			
		||||
@@ -78,7 +79,7 @@ class AccountController extends Controller
 | 
			
		||||
        $query           = $data['query'];
 | 
			
		||||
        $date            = $data['date'] ?? today(config('app.timezone'));
 | 
			
		||||
        $return          = [];
 | 
			
		||||
        $result          = $this->repository->searchAccount((string)$query, $types, $this->parameters->get('limit'));
 | 
			
		||||
        $result          = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
 | 
			
		||||
 | 
			
		||||
        // TODO this code is duplicated in the V2 Autocomplete controller, which means this code is due to be deprecated.
 | 
			
		||||
        $defaultCurrency = app('amount')->getDefaultCurrency();
 | 
			
		||||
@@ -89,20 +90,20 @@ class AccountController extends Controller
 | 
			
		||||
            $currency        = $this->repository->getAccountCurrency($account) ?? $defaultCurrency;
 | 
			
		||||
 | 
			
		||||
            if (in_array($account->accountType->type, $this->balanceTypes, true)) {
 | 
			
		||||
                $balance         = app('steam')->balance($account, $date);
 | 
			
		||||
                $balance         = Steam::finalAccountBalance($account, $date);
 | 
			
		||||
                $nameWithBalance = sprintf(
 | 
			
		||||
                    '%s (%s)',
 | 
			
		||||
                    $account->name,
 | 
			
		||||
                    app('amount')->formatAnything($currency, $balance, false)
 | 
			
		||||
                    app('amount')->formatAnything($currency, $balance['balance'], false)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $return[]        = [
 | 
			
		||||
                'id'                      => (string)$account->id,
 | 
			
		||||
                'id'                      => (string) $account->id,
 | 
			
		||||
                'name'                    => $account->name,
 | 
			
		||||
                'name_with_balance'       => $nameWithBalance,
 | 
			
		||||
                'type'                    => $account->accountType->type,
 | 
			
		||||
                'currency_id'             => (string)$currency->id,
 | 
			
		||||
                'currency_id'             => (string) $currency->id,
 | 
			
		||||
                'currency_name'           => $currency->name,
 | 
			
		||||
                'currency_code'           => $currency->code,
 | 
			
		||||
                'currency_symbol'         => $currency->symbol,
 | 
			
		||||
@@ -115,8 +116,8 @@ class AccountController extends Controller
 | 
			
		||||
            $return,
 | 
			
		||||
            static function (array $left, array $right) {
 | 
			
		||||
                $order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE];
 | 
			
		||||
                $posA  = (int)array_search($left['type'], $order, true);
 | 
			
		||||
                $posB  = (int)array_search($right['type'], $order, true);
 | 
			
		||||
                $posA  = (int) array_search($left['type'], $order, true);
 | 
			
		||||
                $posB  = (int) array_search($right['type'], $order, true);
 | 
			
		||||
 | 
			
		||||
                return $posA - $posB;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ class BillController extends Controller
 | 
			
		||||
        $filtered = $result->map(
 | 
			
		||||
            static function (Bill $item) {
 | 
			
		||||
                return [
 | 
			
		||||
                    'id'     => (string)$item->id,
 | 
			
		||||
                    'id'     => (string) $item->id,
 | 
			
		||||
                    'name'   => $item->name,
 | 
			
		||||
                    'active' => $item->active,
 | 
			
		||||
                ];
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ class BudgetController extends Controller
 | 
			
		||||
        $filtered = $result->map(
 | 
			
		||||
            static function (Budget $item) {
 | 
			
		||||
                return [
 | 
			
		||||
                    'id'   => (string)$item->id,
 | 
			
		||||
                    'id'   => (string) $item->id,
 | 
			
		||||
                    'name' => $item->name,
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ class CategoryController extends Controller
 | 
			
		||||
        $filtered = $result->map(
 | 
			
		||||
            static function (Category $item) {
 | 
			
		||||
                return [
 | 
			
		||||
                    'id'   => (string)$item->id,
 | 
			
		||||
                    'id'   => (string) $item->id,
 | 
			
		||||
                    'name' => $item->name,
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -69,7 +69,7 @@ class CurrencyController extends Controller
 | 
			
		||||
        /** @var TransactionCurrency $currency */
 | 
			
		||||
        foreach ($collection as $currency) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'id'             => (string)$currency->id,
 | 
			
		||||
                'id'             => (string) $currency->id,
 | 
			
		||||
                'name'           => $currency->name,
 | 
			
		||||
                'code'           => $currency->code,
 | 
			
		||||
                'symbol'         => $currency->symbol,
 | 
			
		||||
@@ -95,7 +95,7 @@ class CurrencyController extends Controller
 | 
			
		||||
        /** @var TransactionCurrency $currency */
 | 
			
		||||
        foreach ($collection as $currency) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'id'             => (string)$currency->id,
 | 
			
		||||
                'id'             => (string) $currency->id,
 | 
			
		||||
                'name'           => sprintf('%s (%s)', $currency->name, $currency->code),
 | 
			
		||||
                'code'           => $currency->code,
 | 
			
		||||
                'symbol'         => $currency->symbol,
 | 
			
		||||
 
 | 
			
		||||
@@ -69,7 +69,7 @@ class ObjectGroupController extends Controller
 | 
			
		||||
        /** @var ObjectGroup $objectGroup */
 | 
			
		||||
        foreach ($result as $objectGroup) {
 | 
			
		||||
            $return[] = [
 | 
			
		||||
                'id'    => (string)$objectGroup->id,
 | 
			
		||||
                'id'    => (string) $objectGroup->id,
 | 
			
		||||
                'name'  => $objectGroup->title,
 | 
			
		||||
                'title' => $objectGroup->title,
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -75,14 +75,14 @@ class PiggyBankController extends Controller
 | 
			
		||||
            $currency    = $piggy->transactionCurrency;
 | 
			
		||||
            $objectGroup = $piggy->objectGroups()->first();
 | 
			
		||||
            $response[]  = [
 | 
			
		||||
                'id'                      => (string)$piggy->id,
 | 
			
		||||
                'id'                      => (string) $piggy->id,
 | 
			
		||||
                'name'                    => $piggy->name,
 | 
			
		||||
                'currency_id'             => (string)$currency->id,
 | 
			
		||||
                'currency_id'             => (string) $currency->id,
 | 
			
		||||
                'currency_name'           => $currency->name,
 | 
			
		||||
                'currency_code'           => $currency->code,
 | 
			
		||||
                'currency_symbol'         => $currency->symbol,
 | 
			
		||||
                'currency_decimal_places' => $currency->decimal_places,
 | 
			
		||||
                'object_group_id'         => null === $objectGroup ? null : (string)$objectGroup->id,
 | 
			
		||||
                'object_group_id'         => null === $objectGroup ? null : (string) $objectGroup->id,
 | 
			
		||||
                'object_group_title'      => $objectGroup?->title,
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
@@ -106,7 +106,7 @@ class PiggyBankController extends Controller
 | 
			
		||||
            $currentAmount = $this->piggyRepository->getCurrentAmount($piggy);
 | 
			
		||||
            $objectGroup   = $piggy->objectGroups()->first();
 | 
			
		||||
            $response[]    = [
 | 
			
		||||
                'id'                      => (string)$piggy->id,
 | 
			
		||||
                'id'                      => (string) $piggy->id,
 | 
			
		||||
                'name'                    => $piggy->name,
 | 
			
		||||
                'name_with_balance'       => sprintf(
 | 
			
		||||
                    '%s (%s / %s)',
 | 
			
		||||
@@ -114,12 +114,12 @@ class PiggyBankController extends Controller
 | 
			
		||||
                    app('amount')->formatAnything($currency, $currentAmount, false),
 | 
			
		||||
                    app('amount')->formatAnything($currency, $piggy->target_amount, false),
 | 
			
		||||
                ),
 | 
			
		||||
                'currency_id'             => (string)$currency->id,
 | 
			
		||||
                'currency_id'             => (string) $currency->id,
 | 
			
		||||
                'currency_name'           => $currency->name,
 | 
			
		||||
                'currency_code'           => $currency->code,
 | 
			
		||||
                'currency_symbol'         => $currency->symbol,
 | 
			
		||||
                'currency_decimal_places' => $currency->decimal_places,
 | 
			
		||||
                'object_group_id'         => null === $objectGroup ? null : (string)$objectGroup->id,
 | 
			
		||||
                'object_group_id'         => null === $objectGroup ? null : (string) $objectGroup->id,
 | 
			
		||||
                'object_group_title'      => $objectGroup?->title,
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ class RecurrenceController extends Controller
 | 
			
		||||
        /** @var Recurrence $recurrence */
 | 
			
		||||
        foreach ($recurrences as $recurrence) {
 | 
			
		||||
            $response[] = [
 | 
			
		||||
                'id'          => (string)$recurrence->id,
 | 
			
		||||
                'id'          => (string) $recurrence->id,
 | 
			
		||||
                'name'        => $recurrence->title,
 | 
			
		||||
                'description' => $recurrence->description,
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ class RuleController extends Controller
 | 
			
		||||
        /** @var Rule $rule */
 | 
			
		||||
        foreach ($rules as $rule) {
 | 
			
		||||
            $response[] = [
 | 
			
		||||
                'id'          => (string)$rule->id,
 | 
			
		||||
                'id'          => (string) $rule->id,
 | 
			
		||||
                'name'        => $rule->title,
 | 
			
		||||
                'description' => $rule->description,
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ class RuleGroupController extends Controller
 | 
			
		||||
        /** @var RuleGroup $group */
 | 
			
		||||
        foreach ($groups as $group) {
 | 
			
		||||
            $response[] = [
 | 
			
		||||
                'id'          => (string)$group->id,
 | 
			
		||||
                'id'          => (string) $group->id,
 | 
			
		||||
                'name'        => $group->title,
 | 
			
		||||
                'description' => $group->description,
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -69,7 +69,7 @@ class TagController extends Controller
 | 
			
		||||
        /** @var Tag $tag */
 | 
			
		||||
        foreach ($result as $tag) {
 | 
			
		||||
            $array[] = [
 | 
			
		||||
                'id'   => (string)$tag->id,
 | 
			
		||||
                'id'   => (string) $tag->id,
 | 
			
		||||
                'name' => $tag->tag,
 | 
			
		||||
                'tag'  => $tag->tag,
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -77,8 +77,8 @@ class TransactionController extends Controller
 | 
			
		||||
        /** @var TransactionJournal $journal */
 | 
			
		||||
        foreach ($filtered as $journal) {
 | 
			
		||||
            $array[] = [
 | 
			
		||||
                'id'                   => (string)$journal->id,
 | 
			
		||||
                'transaction_group_id' => (string)$journal->transaction_group_id,
 | 
			
		||||
                'id'                   => (string) $journal->id,
 | 
			
		||||
                'transaction_group_id' => (string) $journal->transaction_group_id,
 | 
			
		||||
                'name'                 => $journal->description,
 | 
			
		||||
                'description'          => $journal->description,
 | 
			
		||||
            ];
 | 
			
		||||
@@ -97,7 +97,7 @@ class TransactionController extends Controller
 | 
			
		||||
        $result = new Collection();
 | 
			
		||||
        if (is_numeric($data['query'])) {
 | 
			
		||||
            // search for group, not journal.
 | 
			
		||||
            $firstResult = $this->groupRepository->find((int)$data['query']);
 | 
			
		||||
            $firstResult = $this->groupRepository->find((int) $data['query']);
 | 
			
		||||
            if (null !== $firstResult) {
 | 
			
		||||
                // group may contain multiple journals, each a result:
 | 
			
		||||
                foreach ($firstResult->transactionJournals as $journal) {
 | 
			
		||||
@@ -115,8 +115,8 @@ class TransactionController extends Controller
 | 
			
		||||
        /** @var TransactionJournal $journal */
 | 
			
		||||
        foreach ($result as $journal) {
 | 
			
		||||
            $array[] = [
 | 
			
		||||
                'id'                   => (string)$journal->id,
 | 
			
		||||
                'transaction_group_id' => (string)$journal->transaction_group_id,
 | 
			
		||||
                'id'                   => (string) $journal->id,
 | 
			
		||||
                'transaction_group_id' => (string) $journal->transaction_group_id,
 | 
			
		||||
                'name'                 => sprintf('#%d: %s', $journal->transaction_group_id, $journal->description),
 | 
			
		||||
                'description'          => sprintf('#%d: %s', $journal->transaction_group_id, $journal->description),
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ class TransactionTypeController extends Controller
 | 
			
		||||
        foreach ($types as $type) {
 | 
			
		||||
            // different key for consistency.
 | 
			
		||||
            $array[] = [
 | 
			
		||||
                'id'   => (string)$type->id,
 | 
			
		||||
                'id'   => (string) $type->id,
 | 
			
		||||
                'name' => $type->type,
 | 
			
		||||
                'type' => $type->type,
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,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,
 | 
			
		||||
@@ -116,13 +116,13 @@ class AccountController extends Controller
 | 
			
		||||
            ];
 | 
			
		||||
            // TODO this code is also present in the V2 chart account controller so this method is due to be deprecated.
 | 
			
		||||
            $currentStart = clone $start;
 | 
			
		||||
            $range        = app('steam')->balanceInRange($account, $start, clone $end);
 | 
			
		||||
            $range        = app('steam')->finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative);
 | 
			
		||||
            // 2022-10-11 this method no longer converts to float.
 | 
			
		||||
            $previous     = array_values($range)[0];
 | 
			
		||||
            while ($currentStart <= $end) {
 | 
			
		||||
                $format                        = $currentStart->format('Y-m-d');
 | 
			
		||||
                $label                         = $currentStart->toAtomString();
 | 
			
		||||
                $balance                       = array_key_exists($format, $range) ? $range[$format] : $previous;
 | 
			
		||||
                $balance                       = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
 | 
			
		||||
                $previous                      = $balance;
 | 
			
		||||
                $currentStart->addDay();
 | 
			
		||||
                $currentSet['entries'][$label] = $balance;
 | 
			
		||||
 
 | 
			
		||||
@@ -50,11 +50,12 @@ abstract class Controller extends BaseController
 | 
			
		||||
    use DispatchesJobs;
 | 
			
		||||
    use ValidatesRequests;
 | 
			
		||||
 | 
			
		||||
    protected const string CONTENT_TYPE = 'application/vnd.api+json';
 | 
			
		||||
    protected const string CONTENT_TYPE    = 'application/vnd.api+json';
 | 
			
		||||
 | 
			
		||||
    /** @var array<int, string> */
 | 
			
		||||
    protected array        $allowedSort;
 | 
			
		||||
    protected ParameterBag $parameters;
 | 
			
		||||
    protected bool        $convertToNative = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Controller constructor.
 | 
			
		||||
@@ -67,8 +68,10 @@ abstract class Controller extends BaseController
 | 
			
		||||
            function ($request, $next) {
 | 
			
		||||
                $this->parameters = $this->getParameters();
 | 
			
		||||
                if (auth()->check()) {
 | 
			
		||||
                    $language = app('steam')->getLanguage();
 | 
			
		||||
                    $language              = app('steam')->getLanguage();
 | 
			
		||||
                    $this->convertToNative = app('preferences')->get('convert_to_native', false)->data;
 | 
			
		||||
                    app()->setLocale($language);
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return $next($request);
 | 
			
		||||
@@ -82,7 +85,7 @@ abstract class Controller extends BaseController
 | 
			
		||||
    private function getParameters(): ParameterBag
 | 
			
		||||
    {
 | 
			
		||||
        $bag      = new ParameterBag();
 | 
			
		||||
        $page     = (int)request()->get('page');
 | 
			
		||||
        $page     = (int) request()->get('page');
 | 
			
		||||
        if ($page < 1) {
 | 
			
		||||
            $page = 1;
 | 
			
		||||
        }
 | 
			
		||||
@@ -107,13 +110,13 @@ abstract class Controller extends BaseController
 | 
			
		||||
            $obj  = null;
 | 
			
		||||
            if (null !== $date) {
 | 
			
		||||
                try {
 | 
			
		||||
                    $obj = Carbon::parse((string)$date);
 | 
			
		||||
                    $obj = Carbon::parse((string) $date);
 | 
			
		||||
                } catch (InvalidDateException|InvalidFormatException $e) {
 | 
			
		||||
                    // don't care
 | 
			
		||||
                    app('log')->warning(
 | 
			
		||||
                        sprintf(
 | 
			
		||||
                            'Ignored invalid date "%s" in API controller parameter check: %s',
 | 
			
		||||
                            substr((string)$date, 0, 20),
 | 
			
		||||
                            substr((string) $date, 0, 20),
 | 
			
		||||
                            $e->getMessage()
 | 
			
		||||
                        )
 | 
			
		||||
                    );
 | 
			
		||||
@@ -134,7 +137,7 @@ abstract class Controller extends BaseController
 | 
			
		||||
                $value = null;
 | 
			
		||||
            }
 | 
			
		||||
            if (null !== $value) {
 | 
			
		||||
                $bag->set($integer, (int)$value);
 | 
			
		||||
                $bag->set($integer, (int) $value);
 | 
			
		||||
            }
 | 
			
		||||
            if (null === $value
 | 
			
		||||
                && 'limit' === $integer // @phpstan-ignore-line
 | 
			
		||||
@@ -144,7 +147,7 @@ abstract class Controller extends BaseController
 | 
			
		||||
                $user     = auth()->user();
 | 
			
		||||
 | 
			
		||||
                /** @var Preference $pageSize */
 | 
			
		||||
                $pageSize = (int)app('preferences')->getForUser($user, 'listPageSize', 50)->data;
 | 
			
		||||
                $pageSize = (int) app('preferences')->getForUser($user, 'listPageSize', 50)->data;
 | 
			
		||||
                $bag->set($integer, $pageSize);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -158,7 +161,7 @@ abstract class Controller extends BaseController
 | 
			
		||||
        $sortParameters = [];
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            $param = (string)request()->query->get('sort');
 | 
			
		||||
            $param = (string) request()->query->get('sort');
 | 
			
		||||
        } catch (BadRequestException $e) {
 | 
			
		||||
            app('log')->error('Request field "sort" contains a non-scalar value. Value set to NULL.');
 | 
			
		||||
            app('log')->error($e->getMessage());
 | 
			
		||||
 
 | 
			
		||||
@@ -70,8 +70,8 @@ class TransactionController extends Controller
 | 
			
		||||
        // to respond to what is in the $query.
 | 
			
		||||
        // this is OK because only one thing can be in the query at the moment.
 | 
			
		||||
        if ($this->isUpdateTransactionAccount($params)) {
 | 
			
		||||
            $original    = $this->repository->find((int)$params['where']['account_id']);
 | 
			
		||||
            $destination = $this->repository->find((int)$params['update']['account_id']);
 | 
			
		||||
            $original    = $this->repository->find((int) $params['where']['account_id']);
 | 
			
		||||
            $destination = $this->repository->find((int) $params['update']['account_id']);
 | 
			
		||||
 | 
			
		||||
            /** @var AccountDestroyService $service */
 | 
			
		||||
            $service     = app(AccountDestroyService::class);
 | 
			
		||||
 
 | 
			
		||||
@@ -88,7 +88,7 @@ class ExportController extends Controller
 | 
			
		||||
            ->header('Expires', '0')
 | 
			
		||||
            ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
 | 
			
		||||
            ->header('Pragma', 'public')
 | 
			
		||||
            ->header('Content-Length', (string)strlen($data[$key]))
 | 
			
		||||
            ->header('Content-Length', (string) strlen($data[$key]))
 | 
			
		||||
        ;
 | 
			
		||||
 | 
			
		||||
        return $response;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@ use FireflyIII\Models\Account;
 | 
			
		||||
use FireflyIII\Models\Bill;
 | 
			
		||||
use FireflyIII\Models\Budget;
 | 
			
		||||
use FireflyIII\Models\Category;
 | 
			
		||||
use FireflyIII\Models\PiggyBank;
 | 
			
		||||
use FireflyIII\Models\Recurrence;
 | 
			
		||||
use FireflyIII\Models\Rule;
 | 
			
		||||
use FireflyIII\Models\RuleGroup;
 | 
			
		||||
 
 | 
			
		||||
@@ -79,11 +79,11 @@ class AccountController extends Controller
 | 
			
		||||
        /** @var array $expense */
 | 
			
		||||
        foreach ($expenses as $expense) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'id'               => (string)$expense['id'],
 | 
			
		||||
                'id'               => (string) $expense['id'],
 | 
			
		||||
                'name'             => $expense['name'],
 | 
			
		||||
                'difference'       => $expense['sum'],
 | 
			
		||||
                'difference_float' => (float)$expense['sum'], // intentional float
 | 
			
		||||
                'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                'difference_float' => (float) $expense['sum'], // intentional float
 | 
			
		||||
                'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                'currency_code'    => $expense['currency_code'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
@@ -107,11 +107,11 @@ class AccountController extends Controller
 | 
			
		||||
        /** @var array $expense */
 | 
			
		||||
        foreach ($expenses as $expense) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'id'               => (string)$expense['id'],
 | 
			
		||||
                'id'               => (string) $expense['id'],
 | 
			
		||||
                'name'             => $expense['name'],
 | 
			
		||||
                'difference'       => $expense['sum'],
 | 
			
		||||
                'difference_float' => (float)$expense['sum'], // intentional float
 | 
			
		||||
                'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                'difference_float' => (float) $expense['sum'], // intentional float
 | 
			
		||||
                'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                'currency_code'    => $expense['currency_code'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -81,33 +81,33 @@ class BillController extends Controller
 | 
			
		||||
 | 
			
		||||
        $genericSet = $collector->getExtractedJournals();
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $billId            = (int)$journal['bill_id'];
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $billId            = (int) $journal['bill_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
            $key               = sprintf('%d-%d', $billId, $currencyId);
 | 
			
		||||
            $foreignKey        = sprintf('%d-%d', $billId, $foreignCurrencyId);
 | 
			
		||||
 | 
			
		||||
            if (0 !== $currencyId) {
 | 
			
		||||
                $response[$key] ??= [
 | 
			
		||||
                    'id'               => (string)$billId,
 | 
			
		||||
                    'id'               => (string) $billId,
 | 
			
		||||
                    'name'             => $journal['bill_name'],
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$currencyId,
 | 
			
		||||
                    'currency_id'      => (string) $currencyId,
 | 
			
		||||
                    'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$key]['difference']       = bcadd($response[$key]['difference'], $journal['amount']);
 | 
			
		||||
                $response[$key]['difference_float'] = (float)$response[$key]['difference']; // intentional float
 | 
			
		||||
                $response[$key]['difference_float'] = (float) $response[$key]['difference']; // intentional float
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $foreignCurrencyId) {
 | 
			
		||||
                $response[$foreignKey] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                    'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                    'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$foreignKey]['difference']       = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']);
 | 
			
		||||
                $response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // intentional float
 | 
			
		||||
                $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -135,28 +135,28 @@ class BillController extends Controller
 | 
			
		||||
        $genericSet = $collector->getExtractedJournals();
 | 
			
		||||
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            if (0 !== $currencyId) {
 | 
			
		||||
                $response[$currencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$currencyId,
 | 
			
		||||
                    'currency_id'      => (string) $currencyId,
 | 
			
		||||
                    'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], $journal['amount']);
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // intentional float
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $foreignCurrencyId) {
 | 
			
		||||
                $response[$foreignCurrencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                    'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                    'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference']       = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // intentional float
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // intentional float
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -85,11 +85,11 @@ class BudgetController extends Controller
 | 
			
		||||
            /** @var array $expense */
 | 
			
		||||
            foreach ($expenses as $expense) {
 | 
			
		||||
                $result[] = [
 | 
			
		||||
                    'id'               => (string)$budget->id,
 | 
			
		||||
                    'id'               => (string) $budget->id,
 | 
			
		||||
                    'name'             => $budget->name,
 | 
			
		||||
                    'difference'       => $expense['sum'],
 | 
			
		||||
                    'difference_float' => (float)$expense['sum'], // intentional float
 | 
			
		||||
                    'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                    'difference_float' => (float) $expense['sum'], // intentional float
 | 
			
		||||
                    'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                    'currency_code'    => $expense['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
@@ -114,8 +114,8 @@ class BudgetController extends Controller
 | 
			
		||||
        foreach ($expenses as $expense) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'difference'       => $expense['sum'],
 | 
			
		||||
                'difference_float' => (float)$expense['sum'], // intentional float
 | 
			
		||||
                'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                'difference_float' => (float) $expense['sum'], // intentional float
 | 
			
		||||
                'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                'currency_code'    => $expense['currency_code'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -85,11 +85,11 @@ class CategoryController extends Controller
 | 
			
		||||
            /** @var array $expense */
 | 
			
		||||
            foreach ($expenses as $expense) {
 | 
			
		||||
                $result[] = [
 | 
			
		||||
                    'id'               => (string)$category->id,
 | 
			
		||||
                    'id'               => (string) $category->id,
 | 
			
		||||
                    'name'             => $category->name,
 | 
			
		||||
                    'difference'       => $expense['sum'],
 | 
			
		||||
                    'difference_float' => (float)$expense['sum'], // intentional float
 | 
			
		||||
                    'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                    'difference_float' => (float) $expense['sum'], // intentional float
 | 
			
		||||
                    'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                    'currency_code'    => $expense['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
@@ -114,8 +114,8 @@ class CategoryController extends Controller
 | 
			
		||||
        foreach ($expenses as $expense) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'difference'       => $expense['sum'],
 | 
			
		||||
                'difference_float' => (float)$expense['sum'], // intentional float
 | 
			
		||||
                'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                'difference_float' => (float) $expense['sum'], // intentional float
 | 
			
		||||
                'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                'currency_code'    => $expense['currency_code'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -51,28 +51,28 @@ class PeriodController extends Controller
 | 
			
		||||
        $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts);
 | 
			
		||||
        $genericSet = $collector->getExtractedJournals();
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            if (0 !== $currencyId) {
 | 
			
		||||
                $response[$currencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$currencyId,
 | 
			
		||||
                    'currency_id'      => (string) $currencyId,
 | 
			
		||||
                    'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], $journal['amount']);
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // intentional float
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $foreignCurrencyId) {
 | 
			
		||||
                $response[$foreignCurrencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                    'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                    'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference']       = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // intentional float
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // intentional float
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -75,28 +75,28 @@ class TagController extends Controller
 | 
			
		||||
        $genericSet = $collector->getExtractedJournals();
 | 
			
		||||
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            if (0 !== $currencyId) {
 | 
			
		||||
                $response[$currencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$currencyId,
 | 
			
		||||
                    'currency_id'      => (string) $currencyId,
 | 
			
		||||
                    'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], $journal['amount']);
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // float but on purpose.
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $foreignCurrencyId) {
 | 
			
		||||
                $response[$foreignCurrencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                    'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                    'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference']       = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose.
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // float but on purpose.
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -130,8 +130,8 @@ class TagController extends Controller
 | 
			
		||||
 | 
			
		||||
        /** @var array $journal */
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            /** @var array $tag */
 | 
			
		||||
            foreach ($journal['tags'] as $tag) {
 | 
			
		||||
@@ -142,15 +142,15 @@ class TagController extends Controller
 | 
			
		||||
                // on currency ID
 | 
			
		||||
                if (0 !== $currencyId) {
 | 
			
		||||
                    $response[$key] ??= [
 | 
			
		||||
                        'id'               => (string)$tagId,
 | 
			
		||||
                        'id'               => (string) $tagId,
 | 
			
		||||
                        'name'             => $tag['name'],
 | 
			
		||||
                        'difference'       => '0',
 | 
			
		||||
                        'difference_float' => 0,
 | 
			
		||||
                        'currency_id'      => (string)$currencyId,
 | 
			
		||||
                        'currency_id'      => (string) $currencyId,
 | 
			
		||||
                        'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                    ];
 | 
			
		||||
                    $response[$key]['difference']       = bcadd($response[$key]['difference'], $journal['amount']);
 | 
			
		||||
                    $response[$key]['difference_float'] = (float)$response[$key]['difference']; // float but on purpose.
 | 
			
		||||
                    $response[$key]['difference_float'] = (float) $response[$key]['difference']; // float but on purpose.
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // on foreign ID
 | 
			
		||||
@@ -158,11 +158,11 @@ class TagController extends Controller
 | 
			
		||||
                    $response[$foreignKey]                     = $journal[$foreignKey] ?? [
 | 
			
		||||
                        'difference'       => '0',
 | 
			
		||||
                        'difference_float' => 0,
 | 
			
		||||
                        'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                        'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                        'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                    ];
 | 
			
		||||
                    $response[$foreignKey]['difference']       = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']);
 | 
			
		||||
                    $response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // float but on purpose.
 | 
			
		||||
                    $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // float but on purpose.
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -79,11 +79,11 @@ class AccountController extends Controller
 | 
			
		||||
        /** @var array $entry */
 | 
			
		||||
        foreach ($income as $entry) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'id'               => (string)$entry['id'],
 | 
			
		||||
                'id'               => (string) $entry['id'],
 | 
			
		||||
                'name'             => $entry['name'],
 | 
			
		||||
                'difference'       => $entry['sum'],
 | 
			
		||||
                'difference_float' => (float)$entry['sum'], // float but on purpose.
 | 
			
		||||
                'currency_id'      => (string)$entry['currency_id'],
 | 
			
		||||
                'difference_float' => (float) $entry['sum'], // float but on purpose.
 | 
			
		||||
                'currency_id'      => (string) $entry['currency_id'],
 | 
			
		||||
                'currency_code'    => $entry['currency_code'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
@@ -107,11 +107,11 @@ class AccountController extends Controller
 | 
			
		||||
        /** @var array $entry */
 | 
			
		||||
        foreach ($income as $entry) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'id'               => (string)$entry['id'],
 | 
			
		||||
                'id'               => (string) $entry['id'],
 | 
			
		||||
                'name'             => $entry['name'],
 | 
			
		||||
                'difference'       => $entry['sum'],
 | 
			
		||||
                'difference_float' => (float)$entry['sum'], // float but on purpose.
 | 
			
		||||
                'currency_id'      => (string)$entry['currency_id'],
 | 
			
		||||
                'difference_float' => (float) $entry['sum'], // float but on purpose.
 | 
			
		||||
                'currency_id'      => (string) $entry['currency_id'],
 | 
			
		||||
                'currency_code'    => $entry['currency_code'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -85,11 +85,11 @@ class CategoryController extends Controller
 | 
			
		||||
            /** @var array $expense */
 | 
			
		||||
            foreach ($expenses as $expense) {
 | 
			
		||||
                $result[] = [
 | 
			
		||||
                    'id'               => (string)$category->id,
 | 
			
		||||
                    'id'               => (string) $category->id,
 | 
			
		||||
                    'name'             => $category->name,
 | 
			
		||||
                    'difference'       => $expense['sum'],
 | 
			
		||||
                    'difference_float' => (float)$expense['sum'], // float but on purpose.
 | 
			
		||||
                    'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                    'difference_float' => (float) $expense['sum'], // float but on purpose.
 | 
			
		||||
                    'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                    'currency_code'    => $expense['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
@@ -114,8 +114,8 @@ class CategoryController extends Controller
 | 
			
		||||
        foreach ($expenses as $expense) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'difference'       => $expense['sum'],
 | 
			
		||||
                'difference_float' => (float)$expense['sum'], // float but on purpose.
 | 
			
		||||
                'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                'difference_float' => (float) $expense['sum'], // float but on purpose.
 | 
			
		||||
                'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                'currency_code'    => $expense['currency_code'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -51,31 +51,31 @@ class PeriodController extends Controller
 | 
			
		||||
        $collector->setTypes([TransactionTypeEnum::DEPOSIT->value])->setRange($start, $end)->setDestinationAccounts($accounts);
 | 
			
		||||
        $genericSet = $collector->getExtractedJournals();
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            if (0 !== $currencyId) {
 | 
			
		||||
                $response[$currencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$currencyId,
 | 
			
		||||
                    'currency_id'      => (string) $currencyId,
 | 
			
		||||
                    'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // float but on purpose.
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $foreignCurrencyId) {
 | 
			
		||||
                $response[$foreignCurrencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                    'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                    'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference']       = bcadd(
 | 
			
		||||
                    $response[$foreignCurrencyId]['difference'],
 | 
			
		||||
                    app('steam')->positive($journal['foreign_amount'])
 | 
			
		||||
                );
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose.
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // float but on purpose.
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -76,31 +76,31 @@ class TagController extends Controller
 | 
			
		||||
        $genericSet = $collector->getExtractedJournals();
 | 
			
		||||
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            if (0 !== $currencyId) {
 | 
			
		||||
                $response[$currencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$currencyId,
 | 
			
		||||
                    'currency_id'      => (string) $currencyId,
 | 
			
		||||
                    'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference'];
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $foreignCurrencyId) {
 | 
			
		||||
                $response[$foreignCurrencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                    'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                    'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference']       = bcadd(
 | 
			
		||||
                    $response[$foreignCurrencyId]['difference'],
 | 
			
		||||
                    app('steam')->positive($journal['foreign_amount'])
 | 
			
		||||
                );
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference'];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -134,8 +134,8 @@ class TagController extends Controller
 | 
			
		||||
 | 
			
		||||
        /** @var array $journal */
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            /** @var array $tag */
 | 
			
		||||
            foreach ($journal['tags'] as $tag) {
 | 
			
		||||
@@ -146,15 +146,15 @@ class TagController extends Controller
 | 
			
		||||
                // on currency ID
 | 
			
		||||
                if (0 !== $currencyId) {
 | 
			
		||||
                    $response[$key] ??= [
 | 
			
		||||
                        'id'               => (string)$tagId,
 | 
			
		||||
                        'id'               => (string) $tagId,
 | 
			
		||||
                        'name'             => $tag['name'],
 | 
			
		||||
                        'difference'       => '0',
 | 
			
		||||
                        'difference_float' => 0,
 | 
			
		||||
                        'currency_id'      => (string)$currencyId,
 | 
			
		||||
                        'currency_id'      => (string) $currencyId,
 | 
			
		||||
                        'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                    ];
 | 
			
		||||
                    $response[$key]['difference']       = bcadd($response[$key]['difference'], app('steam')->positive($journal['amount']));
 | 
			
		||||
                    $response[$key]['difference_float'] = (float)$response[$key]['difference'];
 | 
			
		||||
                    $response[$key]['difference_float'] = (float) $response[$key]['difference'];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // on foreign ID
 | 
			
		||||
@@ -162,14 +162,14 @@ class TagController extends Controller
 | 
			
		||||
                    $response[$foreignKey]                     = $journal[$foreignKey] ?? [
 | 
			
		||||
                        'difference'       => '0',
 | 
			
		||||
                        'difference_float' => 0,
 | 
			
		||||
                        'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                        'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                        'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                    ];
 | 
			
		||||
                    $response[$foreignKey]['difference']       = bcadd(
 | 
			
		||||
                        $response[$foreignKey]['difference'],
 | 
			
		||||
                        app('steam')->positive($journal['foreign_amount'])
 | 
			
		||||
                    );
 | 
			
		||||
                    $response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference'];
 | 
			
		||||
                    $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -85,11 +85,11 @@ class CategoryController extends Controller
 | 
			
		||||
            /** @var array $expense */
 | 
			
		||||
            foreach ($expenses as $expense) {
 | 
			
		||||
                $result[] = [
 | 
			
		||||
                    'id'               => (string)$category->id,
 | 
			
		||||
                    'id'               => (string) $category->id,
 | 
			
		||||
                    'name'             => $category->name,
 | 
			
		||||
                    'difference'       => $expense['sum'],
 | 
			
		||||
                    'difference_float' => (float)$expense['sum'],
 | 
			
		||||
                    'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                    'difference_float' => (float) $expense['sum'],
 | 
			
		||||
                    'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                    'currency_code'    => $expense['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
@@ -114,8 +114,8 @@ class CategoryController extends Controller
 | 
			
		||||
        foreach ($expenses as $expense) {
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'difference'       => $expense['sum'],
 | 
			
		||||
                'difference_float' => (float)$expense['sum'],
 | 
			
		||||
                'currency_id'      => (string)$expense['currency_id'],
 | 
			
		||||
                'difference_float' => (float) $expense['sum'],
 | 
			
		||||
                'currency_id'      => (string) $expense['currency_id'],
 | 
			
		||||
                'currency_code'    => $expense['currency_code'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -51,31 +51,31 @@ class PeriodController extends Controller
 | 
			
		||||
        $collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts);
 | 
			
		||||
        $genericSet = $collector->getExtractedJournals();
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            if (0 !== $currencyId) {
 | 
			
		||||
                $response[$currencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$currencyId,
 | 
			
		||||
                    'currency_id'      => (string) $currencyId,
 | 
			
		||||
                    'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference'];
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $foreignCurrencyId) {
 | 
			
		||||
                $response[$foreignCurrencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                    'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                    'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference']       = bcadd(
 | 
			
		||||
                    $response[$foreignCurrencyId]['difference'],
 | 
			
		||||
                    app('steam')->positive($journal['foreign_amount'])
 | 
			
		||||
                );
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference'];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -74,31 +74,31 @@ class TagController extends Controller
 | 
			
		||||
        $genericSet = $collector->getExtractedJournals();
 | 
			
		||||
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            if (0 !== $currencyId) {
 | 
			
		||||
                $response[$currencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$currencyId,
 | 
			
		||||
                    'currency_id'      => (string) $currencyId,
 | 
			
		||||
                    'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference'];
 | 
			
		||||
                $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $foreignCurrencyId) {
 | 
			
		||||
                $response[$foreignCurrencyId] ??= [
 | 
			
		||||
                    'difference'       => '0',
 | 
			
		||||
                    'difference_float' => 0,
 | 
			
		||||
                    'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                    'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                    'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                ];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference']       = bcadd(
 | 
			
		||||
                    $response[$foreignCurrencyId]['difference'],
 | 
			
		||||
                    app('steam')->positive($journal['foreign_amount'])
 | 
			
		||||
                );
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
 | 
			
		||||
                $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference'];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -132,8 +132,8 @@ class TagController extends Controller
 | 
			
		||||
 | 
			
		||||
        /** @var array $journal */
 | 
			
		||||
        foreach ($genericSet as $journal) {
 | 
			
		||||
            $currencyId        = (int)$journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int)$journal['foreign_currency_id'];
 | 
			
		||||
            $currencyId        = (int) $journal['currency_id'];
 | 
			
		||||
            $foreignCurrencyId = (int) $journal['foreign_currency_id'];
 | 
			
		||||
 | 
			
		||||
            /** @var array $tag */
 | 
			
		||||
            foreach ($journal['tags'] as $tag) {
 | 
			
		||||
@@ -144,15 +144,15 @@ class TagController extends Controller
 | 
			
		||||
                // on currency ID
 | 
			
		||||
                if (0 !== $currencyId) {
 | 
			
		||||
                    $response[$key] ??= [
 | 
			
		||||
                        'id'               => (string)$tagId,
 | 
			
		||||
                        'id'               => (string) $tagId,
 | 
			
		||||
                        'name'             => $tag['name'],
 | 
			
		||||
                        'difference'       => '0',
 | 
			
		||||
                        'difference_float' => 0,
 | 
			
		||||
                        'currency_id'      => (string)$currencyId,
 | 
			
		||||
                        'currency_id'      => (string) $currencyId,
 | 
			
		||||
                        'currency_code'    => $journal['currency_code'],
 | 
			
		||||
                    ];
 | 
			
		||||
                    $response[$key]['difference']       = bcadd($response[$key]['difference'], app('steam')->positive($journal['amount']));
 | 
			
		||||
                    $response[$key]['difference_float'] = (float)$response[$key]['difference'];
 | 
			
		||||
                    $response[$key]['difference_float'] = (float) $response[$key]['difference'];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // on foreign ID
 | 
			
		||||
@@ -160,14 +160,14 @@ class TagController extends Controller
 | 
			
		||||
                    $response[$foreignKey]                     = $journal[$foreignKey] ?? [
 | 
			
		||||
                        'difference'       => '0',
 | 
			
		||||
                        'difference_float' => 0,
 | 
			
		||||
                        'currency_id'      => (string)$foreignCurrencyId,
 | 
			
		||||
                        'currency_id'      => (string) $foreignCurrencyId,
 | 
			
		||||
                        'currency_code'    => $journal['foreign_currency_code'],
 | 
			
		||||
                    ];
 | 
			
		||||
                    $response[$foreignKey]['difference']       = bcadd(
 | 
			
		||||
                        $response[$foreignKey]['difference'],
 | 
			
		||||
                        app('steam')->positive($journal['foreign_amount'])
 | 
			
		||||
                    );
 | 
			
		||||
                    $response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // intentional float
 | 
			
		||||
                    $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -105,7 +105,7 @@ class ShowController extends Controller
 | 
			
		||||
                ->header('Expires', '0')
 | 
			
		||||
                ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
 | 
			
		||||
                ->header('Pragma', 'public')
 | 
			
		||||
                ->header('Content-Length', (string)strlen($content))
 | 
			
		||||
                ->header('Content-Length', (string) strlen($content))
 | 
			
		||||
            ;
 | 
			
		||||
 | 
			
		||||
            return $response;
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,38 @@ class ListController extends Controller
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This endpoint is documented at:
 | 
			
		||||
     * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAccountByPiggyBank
 | 
			
		||||
     *
 | 
			
		||||
     * List single resource.
 | 
			
		||||
     *
 | 
			
		||||
     * @throws FireflyException
 | 
			
		||||
     */
 | 
			
		||||
    public function accounts(PiggyBank $piggyBank): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        // types to get, page size:
 | 
			
		||||
        $pageSize    = $this->parameters->get('limit');
 | 
			
		||||
        $manager     = $this->getManager();
 | 
			
		||||
 | 
			
		||||
        $collection  = $piggyBank->accounts;
 | 
			
		||||
        $count       = $collection->count();
 | 
			
		||||
        $events      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
 | 
			
		||||
 | 
			
		||||
        // make paginator:
 | 
			
		||||
        $paginator   = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
 | 
			
		||||
        $paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
 | 
			
		||||
 | 
			
		||||
        /** @var AccountTransformer $transformer */
 | 
			
		||||
        $transformer = app(AccountTransformer::class);
 | 
			
		||||
        $transformer->setParameters($this->parameters);
 | 
			
		||||
 | 
			
		||||
        $resource    = new FractalCollection($events, $transformer, 'accounts');
 | 
			
		||||
        $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
 | 
			
		||||
 | 
			
		||||
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This endpoint is documented at:
 | 
			
		||||
     * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAttachmentByPiggyBank
 | 
			
		||||
@@ -119,36 +151,4 @@ class ListController extends Controller
 | 
			
		||||
 | 
			
		||||
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This endpoint is documented at:
 | 
			
		||||
     * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAccountByPiggyBank
 | 
			
		||||
     *
 | 
			
		||||
     * List single resource.
 | 
			
		||||
     *
 | 
			
		||||
     * @throws FireflyException
 | 
			
		||||
     */
 | 
			
		||||
    public function accounts(PiggyBank $piggyBank): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        // types to get, page size:
 | 
			
		||||
        $pageSize    = $this->parameters->get('limit');
 | 
			
		||||
        $manager     = $this->getManager();
 | 
			
		||||
 | 
			
		||||
        $collection  = $piggyBank->accounts;
 | 
			
		||||
        $count       = $collection->count();
 | 
			
		||||
        $events      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
 | 
			
		||||
 | 
			
		||||
        // make paginator:
 | 
			
		||||
        $paginator   = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
 | 
			
		||||
        $paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
 | 
			
		||||
 | 
			
		||||
        /** @var AccountTransformer $transformer */
 | 
			
		||||
        $transformer = app(AccountTransformer::class);
 | 
			
		||||
        $transformer->setParameters($this->parameters);
 | 
			
		||||
 | 
			
		||||
        $resource    = new FractalCollection($events, $transformer, 'accounts');
 | 
			
		||||
        $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
 | 
			
		||||
 | 
			
		||||
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -91,7 +91,7 @@ class ListController extends Controller
 | 
			
		||||
        // filter list on currency preference:
 | 
			
		||||
        $collection        = $unfiltered->filter(
 | 
			
		||||
            static function (Account $account) use ($currency, $accountRepository) {
 | 
			
		||||
                $currencyId = (int)$accountRepository->getMetaValue($account, 'currency_id');
 | 
			
		||||
                $currencyId = (int) $accountRepository->getMetaValue($account, 'currency_id');
 | 
			
		||||
 | 
			
		||||
                return $currencyId === $currency->id;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -63,8 +63,8 @@ class AccountController extends Controller
 | 
			
		||||
    public function search(Request $request): JsonResponse|Response
 | 
			
		||||
    {
 | 
			
		||||
        $manager     = $this->getManager();
 | 
			
		||||
        $query       = trim((string)$request->get('query'));
 | 
			
		||||
        $field       = trim((string)$request->get('field'));
 | 
			
		||||
        $query       = trim((string) $request->get('query'));
 | 
			
		||||
        $field       = trim((string) $request->get('field'));
 | 
			
		||||
        $type        = $request->get('type') ?? 'all';
 | 
			
		||||
        if ('' === $query || !in_array($field, $this->validFields, true)) {
 | 
			
		||||
            return response(null, 422);
 | 
			
		||||
 
 | 
			
		||||
@@ -47,8 +47,8 @@ class TransactionController extends Controller
 | 
			
		||||
    public function search(Request $request, SearchInterface $searcher): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        $manager      = $this->getManager();
 | 
			
		||||
        $fullQuery    = (string)$request->get('query');
 | 
			
		||||
        $page         = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
 | 
			
		||||
        $fullQuery    = (string) $request->get('query');
 | 
			
		||||
        $page         = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page');
 | 
			
		||||
        $pageSize     = $this->parameters->get('limit');
 | 
			
		||||
        $searcher->parseQuery($fullQuery);
 | 
			
		||||
        $searcher->setPage($page);
 | 
			
		||||
 
 | 
			
		||||
@@ -27,19 +27,21 @@ namespace FireflyIII\Api\V1\Controllers\Summary;
 | 
			
		||||
use Carbon\Carbon;
 | 
			
		||||
use FireflyIII\Api\V1\Controllers\Controller;
 | 
			
		||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
 | 
			
		||||
use FireflyIII\Enums\AccountTypeEnum;
 | 
			
		||||
use FireflyIII\Enums\TransactionTypeEnum;
 | 
			
		||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
 | 
			
		||||
use FireflyIII\Helpers\Report\NetWorthInterface;
 | 
			
		||||
use FireflyIII\Models\Account;
 | 
			
		||||
use FireflyIII\Models\AccountType;
 | 
			
		||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
 | 
			
		||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
 | 
			
		||||
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
 | 
			
		||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
 | 
			
		||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
 | 
			
		||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
 | 
			
		||||
use FireflyIII\Support\Facades\Amount;
 | 
			
		||||
use FireflyIII\User;
 | 
			
		||||
use Illuminate\Http\JsonResponse;
 | 
			
		||||
use Illuminate\Support\Facades\Log;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class BasicController
 | 
			
		||||
@@ -120,48 +122,53 @@ class BasicController extends Controller
 | 
			
		||||
 | 
			
		||||
    private function getBalanceInformation(Carbon $start, Carbon $end): array
 | 
			
		||||
    {
 | 
			
		||||
        // some config settings
 | 
			
		||||
        $convertToNative = app('preferences')->get('convert_to_native', false)->data;
 | 
			
		||||
        $default         = app('amount')->getDefaultCurrency();
 | 
			
		||||
        // prep some arrays:
 | 
			
		||||
        $incomes   = [];
 | 
			
		||||
        $expenses  = [];
 | 
			
		||||
        $sums      = [];
 | 
			
		||||
        $return    = [];
 | 
			
		||||
        $incomes         = [];
 | 
			
		||||
        $expenses        = [];
 | 
			
		||||
        $sums            = [];
 | 
			
		||||
        $return          = [];
 | 
			
		||||
 | 
			
		||||
        // collect income of user using the new group collector.
 | 
			
		||||
        /** @var GroupCollectorInterface $collector */
 | 
			
		||||
        $collector = app(GroupCollectorInterface::class);
 | 
			
		||||
        $collector       = app(GroupCollectorInterface::class);
 | 
			
		||||
        $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::DEPOSIT->value]);
 | 
			
		||||
 | 
			
		||||
        $set       = $collector->getExtractedJournals();
 | 
			
		||||
        $set             = $collector->getExtractedJournals();
 | 
			
		||||
 | 
			
		||||
        /** @var array $transactionJournal */
 | 
			
		||||
        foreach ($set as $transactionJournal) {
 | 
			
		||||
            $currencyId           = (int)$transactionJournal['currency_id'];
 | 
			
		||||
        /** @var array $journal */
 | 
			
		||||
        foreach ($set as $journal) {
 | 
			
		||||
            $currencyId           = $convertToNative ? $default->id : (int) $journal['currency_id'];
 | 
			
		||||
            $amount               = Amount::getAmountFromJournal($journal);
 | 
			
		||||
            $incomes[$currencyId] ??= '0';
 | 
			
		||||
            $incomes[$currencyId] = bcadd(
 | 
			
		||||
                $incomes[$currencyId],
 | 
			
		||||
                bcmul($transactionJournal['amount'], '-1')
 | 
			
		||||
                bcmul($amount, '-1')
 | 
			
		||||
            );
 | 
			
		||||
            $sums[$currencyId]    ??= '0';
 | 
			
		||||
            $sums[$currencyId]    = bcadd($sums[$currencyId], bcmul($transactionJournal['amount'], '-1'));
 | 
			
		||||
            $sums[$currencyId]    = bcadd($sums[$currencyId], bcmul($amount, '-1'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // collect expenses of user using the new group collector.
 | 
			
		||||
        /** @var GroupCollectorInterface $collector */
 | 
			
		||||
        $collector = app(GroupCollectorInterface::class);
 | 
			
		||||
        $collector       = app(GroupCollectorInterface::class);
 | 
			
		||||
        $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
 | 
			
		||||
        $set       = $collector->getExtractedJournals();
 | 
			
		||||
        $set             = $collector->getExtractedJournals();
 | 
			
		||||
 | 
			
		||||
        /** @var array $transactionJournal */
 | 
			
		||||
        foreach ($set as $transactionJournal) {
 | 
			
		||||
            $currencyId            = (int)$transactionJournal['currency_id'];
 | 
			
		||||
        /** @var array $journal */
 | 
			
		||||
        foreach ($set as $journal) {
 | 
			
		||||
            $currencyId            = $convertToNative ? $default->id : (int) $journal['currency_id'];
 | 
			
		||||
            $amount                = Amount::getAmountFromJournal($journal);
 | 
			
		||||
            $expenses[$currencyId] ??= '0';
 | 
			
		||||
            $expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']);
 | 
			
		||||
            $expenses[$currencyId] = bcadd($expenses[$currencyId], $amount);
 | 
			
		||||
            $sums[$currencyId]     ??= '0';
 | 
			
		||||
            $sums[$currencyId]     = bcadd($sums[$currencyId], $transactionJournal['amount']);
 | 
			
		||||
            $sums[$currencyId]     = bcadd($sums[$currencyId], $amount);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // format amounts:
 | 
			
		||||
        $keys      = array_keys($sums);
 | 
			
		||||
        $keys            = array_keys($sums);
 | 
			
		||||
        foreach ($keys as $currencyId) {
 | 
			
		||||
            $currency = $this->currencyRepos->find($currencyId);
 | 
			
		||||
            if (null === $currency) {
 | 
			
		||||
@@ -172,7 +179,7 @@ class BasicController extends Controller
 | 
			
		||||
                'key'                     => sprintf('balance-in-%s', $currency->code),
 | 
			
		||||
                'title'                   => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
 | 
			
		||||
                'monetary_value'          => $sums[$currencyId] ?? '0',
 | 
			
		||||
                'currency_id'             => (string)$currency->id,
 | 
			
		||||
                'currency_id'             => (string) $currency->id,
 | 
			
		||||
                'currency_code'           => $currency->code,
 | 
			
		||||
                'currency_symbol'         => $currency->symbol,
 | 
			
		||||
                'currency_decimal_places' => $currency->decimal_places,
 | 
			
		||||
@@ -185,7 +192,7 @@ class BasicController extends Controller
 | 
			
		||||
                'key'                     => sprintf('spent-in-%s', $currency->code),
 | 
			
		||||
                'title'                   => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
 | 
			
		||||
                'monetary_value'          => $expenses[$currencyId] ?? '0',
 | 
			
		||||
                'currency_id'             => (string)$currency->id,
 | 
			
		||||
                'currency_id'             => (string) $currency->id,
 | 
			
		||||
                'currency_code'           => $currency->code,
 | 
			
		||||
                'currency_symbol'         => $currency->symbol,
 | 
			
		||||
                'currency_decimal_places' => $currency->decimal_places,
 | 
			
		||||
@@ -197,7 +204,7 @@ class BasicController extends Controller
 | 
			
		||||
                'key'                     => sprintf('earned-in-%s', $currency->code),
 | 
			
		||||
                'title'                   => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
 | 
			
		||||
                'monetary_value'          => $incomes[$currencyId] ?? '0',
 | 
			
		||||
                'currency_id'             => (string)$currency->id,
 | 
			
		||||
                'currency_id'             => (string) $currency->id,
 | 
			
		||||
                'currency_code'           => $currency->code,
 | 
			
		||||
                'currency_symbol'         => $currency->symbol,
 | 
			
		||||
                'currency_decimal_places' => $currency->decimal_places,
 | 
			
		||||
@@ -231,7 +238,7 @@ class BasicController extends Controller
 | 
			
		||||
                'key'                     => sprintf('bills-paid-in-%s', $info['code']),
 | 
			
		||||
                'title'                   => trans('firefly.box_bill_paid_in_currency', ['currency' => $info['symbol']]),
 | 
			
		||||
                'monetary_value'          => $amount,
 | 
			
		||||
                'currency_id'             => (string)$info['id'],
 | 
			
		||||
                'currency_id'             => (string) $info['id'],
 | 
			
		||||
                'currency_code'           => $info['code'],
 | 
			
		||||
                'currency_symbol'         => $info['symbol'],
 | 
			
		||||
                'currency_decimal_places' => $info['decimal_places'],
 | 
			
		||||
@@ -250,7 +257,7 @@ class BasicController extends Controller
 | 
			
		||||
                'key'                     => sprintf('bills-unpaid-in-%s', $info['code']),
 | 
			
		||||
                'title'                   => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $info['symbol']]),
 | 
			
		||||
                'monetary_value'          => $amount,
 | 
			
		||||
                'currency_id'             => (string)$info['id'],
 | 
			
		||||
                'currency_id'             => (string) $info['id'],
 | 
			
		||||
                'currency_code'           => $info['code'],
 | 
			
		||||
                'currency_symbol'         => $info['symbol'],
 | 
			
		||||
                'currency_decimal_places' => $info['decimal_places'],
 | 
			
		||||
@@ -274,24 +281,27 @@ class BasicController extends Controller
 | 
			
		||||
        $available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
 | 
			
		||||
        $budgets   = $this->budgetRepository->getActiveBudgets();
 | 
			
		||||
        $spent     = $this->opsRepository->sumExpenses($start, $end, null, $budgets);
 | 
			
		||||
        $days      = (int) $today->diffInDays($end, true) + 1;
 | 
			
		||||
        Log::debug(sprintf('Now in getLeftToSpendInfo("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
 | 
			
		||||
 | 
			
		||||
        foreach ($spent as $row) {
 | 
			
		||||
            // either an amount was budgeted or 0 is available.
 | 
			
		||||
            $amount          = (string)($available[$row['currency_id']] ?? '0');
 | 
			
		||||
            $currencyId      = $row['currency_id'];
 | 
			
		||||
            $amount          = (string) ($available[$currencyId] ?? '0');
 | 
			
		||||
            $spentInCurrency = $row['sum'];
 | 
			
		||||
            $leftToSpend     = bcadd($amount, $spentInCurrency);
 | 
			
		||||
 | 
			
		||||
            $days            = (int)$today->diffInDays($end, true) + 1;
 | 
			
		||||
            $perDay          = '0';
 | 
			
		||||
            if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
 | 
			
		||||
                $perDay = bcdiv($leftToSpend, (string)$days);
 | 
			
		||||
                $perDay = bcdiv($leftToSpend, (string) $days);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum']));
 | 
			
		||||
 | 
			
		||||
            $return[]        = [
 | 
			
		||||
                'key'                     => sprintf('left-to-spend-in-%s', $row['currency_code']),
 | 
			
		||||
                'title'                   => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
 | 
			
		||||
                'monetary_value'          => $leftToSpend,
 | 
			
		||||
                'currency_id'             => (string)$row['currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $row['currency_id'],
 | 
			
		||||
                'currency_code'           => $row['currency_code'],
 | 
			
		||||
                'currency_symbol'         => $row['currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => $row['currency_decimal_places'],
 | 
			
		||||
@@ -311,9 +321,11 @@ class BasicController extends Controller
 | 
			
		||||
 | 
			
		||||
    private function getNetWorthInfo(Carbon $start, Carbon $end): array
 | 
			
		||||
    {
 | 
			
		||||
        Log::debug('getNetWorthInfo');
 | 
			
		||||
 | 
			
		||||
        /** @var User $user */
 | 
			
		||||
        $user           = auth()->user();
 | 
			
		||||
        $date           = today(config('app.timezone'))->startOfDay();
 | 
			
		||||
        $date           = now(config('app.timezone'));
 | 
			
		||||
        // start and end in the future? use $end
 | 
			
		||||
        if ($this->notInDateRange($date, $start, $end)) {
 | 
			
		||||
            /** @var Carbon $date */
 | 
			
		||||
@@ -323,9 +335,7 @@ class BasicController extends Controller
 | 
			
		||||
        /** @var NetWorthInterface $netWorthHelper */
 | 
			
		||||
        $netWorthHelper = app(NetWorthInterface::class);
 | 
			
		||||
        $netWorthHelper->setUser($user);
 | 
			
		||||
        $allAccounts    = $this->accountRepository->getActiveAccountsByType(
 | 
			
		||||
            [AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT]
 | 
			
		||||
        );
 | 
			
		||||
        $allAccounts    = $this->accountRepository->getActiveAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]);
 | 
			
		||||
 | 
			
		||||
        // filter list on preference of being included.
 | 
			
		||||
        $filtered       = $allAccounts->filter(
 | 
			
		||||
@@ -351,7 +361,7 @@ class BasicController extends Controller
 | 
			
		||||
                'key'                     => sprintf('net-worth-in-%s', $data['currency_code']),
 | 
			
		||||
                'title'                   => trans('firefly.box_net_worth_in_currency', ['currency' => $data['currency_symbol']]),
 | 
			
		||||
                'monetary_value'          => $amount,
 | 
			
		||||
                'currency_id'             => (string)$data['currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $data['currency_id'],
 | 
			
		||||
                'currency_code'           => $data['currency_code'],
 | 
			
		||||
                'currency_symbol'         => $data['currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => $data['currency_decimal_places'],
 | 
			
		||||
@@ -360,6 +370,7 @@ class BasicController extends Controller
 | 
			
		||||
                'sub_title'               => '',
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
        Log::debug('End of getNetWorthInfo');
 | 
			
		||||
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -101,8 +101,8 @@ class ConfigurationController extends Controller
 | 
			
		||||
 | 
			
		||||
        return [
 | 
			
		||||
            'is_demo_site'            => $isDemoSite?->data,
 | 
			
		||||
            'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
 | 
			
		||||
            'last_update_check'       => null === $lastCheck ? null : (int)$lastCheck->data,
 | 
			
		||||
            'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data,
 | 
			
		||||
            'last_update_check'       => null === $lastCheck ? null : (int) $lastCheck->data,
 | 
			
		||||
            'single_user_mode'        => $singleUser?->data,
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -83,12 +83,12 @@ class MoveTransactionsRequest extends FormRequest
 | 
			
		||||
        $data                = $validator->getData();
 | 
			
		||||
        $repository          = app(AccountRepositoryInterface::class);
 | 
			
		||||
        $repository->setUser(auth()->user());
 | 
			
		||||
        $original            = $repository->find((int)$data['original_account']);
 | 
			
		||||
        $destination         = $repository->find((int)$data['destination_account']);
 | 
			
		||||
        $original            = $repository->find((int) $data['original_account']);
 | 
			
		||||
        $destination         = $repository->find((int) $data['destination_account']);
 | 
			
		||||
 | 
			
		||||
        // not the same type:
 | 
			
		||||
        if ($original->accountType->type !== $destination->accountType->type) {
 | 
			
		||||
            $validator->errors()->add('title', (string)trans('validation.same_account_type'));
 | 
			
		||||
            $validator->errors()->add('title', (string) trans('validation.same_account_type'));
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -98,7 +98,7 @@ class MoveTransactionsRequest extends FormRequest
 | 
			
		||||
 | 
			
		||||
        // check different scenario's.
 | 
			
		||||
        if (null === $originalCurrency xor null === $destinationCurrency) {
 | 
			
		||||
            $validator->errors()->add('title', (string)trans('validation.same_account_currency'));
 | 
			
		||||
            $validator->errors()->add('title', (string) trans('validation.same_account_currency'));
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -107,7 +107,7 @@ class MoveTransactionsRequest extends FormRequest
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if ($originalCurrency->code !== $destinationCurrency->code) {
 | 
			
		||||
            $validator->errors()->add('title', (string)trans('validation.same_account_currency'));
 | 
			
		||||
            $validator->errors()->add('title', (string) trans('validation.same_account_currency'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ class ExportRequest extends FormRequest
 | 
			
		||||
 | 
			
		||||
        $accounts           = new Collection();
 | 
			
		||||
        foreach ($parts as $part) {
 | 
			
		||||
            $accountId = (int)$part;
 | 
			
		||||
            $accountId = (int) $part;
 | 
			
		||||
            if (0 !== $accountId) {
 | 
			
		||||
                $account = $repository->find($accountId);
 | 
			
		||||
                if (null !== $account && AccountType::ASSET === $account->accountType->type) {
 | 
			
		||||
 
 | 
			
		||||
@@ -88,7 +88,7 @@ class GenericRequest extends FormRequest
 | 
			
		||||
        $array      = $this->get('accounts');
 | 
			
		||||
        if (is_array($array)) {
 | 
			
		||||
            foreach ($array as $accountId) {
 | 
			
		||||
                $accountId = (int)$accountId;
 | 
			
		||||
                $accountId = (int) $accountId;
 | 
			
		||||
                $account   = $repository->find($accountId);
 | 
			
		||||
                if (null !== $account) {
 | 
			
		||||
                    $this->accounts->push($account);
 | 
			
		||||
@@ -114,7 +114,7 @@ class GenericRequest extends FormRequest
 | 
			
		||||
        $array      = $this->get('bills');
 | 
			
		||||
        if (is_array($array)) {
 | 
			
		||||
            foreach ($array as $billId) {
 | 
			
		||||
                $billId = (int)$billId;
 | 
			
		||||
                $billId = (int) $billId;
 | 
			
		||||
                $bill   = $repository->find($billId);
 | 
			
		||||
                if (null !== $bill) {
 | 
			
		||||
                    $this->bills->push($bill);
 | 
			
		||||
@@ -140,7 +140,7 @@ class GenericRequest extends FormRequest
 | 
			
		||||
        $array      = $this->get('budgets');
 | 
			
		||||
        if (is_array($array)) {
 | 
			
		||||
            foreach ($array as $budgetId) {
 | 
			
		||||
                $budgetId = (int)$budgetId;
 | 
			
		||||
                $budgetId = (int) $budgetId;
 | 
			
		||||
                $budget   = $repository->find($budgetId);
 | 
			
		||||
                if (null !== $budget) {
 | 
			
		||||
                    $this->budgets->push($budget);
 | 
			
		||||
@@ -166,7 +166,7 @@ class GenericRequest extends FormRequest
 | 
			
		||||
        $array      = $this->get('categories');
 | 
			
		||||
        if (is_array($array)) {
 | 
			
		||||
            foreach ($array as $categoryId) {
 | 
			
		||||
                $categoryId = (int)$categoryId;
 | 
			
		||||
                $categoryId = (int) $categoryId;
 | 
			
		||||
                $category   = $repository->find($categoryId);
 | 
			
		||||
                if (null !== $category) {
 | 
			
		||||
                    $this->categories->push($category);
 | 
			
		||||
@@ -240,7 +240,7 @@ class GenericRequest extends FormRequest
 | 
			
		||||
        $array      = $this->get('tags');
 | 
			
		||||
        if (is_array($array)) {
 | 
			
		||||
            foreach ($array as $tagId) {
 | 
			
		||||
                $tagId = (int)$tagId;
 | 
			
		||||
                $tagId = (int) $tagId;
 | 
			
		||||
                $tag   = $repository->find($tagId);
 | 
			
		||||
                if (null !== $tag) {
 | 
			
		||||
                    $this->tags->push($tag);
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ class Request extends FormRequest
 | 
			
		||||
                    $start = new Carbon($data['start']);
 | 
			
		||||
                    $end   = new Carbon($data['end']);
 | 
			
		||||
                    if ($end->isBefore($start)) {
 | 
			
		||||
                        $validator->errors()->add('end', (string)trans('validation.date_after'));
 | 
			
		||||
                        $validator->errors()->add('end', (string) trans('validation.date_after'));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -96,11 +96,11 @@ class StoreRequest extends FormRequest
 | 
			
		||||
        $validator->after(
 | 
			
		||||
            static function (Validator $validator): void {
 | 
			
		||||
                $data = $validator->getData();
 | 
			
		||||
                $min  = (string)($data['amount_min'] ?? '0');
 | 
			
		||||
                $max  = (string)($data['amount_max'] ?? '0');
 | 
			
		||||
                $min  = (string) ($data['amount_min'] ?? '0');
 | 
			
		||||
                $max  = (string) ($data['amount_max'] ?? '0');
 | 
			
		||||
 | 
			
		||||
                if (1 === bccomp($min, $max)) {
 | 
			
		||||
                    $validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max'));
 | 
			
		||||
                    $validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max'));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
                    $max = $data['amount_max'] ?? '0';
 | 
			
		||||
 | 
			
		||||
                    if (1 === bccomp($min, $max)) {
 | 
			
		||||
                        $validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max'));
 | 
			
		||||
                        $validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max'));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,25 @@ class StoreRequest extends FormRequest
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function parseAccounts(mixed $array): array
 | 
			
		||||
    {
 | 
			
		||||
        if (!is_array($array)) {
 | 
			
		||||
            return [];
 | 
			
		||||
        }
 | 
			
		||||
        $return = [];
 | 
			
		||||
        foreach ($array as $entry) {
 | 
			
		||||
            if (!is_array($entry)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            $return[] = [
 | 
			
		||||
                'account_id'     => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
 | 
			
		||||
                'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The rules that the incoming request must be matched against.
 | 
			
		||||
     */
 | 
			
		||||
@@ -109,7 +128,7 @@ class StoreRequest extends FormRequest
 | 
			
		||||
                            // check currency here.
 | 
			
		||||
                            $accountCurrency = $repository->getAccountCurrency($account);
 | 
			
		||||
                            $isMultiCurrency = $repository->getMetaValue($account, 'is_multi_currency');
 | 
			
		||||
                            $currentAmount   = bcadd($currentAmount, (string)($array['current_amount'] ?? '0'));
 | 
			
		||||
                            $currentAmount   = bcadd($currentAmount, (string) ($array['current_amount'] ?? '0'));
 | 
			
		||||
                            if ($accountCurrency->id !== $currency->id && 'true' !== $isMultiCurrency) {
 | 
			
		||||
                                $validator->errors()->add(sprintf('accounts.%d', $index), trans('validation.invalid_account_currency'));
 | 
			
		||||
                            }
 | 
			
		||||
@@ -130,25 +149,6 @@ class StoreRequest extends FormRequest
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function parseAccounts(mixed $array): array
 | 
			
		||||
    {
 | 
			
		||||
        if (!is_array($array)) {
 | 
			
		||||
            return [];
 | 
			
		||||
        }
 | 
			
		||||
        $return = [];
 | 
			
		||||
        foreach ($array as $entry) {
 | 
			
		||||
            if (!is_array($entry)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            $return[] = [
 | 
			
		||||
                'account_id'     => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
 | 
			
		||||
                'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getCurrencyFromData(array $data): TransactionCurrency
 | 
			
		||||
    {
 | 
			
		||||
        if (array_key_exists('transaction_currency_code', $data) && '' !== (string) $data['transaction_currency_code']) {
 | 
			
		||||
 
 | 
			
		||||
@@ -121,10 +121,10 @@ class StoreRequest extends FormRequest
 | 
			
		||||
                $current['moment'] = $repetition['moment'];
 | 
			
		||||
            }
 | 
			
		||||
            if (array_key_exists('skip', $repetition)) {
 | 
			
		||||
                $current['skip'] = (int)$repetition['skip'];
 | 
			
		||||
                $current['skip'] = (int) $repetition['skip'];
 | 
			
		||||
            }
 | 
			
		||||
            if (array_key_exists('weekend', $repetition)) {
 | 
			
		||||
                $current['weekend'] = (int)$repetition['weekend'];
 | 
			
		||||
                $current['weekend'] = (int) $repetition['weekend'];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $return[] = $current;
 | 
			
		||||
 
 | 
			
		||||
@@ -101,15 +101,15 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('moment', $repetition)) {
 | 
			
		||||
                $current['moment'] = (string)$repetition['moment'];
 | 
			
		||||
                $current['moment'] = (string) $repetition['moment'];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('skip', $repetition)) {
 | 
			
		||||
                $current['skip'] = (int)$repetition['skip'];
 | 
			
		||||
                $current['skip'] = (int) $repetition['skip'];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (array_key_exists('weekend', $repetition)) {
 | 
			
		||||
                $current['weekend'] = (int)$repetition['weekend'];
 | 
			
		||||
                $current['weekend'] = (int) $repetition['weekend'];
 | 
			
		||||
            }
 | 
			
		||||
            $return[] = $current;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -74,9 +74,9 @@ class StoreRequest extends FormRequest
 | 
			
		||||
                $return[] = [
 | 
			
		||||
                    'type'            => $trigger['type'] ?? '',
 | 
			
		||||
                    'value'           => $trigger['value'] ?? null,
 | 
			
		||||
                    'prohibited'      => $this->convertBoolean((string)($trigger['prohibited'] ?? 'false')),
 | 
			
		||||
                    'active'          => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
 | 
			
		||||
                    'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
 | 
			
		||||
                    'prohibited'      => $this->convertBoolean((string) ($trigger['prohibited'] ?? 'false')),
 | 
			
		||||
                    'active'          => $this->convertBoolean((string) ($trigger['active'] ?? 'true')),
 | 
			
		||||
                    'stop_processing' => $this->convertBoolean((string) ($trigger['stop_processing'] ?? 'false')),
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -93,8 +93,8 @@ class StoreRequest extends FormRequest
 | 
			
		||||
                $return[] = [
 | 
			
		||||
                    'type'            => $action['type'],
 | 
			
		||||
                    'value'           => $action['value'],
 | 
			
		||||
                    'active'          => $this->convertBoolean((string)($action['active'] ?? 'true')),
 | 
			
		||||
                    'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
 | 
			
		||||
                    'active'          => $this->convertBoolean((string) ($action['active'] ?? 'true')),
 | 
			
		||||
                    'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')),
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -161,7 +161,7 @@ class StoreRequest extends FormRequest
 | 
			
		||||
        $triggers = $data['triggers'] ?? [];
 | 
			
		||||
        // need at least one trigger
 | 
			
		||||
        if (!is_countable($triggers) || 0 === count($triggers)) {
 | 
			
		||||
            $validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
 | 
			
		||||
            $validator->errors()->add('title', (string) trans('validation.at_least_one_trigger'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -174,7 +174,7 @@ class StoreRequest extends FormRequest
 | 
			
		||||
        $actions = $data['actions'] ?? [];
 | 
			
		||||
        // need at least one trigger
 | 
			
		||||
        if (!is_countable($actions) || 0 === count($actions)) {
 | 
			
		||||
            $validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
 | 
			
		||||
            $validator->errors()->add('title', (string) trans('validation.at_least_one_action'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -203,7 +203,7 @@ class StoreRequest extends FormRequest
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (true === $allInactive) {
 | 
			
		||||
            $validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_trigger'));
 | 
			
		||||
            $validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_trigger'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -232,7 +232,7 @@ class StoreRequest extends FormRequest
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (true === $allInactive) {
 | 
			
		||||
            $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
 | 
			
		||||
            $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_action'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ class TestRequest extends FormRequest
 | 
			
		||||
 | 
			
		||||
    private function getPage(): int
 | 
			
		||||
    {
 | 
			
		||||
        return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
 | 
			
		||||
        return 0 === (int) $this->query('page') ? 1 : (int) $this->query('page');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getDate(string $field): ?Carbon
 | 
			
		||||
@@ -58,7 +58,7 @@ class TestRequest extends FormRequest
 | 
			
		||||
        if (is_array($value)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        $value = (string)$value;
 | 
			
		||||
        $value = (string) $value;
 | 
			
		||||
 | 
			
		||||
        return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ class TriggerRequest extends FormRequest
 | 
			
		||||
        if (is_array($value)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        $value = (string)$value;
 | 
			
		||||
        $value = (string) $value;
 | 
			
		||||
 | 
			
		||||
        return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -109,8 +109,8 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
                $return[] = [
 | 
			
		||||
                    'type'            => $action['type'],
 | 
			
		||||
                    'value'           => $action['value'],
 | 
			
		||||
                    'active'          => $this->convertBoolean((string)($action['active'] ?? 'false')),
 | 
			
		||||
                    'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
 | 
			
		||||
                    'active'          => $this->convertBoolean((string) ($action['active'] ?? 'false')),
 | 
			
		||||
                    'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')),
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -181,7 +181,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
        $triggers = $data['triggers'] ?? null;
 | 
			
		||||
        // need at least one trigger
 | 
			
		||||
        if (is_array($triggers) && 0 === count($triggers)) {
 | 
			
		||||
            $validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
 | 
			
		||||
            $validator->errors()->add('title', (string) trans('validation.at_least_one_trigger'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -208,7 +208,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (true === $allInactive) {
 | 
			
		||||
            $validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_trigger'));
 | 
			
		||||
            $validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_trigger'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -221,7 +221,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
        $actions = $data['actions'] ?? null;
 | 
			
		||||
        // need at least one action
 | 
			
		||||
        if (is_array($actions) && 0 === count($actions)) {
 | 
			
		||||
            $validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
 | 
			
		||||
            $validator->errors()->add('title', (string) trans('validation.at_least_one_action'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -249,7 +249,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (true === $allInactive) {
 | 
			
		||||
            $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
 | 
			
		||||
            $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_action'));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ class TestRequest extends FormRequest
 | 
			
		||||
        if (is_array($value)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        $value = (string)$value;
 | 
			
		||||
        $value = (string) $value;
 | 
			
		||||
 | 
			
		||||
        return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ class TriggerRequest extends FormRequest
 | 
			
		||||
        if (is_array($value)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        $value = (string)$value;
 | 
			
		||||
        $value = (string) $value;
 | 
			
		||||
 | 
			
		||||
        return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -84,73 +84,73 @@ class StoreRequest extends FormRequest
 | 
			
		||||
            $return[] = [
 | 
			
		||||
                'type'                  => $this->clearString($object['type']),
 | 
			
		||||
                'date'                  => $this->dateFromValue($object['date']),
 | 
			
		||||
                'order'                 => $this->integerFromValue((string)$object['order']),
 | 
			
		||||
                'order'                 => $this->integerFromValue((string) $object['order']),
 | 
			
		||||
 | 
			
		||||
                'currency_id'           => $this->integerFromValue((string)$object['currency_id']),
 | 
			
		||||
                'currency_code'         => $this->clearString((string)$object['currency_code']),
 | 
			
		||||
                'currency_id'           => $this->integerFromValue((string) $object['currency_id']),
 | 
			
		||||
                'currency_code'         => $this->clearString((string) $object['currency_code']),
 | 
			
		||||
 | 
			
		||||
                // foreign currency info:
 | 
			
		||||
                'foreign_currency_id'   => $this->integerFromValue((string)$object['foreign_currency_id']),
 | 
			
		||||
                'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code']),
 | 
			
		||||
                'foreign_currency_id'   => $this->integerFromValue((string) $object['foreign_currency_id']),
 | 
			
		||||
                'foreign_currency_code' => $this->clearString((string) $object['foreign_currency_code']),
 | 
			
		||||
 | 
			
		||||
                // amount and foreign amount. Cannot be 0.
 | 
			
		||||
                'amount'                => $this->clearString((string)$object['amount']),
 | 
			
		||||
                'foreign_amount'        => $this->clearString((string)$object['foreign_amount']),
 | 
			
		||||
                'amount'                => $this->clearString((string) $object['amount']),
 | 
			
		||||
                'foreign_amount'        => $this->clearString((string) $object['foreign_amount']),
 | 
			
		||||
 | 
			
		||||
                // description.
 | 
			
		||||
                'description'           => $this->clearString($object['description']),
 | 
			
		||||
 | 
			
		||||
                // source of transaction. If everything is null, assume cash account.
 | 
			
		||||
                'source_id'             => $this->integerFromValue((string)$object['source_id']),
 | 
			
		||||
                'source_name'           => $this->clearString((string)$object['source_name']),
 | 
			
		||||
                'source_iban'           => $this->clearIban((string)$object['source_iban']),
 | 
			
		||||
                'source_number'         => $this->clearString((string)$object['source_number']),
 | 
			
		||||
                'source_bic'            => $this->clearString((string)$object['source_bic']),
 | 
			
		||||
                'source_id'             => $this->integerFromValue((string) $object['source_id']),
 | 
			
		||||
                'source_name'           => $this->clearString((string) $object['source_name']),
 | 
			
		||||
                'source_iban'           => $this->clearIban((string) $object['source_iban']),
 | 
			
		||||
                'source_number'         => $this->clearString((string) $object['source_number']),
 | 
			
		||||
                'source_bic'            => $this->clearString((string) $object['source_bic']),
 | 
			
		||||
 | 
			
		||||
                // destination of transaction. If everything is null, assume cash account.
 | 
			
		||||
                'destination_id'        => $this->integerFromValue((string)$object['destination_id']),
 | 
			
		||||
                'destination_name'      => $this->clearString((string)$object['destination_name']),
 | 
			
		||||
                'destination_iban'      => $this->clearIban((string)$object['destination_iban']),
 | 
			
		||||
                'destination_number'    => $this->clearString((string)$object['destination_number']),
 | 
			
		||||
                'destination_bic'       => $this->clearString((string)$object['destination_bic']),
 | 
			
		||||
                'destination_id'        => $this->integerFromValue((string) $object['destination_id']),
 | 
			
		||||
                'destination_name'      => $this->clearString((string) $object['destination_name']),
 | 
			
		||||
                'destination_iban'      => $this->clearIban((string) $object['destination_iban']),
 | 
			
		||||
                'destination_number'    => $this->clearString((string) $object['destination_number']),
 | 
			
		||||
                'destination_bic'       => $this->clearString((string) $object['destination_bic']),
 | 
			
		||||
 | 
			
		||||
                // budget info
 | 
			
		||||
                'budget_id'             => $this->integerFromValue((string)$object['budget_id']),
 | 
			
		||||
                'budget_name'           => $this->clearString((string)$object['budget_name']),
 | 
			
		||||
                'budget_id'             => $this->integerFromValue((string) $object['budget_id']),
 | 
			
		||||
                'budget_name'           => $this->clearString((string) $object['budget_name']),
 | 
			
		||||
 | 
			
		||||
                // category info
 | 
			
		||||
                'category_id'           => $this->integerFromValue((string)$object['category_id']),
 | 
			
		||||
                'category_name'         => $this->clearString((string)$object['category_name']),
 | 
			
		||||
                'category_id'           => $this->integerFromValue((string) $object['category_id']),
 | 
			
		||||
                'category_name'         => $this->clearString((string) $object['category_name']),
 | 
			
		||||
 | 
			
		||||
                // journal bill reference. Optional. Will only work for withdrawals
 | 
			
		||||
                'bill_id'               => $this->integerFromValue((string)$object['bill_id']),
 | 
			
		||||
                'bill_name'             => $this->clearString((string)$object['bill_name']),
 | 
			
		||||
                'bill_id'               => $this->integerFromValue((string) $object['bill_id']),
 | 
			
		||||
                'bill_name'             => $this->clearString((string) $object['bill_name']),
 | 
			
		||||
 | 
			
		||||
                // piggy bank reference. Optional. Will only work for transfers
 | 
			
		||||
                'piggy_bank_id'         => $this->integerFromValue((string)$object['piggy_bank_id']),
 | 
			
		||||
                'piggy_bank_name'       => $this->clearString((string)$object['piggy_bank_name']),
 | 
			
		||||
                'piggy_bank_id'         => $this->integerFromValue((string) $object['piggy_bank_id']),
 | 
			
		||||
                'piggy_bank_name'       => $this->clearString((string) $object['piggy_bank_name']),
 | 
			
		||||
 | 
			
		||||
                // some other interesting properties
 | 
			
		||||
                'reconciled'            => $this->convertBoolean((string)$object['reconciled']),
 | 
			
		||||
                'notes'                 => $this->clearStringKeepNewlines((string)$object['notes']),
 | 
			
		||||
                'reconciled'            => $this->convertBoolean((string) $object['reconciled']),
 | 
			
		||||
                'notes'                 => $this->clearStringKeepNewlines((string) $object['notes']),
 | 
			
		||||
                'tags'                  => $this->arrayFromValue($object['tags']),
 | 
			
		||||
 | 
			
		||||
                // all custom fields:
 | 
			
		||||
                'internal_reference'    => $this->clearString((string)$object['internal_reference']),
 | 
			
		||||
                'external_id'           => $this->clearString((string)$object['external_id']),
 | 
			
		||||
                'internal_reference'    => $this->clearString((string) $object['internal_reference']),
 | 
			
		||||
                'external_id'           => $this->clearString((string) $object['external_id']),
 | 
			
		||||
                'original_source'       => sprintf('ff3-v%s', config('firefly.version')),
 | 
			
		||||
                'recurrence_id'         => $this->integerFromValue($object['recurrence_id']),
 | 
			
		||||
                'bunq_payment_id'       => $this->clearString((string)$object['bunq_payment_id']),
 | 
			
		||||
                'external_url'          => $this->clearString((string)$object['external_url']),
 | 
			
		||||
                'bunq_payment_id'       => $this->clearString((string) $object['bunq_payment_id']),
 | 
			
		||||
                'external_url'          => $this->clearString((string) $object['external_url']),
 | 
			
		||||
 | 
			
		||||
                'sepa_cc'               => $this->clearString((string)$object['sepa_cc']),
 | 
			
		||||
                'sepa_ct_op'            => $this->clearString((string)$object['sepa_ct_op']),
 | 
			
		||||
                'sepa_ct_id'            => $this->clearString((string)$object['sepa_ct_id']),
 | 
			
		||||
                'sepa_db'               => $this->clearString((string)$object['sepa_db']),
 | 
			
		||||
                'sepa_country'          => $this->clearString((string)$object['sepa_country']),
 | 
			
		||||
                'sepa_ep'               => $this->clearString((string)$object['sepa_ep']),
 | 
			
		||||
                'sepa_ci'               => $this->clearString((string)$object['sepa_ci']),
 | 
			
		||||
                'sepa_batch_id'         => $this->clearString((string)$object['sepa_batch_id']),
 | 
			
		||||
                'sepa_cc'               => $this->clearString((string) $object['sepa_cc']),
 | 
			
		||||
                'sepa_ct_op'            => $this->clearString((string) $object['sepa_ct_op']),
 | 
			
		||||
                'sepa_ct_id'            => $this->clearString((string) $object['sepa_ct_id']),
 | 
			
		||||
                'sepa_db'               => $this->clearString((string) $object['sepa_db']),
 | 
			
		||||
                'sepa_country'          => $this->clearString((string) $object['sepa_country']),
 | 
			
		||||
                'sepa_ep'               => $this->clearString((string) $object['sepa_ep']),
 | 
			
		||||
                'sepa_ci'               => $this->clearString((string) $object['sepa_ci']),
 | 
			
		||||
                'sepa_batch_id'         => $this->clearString((string) $object['sepa_batch_id']),
 | 
			
		||||
                // custom date fields. Must be Carbon objects. Presence is optional.
 | 
			
		||||
                'interest_date'         => $this->dateFromValue($object['interest_date']),
 | 
			
		||||
                'book_date'             => $this->dateFromValue($object['book_date']),
 | 
			
		||||
 
 | 
			
		||||
@@ -137,7 +137,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->integerFields as $fieldName) {
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                $current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]);
 | 
			
		||||
                $current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -152,7 +152,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->stringFields as $fieldName) {
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                $current[$fieldName] = $this->clearString((string)$transaction[$fieldName]);
 | 
			
		||||
                $current[$fieldName] = $this->clearString((string) $transaction[$fieldName]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -167,7 +167,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->textareaFields as $fieldName) {
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                $current[$fieldName] = $this->clearStringKeepNewlines((string)$transaction[$fieldName]); // keep newlines
 | 
			
		||||
                $current[$fieldName] = $this->clearStringKeepNewlines((string) $transaction[$fieldName]); // keep newlines
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -183,8 +183,8 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
        foreach ($this->dateFields as $fieldName) {
 | 
			
		||||
            app('log')->debug(sprintf('Now at date field %s', $fieldName));
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                app('log')->debug(sprintf('New value: "%s"', (string)$transaction[$fieldName]));
 | 
			
		||||
                $current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]);
 | 
			
		||||
                app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
 | 
			
		||||
                $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -199,7 +199,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->booleanFields as $fieldName) {
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                $current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]);
 | 
			
		||||
                $current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -234,7 +234,7 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
                    $current[$fieldName] = sprintf('%.12f', $value);
 | 
			
		||||
                }
 | 
			
		||||
                if (!is_float($value)) {
 | 
			
		||||
                    $current[$fieldName] = (string)$value;
 | 
			
		||||
                    $current[$fieldName] = (string) $value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -98,8 +98,8 @@ class StoreRequest extends FormRequest
 | 
			
		||||
        $journalRepos->setUser($user);
 | 
			
		||||
 | 
			
		||||
        $data         = $validator->getData();
 | 
			
		||||
        $inwardId     = (int)($data['inward_id'] ?? 0);
 | 
			
		||||
        $outwardId    = (int)($data['outward_id'] ?? 0);
 | 
			
		||||
        $inwardId     = (int) ($data['inward_id'] ?? 0);
 | 
			
		||||
        $outwardId    = (int) ($data['outward_id'] ?? 0);
 | 
			
		||||
        $inward       = $journalRepos->find($inwardId);
 | 
			
		||||
        $outward      = $journalRepos->find($outwardId);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -100,8 +100,8 @@ class UpdateRequest extends FormRequest
 | 
			
		||||
 | 
			
		||||
        $inwardId     = $data['inward_id'] ?? $existing->source_id;
 | 
			
		||||
        $outwardId    = $data['outward_id'] ?? $existing->destination_id;
 | 
			
		||||
        $inward       = $journalRepos->find((int)$inwardId);
 | 
			
		||||
        $outward      = $journalRepos->find((int)$outwardId);
 | 
			
		||||
        $inward       = $journalRepos->find((int) $inwardId);
 | 
			
		||||
        $outward      = $journalRepos->find((int) $outwardId);
 | 
			
		||||
        if (null === $inward) {
 | 
			
		||||
            $inward = $existing->source;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,9 +55,9 @@ class CreateRequest extends FormRequest
 | 
			
		||||
 | 
			
		||||
        // this is the way.
 | 
			
		||||
        $return             = $this->getAllData($fields);
 | 
			
		||||
        $return['trigger']  = $triggers[$return['trigger']] ?? (int)$return['trigger'];
 | 
			
		||||
        $return['response'] = $responses[$return['response']] ?? (int)$return['response'];
 | 
			
		||||
        $return['delivery'] = $deliveries[$return['delivery']] ?? (int)$return['delivery'];
 | 
			
		||||
        $return['trigger']  = $triggers[$return['trigger']] ?? (int) $return['trigger'];
 | 
			
		||||
        $return['response'] = $responses[$return['response']] ?? (int) $return['response'];
 | 
			
		||||
        $return['delivery'] = $deliveries[$return['delivery']] ?? (int) $return['delivery'];
 | 
			
		||||
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -94,7 +94,7 @@ class UserUpdateRequest extends FormRequest
 | 
			
		||||
                $isAdmin = auth()->user()->hasRole('owner');
 | 
			
		||||
                // not admin, and not own user?
 | 
			
		||||
                if (auth()->check() && false === $isAdmin && $current?->id !== auth()->user()->id) {
 | 
			
		||||
                    $validator->errors()->add('email', (string)trans('validation.invalid_selection'));
 | 
			
		||||
                    $validator->errors()->add('email', (string) trans('validation.invalid_selection'));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ class PreferenceStoreRequest extends FormRequest
 | 
			
		||||
            $array['data'] = false;
 | 
			
		||||
        }
 | 
			
		||||
        if (is_numeric($array['data'])) {
 | 
			
		||||
            $array['data'] = (float)$array['data']; // intentional float.
 | 
			
		||||
            $array['data'] = (float) $array['data']; // intentional float.
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $array;
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ class PreferenceUpdateRequest extends FormRequest
 | 
			
		||||
            $array['data'] = false;
 | 
			
		||||
        }
 | 
			
		||||
        if (is_numeric($array['data'])) {
 | 
			
		||||
            $array['data'] = (float)$array['data']; // intentional float.
 | 
			
		||||
            $array['data'] = (float) $array['data']; // intentional float.
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $array;
 | 
			
		||||
 
 | 
			
		||||
@@ -40,9 +40,9 @@ use Illuminate\Support\Facades\Log;
 | 
			
		||||
 */
 | 
			
		||||
class AccountController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
    private TransactionCurrency        $default;
 | 
			
		||||
    private ExchangeRateConverter      $converter;
 | 
			
		||||
    private TransactionCurrency        $default;
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * AccountController constructor.
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@ class CategoryController extends Controller
 | 
			
		||||
        $filtered        = $result->map(
 | 
			
		||||
            static function (Category $item) {
 | 
			
		||||
                return [
 | 
			
		||||
                    'id'    => (string)$item->id,
 | 
			
		||||
                    'id'    => (string) $item->id,
 | 
			
		||||
                    'title' => $item->name,
 | 
			
		||||
                    'meta'  => [],
 | 
			
		||||
                ];
 | 
			
		||||
 
 | 
			
		||||
@@ -45,9 +45,9 @@ class AccountController extends Controller
 | 
			
		||||
    use CollectsAccountsFromFilter;
 | 
			
		||||
    use ValidatesUserGroupTrait;
 | 
			
		||||
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
    private ChartData                  $chartData;
 | 
			
		||||
    private TransactionCurrency        $default;
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
@@ -92,11 +92,11 @@ class AccountController extends Controller
 | 
			
		||||
     */
 | 
			
		||||
    private function renderAccountData(array $params, Account $account): void
 | 
			
		||||
    {
 | 
			
		||||
        $currency          = $this->repository->getAccountCurrency($account);
 | 
			
		||||
        $currency       = $this->repository->getAccountCurrency($account);
 | 
			
		||||
        if (null === $currency) {
 | 
			
		||||
            $currency = $this->default;
 | 
			
		||||
        }
 | 
			
		||||
        $currentSet        = [
 | 
			
		||||
        $currentSet     = [
 | 
			
		||||
            'label'                          => $account->name,
 | 
			
		||||
 | 
			
		||||
            // the currency that belongs to the account.
 | 
			
		||||
@@ -117,23 +117,22 @@ class AccountController extends Controller
 | 
			
		||||
            'entries'                        => [],
 | 
			
		||||
            'native_entries'                 => [],
 | 
			
		||||
        ];
 | 
			
		||||
        $currentStart      = clone $params['start'];
 | 
			
		||||
        $range             = app('steam')->balanceInRange($account, $params['start'], clone $params['end'], $currency);
 | 
			
		||||
        $rangeConverted    = app('steam')->balanceInRangeConverted($account, $params['start'], clone $params['end'], $this->default);
 | 
			
		||||
        $currentStart   = clone $params['start'];
 | 
			
		||||
        $range          = app('steam')->finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative);
 | 
			
		||||
 | 
			
		||||
        $previous          = array_values($range)[0];
 | 
			
		||||
        $previousConverted = array_values($rangeConverted)[0];
 | 
			
		||||
        $previous       = array_values($range)[0]['balance'];
 | 
			
		||||
        $previousNative = array_values($range)[0]['native_balance'];
 | 
			
		||||
        while ($currentStart <= $params['end']) {
 | 
			
		||||
            $format                               = $currentStart->format('Y-m-d');
 | 
			
		||||
            $label                                = $currentStart->toAtomString();
 | 
			
		||||
            $balance                              = array_key_exists($format, $range) ? $range[$format] : $previous;
 | 
			
		||||
            $balanceConverted                     = array_key_exists($format, $rangeConverted) ? $rangeConverted[$format] : $previousConverted;
 | 
			
		||||
            $balance                              = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
 | 
			
		||||
            $balanceNative                        = array_key_exists($format, $range) ? $range[$format]['balance_native'] : $previousNative;
 | 
			
		||||
            $previous                             = $balance;
 | 
			
		||||
            $previousConverted                    = $balanceConverted;
 | 
			
		||||
            $previousNative                       = $balanceNative;
 | 
			
		||||
 | 
			
		||||
            $currentStart->addDay();
 | 
			
		||||
            $currentSet['entries'][$label]        = $balance;
 | 
			
		||||
            $currentSet['native_entries'][$label] = $balanceConverted;
 | 
			
		||||
            $currentSet['native_entries'][$label] = $balanceNative;
 | 
			
		||||
        }
 | 
			
		||||
        $this->chartData->add($currentSet);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -45,9 +45,10 @@ class BalanceController extends Controller
 | 
			
		||||
    use CleansChartData;
 | 
			
		||||
    use CollectsAccountsFromFilter;
 | 
			
		||||
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
    private GroupCollectorInterface    $collector;
 | 
			
		||||
    private ChartData                  $chartData;
 | 
			
		||||
    private GroupCollectorInterface    $collector;
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    // private TransactionCurrency        $default;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
 
 | 
			
		||||
@@ -54,9 +54,10 @@ class Controller extends BaseController
 | 
			
		||||
{
 | 
			
		||||
    use ValidatesUserGroupTrait;
 | 
			
		||||
 | 
			
		||||
    protected const string CONTENT_TYPE = 'application/vnd.api+json';
 | 
			
		||||
    protected const string CONTENT_TYPE     = 'application/vnd.api+json';
 | 
			
		||||
    protected array        $acceptedRoles   = [UserRoleEnum::READ_ONLY];
 | 
			
		||||
    protected ParameterBag $parameters;
 | 
			
		||||
    protected array $acceptedRoles      = [UserRoleEnum::READ_ONLY];
 | 
			
		||||
    protected bool         $convertToNative = false;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
@@ -81,7 +82,7 @@ class Controller extends BaseController
 | 
			
		||||
        $bag->set('limit', 50);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            $page = (int)request()->get('page');
 | 
			
		||||
            $page = (int) request()->get('page');
 | 
			
		||||
        } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
 | 
			
		||||
            $page = 1;
 | 
			
		||||
        }
 | 
			
		||||
@@ -92,8 +93,8 @@ class Controller extends BaseController
 | 
			
		||||
        if ($page < 1) {
 | 
			
		||||
            $page = 1;
 | 
			
		||||
        }
 | 
			
		||||
        if ($page > (2 ^ 16)) {
 | 
			
		||||
            $page = (2 ^ 16);
 | 
			
		||||
        if ($page > 2 ** 16) {
 | 
			
		||||
            $page = 2 ** 16;
 | 
			
		||||
        }
 | 
			
		||||
        $bag->set('page', $page);
 | 
			
		||||
 | 
			
		||||
@@ -111,10 +112,10 @@ class Controller extends BaseController
 | 
			
		||||
            }
 | 
			
		||||
            if (null !== $date) {
 | 
			
		||||
                try {
 | 
			
		||||
                    $obj = Carbon::parse((string)$date, config('app.timezone'));
 | 
			
		||||
                    $obj = Carbon::parse((string) $date, config('app.timezone'));
 | 
			
		||||
                } catch (InvalidDateException|InvalidFormatException $e) {
 | 
			
		||||
                    // don't care
 | 
			
		||||
                    app('log')->warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', substr((string)$date, 0, 20), $e->getMessage()));
 | 
			
		||||
                    app('log')->warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', substr((string) $date, 0, 20), $e->getMessage()));
 | 
			
		||||
                }
 | 
			
		||||
                // out of range? set to null.
 | 
			
		||||
                if (null !== $obj && ($obj->year <= 1900 || $obj->year > 2099)) {
 | 
			
		||||
@@ -138,11 +139,11 @@ class Controller extends BaseController
 | 
			
		||||
                $value = null;
 | 
			
		||||
            }
 | 
			
		||||
            if (null !== $value) {
 | 
			
		||||
                $bag->set($integer, (int)$value);
 | 
			
		||||
                $bag->set($integer, (int) $value);
 | 
			
		||||
            }
 | 
			
		||||
            if (null === $value && 'limit' === $integer && auth()->check()) {
 | 
			
		||||
                // set default for user:
 | 
			
		||||
                $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
 | 
			
		||||
                $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
 | 
			
		||||
                $bag->set($integer, $pageSize);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -48,6 +48,7 @@ class AccountController extends Controller
 | 
			
		||||
    use Actions\DetachRelationship;
 | 
			
		||||
 | 
			
		||||
    use Actions\FetchMany;
 | 
			
		||||
 | 
			
		||||
    // use Actions\FetchOne;
 | 
			
		||||
    use Actions\FetchRelated;
 | 
			
		||||
    use Actions\FetchRelationship;
 | 
			
		||||
 
 | 
			
		||||
@@ -36,9 +36,8 @@ use Illuminate\Support\Facades\Log;
 | 
			
		||||
class IndexController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    public const string RESOURCE_KEY                  = 'accounts';
 | 
			
		||||
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
    protected array                    $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * AccountController constructor.
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,8 @@ use Illuminate\Http\JsonResponse;
 | 
			
		||||
class ShowController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    public const string RESOURCE_KEY                  = 'accounts';
 | 
			
		||||
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
    protected array                    $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * AccountController constructor.
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,67 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DestroyController.php
 | 
			
		||||
 * Copyright (c) 2024 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\V2\Controllers\Model\ExchangeRate;
 | 
			
		||||
 | 
			
		||||
use FireflyIII\Api\V2\Controllers\Controller;
 | 
			
		||||
use FireflyIII\Api\V2\Request\Model\ExchangeRate\DestroyRequest;
 | 
			
		||||
use FireflyIII\Models\TransactionCurrency;
 | 
			
		||||
use FireflyIII\Repositories\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
 | 
			
		||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
 | 
			
		||||
use Illuminate\Http\JsonResponse;
 | 
			
		||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 | 
			
		||||
 | 
			
		||||
class DestroyController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    use ValidatesUserGroupTrait;
 | 
			
		||||
 | 
			
		||||
    public const string RESOURCE_KEY = 'exchange-rates';
 | 
			
		||||
 | 
			
		||||
    private ExchangeRateRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
        $this->middleware(
 | 
			
		||||
            function ($request, $next) {
 | 
			
		||||
                $this->repository = app(ExchangeRateRepositoryInterface::class);
 | 
			
		||||
                $this->repository->setUserGroup($this->validateUserGroup($request));
 | 
			
		||||
 | 
			
		||||
                return $next($request);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function destroy(DestroyRequest $request, TransactionCurrency $from, TransactionCurrency $to): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        $date = $request->getDate();
 | 
			
		||||
        $rate = $this->repository->getSpecificRateOnDate($from, $to, $date);
 | 
			
		||||
        if (null === $rate) {
 | 
			
		||||
            throw new NotFoundHttpException();
 | 
			
		||||
        }
 | 
			
		||||
        $this->repository->deleteRate($rate);
 | 
			
		||||
 | 
			
		||||
        return response()->json([], 204);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -36,6 +36,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		||||
class IndexController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    use ValidatesUserGroupTrait;
 | 
			
		||||
 | 
			
		||||
    public const string RESOURCE_KEY = 'exchange-rates';
 | 
			
		||||
 | 
			
		||||
    private ExchangeRateRepositoryInterface $repository;
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		||||
class ShowController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    use ValidatesUserGroupTrait;
 | 
			
		||||
 | 
			
		||||
    public const string RESOURCE_KEY = 'exchange-rates';
 | 
			
		||||
 | 
			
		||||
    private ExchangeRateRepositoryInterface $repository;
 | 
			
		||||
@@ -57,13 +58,12 @@ class ShowController extends Controller
 | 
			
		||||
 | 
			
		||||
    public function show(TransactionCurrency $from, TransactionCurrency $to): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        //        $piggies   = $this->repository->getAll();
 | 
			
		||||
        //
 | 
			
		||||
        $pageSize    = $this->parameters->get('limit');
 | 
			
		||||
        $page        = $this->parameters->get('page');
 | 
			
		||||
        $rates       = $this->repository->getRates($from, $to);
 | 
			
		||||
        $count       = $rates->count();
 | 
			
		||||
        $rates       = $rates->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
 | 
			
		||||
        $paginator   = new LengthAwarePaginator($rates, $count, $pageSize, $this->parameters->get('page'));
 | 
			
		||||
        $rates       = $rates->slice(($page - 1) * $pageSize, $pageSize);
 | 
			
		||||
        $paginator   = new LengthAwarePaginator($rates, $count, $pageSize, $page);
 | 
			
		||||
 | 
			
		||||
        $transformer = new ExchangeRateTransformer();
 | 
			
		||||
        $transformer->setParameters($this->parameters); // give params to transformer
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,81 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DestroyController.php
 | 
			
		||||
 * Copyright (c) 2024 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\V2\Controllers\Model\ExchangeRate;
 | 
			
		||||
 | 
			
		||||
use FireflyIII\Api\V2\Controllers\Controller;
 | 
			
		||||
use FireflyIII\Api\V2\Request\Model\ExchangeRate\StoreRequest;
 | 
			
		||||
use FireflyIII\Repositories\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
 | 
			
		||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
 | 
			
		||||
use FireflyIII\Transformers\V2\ExchangeRateTransformer;
 | 
			
		||||
use Illuminate\Http\JsonResponse;
 | 
			
		||||
 | 
			
		||||
class StoreController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    use ValidatesUserGroupTrait;
 | 
			
		||||
 | 
			
		||||
    public const string RESOURCE_KEY = 'exchange-rates';
 | 
			
		||||
 | 
			
		||||
    private ExchangeRateRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
        $this->middleware(
 | 
			
		||||
            function ($request, $next) {
 | 
			
		||||
                $this->repository = app(ExchangeRateRepositoryInterface::class);
 | 
			
		||||
                $this->repository->setUserGroup($this->validateUserGroup($request));
 | 
			
		||||
 | 
			
		||||
                return $next($request);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function store(StoreRequest $request): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        $date        = $request->getDate();
 | 
			
		||||
        $rate        = $request->getRate();
 | 
			
		||||
        $from        = $request->getFromCurrency();
 | 
			
		||||
        $to          = $request->getToCurrency();
 | 
			
		||||
 | 
			
		||||
        // already has rate?
 | 
			
		||||
        $object      = $this->repository->getSpecificRateOnDate($from, $to, $date);
 | 
			
		||||
        if (null !== $object) {
 | 
			
		||||
            // just update it, no matter.
 | 
			
		||||
            $rate = $this->repository->updateExchangeRate($object, $rate, $date);
 | 
			
		||||
        }
 | 
			
		||||
        if (null === $object) {
 | 
			
		||||
            // store new
 | 
			
		||||
            $rate = $this->repository->storeExchangeRate($from, $to, $rate, $date);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $transformer = new ExchangeRateTransformer();
 | 
			
		||||
        $transformer->setParameters($this->parameters);
 | 
			
		||||
 | 
			
		||||
        return response()
 | 
			
		||||
            ->api($this->jsonApiObject(self::RESOURCE_KEY, $rate, $transformer))
 | 
			
		||||
            ->header('Content-Type', self::CONTENT_TYPE)
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,69 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DestroyController.php
 | 
			
		||||
 * Copyright (c) 2024 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\V2\Controllers\Model\ExchangeRate;
 | 
			
		||||
 | 
			
		||||
use FireflyIII\Api\V2\Controllers\Controller;
 | 
			
		||||
use FireflyIII\Api\V2\Request\Model\ExchangeRate\UpdateRequest;
 | 
			
		||||
use FireflyIII\Models\CurrencyExchangeRate;
 | 
			
		||||
use FireflyIII\Repositories\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
 | 
			
		||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
 | 
			
		||||
use FireflyIII\Transformers\V2\ExchangeRateTransformer;
 | 
			
		||||
use Illuminate\Http\JsonResponse;
 | 
			
		||||
 | 
			
		||||
class UpdateController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    use ValidatesUserGroupTrait;
 | 
			
		||||
 | 
			
		||||
    public const string RESOURCE_KEY = 'exchange-rates';
 | 
			
		||||
 | 
			
		||||
    private ExchangeRateRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
        $this->middleware(
 | 
			
		||||
            function ($request, $next) {
 | 
			
		||||
                $this->repository = app(ExchangeRateRepositoryInterface::class);
 | 
			
		||||
                $this->repository->setUserGroup($this->validateUserGroup($request));
 | 
			
		||||
 | 
			
		||||
                return $next($request);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function update(UpdateRequest $request, CurrencyExchangeRate $exchangeRate): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        $date         = $request->getDate();
 | 
			
		||||
        $rate         = $request->getRate();
 | 
			
		||||
        $exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date);
 | 
			
		||||
        $transformer  = new ExchangeRateTransformer();
 | 
			
		||||
        $transformer->setParameters($this->parameters);
 | 
			
		||||
 | 
			
		||||
        return response()
 | 
			
		||||
            ->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))
 | 
			
		||||
            ->header('Content-Type', self::CONTENT_TYPE)
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -35,9 +35,8 @@ use Illuminate\Pagination\LengthAwarePaginator;
 | 
			
		||||
class IndexController extends Controller
 | 
			
		||||
{
 | 
			
		||||
    public const string RESOURCE_KEY                   = 'transaction-currencies';
 | 
			
		||||
 | 
			
		||||
    private CurrencyRepositoryInterface $repository;
 | 
			
		||||
    protected array                     $acceptedRoles = [UserRoleEnum::READ_ONLY];
 | 
			
		||||
    private CurrencyRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -179,7 +179,7 @@ class BasicController extends Controller
 | 
			
		||||
            $return[]     = [
 | 
			
		||||
                'key'                     => sprintf('bills-paid-in-%s', $info['currency_code']),
 | 
			
		||||
                'value'                   => $amount,
 | 
			
		||||
                'currency_id'             => (string)$info['currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $info['currency_id'],
 | 
			
		||||
                'currency_code'           => $info['currency_code'],
 | 
			
		||||
                'currency_symbol'         => $info['currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => $info['currency_decimal_places'],
 | 
			
		||||
@@ -187,7 +187,7 @@ class BasicController extends Controller
 | 
			
		||||
            $return[]     = [
 | 
			
		||||
                'key'                     => 'bills-paid-in-native',
 | 
			
		||||
                'value'                   => $nativeAmount,
 | 
			
		||||
                'currency_id'             => (string)$info['native_currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $info['native_currency_id'],
 | 
			
		||||
                'currency_code'           => $info['native_currency_code'],
 | 
			
		||||
                'currency_symbol'         => $info['native_currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => $info['native_currency_decimal_places'],
 | 
			
		||||
@@ -203,7 +203,7 @@ class BasicController extends Controller
 | 
			
		||||
            $return[]     = [
 | 
			
		||||
                'key'                     => sprintf('bills-unpaid-in-%s', $info['currency_code']),
 | 
			
		||||
                'value'                   => $amount,
 | 
			
		||||
                'currency_id'             => (string)$info['currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $info['currency_id'],
 | 
			
		||||
                'currency_code'           => $info['currency_code'],
 | 
			
		||||
                'currency_symbol'         => $info['currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => $info['currency_decimal_places'],
 | 
			
		||||
@@ -211,7 +211,7 @@ class BasicController extends Controller
 | 
			
		||||
            $return[]     = [
 | 
			
		||||
                'key'                     => 'bills-unpaid-in-native',
 | 
			
		||||
                'value'                   => $nativeAmount,
 | 
			
		||||
                'currency_id'             => (string)$info['native_currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $info['native_currency_id'],
 | 
			
		||||
                'currency_code'           => $info['native_currency_code'],
 | 
			
		||||
                'currency_symbol'         => $info['native_currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => $info['native_currency_decimal_places'],
 | 
			
		||||
@@ -241,7 +241,7 @@ class BasicController extends Controller
 | 
			
		||||
        $nativeLeft   = [
 | 
			
		||||
            'key'                     => 'left-to-spend-in-native',
 | 
			
		||||
            'value'                   => '0',
 | 
			
		||||
            'currency_id'             => (string)$default->id,
 | 
			
		||||
            'currency_id'             => (string) $default->id,
 | 
			
		||||
            'currency_code'           => $default->code,
 | 
			
		||||
            'currency_symbol'         => $default->symbol,
 | 
			
		||||
            'currency_decimal_places' => $default->decimal_places,
 | 
			
		||||
@@ -249,7 +249,7 @@ class BasicController extends Controller
 | 
			
		||||
        $nativePerDay = [
 | 
			
		||||
            'key'                     => 'left-per-day-to-spend-in-native',
 | 
			
		||||
            'value'                   => '0',
 | 
			
		||||
            'currency_id'             => (string)$default->id,
 | 
			
		||||
            'currency_id'             => (string) $default->id,
 | 
			
		||||
            'currency_code'           => $default->code,
 | 
			
		||||
            'currency_symbol'         => $default->symbol,
 | 
			
		||||
            'currency_decimal_places' => $default->decimal_places,
 | 
			
		||||
@@ -276,7 +276,7 @@ class BasicController extends Controller
 | 
			
		||||
                    $currencies[$currencyId] = $currency;
 | 
			
		||||
                    $amount                  = app('steam')->negative($journal['amount']);
 | 
			
		||||
                    $amountNative            = $converter->convert($default, $currency, $start, $amount);
 | 
			
		||||
                    if ((int)$journal['foreign_currency_id'] === $default->id) {
 | 
			
		||||
                    if ((int) $journal['foreign_currency_id'] === $default->id) {
 | 
			
		||||
                        $amountNative = $journal['foreign_amount'];
 | 
			
		||||
                    }
 | 
			
		||||
                    $spent                   = bcadd($spent, $amount);
 | 
			
		||||
@@ -296,24 +296,24 @@ class BasicController extends Controller
 | 
			
		||||
            app('log')->debug(sprintf('Amount left is %s', $left));
 | 
			
		||||
 | 
			
		||||
            // how much left per day?
 | 
			
		||||
            $days                    = (int)$today->diffInDays($end, true) + 1;
 | 
			
		||||
            $days                    = (int) $today->diffInDays($end, true) + 1;
 | 
			
		||||
            $perDay                  = '0';
 | 
			
		||||
            $perDayNative            = '0';
 | 
			
		||||
            if (0 !== $days && bccomp($left, '0') > -1) {
 | 
			
		||||
                $perDay = bcdiv($left, (string)$days);
 | 
			
		||||
                $perDay = bcdiv($left, (string) $days);
 | 
			
		||||
            }
 | 
			
		||||
            if (0 !== $days && bccomp($leftNative, '0') > -1) {
 | 
			
		||||
                $perDayNative = bcdiv($leftNative, (string)$days);
 | 
			
		||||
                $perDayNative = bcdiv($leftNative, (string) $days);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // left
 | 
			
		||||
            $return[]                = [
 | 
			
		||||
                'key'                     => sprintf('left-to-spend-in-%s', $row['currency_code']),
 | 
			
		||||
                'value'                   => $left,
 | 
			
		||||
                'currency_id'             => (string)$row['currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $row['currency_id'],
 | 
			
		||||
                'currency_code'           => $row['currency_code'],
 | 
			
		||||
                'currency_symbol'         => $row['currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => (int)$row['currency_decimal_places'],
 | 
			
		||||
                'currency_decimal_places' => (int) $row['currency_decimal_places'],
 | 
			
		||||
            ];
 | 
			
		||||
            // left (native)
 | 
			
		||||
            $nativeLeft['value']     = $leftNative;
 | 
			
		||||
@@ -322,10 +322,10 @@ class BasicController extends Controller
 | 
			
		||||
            $return[]                = [
 | 
			
		||||
                'key'                     => sprintf('left-per-day-to-spend-in-%s', $row['currency_code']),
 | 
			
		||||
                'value'                   => $perDay,
 | 
			
		||||
                'currency_id'             => (string)$row['currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $row['currency_id'],
 | 
			
		||||
                'currency_code'           => $row['currency_code'],
 | 
			
		||||
                'currency_symbol'         => $row['currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => (int)$row['currency_decimal_places'],
 | 
			
		||||
                'currency_decimal_places' => (int) $row['currency_decimal_places'],
 | 
			
		||||
            ];
 | 
			
		||||
 | 
			
		||||
            // left per day (native)
 | 
			
		||||
@@ -371,7 +371,7 @@ class BasicController extends Controller
 | 
			
		||||
        $return[]       = [
 | 
			
		||||
            'key'                     => 'net-worth-in-native',
 | 
			
		||||
            'value'                   => $netWorthSet['native']['balance'],
 | 
			
		||||
            'currency_id'             => (string)$netWorthSet['native']['currency_id'],
 | 
			
		||||
            'currency_id'             => (string) $netWorthSet['native']['currency_id'],
 | 
			
		||||
            'currency_code'           => $netWorthSet['native']['currency_code'],
 | 
			
		||||
            'currency_symbol'         => $netWorthSet['native']['currency_symbol'],
 | 
			
		||||
            'currency_decimal_places' => $netWorthSet['native']['currency_decimal_places'],
 | 
			
		||||
@@ -383,7 +383,7 @@ class BasicController extends Controller
 | 
			
		||||
            $return[] = [
 | 
			
		||||
                'key'                     => sprintf('net-worth-in-%s', $data['currency_code']),
 | 
			
		||||
                'value'                   => $data['balance'],
 | 
			
		||||
                'currency_id'             => (string)$data['currency_id'],
 | 
			
		||||
                'currency_id'             => (string) $data['currency_id'],
 | 
			
		||||
                'currency_code'           => $data['currency_code'],
 | 
			
		||||
                'currency_symbol'         => $data['currency_symbol'],
 | 
			
		||||
                'currency_decimal_places' => $data['currency_decimal_places'],
 | 
			
		||||
 
 | 
			
		||||
@@ -73,6 +73,16 @@ class AutocompleteRequest extends FormRequest
 | 
			
		||||
        return $array;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getAccountTypeParameter(array $types): array
 | 
			
		||||
    {
 | 
			
		||||
        $return = [];
 | 
			
		||||
        foreach ($types as $type) {
 | 
			
		||||
            $return = array_merge($return, $this->mapAccountTypes($type));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return array_unique($return);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function rules(): array
 | 
			
		||||
    {
 | 
			
		||||
        $valid = array_keys($this->types);
 | 
			
		||||
@@ -86,14 +96,4 @@ class AutocompleteRequest extends FormRequest
 | 
			
		||||
            'transaction_types' => 'nullable|in:todo',
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getAccountTypeParameter(array $types): array
 | 
			
		||||
    {
 | 
			
		||||
        $return = [];
 | 
			
		||||
        foreach ($types as $type) {
 | 
			
		||||
            $return = array_merge($return, $this->mapAccountTypes($type));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return array_unique($return);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,8 @@ class BalanceChartRequest extends FormRequest
 | 
			
		||||
    use ChecksLogin;
 | 
			
		||||
    use ConvertsDataTypes;
 | 
			
		||||
    use ValidatesUserGroupTrait;
 | 
			
		||||
    protected array                    $acceptedRoles = [UserRoleEnum::READ_ONLY];
 | 
			
		||||
 | 
			
		||||
    protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get all data from the request.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								app/Api/V2/Request/Model/ExchangeRate/DestroyRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/Api/V2/Request/Model/ExchangeRate/DestroyRequest.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DestroyRequest.php
 | 
			
		||||
 * Copyright (c) 2024 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\V2\Request\Model\ExchangeRate;
 | 
			
		||||
 | 
			
		||||
use Carbon\Carbon;
 | 
			
		||||
use FireflyIII\Support\Request\ChecksLogin;
 | 
			
		||||
use FireflyIII\Support\Request\ConvertsDataTypes;
 | 
			
		||||
use Illuminate\Foundation\Http\FormRequest;
 | 
			
		||||
 | 
			
		||||
class DestroyRequest extends FormRequest
 | 
			
		||||
{
 | 
			
		||||
    use ChecksLogin;
 | 
			
		||||
    use ConvertsDataTypes;
 | 
			
		||||
 | 
			
		||||
    public function getDate(): Carbon
 | 
			
		||||
    {
 | 
			
		||||
        return $this->getCarbonDate('date');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The rules that the incoming request must be matched against.
 | 
			
		||||
     */
 | 
			
		||||
    public function rules(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            'date'  => 'required|date|after:1900-01-01|before:2099-12-31',
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								app/Api/V2/Request/Model/ExchangeRate/StoreRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app/Api/V2/Request/Model/ExchangeRate/StoreRequest.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DestroyRequest.php
 | 
			
		||||
 * Copyright (c) 2024 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\V2\Request\Model\ExchangeRate;
 | 
			
		||||
 | 
			
		||||
use Carbon\Carbon;
 | 
			
		||||
use FireflyIII\Models\TransactionCurrency;
 | 
			
		||||
use FireflyIII\Support\Request\ChecksLogin;
 | 
			
		||||
use FireflyIII\Support\Request\ConvertsDataTypes;
 | 
			
		||||
use Illuminate\Foundation\Http\FormRequest;
 | 
			
		||||
 | 
			
		||||
class StoreRequest extends FormRequest
 | 
			
		||||
{
 | 
			
		||||
    use ChecksLogin;
 | 
			
		||||
    use ConvertsDataTypes;
 | 
			
		||||
 | 
			
		||||
    public function getDate(): ?Carbon
 | 
			
		||||
    {
 | 
			
		||||
        return $this->getCarbonDate('date');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getRate(): string
 | 
			
		||||
    {
 | 
			
		||||
        return (string) $this->get('rate');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFromCurrency(): TransactionCurrency
 | 
			
		||||
    {
 | 
			
		||||
        return TransactionCurrency::where('code', $this->get('from'))->first();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getToCurrency(): TransactionCurrency
 | 
			
		||||
    {
 | 
			
		||||
        return TransactionCurrency::where('code', $this->get('to'))->first();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The rules that the incoming request must be matched against.
 | 
			
		||||
     */
 | 
			
		||||
    public function rules(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            'date' => 'required|date|after:1900-01-01|before:2099-12-31',
 | 
			
		||||
            'rate' => 'required|numeric|gt:0',
 | 
			
		||||
            'from' => 'required|exists:transaction_currencies,code',
 | 
			
		||||
            'to'   => 'required|exists:transaction_currencies,code',
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								app/Api/V2/Request/Model/ExchangeRate/UpdateRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								app/Api/V2/Request/Model/ExchangeRate/UpdateRequest.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DestroyRequest.php
 | 
			
		||||
 * Copyright (c) 2024 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\V2\Request\Model\ExchangeRate;
 | 
			
		||||
 | 
			
		||||
use Carbon\Carbon;
 | 
			
		||||
use FireflyIII\Support\Request\ChecksLogin;
 | 
			
		||||
use FireflyIII\Support\Request\ConvertsDataTypes;
 | 
			
		||||
use Illuminate\Foundation\Http\FormRequest;
 | 
			
		||||
 | 
			
		||||
class UpdateRequest extends FormRequest
 | 
			
		||||
{
 | 
			
		||||
    use ChecksLogin;
 | 
			
		||||
    use ConvertsDataTypes;
 | 
			
		||||
 | 
			
		||||
    public function getDate(): ?Carbon
 | 
			
		||||
    {
 | 
			
		||||
        return $this->getCarbonDate('date');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getRate(): string
 | 
			
		||||
    {
 | 
			
		||||
        return (string) $this->get('rate');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The rules that the incoming request must be matched against.
 | 
			
		||||
     */
 | 
			
		||||
    public function rules(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            'date'  => 'date|after:1900-01-01|before:2099-12-31',
 | 
			
		||||
            'rate'  => 'required|numeric|gt:0',
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -87,7 +87,7 @@ class InfiniteListRequest extends FormRequest
 | 
			
		||||
 | 
			
		||||
    public function getAccountTypes(): array
 | 
			
		||||
    {
 | 
			
		||||
        $type = (string)$this->get('type', 'default');
 | 
			
		||||
        $type = (string) $this->get('type', 'default');
 | 
			
		||||
 | 
			
		||||
        return $this->mapAccountTypes($type);
 | 
			
		||||
    }
 | 
			
		||||
@@ -101,7 +101,7 @@ class InfiniteListRequest extends FormRequest
 | 
			
		||||
 | 
			
		||||
    public function getTransactionTypes(): array
 | 
			
		||||
    {
 | 
			
		||||
        $type = (string)$this->get('type', 'default');
 | 
			
		||||
        $type = (string) $this->get('type', 'default');
 | 
			
		||||
 | 
			
		||||
        return $this->mapTransactionTypes($type);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ class ListRequest extends FormRequest
 | 
			
		||||
 | 
			
		||||
    public function getTransactionTypes(): array
 | 
			
		||||
    {
 | 
			
		||||
        $type = (string)$this->get('type', 'default');
 | 
			
		||||
        $type = (string) $this->get('type', 'default');
 | 
			
		||||
 | 
			
		||||
        return $this->mapTransactionTypes($type);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -94,73 +94,73 @@ class StoreRequest extends FormRequest
 | 
			
		||||
            $result   = [
 | 
			
		||||
                'type'                  => $this->clearString($object['type']),
 | 
			
		||||
                'date'                  => $this->dateFromValue($object['date']),
 | 
			
		||||
                'order'                 => $this->integerFromValue((string)$object['order']),
 | 
			
		||||
                'order'                 => $this->integerFromValue((string) $object['order']),
 | 
			
		||||
 | 
			
		||||
                'currency_id'           => $this->integerFromValue((string)$object['currency_id']),
 | 
			
		||||
                'currency_code'         => $this->clearString((string)$object['currency_code']),
 | 
			
		||||
                'currency_id'           => $this->integerFromValue((string) $object['currency_id']),
 | 
			
		||||
                'currency_code'         => $this->clearString((string) $object['currency_code']),
 | 
			
		||||
 | 
			
		||||
                // foreign currency info:
 | 
			
		||||
                'foreign_currency_id'   => $this->integerFromValue((string)$object['foreign_currency_id']),
 | 
			
		||||
                'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code']),
 | 
			
		||||
                'foreign_currency_id'   => $this->integerFromValue((string) $object['foreign_currency_id']),
 | 
			
		||||
                'foreign_currency_code' => $this->clearString((string) $object['foreign_currency_code']),
 | 
			
		||||
 | 
			
		||||
                // amount and foreign amount. Cannot be 0.
 | 
			
		||||
                'amount'                => $this->clearString((string)$object['amount']),
 | 
			
		||||
                'foreign_amount'        => $this->clearString((string)$object['foreign_amount']),
 | 
			
		||||
                'amount'                => $this->clearString((string) $object['amount']),
 | 
			
		||||
                'foreign_amount'        => $this->clearString((string) $object['foreign_amount']),
 | 
			
		||||
 | 
			
		||||
                // description.
 | 
			
		||||
                'description'           => $this->clearString($object['description']),
 | 
			
		||||
 | 
			
		||||
                // source of transaction. If everything is null, assume cash account.
 | 
			
		||||
                'source_id'             => $this->integerFromValue((string)$object['source_id']),
 | 
			
		||||
                'source_name'           => $this->clearString((string)$object['source_name']),
 | 
			
		||||
                'source_iban'           => $this->clearString((string)$object['source_iban']),
 | 
			
		||||
                'source_number'         => $this->clearString((string)$object['source_number']),
 | 
			
		||||
                'source_bic'            => $this->clearString((string)$object['source_bic']),
 | 
			
		||||
                'source_id'             => $this->integerFromValue((string) $object['source_id']),
 | 
			
		||||
                'source_name'           => $this->clearString((string) $object['source_name']),
 | 
			
		||||
                'source_iban'           => $this->clearString((string) $object['source_iban']),
 | 
			
		||||
                'source_number'         => $this->clearString((string) $object['source_number']),
 | 
			
		||||
                'source_bic'            => $this->clearString((string) $object['source_bic']),
 | 
			
		||||
 | 
			
		||||
                // destination of transaction. If everything is null, assume cash account.
 | 
			
		||||
                'destination_id'        => $this->integerFromValue((string)$object['destination_id']),
 | 
			
		||||
                'destination_name'      => $this->clearString((string)$object['destination_name']),
 | 
			
		||||
                'destination_iban'      => $this->clearString((string)$object['destination_iban']),
 | 
			
		||||
                'destination_number'    => $this->clearString((string)$object['destination_number']),
 | 
			
		||||
                'destination_bic'       => $this->clearString((string)$object['destination_bic']),
 | 
			
		||||
                'destination_id'        => $this->integerFromValue((string) $object['destination_id']),
 | 
			
		||||
                'destination_name'      => $this->clearString((string) $object['destination_name']),
 | 
			
		||||
                'destination_iban'      => $this->clearString((string) $object['destination_iban']),
 | 
			
		||||
                'destination_number'    => $this->clearString((string) $object['destination_number']),
 | 
			
		||||
                'destination_bic'       => $this->clearString((string) $object['destination_bic']),
 | 
			
		||||
 | 
			
		||||
                // budget info
 | 
			
		||||
                'budget_id'             => $this->integerFromValue((string)$object['budget_id']),
 | 
			
		||||
                'budget_name'           => $this->clearString((string)$object['budget_name']),
 | 
			
		||||
                'budget_id'             => $this->integerFromValue((string) $object['budget_id']),
 | 
			
		||||
                'budget_name'           => $this->clearString((string) $object['budget_name']),
 | 
			
		||||
 | 
			
		||||
                // category info
 | 
			
		||||
                'category_id'           => $this->integerFromValue((string)$object['category_id']),
 | 
			
		||||
                'category_name'         => $this->clearString((string)$object['category_name']),
 | 
			
		||||
                'category_id'           => $this->integerFromValue((string) $object['category_id']),
 | 
			
		||||
                'category_name'         => $this->clearString((string) $object['category_name']),
 | 
			
		||||
 | 
			
		||||
                // journal bill reference. Optional. Will only work for withdrawals
 | 
			
		||||
                'bill_id'               => $this->integerFromValue((string)$object['bill_id']),
 | 
			
		||||
                'bill_name'             => $this->clearString((string)$object['bill_name']),
 | 
			
		||||
                'bill_id'               => $this->integerFromValue((string) $object['bill_id']),
 | 
			
		||||
                'bill_name'             => $this->clearString((string) $object['bill_name']),
 | 
			
		||||
 | 
			
		||||
                // piggy bank reference. Optional. Will only work for transfers
 | 
			
		||||
                'piggy_bank_id'         => $this->integerFromValue((string)$object['piggy_bank_id']),
 | 
			
		||||
                'piggy_bank_name'       => $this->clearString((string)$object['piggy_bank_name']),
 | 
			
		||||
                'piggy_bank_id'         => $this->integerFromValue((string) $object['piggy_bank_id']),
 | 
			
		||||
                'piggy_bank_name'       => $this->clearString((string) $object['piggy_bank_name']),
 | 
			
		||||
 | 
			
		||||
                // some other interesting properties
 | 
			
		||||
                'reconciled'            => $this->convertBoolean((string)$object['reconciled']),
 | 
			
		||||
                'notes'                 => $this->clearStringKeepNewlines((string)$object['notes']),
 | 
			
		||||
                'reconciled'            => $this->convertBoolean((string) $object['reconciled']),
 | 
			
		||||
                'notes'                 => $this->clearStringKeepNewlines((string) $object['notes']),
 | 
			
		||||
                'tags'                  => $this->arrayFromValue($object['tags']),
 | 
			
		||||
 | 
			
		||||
                // all custom fields:
 | 
			
		||||
                'internal_reference'    => $this->clearString((string)$object['internal_reference']),
 | 
			
		||||
                'external_id'           => $this->clearString((string)$object['external_id']),
 | 
			
		||||
                'internal_reference'    => $this->clearString((string) $object['internal_reference']),
 | 
			
		||||
                'external_id'           => $this->clearString((string) $object['external_id']),
 | 
			
		||||
                'original_source'       => sprintf('ff3-v%s', config('firefly.version')),
 | 
			
		||||
                'recurrence_id'         => $this->integerFromValue($object['recurrence_id']),
 | 
			
		||||
                'bunq_payment_id'       => $this->clearString((string)$object['bunq_payment_id']),
 | 
			
		||||
                'external_url'          => $this->clearString((string)$object['external_url']),
 | 
			
		||||
                'bunq_payment_id'       => $this->clearString((string) $object['bunq_payment_id']),
 | 
			
		||||
                'external_url'          => $this->clearString((string) $object['external_url']),
 | 
			
		||||
 | 
			
		||||
                'sepa_cc'               => $this->clearString((string)$object['sepa_cc']),
 | 
			
		||||
                'sepa_ct_op'            => $this->clearString((string)$object['sepa_ct_op']),
 | 
			
		||||
                'sepa_ct_id'            => $this->clearString((string)$object['sepa_ct_id']),
 | 
			
		||||
                'sepa_db'               => $this->clearString((string)$object['sepa_db']),
 | 
			
		||||
                'sepa_country'          => $this->clearString((string)$object['sepa_country']),
 | 
			
		||||
                'sepa_ep'               => $this->clearString((string)$object['sepa_ep']),
 | 
			
		||||
                'sepa_ci'               => $this->clearString((string)$object['sepa_ci']),
 | 
			
		||||
                'sepa_batch_id'         => $this->clearString((string)$object['sepa_batch_id']),
 | 
			
		||||
                'sepa_cc'               => $this->clearString((string) $object['sepa_cc']),
 | 
			
		||||
                'sepa_ct_op'            => $this->clearString((string) $object['sepa_ct_op']),
 | 
			
		||||
                'sepa_ct_id'            => $this->clearString((string) $object['sepa_ct_id']),
 | 
			
		||||
                'sepa_db'               => $this->clearString((string) $object['sepa_db']),
 | 
			
		||||
                'sepa_country'          => $this->clearString((string) $object['sepa_country']),
 | 
			
		||||
                'sepa_ep'               => $this->clearString((string) $object['sepa_ep']),
 | 
			
		||||
                'sepa_ci'               => $this->clearString((string) $object['sepa_ci']),
 | 
			
		||||
                'sepa_batch_id'         => $this->clearString((string) $object['sepa_batch_id']),
 | 
			
		||||
                // custom date fields. Must be Carbon objects. Presence is optional.
 | 
			
		||||
                'interest_date'         => $this->dateFromValue($object['interest_date']),
 | 
			
		||||
                'book_date'             => $this->dateFromValue($object['book_date']),
 | 
			
		||||
 
 | 
			
		||||
@@ -139,7 +139,7 @@ class UpdateRequest extends Request
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->integerFields as $fieldName) {
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                $current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]);
 | 
			
		||||
                $current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -154,7 +154,7 @@ class UpdateRequest extends Request
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->stringFields as $fieldName) {
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                $current[$fieldName] = $this->clearString((string)$transaction[$fieldName]);
 | 
			
		||||
                $current[$fieldName] = $this->clearString((string) $transaction[$fieldName]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -169,7 +169,7 @@ class UpdateRequest extends Request
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->textareaFields as $fieldName) {
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                $current[$fieldName] = $this->clearStringKeepNewlines((string)$transaction[$fieldName]); // keep newlines
 | 
			
		||||
                $current[$fieldName] = $this->clearStringKeepNewlines((string) $transaction[$fieldName]); // keep newlines
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -185,8 +185,8 @@ class UpdateRequest extends Request
 | 
			
		||||
        foreach ($this->dateFields as $fieldName) {
 | 
			
		||||
            app('log')->debug(sprintf('Now at date field %s', $fieldName));
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                app('log')->debug(sprintf('New value: "%s"', (string)$transaction[$fieldName]));
 | 
			
		||||
                $current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]);
 | 
			
		||||
                app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
 | 
			
		||||
                $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -201,7 +201,7 @@ class UpdateRequest extends Request
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->booleanFields as $fieldName) {
 | 
			
		||||
            if (array_key_exists($fieldName, $transaction)) {
 | 
			
		||||
                $current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]);
 | 
			
		||||
                $current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -236,7 +236,7 @@ class UpdateRequest extends Request
 | 
			
		||||
                    $current[$fieldName] = sprintf('%.12f', $value);
 | 
			
		||||
                }
 | 
			
		||||
                if (!is_float($value)) {
 | 
			
		||||
                    $current[$fieldName] = (string)$value;
 | 
			
		||||
                    $current[$fieldName] = (string) $value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ class AutoSum
 | 
			
		||||
            $amount                       = $getSum($object);
 | 
			
		||||
 | 
			
		||||
            $return[$currency->id] ??= [
 | 
			
		||||
                'id'             => (string)$currency->id,
 | 
			
		||||
                'id'             => (string) $currency->id,
 | 
			
		||||
                'name'           => $currency->name,
 | 
			
		||||
                'symbol'         => $currency->symbol,
 | 
			
		||||
                'code'           => $currency->code,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,25 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ConvertsDatesToUTC.php
 | 
			
		||||
 * Copyright (c) 2024 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);
 | 
			
		||||
/*
 | 
			
		||||
 * ConvertDatesToUTC.php
 | 
			
		||||
@@ -21,7 +41,7 @@ declare(strict_types=1);
 | 
			
		||||
 * along with this program.  If not, see https://www.gnu.org/licenses/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace FireflyIII\Console\Commands\Integrity;
 | 
			
		||||
namespace FireflyIII\Console\Commands\Correction;
 | 
			
		||||
 | 
			
		||||
use Carbon\Carbon;
 | 
			
		||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
 | 
			
		||||
@@ -31,17 +51,10 @@ use Illuminate\Database\QueryException;
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Illuminate\Support\Facades\Log;
 | 
			
		||||
 | 
			
		||||
class ConvertDatesToUTC extends Command
 | 
			
		||||
class ConvertsDatesToUTC extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The name and signature of the console command.
 | 
			
		||||
     *
 | 
			
		||||
     * @var string
 | 
			
		||||
     */
 | 
			
		||||
    protected $signature   = 'firefly-iii:migrate-to-utc';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The console command description.
 | 
			
		||||
     *
 | 
			
		||||
@@ -49,11 +62,22 @@ class ConvertDatesToUTC extends Command
 | 
			
		||||
     */
 | 
			
		||||
    protected $description = 'Convert stored dates to UTC.';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The name and signature of the console command.
 | 
			
		||||
     *
 | 
			
		||||
     * @var string
 | 
			
		||||
     */
 | 
			
		||||
    protected $signature   = 'correction:convert-to-utc';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(): int
 | 
			
		||||
    {
 | 
			
		||||
        $this->friendlyWarning('Please do not use this command.');
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @var string $model
 | 
			
		||||
         * @var array  $fields
 | 
			
		||||
@@ -29,15 +29,12 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
 | 
			
		||||
use FireflyIII\User;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class FixAccountOrder
 | 
			
		||||
 */
 | 
			
		||||
class FixAccountOrder extends Command
 | 
			
		||||
class CorrectsAccountOrder extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Make sure account order is correct.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:fix-account-order';
 | 
			
		||||
    protected $signature   = 'correction:account-order';
 | 
			
		||||
 | 
			
		||||
    private AccountRepositoryInterface $repository;
 | 
			
		||||
 | 
			
		||||
@@ -54,8 +51,6 @@ class FixAccountOrder extends Command
 | 
			
		||||
            $this->repository->resetAccountOrder();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->friendlyPositive('All accounts are ordered correctly');
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -36,15 +36,12 @@ use Illuminate\Console\Command;
 | 
			
		||||
use Illuminate\Database\Eloquent\Builder;
 | 
			
		||||
use Illuminate\Database\Query\JoinClause;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class FixAccountTypes
 | 
			
		||||
 */
 | 
			
		||||
class FixAccountTypes extends Command
 | 
			
		||||
class CorrectsAccountTypes extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Make sure all journals have the correct from/to account types.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:fix-account-types';
 | 
			
		||||
    protected $signature   = 'correction:account-types';
 | 
			
		||||
    private int            $count;
 | 
			
		||||
    private array          $expected;
 | 
			
		||||
    private AccountFactory $factory;
 | 
			
		||||
@@ -120,9 +117,6 @@ class FixAccountTypes extends Command
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (0 === $this->count) {
 | 
			
		||||
            $this->friendlyPositive('All account types are OK');
 | 
			
		||||
        }
 | 
			
		||||
        if (0 !== $this->count) {
 | 
			
		||||
            app('log')->debug(sprintf('%d journals had to be fixed.', $this->count));
 | 
			
		||||
            $this->friendlyInfo(sprintf('Acted on %d transaction(s)', $this->count));
 | 
			
		||||
@@ -36,15 +36,12 @@ use FireflyIII\Models\RuleTrigger;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class ReportSkeleton
 | 
			
		||||
 */
 | 
			
		||||
class CorrectAmounts extends Command
 | 
			
		||||
class CorrectsAmounts extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'This command makes sure positive and negative amounts are recorded correctly.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:fix-amount-pos-neg';
 | 
			
		||||
    protected $signature   = 'correction:amounts';
 | 
			
		||||
 | 
			
		||||
    public function handle(): int
 | 
			
		||||
    {
 | 
			
		||||
@@ -72,7 +69,6 @@ class CorrectAmounts extends Command
 | 
			
		||||
    {
 | 
			
		||||
        $count = AutoBudget::where('amount', '<', 0)->update(['amount' => DB::raw('amount * -1')]);
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $this->friendlyPositive('All auto budget amounts are positive.');
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -83,7 +79,6 @@ class CorrectAmounts extends Command
 | 
			
		||||
    {
 | 
			
		||||
        $count = AvailableBudget::where('amount', '<', 0)->update(['amount' => DB::raw('amount * -1')]);
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $this->friendlyPositive('All available budget amounts are positive.');
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -96,7 +91,6 @@ class CorrectAmounts extends Command
 | 
			
		||||
        $count += Bill::where('amount_max', '<', 0)->update(['amount_max' => DB::raw('amount_max * -1')]);
 | 
			
		||||
        $count += Bill::where('amount_min', '<', 0)->update(['amount_min' => DB::raw('amount_min * -1')]);
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $this->friendlyPositive('All bill amounts are positive.');
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -107,7 +101,6 @@ class CorrectAmounts extends Command
 | 
			
		||||
    {
 | 
			
		||||
        $count = BudgetLimit::where('amount', '<', 0)->update(['amount' => DB::raw('amount * -1')]);
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $this->friendlyPositive('All budget limit amounts are positive.');
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -118,7 +111,6 @@ class CorrectAmounts extends Command
 | 
			
		||||
    {
 | 
			
		||||
        $count = CurrencyExchangeRate::where('rate', '<', 0)->update(['rate' => DB::raw('rate * -1')]);
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $this->friendlyPositive('All currency exchange rates are positive.');
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -129,7 +121,6 @@ class CorrectAmounts extends Command
 | 
			
		||||
    {
 | 
			
		||||
        $count = PiggyBank::where('target_amount', '<', 0)->update(['target_amount' => DB::raw('target_amount * -1')]);
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $this->friendlyPositive('All piggy bank amounts are positive.');
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -142,7 +133,6 @@ class CorrectAmounts extends Command
 | 
			
		||||
        $count += RecurrenceTransaction::where('amount', '<', 0)->update(['amount' => DB::raw('amount * -1')]);
 | 
			
		||||
        $count += RecurrenceTransaction::where('foreign_amount', '<', 0)->update(['foreign_amount' => DB::raw('foreign_amount * -1')]);
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $this->friendlyPositive('All recurring transaction amounts are positive.');
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -165,7 +155,6 @@ class CorrectAmounts extends Command
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (0 === $fixed) {
 | 
			
		||||
            $this->friendlyPositive('All rule trigger amounts are positive.');
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -37,15 +37,12 @@ use Illuminate\Support\Collection;
 | 
			
		||||
use Illuminate\Support\Facades\Log;
 | 
			
		||||
use Symfony\Component\Console\Command\Command as CommandAlias;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class EnableCurrencies
 | 
			
		||||
 */
 | 
			
		||||
class EnableCurrencies extends Command
 | 
			
		||||
class CorrectsCurrencies extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Enables all currencies in use.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:enable-currencies';
 | 
			
		||||
    protected $signature   = 'correction:currencies';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
@@ -77,7 +74,7 @@ class EnableCurrencies extends Command
 | 
			
		||||
            ->where('account_meta.name', 'currency_id')->groupBy('data')->get(['data'])
 | 
			
		||||
        ;
 | 
			
		||||
        foreach ($meta as $entry) {
 | 
			
		||||
            $found[] = (int)$entry->data;
 | 
			
		||||
            $found[] = (int) $entry->data;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // get all from journals:
 | 
			
		||||
@@ -85,7 +82,7 @@ class EnableCurrencies extends Command
 | 
			
		||||
            ->groupBy('transaction_currency_id')->get(['transaction_currency_id'])
 | 
			
		||||
        ;
 | 
			
		||||
        foreach ($journals as $entry) {
 | 
			
		||||
            $found[] = (int)$entry->transaction_currency_id;
 | 
			
		||||
            $found[] = (int) $entry->transaction_currency_id;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // get all from transactions
 | 
			
		||||
@@ -95,8 +92,8 @@ class EnableCurrencies extends Command
 | 
			
		||||
            ->get(['transactions.transaction_currency_id', 'transactions.foreign_currency_id'])
 | 
			
		||||
        ;
 | 
			
		||||
        foreach ($transactions as $entry) {
 | 
			
		||||
            $found[] = (int)$entry->transaction_currency_id;
 | 
			
		||||
            $found[] = (int)$entry->foreign_currency_id;
 | 
			
		||||
            $found[] = (int) $entry->transaction_currency_id;
 | 
			
		||||
            $found[] = (int) $entry->foreign_currency_id;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // get all from budget limits
 | 
			
		||||
@@ -27,14 +27,11 @@ namespace FireflyIII\Console\Commands\Correction;
 | 
			
		||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class CorrectDatabase
 | 
			
		||||
 */
 | 
			
		||||
class CorrectDatabase extends Command
 | 
			
		||||
class CorrectsDatabase extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Will correct the integrity of your database, if necessary.';
 | 
			
		||||
    protected $description = 'Will validate and correct the integrity of your database, if necessary.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:correct-database';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -49,32 +46,36 @@ class CorrectDatabase extends Command
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
        $commands = [
 | 
			
		||||
            'firefly-iii:fix-piggies',
 | 
			
		||||
            'firefly-iii:create-link-types',
 | 
			
		||||
            'firefly-iii:create-access-tokens',
 | 
			
		||||
            'firefly-iii:remove-bills',
 | 
			
		||||
            'firefly-iii:fix-amount-pos-neg',
 | 
			
		||||
            'firefly-iii:enable-currencies',
 | 
			
		||||
            'firefly-iii:fix-transfer-budgets',
 | 
			
		||||
            'firefly-iii:fix-uneven-amount',
 | 
			
		||||
            'firefly-iii:delete-zero-amount',
 | 
			
		||||
            'firefly-iii:delete-orphaned-transactions',
 | 
			
		||||
            'firefly-iii:delete-empty-journals',
 | 
			
		||||
            'firefly-iii:delete-empty-groups',
 | 
			
		||||
            'firefly-iii:fix-account-types',
 | 
			
		||||
            'firefly-iii:fix-ibans',
 | 
			
		||||
            'firefly-iii:fix-account-order',
 | 
			
		||||
            'firefly-iii:rename-meta-fields',
 | 
			
		||||
            'firefly-iii:fix-ob-currencies',
 | 
			
		||||
            'firefly-iii:fix-long-descriptions',
 | 
			
		||||
            'firefly-iii:fix-recurring-transactions',
 | 
			
		||||
            'firefly-iii:upgrade-group-information',
 | 
			
		||||
            // 'firefly-iii:fix-transaction-types', // very resource heavy.
 | 
			
		||||
            'firefly-iii:fix-frontpage-accounts',
 | 
			
		||||
            // new!
 | 
			
		||||
            'firefly-iii:unify-group-accounts',
 | 
			
		||||
            'firefly-iii:trigger-credit-recalculation',
 | 
			
		||||
            'firefly-iii:migrate-preferences',
 | 
			
		||||
            'correction:restore-oauth-keys',
 | 
			
		||||
            'correction:timezones',
 | 
			
		||||
            'correction:create-group-memberships',
 | 
			
		||||
            'correction:group-information',
 | 
			
		||||
            'correction:piggy-banks',
 | 
			
		||||
            'correction:link-types',
 | 
			
		||||
            'correction:access-tokens',
 | 
			
		||||
            'correction:bills',
 | 
			
		||||
            'correction:amounts',
 | 
			
		||||
            'correction:currencies',
 | 
			
		||||
            'correction:transfer-budgets',
 | 
			
		||||
            'correction:uneven-amounts',
 | 
			
		||||
            'correction:zero-amounts',
 | 
			
		||||
            'correction:orphaned-transactions',
 | 
			
		||||
            'correction:empty-journals',
 | 
			
		||||
            'correction:empty-groups',
 | 
			
		||||
            'correction:account-types',
 | 
			
		||||
            'correction:ibans',
 | 
			
		||||
            'correction:account-order',
 | 
			
		||||
            'correction:meta-fields',
 | 
			
		||||
            'correction:opening-balance-currencies',
 | 
			
		||||
            'correction:long-descriptions',
 | 
			
		||||
            'correction:recurring-transactions',
 | 
			
		||||
            'correction:frontpage-accounts',
 | 
			
		||||
            'correction:group-accounts',
 | 
			
		||||
            'correction:recalculates-liabilities',
 | 
			
		||||
            'correction:preferences',
 | 
			
		||||
            // 'correction:transaction-types', // resource heavy, disabled.
 | 
			
		||||
            // 'correction:recalculate-native-amounts', // not necessary, disabled.
 | 
			
		||||
            'firefly-iii:report-integrity',
 | 
			
		||||
        ];
 | 
			
		||||
        foreach ($commands as $command) {
 | 
			
		||||
            $this->friendlyLine(sprintf('Now executing command "%s"', $command));
 | 
			
		||||
@@ -31,15 +31,12 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
 | 
			
		||||
use FireflyIII\User;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class FixFrontpageAccounts
 | 
			
		||||
 */
 | 
			
		||||
class FixFrontpageAccounts extends Command
 | 
			
		||||
class CorrectsFrontpageAccounts extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Fixes a preference that may include deleted accounts or accounts of another type.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:fix-frontpage-accounts';
 | 
			
		||||
    protected $signature   = 'correction:frontpage-accounts';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
@@ -55,7 +52,6 @@ class FixFrontpageAccounts extends Command
 | 
			
		||||
                $this->fixPreference($preference);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $this->friendlyPositive('Account preferences are OK');
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -74,7 +70,7 @@ class FixFrontpageAccounts extends Command
 | 
			
		||||
        if (is_array($data)) {
 | 
			
		||||
            /** @var string $accountId */
 | 
			
		||||
            foreach ($data as $accountId) {
 | 
			
		||||
                $accountIdInt = (int)$accountId;
 | 
			
		||||
                $accountIdInt = (int) $accountId;
 | 
			
		||||
                $account      = $repository->find($accountIdInt);
 | 
			
		||||
                if (null !== $account
 | 
			
		||||
                    && in_array($account->accountType->type, [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], true)
 | 
			
		||||
@@ -34,12 +34,12 @@ use Illuminate\Console\Command;
 | 
			
		||||
/**
 | 
			
		||||
 * Class FixGroupAccounts
 | 
			
		||||
 */
 | 
			
		||||
class FixGroupAccounts extends Command
 | 
			
		||||
class CorrectsGroupAccounts extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Unify the source / destination accounts of split groups.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:unify-group-accounts';
 | 
			
		||||
    protected $signature   = 'correction:group-accounts';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
@@ -53,8 +53,8 @@ class FixGroupAccounts extends Command
 | 
			
		||||
 | 
			
		||||
        /** @var TransactionJournal $journal */
 | 
			
		||||
        foreach ($res as $journal) {
 | 
			
		||||
            if ((int)$journal->the_count > 1) {
 | 
			
		||||
                $groups[] = (int)$journal->transaction_group_id;
 | 
			
		||||
            if ((int) $journal->the_count > 1) {
 | 
			
		||||
                $groups[] = (int) $journal->transaction_group_id;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $handler = new UpdatedGroupEventHandler();
 | 
			
		||||
@@ -64,8 +64,6 @@ class FixGroupAccounts extends Command
 | 
			
		||||
            $handler->unifyAccounts($event);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->friendlyPositive('Updated possible inconsistent transaction groups.');
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * UpdateGroupInformation.php
 | 
			
		||||
 * Copyright (c) 2022 james@firefly-iii.org
 | 
			
		||||
 * CorrectsGroupInformation.php
 | 
			
		||||
 * Copyright (c) 2024 james@firefly-iii.org.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of Firefly III (https://github.com/firefly-iii).
 | 
			
		||||
 *
 | 
			
		||||
@@ -17,12 +17,12 @@
 | 
			
		||||
 * 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/>.
 | 
			
		||||
 * along with this program.  If not, see https://www.gnu.org/licenses/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace FireflyIII\Console\Commands\Integrity;
 | 
			
		||||
namespace FireflyIII\Console\Commands\Correction;
 | 
			
		||||
 | 
			
		||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
 | 
			
		||||
use FireflyIII\Models\Account;
 | 
			
		||||
@@ -45,15 +45,12 @@ use FireflyIII\User;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
use Illuminate\Database\QueryException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class UpdateGroupInformation
 | 
			
		||||
 */
 | 
			
		||||
class UpdateGroupInformation extends Command
 | 
			
		||||
class CorrectsGroupInformation extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Makes sure that every object is linked to a group';
 | 
			
		||||
    protected $signature   = 'firefly-iii:upgrade-group-information';
 | 
			
		||||
    protected $signature   = 'correction:group-information';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
@@ -79,7 +76,7 @@ class UpdateGroupInformation extends Command
 | 
			
		||||
    {
 | 
			
		||||
        $group = $user->userGroup;
 | 
			
		||||
        if (null === $group) {
 | 
			
		||||
            $this->friendlyWarning(sprintf('User "%s" has no group.', $user->email));
 | 
			
		||||
            $this->friendlyWarning(sprintf('User "%s" has no group. Please run "php artisan firefly-iii:create-group-memberships"', $user->email));
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -30,15 +30,12 @@ use FireflyIII\Models\AccountType;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class FixIbans
 | 
			
		||||
 */
 | 
			
		||||
class FixIbans extends Command
 | 
			
		||||
class CorrectsIbans extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Removes spaces from IBANs';
 | 
			
		||||
    protected $signature   = 'firefly-iii:fix-ibans';
 | 
			
		||||
    protected $signature   = 'correction:ibans';
 | 
			
		||||
    private int $count     = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -49,9 +46,6 @@ class FixIbans extends Command
 | 
			
		||||
        $accounts = Account::whereNotNull('iban')->get();
 | 
			
		||||
        $this->filterIbans($accounts);
 | 
			
		||||
        $this->countAndCorrectIbans($accounts);
 | 
			
		||||
        if (0 === $this->count) {
 | 
			
		||||
            $this->friendlyPositive('All IBANs are valid.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -28,24 +28,22 @@ use FireflyIII\Console\Commands\ShowsFriendlyMessages;
 | 
			
		||||
use FireflyIII\Models\TransactionGroup;
 | 
			
		||||
use FireflyIII\Models\TransactionJournal;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class FixLongDescriptions
 | 
			
		||||
 */
 | 
			
		||||
class FixLongDescriptions extends Command
 | 
			
		||||
class CorrectsLongDescriptions extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    private const int MAX_LENGTH = 1000;
 | 
			
		||||
    protected $description       = 'Fixes long descriptions in journals and groups.';
 | 
			
		||||
    protected $signature         = 'firefly-iii:fix-long-descriptions';
 | 
			
		||||
    protected $signature         = 'correction:long-descriptions';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(): int
 | 
			
		||||
    {
 | 
			
		||||
        $journals = TransactionJournal::get(['id', 'description']);
 | 
			
		||||
        $journals = TransactionJournal::where(DB::raw('LENGTH(description)'), '>', self::MAX_LENGTH)->get(['id', 'description']);
 | 
			
		||||
        $count    = 0;
 | 
			
		||||
 | 
			
		||||
        /** @var TransactionJournal $journal */
 | 
			
		||||
@@ -58,20 +56,17 @@ class FixLongDescriptions extends Command
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $groups   = TransactionGroup::get(['id', 'title']);
 | 
			
		||||
        $groups   = TransactionGroup::where(DB::raw('LENGTH(title)'), '>', self::MAX_LENGTH)->get(['id', 'title']);
 | 
			
		||||
 | 
			
		||||
        /** @var TransactionGroup $group */
 | 
			
		||||
        foreach ($groups as $group) {
 | 
			
		||||
            if (strlen((string)$group->title) > self::MAX_LENGTH) {
 | 
			
		||||
            if (strlen((string) $group->title) > self::MAX_LENGTH) {
 | 
			
		||||
                $group->title = substr($group->title, 0, self::MAX_LENGTH);
 | 
			
		||||
                $group->save();
 | 
			
		||||
                $this->friendlyWarning(sprintf('Truncated description of transaction group #%d', $group->id));
 | 
			
		||||
                ++$count;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $this->friendlyPositive('All transaction group and journal title lengths are within bounds.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -26,16 +26,14 @@ namespace FireflyIII\Console\Commands\Correction;
 | 
			
		||||
 | 
			
		||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class RenameMetaFields
 | 
			
		||||
 */
 | 
			
		||||
class RenameMetaFields extends Command
 | 
			
		||||
class CorrectsMetaDataFields extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Rename changed meta fields.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:rename-meta-fields';
 | 
			
		||||
    protected $signature   = 'correction:meta-fields';
 | 
			
		||||
 | 
			
		||||
    private int $count     = 0;
 | 
			
		||||
 | 
			
		||||
@@ -61,9 +59,6 @@ class RenameMetaFields extends Command
 | 
			
		||||
        foreach ($changes as $original => $update) {
 | 
			
		||||
            $this->rename($original, $update);
 | 
			
		||||
        }
 | 
			
		||||
        if (0 === $this->count) {
 | 
			
		||||
            $this->friendlyPositive('All meta fields are correct.');
 | 
			
		||||
        }
 | 
			
		||||
        if (0 !== $this->count) {
 | 
			
		||||
            $this->friendlyInfo(sprintf('Renamed %d meta field(s).', $this->count));
 | 
			
		||||
        }
 | 
			
		||||
@@ -73,7 +68,7 @@ class RenameMetaFields extends Command
 | 
			
		||||
 | 
			
		||||
    private function rename(string $original, string $update): void
 | 
			
		||||
    {
 | 
			
		||||
        $total = \DB::table('journal_meta')
 | 
			
		||||
        $total = DB::table('journal_meta')
 | 
			
		||||
            ->where('name', '=', $original)
 | 
			
		||||
            ->update(['name' => $update])
 | 
			
		||||
        ;
 | 
			
		||||
@@ -46,13 +46,13 @@ use Illuminate\Database\Query\Builder as DatabaseBuilder;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
use Illuminate\Support\Facades\Log;
 | 
			
		||||
 | 
			
		||||
class RecalculateNativeAmounts extends Command
 | 
			
		||||
class CorrectsNativeAmounts extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Recalculate native amounts for all objects.';
 | 
			
		||||
 | 
			
		||||
    protected $signature   = 'firefly-iii:recalculate-native-amounts';
 | 
			
		||||
    protected $signature   = 'correction:recalculate-native-amounts';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
@@ -108,6 +108,7 @@ class RecalculateNativeAmounts extends Command
 | 
			
		||||
    private function recalculatePiggyBanks(UserGroup $userGroup, TransactionCurrency $currency): void
 | 
			
		||||
    {
 | 
			
		||||
        $converter  = new ExchangeRateConverter();
 | 
			
		||||
        $converter->setUserGroup($userGroup);
 | 
			
		||||
        $converter->setIgnoreSettings(true);
 | 
			
		||||
        $repository = app(PiggyBankRepositoryInterface::class);
 | 
			
		||||
        $repository->setUserGroup($userGroup);
 | 
			
		||||
@@ -181,17 +182,6 @@ class RecalculateNativeAmounts extends Command
 | 
			
		||||
        Log::debug(sprintf('Recalculated %d auto budgets.', $set->count()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function recalculateBills(UserGroup $userGroup, TransactionCurrency $currency): void
 | 
			
		||||
    {
 | 
			
		||||
        $set = $userGroup->bills()->where('transaction_currency_id', '!=', $currency->id)->get();
 | 
			
		||||
 | 
			
		||||
        /** @var Bill $bill */
 | 
			
		||||
        foreach ($set as $bill) {
 | 
			
		||||
            $bill->touch();
 | 
			
		||||
        }
 | 
			
		||||
        Log::debug(sprintf('Recalculated %d bills.', $set->count()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function recalculateAvailableBudgets(UserGroup $userGroup, TransactionCurrency $currency): void
 | 
			
		||||
    {
 | 
			
		||||
        Log::debug('Start with available budgets.');
 | 
			
		||||
@@ -204,17 +194,36 @@ class RecalculateNativeAmounts extends Command
 | 
			
		||||
        Log::debug(sprintf('Recalculated %d available budgets.', $set->count()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function recalculateBills(UserGroup $userGroup, TransactionCurrency $currency): void
 | 
			
		||||
    {
 | 
			
		||||
        $set = $userGroup->bills()->where('transaction_currency_id', '!=', $currency->id)->get();
 | 
			
		||||
 | 
			
		||||
        /** @var Bill $bill */
 | 
			
		||||
        foreach ($set as $bill) {
 | 
			
		||||
            $bill->touch();
 | 
			
		||||
        }
 | 
			
		||||
        Log::debug(sprintf('Recalculated %d bills.', $set->count()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function calculateTransactions(UserGroup $userGroup, TransactionCurrency $currency): void
 | 
			
		||||
    {
 | 
			
		||||
        // custom query because of the potential size of this update.
 | 
			
		||||
        $set                              = DB::table('transactions')
 | 
			
		||||
            ->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
 | 
			
		||||
            ->where('transaction_journals.user_group_id', $userGroup->id)
 | 
			
		||||
            ->where(static function (DatabaseBuilder $q) use ($currency): void {
 | 
			
		||||
                $q->whereNot('transactions.transaction_currency_id', $currency->id)
 | 
			
		||||
                    ->orWhereNot('transactions.foreign_currency_id', $currency->id)
 | 
			
		||||
                ;
 | 
			
		||||
 | 
			
		||||
            ->where(function (DatabaseBuilder $q1) use ($currency): void {
 | 
			
		||||
                $q1->where(function (DatabaseBuilder $q2) use ($currency): void {
 | 
			
		||||
                    $q2->whereNot('transactions.transaction_currency_id', $currency->id)->whereNull('transactions.foreign_currency_id');
 | 
			
		||||
                })->orWhere(function (DatabaseBuilder $q3) use ($currency): void {
 | 
			
		||||
                    $q3->whereNot('transactions.transaction_currency_id', $currency->id)->whereNot('transactions.foreign_currency_id', $currency->id);
 | 
			
		||||
                });
 | 
			
		||||
            })
 | 
			
		||||
//            ->where(static function (DatabaseBuilder $q) use ($currency): void {
 | 
			
		||||
//                $q->whereNot('transactions.transaction_currency_id', $currency->id)
 | 
			
		||||
//                    ->whereNot('transactions.foreign_currency_id', $currency->id)
 | 
			
		||||
//                ;
 | 
			
		||||
//            })
 | 
			
		||||
            ->get(['transactions.id'])
 | 
			
		||||
        ;
 | 
			
		||||
        TransactionObserver::$recalculate = false;
 | 
			
		||||
@@ -35,15 +35,12 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
 | 
			
		||||
use Illuminate\Console\Command;
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class CorrectOpeningBalanceCurrencies
 | 
			
		||||
 */
 | 
			
		||||
class CorrectOpeningBalanceCurrencies extends Command
 | 
			
		||||
class CorrectsOpeningBalanceCurrencies extends Command
 | 
			
		||||
{
 | 
			
		||||
    use ShowsFriendlyMessages;
 | 
			
		||||
 | 
			
		||||
    protected $description = 'Will make sure that opening balance transaction currencies match the account they\'re for.';
 | 
			
		||||
    protected $signature   = 'firefly-iii:fix-ob-currencies';
 | 
			
		||||
    protected $signature   = 'correction:opening-balance-currencies';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
@@ -62,10 +59,6 @@ class CorrectOpeningBalanceCurrencies extends Command
 | 
			
		||||
            $message = sprintf('Corrected %d opening balance transaction(s).', $count);
 | 
			
		||||
            $this->friendlyInfo($message);
 | 
			
		||||
        }
 | 
			
		||||
        if (0 === $count) {
 | 
			
		||||
            $message = 'There was nothing to fix in the opening balance transactions.';
 | 
			
		||||
            $this->friendlyPositive($message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -115,7 +108,7 @@ class CorrectOpeningBalanceCurrencies extends Command
 | 
			
		||||
    {
 | 
			
		||||
        $currency = $this->getCurrency($account);
 | 
			
		||||
        $count    = 0;
 | 
			
		||||
        if ((int)$journal->transaction_currency_id !== $currency->id) {
 | 
			
		||||
        if ((int) $journal->transaction_currency_id !== $currency->id) {
 | 
			
		||||
            $journal->transaction_currency_id = $currency->id;
 | 
			
		||||
            $journal->save();
 | 
			
		||||
            $count                            = 1;
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user