mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-03-02 22:14:11 +00:00
Compare commits
21 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
028544ca2e | ||
|
|
af46729372 | ||
|
|
4c7789a668 | ||
|
|
292908048c | ||
|
|
e300314e05 | ||
|
|
4f1f360346 | ||
|
|
bff856aeff | ||
|
|
7f5a1bda8d | ||
|
|
b506281bd6 | ||
|
|
dfe9b3e787 | ||
|
|
2428a2a7c5 | ||
|
|
0e8f608e00 | ||
|
|
70071767ab | ||
|
|
0ad6beb66c | ||
|
|
1197f65589 | ||
|
|
7bbf2dcc6f | ||
|
|
d4ab69ebe6 | ||
|
|
c8c552602e | ||
|
|
1921a8050b | ||
|
|
f488feda93 | ||
|
|
d90c033b83 |
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
@@ -117,6 +118,13 @@ class ListController extends Controller
|
||||
$count = $collection->count();
|
||||
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$piggyBanks = $enrichment->enrich($piggyBanks);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.accounts.piggy-banks', [$account->id]).$this->buildParams());
|
||||
@@ -125,7 +133,7 @@ class ListController extends Controller
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks');
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
||||
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Category\StoreRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\CategoryEnrichment;
|
||||
use FireflyIII\Transformers\CategoryTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -72,6 +74,15 @@ class StoreController extends Controller
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new CategoryEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setStart($this->parameters->get('start'));
|
||||
$enrichment->setEnd($this->parameters->get('end'));
|
||||
$category = $enrichment->enrichSingle($category);
|
||||
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
||||
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Category\UpdateRequest;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\CategoryEnrichment;
|
||||
use FireflyIII\Transformers\CategoryTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -71,6 +73,15 @@ class UpdateController extends Controller
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new CategoryEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setStart($this->parameters->get('start'));
|
||||
$enrichment->setEnd($this->parameters->get('end'));
|
||||
$category = $enrichment->enrichSingle($category);
|
||||
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\ExchangeRateTransformer;
|
||||
@@ -39,7 +40,7 @@ class IndexController extends Controller
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'currency_exchange_rates';
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::OWNER];
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
@@ -41,7 +42,7 @@ class ShowController extends Controller
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'exchange-rates';
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::OWNER];
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\StoreRequest;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
@@ -37,7 +38,7 @@ class StoreController extends Controller
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'exchange-rates';
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::OWNER];
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\UpdateRequest;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
@@ -37,7 +38,7 @@ class UpdateController extends Controller
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'exchange-rates';
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::OWNER];
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
|
||||
@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
@@ -124,6 +125,13 @@ class ListController extends Controller
|
||||
$count = $collection->count();
|
||||
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$piggyBanks = $enrichment->enrich($piggyBanks);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.object-groups.piggy-banks', [$objectGroup->id]).$this->buildParams());
|
||||
@@ -132,7 +140,7 @@ class ListController extends Controller
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks');
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
||||
@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEventEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
@@ -148,6 +149,13 @@ class ListController extends Controller
|
||||
$count = $collection->count();
|
||||
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEventEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$events = $enrichment->enrich($events);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy-banks.events', [$piggyBank->id]).$this->buildParams());
|
||||
@@ -156,7 +164,7 @@ class ListController extends Controller
|
||||
$transformer = app(PiggyBankEventTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events');
|
||||
$resource = new FractalCollection($events, $transformer, sprintf('piggy-banks/%d/events', $piggyBank->id));
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
||||
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
@@ -77,6 +79,13 @@ class ShowController extends Controller
|
||||
$count = $collection->count();
|
||||
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$piggyBanks = $enrichment->enrich($piggyBanks);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy-banks.index').$this->buildParams());
|
||||
@@ -85,7 +94,7 @@ class ShowController extends Controller
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks');
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
@@ -101,11 +110,19 @@ class ShowController extends Controller
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
||||
|
||||
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||
$resource = new Item($piggyBank, $transformer, 'piggy-banks');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\PiggyBank\StoreRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -68,6 +70,13 @@ class StoreController extends Controller
|
||||
$piggyBank = $this->repository->store($request->getAll());
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
||||
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\PiggyBank\UpdateRequest;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -70,13 +72,20 @@ class UpdateController extends Controller
|
||||
$this->repository->setCurrentAmount($piggyBank, $data['current_amount']);
|
||||
}
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
||||
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||
$resource = new Item($piggyBank, $transformer, 'piggy-banks');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
@@ -76,17 +78,24 @@ class ShowController extends Controller
|
||||
// get list of budgets. Count it and split it.
|
||||
$collection = $this->repository->get();
|
||||
$count = $collection->count();
|
||||
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$recurrences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new RecurringEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$recurrences = $enrichment->enrich($recurrences);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator = new LengthAwarePaginator($recurrences, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.recurrences.index').$this->buildParams());
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'recurrences');
|
||||
$resource = new FractalCollection($recurrences, $transformer, 'recurrences');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
@@ -102,6 +111,13 @@ class ShowController extends Controller
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new RecurringEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$recurrence = $enrichment->enrichSingle($recurrence);
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Recurrence\StoreRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -69,6 +71,13 @@ class StoreController extends Controller
|
||||
$recurrence = $this->repository->store($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new RecurringEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$recurrence = $enrichment->enrichSingle($recurrence);
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Recurrence\UpdateRequest;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -67,6 +69,13 @@ class UpdateController extends Controller
|
||||
$recurrence = $this->repository->update($recurrence, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new RecurringEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$recurrence = $enrichment->enrichSingle($recurrence);
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEventEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use FireflyIII\Transformers\TransactionLinkTransformer;
|
||||
@@ -113,6 +114,14 @@ class ListController extends Controller
|
||||
}
|
||||
$count = $collection->count();
|
||||
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEventEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$events = $enrichment->enrich($events);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.transactions.piggy-bank-events', [$transactionGroup->id]).$this->buildParams());
|
||||
|
||||
@@ -44,6 +44,7 @@ use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
@@ -276,17 +277,24 @@ class ListController extends Controller
|
||||
}
|
||||
);
|
||||
$count = $collection->count();
|
||||
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$recurrences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new RecurringEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$recurrences = $enrichment->enrich($recurrences);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator = new LengthAwarePaginator($recurrences, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]).$this->buildParams());
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'recurrences');
|
||||
$resource = new FractalCollection($recurrences, $transformer, 'recurrences');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
||||
@@ -157,6 +157,11 @@ class DebugController extends Controller
|
||||
return view('debug', compact('table', 'now', 'logContent'));
|
||||
}
|
||||
|
||||
public function apiTest()
|
||||
{
|
||||
return view('test.api-test');
|
||||
}
|
||||
|
||||
private function generateTable(): string
|
||||
{
|
||||
// system information:
|
||||
|
||||
@@ -32,8 +32,10 @@ use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -114,6 +116,13 @@ class IndexController extends Controller
|
||||
$transformer->setParameters(new ParameterBag());
|
||||
$piggyBanks = [];
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$collection = $enrichment->enrich($collection);
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($collection as $piggy) {
|
||||
$array = $transformer->transform($piggy);
|
||||
|
||||
@@ -29,7 +29,9 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\View\View;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
@@ -75,6 +77,13 @@ class ShowController extends Controller
|
||||
$parameters = new ParameterBag();
|
||||
$parameters->set('end', $end);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new PiggyBankEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$piggyBank = $enrichment->enrichSingle($piggyBank);
|
||||
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($parameters);
|
||||
|
||||
@@ -34,7 +34,9 @@ use FireflyIII\Models\RecurrenceRepetition;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -92,6 +94,13 @@ class EditController extends Controller
|
||||
throw new FireflyException('This recurring transaction has no meta-data. You will have to delete it and recreate it. Sorry!');
|
||||
}
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new RecurringEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$recurrence = $enrichment->enrichSingle($recurrence);
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters(new ParameterBag());
|
||||
|
||||
@@ -29,7 +29,9 @@ use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@@ -85,6 +87,13 @@ class IndexController extends Controller
|
||||
$total = $collection->count();
|
||||
$recurrences = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new RecurringEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$recurrences = $enrichment->enrich($recurrences);
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters(new ParameterBag());
|
||||
|
||||
@@ -32,8 +32,10 @@ use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\View\View;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
@@ -80,6 +82,13 @@ class ShowController extends Controller
|
||||
{
|
||||
$repos = app(AttachmentRepositoryInterface::class);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new RecurringEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$recurrence = $enrichment->enrichSingle($recurrence);
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters(new ParameterBag());
|
||||
|
||||
@@ -51,7 +51,7 @@ use Override;
|
||||
*/
|
||||
class AccountEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private array $accountIds;
|
||||
private array $ids;
|
||||
private array $accountTypeIds;
|
||||
private array $accountTypes;
|
||||
private Collection $collection;
|
||||
@@ -66,13 +66,14 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
private array $lastActivities;
|
||||
private ?Carbon $date = null;
|
||||
private bool $convertToPrimary = false;
|
||||
private array $balances = [];
|
||||
|
||||
/**
|
||||
* TODO The account enricher must do conversion from and to the primary currency.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->accountIds = [];
|
||||
$this->ids = [];
|
||||
$this->openingBalances = [];
|
||||
$this->currencies = [];
|
||||
$this->accountTypeIds = [];
|
||||
@@ -105,7 +106,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
// prep local fields
|
||||
$this->collection = $collection;
|
||||
$this->collectAccountIds();
|
||||
$this->collectIds();
|
||||
$this->getAccountTypes();
|
||||
$this->collectMetaData();
|
||||
$this->collectNotes();
|
||||
@@ -118,14 +119,14 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
private function collectAccountIds(): void
|
||||
private function collectIds(): void
|
||||
{
|
||||
/** @var Account $account */
|
||||
foreach ($this->collection as $account) {
|
||||
$this->accountIds[] = (int) $account->id;
|
||||
$this->accountTypeIds[] = (int) $account->account_type_id;
|
||||
$this->ids[] = (int)$account->id;
|
||||
$this->accountTypeIds[] = (int)$account->account_type_id;
|
||||
}
|
||||
$this->accountIds = array_unique($this->accountIds);
|
||||
$this->ids = array_unique($this->ids);
|
||||
$this->accountTypeIds = array_unique($this->accountTypeIds);
|
||||
}
|
||||
|
||||
@@ -135,27 +136,29 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
/** @var AccountType $type */
|
||||
foreach ($types as $type) {
|
||||
$this->accountTypes[(int) $type->id] = $type->type;
|
||||
$this->accountTypes[(int)$type->id] = $type->type;
|
||||
}
|
||||
}
|
||||
|
||||
private function collectMetaData(): void
|
||||
{
|
||||
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
|
||||
->whereIn('account_id', $this->accountIds)
|
||||
->whereIn('account_id', $this->ids)
|
||||
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray()
|
||||
;
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($set as $entry) {
|
||||
$this->meta[(int) $entry['account_id']][$entry['name']] = (string) $entry['data'];
|
||||
$this->meta[(int)$entry['account_id']][$entry['name']] = (string)$entry['data'];
|
||||
if ('currency_id' === $entry['name']) {
|
||||
$this->currencies[(int) $entry['data']] = true;
|
||||
$this->currencies[(int)$entry['data']] = true;
|
||||
}
|
||||
}
|
||||
$currencies = TransactionCurrency::whereIn('id', array_keys($this->currencies))->get();
|
||||
foreach ($currencies as $currency) {
|
||||
$this->currencies[(int) $currency->id] = $currency;
|
||||
if (count($this->currencies) > 0) {
|
||||
$currencies = TransactionCurrency::whereIn('id', array_keys($this->currencies))->get();
|
||||
foreach ($currencies as $currency) {
|
||||
$this->currencies[(int)$currency->id] = $currency;
|
||||
}
|
||||
}
|
||||
$this->currencies[0] = $this->primaryCurrency;
|
||||
foreach ($this->currencies as $id => $currency) {
|
||||
@@ -167,28 +170,28 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->accountIds)
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int) $note['noteable_id']] = (string) $note['text'];
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d note(s)', count($this->notes)));
|
||||
}
|
||||
|
||||
private function collectLocations(): void
|
||||
{
|
||||
$locations = Location::query()->whereIn('locatable_id', $this->accountIds)
|
||||
$locations = Location::query()->whereIn('locatable_id', $this->ids)
|
||||
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray()
|
||||
;
|
||||
foreach ($locations as $location) {
|
||||
$this->locations[(int) $location['locatable_id']]
|
||||
$this->locations[(int)$location['locatable_id']]
|
||||
= [
|
||||
'latitude' => (float) $location['latitude'],
|
||||
'longitude' => (float) $location['longitude'],
|
||||
'zoom_level' => (int) $location['zoom_level'],
|
||||
'latitude' => (float)$location['latitude'],
|
||||
'longitude' => (float)$location['longitude'],
|
||||
'zoom_level' => (int)$location['zoom_level'],
|
||||
];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
|
||||
@@ -208,12 +211,12 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
;
|
||||
$journals = $collector->getExtractedJournals();
|
||||
foreach ($journals as $journal) {
|
||||
$this->openingBalances[(int) $journal['source_account_id']]
|
||||
$this->openingBalances[(int)$journal['source_account_id']]
|
||||
= [
|
||||
'amount' => Steam::negative($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
$this->openingBalances[(int) $journal['destination_account_id']]
|
||||
$this->openingBalances[(int)$journal['destination_account_id']]
|
||||
= [
|
||||
'amount' => Steam::positive($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
@@ -234,59 +237,61 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$notes = $this->notes;
|
||||
$openingBalances = $this->openingBalances;
|
||||
$locations = $this->locations;
|
||||
$lastActivities = $this->lastActivities;
|
||||
$this->collection = $this->collection->map(function (Account $item) use ($notes, $openingBalances, $locations, $lastActivities) {
|
||||
$item->full_account_type = $this->accountTypes[(int) $item->account_type_id] ?? null;
|
||||
$accountMeta = [
|
||||
'currency' => null,
|
||||
'location' => [
|
||||
$this->collection = $this->collection->map(function (Account $item) {
|
||||
$id = (int)$item->id;
|
||||
$item->full_account_type = $this->accountTypes[(int)$item->account_type_id] ?? null;
|
||||
$meta = [
|
||||
'currency' => null,
|
||||
'location' => [
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoom_level' => null,
|
||||
],
|
||||
'opening_balance_date' => null,
|
||||
'opening_balance_date' => null,
|
||||
'opening_balance_amount' => null,
|
||||
'account_number' => null,
|
||||
'notes' => $notes[$id] ?? null,
|
||||
'last_activity' => $this->lastActivities[$id] ?? null,
|
||||
];
|
||||
if (array_key_exists((int) $item->id, $this->meta)) {
|
||||
foreach ($this->meta[(int) $item->id] as $name => $value) {
|
||||
$accountMeta[$name] = $value;
|
||||
|
||||
// if location, add location:
|
||||
if (array_key_exists($id, $this->locations)) {
|
||||
$meta['location'] = $this->locations[$id];
|
||||
}
|
||||
if (array_key_exists($id, $this->meta)) {
|
||||
foreach ($this->meta[$id] as $name => $value) {
|
||||
$meta[$name] = $value;
|
||||
}
|
||||
}
|
||||
// also add currency, if present.
|
||||
if (array_key_exists('currency_id', $accountMeta)) {
|
||||
$currencyId = (int) $accountMeta['currency_id'];
|
||||
$accountMeta['currency'] = $this->currencies[$currencyId];
|
||||
if (array_key_exists('currency_id', $meta)) {
|
||||
$currencyId = (int)$meta['currency_id'];
|
||||
$meta['currency'] = $this->currencies[$currencyId];
|
||||
}
|
||||
|
||||
// if notes, add notes.
|
||||
if (array_key_exists($item->id, $notes)) {
|
||||
$accountMeta['notes'] = $notes[$item->id];
|
||||
}
|
||||
// if opening balance, add opening balance
|
||||
if (array_key_exists($item->id, $openingBalances)) {
|
||||
$accountMeta['opening_balance_date'] = $openingBalances[$item->id]['date'];
|
||||
$accountMeta['opening_balance_amount'] = $openingBalances[$item->id]['amount'];
|
||||
if (array_key_exists($id, $this->openingBalances)) {
|
||||
$meta['opening_balance_date'] = $this->openingBalances[$id]['date'];
|
||||
$meta['opening_balance_amount'] = $this->openingBalances[$id]['amount'];
|
||||
}
|
||||
|
||||
// add balances
|
||||
// get currencies:
|
||||
$currency = $this->primaryCurrency; // assume primary currency
|
||||
if (null !== $accountMeta['currency']) {
|
||||
$currency = $accountMeta['currency'];
|
||||
if (null !== $meta['currency']) {
|
||||
$currency = $meta['currency'];
|
||||
}
|
||||
|
||||
// get the current balance:
|
||||
$date = $this->getDate();
|
||||
$finalBalance = Steam::finalAccountBalance($item, $date, $this->primaryCurrency, $this->convertToPrimary);
|
||||
// $finalBalance = Steam::finalAccountBalance($item, $date, $this->primaryCurrency, $this->convertToPrimary);
|
||||
$finalBalance = $this->balances[$id];
|
||||
Log::debug(sprintf('Call finalAccountBalance(%s) with date/time "%s"', var_export($this->convertToPrimary, true), $date->toIso8601String()), $finalBalance);
|
||||
|
||||
// collect current balances:
|
||||
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
|
||||
$openingBalance = Steam::bcround($accountMeta['opening_balance_amount'] ?? '0', $currency->decimal_places);
|
||||
$openingBalance = Steam::bcround($meta['opening_balance_amount'] ?? '0', $currency->decimal_places);
|
||||
$virtualBalance = Steam::bcround($account->virtual_balance ?? '0', $currency->decimal_places);
|
||||
$debtAmount = $accountMeta['current_debt'] ?? null;
|
||||
$debtAmount = $meta['current_debt'] ?? null;
|
||||
|
||||
// set some pc_ default values to NULL:
|
||||
$pcCurrentBalance = null;
|
||||
@@ -311,11 +316,11 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
// set opening balance(s) to NULL if the date is null
|
||||
if (null === $accountMeta['opening_balance_date']) {
|
||||
if (null === $meta['opening_balance_date']) {
|
||||
$openingBalance = null;
|
||||
$pcOpeningBalance = null;
|
||||
}
|
||||
$accountMeta['balances'] = [
|
||||
$meta['balances'] = [
|
||||
'current_balance' => $currentBalance,
|
||||
'pc_current_balance' => $pcCurrentBalance,
|
||||
'opening_balance' => $openingBalance,
|
||||
@@ -326,16 +331,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
'pc_debt_amount' => $pcDebtAmount,
|
||||
];
|
||||
// end add balances
|
||||
|
||||
|
||||
// if location, add location:
|
||||
if (array_key_exists($item->id, $locations)) {
|
||||
$accountMeta['location'] = $locations[$item->id];
|
||||
}
|
||||
if (array_key_exists($item->id, $lastActivities)) {
|
||||
$accountMeta['last_activity'] = $lastActivities[$item->id];
|
||||
}
|
||||
$item->meta = $accountMeta;
|
||||
$item->meta = $meta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
@@ -343,10 +339,13 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectLastActivities(): void
|
||||
{
|
||||
$this->lastActivities = Steam::getLastActivities($this->accountIds);
|
||||
$this->lastActivities = Steam::getLastActivities($this->ids);
|
||||
}
|
||||
|
||||
private function collectBalances(): void {}
|
||||
private function collectBalances(): void
|
||||
{
|
||||
$this->balances = Steam::accountsBalancesOptimized($this->collection, $this->getDate(), $this->primaryCurrency, $this->convertToPrimary);
|
||||
}
|
||||
|
||||
public function setDate(?Carbon $date): void
|
||||
{
|
||||
|
||||
@@ -45,6 +45,8 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
private TransactionCurrency $primaryCurrency;
|
||||
private bool $convertToPrimary = false;
|
||||
private array $ids = [];
|
||||
private array $currencyIds = [];
|
||||
private array $currencies = [];
|
||||
private Collection $collection;
|
||||
private array $spentInBudgets = [];
|
||||
private array $spentOutsideBudgets = [];
|
||||
@@ -72,6 +74,7 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->collectIds();
|
||||
$this->collectCurrencies();
|
||||
$this->collectSpentInfo();
|
||||
$this->appendCollectedData();
|
||||
|
||||
@@ -108,7 +111,8 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
{
|
||||
/** @var AvailableBudget $availableBudget */
|
||||
foreach ($this->collection as $availableBudget) {
|
||||
$this->ids[] = (int) $availableBudget->id;
|
||||
$this->ids[] = (int)$availableBudget->id;
|
||||
$this->currencyIds[(int)$availableBudget->id] = (int)$availableBudget->transaction_currency_id;
|
||||
}
|
||||
$this->ids = array_unique($this->ids);
|
||||
}
|
||||
@@ -121,15 +125,17 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
$spentInBudgets = $this->opsRepository->collectExpenses($start, $end, null, $allActive, null);
|
||||
$spentOutsideBudgets = $this->noBudgetRepository->collectExpenses($start, $end, null, null, null);
|
||||
foreach ($this->collection as $availableBudget) {
|
||||
$id = (int) $availableBudget->id;
|
||||
$filteredSpentInBudgets = $this->opsRepository->sumCollectedExpenses($spentInBudgets, $availableBudget->start_date, $availableBudget->end_date, $availableBudget->transactionCurrency, false);
|
||||
$filteredSpentOutsideBudgets = $this->opsRepository->sumCollectedExpenses($spentOutsideBudgets, $availableBudget->start_date, $availableBudget->end_date, $availableBudget->transactionCurrency, false);
|
||||
$id = (int)$availableBudget->id;
|
||||
$currencyId = $this->currencyIds[$id];
|
||||
$currency = $this->currencies[$currencyId];
|
||||
$filteredSpentInBudgets = $this->opsRepository->sumCollectedExpenses($spentInBudgets, $availableBudget->start_date, $availableBudget->end_date, $currency, false);
|
||||
$filteredSpentOutsideBudgets = $this->opsRepository->sumCollectedExpenses($spentOutsideBudgets, $availableBudget->start_date, $availableBudget->end_date, $currency, false);
|
||||
$this->spentInBudgets[$id] = array_values($filteredSpentInBudgets);
|
||||
$this->spentOutsideBudgets[$id] = array_values($filteredSpentOutsideBudgets);
|
||||
|
||||
if (true === $this->convertToPrimary) {
|
||||
$pcFilteredSpentInBudgets = $this->opsRepository->sumCollectedExpenses($spentInBudgets, $availableBudget->start_date, $availableBudget->end_date, $availableBudget->transactionCurrency, true);
|
||||
$pcFilteredSpentOutsideBudgets = $this->opsRepository->sumCollectedExpenses($spentOutsideBudgets, $availableBudget->start_date, $availableBudget->end_date, $availableBudget->transactionCurrency, true);
|
||||
$pcFilteredSpentInBudgets = $this->opsRepository->sumCollectedExpenses($spentInBudgets, $availableBudget->start_date, $availableBudget->end_date, $currency, true);
|
||||
$pcFilteredSpentOutsideBudgets = $this->opsRepository->sumCollectedExpenses($spentOutsideBudgets, $availableBudget->start_date, $availableBudget->end_date, $currency, true);
|
||||
$this->pcSpentInBudgets[$id] = array_values($pcFilteredSpentInBudgets);
|
||||
$this->pcSpentOutsideBudgets[$id] = array_values($pcFilteredSpentOutsideBudgets);
|
||||
}
|
||||
@@ -145,22 +151,29 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$spentInsideBudgets = $this->spentInBudgets;
|
||||
$spentOutsideBudgets = $this->spentOutsideBudgets;
|
||||
$pcSpentInBudgets = $this->pcSpentInBudgets;
|
||||
$pcSpentOutsideBudgets = $this->pcSpentOutsideBudgets;
|
||||
$this->collection = $this->collection->map(function (AvailableBudget $item) use ($spentInsideBudgets, $spentOutsideBudgets, $pcSpentInBudgets, $pcSpentOutsideBudgets) {
|
||||
$id = (int) $item->id;
|
||||
$this->collection = $this->collection->map(function (AvailableBudget $item) {
|
||||
$id = (int)$item->id;
|
||||
$currencyId = $this->currencyIds[$id];
|
||||
$currency = $this->currencies[$currencyId];
|
||||
$meta = [
|
||||
'spent_in_budgets' => $spentInsideBudgets[$id] ?? [],
|
||||
'pc_spent_in_budgets' => $pcSpentInBudgets[$id] ?? [],
|
||||
|
||||
'spent_outside_budgets' => $spentOutsideBudgets[$id] ?? [],
|
||||
'pc_spent_outside_budgets' => $pcSpentOutsideBudgets[$id] ?? [],
|
||||
'currency' => $currency,
|
||||
'spent_in_budgets' => $this->spentInsideBudgets[$id] ?? [],
|
||||
'pc_spent_in_budgets' => $this->pcSpentInBudgets[$id] ?? [],
|
||||
'spent_outside_budgets' => $this->spentOutsideBudgets[$id] ?? [],
|
||||
'pc_spent_outside_budgets' => $this->pcSpentOutsideBudgets[$id] ?? [],
|
||||
];
|
||||
$item->meta = $meta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
|
||||
private function collectCurrencies(): void
|
||||
{
|
||||
$ids = array_unique(array_values($this->currencyIds));
|
||||
$set = TransactionCurrency::whereIn('id', $ids)->get();
|
||||
foreach ($set as $currency) {
|
||||
$this->currencies[(int)$currency->id] = $currency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
273
app/Support/JsonApi/Enrichments/PiggyBankEnrichment.php
Normal file
273
app/Support/JsonApi/Enrichments/PiggyBankEnrichment.php
Normal file
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PiggyBankEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
private Collection $collection;
|
||||
private array $ids;
|
||||
private array $currencyIds = [];
|
||||
private array $currencies = [];
|
||||
private array $accountIds = [];
|
||||
private array $accountCurrencies = [];
|
||||
private array $notes = [];
|
||||
private array $mappedObjects = [];
|
||||
private TransactionCurrency $primaryCurrency;
|
||||
private array $amounts = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->primaryCurrency = Amount::getPrimaryCurrency();
|
||||
}
|
||||
|
||||
public function enrich(Collection $collection): Collection
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->collectIds();
|
||||
$this->collectObjectGroups();
|
||||
$this->collectNotes();
|
||||
$this->collectCurrentAmounts();
|
||||
|
||||
|
||||
$this->appendCollectedData();
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection([$model]);
|
||||
$collection = $this->enrich($collection);
|
||||
|
||||
return $collection->first();
|
||||
}
|
||||
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->setUserGroup($user->userGroup);
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
|
||||
private function collectIds(): void
|
||||
{
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($this->collection as $piggy) {
|
||||
$id = (int)$piggy->id;
|
||||
$this->ids[] = $id;
|
||||
$this->currencyIds[$id] = (int)$piggy->transaction_currency_id;
|
||||
}
|
||||
$this->ids = array_unique($this->ids);
|
||||
|
||||
// collect currencies.
|
||||
$currencies = TransactionCurrency::whereIn('id', $this->currencyIds)->get();
|
||||
foreach ($currencies as $currency) {
|
||||
$this->currencies[(int)$currency->id] = $currency;
|
||||
}
|
||||
|
||||
// collect accounts
|
||||
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->ids)->get(['piggy_bank_id', 'account_id', 'current_amount', 'native_current_amount']);
|
||||
foreach ($set as $item) {
|
||||
$id = (int)$item->piggy_bank_id;
|
||||
$accountId = (int)$item->account_id;
|
||||
$this->amounts[$id] ??= [];
|
||||
if (!array_key_exists($id, $this->accountIds)) {
|
||||
$this->accountIds[$id] = (int)$item->account_id;
|
||||
}
|
||||
if (!array_key_exists($accountId, $this->amounts[$id])) {
|
||||
$this->amounts[$id][$accountId] = [
|
||||
'current_amount' => '0',
|
||||
'pc_current_amount' => null,
|
||||
];
|
||||
}
|
||||
$this->amounts[$id][$accountId]['current_amount'] = bcadd($this->amounts[$id][$accountId]['current_amount'], $item->current_amount);
|
||||
if (null !== $this->amounts[$id][$accountId]['pc_current_amount'] && null !== $item->native_current_amount) {
|
||||
$this->amounts[$id][$accountId]['pc_current_amount'] = bcadd($this->amounts[$id][$accountId]['pc_current_amount'], $item->native_current_amount);
|
||||
}
|
||||
}
|
||||
|
||||
// get account currency preference for ALL.
|
||||
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
||||
|
||||
/** @var AccountMeta $item */
|
||||
foreach ($set as $item) {
|
||||
$accountId = (int)$item->account_id;
|
||||
$currencyId = (int)$item->data;
|
||||
if (!array_key_exists($currencyId, $this->currencies)) {
|
||||
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
||||
}
|
||||
$this->accountCurrencies[$accountId] = $this->currencies[$currencyId];
|
||||
}
|
||||
|
||||
// get account info.
|
||||
$set = Account::whereIn('id', array_values($this->accountIds))->get();
|
||||
|
||||
/** @var Account $item */
|
||||
foreach ($set as $item) {
|
||||
$id = (int)$item->id;
|
||||
$this->accounts[$id] = [
|
||||
'id' => $id,
|
||||
'name' => $item->name,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (PiggyBank $item) {
|
||||
$id = (int)$item->id;
|
||||
$currencyId = (int)$item->transaction_currency_id;
|
||||
$currency = $this->currencies[$currencyId] ?? $this->primaryCurrency;
|
||||
$targetAmount = null;
|
||||
if (0 !== bccomp($item->target_amount, '0')) {
|
||||
$targetAmount = $item->target_amount;
|
||||
}
|
||||
$meta = [
|
||||
'notes' => $this->notes[$id] ?? null,
|
||||
'currency' => $this->currencies[$currencyId] ?? null,
|
||||
// 'auto_budget' => $this->autoBudgets[$id] ?? null,
|
||||
// 'spent' => $this->spent[$id] ?? null,
|
||||
// 'pc_spent' => $this->pcSpent[$id] ?? null,
|
||||
'object_group_id' => null,
|
||||
'object_group_order' => null,
|
||||
'object_group_title' => null,
|
||||
'current_amount' => null,
|
||||
'pc_current_amount' => null,
|
||||
'target_amount' => null === $targetAmount ? null : Steam::bcround($targetAmount, $currency->decimal_places),
|
||||
'pc_target_amount' => null === $item->native_target_amount ? null : Steam::bcround($item->native_target_amount, $this->primaryCurrency->decimal_places),
|
||||
'left_to_save' => null,
|
||||
'pc_left_to_save' => null,
|
||||
'save_per_month' => null,
|
||||
'pc_save_per_month' => null,
|
||||
'accounts' => [],
|
||||
];
|
||||
|
||||
// add object group if available
|
||||
if (array_key_exists($id, $this->mappedObjects)) {
|
||||
$key = $this->mappedObjects[$id];
|
||||
$meta['object_group_id'] = $this->objectGroups[$key]['id'];
|
||||
$meta['object_group_title'] = $this->objectGroups[$key]['title'];
|
||||
$meta['object_group_order'] = $this->objectGroups[$key]['order'];
|
||||
}
|
||||
// add current amount(s).
|
||||
foreach ($this->amounts[$id] as $accountId => $row) {
|
||||
$meta['accounts'][] = [
|
||||
'account_id' => (string)$accountId,
|
||||
'name' => $this->accounts[$accountId]['name'] ?? '',
|
||||
'current_amount' => Steam::bcround($row['current_amount'], $currency->decimal_places),
|
||||
'pc_current_amount' => Steam::bcround($row['pc_current_amount'], $this->primaryCurrency->decimal_places),
|
||||
];
|
||||
$meta['current_amount'] = bcadd($meta['current_amount'], $row['current_amount']);
|
||||
// only add pc_current_amount when the pc_current_amount is set
|
||||
$meta['pc_current_amount'] = null === $row['pc_current_amount'] ? null : bcadd($meta['pc_current_amount'], $row['pc_current_amount']);
|
||||
}
|
||||
$meta['current_amount'] = Steam::bcround($meta['current_amount'], $currency->decimal_places);
|
||||
// only round this number when pc_current_amount is set.
|
||||
$meta['pc_current_amount'] = null === $meta['pc_current_amount'] ? null : Steam::bcround($meta['pc_current_amount'], $this->primaryCurrency->decimal_places);
|
||||
|
||||
// calculate left to save, only when there is a target amount.
|
||||
if (null !== $targetAmount) {
|
||||
$meta['left_to_save'] = bcsub($meta['target_amount'], $meta['current_amount']);
|
||||
$meta['pc_left_to_save'] = null === $meta['pc_target_amount'] ? null : bcsub($meta['pc_target_amount'], $meta['pc_current_amount']);
|
||||
}
|
||||
|
||||
// get suggested per month.
|
||||
$meta['save_per_month'] = Steam::bcround($this->getSuggestedMonthlyAmount($item->start_date, $item->target_date, $meta['target_amount'], $meta['current_amount']), $currency->decimal_places);
|
||||
$meta['pc_save_per_month'] = Steam::bcround($this->getSuggestedMonthlyAmount($item->start_date, $item->target_date, $meta['pc_target_amount'], $meta['pc_current_amount']), $currency->decimal_places);
|
||||
|
||||
$item->meta = $meta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', PiggyBank::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d note(s)', count($this->notes)));
|
||||
}
|
||||
|
||||
private function collectObjectGroups(): void
|
||||
{
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', PiggyBank::class)
|
||||
->get(['object_groupable_id', 'object_group_id'])
|
||||
;
|
||||
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->mappedObjects[(int)$entry->object_groupable_id] = (int)$entry->object_group_id;
|
||||
}
|
||||
|
||||
$groups = ObjectGroup::whereIn('id', $ids)->get(['id', 'title', 'order'])->toArray();
|
||||
foreach ($groups as $group) {
|
||||
$group['id'] = (int)$group['id'];
|
||||
$group['order'] = (int)$group['order'];
|
||||
$this->objectGroups[(int)$group['id']] = $group;
|
||||
}
|
||||
}
|
||||
|
||||
private function collectCurrentAmounts(): void {}
|
||||
|
||||
/**
|
||||
* Returns the suggested amount the user should save per month, or "".
|
||||
*/
|
||||
private function getSuggestedMonthlyAmount(?Carbon $startDate, ?Carbon $targetDate, ?string $targetAmount, string $currentAmount): string
|
||||
{
|
||||
if (null === $targetAmount || null === $targetDate || null === $startDate) {
|
||||
return '0';
|
||||
}
|
||||
$savePerMonth = '0';
|
||||
if (1 === bccomp($targetAmount, $currentAmount)) {
|
||||
$now = today(config('app.timezone'));
|
||||
$diffInMonths = (int)$startDate->diffInMonths($targetDate);
|
||||
$remainingAmount = bcsub($targetAmount, $currentAmount);
|
||||
|
||||
// more than 1 month to go and still need money to save:
|
||||
if ($diffInMonths > 0 && 1 === bccomp($remainingAmount, '0')) {
|
||||
$savePerMonth = bcdiv($remainingAmount, (string)$diffInMonths);
|
||||
}
|
||||
|
||||
// less than 1 month to go but still need money to save:
|
||||
if (0 === $diffInMonths && 1 === bccomp($remainingAmount, '0')) {
|
||||
$savePerMonth = $remainingAmount;
|
||||
}
|
||||
}
|
||||
|
||||
return $savePerMonth;
|
||||
}
|
||||
}
|
||||
133
app/Support/JsonApi/Enrichments/PiggyBankEventEnrichment.php
Normal file
133
app/Support/JsonApi/Enrichments/PiggyBankEventEnrichment.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
private Collection $collection;
|
||||
private array $ids = [];
|
||||
private array $journalIds = [];
|
||||
private array $groupIds = [];
|
||||
private array $accountIds = [];
|
||||
private array $piggybankIds = [];
|
||||
private array $accountCurrencies = [];
|
||||
private array $currencies = [];
|
||||
// private bool $convertToPrimary = false;
|
||||
// private TransactionCurrency $primaryCurrency;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// $this->convertToPrimary = Amount::convertToPrimary();
|
||||
// $this->primaryCurrency = Amount::getPrimaryCurrency();
|
||||
}
|
||||
|
||||
public function enrich(Collection $collection): Collection
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->collectIds();
|
||||
$this->appendCollectedData();
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection([$model]);
|
||||
$collection = $this->enrich($collection);
|
||||
|
||||
return $collection->first();
|
||||
}
|
||||
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->setUserGroup($user->userGroup);
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
|
||||
private function collectIds(): void
|
||||
{
|
||||
/** @var PiggyBankEvent $event */
|
||||
foreach ($this->collection as $event) {
|
||||
$this->ids[] = (int)$event->id;
|
||||
$this->journalIds[(int)$event->id] = (int)$event->transaction_journal_id;
|
||||
$this->piggybankIds[(int)$event->id] = (int)$event->piggy_bank_id;
|
||||
}
|
||||
$this->ids = array_unique($this->ids);
|
||||
// collect groups with journal info.
|
||||
$set = TransactionJournal::whereIn('id', $this->journalIds)->get(['id', 'transaction_group_id']);
|
||||
|
||||
/** @var TransactionJournal $item */
|
||||
foreach ($set as $item) {
|
||||
$this->groupIds[(int)$item->id] = (int)$item->transaction_group_id;
|
||||
}
|
||||
|
||||
// collect account info.
|
||||
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->piggybankIds)->get(['piggy_bank_id', 'account_id']);
|
||||
foreach ($set as $item) {
|
||||
$id = (int)$item->piggy_bank_id;
|
||||
if (!array_key_exists($id, $this->accountIds)) {
|
||||
$this->accountIds[$id] = (int)$item->account_id;
|
||||
}
|
||||
}
|
||||
|
||||
// get account currency preference for ALL.
|
||||
// TODO This method does a find in a loop.
|
||||
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
||||
|
||||
/** @var AccountMeta $item */
|
||||
foreach ($set as $item) {
|
||||
$accountId = (int)$item->account_id;
|
||||
$currencyId = (int)$item->data;
|
||||
if (!array_key_exists($currencyId, $this->currencies)) {
|
||||
$this->currencies[$currencyId] = TransactionCurrency::find($currencyId);
|
||||
}
|
||||
$this->accountCurrencies[$accountId] = $this->currencies[$currencyId];
|
||||
}
|
||||
}
|
||||
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (PiggyBankEvent $item) {
|
||||
$id = (int)$item->id;
|
||||
$piggyId = (int)$item->piggy_bank_id;
|
||||
$journalId = (int)$item->transaction_journal_id;
|
||||
$currency = null;
|
||||
if (array_key_exists($piggyId, $this->accountIds)) {
|
||||
$accountId = $this->accountIds[$piggyId];
|
||||
if (array_key_exists($accountId, $this->accountCurrencies)) {
|
||||
$currency = $this->accountCurrencies[$accountId];
|
||||
}
|
||||
}
|
||||
$meta = [
|
||||
'transaction_group_id' => array_key_exists($journalId, $this->groupIds) ? (string)$this->groupIds[$journalId] : null,
|
||||
'currency' => $currency,
|
||||
];
|
||||
$item->meta = $meta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
586
app/Support/JsonApi/Enrichments/RecurringEnrichment.php
Normal file
586
app/Support/JsonApi/Enrichments/RecurringEnrichment.php
Normal file
@@ -0,0 +1,586 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\RecurrenceRepetitionWeekend;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Factory\CategoryFactory;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceRepetition;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\RecurrenceTransactionMeta;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class RecurringEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private Collection $collection;
|
||||
private array $ids = [];
|
||||
private array $transactionTypeIds = [];
|
||||
private array $transactionTypes = [];
|
||||
private array $notes = [];
|
||||
private array $repetitions = [];
|
||||
private array $transactions = [];
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
private string $language = 'en_US';
|
||||
private array $currencyIds = [];
|
||||
private array $foreignCurrencyIds = [];
|
||||
private array $sourceAccountIds = [];
|
||||
private array $destinationAccountIds = [];
|
||||
private array $accounts = [];
|
||||
private array $currencies = [];
|
||||
private array $recurrenceIds = [];
|
||||
private TransactionCurrency $primaryCurrency;
|
||||
private bool $convertToPrimary = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->primaryCurrency = Amount::getPrimaryCurrency();
|
||||
$this->convertToPrimary = Amount::convertToPrimary();
|
||||
}
|
||||
|
||||
public function enrich(Collection $collection): Collection
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->collectIds();
|
||||
$this->collectRepetitions();
|
||||
$this->collectTransactions();
|
||||
$this->collectCurrencies();
|
||||
$this->collectNotes();
|
||||
$this->collectAccounts();
|
||||
$this->collectTransactionMetaData();
|
||||
|
||||
$this->appendCollectedData();
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection([$model]);
|
||||
$collection = $this->enrich($collection);
|
||||
|
||||
return $collection->first();
|
||||
}
|
||||
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->setUserGroup($user->userGroup);
|
||||
$this->getLanguage();
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
|
||||
private function collectIds(): void
|
||||
{
|
||||
/** @var Recurrence $recurrence */
|
||||
foreach ($this->collection as $recurrence) {
|
||||
$id = (int)$recurrence->id;
|
||||
$typeId = (int)$recurrence->transaction_type_id;
|
||||
$this->ids[] = $id;
|
||||
$this->transactionTypeIds[$id] = $typeId;
|
||||
}
|
||||
$this->ids = array_unique($this->ids);
|
||||
|
||||
// collect transaction types.
|
||||
$transactionTypes = TransactionType::whereIn('id', array_unique($this->transactionTypeIds))->get();
|
||||
foreach ($transactionTypes as $transactionType) {
|
||||
$id = (int)$transactionType->id;
|
||||
$this->transactionTypes[$id] = TransactionTypeEnum::from($transactionType->type);
|
||||
}
|
||||
}
|
||||
|
||||
private function collectRepetitions(): void
|
||||
{
|
||||
Log::debug('Start of enrichment: collectRepetitions()');
|
||||
$repository = app(RecurringRepositoryInterface::class);
|
||||
$repository->setUserGroup($this->userGroup);
|
||||
$set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get();
|
||||
|
||||
/** @var RecurrenceRepetition $repetition */
|
||||
foreach ($set as $repetition) {
|
||||
$recurrence = $this->collection->filter(function (Recurrence $item) use ($repetition) {
|
||||
return (int)$item->id === (int)$repetition->recurrence_id;
|
||||
})->first();
|
||||
$fromDate = $recurrence->latest_date ?? $recurrence->first_date;
|
||||
$id = (int)$repetition->recurrence_id;
|
||||
$repId = (int)$repetition->id;
|
||||
$this->repetitions[$id] ??= [];
|
||||
|
||||
// get the (future) occurrences for this specific type of repetition:
|
||||
$amount = 'daily' === $repetition->repetition_type ? 9 : 5;
|
||||
$set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount);
|
||||
|
||||
/** @var Carbon $carbon */
|
||||
foreach ($set as $carbon) {
|
||||
$occurrences[] = $carbon->toAtomString();
|
||||
}
|
||||
|
||||
$this->repetitions[$id][$repId] = [
|
||||
'id' => (string)$repId,
|
||||
'created_at' => $repetition->created_at->toAtomString(),
|
||||
'updated_at' => $repetition->updated_at->toAtomString(),
|
||||
'type' => $repetition->repetition_type,
|
||||
'moment' => (string)$repetition->moment,
|
||||
'skip' => (int)$repetition->skip,
|
||||
'weekend' => RecurrenceRepetitionWeekend::from((int)$repetition->weekend),
|
||||
'description' => $this->getRepetitionDescription($repetition),
|
||||
'occurrences' => $occurrences,
|
||||
];
|
||||
}
|
||||
Log::debug('End of enrichment: collectRepetitions()');
|
||||
}
|
||||
|
||||
private function collectTransactions(): void
|
||||
{
|
||||
$set = RecurrenceTransaction::whereIn('recurrence_id', $this->ids)->get();
|
||||
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($set as $transaction) {
|
||||
$id = (int)$transaction->recurrence_id;
|
||||
$transactionId = (int)$transaction->id;
|
||||
$this->recurrenceIds[$transactionId] = $id;
|
||||
$this->transactions[$id] ??= [];
|
||||
$amount = $transaction->amount;
|
||||
$foreignAmount = $transaction->foreign_amount;
|
||||
|
||||
$this->transactions[$id][$transactionId] = [
|
||||
'id' => (string)$transactionId,
|
||||
'recurrence_id' => $id,
|
||||
'transaction_currency_id' => (int)$transaction->transaction_currency_id,
|
||||
'foreign_currency_id' => null === $transaction->foreign_currency_id ? null : (int)$transaction->foreign_currency_id,
|
||||
'source_id' => (int)$transaction->source_id,
|
||||
'object_has_currency_setting' => true,
|
||||
'destination_id' => (int)$transaction->destination_id,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => $foreignAmount,
|
||||
'pc_amount' => null,
|
||||
'pc_foreign_amount' => null,
|
||||
'description' => $transaction->description,
|
||||
'tags' => [],
|
||||
'category_id' => null,
|
||||
'category_name' => null,
|
||||
'budget_id' => null,
|
||||
'budget_name' => null,
|
||||
'piggy_bank_id' => null,
|
||||
'piggy_bank_name' => null,
|
||||
'subscription_id' => null,
|
||||
'subscription_name' => null,
|
||||
|
||||
];
|
||||
// collect all kinds of meta data to be collected later.
|
||||
$this->currencyIds[$transactionId] = (int)$transaction->transaction_currency_id;
|
||||
$this->sourceAccountIds[$transactionId] = (int)$transaction->source_id;
|
||||
$this->destinationAccountIds[$transactionId] = (int)$transaction->destination_id;
|
||||
if (null !== $transaction->foreign_currency_id) {
|
||||
$this->foreignCurrencyIds[$transactionId] = (int)$transaction->foreign_currency_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (Recurrence $item) {
|
||||
$id = (int)$item->id;
|
||||
$meta = [
|
||||
'notes' => $this->notes[$id] ?? null,
|
||||
'repetitions' => array_values($this->repetitions[$id] ?? []),
|
||||
'transactions' => $this->processTransactions(array_values($this->transactions[$id] ?? [])),
|
||||
];
|
||||
|
||||
$item->meta = $meta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the repetition in a string that is user readable.
|
||||
* TODO duplicate with repository.
|
||||
*/
|
||||
public function getRepetitionDescription(RecurrenceRepetition $repetition): string
|
||||
{
|
||||
if ('daily' === $repetition->repetition_type) {
|
||||
return (string)trans('firefly.recurring_daily', [], $this->language);
|
||||
}
|
||||
if ('weekly' === $repetition->repetition_type) {
|
||||
$dayOfWeek = trans(sprintf('config.dow_%s', $repetition->repetition_moment), [], $this->language);
|
||||
if ($repetition->repetition_skip > 0) {
|
||||
return (string)trans('firefly.recurring_weekly_skip', ['weekday' => $dayOfWeek, 'skip' => $repetition->repetition_skip + 1], $this->language);
|
||||
}
|
||||
|
||||
return (string)trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek], $this->language);
|
||||
}
|
||||
if ('monthly' === $repetition->repetition_type) {
|
||||
if ($repetition->repetition_skip > 0) {
|
||||
return (string)trans('firefly.recurring_monthly_skip', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip + 1], $this->language);
|
||||
}
|
||||
|
||||
return (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], $this->language);
|
||||
}
|
||||
if ('ndom' === $repetition->repetition_type) {
|
||||
$parts = explode(',', $repetition->repetition_moment);
|
||||
// first part is number of week, second is weekday.
|
||||
$dayOfWeek = trans(sprintf('config.dow_%s', $parts[1]), [], $this->language);
|
||||
if ($repetition->repetition_skip > 0) {
|
||||
return (string)trans('firefly.recurring_ndom_skip', ['skip' => $repetition->repetition_skip, 'weekday' => $dayOfWeek, 'dayOfMonth' => $parts[0]], $this->language);
|
||||
}
|
||||
|
||||
return (string)trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $parts[0]], $this->language);
|
||||
}
|
||||
if ('yearly' === $repetition->repetition_type) {
|
||||
$today = today(config('app.timezone'))->endOfYear();
|
||||
$repDate = Carbon::createFromFormat('Y-m-d', $repetition->repetition_moment);
|
||||
if (!$repDate instanceof Carbon) {
|
||||
$repDate = clone $today;
|
||||
}
|
||||
// $diffInYears = (int)$today->diffInYears($repDate, true);
|
||||
// $repDate->addYears($diffInYears); // technically not necessary.
|
||||
$string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js'));
|
||||
|
||||
return (string)trans('firefly.recurring_yearly', ['date' => $string], $this->language);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function getLanguage(): void
|
||||
{
|
||||
/** @var Preference $preference */
|
||||
$preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US'));
|
||||
$language = $preference->data;
|
||||
if (is_array($language)) {
|
||||
$language = 'en_US';
|
||||
}
|
||||
$language = (string)$language;
|
||||
$this->language = $language;
|
||||
}
|
||||
|
||||
private function collectCurrencies(): void
|
||||
{
|
||||
$all = array_merge(array_unique($this->currencyIds), array_unique($this->foreignCurrencyIds));
|
||||
$currencies = TransactionCurrency::whereIn('id', array_unique($all))->get();
|
||||
foreach ($currencies as $currency) {
|
||||
$id = (int)$currency->id;
|
||||
$this->currencies[$id] = $currency;
|
||||
}
|
||||
}
|
||||
|
||||
private function processTransactions(array $transactions): array
|
||||
{
|
||||
$return = [];
|
||||
$converter = new ExchangeRateConverter();
|
||||
foreach ($transactions as $transaction) {
|
||||
$currencyId = $transaction['transaction_currency_id'];
|
||||
$pcAmount = null;
|
||||
$pcForeignAmount = null;
|
||||
// set the same amount in the primary currency, if both are the same anyway.
|
||||
if (true === $this->convertToPrimary && $currencyId === (int)$this->primaryCurrency->id) {
|
||||
$pcAmount = $transaction['amount'];
|
||||
}
|
||||
// convert the amount to the primary currency, if it is not the same.
|
||||
if (true === $this->convertToPrimary && $currencyId !== (int)$this->primaryCurrency->id) {
|
||||
$pcAmount = $converter->convert($this->currencies[$currencyId], $this->primaryCurrency, today(), $transaction['amount']);
|
||||
}
|
||||
if (null !== $transaction['foreign_amount']) {
|
||||
$foreignCurrencyId = $transaction['foreign_currency_id'];
|
||||
if ($foreignCurrencyId !== $this->primaryCurrency->id) {
|
||||
$pcForeignAmount = $converter->convert($this->currencies[$foreignCurrencyId], $this->primaryCurrency, today(), $transaction['foreign_amount']);
|
||||
}
|
||||
}
|
||||
|
||||
$transaction['pc_amount'] = $pcAmount;
|
||||
$transaction['pc_foreign_amount'] = $pcForeignAmount;
|
||||
|
||||
$sourceId = $transaction['source_id'];
|
||||
$transaction['source_name'] = $this->accounts[$sourceId]->name;
|
||||
$transaction['source_iban'] = $this->accounts[$sourceId]->iban;
|
||||
$transaction['source_type'] = $this->accounts[$sourceId]->accountType->type;
|
||||
$transaction['source_id'] = (string)$transaction['source_id'];
|
||||
|
||||
$destId = $transaction['destination_id'];
|
||||
$transaction['destination_name'] = $this->accounts[$destId]->name;
|
||||
$transaction['destination_iban'] = $this->accounts[$destId]->iban;
|
||||
$transaction['destination_type'] = $this->accounts[$destId]->accountType->type;
|
||||
$transaction['destination_id'] = (string)$transaction['destination_id'];
|
||||
|
||||
$transaction['currency_id'] = (string)$currencyId;
|
||||
$transaction['currency_name'] = $this->currencies[$currencyId]->name;
|
||||
$transaction['currency_code'] = $this->currencies[$currencyId]->code;
|
||||
$transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol;
|
||||
$transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
||||
|
||||
$transaction['primary_currency_id'] = (string)$this->primaryCurrency->id;
|
||||
$transaction['primary_currency_name'] = $this->primaryCurrency->name;
|
||||
$transaction['primary_currency_code'] = $this->primaryCurrency->code;
|
||||
$transaction['primary_currency_symbol'] = $this->primaryCurrency->symbol;
|
||||
$transaction['primary_currency_decimal_places'] = $this->primaryCurrency->decimal_places;
|
||||
|
||||
// $transaction['foreign_currency_id'] = null;
|
||||
$transaction['foreign_currency_name'] = null;
|
||||
$transaction['foreign_currency_code'] = null;
|
||||
$transaction['foreign_currency_symbol'] = null;
|
||||
$transaction['foreign_currency_decimal_places'] = null;
|
||||
if (null !== $transaction['foreign_currency_id']) {
|
||||
$currencyId = $transaction['foreign_currency_id'];
|
||||
$transaction['foreign_currency_id'] = (string)$currencyId;
|
||||
$transaction['foreign_currency_name'] = $this->currencies[$currencyId]->name;
|
||||
$transaction['foreign_currency_code'] = $this->currencies[$currencyId]->code;
|
||||
$transaction['foreign_currency_symbol'] = $this->currencies[$currencyId]->symbol;
|
||||
$transaction['foreign_currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
||||
}
|
||||
unset($transaction['transaction_currency_id']);
|
||||
$return[] = $transaction;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function collectAccounts(): void
|
||||
{
|
||||
$all = array_merge(array_unique($this->sourceAccountIds), array_unique($this->destinationAccountIds));
|
||||
$accounts = Account::with(['accountType'])->whereIn('id', array_unique($all))->get();
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$id = (int)$account->id;
|
||||
$this->accounts[$id] = $account;
|
||||
}
|
||||
}
|
||||
|
||||
private function collectTransactionMetaData(): void
|
||||
{
|
||||
$ids = array_keys($this->transactions);
|
||||
$meta = RecurrenceTransactionMeta::whereIn('rt_id', $ids)->get();
|
||||
// other meta-data to be collected:
|
||||
$billIds = [];
|
||||
$piggyBankIds = [];
|
||||
$categoryIds = [];
|
||||
$categoryNames = [];
|
||||
$budgetIds = [];
|
||||
foreach ($meta as $entry) {
|
||||
$id = (int)$entry->id;
|
||||
$transactionId = (int)$entry->rt_id;
|
||||
$recurrenceId = $this->recurrenceIds[$transactionId];
|
||||
$name = (string)$entry->name;
|
||||
|
||||
switch ($name) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Recurrence transformer cant handle field "%s"', $name));
|
||||
|
||||
case 'bill_id':
|
||||
if ((int)$entry->value > 0) {
|
||||
$this->transactions[$recurrenceId][$transactionId]['subscription_id'] = $entry->value;
|
||||
if (!array_key_exists($id, $billIds)) {
|
||||
$billIds[$id] = [
|
||||
'recurrence_id' => $recurrenceId,
|
||||
'transaction_id' => $transactionId,
|
||||
'bill_id' => (int)$entry->value,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'tags':
|
||||
$this->transactions[$recurrenceId][$transactionId]['tags'] = json_decode((string)$entry->value);
|
||||
|
||||
break;
|
||||
|
||||
case 'piggy_bank_id':
|
||||
if ((int)$entry->value > 0) {
|
||||
$this->transactions[$recurrenceId][$transactionId]['piggy_bank_id'] = (string)$entry->value;
|
||||
if (!array_key_exists($id, $piggyBankIds)) {
|
||||
$piggyBankIds[$id] = [
|
||||
'recurrence_id' => $recurrenceId,
|
||||
'transaction_id' => $transactionId,
|
||||
'piggy_bank_id' => (int)$entry->value,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'category_id':
|
||||
if ((int)$entry->value > 0) {
|
||||
$this->transactions[$recurrenceId][$transactionId]['category_id'] = (string)$entry->value;
|
||||
if (!array_key_exists($id, $categoryIds)) {
|
||||
$categoryIds[$id] = [
|
||||
'recurrence_id' => $recurrenceId,
|
||||
'transaction_id' => $transactionId,
|
||||
'category_id' => (int)$entry->value,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'category_name':
|
||||
if ('' !== (string)$entry->value) {
|
||||
$this->transactions[$recurrenceId][$transactionId]['category_name'] = (string)$entry->value;
|
||||
if (!array_key_exists($id, $categoryIds)) {
|
||||
$categoryNames[$id] = [
|
||||
'recurrence_id' => $recurrenceId,
|
||||
'transaction_id' => $transactionId,
|
||||
'category_name' => $entry->value,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'budget_id':
|
||||
if ((int)$entry->value > 0) {
|
||||
$this->transactions[$recurrenceId][$transactionId]['budget_id'] = (string)$entry->value;
|
||||
if (!array_key_exists($id, $budgetIds)) {
|
||||
$budgetIds[$id] = [
|
||||
'recurrence_id' => $recurrenceId,
|
||||
'transaction_id' => $transactionId,
|
||||
'budget_id' => (int)$entry->value,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->collectBillInfo($billIds);
|
||||
$this->collectPiggyBankInfo($piggyBankIds);
|
||||
$this->collectCategoryIdInfo($categoryIds);
|
||||
$this->collectCategoryNameInfo($categoryNames);
|
||||
$this->collectBudgetInfo($budgetIds);
|
||||
}
|
||||
|
||||
private function collectBillInfo(array $billIds): void
|
||||
{
|
||||
if (0 === count($billIds)) {
|
||||
return;
|
||||
}
|
||||
$ids = Arr::pluck($billIds, 'bill_id');
|
||||
$bills = Bill::whereIn('id', $ids)->get();
|
||||
$mapped = [];
|
||||
foreach ($bills as $bill) {
|
||||
$mapped[(int)$bill->id] = $bill;
|
||||
}
|
||||
foreach ($billIds as $info) {
|
||||
$recurrenceId = $info['recurrence_id'];
|
||||
$transactionId = $info['transaction_id'];
|
||||
$this->transactions[$recurrenceId][$transactionId]['subscription_name'] = $mapped[$info['bill_id']]->name ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
private function collectPiggyBankInfo(array $piggyBankIds): void
|
||||
{
|
||||
if (0 === count($piggyBankIds)) {
|
||||
return;
|
||||
}
|
||||
$ids = Arr::pluck($piggyBankIds, 'piggy_bank_id');
|
||||
$piggyBanks = PiggyBank::whereIn('id', $ids)->get();
|
||||
$mapped = [];
|
||||
foreach ($piggyBanks as $piggyBank) {
|
||||
$mapped[(int)$piggyBank->id] = $piggyBank;
|
||||
}
|
||||
foreach ($piggyBankIds as $info) {
|
||||
$recurrenceId = $info['recurrence_id'];
|
||||
$transactionId = $info['transaction_id'];
|
||||
$this->transactions[$recurrenceId][$transactionId]['piggy_bank_name'] = $mapped[$info['piggy_bank_id']]->name ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
private function collectCategoryIdInfo(array $categoryIds): void
|
||||
{
|
||||
if (0 === count($categoryIds)) {
|
||||
return;
|
||||
}
|
||||
$ids = Arr::pluck($categoryIds, 'category_id');
|
||||
$categories = Category::whereIn('id', $ids)->get();
|
||||
$mapped = [];
|
||||
foreach ($categories as $category) {
|
||||
$mapped[(int)$category->id] = $category;
|
||||
}
|
||||
foreach ($categoryIds as $info) {
|
||||
$recurrenceId = $info['recurrence_id'];
|
||||
$transactionId = $info['transaction_id'];
|
||||
$this->transactions[$recurrenceId][$transactionId]['category_name'] = $mapped[$info['category_id']]->name ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO This method does look-up in a loop.
|
||||
*/
|
||||
private function collectCategoryNameInfo(array $categoryNames): void
|
||||
{
|
||||
if (0 === count($categoryNames)) {
|
||||
return;
|
||||
}
|
||||
$factory = app(CategoryFactory::class);
|
||||
$factory->setUser($this->user);
|
||||
foreach ($categoryNames as $info) {
|
||||
$recurrenceId = $info['recurrence_id'];
|
||||
$transactionId = $info['transaction_id'];
|
||||
$category = $factory->findOrCreate(null, $info['category_name']);
|
||||
if (null !== $category) {
|
||||
$this->transactions[$recurrenceId][$transactionId]['category_id'] = (string)$category->id;
|
||||
$this->transactions[$recurrenceId][$transactionId]['category_name'] = $category->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function collectBudgetInfo(array $budgetIds): void
|
||||
{
|
||||
if (0 === count($budgetIds)) {
|
||||
return;
|
||||
}
|
||||
$ids = Arr::pluck($budgetIds, 'budget_id');
|
||||
$categories = Budget::whereIn('id', $ids)->get();
|
||||
$mapped = [];
|
||||
foreach ($categories as $category) {
|
||||
$mapped[(int)$category->id] = $category;
|
||||
}
|
||||
foreach ($budgetIds as $info) {
|
||||
$recurrenceId = $info['recurrence_id'];
|
||||
$transactionId = $info['transaction_id'];
|
||||
$this->transactions[$recurrenceId][$transactionId]['budget_name'] = $mapped[$info['budget_id']]->name ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Recurrence::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d note(s)', count($this->notes)));
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,8 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
$this->collectPaidDates();
|
||||
$this->collectPayDates();
|
||||
|
||||
// TODO clean me up.
|
||||
|
||||
$notes = $this->notes;
|
||||
$objectGroups = $this->objectGroups;
|
||||
$paidDates = $this->paidDates;
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Support\Repositories\Recurring;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class CalculateXOccurrencesSince
|
||||
@@ -37,7 +38,7 @@ trait CalculateXOccurrencesSince
|
||||
*/
|
||||
protected function getXDailyOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$return = [];
|
||||
$mutator = clone $date;
|
||||
$total = 0;
|
||||
@@ -62,7 +63,7 @@ trait CalculateXOccurrencesSince
|
||||
*/
|
||||
protected function getXMonthlyOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s(%s, %s, %d)', __METHOD__, $date->format('Y-m-d'), $afterDate->format('Y-m-d'), $count));
|
||||
Log::debug(sprintf('Now in %s(%s, %s, %d)', __METHOD__, $date->format('Y-m-d'), $afterDate->format('Y-m-d'), $count));
|
||||
$return = [];
|
||||
$mutator = clone $date;
|
||||
$total = 0;
|
||||
@@ -70,24 +71,25 @@ trait CalculateXOccurrencesSince
|
||||
$dayOfMonth = (int) $moment;
|
||||
$dayOfMonth = 0 === $dayOfMonth ? 1 : $dayOfMonth;
|
||||
if ($mutator->day > $dayOfMonth) {
|
||||
app('log')->debug(sprintf('%d is after %d, add a month. Mutator is now', $mutator->day, $dayOfMonth));
|
||||
Log::debug(sprintf('%d is after %d, add a month. Mutator is now...', $mutator->day, $dayOfMonth));
|
||||
// day has passed already, add a month.
|
||||
$mutator->addMonth();
|
||||
app('log')->debug(sprintf('%s', $mutator->format('Y-m-d')));
|
||||
Log::debug(sprintf('%s', $mutator->toAtomString()));
|
||||
}
|
||||
|
||||
while ($total < $count) {
|
||||
$domCorrected = min($dayOfMonth, $mutator->daysInMonth);
|
||||
$mutator->day = $domCorrected;
|
||||
app('log')->debug(sprintf('Mutator is now %s', $mutator->format('Y-m-d')));
|
||||
$mutator->setTime(0, 0, 0);
|
||||
if (0 === $attempts % $skipMod && $mutator->gte($afterDate)) {
|
||||
app('log')->debug('Is added to the list.');
|
||||
Log::debug(sprintf('Mutator is now %s and is added to the list.', $mutator->toAtomString()));
|
||||
$return[] = clone $mutator;
|
||||
++$total;
|
||||
}
|
||||
++$attempts;
|
||||
$mutator = $mutator->endOfMonth()->addDay();
|
||||
}
|
||||
Log::debug('Collected enough occurrences.');
|
||||
|
||||
return $return;
|
||||
}
|
||||
@@ -100,7 +102,7 @@ trait CalculateXOccurrencesSince
|
||||
*/
|
||||
protected function getXNDomOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
@@ -134,7 +136,7 @@ trait CalculateXOccurrencesSince
|
||||
*/
|
||||
protected function getXWeeklyOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$return = [];
|
||||
$total = 0;
|
||||
$attempts = 0;
|
||||
@@ -173,7 +175,7 @@ trait CalculateXOccurrencesSince
|
||||
*/
|
||||
protected function getXYearlyOccurrencesSince(Carbon $date, Carbon $afterDate, int $count, int $skipMod, string $moment): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s(%s, %d, %d, %s)', __METHOD__, $date->format('Y-m-d'), $date->format('Y-m-d'), $count, $skipMod));
|
||||
Log::debug(sprintf('Now in %s(%s, %d, %d, %s)', __METHOD__, $date->format('Y-m-d'), $date->format('Y-m-d'), $count, $skipMod));
|
||||
$return = [];
|
||||
$mutator = clone $date;
|
||||
$total = 0;
|
||||
@@ -181,19 +183,19 @@ trait CalculateXOccurrencesSince
|
||||
$date = new Carbon($moment);
|
||||
$date->year = $mutator->year;
|
||||
if ($mutator > $date) {
|
||||
app('log')->debug(
|
||||
Log::debug(
|
||||
sprintf('mutator (%s) > date (%s), so add a year to date (%s)', $mutator->format('Y-m-d'), $date->format('Y-m-d'), $date->format('Y-m-d'))
|
||||
);
|
||||
$date->addYear();
|
||||
app('log')->debug(sprintf('Date is now %s', $date->format('Y-m-d')));
|
||||
Log::debug(sprintf('Date is now %s', $date->format('Y-m-d')));
|
||||
}
|
||||
$obj = clone $date;
|
||||
while ($total < $count) {
|
||||
app('log')->debug(sprintf('total (%d) < count (%d) so go.', $total, $count));
|
||||
app('log')->debug(sprintf('attempts (%d) %% skipmod (%d) === %d', $attempts, $skipMod, $attempts % $skipMod));
|
||||
app('log')->debug(sprintf('Obj (%s) gte afterdate (%s)? %s', $obj->format('Y-m-d'), $afterDate->format('Y-m-d'), var_export($obj->gte($afterDate), true)));
|
||||
Log::debug(sprintf('total (%d) < count (%d) so go.', $total, $count));
|
||||
Log::debug(sprintf('attempts (%d) %% skipmod (%d) === %d', $attempts, $skipMod, $attempts % $skipMod));
|
||||
Log::debug(sprintf('Obj (%s) gte afterdate (%s)? %s', $obj->format('Y-m-d'), $afterDate->format('Y-m-d'), var_export($obj->gte($afterDate), true)));
|
||||
if (0 === $attempts % $skipMod && $obj->gte($afterDate)) {
|
||||
app('log')->debug('All conditions true, add obj.');
|
||||
Log::debug('All conditions true, add obj.');
|
||||
$return[] = clone $obj;
|
||||
++$total;
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Support;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
@@ -34,11 +36,10 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
use Exception;
|
||||
use ValueError;
|
||||
|
||||
use function Safe\preg_replace;
|
||||
use function Safe\parse_url;
|
||||
use function Safe\preg_replace;
|
||||
|
||||
/**
|
||||
* Class Steam.
|
||||
@@ -277,7 +278,7 @@ class Steam
|
||||
$carbon = new Carbon($entry->date, $entry->date_tz);
|
||||
$carbonKey = $carbon->format('Y-m-d');
|
||||
// make sure sum is a string:
|
||||
$sumOfDay = (string) ($entry->sum_of_day ?? '0');
|
||||
$sumOfDay = (string)($entry->sum_of_day ?? '0');
|
||||
// #10426 make sure sum is not in scientific notation.
|
||||
$sumOfDay = $this->floatalize($sumOfDay);
|
||||
|
||||
@@ -292,20 +293,20 @@ class Steam
|
||||
|
||||
// add amount to current balance in currency code.
|
||||
$currentBalance[$entryCurrency->code] ??= '0';
|
||||
$currentBalance[$entryCurrency->code] = bcadd($sumOfDay, (string) $currentBalance[$entryCurrency->code]);
|
||||
$currentBalance[$entryCurrency->code] = bcadd($sumOfDay, (string)$currentBalance[$entryCurrency->code]);
|
||||
|
||||
// if not requested to convert to primary currency, add the amount to "balance", do nothing else.
|
||||
if (!$convertToPrimary) {
|
||||
$currentBalance['balance'] = bcadd((string) $currentBalance['balance'], $sumOfDay);
|
||||
$currentBalance['balance'] = bcadd((string)$currentBalance['balance'], $sumOfDay);
|
||||
}
|
||||
// if convert to primary currency add the converted amount to "pc_balance".
|
||||
// if there is a request to convert, convert to "pc_balance" and use "balance" for whichever amount is in the primary currency.
|
||||
if ($convertToPrimary) {
|
||||
$pcSumOfDay = $converter->convert($entryCurrency, $primaryCurrency, $carbon, $sumOfDay);
|
||||
$currentBalance['pc_balance'] = bcadd((string) ($currentBalance['pc_balance'] ?? '0'), $pcSumOfDay);
|
||||
$currentBalance['pc_balance'] = bcadd((string)($currentBalance['pc_balance'] ?? '0'), $pcSumOfDay);
|
||||
// if it's the same currency as the entry, also add to balance (see other code).
|
||||
if ($currency->id === $entryCurrency->id) {
|
||||
$currentBalance['balance'] = bcadd((string) $currentBalance['balance'], $sumOfDay);
|
||||
$currentBalance['balance'] = bcadd((string)$currentBalance['balance'], $sumOfDay);
|
||||
}
|
||||
}
|
||||
// add to final array.
|
||||
@@ -318,6 +319,72 @@ class Steam
|
||||
return $balances;
|
||||
}
|
||||
|
||||
public function accountsBalancesOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
||||
{
|
||||
$result = [];
|
||||
$convertToPrimary ??= Amount::convertToPrimary();
|
||||
$primary ??= Amount::getPrimaryCurrency();
|
||||
$currencies = $this->getCurrencies($accounts);
|
||||
|
||||
// balance(s) in all currencies for ALL accounts.
|
||||
$array = Transaction::whereIn('account_id', $accounts->pluck('id')->toArray())
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
|
||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
|
||||
->get(['transactions.account_id', 'transaction_currencies.code', 'transactions.amount'])->toArray()
|
||||
;
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
// filter array back to this account:
|
||||
$filtered = array_filter($array, function ($item) use ($account) {
|
||||
return (int)$item['account_id'] === $account->id;
|
||||
});
|
||||
$currency = $currencies[$account->id];
|
||||
// this array is PER account, so we wait a bit before we change code here.
|
||||
$return = [
|
||||
'pc_balance' => '0',
|
||||
'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
|
||||
];
|
||||
|
||||
// balance(s) in all currencies.
|
||||
$others = $this->groupAndSumTransactions($filtered, 'code', 'amount');
|
||||
// Log::debug('All balances are (joined)', $others);
|
||||
// if there is no request to convert, take this as "balance" and "pc_balance".
|
||||
$return['balance'] = $others[$currency->code] ?? '0';
|
||||
if (!$convertToPrimary) {
|
||||
unset($return['pc_balance']);
|
||||
// Log::debug(sprintf('Set balance to %s, unset pc_balance', $return['balance']));
|
||||
}
|
||||
// if there is a request to convert, convert to "pc_balance" and use "balance" for whichever amount is in the primary currency.
|
||||
if ($convertToPrimary) {
|
||||
$return['pc_balance'] = $this->convertAllBalances($others, $primary, $date); // todo sum all and convert.
|
||||
// Log::debug(sprintf('Set pc_balance to %s', $return['pc_balance']));
|
||||
}
|
||||
|
||||
// either way, the balance is always combined with the virtual balance:
|
||||
$virtualBalance = (string)('' === (string)$account->virtual_balance ? '0' : $account->virtual_balance);
|
||||
|
||||
if ($convertToPrimary) {
|
||||
// the primary currency balance is combined with a converted virtual_balance:
|
||||
$converter = new ExchangeRateConverter();
|
||||
$pcVirtualBalance = $converter->convert($currency, $primary, $date, $virtualBalance);
|
||||
$return['pc_balance'] = bcadd($pcVirtualBalance, $return['pc_balance']);
|
||||
// Log::debug(sprintf('Primary virtual balance makes the primary total %s', $return['pc_balance']));
|
||||
}
|
||||
if (!$convertToPrimary) {
|
||||
// if not, also increase the balance + primary balance for consistency.
|
||||
$return['balance'] = bcadd($return['balance'], $virtualBalance);
|
||||
// Log::debug(sprintf('Virtual balance makes the (primary currency) total %s', $return['balance']));
|
||||
}
|
||||
$final = array_merge($return, $others);
|
||||
$result[$account->id] = $final;
|
||||
// Log::debug('Final balance is', $final);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns smaller than or equal to, so be careful with END OF DAY.
|
||||
*
|
||||
@@ -340,7 +407,7 @@ class Steam
|
||||
if ($cache->has()) {
|
||||
Log::debug(sprintf('CACHED finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||
|
||||
return $cache->get();
|
||||
// return $cache->get();
|
||||
}
|
||||
// Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||
if (null === $convertToPrimary) {
|
||||
@@ -361,8 +428,8 @@ class Steam
|
||||
$hasCurrency = null !== $accountCurrency;
|
||||
$currency = $hasCurrency ? $accountCurrency : $primary;
|
||||
$return = [
|
||||
'pc_balance' => '0',
|
||||
'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
|
||||
'pc_balance' => '0',
|
||||
'balance' => '0', // this key is overwritten right away, but I must remember it is always created.
|
||||
];
|
||||
// balance(s) in all currencies.
|
||||
$array = $account->transactions()
|
||||
@@ -386,7 +453,7 @@ class Steam
|
||||
}
|
||||
|
||||
// either way, the balance is always combined with the virtual balance:
|
||||
$virtualBalance = (string) ('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance);
|
||||
$virtualBalance = (string)('' === (string)$account->virtual_balance ? '0' : $account->virtual_balance);
|
||||
|
||||
if ($convertToPrimary) {
|
||||
// the primary currency balance is combined with a converted virtual_balance:
|
||||
@@ -421,7 +488,7 @@ class Steam
|
||||
return null;
|
||||
}
|
||||
|
||||
return TransactionCurrency::find((int) $result->data);
|
||||
return TransactionCurrency::find((int)$result->data);
|
||||
}
|
||||
|
||||
private function groupAndSumTransactions(array $array, string $group, string $field): array
|
||||
@@ -430,7 +497,7 @@ class Steam
|
||||
|
||||
foreach ($array as $item) {
|
||||
$groupKey = $item[$group] ?? 'unknown';
|
||||
$return[$groupKey] = bcadd($return[$groupKey] ?? '0', (string) $item[$field]);
|
||||
$return[$groupKey] = bcadd($return[$groupKey] ?? '0', (string)$item[$field]);
|
||||
}
|
||||
|
||||
return $return;
|
||||
@@ -478,11 +545,11 @@ class Steam
|
||||
$hostName = $ipAddress;
|
||||
}
|
||||
|
||||
if ('' !== (string) $hostName && $hostName !== $ipAddress) {
|
||||
if ('' !== (string)$hostName && $hostName !== $ipAddress) {
|
||||
$host = $hostName;
|
||||
}
|
||||
|
||||
return (string) $host;
|
||||
return (string)$host;
|
||||
}
|
||||
|
||||
public function getLastActivities(array $accounts): array
|
||||
@@ -497,9 +564,9 @@ class Steam
|
||||
|
||||
/** @var Transaction $entry */
|
||||
foreach ($set as $entry) {
|
||||
$date = new Carbon($entry->max_date, config('app.timezone'));
|
||||
$date = new Carbon($entry->max_date, config('app.timezone'));
|
||||
$date->setTimezone(config('app.timezone'));
|
||||
$list[(int) $entry->account_id] = $date;
|
||||
$list[(int)$entry->account_id] = $date;
|
||||
}
|
||||
|
||||
return $list;
|
||||
@@ -517,7 +584,7 @@ class Steam
|
||||
if ('equal' === $locale) {
|
||||
$locale = $this->getLanguage();
|
||||
}
|
||||
$locale = (string) $locale;
|
||||
$locale = (string)$locale;
|
||||
|
||||
// Check for Windows to replace the locale correctly.
|
||||
if ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) {
|
||||
@@ -617,20 +684,20 @@ class Steam
|
||||
}
|
||||
Log::debug(sprintf('Floatalizing %s', $value));
|
||||
|
||||
$number = substr($value, 0, (int) strpos($value, 'E'));
|
||||
$number = substr($value, 0, (int)strpos($value, 'E'));
|
||||
if (str_contains($number, '.')) {
|
||||
$post = strlen(substr($number, (int) strpos($number, '.') + 1));
|
||||
$mantis = substr($value, (int) strpos($value, 'E') + 1);
|
||||
$post = strlen(substr($number, (int)strpos($number, '.') + 1));
|
||||
$mantis = substr($value, (int)strpos($value, 'E') + 1);
|
||||
if ($mantis < 0) {
|
||||
$post += abs((int) $mantis);
|
||||
$post += abs((int)$mantis);
|
||||
}
|
||||
|
||||
// TODO careless float could break financial math.
|
||||
return number_format((float) $value, $post, '.', '');
|
||||
return number_format((float)$value, $post, '.', '');
|
||||
}
|
||||
|
||||
// TODO careless float could break financial math.
|
||||
return number_format((float) $value, 0, '.', '');
|
||||
return number_format((float)$value, 0, '.', '');
|
||||
}
|
||||
|
||||
public function opposite(?string $amount = null): ?string
|
||||
@@ -650,24 +717,24 @@ class Steam
|
||||
// has a K in it, remove the K and multiply by 1024.
|
||||
$bytes = bcmul(rtrim($string, 'k'), '1024');
|
||||
|
||||
return (int) $bytes;
|
||||
return (int)$bytes;
|
||||
}
|
||||
|
||||
if (false !== stripos($string, 'm')) {
|
||||
// has a M in it, remove the M and multiply by 1048576.
|
||||
$bytes = bcmul(rtrim($string, 'm'), '1048576');
|
||||
|
||||
return (int) $bytes;
|
||||
return (int)$bytes;
|
||||
}
|
||||
|
||||
if (false !== stripos($string, 'g')) {
|
||||
// has a G in it, remove the G and multiply by (1024)^3.
|
||||
$bytes = bcmul(rtrim($string, 'g'), '1073741824');
|
||||
|
||||
return (int) $bytes;
|
||||
return (int)$bytes;
|
||||
}
|
||||
|
||||
return (int) $string;
|
||||
return (int)$string;
|
||||
}
|
||||
|
||||
public function positive(string $amount): string
|
||||
@@ -689,4 +756,48 @@ class Steam
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
private function getCurrencies(Collection $accounts): array
|
||||
{
|
||||
$currencies = [];
|
||||
$accountCurrencies = [];
|
||||
$accountPreferences = [];
|
||||
$primary = Amount::getPrimaryCurrency();
|
||||
$currencies[$primary->id] = $primary;
|
||||
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
$result = AccountMeta::whereIn('account_id', $ids)->where('name', 'currency_id')->get();
|
||||
|
||||
/** @var AccountMeta $item */
|
||||
foreach ($result as $item) {
|
||||
$integer = (int)$item->data;
|
||||
if (0 !== $integer) {
|
||||
$accountPreferences[(int)$item->account_id] = $integer;
|
||||
}
|
||||
}
|
||||
// collect those currencies, skip primary because we already have it.
|
||||
$set = TransactionCurrency::whereIn('id', $accountPreferences)->where('id', '!=', $primary->id)->get();
|
||||
foreach ($set as $item) {
|
||||
$currencies[$item->id] = $item;
|
||||
}
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$accountId = $account->id;
|
||||
$currencyPresent = isset($account->meta) && array_key_exists('currency', $account->meta) && null !== $account->meta['currency'];
|
||||
if ($currencyPresent) {
|
||||
$currencyId = $account->meta['currency']->id;
|
||||
$currencies[$currencyId] ??= $account->meta['currency'];
|
||||
$accountCurrencies[$accountId] = $account->meta['currency'];
|
||||
}
|
||||
if (!$currencyPresent && !array_key_exists($accountId, $accountPreferences)) {
|
||||
$accountCurrencies[$accountId] = $primary;
|
||||
}
|
||||
if (!$currencyPresent && array_key_exists($accountId, $accountPreferences)) {
|
||||
$accountCurrencies[$accountId] = $currencies[$accountPreferences[$account->id]];
|
||||
}
|
||||
}
|
||||
|
||||
return $accountCurrencies;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,8 @@ class AccountTransformer extends AbstractTransformer
|
||||
'type' => strtolower($accountType),
|
||||
'account_role' => $accountRole,
|
||||
|
||||
// TODO object group
|
||||
|
||||
// currency information, structured for 6.3.0.
|
||||
'object_has_currency_setting' => $hasCurrencySettings,
|
||||
|
||||
@@ -141,7 +143,7 @@ class AccountTransformer extends AbstractTransformer
|
||||
'notes' => $account->meta['notes'] ?? null,
|
||||
'monthly_payment_date' => $monthlyPaymentDate,
|
||||
'credit_card_type' => $creditCardType,
|
||||
'account_number' => $account->meta['account_number'] ?? null,
|
||||
'account_number' => $account->meta['account_number'],
|
||||
'iban' => '' === $account->iban ? null : $account->iban,
|
||||
'bic' => $account->meta['BIC'] ?? null,
|
||||
'opening_balance_date' => $openingBalanceDate,
|
||||
@@ -153,7 +155,7 @@ class AccountTransformer extends AbstractTransformer
|
||||
'longitude' => $longitude,
|
||||
'latitude' => $latitude,
|
||||
'zoom_level' => $zoomLevel,
|
||||
'last_activity' => array_key_exists('last_activity', $account->meta) ? $account->meta['last_activity']->toAtomString() : null,
|
||||
'last_activity' => $account->meta['last_activity']?->toAtomString(),
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'self',
|
||||
|
||||
@@ -51,7 +51,7 @@ class AvailableBudgetTransformer extends AbstractTransformer
|
||||
*/
|
||||
public function transform(AvailableBudget $availableBudget): array
|
||||
{
|
||||
$currency = $availableBudget->transactionCurrency;
|
||||
$currency = $availableBudget->meta['currency'];
|
||||
$amount = Steam::bcround($availableBudget->amount, $currency->decimal_places);
|
||||
$pcAmount = null;
|
||||
|
||||
|
||||
@@ -87,6 +87,8 @@ class BudgetTransformer extends AbstractTransformer
|
||||
'auto_budget_type' => $abType,
|
||||
'auto_budget_period' => $abPeriod,
|
||||
|
||||
// TODO object group
|
||||
|
||||
// new currency settings.
|
||||
'object_has_currency_setting' => null !== $budget->meta['currency'],
|
||||
'currency_id' => null === $currency ? null : (string)$currency->id,
|
||||
|
||||
@@ -59,9 +59,8 @@ class CategoryTransformer extends AbstractTransformer
|
||||
|
||||
// category never has currency settings.
|
||||
'object_has_currency_setting' => false,
|
||||
|
||||
|
||||
'primary_currency_id' => (string)$this->primaryCurrency->id,
|
||||
'primary_currency_name' => $this->primaryCurrency->name,
|
||||
'primary_currency_code' => $this->primaryCurrency->code,
|
||||
'primary_currency_symbol' => $this->primaryCurrency->symbol,
|
||||
'primary_currency_decimal_places' => (int)$this->primaryCurrency->decimal_places,
|
||||
|
||||
@@ -26,8 +26,7 @@ namespace FireflyIII\Transformers;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
|
||||
@@ -36,16 +35,16 @@ use FireflyIII\Support\Facades\Steam;
|
||||
*/
|
||||
class PiggyBankEventTransformer extends AbstractTransformer
|
||||
{
|
||||
private readonly PiggyBankRepositoryInterface $piggyRepos;
|
||||
private readonly AccountRepositoryInterface $repository;
|
||||
private TransactionCurrency $primaryCurrency;
|
||||
private bool $convertToPrimary = false;
|
||||
|
||||
/**
|
||||
* PiggyBankEventTransformer constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->piggyRepos = app(PiggyBankRepositoryInterface::class);
|
||||
$this->primaryCurrency = Amount::getPrimaryCurrency();
|
||||
$this->convertToPrimary = Amount::convertToPrimary();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,39 +54,43 @@ class PiggyBankEventTransformer extends AbstractTransformer
|
||||
*/
|
||||
public function transform(PiggyBankEvent $event): array
|
||||
{
|
||||
// get account linked to piggy bank
|
||||
$account = $event->piggyBank->accounts()->first();
|
||||
|
||||
// set up repositories.
|
||||
$this->repository->setUser($account->user);
|
||||
$this->piggyRepos->setUser($account->user);
|
||||
|
||||
// get associated currency or fall back to the default:
|
||||
$currency = $this->repository->getAccountCurrency($account) ?? Amount::getPrimaryCurrencyByUserGroup($account->user->userGroup);
|
||||
|
||||
// get associated journal and transaction, if any:
|
||||
$journalId = $event->transaction_journal_id;
|
||||
$groupId = null;
|
||||
if (0 !== (int) $journalId) {
|
||||
$groupId = (int) $event->transactionJournal->transaction_group_id;
|
||||
$journalId = (int) $journalId;
|
||||
$currency = $event->meta['currency'] ?? $this->primaryCurrency;
|
||||
$amount = Steam::bcround($event->amount, $currency->decimal_places);
|
||||
$primaryAmount = null;
|
||||
if ($this->convertToPrimary && $currency->id === $this->primaryCurrency->id) {
|
||||
$primaryAmount = $amount;
|
||||
}
|
||||
if ($this->convertToPrimary && $currency->id !== $this->primaryCurrency->id) {
|
||||
$primaryAmount = Steam::bcround($event->native_amount, $this->primaryCurrency->decimal_places);
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => (string) $event->id,
|
||||
'created_at' => $event->created_at?->toAtomString(),
|
||||
'updated_at' => $event->updated_at?->toAtomString(),
|
||||
'amount' => Steam::bcround($event->amount, $currency->decimal_places),
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'transaction_journal_id' => null !== $journalId ? (string) $journalId : null,
|
||||
'transaction_group_id' => null !== $groupId ? (string) $groupId : null,
|
||||
'links' => [
|
||||
'id' => (string)$event->id,
|
||||
'created_at' => $event->created_at?->toAtomString(),
|
||||
'updated_at' => $event->updated_at?->toAtomString(),
|
||||
'amount' => $amount,
|
||||
'pc_amount' => $primaryAmount,
|
||||
|
||||
// currencies according to 6.3.0
|
||||
'has_currency_setting' => true,
|
||||
'currency_id' => (string)$currency->id,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
|
||||
'primary_currency_id' => (string)$this->primaryCurrency->id,
|
||||
'primary_currency_name' => $this->primaryCurrency->name,
|
||||
'primary_currency_code' => $this->primaryCurrency->code,
|
||||
'primary_currency_symbol' => $this->primaryCurrency->symbol,
|
||||
'primary_currency_decimal_places' => $this->primaryCurrency->decimal_places,
|
||||
|
||||
'transaction_journal_id' => null !== $event->transaction_journal_id ? (string)$event->transaction_journal_id : null,
|
||||
'transaction_group_id' => $event->meta['transaction_group_id'],
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'self',
|
||||
'uri' => '/piggy_bank_events/'.$event->id,
|
||||
'uri' => sprintf('/piggy-banks/%d/events/%s', $event->piggy_bank_id, $event->id),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -25,27 +25,23 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Transformers;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
|
||||
/**
|
||||
* Class PiggyBankTransformer
|
||||
*/
|
||||
class PiggyBankTransformer extends AbstractTransformer
|
||||
{
|
||||
private readonly AccountRepositoryInterface $accountRepos;
|
||||
private readonly PiggyBankRepositoryInterface $piggyRepos;
|
||||
private TransactionCurrency $primaryCurrency;
|
||||
|
||||
/**
|
||||
* PiggyBankTransformer constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->accountRepos = app(AccountRepositoryInterface::class);
|
||||
$this->piggyRepos = app(PiggyBankRepositoryInterface::class);
|
||||
$this->primaryCurrency = Amount::getPrimaryCurrency();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,74 +51,58 @@ class PiggyBankTransformer extends AbstractTransformer
|
||||
*/
|
||||
public function transform(PiggyBank $piggyBank): array
|
||||
{
|
||||
$user = $piggyBank->accounts()->first()->user;
|
||||
|
||||
// set up repositories
|
||||
$this->accountRepos->setUser($user);
|
||||
$this->piggyRepos->setUser($user);
|
||||
|
||||
// note
|
||||
$notes = $this->piggyRepos->getNoteText($piggyBank);
|
||||
$notes = '' === $notes ? null : $notes;
|
||||
|
||||
$objectGroupId = null;
|
||||
$objectGroupOrder = null;
|
||||
$objectGroupTitle = null;
|
||||
|
||||
/** @var null|ObjectGroup $objectGroup */
|
||||
$objectGroup = $piggyBank->objectGroups->first();
|
||||
if (null !== $objectGroup) {
|
||||
$objectGroupId = $objectGroup->id;
|
||||
$objectGroupOrder = $objectGroup->order;
|
||||
$objectGroupTitle = $objectGroup->title;
|
||||
}
|
||||
|
||||
// get currently saved amount:
|
||||
$currency = $piggyBank->transactionCurrency;
|
||||
$currentAmount = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||
|
||||
// Amounts, depending on 0.0 state of target amount
|
||||
$percentage = null;
|
||||
$targetAmount = $piggyBank->target_amount;
|
||||
$leftToSave = null;
|
||||
$savePerMonth = null;
|
||||
if (0 !== bccomp($targetAmount, '0')) { // target amount is not 0.00
|
||||
$leftToSave = bcsub($piggyBank->target_amount, $currentAmount);
|
||||
$percentage = (int) bcmul(bcdiv($currentAmount, $targetAmount), '100');
|
||||
$targetAmount = Steam::bcround($targetAmount, $currency->decimal_places);
|
||||
$leftToSave = Steam::bcround($leftToSave, $currency->decimal_places);
|
||||
$savePerMonth = Steam::bcround($this->piggyRepos->getSuggestedMonthlyAmount($piggyBank), $currency->decimal_places);
|
||||
$percentage = null;
|
||||
if (null !== $piggyBank->meta['target_amount'] && 0 !== bccomp($piggyBank->meta['current_amount'], '0')) { // target amount is not 0.00
|
||||
$percentage = (int)bcmul(bcdiv($piggyBank->meta['current_amount'], $piggyBank->meta['target_amount']), '100');
|
||||
}
|
||||
$startDate = $piggyBank->start_date?->format('Y-m-d');
|
||||
$targetDate = $piggyBank->target_date?->format('Y-m-d');
|
||||
$startDate = $piggyBank->start_date?->toAtomString();
|
||||
$targetDate = $piggyBank->target_date?->toAtomString();
|
||||
|
||||
return [
|
||||
'id' => (string) $piggyBank->id,
|
||||
'created_at' => $piggyBank->created_at->toAtomString(),
|
||||
'updated_at' => $piggyBank->updated_at->toAtomString(),
|
||||
'name' => $piggyBank->name,
|
||||
'accounts' => $this->renderAccounts($piggyBank),
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'target_amount' => $targetAmount,
|
||||
'percentage' => $percentage,
|
||||
'current_amount' => $currentAmount,
|
||||
'left_to_save' => $leftToSave,
|
||||
'save_per_month' => $savePerMonth,
|
||||
'start_date' => $startDate,
|
||||
'target_date' => $targetDate,
|
||||
'order' => $piggyBank->order,
|
||||
'active' => true,
|
||||
'notes' => $notes,
|
||||
'object_group_id' => null !== $objectGroupId ? (string) $objectGroupId : null,
|
||||
'object_group_order' => $objectGroupOrder,
|
||||
'object_group_title' => $objectGroupTitle,
|
||||
'links' => [
|
||||
'id' => (string)$piggyBank->id,
|
||||
'created_at' => $piggyBank->created_at->toAtomString(),
|
||||
'updated_at' => $piggyBank->updated_at->toAtomString(),
|
||||
'name' => $piggyBank->name,
|
||||
'percentage' => $percentage,
|
||||
'start_date' => $startDate,
|
||||
'target_date' => $targetDate,
|
||||
'order' => $piggyBank->order,
|
||||
'active' => true,
|
||||
'notes' => $piggyBank->meta['notes'],
|
||||
'object_group_id' => $piggyBank->meta['object_group_id'],
|
||||
'object_group_order' => $piggyBank->meta['object_group_order'],
|
||||
'object_group_title' => $piggyBank->meta['object_group_title'],
|
||||
'accounts' => $piggyBank->meta['accounts'],
|
||||
|
||||
// currency settings, 6.3.0.
|
||||
'object_has_currency_setting' => true,
|
||||
'currency_id' => (string)$piggyBank->meta['currency']->id,
|
||||
'currency_name' => $piggyBank->meta['currency']->name,
|
||||
'currency_code' => $piggyBank->meta['currency']->code,
|
||||
'currency_symbol' => $piggyBank->meta['currency']->symbol,
|
||||
'currency_decimal_places' => $piggyBank->meta['currency']->decimal_places,
|
||||
|
||||
'primary_currency_id' => (string)$this->primaryCurrency->id,
|
||||
'primary_currency_name' => $this->primaryCurrency->name,
|
||||
'primary_currency_code' => $this->primaryCurrency->code,
|
||||
'primary_currency_symbol' => $this->primaryCurrency->symbol,
|
||||
'primary_currency_decimal_places' => (int)$this->primaryCurrency->decimal_places,
|
||||
|
||||
|
||||
'target_amount' => $piggyBank->meta['target_amount'],
|
||||
'pc_target_amount' => $piggyBank->meta['pc_target_amount'],
|
||||
'current_amount' => $piggyBank->meta['current_amount'],
|
||||
'pc_current_amount' => $piggyBank->meta['pc_current_amount'],
|
||||
'left_to_save' => $piggyBank->meta['left_to_save'],
|
||||
'pc_left_to_save' => $piggyBank->meta['pc_left_to_save'],
|
||||
'save_per_month' => $piggyBank->meta['save_per_month'],
|
||||
'pc_save_per_month' => $piggyBank->meta['pc_save_per_month'],
|
||||
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'self',
|
||||
'uri' => '/piggy_banks/'.$piggyBank->id,
|
||||
'uri' => sprintf('/piggy-banks/%d', $piggyBank->id),
|
||||
],
|
||||
],
|
||||
];
|
||||
@@ -133,10 +113,10 @@ class PiggyBankTransformer extends AbstractTransformer
|
||||
$return = [];
|
||||
foreach ($piggyBank->accounts()->get() as $account) {
|
||||
$return[] = [
|
||||
'id' => (string) $account->id,
|
||||
'name' => $account->name,
|
||||
'current_amount' => (string) $account->pivot->current_amount,
|
||||
'pc_current_amount' => (string) $account->pivot->native_current_amount,
|
||||
'id' => (string)$account->id,
|
||||
'name' => $account->name,
|
||||
'current_amount' => (string)$account->pivot->current_amount,
|
||||
'pc_current_amount' => (string)$account->pivot->native_current_amount,
|
||||
// TODO add balance, add left to save.
|
||||
];
|
||||
}
|
||||
|
||||
@@ -24,45 +24,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Transformers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Factory\CategoryFactory;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceRepetition;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\RecurrenceTransactionMeta;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use function Safe\json_decode;
|
||||
|
||||
/**
|
||||
* Class RecurringTransactionTransformer
|
||||
*/
|
||||
class RecurrenceTransformer extends AbstractTransformer
|
||||
{
|
||||
private readonly BillRepositoryInterface $billRepos;
|
||||
private readonly BudgetRepositoryInterface $budgetRepos;
|
||||
private readonly CategoryFactory $factory;
|
||||
private readonly PiggyBankRepositoryInterface $piggyRepos;
|
||||
private readonly RecurringRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* RecurrenceTransformer constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->repository = app(RecurringRepositoryInterface::class);
|
||||
$this->piggyRepos = app(PiggyBankRepositoryInterface::class);
|
||||
$this->factory = app(CategoryFactory::class);
|
||||
$this->budgetRepos = app(BudgetRepositoryInterface::class);
|
||||
$this->billRepos = app(BillRepositoryInterface::class);
|
||||
}
|
||||
public function __construct() {}
|
||||
|
||||
/**
|
||||
* Transform the recurring transaction.
|
||||
@@ -72,34 +46,28 @@ class RecurrenceTransformer extends AbstractTransformer
|
||||
public function transform(Recurrence $recurrence): array
|
||||
{
|
||||
Log::debug('Now in Recurrence::transform()');
|
||||
$this->repository->setUser($recurrence->user);
|
||||
$this->piggyRepos->setUser($recurrence->user);
|
||||
$this->factory->setUser($recurrence->user);
|
||||
$this->budgetRepos->setUser($recurrence->user);
|
||||
Log::debug('Set user.');
|
||||
|
||||
$shortType = (string) config(sprintf('firefly.transactionTypesToShort.%s', $recurrence->transactionType->type));
|
||||
$notes = $this->repository->getNoteText($recurrence);
|
||||
$reps = 0 === (int) $recurrence->repetitions ? null : (int) $recurrence->repetitions;
|
||||
$shortType = (string)config(sprintf('firefly.transactionTypesToShort.%s', $recurrence->transactionType->type));
|
||||
$reps = 0 === (int)$recurrence->repetitions ? null : (int)$recurrence->repetitions;
|
||||
Log::debug('Get basic data.');
|
||||
|
||||
// basic data.
|
||||
return [
|
||||
'id' => (string) $recurrence->id,
|
||||
'id' => (string)$recurrence->id,
|
||||
'created_at' => $recurrence->created_at->toAtomString(),
|
||||
'updated_at' => $recurrence->updated_at->toAtomString(),
|
||||
'type' => $shortType,
|
||||
'title' => $recurrence->title,
|
||||
'description' => $recurrence->description,
|
||||
'first_date' => $recurrence->first_date->format('Y-m-d'),
|
||||
'latest_date' => $recurrence->latest_date?->format('Y-m-d'),
|
||||
'repeat_until' => $recurrence->repeat_until?->format('Y-m-d'),
|
||||
'first_date' => $recurrence->first_date->toAtomString(),
|
||||
'latest_date' => $recurrence->latest_date?->toAtomString(),
|
||||
'repeat_until' => $recurrence->repeat_until?->toAtomString(),
|
||||
'apply_rules' => $recurrence->apply_rules,
|
||||
'active' => $recurrence->active,
|
||||
'nr_of_repetitions' => $reps,
|
||||
'notes' => '' === $notes ? null : $notes,
|
||||
'repetitions' => $this->getRepetitions($recurrence),
|
||||
'transactions' => $this->getTransactions($recurrence),
|
||||
'notes' => $recurrence->meta['notes'],
|
||||
'repetitions' => $recurrence->meta['repetitions'],
|
||||
'new_transactions' => $recurrence->meta['transactions'],
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'self',
|
||||
@@ -108,208 +76,4 @@ class RecurrenceTransformer extends AbstractTransformer
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getRepetitions(Recurrence $recurrence): array
|
||||
{
|
||||
Log::debug('Now in getRepetitions().');
|
||||
$fromDate = $recurrence->latest_date ?? $recurrence->first_date;
|
||||
$return = [];
|
||||
|
||||
/** @var RecurrenceRepetition $repetition */
|
||||
foreach ($recurrence->recurrenceRepetitions as $repetition) {
|
||||
$repetitionArray = [
|
||||
'id' => (string) $repetition->id,
|
||||
'created_at' => $repetition->created_at->toAtomString(),
|
||||
'updated_at' => $repetition->updated_at->toAtomString(),
|
||||
'type' => $repetition->repetition_type,
|
||||
'moment' => $repetition->repetition_moment,
|
||||
'skip' => $repetition->repetition_skip,
|
||||
'weekend' => $repetition->weekend,
|
||||
'description' => $this->repository->repetitionDescription($repetition),
|
||||
'occurrences' => [],
|
||||
];
|
||||
|
||||
// get the (future) occurrences for this specific type of repetition:
|
||||
$amount = 'daily' === $repetition->repetition_type ? 9 : 5;
|
||||
$occurrences = $this->repository->getXOccurrencesSince($repetition, $fromDate, now(), $amount);
|
||||
|
||||
/** @var Carbon $carbon */
|
||||
foreach ($occurrences as $carbon) {
|
||||
$repetitionArray['occurrences'][] = $carbon->toAtomString();
|
||||
}
|
||||
|
||||
$return[] = $repetitionArray;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getTransactions(Recurrence $recurrence): array
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$return = [];
|
||||
|
||||
// get all transactions:
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($recurrence->recurrenceTransactions()->get() as $transaction) {
|
||||
/** @var null|Account $sourceAccount */
|
||||
$sourceAccount = $transaction->sourceAccount;
|
||||
|
||||
/** @var null|Account $destinationAccount */
|
||||
$destinationAccount = $transaction->destinationAccount;
|
||||
$foreignCurrencyCode = null;
|
||||
$foreignCurrencySymbol = null;
|
||||
$foreignCurrencyDp = null;
|
||||
$foreignCurrencyId = null;
|
||||
if (null !== $transaction->foreign_currency_id) {
|
||||
$foreignCurrencyId = (int) $transaction->foreign_currency_id;
|
||||
$foreignCurrencyCode = $transaction->foreignCurrency->code;
|
||||
$foreignCurrencySymbol = $transaction->foreignCurrency->symbol;
|
||||
$foreignCurrencyDp = $transaction->foreignCurrency->decimal_places;
|
||||
}
|
||||
|
||||
// source info:
|
||||
$sourceName = '';
|
||||
$sourceId = null;
|
||||
$sourceType = null;
|
||||
$sourceIban = null;
|
||||
if (null !== $sourceAccount) {
|
||||
$sourceName = $sourceAccount->name;
|
||||
$sourceId = $sourceAccount->id;
|
||||
$sourceType = $sourceAccount->accountType->type;
|
||||
$sourceIban = $sourceAccount->iban;
|
||||
}
|
||||
$destinationName = '';
|
||||
$destinationId = null;
|
||||
$destinationType = null;
|
||||
$destinationIban = null;
|
||||
if (null !== $destinationAccount) {
|
||||
$destinationName = $destinationAccount->name;
|
||||
$destinationId = $destinationAccount->id;
|
||||
$destinationType = $destinationAccount->accountType->type;
|
||||
$destinationIban = $destinationAccount->iban;
|
||||
}
|
||||
$amount = Steam::bcround($transaction->amount, $transaction->transactionCurrency->decimal_places);
|
||||
$foreignAmount = null;
|
||||
if (null !== $transaction->foreign_currency_id && null !== $transaction->foreign_amount) {
|
||||
$foreignAmount = Steam::bcround($transaction->foreign_amount, $foreignCurrencyDp);
|
||||
}
|
||||
$transactionArray = [
|
||||
'id' => (string) $transaction->id,
|
||||
'currency_id' => (string) $transaction->transaction_currency_id,
|
||||
'currency_code' => $transaction->transactionCurrency->code,
|
||||
'currency_symbol' => $transaction->transactionCurrency->symbol,
|
||||
'currency_decimal_places' => $transaction->transactionCurrency->decimal_places,
|
||||
'foreign_currency_id' => null === $foreignCurrencyId ? null : (string) $foreignCurrencyId,
|
||||
'foreign_currency_code' => $foreignCurrencyCode,
|
||||
'foreign_currency_symbol' => $foreignCurrencySymbol,
|
||||
'foreign_currency_decimal_places' => $foreignCurrencyDp,
|
||||
'source_id' => (string) $sourceId,
|
||||
'source_name' => $sourceName,
|
||||
'source_iban' => $sourceIban,
|
||||
'source_type' => $sourceType,
|
||||
'destination_id' => (string) $destinationId,
|
||||
'destination_name' => $destinationName,
|
||||
'destination_iban' => $destinationIban,
|
||||
'destination_type' => $destinationType,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => $foreignAmount,
|
||||
'description' => $transaction->description,
|
||||
];
|
||||
$transactionArray = $this->getTransactionMeta($transaction, $transactionArray);
|
||||
if (null !== $transaction->foreign_currency_id) {
|
||||
$transactionArray['foreign_currency_code'] = $transaction->foreignCurrency->code;
|
||||
$transactionArray['foreign_currency_symbol'] = $transaction->foreignCurrency->symbol;
|
||||
$transactionArray['foreign_currency_decimal_places'] = $transaction->foreignCurrency->decimal_places;
|
||||
}
|
||||
|
||||
// store transaction in recurrence array.
|
||||
$return[] = $transactionArray;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getTransactionMeta(RecurrenceTransaction $transaction, array $array): array
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$array['tags'] = [];
|
||||
$array['category_id'] = null;
|
||||
$array['category_name'] = null;
|
||||
$array['budget_id'] = null;
|
||||
$array['budget_name'] = null;
|
||||
$array['piggy_bank_id'] = null;
|
||||
$array['piggy_bank_name'] = null;
|
||||
$array['bill_id'] = null;
|
||||
$array['bill_name'] = null;
|
||||
|
||||
/** @var RecurrenceTransactionMeta $transactionMeta */
|
||||
foreach ($transaction->recurrenceTransactionMeta as $transactionMeta) {
|
||||
switch ($transactionMeta->name) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Recurrence transformer cant handle field "%s"', $transactionMeta->name));
|
||||
|
||||
case 'bill_id':
|
||||
$bill = $this->billRepos->find((int) $transactionMeta->value);
|
||||
if (null !== $bill) {
|
||||
$array['bill_id'] = (string) $bill->id;
|
||||
$array['bill_name'] = $bill->name;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'tags':
|
||||
$array['tags'] = json_decode((string) $transactionMeta->value);
|
||||
|
||||
break;
|
||||
|
||||
case 'piggy_bank_id':
|
||||
$piggy = $this->piggyRepos->find((int) $transactionMeta->value);
|
||||
if (null !== $piggy) {
|
||||
$array['piggy_bank_id'] = (string) $piggy->id;
|
||||
$array['piggy_bank_name'] = $piggy->name;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'category_id':
|
||||
$category = $this->factory->findOrCreate((int) $transactionMeta->value, null);
|
||||
if (null !== $category) {
|
||||
$array['category_id'] = (string) $category->id;
|
||||
$array['category_name'] = $category->name;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'category_name':
|
||||
$category = $this->factory->findOrCreate(null, $transactionMeta->value);
|
||||
if (null !== $category) {
|
||||
$array['category_id'] = (string) $category->id;
|
||||
$array['category_name'] = $category->name;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'budget_id':
|
||||
$budget = $this->budgetRepos->find((int) $transactionMeta->value);
|
||||
if (null !== $budget) {
|
||||
$array['budget_id'] = (string) $budget->id;
|
||||
$array['budget_name'] = $budget->name;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
||||
33
composer.lock
generated
33
composer.lock
generated
@@ -3878,29 +3878,29 @@
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v4.0.7",
|
||||
"version": "v4.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2"
|
||||
"reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2",
|
||||
"reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede",
|
||||
"reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "8.0 - 8.4"
|
||||
"php": "8.0 - 8.5"
|
||||
},
|
||||
"conflict": {
|
||||
"nette/finder": "<3",
|
||||
"nette/schema": "<1.2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"jetbrains/phpstorm-attributes": "dev-master",
|
||||
"jetbrains/phpstorm-attributes": "^1.2",
|
||||
"nette/tester": "^2.5",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"phpstan/phpstan-nette": "^2.0@stable",
|
||||
"tracy/tracy": "^2.9"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -3918,6 +3918,9 @@
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nette\\": "src"
|
||||
},
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
@@ -3958,9 +3961,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/utils/issues",
|
||||
"source": "https://github.com/nette/utils/tree/v4.0.7"
|
||||
"source": "https://github.com/nette/utils/tree/v4.0.8"
|
||||
},
|
||||
"time": "2025-06-03T04:55:08+00:00"
|
||||
"time": "2025-08-06T21:43:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nunomaduro/collision",
|
||||
@@ -5101,16 +5104,16 @@
|
||||
},
|
||||
{
|
||||
"name": "predis/predis",
|
||||
"version": "v3.1.0",
|
||||
"version": "v3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/predis/predis.git",
|
||||
"reference": "202e0c5322b906ec4c761c0cefebad6d0959a699"
|
||||
"reference": "9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/predis/predis/zipball/202e0c5322b906ec4c761c0cefebad6d0959a699",
|
||||
"reference": "202e0c5322b906ec4c761c0cefebad6d0959a699",
|
||||
"url": "https://api.github.com/repos/predis/predis/zipball/9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8",
|
||||
"reference": "9e9deec4dfd3ebf65d32eb368f498c646ba2ecd8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5152,7 +5155,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/predis/predis/issues",
|
||||
"source": "https://github.com/predis/predis/tree/v3.1.0"
|
||||
"source": "https://github.com/predis/predis/tree/v3.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5160,7 +5163,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-07-22T15:37:44+00:00"
|
||||
"time": "2025-08-06T06:41:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
|
||||
@@ -78,8 +78,8 @@ return [
|
||||
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => 'develop/2025-08-05',
|
||||
'build_time' => 1754394714,
|
||||
'version' => 'develop/2025-08-07',
|
||||
'build_time' => 1754539423,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 26,
|
||||
|
||||
|
||||
@@ -23,243 +23,244 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'operators' => [
|
||||
'user_action' => ['alias' => false, 'needs_context' => true],
|
||||
'account_id' => ['alias' => false, 'needs_context' => true],
|
||||
'reconciled' => ['alias' => false, 'needs_context' => false],
|
||||
'source_account_id' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_account_id' => ['alias' => false, 'needs_context' => true],
|
||||
'transaction_type' => ['alias' => false, 'needs_context' => true],
|
||||
'type' => ['alias' => true, 'alias_for' => 'transaction_type', 'needs_context' => true],
|
||||
'tag_is' => ['alias' => false, 'needs_context' => true],
|
||||
'tag_is_not' => ['alias' => false, 'needs_context' => true],
|
||||
'tag' => ['alias' => true, 'alias_for' => 'tag_is', 'needs_context' => true],
|
||||
'tag_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'tag_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'tag_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'description_is' => ['alias' => false, 'needs_context' => true],
|
||||
'description' => ['alias' => true, 'alias_for' => 'description_is', 'needs_context' => true],
|
||||
'description_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'description_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'description_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_is' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_are' => ['alias' => true, 'alias_for' => 'notes_is', 'needs_context' => true],
|
||||
'notes_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_contain' => ['alias' => true, 'alias_for' => 'notes_contains', 'needs_context' => true],
|
||||
'notes' => ['alias' => true, 'alias_for' => 'notes_contains', 'needs_context' => true],
|
||||
'notes_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_end' => ['alias' => true, 'alias_for' => 'notes_ends', 'needs_context' => true],
|
||||
'notes_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_start' => ['alias' => true, 'alias_for' => 'notes_starts', 'needs_context' => true],
|
||||
'source_account_is' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_is' => ['alias' => true, 'alias_for' => 'source_account_is', 'needs_context' => true],
|
||||
'source_account_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'source' => ['alias' => true, 'alias_for' => 'source_account_contains', 'needs_context' => true],
|
||||
'from' => ['alias' => true, 'alias_for' => 'source_account_contains', 'needs_context' => true],
|
||||
'from_account_contains' => ['alias' => true, 'alias_for' => 'source_account_contains', 'needs_context' => true],
|
||||
'source_account_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_ends' => ['alias' => true, 'alias_for' => 'source_account_ends', 'needs_context' => true],
|
||||
'source_account_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_starts' => ['alias' => true, 'alias_for' => 'source_account_starts', 'needs_context' => true],
|
||||
'source_account_nr_is' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_nr_is' => ['alias' => true, 'alias_for' => 'source_account_nr_is', 'needs_context' => true],
|
||||
'source_account_nr_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_nr_contains' => ['alias' => true, 'alias_for' => 'source_account_nr_contains', 'needs_context' => true],
|
||||
'source_account_nr_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_nr_ends' => ['alias' => true, 'alias_for' => 'source_account_nr_ends', 'needs_context' => true],
|
||||
'source_account_nr_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_nr_starts' => ['alias' => true, 'alias_for' => 'source_account_nr_starts', 'needs_context' => true],
|
||||
'destination_account_is' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_is' => ['alias' => true, 'alias_for' => 'destination_account_is', 'needs_context' => true],
|
||||
'destination_account_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'destination' => ['alias' => true, 'alias_for' => 'destination_account_contains', 'needs_context' => true],
|
||||
'to' => ['alias' => true, 'alias_for' => 'destination_account_contains', 'needs_context' => true],
|
||||
'to_account_contains' => ['alias' => true, 'alias_for' => 'destination_account_contains', 'needs_context' => true],
|
||||
'destination_account_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_ends' => ['alias' => true, 'alias_for' => 'destination_account_ends', 'needs_context' => true],
|
||||
'destination_account_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_starts' => ['alias' => true, 'alias_for' => 'destination_account_starts', 'needs_context' => true],
|
||||
'destination_account_nr_is' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_nr_is' => ['alias' => true, 'alias_for' => 'destination_account_nr_is', 'needs_context' => true],
|
||||
'destination_account_nr_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_nr_contains' => ['alias' => true, 'alias_for' => 'destination_account_nr_contains', 'needs_context' => true],
|
||||
'destination_account_nr_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_nr_ends' => ['alias' => true, 'alias_for' => 'destination_account_nr_ends', 'needs_context' => true],
|
||||
'destination_account_nr_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_nr_starts' => ['alias' => true, 'alias_for' => 'destination_account_nr_starts', 'needs_context' => true],
|
||||
'account_is' => ['alias' => false, 'needs_context' => true],
|
||||
'account_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'account_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'account_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'account_nr_is' => ['alias' => false, 'needs_context' => true],
|
||||
'account_nr_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'account_nr_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'account_nr_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'category_is' => ['alias' => false, 'needs_context' => true],
|
||||
'category_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'category' => ['alias' => true, 'alias_for' => 'category_contains', 'needs_context' => true],
|
||||
'category_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'category_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'budget_is' => ['alias' => false, 'needs_context' => true],
|
||||
'budget_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'budget' => ['alias' => true, 'alias_for' => 'budget_contains', 'needs_context' => true],
|
||||
'budget_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'budget_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'bill_is' => ['alias' => false, 'needs_context' => true],
|
||||
'bill_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'bill' => ['alias' => true, 'alias_for' => 'bill_contains', 'needs_context' => true],
|
||||
'bill_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'bill_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'subscription_is' => ['alias' => true, 'alias_for' => 'bill_is', 'needs_context' => true],
|
||||
'subscription_contains' => ['alias' => true, 'alias_for' => 'bill_contains', 'needs_context' => true],
|
||||
'subscription' => ['alias' => true, 'alias_for' => 'bill_contains', 'needs_context' => true],
|
||||
'subscription_ends' => ['alias' => true, 'alias_for' => 'bill_ends', 'needs_context' => true],
|
||||
'subscription_starts' => ['alias' => true, 'alias_for' => 'bill_starts', 'needs_context' => true],
|
||||
'external_id_is' => ['alias' => false, 'needs_context' => true],
|
||||
'external_id_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'external_id' => ['alias' => true, 'alias_for' => 'external_id_contains', 'needs_context' => true],
|
||||
'external_id_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'external_id_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'internal_reference_is' => ['alias' => false, 'needs_context' => true],
|
||||
'internal_reference_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'internal_reference' => ['alias' => true, 'alias_for' => 'internal_reference_contains', 'needs_context' => true],
|
||||
'internal_reference_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'internal_reference_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'external_url_is' => ['alias' => false, 'needs_context' => true],
|
||||
'external_url_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'external_url' => ['alias' => true, 'alias_for' => 'external_url_contains', 'needs_context' => true],
|
||||
'external_url_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'external_url_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'has_attachments' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_category' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_budget' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_bill' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_subscription' => ['alias' => true, 'needs_context' => false, 'alias_for' => 'has_any_bill'],
|
||||
'has_any_tag' => ['alias' => false, 'needs_context' => false],
|
||||
'any_notes' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_notes' => ['alias' => true, 'alias_for' => 'any_notes', 'needs_context' => false],
|
||||
'has_notes' => ['alias' => true, 'alias_for' => 'any_notes', 'needs_context' => false],
|
||||
'any_external_url' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_external_url' => ['alias' => true, 'alias_for' => 'any_external_url', 'needs_context' => false],
|
||||
'has_no_attachments' => ['alias' => false, 'needs_context' => false],
|
||||
'has_no_category' => ['alias' => false, 'needs_context' => false],
|
||||
'has_no_budget' => ['alias' => false, 'needs_context' => false],
|
||||
'has_no_bill' => ['alias' => false, 'needs_context' => false],
|
||||
'has_no_subscription' => ['alias' => true, 'needs_context' => false, 'alias_for' => 'has_no_bill'],
|
||||
'has_no_tag' => ['alias' => false, 'needs_context' => false],
|
||||
'no_notes' => ['alias' => false, 'needs_context' => false],
|
||||
'no_external_url' => ['alias' => false, 'needs_context' => false],
|
||||
'source_is_cash' => ['alias' => false, 'needs_context' => false],
|
||||
'destination_is_cash' => ['alias' => false, 'needs_context' => false],
|
||||
'account_is_cash' => ['alias' => false, 'needs_context' => false],
|
||||
'currency_is' => ['alias' => false, 'needs_context' => true],
|
||||
'foreign_currency_is' => ['alias' => false, 'needs_context' => true],
|
||||
'id' => ['alias' => false, 'trigger_class' => '', 'needs_context' => true],
|
||||
'journal_id' => ['alias' => false, 'trigger_class' => '', 'needs_context' => true],
|
||||
'recurrence_id' => ['alias' => false, 'trigger_class' => '', 'needs_context' => true],
|
||||
'date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'date' => ['alias' => true, 'alias_for' => 'date_on', 'needs_context' => true],
|
||||
'date_is' => ['alias' => true, 'alias_for' => 'date_on', 'needs_context' => true],
|
||||
'on' => ['alias' => true, 'alias_for' => 'date_on', 'needs_context' => true],
|
||||
'date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'before' => ['alias' => true, 'alias_for' => 'date_before', 'needs_context' => true],
|
||||
'date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'after' => ['alias' => true, 'alias_for' => 'date_after', 'needs_context' => true],
|
||||
'interest_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'interest_date' => ['alias' => true, 'alias_for' => 'interest_date_on', 'needs_context' => true],
|
||||
'interest_date_is' => ['alias' => true, 'alias_for' => 'interest_date_on', 'needs_context' => true],
|
||||
'interest_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'interest_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'book_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'book_date' => ['alias' => true, 'alias_for' => 'book_date_on', 'needs_context' => true],
|
||||
'book_date_is' => ['alias' => true, 'alias_for' => 'book_date_on', 'needs_context' => true],
|
||||
'book_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'book_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'process_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'process_date' => ['alias' => true, 'alias_for' => 'process_date_on', 'needs_context' => true],
|
||||
'process_date_is' => ['alias' => true, 'alias_for' => 'process_date_on', 'needs_context' => true],
|
||||
'process_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'process_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'due_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'due_date' => ['alias' => true, 'alias_for' => 'due_date_on', 'needs_context' => true],
|
||||
'due_date_is' => ['alias' => true, 'alias_for' => 'due_date_on', 'needs_context' => true],
|
||||
'due_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'due_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'payment_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'payment_date' => ['alias' => true, 'alias_for' => 'payment_date_on', 'needs_context' => true],
|
||||
'payment_date_is' => ['alias' => true, 'alias_for' => 'payment_date_on', 'needs_context' => true],
|
||||
'payment_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'payment_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'invoice_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'invoice_date' => ['alias' => true, 'alias_for' => 'invoice_date_on', 'needs_context' => true],
|
||||
'invoice_date_is' => ['alias' => true, 'alias_for' => 'invoice_date_on', 'needs_context' => true],
|
||||
'invoice_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'invoice_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'created_at_on' => ['alias' => false, 'needs_context' => true],
|
||||
'created_at' => ['alias' => true, 'alias_for' => 'created_at_on', 'needs_context' => true],
|
||||
'created_at_is' => ['alias' => true, 'alias_for' => 'created_at_on', 'needs_context' => true],
|
||||
'created_at_before' => ['alias' => false, 'needs_context' => true],
|
||||
'created_at_after' => ['alias' => false, 'needs_context' => true],
|
||||
'updated_at_on' => ['alias' => false, 'needs_context' => true],
|
||||
'updated_at' => ['alias' => true, 'alias_for' => 'updated_at_on', 'needs_context' => true],
|
||||
'updated_at_is' => ['alias' => true, 'alias_for' => 'updated_at_on', 'needs_context' => true],
|
||||
'updated_at_before' => ['alias' => false, 'needs_context' => true],
|
||||
'updated_at_after' => ['alias' => false, 'needs_context' => true],
|
||||
'created_on_on' => ['alias' => true, 'alias_for' => 'created_at_on', 'needs_context' => true],
|
||||
'created_on' => ['alias' => true, 'alias_for' => 'created_at', 'needs_context' => true],
|
||||
'created_on_before' => ['alias' => true, 'alias_for' => 'created_at_before', 'needs_context' => true],
|
||||
'created_on_after' => ['alias' => true, 'alias_for' => 'created_at_after', 'needs_context' => true],
|
||||
'updated_on_on' => ['alias' => true, 'alias_for' => 'updated_at_on', 'needs_context' => true],
|
||||
'updated_on' => ['alias' => true, 'alias_for' => 'updated_at', 'needs_context' => true],
|
||||
'updated_on_before' => ['alias' => true, 'alias_for' => 'updated_at_before', 'needs_context' => true],
|
||||
'updated_on_after' => ['alias' => true, 'alias_for' => 'updated_at_after', 'needs_context' => true],
|
||||
'amount_is' => ['alias' => false, 'needs_context' => true],
|
||||
'amount' => ['alias' => true, 'alias_for' => 'amount_is', 'needs_context' => true],
|
||||
'amount_exactly' => ['alias' => true, 'alias_for' => 'amount_is', 'needs_context' => true],
|
||||
'amount_less' => ['alias' => false, 'needs_context' => true],
|
||||
'amount_max' => ['alias' => true, 'alias_for' => 'amount_less', 'needs_context' => true],
|
||||
'less' => ['alias' => true, 'alias_for' => 'amount_less', 'needs_context' => true],
|
||||
'amount_more' => ['alias' => false, 'needs_context' => true],
|
||||
'amount_min' => ['alias' => true, 'alias_for' => 'amount_more', 'needs_context' => true],
|
||||
'more' => ['alias' => true, 'alias_for' => 'amount_more', 'needs_context' => true],
|
||||
'foreign_amount_is' => ['alias' => false, 'needs_context' => true],
|
||||
'foreign_amount' => ['alias' => true, 'alias_for' => 'foreign_amount_is', 'needs_context' => true],
|
||||
'foreign_amount_less' => ['alias' => false, 'needs_context' => true],
|
||||
'foreign_amount_max' => ['alias' => true, 'alias_for' => 'foreign_amount_less', 'needs_context' => true],
|
||||
'foreign_amount_more' => ['alias' => false, 'needs_context' => true],
|
||||
'foreign_amount_min' => ['alias' => true, 'alias_for' => 'foreign_amount_more', 'needs_context' => true],
|
||||
'attachment_name_is' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment' => ['alias' => true, 'alias_for' => 'attachment_name_is', 'needs_context' => true],
|
||||
'attachment_is' => ['alias' => true, 'alias_for' => 'attachment_name_is', 'needs_context' => true],
|
||||
'attachment_name' => ['alias' => true, 'alias_for' => 'attachment_name_is', 'needs_context' => true],
|
||||
'attachment_name_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_name_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_name_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes' => ['alias' => true, 'alias_for' => 'attachment_notes_are', 'needs_context' => true],
|
||||
'attachment_notes_are' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_contain' => ['alias' => true, 'alias_for' => 'attachment_notes_contains', 'needs_context' => true],
|
||||
'attachment_notes_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_start' => ['alias' => true, 'alias_for' => 'attachment_notes_starts', 'needs_context' => true],
|
||||
'attachment_notes_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_end' => ['alias' => true, 'alias_for' => 'attachment_notes_ends', 'needs_context' => true],
|
||||
'exists' => ['alias' => false, 'needs_context' => false],
|
||||
'sepa_ct_is' => ['alias' => false, 'needs_context' => true],
|
||||
'no_external_id' => ['alias' => false, 'needs_context' => false],
|
||||
'any_external_id' => ['alias' => false, 'needs_context' => false],
|
||||
'operators' => [
|
||||
'user_action' => ['alias' => false, 'needs_context' => true],
|
||||
'account_id' => ['alias' => false, 'needs_context' => true],
|
||||
'reconciled' => ['alias' => false, 'needs_context' => false],
|
||||
'source_account_id' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_account_id' => ['alias' => false, 'needs_context' => true],
|
||||
'transaction_type' => ['alias' => false, 'needs_context' => true],
|
||||
'type' => ['alias' => true, 'alias_for' => 'transaction_type', 'needs_context' => true],
|
||||
'tag_is' => ['alias' => false, 'needs_context' => true],
|
||||
'tag_is_not' => ['alias' => false, 'needs_context' => true],
|
||||
'tag' => ['alias' => true, 'alias_for' => 'tag_is', 'needs_context' => true],
|
||||
'tag_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'tag_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'tag_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'description_is' => ['alias' => false, 'needs_context' => true],
|
||||
'description' => ['alias' => true, 'alias_for' => 'description_is', 'needs_context' => true],
|
||||
'description_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'description_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'description_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_is' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_are' => ['alias' => true, 'alias_for' => 'notes_is', 'needs_context' => true],
|
||||
'notes_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_contain' => ['alias' => true, 'alias_for' => 'notes_contains', 'needs_context' => true],
|
||||
'notes' => ['alias' => true, 'alias_for' => 'notes_contains', 'needs_context' => true],
|
||||
'notes_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_end' => ['alias' => true, 'alias_for' => 'notes_ends', 'needs_context' => true],
|
||||
'notes_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'notes_start' => ['alias' => true, 'alias_for' => 'notes_starts', 'needs_context' => true],
|
||||
'source_account_is' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_is' => ['alias' => true, 'alias_for' => 'source_account_is', 'needs_context' => true],
|
||||
'source_account_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'source' => ['alias' => true, 'alias_for' => 'source_account_contains', 'needs_context' => true],
|
||||
'from' => ['alias' => true, 'alias_for' => 'source_account_contains', 'needs_context' => true],
|
||||
'from_account_contains' => ['alias' => true, 'alias_for' => 'source_account_contains', 'needs_context' => true],
|
||||
'source_account_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_ends' => ['alias' => true, 'alias_for' => 'source_account_ends', 'needs_context' => true],
|
||||
'source_account_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_starts' => ['alias' => true, 'alias_for' => 'source_account_starts', 'needs_context' => true],
|
||||
'source_account_nr_is' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_nr_is' => ['alias' => true, 'alias_for' => 'source_account_nr_is', 'needs_context' => true],
|
||||
'source_account_nr_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_nr_contains' => ['alias' => true, 'alias_for' => 'source_account_nr_contains', 'needs_context' => true],
|
||||
'source_account_nr_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_nr_ends' => ['alias' => true, 'alias_for' => 'source_account_nr_ends', 'needs_context' => true],
|
||||
'source_account_nr_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'from_account_nr_starts' => ['alias' => true, 'alias_for' => 'source_account_nr_starts', 'needs_context' => true],
|
||||
'destination_account_is' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_is' => ['alias' => true, 'alias_for' => 'destination_account_is', 'needs_context' => true],
|
||||
'destination_account_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'destination' => ['alias' => true, 'alias_for' => 'destination_account_contains', 'needs_context' => true],
|
||||
'to' => ['alias' => true, 'alias_for' => 'destination_account_contains', 'needs_context' => true],
|
||||
'to_account_contains' => ['alias' => true, 'alias_for' => 'destination_account_contains', 'needs_context' => true],
|
||||
'destination_account_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_ends' => ['alias' => true, 'alias_for' => 'destination_account_ends', 'needs_context' => true],
|
||||
'destination_account_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_starts' => ['alias' => true, 'alias_for' => 'destination_account_starts', 'needs_context' => true],
|
||||
'destination_account_nr_is' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_nr_is' => ['alias' => true, 'alias_for' => 'destination_account_nr_is', 'needs_context' => true],
|
||||
'destination_account_nr_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_nr_contains' => ['alias' => true, 'alias_for' => 'destination_account_nr_contains', 'needs_context' => true],
|
||||
'destination_account_nr_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_nr_ends' => ['alias' => true, 'alias_for' => 'destination_account_nr_ends', 'needs_context' => true],
|
||||
'destination_account_nr_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'to_account_nr_starts' => ['alias' => true, 'alias_for' => 'destination_account_nr_starts', 'needs_context' => true],
|
||||
'account_is' => ['alias' => false, 'needs_context' => true],
|
||||
'account_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'account_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'account_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'account_nr_is' => ['alias' => false, 'needs_context' => true],
|
||||
'account_nr_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'account_nr_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'account_nr_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'category_is' => ['alias' => false, 'needs_context' => true],
|
||||
'category_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'category' => ['alias' => true, 'alias_for' => 'category_contains', 'needs_context' => true],
|
||||
'category_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'category_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'budget_is' => ['alias' => false, 'needs_context' => true],
|
||||
'budget_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'budget' => ['alias' => true, 'alias_for' => 'budget_contains', 'needs_context' => true],
|
||||
'budget_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'budget_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'bill_is' => ['alias' => false, 'needs_context' => true],
|
||||
'bill_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'bill' => ['alias' => true, 'alias_for' => 'bill_contains', 'needs_context' => true],
|
||||
'bill_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'bill_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'subscription_is' => ['alias' => true, 'alias_for' => 'bill_is', 'needs_context' => true],
|
||||
'subscription_contains' => ['alias' => true, 'alias_for' => 'bill_contains', 'needs_context' => true],
|
||||
'subscription' => ['alias' => true, 'alias_for' => 'bill_contains', 'needs_context' => true],
|
||||
'subscription_ends' => ['alias' => true, 'alias_for' => 'bill_ends', 'needs_context' => true],
|
||||
'subscription_starts' => ['alias' => true, 'alias_for' => 'bill_starts', 'needs_context' => true],
|
||||
'external_id_is' => ['alias' => false, 'needs_context' => true],
|
||||
'external_id_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'external_id' => ['alias' => true, 'alias_for' => 'external_id_contains', 'needs_context' => true],
|
||||
'external_id_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'external_id_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'internal_reference_is' => ['alias' => false, 'needs_context' => true],
|
||||
'internal_reference_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'internal_reference' => ['alias' => true, 'alias_for' => 'internal_reference_contains', 'needs_context' => true],
|
||||
'internal_reference_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'internal_reference_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'external_url_is' => ['alias' => false, 'needs_context' => true],
|
||||
'external_url_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'external_url' => ['alias' => true, 'alias_for' => 'external_url_contains', 'needs_context' => true],
|
||||
'external_url_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'external_url_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'has_attachments' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_category' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_budget' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_bill' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_subscription' => ['alias' => true, 'needs_context' => false, 'alias_for' => 'has_any_bill'],
|
||||
'has_any_tag' => ['alias' => false, 'needs_context' => false],
|
||||
'any_notes' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_notes' => ['alias' => true, 'alias_for' => 'any_notes', 'needs_context' => false],
|
||||
'has_notes' => ['alias' => true, 'alias_for' => 'any_notes', 'needs_context' => false],
|
||||
'any_external_url' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_external_url' => ['alias' => true, 'alias_for' => 'any_external_url', 'needs_context' => false],
|
||||
'has_no_attachments' => ['alias' => false, 'needs_context' => false],
|
||||
'has_no_category' => ['alias' => false, 'needs_context' => false],
|
||||
'has_no_budget' => ['alias' => false, 'needs_context' => false],
|
||||
'has_no_bill' => ['alias' => false, 'needs_context' => false],
|
||||
'has_no_subscription' => ['alias' => true, 'needs_context' => false, 'alias_for' => 'has_no_bill'],
|
||||
'has_no_tag' => ['alias' => false, 'needs_context' => false],
|
||||
'no_notes' => ['alias' => false, 'needs_context' => false],
|
||||
'no_external_url' => ['alias' => false, 'needs_context' => false],
|
||||
'source_is_cash' => ['alias' => false, 'needs_context' => false],
|
||||
'destination_is_cash' => ['alias' => false, 'needs_context' => false],
|
||||
'account_is_cash' => ['alias' => false, 'needs_context' => false],
|
||||
'currency_is' => ['alias' => false, 'needs_context' => true],
|
||||
'foreign_currency_is' => ['alias' => false, 'needs_context' => true],
|
||||
'id' => ['alias' => false, 'trigger_class' => '', 'needs_context' => true],
|
||||
'journal_id' => ['alias' => false, 'trigger_class' => '', 'needs_context' => true],
|
||||
'recurrence_id' => ['alias' => false, 'trigger_class' => '', 'needs_context' => true],
|
||||
'date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'date' => ['alias' => true, 'alias_for' => 'date_on', 'needs_context' => true],
|
||||
'date_is' => ['alias' => true, 'alias_for' => 'date_on', 'needs_context' => true],
|
||||
'on' => ['alias' => true, 'alias_for' => 'date_on', 'needs_context' => true],
|
||||
'date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'before' => ['alias' => true, 'alias_for' => 'date_before', 'needs_context' => true],
|
||||
'date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'after' => ['alias' => true, 'alias_for' => 'date_after', 'needs_context' => true],
|
||||
'interest_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'interest_date' => ['alias' => true, 'alias_for' => 'interest_date_on', 'needs_context' => true],
|
||||
'interest_date_is' => ['alias' => true, 'alias_for' => 'interest_date_on', 'needs_context' => true],
|
||||
'interest_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'interest_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'book_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'book_date' => ['alias' => true, 'alias_for' => 'book_date_on', 'needs_context' => true],
|
||||
'book_date_is' => ['alias' => true, 'alias_for' => 'book_date_on', 'needs_context' => true],
|
||||
'book_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'book_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'process_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'process_date' => ['alias' => true, 'alias_for' => 'process_date_on', 'needs_context' => true],
|
||||
'process_date_is' => ['alias' => true, 'alias_for' => 'process_date_on', 'needs_context' => true],
|
||||
'process_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'process_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'due_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'due_date' => ['alias' => true, 'alias_for' => 'due_date_on', 'needs_context' => true],
|
||||
'due_date_is' => ['alias' => true, 'alias_for' => 'due_date_on', 'needs_context' => true],
|
||||
'due_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'due_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'payment_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'payment_date' => ['alias' => true, 'alias_for' => 'payment_date_on', 'needs_context' => true],
|
||||
'payment_date_is' => ['alias' => true, 'alias_for' => 'payment_date_on', 'needs_context' => true],
|
||||
'payment_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'payment_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'invoice_date_on' => ['alias' => false, 'needs_context' => true],
|
||||
'invoice_date' => ['alias' => true, 'alias_for' => 'invoice_date_on', 'needs_context' => true],
|
||||
'invoice_date_is' => ['alias' => true, 'alias_for' => 'invoice_date_on', 'needs_context' => true],
|
||||
'invoice_date_before' => ['alias' => false, 'needs_context' => true],
|
||||
'invoice_date_after' => ['alias' => false, 'needs_context' => true],
|
||||
'created_at_on' => ['alias' => false, 'needs_context' => true],
|
||||
'created_at' => ['alias' => true, 'alias_for' => 'created_at_on', 'needs_context' => true],
|
||||
'created_at_is' => ['alias' => true, 'alias_for' => 'created_at_on', 'needs_context' => true],
|
||||
'created_at_before' => ['alias' => false, 'needs_context' => true],
|
||||
'created_at_after' => ['alias' => false, 'needs_context' => true],
|
||||
'updated_at_on' => ['alias' => false, 'needs_context' => true],
|
||||
'updated_at' => ['alias' => true, 'alias_for' => 'updated_at_on', 'needs_context' => true],
|
||||
'updated_at_is' => ['alias' => true, 'alias_for' => 'updated_at_on', 'needs_context' => true],
|
||||
'updated_at_before' => ['alias' => false, 'needs_context' => true],
|
||||
'updated_at_after' => ['alias' => false, 'needs_context' => true],
|
||||
'created_on_on' => ['alias' => true, 'alias_for' => 'created_at_on', 'needs_context' => true],
|
||||
'created_on' => ['alias' => true, 'alias_for' => 'created_at', 'needs_context' => true],
|
||||
'created_on_before' => ['alias' => true, 'alias_for' => 'created_at_before', 'needs_context' => true],
|
||||
'created_on_after' => ['alias' => true, 'alias_for' => 'created_at_after', 'needs_context' => true],
|
||||
'updated_on_on' => ['alias' => true, 'alias_for' => 'updated_at_on', 'needs_context' => true],
|
||||
'updated_on' => ['alias' => true, 'alias_for' => 'updated_at', 'needs_context' => true],
|
||||
'updated_on_before' => ['alias' => true, 'alias_for' => 'updated_at_before', 'needs_context' => true],
|
||||
'updated_on_after' => ['alias' => true, 'alias_for' => 'updated_at_after', 'needs_context' => true],
|
||||
'amount_is' => ['alias' => false, 'needs_context' => true],
|
||||
'amount' => ['alias' => true, 'alias_for' => 'amount_is', 'needs_context' => true],
|
||||
'amount_exactly' => ['alias' => true, 'alias_for' => 'amount_is', 'needs_context' => true],
|
||||
'amount_less' => ['alias' => false, 'needs_context' => true],
|
||||
'amount_max' => ['alias' => true, 'alias_for' => 'amount_less', 'needs_context' => true],
|
||||
'less' => ['alias' => true, 'alias_for' => 'amount_less', 'needs_context' => true],
|
||||
'amount_more' => ['alias' => false, 'needs_context' => true],
|
||||
'amount_min' => ['alias' => true, 'alias_for' => 'amount_more', 'needs_context' => true],
|
||||
'more' => ['alias' => true, 'alias_for' => 'amount_more', 'needs_context' => true],
|
||||
'foreign_amount_is' => ['alias' => false, 'needs_context' => true],
|
||||
'foreign_amount' => ['alias' => true, 'alias_for' => 'foreign_amount_is', 'needs_context' => true],
|
||||
'foreign_amount_less' => ['alias' => false, 'needs_context' => true],
|
||||
'foreign_amount_max' => ['alias' => true, 'alias_for' => 'foreign_amount_less', 'needs_context' => true],
|
||||
'foreign_amount_more' => ['alias' => false, 'needs_context' => true],
|
||||
'foreign_amount_min' => ['alias' => true, 'alias_for' => 'foreign_amount_more', 'needs_context' => true],
|
||||
'attachment_name_is' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment' => ['alias' => true, 'alias_for' => 'attachment_name_is', 'needs_context' => true],
|
||||
'attachment_is' => ['alias' => true, 'alias_for' => 'attachment_name_is', 'needs_context' => true],
|
||||
'attachment_name' => ['alias' => true, 'alias_for' => 'attachment_name_is', 'needs_context' => true],
|
||||
'attachment_name_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_name_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_name_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes' => ['alias' => true, 'alias_for' => 'attachment_notes_are', 'needs_context' => true],
|
||||
'attachment_notes_are' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_contains' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_contain' => ['alias' => true, 'alias_for' => 'attachment_notes_contains', 'needs_context' => true],
|
||||
'attachment_notes_starts' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_start' => ['alias' => true, 'alias_for' => 'attachment_notes_starts', 'needs_context' => true],
|
||||
'attachment_notes_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_end' => ['alias' => true, 'alias_for' => 'attachment_notes_ends', 'needs_context' => true],
|
||||
'exists' => ['alias' => false, 'needs_context' => false],
|
||||
'sepa_ct_is' => ['alias' => false, 'needs_context' => true],
|
||||
'no_external_id' => ['alias' => false, 'needs_context' => false],
|
||||
'any_external_id' => ['alias' => false, 'needs_context' => false],
|
||||
'has_any_external_id' => ['alias' => true, 'alias_for' => 'any_external_id', 'needs_context' => false],
|
||||
|
||||
// based on source or destination balance. Very heavy search.
|
||||
'source_balance_gte' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_gt' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_lte' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_lt' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_is' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_gte' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_gt' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_lte' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_lt' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_is' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_gte' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_gt' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_lte' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_lt' => ['alias' => false, 'needs_context' => true],
|
||||
'source_balance_is' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_gte' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_gt' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_lte' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_lt' => ['alias' => false, 'needs_context' => true],
|
||||
'destination_balance_is' => ['alias' => false, 'needs_context' => true],
|
||||
],
|
||||
// Which query parser to use - 'new' or 'legacy'
|
||||
'query_parser' => env('QUERY_PARSER_IMPLEMENTATION', 'legacy'),
|
||||
'query_parser' => env('QUERY_PARSER_IMPLEMENTATION', 'legacy'),
|
||||
];
|
||||
|
||||
24
package-lock.json
generated
24
package-lock.json
generated
@@ -5700,9 +5700,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.195",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.195.tgz",
|
||||
"integrity": "sha512-URclP0iIaDUzqcAyV1v2PgduJ9N0IdXmWsnPzPfelvBmjmZzEy6xJcjb1cXj+TbYqXgtLrjHEoaSIdTYhw4ezg==",
|
||||
"version": "1.5.198",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.198.tgz",
|
||||
"integrity": "sha512-G5COfnp3w+ydVu80yprgWSfmfQaYRh9DOxfhAxstLyetKaLyl55QrNjx8C38Pc/C+RaDmb1M0Lk8wPEMQ+bGgQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
@@ -5757,9 +5757,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.18.2",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz",
|
||||
"integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
|
||||
"version": "5.18.3",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
||||
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -10214,9 +10214,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.89.2",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz",
|
||||
"integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==",
|
||||
"version": "1.90.0",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.90.0.tgz",
|
||||
"integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -12459,9 +12459,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
|
||||
"integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
|
||||
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
|
||||
@@ -1,154 +1,154 @@
|
||||
{
|
||||
"firefly": {
|
||||
"administrations_page_title": "Financial administrations",
|
||||
"administrations_index_menu": "Financial administrations",
|
||||
"expires_at": "Expires at",
|
||||
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its primary currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
|
||||
"administration_currency_form_help": "It may take a long time for the page to load if you change the primary currency because transaction may need to be converted to your (new) primary currency.",
|
||||
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
|
||||
"table": "Table",
|
||||
"welcome_back": "What's playing?",
|
||||
"flash_error": "Error!",
|
||||
"flash_warning": "Warning!",
|
||||
"flash_success": "Success!",
|
||||
"close": "Close",
|
||||
"select_dest_account": "Please select or type a valid destination account name",
|
||||
"select_source_account": "Please select or type a valid source account name",
|
||||
"split_transaction_title": "Description of the split transaction",
|
||||
"errors_submission": "There was something wrong with your submission. Please check out the errors below.",
|
||||
"is_reconciled": "Is reconciled",
|
||||
"split": "Split",
|
||||
"single_split": "Split",
|
||||
"not_enough_currencies": "Not enough currencies",
|
||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID} (\"{title}\")<\/a> has been stored.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID} (\"{title}\")<\/a> has been stored.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID}<\/a> (\"{title}\") has been updated.",
|
||||
"transaction_updated_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID}<\/a> (\"{title}\") has been updated.",
|
||||
"transaction_new_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID}<\/a> has been stored.",
|
||||
"transaction_journal_information": "Transaction information",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"no_budget_pointer": "You seem to have no budgets yet. You should create some on the <a href=\"budgets\">budgets<\/a>-page. Budgets can help you keep track of expenses.",
|
||||
"no_bill_pointer": "You seem to have no subscription yet. You should create some on the <a href=\"subscriptions\">subscription<\/a>-page. Subscriptions can help you keep track of expenses.",
|
||||
"source_account": "Source account",
|
||||
"hidden_fields_preferences": "You can enable more transaction options in your <a href=\"preferences\">preferences<\/a>.",
|
||||
"destination_account": "Destination account",
|
||||
"add_another_split": "Add another split",
|
||||
"submission": "Submission",
|
||||
"stored_journal": "Successfully created new transaction \":description\"",
|
||||
"create_another": "After storing, return here to create another one.",
|
||||
"reset_after": "Reset form after submission",
|
||||
"submit": "Submit",
|
||||
"amount": "Amount",
|
||||
"date": "Date",
|
||||
"is_reconciled_fields_dropped": "Because this transaction is reconciled, you will not be able to update the accounts, nor the amount(s) unless you remove the reconciliation flag.",
|
||||
"tags": "Tags",
|
||||
"no_budget": "(no budget)",
|
||||
"no_bill": "(no subscription)",
|
||||
"category": "Category",
|
||||
"attachments": "Attachments",
|
||||
"notes": "Notes",
|
||||
"external_url": "External URL",
|
||||
"update_transaction": "Update transaction",
|
||||
"after_update_create_another": "After updating, return here to continue editing.",
|
||||
"store_as_new": "Store as a new transaction instead of updating.",
|
||||
"split_title_help": "If you create a split transaction, there must be a global description for all splits of the transaction.",
|
||||
"none_in_select_list": "(none)",
|
||||
"no_piggy_bank": "(no piggy bank)",
|
||||
"description": "Description",
|
||||
"split_transaction_title_help": "If you create a split transaction, there must be a global description for all splits of the transaction.",
|
||||
"destination_account_reconciliation": "You can't edit the destination account of a reconciliation transaction.",
|
||||
"source_account_reconciliation": "You can't edit the source account of a reconciliation transaction.",
|
||||
"budget": "Budget",
|
||||
"bill": "Subscription",
|
||||
"you_create_withdrawal": "You're creating a withdrawal.",
|
||||
"you_create_transfer": "You're creating a transfer.",
|
||||
"you_create_deposit": "You're creating a deposit.",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"name": "Name",
|
||||
"profile_whoops": "Whoops!",
|
||||
"profile_something_wrong": "Something went wrong!",
|
||||
"profile_try_again": "Something went wrong. Please try again.",
|
||||
"profile_oauth_clients": "OAuth Clients",
|
||||
"profile_oauth_no_clients": "You have not created any OAuth clients.",
|
||||
"profile_oauth_clients_header": "Clients",
|
||||
"profile_oauth_client_id": "Client ID",
|
||||
"profile_oauth_client_name": "Name",
|
||||
"profile_oauth_client_secret": "Secret",
|
||||
"profile_oauth_create_new_client": "Create New Client",
|
||||
"profile_oauth_create_client": "Create Client",
|
||||
"profile_oauth_edit_client": "Edit Client",
|
||||
"profile_oauth_name_help": "Something your users will recognize and trust.",
|
||||
"profile_oauth_redirect_url": "Redirect URL",
|
||||
"profile_oauth_clients_external_auth": "If you're using an external authentication provider like Authelia, OAuth Clients will not work. You can use Personal Access Tokens only.",
|
||||
"profile_oauth_redirect_url_help": "Your application's authorization callback URL.",
|
||||
"profile_authorized_apps": "Authorized applications",
|
||||
"profile_authorized_clients": "Authorized clients",
|
||||
"profile_scopes": "Scopes",
|
||||
"profile_revoke": "Revoke",
|
||||
"profile_personal_access_tokens": "Personal Access Tokens",
|
||||
"profile_personal_access_token": "Personal Access Token",
|
||||
"profile_personal_access_token_explanation": "Here is your new personal access token. This is the only time it will be shown so don't lose it! You may now use this token to make API requests.",
|
||||
"profile_no_personal_access_token": "You have not created any personal access tokens.",
|
||||
"profile_create_new_token": "Create new token",
|
||||
"profile_create_token": "Create token",
|
||||
"profile_create": "Create",
|
||||
"profile_save_changes": "Save changes",
|
||||
"default_group_title_name": "(ungrouped)",
|
||||
"piggy_bank": "Piggy bank",
|
||||
"profile_oauth_client_secret_title": "Client Secret",
|
||||
"profile_oauth_client_secret_expl": "Here is your new client secret. This is the only time it will be shown so don't lose it! You may now use this secret to make API requests.",
|
||||
"profile_oauth_confidential": "Confidential",
|
||||
"profile_oauth_confidential_help": "Require the client to authenticate with a secret. Confidential clients can hold credentials in a secure way without exposing them to unauthorized parties. Public applications, such as primary desktop or JavaScript SPA applications, are unable to hold secrets securely.",
|
||||
"multi_account_warning_unknown": "Depending on the type of transaction you create, the source and\/or destination account of subsequent splits may be overruled by whatever is defined in the first split of the transaction.",
|
||||
"multi_account_warning_withdrawal": "Keep in mind that the source account of subsequent splits will be overruled by whatever is defined in the first split of the withdrawal.",
|
||||
"multi_account_warning_deposit": "Keep in mind that the destination account of subsequent splits will be overruled by whatever is defined in the first split of the deposit.",
|
||||
"multi_account_warning_transfer": "Keep in mind that the source + destination account of subsequent splits will be overruled by whatever is defined in the first split of the transfer.",
|
||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||
"webhook_response_ACCOUNTS": "Account details",
|
||||
"webhook_response_none_NONE": "No details",
|
||||
"administrations_page_title": "\u0627\u0644\u0625\u062f\u0627\u0631\u0627\u062a \u0627\u0644\u0645\u0627\u0644\u064a\u0629",
|
||||
"administrations_index_menu": "\u0627\u0644\u0625\u062f\u0627\u0631\u0627\u062a \u0627\u0644\u0645\u0627\u0644\u064a\u0629",
|
||||
"expires_at": "\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0627\u0646\u062a\u0647\u0627\u0621",
|
||||
"temp_administrations_introduction": "\u0633\u064a\u062d\u0635\u0644 Firefly III \u0642\u0631\u064a\u0628\u0627\u064b \u0639\u0644\u0649 \u0625\u0645\u0643\u0627\u0646\u064a\u0629 \u0625\u062f\u0627\u0631\u0629 \u0639\u062f\u0629 \u0625\u062f\u0627\u0631\u0627\u062a \u0645\u0627\u0644\u064a\u0629. \u062d\u0627\u0644\u064a\u0627\u064b \u0644\u062f\u064a\u0643 \u0648\u0627\u062d\u062f\u0629 \u0641\u0642\u0637. \u064a\u0645\u0643\u0646\u0643 \u062a\u0639\u064a\u064a\u0646 \u0639\u0646\u0648\u0627\u0646 \u0647\u0630\u0647 \u0627\u0644\u0625\u062f\u0627\u0631\u0629 \u0648\u0639\u0645\u0644\u062a\u0647\u0627 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629. \u0647\u0630\u0627 \u064a\u0633\u062a\u0628\u062f\u0644 \u0627\u0644\u0625\u0639\u062f\u0627\u062f \u0627\u0644\u0633\u0627\u0628\u0642 \u062d\u064a\u062b \u0643\u0646\u062a \u062a\u0639\u064a\u0646 \"\u0627\u0644\u0639\u0645\u0644\u0629 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a\u0629\". \u0647\u0630\u0627 \u0627\u0644\u0625\u0639\u062f\u0627\u062f \u0623\u0635\u0628\u062d \u0627\u0644\u0622\u0646 \u0645\u0631\u062a\u0628\u0637\u0627\u064b \u0628\u0627\u0644\u0625\u062f\u0627\u0631\u0629 \u0627\u0644\u0645\u0627\u0644\u064a\u0629 \u0648\u064a\u0645\u0643\u0646 \u0623\u0646 \u064a\u062e\u062a\u0644\u0641 \u0644\u0643\u0644 \u0625\u062f\u0627\u0631\u0629.",
|
||||
"administration_currency_form_help": "\u0642\u062f \u064a\u0633\u062a\u063a\u0631\u0642 \u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0635\u0641\u062d\u0629 \u0648\u0642\u062a\u0627\u064b \u0637\u0648\u064a\u0644\u0627\u064b \u0625\u0630\u0627 \u0642\u0645\u062a \u0628\u062a\u063a\u064a\u064a\u0631 \u0627\u0644\u0639\u0645\u0644\u0629 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629 \u0644\u0623\u0646 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0642\u062f \u062a\u062d\u062a\u0627\u062c \u0625\u0644\u0649 \u0627\u0644\u062a\u062d\u0648\u064a\u0644 \u0625\u0644\u0649 \u0639\u0645\u0644\u062a\u0643 (\u0627\u0644\u062c\u062f\u064a\u062f\u0629) \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629.",
|
||||
"administrations_page_edit_sub_title_js": "\u062a\u0639\u062f\u064a\u0644 \u0627\u0644\u0625\u062f\u0627\u0631\u0629 \u0627\u0644\u0645\u0627\u0644\u064a\u0629 \"{title}\"",
|
||||
"table": "\u062c\u062f\u0648\u0644",
|
||||
"welcome_back": "\u0623\u0647\u0644\u0627\u064b \u0648\u0633\u0647\u0644\u0627\u064b!",
|
||||
"flash_error": "\u062e\u0637\u0623!",
|
||||
"flash_warning": "\u062a\u062d\u0630\u064a\u0631!",
|
||||
"flash_success": "\u0646\u062c\u062d!",
|
||||
"close": "\u0625\u063a\u0644\u0627\u0642",
|
||||
"select_dest_account": "\u064a\u0631\u062c\u0649 \u0627\u062e\u062a\u064a\u0627\u0631 \u0623\u0648 \u0643\u062a\u0627\u0628\u0629 \u0627\u0633\u0645 \u062d\u0633\u0627\u0628 \u0648\u062c\u0647\u0629 \u0635\u0627\u0644\u062d",
|
||||
"select_source_account": "\u064a\u0631\u062c\u0649 \u0627\u062e\u062a\u064a\u0627\u0631 \u0623\u0648 \u0643\u062a\u0627\u0628\u0629 \u0627\u0633\u0645 \u062d\u0633\u0627\u0628 \u0645\u0635\u062f\u0631 \u0635\u0627\u0644\u062d",
|
||||
"split_transaction_title": "\u0648\u0635\u0641 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u0645\u0646\u0642\u0633\u0645\u0629",
|
||||
"errors_submission": "\u0643\u0627\u0646 \u0647\u0646\u0627\u0643 \u062e\u0637\u0623 \u0645\u0627 \u0641\u064a \u062a\u0642\u062f\u064a\u0645\u0643. \u064a\u0631\u062c\u0649 \u0627\u0644\u062a\u062d\u0642\u0642 \u0645\u0646 \u0627\u0644\u0623\u062e\u0637\u0627\u0621 \u0623\u062f\u0646\u0627\u0647.",
|
||||
"is_reconciled": "\u062a\u0645\u062a \u0627\u0644\u062a\u0633\u0648\u064a\u0629",
|
||||
"split": "\u062a\u0642\u0633\u064a\u0645",
|
||||
"single_split": "\u062a\u0642\u0633\u064a\u0645",
|
||||
"not_enough_currencies": "\u0639\u062f\u062f \u0627\u0644\u0639\u0645\u0644\u0627\u062a \u063a\u064a\u0631 \u0643\u0627\u0641\u064d",
|
||||
"not_enough_currencies_enabled": "\u0625\u0630\u0627 \u0643\u0627\u0646 \u0644\u062f\u064a\u0643 \u0639\u0645\u0644\u0629 \u0648\u0627\u062d\u062f\u0629 \u0641\u0642\u0637 \u0645\u0641\u0639\u0644\u0629\u060c \u0641\u0644\u0627 \u062f\u0627\u0639\u064a \u0644\u0625\u0636\u0627\u0641\u0629 \u0623\u0633\u0639\u0627\u0631 \u0635\u0631\u0641.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">\u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 #{ID} (\"{title}\")<\/a> \u062a\u0645 \u062d\u0641\u0638\u0647\u0627.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">\u0648\u064a\u0628 \u0647\u0648\u0643 #{ID} (\"{title}\")<\/a> \u062a\u0645 \u062d\u0641\u0638\u0647.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">\u0648\u064a\u0628 \u0647\u0648\u0643 #{ID}<\/a> (\"{title}\") \u062a\u0645 \u062a\u062d\u062f\u064a\u062b\u0647.",
|
||||
"transaction_updated_link": "<a href=\"transactions\/show\/{ID}\">\u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 #{ID}<\/a> (\"{title}\") \u062a\u0645 \u062a\u062d\u062f\u064a\u062b\u0647\u0627.",
|
||||
"transaction_new_stored_link": "<a href=\"transactions\/show\/{ID}\">\u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 #{ID}<\/a> \u062a\u0645 \u062d\u0641\u0638\u0647\u0627.",
|
||||
"transaction_journal_information": "\u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||
"submission_options": "\u062e\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u0625\u0631\u0633\u0627\u0644",
|
||||
"apply_rules_checkbox": "\u062a\u0637\u0628\u064a\u0642 \u0627\u0644\u0642\u0648\u0627\u0639\u062f",
|
||||
"fire_webhooks_checkbox": "\u062a\u0634\u063a\u064a\u0644 Webhooks",
|
||||
"no_budget_pointer": "\u064a\u0628\u062f\u0648 \u0623\u0646\u0647 \u0644\u064a\u0633 \u0644\u062f\u064a\u0643 \u0645\u064a\u0632\u0627\u0646\u064a\u0627\u062a \u0628\u0639\u062f. \u064a\u062c\u0628 \u0623\u0646 \u062a\u0646\u0634\u0626 \u0628\u0639\u0636\u0647\u0627 \u0641\u064a <a href=\"budgets\">\u0635\u0641\u062d\u0629 \u0627\u0644\u0645\u064a\u0632\u0627\u0646\u064a\u0627\u062a<\/a>. \u0627\u0644\u0645\u064a\u0632\u0627\u0646\u064a\u0627\u062a \u064a\u0645\u0643\u0646 \u0623\u0646 \u062a\u0633\u0627\u0639\u062f\u0643 \u0641\u064a \u062a\u062a\u0628\u0639 \u0627\u0644\u0646\u0641\u0642\u0627\u062a.",
|
||||
"no_bill_pointer": "\u064a\u0628\u062f\u0648 \u0623\u0646\u0647 \u0644\u064a\u0633 \u0644\u062f\u064a\u0643 \u0627\u0634\u062a\u0631\u0627\u0643\u0627\u062a \u0628\u0639\u062f. \u064a\u062c\u0628 \u0623\u0646 \u062a\u0646\u0634\u0626 \u0628\u0639\u0636\u0647\u0627 \u0641\u064a <a href=\"subscriptions\">\u0635\u0641\u062d\u0629 \u0627\u0644\u0627\u0634\u062a\u0631\u0627\u0643\u0627\u062a<\/a>. \u0627\u0644\u0627\u0634\u062a\u0631\u0627\u0643\u0627\u062a \u064a\u0645\u0643\u0646 \u0623\u0646 \u062a\u0633\u0627\u0639\u062f\u0643 \u0641\u064a \u062a\u062a\u0628\u0639 \u0627\u0644\u0646\u0641\u0642\u0627\u062a.",
|
||||
"source_account": "\u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631",
|
||||
"hidden_fields_preferences": "\u064a\u0645\u0643\u0646\u0643 \u062a\u0645\u0643\u064a\u0646 \u0627\u0644\u0645\u0632\u064a\u062f \u0645\u0646 \u062e\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0641\u064a <a href=\"preferences\">\u0627\u0644\u062a\u0641\u0636\u064a\u0644\u0627\u062a<\/a> \u0627\u0644\u062e\u0627\u0635\u0629 \u0628\u0643.",
|
||||
"destination_account": "\u062d\u0633\u0627\u0628 \u0627\u0644\u0648\u062c\u0647\u0629",
|
||||
"add_another_split": "\u0625\u0636\u0627\u0641\u0629 \u062a\u0642\u0633\u064a\u0645 \u0622\u062e\u0631",
|
||||
"submission": "\u0625\u0631\u0633\u0627\u0644",
|
||||
"stored_journal": "\u062a\u0645 \u0625\u0646\u0634\u0627\u0621 \u0645\u0639\u0627\u0645\u0644\u0629 \u062c\u062f\u064a\u062f\u0629 \":description\"",
|
||||
"create_another": "\u0628\u0639\u062f \u0627\u0644\u062a\u062e\u0632\u064a\u0646\u060c \u0639\u062f \u0625\u0644\u0649 \u0647\u0646\u0627 \u0644\u0625\u0646\u0634\u0627\u0621 \u0648\u0627\u062d\u062f\u0629 \u0623\u062e\u0631\u0649.",
|
||||
"reset_after": "\u0625\u0639\u0627\u062f\u0629 \u062a\u0639\u064a\u064a\u0646 \u0627\u0644\u0646\u0645\u0648\u0630\u062c \u0628\u0639\u062f \u0627\u0644\u0625\u0631\u0633\u0627\u0644",
|
||||
"submit": "\u0625\u0631\u0633\u0627\u0644",
|
||||
"amount": "\u0627\u0644\u0645\u0628\u0644\u063a",
|
||||
"date": "\u0627\u0644\u062a\u0627\u0631\u064a\u062e",
|
||||
"is_reconciled_fields_dropped": "\u0644\u0623\u0646 \u0647\u0630\u0647 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u062a\u0645\u062a \u062a\u0633\u0648\u064a\u062a\u0647\u0627\u060c \u0644\u0646 \u062a\u062a\u0645\u0643\u0646 \u0645\u0646 \u062a\u062d\u062f\u064a\u062b \u0627\u0644\u062d\u0633\u0627\u0628\u0627\u062a \u0623\u0648 \u0627\u0644\u0645\u0628\u0627\u0644\u063a \u0625\u0644\u0627 \u0625\u0630\u0627 \u0623\u0632\u0644\u062a \u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u062a\u0633\u0648\u064a\u0629.",
|
||||
"tags": "\u0627\u0644\u0648\u0633\u0648\u0645",
|
||||
"no_budget": "(\u0644\u0627 \u062a\u0648\u062c\u062f \u0645\u064a\u0632\u0627\u0646\u064a\u0629)",
|
||||
"no_bill": "(\u0644\u0627 \u062a\u0648\u062c\u062f \u0627\u0634\u062a\u0631\u0627\u0643)",
|
||||
"category": "\u0641\u0626\u0629",
|
||||
"attachments": "\u0627\u0644\u0645\u0631\u0641\u0642\u0627\u062a",
|
||||
"notes": "\u0645\u0644\u0627\u062d\u0638\u0627\u062a",
|
||||
"external_url": "\u0631\u0627\u0628\u0637 \u062e\u0627\u0631\u062c\u064a",
|
||||
"update_transaction": "\u062a\u062d\u062f\u064a\u062b \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||
"after_update_create_another": "\u0628\u0639\u062f \u0627\u0644\u062a\u062d\u062f\u064a\u062b\u060c \u0639\u062f \u0625\u0644\u0649 \u0647\u0646\u0627 \u0644\u0645\u062a\u0627\u0628\u0639\u0629 \u0627\u0644\u062a\u062d\u0631\u064a\u0631.",
|
||||
"store_as_new": "\u062a\u062e\u0632\u064a\u0646 \u0643\u0645\u0639\u0627\u0645\u0644\u0629 \u062c\u062f\u064a\u062f\u0629 \u0628\u062f\u0644\u0627\u064b \u0645\u0646 \u0627\u0644\u062a\u062d\u062f\u064a\u062b.",
|
||||
"split_title_help": "\u0625\u0630\u0627 \u0642\u0645\u062a \u0628\u0625\u0646\u0634\u0627\u0621 \u0645\u0639\u0627\u0645\u0644\u0629 \u0645\u0646\u0642\u0633\u0645\u0629\u060c \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648\u0646 \u0647\u0646\u0627\u0643 \u0648\u0635\u0641 \u0639\u0627\u0644\u0645\u064a \u0644\u062c\u0645\u064a\u0639 \u0627\u0646\u0642\u0633\u0627\u0645\u0627\u062a \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629.",
|
||||
"none_in_select_list": "(\u0644\u0627 \u064a\u0648\u062c\u062f)",
|
||||
"no_piggy_bank": "(\u0644\u0627 \u062a\u0648\u062c\u062f \u062d\u0635\u0627\u0644\u0629)",
|
||||
"description": "\u0627\u0644\u0648\u0635\u0641",
|
||||
"split_transaction_title_help": "\u0625\u0630\u0627 \u0642\u0645\u062a \u0628\u0625\u0646\u0634\u0627\u0621 \u0645\u0639\u0627\u0645\u0644\u0629 \u0645\u0646\u0642\u0633\u0645\u0629\u060c \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648\u0646 \u0647\u0646\u0627\u0643 \u0648\u0635\u0641 \u0639\u0627\u0644\u0645\u064a \u0644\u062c\u0645\u064a\u0639 \u0627\u0646\u0642\u0633\u0627\u0645\u0627\u062a \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629.",
|
||||
"destination_account_reconciliation": "\u0644\u0627 \u064a\u0645\u0643\u0646\u0643 \u062a\u0639\u062f\u064a\u0644 \u062d\u0633\u0627\u0628 \u0627\u0644\u0648\u062c\u0647\u0629 \u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u062a\u0633\u0648\u064a\u0629.",
|
||||
"source_account_reconciliation": "\u0644\u0627 \u064a\u0645\u0643\u0646\u0643 \u062a\u0639\u062f\u064a\u0644 \u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631 \u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u062a\u0633\u0648\u064a\u0629.",
|
||||
"budget": "\u0645\u064a\u0632\u0627\u0646\u064a\u0629",
|
||||
"bill": "\u0627\u0634\u062a\u0631\u0627\u0643",
|
||||
"you_create_withdrawal": "\u0623\u0646\u062a \u062a\u0642\u0648\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u0633\u062d\u0628.",
|
||||
"you_create_transfer": "\u0623\u0646\u062a \u062a\u0642\u0648\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u062a\u062d\u0648\u064a\u0644.",
|
||||
"you_create_deposit": "\u0623\u0646\u062a \u062a\u0642\u0648\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u0625\u064a\u062f\u0627\u0639.",
|
||||
"edit": "\u062a\u0639\u062f\u064a\u0644",
|
||||
"delete": "\u062d\u0630\u0641",
|
||||
"name": "\u0627\u0644\u0627\u0633\u0645",
|
||||
"profile_whoops": "\u0639\u0630\u0631\u0627\u064b!",
|
||||
"profile_something_wrong": "\u062d\u062f\u062b \u062e\u0637\u0623 \u0645\u0627!",
|
||||
"profile_try_again": "\u062d\u062f\u062b \u062e\u0637\u0623 \u0645\u0627. \u064a\u0631\u062c\u0649 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062e\u0631\u0649.",
|
||||
"profile_oauth_clients": "\u0639\u0645\u0644\u0627\u0621 OAuth",
|
||||
"profile_oauth_no_clients": "\u0644\u0645 \u062a\u0642\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u0623\u064a \u0639\u0645\u0644\u0627\u0621 OAuth.",
|
||||
"profile_oauth_clients_header": "\u0627\u0644\u0639\u0645\u0644\u0627\u0621",
|
||||
"profile_oauth_client_id": "\u0645\u0639\u0631\u0651\u0641 \u0627\u0644\u0639\u0645\u064a\u0644",
|
||||
"profile_oauth_client_name": "\u0627\u0644\u0627\u0633\u0645",
|
||||
"profile_oauth_client_secret": "\u0627\u0644\u0633\u0631",
|
||||
"profile_oauth_create_new_client": "\u0625\u0646\u0634\u0627\u0621 \u0639\u0645\u064a\u0644 \u062c\u062f\u064a\u062f",
|
||||
"profile_oauth_create_client": "\u0625\u0646\u0634\u0627\u0621 \u0639\u0645\u064a\u0644",
|
||||
"profile_oauth_edit_client": "\u062a\u0639\u062f\u064a\u0644 \u0627\u0644\u0639\u0645\u064a\u0644",
|
||||
"profile_oauth_name_help": "\u0634\u064a\u0621 \u0633\u064a\u062a\u0639\u0631\u0641 \u0639\u0644\u064a\u0647 \u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645\u0648\u0646 \u0648\u064a\u062b\u0642\u0648\u0646 \u0628\u0647.",
|
||||
"profile_oauth_redirect_url": "\u0631\u0627\u0628\u0637 \u0625\u0639\u0627\u062f\u0629 \u0627\u0644\u062a\u0648\u062c\u064a\u0647",
|
||||
"profile_oauth_clients_external_auth": "\u0625\u0630\u0627 \u0643\u0646\u062a \u062a\u0633\u062a\u062e\u062f\u0645 \u0645\u0648\u0641\u0631 \u0645\u0635\u0627\u062f\u0642\u0629 \u062e\u0627\u0631\u062c\u064a \u0645\u062b\u0644 Authelia\u060c \u0641\u0644\u0646 \u062a\u0639\u0645\u0644 \u0639\u0645\u0644\u0627\u0621 OAuth. \u064a\u0645\u0643\u0646\u0643 \u0641\u0642\u0637 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0631\u0645\u0648\u0632 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0634\u062e\u0635\u064a\u0629.",
|
||||
"profile_oauth_redirect_url_help": "\u0631\u0627\u0628\u0637 \u0625\u0639\u0627\u062f\u0629 \u0627\u0644\u062a\u0648\u062c\u064a\u0647 \u0644\u062a\u0637\u0628\u064a\u0642\u0643.",
|
||||
"profile_authorized_apps": "\u0627\u0644\u062a\u0637\u0628\u064a\u0642\u0627\u062a \u0627\u0644\u0645\u0635\u0631\u062d \u0628\u0647\u0627",
|
||||
"profile_authorized_clients": "\u0627\u0644\u0639\u0645\u0644\u0627\u0621 \u0627\u0644\u0645\u0635\u0631\u062d \u0644\u0647\u0645",
|
||||
"profile_scopes": "\u0627\u0644\u0646\u0637\u0627\u0642\u0627\u062a",
|
||||
"profile_revoke": "\u0625\u0644\u063a\u0627\u0621",
|
||||
"profile_personal_access_tokens": "\u0631\u0645\u0648\u0632 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0634\u062e\u0635\u064a\u0629",
|
||||
"profile_personal_access_token": "\u0631\u0645\u0632 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0634\u062e\u0635\u064a",
|
||||
"profile_personal_access_token_explanation": "\u0647\u0630\u0627 \u0647\u0648 \u0631\u0645\u0632 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u0634\u062e\u0635\u064a \u0627\u0644\u062c\u062f\u064a\u062f \u0627\u0644\u062e\u0627\u0635 \u0628\u0643. \u0647\u0630\u0647 \u0647\u064a \u0627\u0644\u0645\u0631\u0629 \u0627\u0644\u0648\u062d\u064a\u062f\u0629 \u0627\u0644\u062a\u064a \u0633\u064a\u0638\u0647\u0631 \u0641\u064a\u0647\u0627 \u0641\u0644\u0627 \u062a\u0641\u0642\u062f\u0647! \u064a\u0645\u0643\u0646\u0643 \u0627\u0644\u0622\u0646 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0647\u0630\u0627 \u0627\u0644\u0631\u0645\u0632 \u0644\u0625\u062c\u0631\u0627\u0621 \u0637\u0644\u0628\u0627\u062a API.",
|
||||
"profile_no_personal_access_token": "\u0644\u0645 \u062a\u0642\u0645 \u0628\u0625\u0646\u0634\u0627\u0621 \u0623\u064a \u0631\u0645\u0648\u0632 \u0648\u0635\u0648\u0644 \u0634\u062e\u0635\u064a\u0629.",
|
||||
"profile_create_new_token": "\u0625\u0646\u0634\u0627\u0621 \u0631\u0645\u0632 \u062c\u062f\u064a\u062f",
|
||||
"profile_create_token": "\u0625\u0646\u0634\u0627\u0621 \u0631\u0645\u0632",
|
||||
"profile_create": "\u0625\u0646\u0634\u0627\u0621",
|
||||
"profile_save_changes": "\u062d\u0641\u0638 \u0627\u0644\u062a\u063a\u064a\u064a\u0631\u0627\u062a",
|
||||
"default_group_title_name": "(\u063a\u064a\u0631 \u0645\u062c\u0645\u0639)",
|
||||
"piggy_bank": "\u062d\u0635\u0627\u0644\u0629",
|
||||
"profile_oauth_client_secret_title": "\u0633\u0631 \u0627\u0644\u0639\u0645\u064a\u0644",
|
||||
"profile_oauth_client_secret_expl": "\u0647\u0630\u0627 \u0647\u0648 \u0633\u0631 \u0627\u0644\u0639\u0645\u064a\u0644 \u0627\u0644\u062c\u062f\u064a\u062f \u0627\u0644\u062e\u0627\u0635 \u0628\u0643. \u0647\u0630\u0647 \u0647\u064a \u0627\u0644\u0645\u0631\u0629 \u0627\u0644\u0648\u062d\u064a\u062f\u0629 \u0627\u0644\u062a\u064a \u0633\u064a\u0638\u0647\u0631 \u0641\u064a\u0647\u0627 \u0641\u0644\u0627 \u062a\u0641\u0642\u062f\u0647! \u064a\u0645\u0643\u0646\u0643 \u0627\u0644\u0622\u0646 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0647\u0630\u0627 \u0627\u0644\u0633\u0631 \u0644\u0625\u062c\u0631\u0627\u0621 \u0637\u0644\u0628\u0627\u062a API.",
|
||||
"profile_oauth_confidential": "\u0633\u0631\u064a",
|
||||
"profile_oauth_confidential_help": "\u064a\u062a\u0637\u0644\u0628 \u0645\u0646 \u0627\u0644\u0639\u0645\u064a\u0644 \u0627\u0644\u0645\u0635\u0627\u062f\u0642\u0629 \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0633\u0631. \u064a\u0645\u0643\u0646 \u0644\u0644\u0639\u0645\u0644\u0627\u0621 \u0627\u0644\u0633\u0631\u064a\u064a\u0646 \u0627\u0644\u0627\u062d\u062a\u0641\u0627\u0638 \u0628\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0627\u0639\u062a\u0645\u0627\u062f \u0628\u0637\u0631\u064a\u0642\u0629 \u0622\u0645\u0646\u0629 \u062f\u0648\u0646 \u0643\u0634\u0641\u0647\u0627 \u0644\u0623\u0637\u0631\u0627\u0641 \u063a\u064a\u0631 \u0645\u0635\u0631\u062d \u0644\u0647\u0627. \u0627\u0644\u062a\u0637\u0628\u064a\u0642\u0627\u062a \u0627\u0644\u0639\u0627\u0645\u0629 \u0645\u062b\u0644 \u062a\u0637\u0628\u064a\u0642\u0627\u062a \u0633\u0637\u062d \u0627\u0644\u0645\u0643\u062a\u0628 \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629 \u0623\u0648 \u062a\u0637\u0628\u064a\u0642\u0627\u062a SPA JavaScript \u063a\u064a\u0631 \u0642\u0627\u062f\u0631\u0629 \u0639\u0644\u0649 \u0627\u0644\u0627\u062d\u062a\u0641\u0627\u0638 \u0628\u0627\u0644\u0623\u0633\u0631\u0627\u0631 \u0628\u0623\u0645\u0627\u0646.",
|
||||
"multi_account_warning_unknown": "\u0627\u0639\u062a\u0645\u0627\u062f\u0627\u064b \u0639\u0644\u0649 \u0646\u0648\u0639 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u062a\u064a \u062a\u0646\u0634\u0626\u0647\u0627\u060c \u0642\u062f \u064a\u062a\u0645 \u062a\u062c\u0627\u0648\u0632 \u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631 \u0648\/\u0623\u0648 \u0627\u0644\u0648\u062c\u0647\u0629 \u0641\u064a \u0627\u0644\u062a\u0642\u0633\u064a\u0645\u0627\u062a \u0627\u0644\u0644\u0627\u062d\u0642\u0629 \u0628\u0645\u0627 \u0647\u0648 \u0645\u062d\u062f\u062f \u0641\u064a \u0623\u0648\u0644 \u062a\u0642\u0633\u064a\u0645 \u0644\u0644\u0645\u0639\u0627\u0645\u0644\u0629.",
|
||||
"multi_account_warning_withdrawal": "\u0636\u0639 \u0641\u064a \u0627\u0639\u062a\u0628\u0627\u0631\u0643 \u0623\u0646 \u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631 \u0641\u064a \u0627\u0644\u062a\u0642\u0633\u064a\u0645\u0627\u062a \u0627\u0644\u0644\u0627\u062d\u0642\u0629 \u0633\u064a\u062a\u0645 \u062a\u062c\u0627\u0648\u0632\u0647 \u0628\u0645\u0627 \u0647\u0648 \u0645\u062d\u062f\u062f \u0641\u064a \u0623\u0648\u0644 \u062a\u0642\u0633\u064a\u0645 \u0644\u0644\u0633\u062d\u0628.",
|
||||
"multi_account_warning_deposit": "\u0636\u0639 \u0641\u064a \u0627\u0639\u062a\u0628\u0627\u0631\u0643 \u0623\u0646 \u062d\u0633\u0627\u0628 \u0627\u0644\u0648\u062c\u0647\u0629 \u0641\u064a \u0627\u0644\u062a\u0642\u0633\u064a\u0645\u0627\u062a \u0627\u0644\u0644\u0627\u062d\u0642\u0629 \u0633\u064a\u062a\u0645 \u062a\u062c\u0627\u0648\u0632\u0647 \u0628\u0645\u0627 \u0647\u0648 \u0645\u062d\u062f\u062f \u0641\u064a \u0623\u0648\u0644 \u062a\u0642\u0633\u064a\u0645 \u0644\u0644\u0625\u064a\u062f\u0627\u0639.",
|
||||
"multi_account_warning_transfer": "\u0636\u0639 \u0641\u064a \u0627\u0639\u062a\u0628\u0627\u0631\u0643 \u0623\u0646 \u062d\u0633\u0627\u0628 \u0627\u0644\u0645\u0635\u062f\u0631 + \u0627\u0644\u0648\u062c\u0647\u0629 \u0641\u064a \u0627\u0644\u062a\u0642\u0633\u064a\u0645\u0627\u062a \u0627\u0644\u0644\u0627\u062d\u0642\u0629 \u0633\u064a\u062a\u0645 \u062a\u062c\u0627\u0648\u0632\u0647\u0645\u0627 \u0628\u0645\u0627 \u0647\u0648 \u0645\u062d\u062f\u062f \u0641\u064a \u0623\u0648\u0644 \u062a\u0642\u0633\u064a\u0645 \u0644\u0644\u062a\u062d\u0648\u064a\u0644.",
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u0628\u0639\u062f \u0625\u0646\u0634\u0627\u0621 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u0628\u0639\u062f \u062a\u062d\u062f\u064a\u062b \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u0628\u0639\u062f \u062d\u0630\u0641 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||
"webhook_response_TRANSACTIONS": "\u062a\u0641\u0627\u0635\u064a\u0644 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629",
|
||||
"webhook_response_ACCOUNTS": "\u062a\u0641\u0627\u0635\u064a\u0644 \u0627\u0644\u062d\u0633\u0627\u0628",
|
||||
"webhook_response_none_NONE": "\u0644\u0627 \u062a\u0648\u062c\u062f \u062a\u0641\u0627\u0635\u064a\u0644",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Actions",
|
||||
"meta_data": "Meta data",
|
||||
"webhook_messages": "Webhook message",
|
||||
"inactive": "Inactive",
|
||||
"no_webhook_messages": "There are no webhook messages",
|
||||
"inspect": "Inspect",
|
||||
"create_new_webhook": "Create new webhook",
|
||||
"webhooks": "Webhooks",
|
||||
"webhook_trigger_form_help": "Indicate on what event the webhook will trigger",
|
||||
"webhook_response_form_help": "Indicate what the webhook must submit to the URL.",
|
||||
"webhook_delivery_form_help": "Which format the webhook must deliver data in.",
|
||||
"webhook_active_form_help": "The webhook must be active or it won't be called.",
|
||||
"edit_webhook_js": "Edit webhook \"{title}\"",
|
||||
"webhook_was_triggered": "The webhook was triggered on the indicated transaction. Please wait for results to appear.",
|
||||
"view_message": "View message",
|
||||
"view_attempts": "View failed attempts",
|
||||
"message_content_title": "Webhook message content",
|
||||
"message_content_help": "This is the content of the message that was sent (or tried) using this webhook.",
|
||||
"attempt_content_title": "Webhook attempts",
|
||||
"attempt_content_help": "These are all the unsuccessful attempts of this webhook message to submit to the configured URL. After some time, Firefly III will stop trying.",
|
||||
"no_attempts": "There are no unsuccessful attempts. That's a good thing!",
|
||||
"webhook_attempt_at": "Attempt at {moment}",
|
||||
"logs": "Logs",
|
||||
"response": "Response",
|
||||
"visit_webhook_url": "Visit webhook URL",
|
||||
"reset_webhook_secret": "Reset webhook secret",
|
||||
"header_exchange_rates": "Exchange rates",
|
||||
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">the documentation<\/a>.",
|
||||
"exchange_rates_from_to": "Between {from} and {to} (and the other way around)",
|
||||
"exchange_rates_intro_rates": "Firefly III uses the following exchange rates. The inverse is automatically calculated when it is not provided. If no exchange rate exists for the date of the transaction, Firefly III will go back in time to find one. If none are present, the rate \"1\" will be used.",
|
||||
"header_exchange_rates_rates": "Exchange rates",
|
||||
"header_exchange_rates_table": "Table with exchange rates",
|
||||
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
|
||||
"add_new_rate": "Add a new exchange rate",
|
||||
"save_new_rate": "Save new rate"
|
||||
"actions": "\u0627\u0644\u0625\u062c\u0631\u0627\u0621\u0627\u062a",
|
||||
"meta_data": "\u0628\u064a\u0627\u0646\u0627\u062a \u0648\u0635\u0641\u064a\u0629",
|
||||
"webhook_messages": "\u0631\u0633\u0627\u0644\u0629 \u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||
"inactive": "\u063a\u064a\u0631 \u0646\u0634\u0637",
|
||||
"no_webhook_messages": "\u0644\u0627 \u062a\u0648\u062c\u062f \u0631\u0633\u0627\u0626\u0644 \u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||
"inspect": "\u062a\u0641\u0642\u062f",
|
||||
"create_new_webhook": "\u0625\u0646\u0634\u0627\u0621 \u0648\u064a\u0628 \u0647\u0648\u0643 \u062c\u062f\u064a\u062f",
|
||||
"webhooks": "\u0648\u064a\u0628 \u0647\u0648\u0643\u0633",
|
||||
"webhook_trigger_form_help": "\u062d\u062f\u062f \u0627\u0644\u062d\u062f\u062b \u0627\u0644\u0630\u064a \u0633\u064a\u0634\u063a\u0644 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||
"webhook_response_form_help": "\u062d\u062f\u062f \u0645\u0627 \u064a\u062c\u0628 \u0623\u0646 \u064a\u0631\u0633\u0644\u0647 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643 \u0625\u0644\u0649 \u0627\u0644\u0631\u0627\u0628\u0637.",
|
||||
"webhook_delivery_form_help": "\u062d\u062f\u062f \u0623\u064a \u0635\u064a\u063a\u0629 \u064a\u062c\u0628 \u0623\u0646 \u064a\u0631\u0633\u0644 \u0628\u0647\u0627 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a.",
|
||||
"webhook_active_form_help": "\u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648\u0646 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643 \u0646\u0634\u0637\u0627\u064b \u0648\u0625\u0644\u0627 \u0644\u0646 \u064a\u062a\u0645 \u0627\u0633\u062a\u062f\u0639\u0627\u0624\u0647.",
|
||||
"edit_webhook_js": "\u062a\u0639\u062f\u064a\u0644 \u0648\u064a\u0628 \u0647\u0648\u0643 \"{title}\"",
|
||||
"webhook_was_triggered": "\u062a\u0645 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643 \u0639\u0644\u0649 \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629 \u0627\u0644\u0645\u062d\u062f\u062f\u0629. \u064a\u0631\u062c\u0649 \u0627\u0644\u0627\u0646\u062a\u0638\u0627\u0631 \u062d\u062a\u0649 \u062a\u0638\u0647\u0631 \u0627\u0644\u0646\u062a\u0627\u0626\u062c.",
|
||||
"view_message": "\u0639\u0631\u0636 \u0627\u0644\u0631\u0633\u0627\u0644\u0629",
|
||||
"view_attempts": "\u0639\u0631\u0636 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0627\u062a \u0627\u0644\u0641\u0627\u0634\u0644\u0629",
|
||||
"message_content_title": "\u0645\u062d\u062a\u0648\u0649 \u0631\u0633\u0627\u0644\u0629 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||
"message_content_help": "\u0647\u0630\u0627 \u0647\u0648 \u0645\u062d\u062a\u0648\u0649 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u0627\u0644\u062a\u064a \u062a\u0645 \u0625\u0631\u0633\u0627\u0644\u0647\u0627 (\u0623\u0648 \u0645\u062d\u0627\u0648\u0644\u0629 \u0625\u0631\u0633\u0627\u0644\u0647\u0627) \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0647\u0630\u0627 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643.",
|
||||
"attempt_content_title": "\u0645\u062d\u0627\u0648\u0644\u0627\u062a \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||
"attempt_content_help": "\u0647\u0630\u0647 \u0647\u064a \u062c\u0645\u064a\u0639 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0627\u062a \u063a\u064a\u0631 \u0627\u0644\u0646\u0627\u062c\u062d\u0629 \u0644\u0647\u0630\u0647 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u0644\u0625\u0631\u0633\u0627\u0644\u0647\u0627 \u0625\u0644\u0649 \u0627\u0644\u0631\u0627\u0628\u0637 \u0627\u0644\u0645\u062d\u062f\u062f. \u0628\u0639\u062f \u0641\u062a\u0631\u0629\u060c \u0633\u064a\u062a\u0648\u0642\u0641 Firefly III \u0639\u0646 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0629.",
|
||||
"no_attempts": "\u0644\u0627 \u062a\u0648\u062c\u062f \u0645\u062d\u0627\u0648\u0644\u0627\u062a \u063a\u064a\u0631 \u0646\u0627\u062c\u062d\u0629. \u0647\u0630\u0627 \u0623\u0645\u0631 \u062c\u064a\u062f!",
|
||||
"webhook_attempt_at": "\u0645\u062d\u0627\u0648\u0644\u0629 \u0641\u064a {moment}",
|
||||
"logs": "\u0627\u0644\u0633\u062c\u0644\u0627\u062a",
|
||||
"response": "\u0627\u0644\u0627\u0633\u062a\u062c\u0627\u0628\u0629",
|
||||
"visit_webhook_url": "\u0632\u064a\u0627\u0631\u0629 \u0631\u0627\u0628\u0637 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||
"reset_webhook_secret": "\u0625\u0639\u0627\u062f\u0629 \u062a\u0639\u064a\u064a\u0646 \u0633\u0631 \u0627\u0644\u0648\u064a\u0628 \u0647\u0648\u0643",
|
||||
"header_exchange_rates": "\u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641",
|
||||
"exchange_rates_intro": "\u064a\u062f\u0639\u0645 Firefly III \u062a\u0646\u0632\u064a\u0644 \u0648\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641. \u0627\u0642\u0631\u0623 \u0627\u0644\u0645\u0632\u064a\u062f \u0639\u0646 \u0630\u0644\u0643 \u0641\u064a <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">\u0627\u0644\u0648\u062b\u0627\u0626\u0642<\/a>.",
|
||||
"exchange_rates_from_to": "\u0628\u064a\u0646 {from} \u0648{to} (\u0648\u0628\u0627\u0644\u0639\u0643\u0633)",
|
||||
"exchange_rates_intro_rates": "\u064a\u0633\u062a\u062e\u062f\u0645 Firefly III \u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641 \u0627\u0644\u062a\u0627\u0644\u064a\u0629. \u064a\u062a\u0645 \u062d\u0633\u0627\u0628 \u0627\u0644\u0639\u0643\u0633 \u062a\u0644\u0642\u0627\u0626\u064a\u0627\u064b \u0625\u0630\u0627 \u0644\u0645 \u064a\u062a\u0645 \u062a\u0648\u0641\u064a\u0631\u0647. \u0625\u0630\u0627 \u0644\u0645 \u064a\u0648\u062c\u062f \u0633\u0639\u0631 \u0635\u0631\u0641 \u0644\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0645\u0639\u0627\u0645\u0644\u0629\u060c \u0633\u064a\u0639\u0648\u062f Firefly III \u0628\u0627\u0644\u0632\u0645\u0646 \u0644\u0644\u0639\u062b\u0648\u0631 \u0639\u0644\u0649 \u0648\u0627\u062d\u062f. \u0625\u0630\u0627 \u0644\u0645 \u064a\u0648\u062c\u062f \u0623\u064a \u0633\u0639\u0631\u060c \u0633\u064a\u062a\u0645 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0627\u0644\u0633\u0639\u0631 \"1\".",
|
||||
"header_exchange_rates_rates": "\u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641",
|
||||
"header_exchange_rates_table": "\u062c\u062f\u0648\u0644 \u0623\u0633\u0639\u0627\u0631 \u0627\u0644\u0635\u0631\u0641",
|
||||
"help_rate_form": "\u0641\u064a \u0647\u0630\u0627 \u0627\u0644\u064a\u0648\u0645\u060c \u0643\u0645 {to} \u0633\u062a\u062d\u0635\u0644 \u0645\u0642\u0627\u0628\u0644 \u0648\u0627\u062d\u062f {from}\u061f",
|
||||
"add_new_rate": "\u0625\u0636\u0627\u0641\u0629 \u0633\u0639\u0631 \u0635\u0631\u0641 \u062c\u062f\u064a\u062f",
|
||||
"save_new_rate": "\u062d\u0641\u0638 \u0633\u0639\u0631 \u062c\u062f\u064a\u062f"
|
||||
},
|
||||
"form": {
|
||||
"url": "URL",
|
||||
|
||||
@@ -183,6 +183,6 @@
|
||||
},
|
||||
"config": {
|
||||
"html_language": "sv",
|
||||
"date_time_fns": "MMMM do, yyyy @ HH:mm:ss"
|
||||
"date_time_fns": "D MMMM YYYY @ HH:mm:ss"
|
||||
}
|
||||
}
|
||||
@@ -1105,7 +1105,7 @@ return [
|
||||
'rule_trigger_not_tag_is' => 'Tag is not ":trigger_value"',
|
||||
'rule_trigger_not_tag_is_not' => 'Tag is ":trigger_value"',
|
||||
'rule_trigger_not_description_is' => 'Description is not ":trigger_value"',
|
||||
'rule_trigger_not_description_contains' => 'Description does not contain',
|
||||
'rule_trigger_not_description_contains' => 'Description does not contain ":trigger_value"',
|
||||
'rule_trigger_not_description_ends' => 'Description does not end with ":trigger_value"',
|
||||
'rule_trigger_not_description_starts' => 'Description does not start with ":trigger_value"',
|
||||
'rule_trigger_not_notes_is' => 'Notes are not ":trigger_value"',
|
||||
@@ -2793,6 +2793,7 @@ return [
|
||||
'recurring_monthly' => 'Every month on the :dayOfMonth(st/nd/rd/th) day',
|
||||
'recurring_monthly_skip' => 'Every :skip(st/nd/rd/th) month on the :dayOfMonth(st/nd/rd/th) day',
|
||||
'recurring_ndom' => 'Every month on the :dayOfMonth(st/nd/rd/th) :weekday',
|
||||
'recurring_ndom_skip' => 'Every :skip(st/nd/rd/th) month on the :dayOfMonth(st/nd/rd/th) :weekday',
|
||||
'recurring_yearly' => 'Every year on :date',
|
||||
'overview_for_recurrence' => 'Overview for recurring transaction ":title"',
|
||||
'warning_duplicates_repetitions' => 'In rare instances, dates appear twice in this list. This can happen when multiple repetitions collide. Firefly III will always generate one transaction per day.',
|
||||
|
||||
73
resources/views/test/api-test.twig
Normal file
73
resources/views/test/api-test.twig
Normal file
@@ -0,0 +1,73 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Firefly III API test</title>
|
||||
<base href="{{ route('index', null, true) }}/">
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Hi there,
|
||||
</p>
|
||||
<p>
|
||||
This page is created to do some basic API testing. It's not very exciting, is it?
|
||||
</p>
|
||||
<script src="v1/js/app.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
|
||||
<script type="text/javascript" nonce="{{ JS_NONCE }}">
|
||||
$(function () {
|
||||
"use strict";
|
||||
console.log('Hello from the API test page!');
|
||||
$.ajax({
|
||||
url: 'api/v1/accounts?size=50&date=2025-08-06',
|
||||
type: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
});
|
||||
$.ajax({
|
||||
url: 'api/v1/available-budgets?size=50&date=2025-08-06',
|
||||
type: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
});
|
||||
$.ajax({
|
||||
url: 'api/v1/budgets?size=50&date=2025-08-06&start=2025-08-01&end=2025-08-31',
|
||||
type: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
});
|
||||
$.ajax({
|
||||
url: 'api/v1/budgets/1/limits?size=50&date=2025-08-06&start=2025-08-01&end=2025-08-31',
|
||||
type: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
});
|
||||
$.ajax({
|
||||
url: 'api/v1/categories?size=50&date=2025-08-06&start=2025-08-01&end=2025-08-31',
|
||||
type: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
});
|
||||
$.ajax({
|
||||
url: 'api/v1/bills?size=50&date=2025-08-06&start=2025-08-01&end=2025-08-31',
|
||||
type: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,2 +0,0 @@
|
||||
list-length: {{ listLength }}
|
||||
user-email: {{ Auth.user.email }}
|
||||
@@ -120,6 +120,7 @@ Route::group(
|
||||
Route::get('flush', ['uses' => 'DebugController@flush', 'as' => 'flush']);
|
||||
Route::get('routes', ['uses' => 'DebugController@routes', 'as' => 'routes']);
|
||||
Route::get('debug', 'DebugController@index')->name('debug');
|
||||
Route::get('debug/api-test', 'DebugController@apiTest')->name('api-test');
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user