mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-22 20:16:22 +00:00
Compare commits
19 Commits
develop-20
...
develop-20
Author | SHA1 | Date | |
---|---|---|---|
|
3a659c9a81 | ||
|
e28a988eb3 | ||
|
5566671971 | ||
|
defcc7a00c | ||
|
5183de634b | ||
|
7771b0311c | ||
|
52abe3bbc2 | ||
|
34db9f41c2 | ||
|
72c31fbe6a | ||
|
1d8dd41564 | ||
|
3409240a19 | ||
|
eccc58e75a | ||
|
24098f35bb | ||
|
e7d9dc57d8 | ||
|
f04ed5b8f0 | ||
|
8bd44f429b | ||
|
fb7866b165 | ||
|
98db6db1eb | ||
|
0a235ec523 |
2
.github/workflows/lock.yml
vendored
2
.github/workflows/lock.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
discussions: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v5
|
||||
- uses: JC5/lock-threads@v6.0.2
|
||||
with:
|
||||
issue-inactive-days: 21
|
||||
pr-inactive-days: 21
|
||||
|
@@ -47,9 +47,9 @@ class AccountController extends Controller
|
||||
use CleansChartData;
|
||||
use CollectsAccountsFromFilter;
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||
|
||||
private array $chartData;
|
||||
private array $chartData = [];
|
||||
private AccountRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
@@ -61,6 +61,7 @@ class AccountController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->validateUserGroup($request);
|
||||
$this->repository->setUserGroup($this->userGroup);
|
||||
$this->repository->setUser($this->user);
|
||||
|
||||
|
@@ -38,6 +38,7 @@ class BalanceController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->validateUserGroup($request);
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->collector = app(GroupCollectorInterface::class);
|
||||
$this->repository->setUserGroup($this->userGroup);
|
||||
|
@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
||||
use FireflyIII\Api\V1\Requests\Data\SameDateRequest;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Budget;
|
||||
@@ -67,7 +67,6 @@ class BudgetController extends Controller
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$this->validateUserGroup($request);
|
||||
$this->repository->setUserGroup($this->userGroup);
|
||||
$this->opsRepository->setUserGroup($this->userGroup);
|
||||
$this->blRepository->setUserGroup($this->userGroup);
|
||||
@@ -85,7 +84,7 @@ class BudgetController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
public function overview(SameDateRequest $request): JsonResponse
|
||||
{
|
||||
$params = $request->getAll();
|
||||
|
||||
|
@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
||||
use FireflyIII\Api\V1\Requests\Data\SameDateRequest;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
@@ -59,6 +59,7 @@ class CategoryController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->validateUserGroup($request);
|
||||
$this->accountRepos = app(AccountRepositoryInterface::class);
|
||||
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
$this->accountRepos->setUserGroup($this->userGroup);
|
||||
@@ -79,7 +80,7 @@ class CategoryController extends Controller
|
||||
*
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
public function overview(SameDateRequest $request): JsonResponse
|
||||
{
|
||||
/** @var Carbon $start */
|
||||
$start = $this->parameters->get('start');
|
||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers\Data;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
@@ -44,6 +45,20 @@ use Illuminate\Http\JsonResponse;
|
||||
*/
|
||||
class PurgeController extends Controller
|
||||
{
|
||||
protected array $acceptedRoles = [UserRoleEnum::FULL];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->validateUserGroup($request);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO cleanup and use repositories.
|
||||
*/
|
||||
|
@@ -24,15 +24,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\System;
|
||||
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\System\UpdateRequest;
|
||||
use FireflyIII\Enums\WebhookDelivery;
|
||||
use FireflyIII\Enums\WebhookResponse;
|
||||
use FireflyIII\Enums\WebhookTrigger;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Binder\EitherConfigKey;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
/**
|
||||
@@ -107,8 +110,8 @@ class ConfigurationController extends Controller
|
||||
|
||||
return [
|
||||
'is_demo_site' => $isDemoSite?->data,
|
||||
'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data,
|
||||
'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data,
|
||||
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
|
||||
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
|
||||
'single_user_mode' => $singleUser?->data,
|
||||
];
|
||||
}
|
||||
@@ -139,7 +142,20 @@ class ConfigurationController extends Controller
|
||||
'value' => $dynamic[$shortKey],
|
||||
'editable' => true,
|
||||
];
|
||||
|
||||
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
|
||||
}
|
||||
if (str_starts_with($configKey, 'webhook.')) {
|
||||
$data = [
|
||||
'title' => $configKey,
|
||||
'value' => $this->getWebhookConfiguration($configKey),
|
||||
'editable' => false,
|
||||
];
|
||||
|
||||
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
|
||||
}
|
||||
|
||||
// fallback
|
||||
if (!str_starts_with($configKey, 'configuration.')) {
|
||||
$data = [
|
||||
'title' => $configKey,
|
||||
@@ -182,4 +198,39 @@ class ConfigurationController extends Controller
|
||||
|
||||
return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
private function getWebhookConfiguration(string $configKey): array
|
||||
{
|
||||
switch ($configKey) {
|
||||
case 'webhook.triggers':
|
||||
$cases = WebhookTrigger::cases();
|
||||
$data = [];
|
||||
foreach ($cases as $c) {
|
||||
$data[$c->name] = $c->value;
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
case 'webhook.responses':
|
||||
$cases = WebhookResponse::cases();
|
||||
$data = [];
|
||||
foreach ($cases as $c) {
|
||||
$data[$c->name] = $c->value;
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
case 'webhook.deliveries':
|
||||
$cases = WebhookDelivery::cases();
|
||||
$data = [];
|
||||
foreach ($cases as $c) {
|
||||
$data[$c->name] = $c->value;
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
default:
|
||||
throw new FireflyException(sprintf('Unknown webhook configuration key "%s".', $configKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers\Webhook;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Enums\WebhookTrigger;
|
||||
use FireflyIII\Events\RequestedSendWebhookMessages;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
|
||||
@@ -146,7 +147,7 @@ class ShowController extends Controller
|
||||
$engine->setUser(auth()->user());
|
||||
|
||||
// tell the generator which trigger it should look for
|
||||
$engine->setTrigger($webhook->trigger);
|
||||
$engine->setTrigger(WebhookTrigger::tryFrom($webhook->trigger));
|
||||
// tell the generator which objects to process
|
||||
$engine->setObjects(new Collection([$group]));
|
||||
// set the webhook to trigger
|
||||
|
@@ -24,11 +24,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
||||
|
||||
use FireflyIII\Enums\WebhookResponse;
|
||||
use FireflyIII\Enums\WebhookTrigger;
|
||||
use FireflyIII\Models\Webhook;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class CreateRequest
|
||||
@@ -55,9 +59,9 @@ class CreateRequest extends FormRequest
|
||||
|
||||
// this is the way.
|
||||
$return = $this->getAllData($fields);
|
||||
$return['trigger'] = $triggers[$return['trigger']] ?? (int) $return['trigger'];
|
||||
$return['response'] = $responses[$return['response']] ?? (int) $return['response'];
|
||||
$return['delivery'] = $deliveries[$return['delivery']] ?? (int) $return['delivery'];
|
||||
$return['trigger'] = $triggers[$return['trigger']] ?? (int)$return['trigger'];
|
||||
$return['response'] = $responses[$return['response']] ?? (int)$return['response'];
|
||||
$return['delivery'] = $deliveries[$return['delivery']] ?? (int)$return['delivery'];
|
||||
|
||||
return $return;
|
||||
}
|
||||
@@ -81,4 +85,45 @@ class CreateRequest extends FormRequest
|
||||
'url' => ['required', sprintf('url:%s', $validProtocols), 'uniqueWebhook'],
|
||||
];
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator): void {
|
||||
Log::debug('Validating webhook');
|
||||
$data = $validator->getData();
|
||||
$trigger = $data['trigger'] ?? null;
|
||||
$response = $data['response'] ?? null;
|
||||
if (null === $trigger || null === $response) {
|
||||
Log::debug('No trigger or response, return.');
|
||||
|
||||
return;
|
||||
}
|
||||
$triggers = array_keys(Webhook::getTriggersForValidation());
|
||||
$responses = array_keys(Webhook::getResponsesForValidation());
|
||||
if (!in_array($trigger, $triggers, true) || !in_array($response, $responses, true)) {
|
||||
return;
|
||||
}
|
||||
// cannot deliver budget info.
|
||||
if (is_int($trigger)) {
|
||||
Log::debug(sprintf('Trigger was integer (%d).', $trigger));
|
||||
$trigger = WebhookTrigger::from($trigger)->name;
|
||||
}
|
||||
if (is_int($response)) {
|
||||
Log::debug(sprintf('Response was integer (%d).', $response));
|
||||
$response = WebhookResponse::from($response)->name;
|
||||
}
|
||||
Log::debug(sprintf('Trigger is %s, response is %s', $trigger, $response));
|
||||
if (str_contains($trigger, 'TRANSACTION') && str_contains($response, 'BUDGET')) {
|
||||
$validator->errors()->add('response', trans('validation.webhook_budget_info'));
|
||||
}
|
||||
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'ACCOUNT')) {
|
||||
$validator->errors()->add('response', trans('validation.webhook_account_info'));
|
||||
}
|
||||
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'TRANSACTION')) {
|
||||
$validator->errors()->add('response', trans('validation.webhook_transaction_info'));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -24,11 +24,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
||||
|
||||
use FireflyIII\Enums\WebhookResponse;
|
||||
use FireflyIII\Enums\WebhookTrigger;
|
||||
use FireflyIII\Models\Webhook;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class UpdateRequest
|
||||
@@ -94,4 +98,45 @@ class UpdateRequest extends FormRequest
|
||||
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
|
||||
];
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator): void {
|
||||
Log::debug('Validating webhook');
|
||||
$data = $validator->getData();
|
||||
$trigger = $data['trigger'] ?? null;
|
||||
$response = $data['response'] ?? null;
|
||||
if (null === $trigger || null === $response) {
|
||||
Log::debug('No trigger or response, return.');
|
||||
|
||||
return;
|
||||
}
|
||||
$triggers = array_keys(Webhook::getTriggersForValidation());
|
||||
$responses = array_keys(Webhook::getResponsesForValidation());
|
||||
if (!in_array($trigger, $triggers, true) || !in_array($response, $responses, true)) {
|
||||
return;
|
||||
}
|
||||
// cannot deliver budget info.
|
||||
if (is_int($trigger)) {
|
||||
Log::debug(sprintf('Trigger was integer (%d).', $trigger));
|
||||
$trigger = WebhookTrigger::from($trigger)->name;
|
||||
}
|
||||
if (is_int($response)) {
|
||||
Log::debug(sprintf('Response was integer (%d).', $response));
|
||||
$response = WebhookResponse::from($response)->name;
|
||||
}
|
||||
Log::debug(sprintf('Trigger is %s, response is %s', $trigger, $response));
|
||||
if (str_contains($trigger, 'TRANSACTION') && str_contains($response, 'BUDGET')) {
|
||||
$validator->errors()->add('response', trans('validation.webhook_budget_info'));
|
||||
}
|
||||
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'ACCOUNT')) {
|
||||
$validator->errors()->add('response', trans('validation.webhook_account_info'));
|
||||
}
|
||||
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'TRANSACTION')) {
|
||||
$validator->errors()->add('response', trans('validation.webhook_transaction_info'));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -49,14 +49,23 @@ class ValidatesEnvironmentVariables extends Command
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$this->validateLanguage();
|
||||
$this->validateGuard();
|
||||
$this->validateStaticToken();
|
||||
$result = $this->validateLanguage();
|
||||
if (false === $result) {
|
||||
return Command::FAILURE;
|
||||
}
|
||||
$result = $this->validateGuard();
|
||||
if (false === $result) {
|
||||
return Command::FAILURE;
|
||||
}
|
||||
$result = $this->validateStaticToken();
|
||||
if (false === $result) {
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
private function validateLanguage(): void
|
||||
private function validateLanguage(): bool
|
||||
{
|
||||
$language = config('firefly.default_language');
|
||||
$locale = config('firefly.default_locale');
|
||||
@@ -67,7 +76,7 @@ class ValidatesEnvironmentVariables extends Command
|
||||
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
||||
$this->friendlyError(sprintf('Valid languages are: %s', implode(', ', $options)));
|
||||
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
$options[] = 'equal';
|
||||
if (!in_array($locale, $options, true)) {
|
||||
@@ -75,11 +84,13 @@ class ValidatesEnvironmentVariables extends Command
|
||||
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
||||
$this->friendlyError(sprintf('Valid locales are: %s', implode(', ', $options)));
|
||||
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function validateGuard(): void
|
||||
private function validateGuard(): bool
|
||||
{
|
||||
$guard = config('auth.defaults.guard');
|
||||
if ('web' !== $guard && 'remote_user_guard' !== $guard) {
|
||||
@@ -87,18 +98,22 @@ class ValidatesEnvironmentVariables extends Command
|
||||
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
||||
$this->friendlyError('Valid guards are: web, remote_user_guard');
|
||||
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function validateStaticToken(): void
|
||||
private function validateStaticToken(): bool
|
||||
{
|
||||
$token = (string) config('firefly.static_cron_token');
|
||||
$token = (string)config('firefly.static_cron_token');
|
||||
if ('' !== $token && 32 !== strlen($token)) {
|
||||
$this->friendlyError('STATIC_CRON_TOKEN must be empty or a 32-character string.');
|
||||
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
||||
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -29,12 +29,16 @@ use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Safe\Exceptions\FileinfoException;
|
||||
use Safe\Exceptions\FilesystemException;
|
||||
use Safe\Exceptions\StringsException;
|
||||
|
||||
use function Safe\tempnam;
|
||||
use function Safe\file_put_contents;
|
||||
use function Safe\md5_file;
|
||||
use function Safe\mime_content_type;
|
||||
use function Safe\tempnam;
|
||||
|
||||
class ScansAttachments extends Command
|
||||
{
|
||||
@@ -46,6 +50,10 @@ class ScansAttachments extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @throws FilesystemException
|
||||
* @throws StringsException
|
||||
* @throws FileinfoException
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
@@ -57,7 +65,7 @@ class ScansAttachments extends Command
|
||||
$fileName = $attachment->fileName();
|
||||
$encryptedContent = $disk->get($fileName);
|
||||
if (null === $encryptedContent) {
|
||||
app('log')->error(sprintf('No content for attachment #%d under filename "%s"', $attachment->id, $fileName));
|
||||
Log::error(sprintf('No content for attachment #%d under filename "%s"', $attachment->id, $fileName));
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -65,18 +73,13 @@ class ScansAttachments extends Command
|
||||
try {
|
||||
$decryptedContent = Crypt::decrypt($encryptedContent); // verified
|
||||
} catch (DecryptException $e) {
|
||||
app('log')->error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage()));
|
||||
Log::error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage()));
|
||||
$decryptedContent = $encryptedContent;
|
||||
}
|
||||
$tempFileName = tempnam(sys_get_temp_dir(), 'FireflyIII');
|
||||
if (false === $tempFileName) {
|
||||
app('log')->error(sprintf('Could not create temporary file for attachment #%d', $attachment->id));
|
||||
|
||||
exit(1);
|
||||
}
|
||||
file_put_contents($tempFileName, $decryptedContent);
|
||||
$attachment->md5 = (string) md5_file($tempFileName);
|
||||
$attachment->mime = (string) mime_content_type($tempFileName);
|
||||
$attachment->md5 = (string)md5_file($tempFileName);
|
||||
$attachment->mime = (string)mime_content_type($tempFileName);
|
||||
$attachment->save();
|
||||
$this->friendlyInfo(sprintf('Fixed attachment #%d', $attachment->id));
|
||||
}
|
||||
|
@@ -31,5 +31,6 @@ enum WebhookResponse: int
|
||||
{
|
||||
case TRANSACTIONS = 200;
|
||||
case ACCOUNTS = 210;
|
||||
case BUDGET = 230;
|
||||
case NONE = 220;
|
||||
}
|
||||
|
@@ -29,10 +29,11 @@ namespace FireflyIII\Enums;
|
||||
*/
|
||||
enum WebhookTrigger: int
|
||||
{
|
||||
case STORE_TRANSACTION = 100;
|
||||
// case BEFORE_STORE_TRANSACTION = 101;
|
||||
case UPDATE_TRANSACTION = 110;
|
||||
// case BEFORE_UPDATE_TRANSACTION = 111;
|
||||
case DESTROY_TRANSACTION = 120;
|
||||
// case BEFORE_DESTROY_TRANSACTION = 121;
|
||||
case STORE_TRANSACTION = 100;
|
||||
case UPDATE_TRANSACTION = 110;
|
||||
case DESTROY_TRANSACTION = 120;
|
||||
case STORE_BUDGET = 200;
|
||||
case UPDATE_BUDGET = 210;
|
||||
case DESTROY_BUDGET = 220;
|
||||
case STORE_UPDATE_BUDGET_LIMIT = 230;
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Webhook;
|
||||
|
||||
use FireflyIII\Enums\WebhookTrigger;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
@@ -38,7 +39,7 @@ interface MessageGeneratorInterface
|
||||
|
||||
public function setObjects(Collection $objects): void;
|
||||
|
||||
public function setTrigger(int $trigger): void;
|
||||
public function setTrigger(WebhookTrigger $trigger): void;
|
||||
|
||||
public function setUser(User $user): void;
|
||||
|
||||
|
@@ -47,11 +47,11 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
*/
|
||||
class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
{
|
||||
private Collection $objects;
|
||||
private int $trigger;
|
||||
private User $user;
|
||||
private int $version = 0;
|
||||
private Collection $webhooks;
|
||||
private Collection $objects;
|
||||
private WebhookTrigger $trigger;
|
||||
private User $user;
|
||||
private int $version = 0;
|
||||
private Collection $webhooks;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -68,9 +68,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
}
|
||||
|
||||
// do some debugging
|
||||
Log::debug(
|
||||
sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count())
|
||||
);
|
||||
Log::debug(sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count()));
|
||||
$this->run();
|
||||
}
|
||||
|
||||
@@ -79,6 +77,9 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function run(): void
|
||||
{
|
||||
Log::debug('Now in StandardMessageGenerator::run');
|
||||
@@ -114,28 +115,28 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
|
||||
$uuid = Uuid::uuid4();
|
||||
$basicMessage = [
|
||||
'uuid' => $uuid->toString(),
|
||||
'user_id' => 0,
|
||||
'trigger' => WebhookTrigger::from($webhook->trigger)->name,
|
||||
'response' => WebhookResponse::from($webhook->response)->name,
|
||||
'url' => $webhook->url,
|
||||
'version' => sprintf('v%d', $this->getVersion()),
|
||||
'content' => [],
|
||||
'uuid' => $uuid->toString(),
|
||||
'user_id' => 0,
|
||||
'user_group_id' => 0,
|
||||
'trigger' => $webhook->trigger->name,
|
||||
'response' => WebhookResponse::from($webhook->response)->name,
|
||||
'url' => $webhook->url,
|
||||
'version' => sprintf('v%d', $this->getVersion()),
|
||||
'content' => [],
|
||||
];
|
||||
|
||||
// depends on the model how user_id is set:
|
||||
switch ($class) {
|
||||
default:
|
||||
// Line is ignored because all of Firefly III's Models have an id property.
|
||||
Log::error(
|
||||
sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id)
|
||||
);
|
||||
Log::error(sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id));
|
||||
|
||||
return;
|
||||
|
||||
case TransactionGroup::class:
|
||||
/** @var TransactionGroup $model */
|
||||
$basicMessage['user_id'] = $model->user->id;
|
||||
$basicMessage['user_id'] = $model->user_id;
|
||||
$basicMessage['user_group_id'] = $model->user_group_id;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -143,9 +144,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
// then depends on the response what to put in the message:
|
||||
switch ($webhook->response) {
|
||||
default:
|
||||
Log::error(
|
||||
sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response)
|
||||
);
|
||||
Log::error(sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response));
|
||||
|
||||
return;
|
||||
|
||||
@@ -224,7 +223,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
||||
$this->objects = $objects;
|
||||
}
|
||||
|
||||
public function setTrigger(int $trigger): void
|
||||
public function setTrigger(WebhookTrigger $trigger): void
|
||||
{
|
||||
$this->trigger = $trigger;
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ class DestroyedGroupEventHandler
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection([$group]));
|
||||
$engine->setTrigger(WebhookTrigger::DESTROY_TRANSACTION->value);
|
||||
$engine->setTrigger(WebhookTrigger::DESTROY_TRANSACTION);
|
||||
$engine->generateMessages();
|
||||
|
||||
event(new RequestedSendWebhookMessages());
|
||||
|
@@ -32,6 +32,7 @@ use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class StoredGroupEventHandler
|
||||
@@ -51,11 +52,11 @@ class StoredGroupEventHandler
|
||||
private function processRules(StoredTransactionGroup $storedGroupEvent): void
|
||||
{
|
||||
if (false === $storedGroupEvent->applyRules) {
|
||||
app('log')->info(sprintf('Will not run rules on group #%d', $storedGroupEvent->transactionGroup->id));
|
||||
Log::info(sprintf('Will not run rules on group #%d', $storedGroupEvent->transactionGroup->id));
|
||||
|
||||
return;
|
||||
}
|
||||
app('log')->debug('Now in StoredGroupEventHandler::processRules()');
|
||||
Log::debug('Now in StoredGroupEventHandler::processRules()');
|
||||
|
||||
$journals = $storedGroupEvent->transactionGroup->transactionJournals;
|
||||
$array = [];
|
||||
@@ -65,7 +66,7 @@ class StoredGroupEventHandler
|
||||
$array[] = $journal->id;
|
||||
}
|
||||
$journalIds = implode(',', $array);
|
||||
app('log')->debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
||||
Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
||||
|
||||
// collect rules:
|
||||
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||
@@ -98,10 +99,10 @@ class StoredGroupEventHandler
|
||||
*/
|
||||
private function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void
|
||||
{
|
||||
app('log')->debug(__METHOD__);
|
||||
Log::debug(__METHOD__);
|
||||
$group = $storedGroupEvent->transactionGroup;
|
||||
if (false === $storedGroupEvent->fireWebhooks) {
|
||||
app('log')->info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
||||
Log::info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -113,7 +114,7 @@ class StoredGroupEventHandler
|
||||
$engine->setUser($user);
|
||||
|
||||
// tell the generator which trigger it should look for
|
||||
$engine->setTrigger(WebhookTrigger::STORE_TRANSACTION->value);
|
||||
$engine->setTrigger(WebhookTrigger::STORE_TRANSACTION);
|
||||
// tell the generator which objects to process
|
||||
$engine->setObjects(new Collection([$group]));
|
||||
// tell the generator to generate the messages
|
||||
|
@@ -164,7 +164,7 @@ class UpdatedGroupEventHandler
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection([$group]));
|
||||
$engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION->value);
|
||||
$engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION);
|
||||
$engine->generateMessages();
|
||||
|
||||
event(new RequestedSendWebhookMessages());
|
||||
|
@@ -839,7 +839,7 @@ class GroupCollector implements GroupCollectorInterface
|
||||
return 'zzz';
|
||||
}
|
||||
|
||||
exit('here we are 2');
|
||||
return 'zzz';
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -36,6 +36,7 @@ use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\View\View;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
@@ -94,7 +95,7 @@ class RegisterController extends Controller
|
||||
|
||||
$this->validator($request->all())->validate();
|
||||
$user = $this->createUser($request->all());
|
||||
app('log')->info(sprintf('Registered new user %s', $user->email));
|
||||
Log::info(sprintf('Registered new user %s', $user->email));
|
||||
$owner = new OwnerNotifiable();
|
||||
event(new RegisteredUser($owner, $user));
|
||||
|
||||
|
@@ -57,6 +57,11 @@ class EitherConfigKey
|
||||
'firefly.rule-actions',
|
||||
'firefly.context-rule-actions',
|
||||
'search.operators',
|
||||
|
||||
// webhooks
|
||||
'webhook.triggers',
|
||||
'webhook.responses',
|
||||
'webhook.deliveries',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@@ -65,55 +65,27 @@ class FrontpageChartGenerator
|
||||
|
||||
public function generate(): array
|
||||
{
|
||||
Log::debug('Now in generate()');
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$categories = $this->repository->getCategories();
|
||||
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]);
|
||||
|
||||
// get expenses + income per category:
|
||||
$collection = [];
|
||||
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
// get expenses
|
||||
$collection[] = $this->collectExpenses($category, $accounts);
|
||||
}
|
||||
$collection = $this->collectExpensesAll($categories, $accounts);
|
||||
|
||||
// collect for no-category:
|
||||
$collection[] = $this->collectNoCatExpenses($accounts);
|
||||
|
||||
$tempData = array_merge(...$collection);
|
||||
$noCategory = $this->collectNoCatExpenses($accounts);
|
||||
$collection = array_merge($collection, $noCategory);
|
||||
|
||||
// sort temp array by amount.
|
||||
$amounts = array_column($tempData, 'sum_float');
|
||||
array_multisort($amounts, SORT_ASC, $tempData);
|
||||
$amounts = array_column($collection, 'sum_float');
|
||||
array_multisort($amounts, SORT_ASC, $collection);
|
||||
|
||||
$currencyData = $this->createCurrencyGroups($tempData);
|
||||
$currencyData = $this->createCurrencyGroups($collection);
|
||||
|
||||
return $this->insertValues($currencyData, $tempData);
|
||||
}
|
||||
|
||||
private function collectExpenses(Category $category, Collection $accounts): array
|
||||
{
|
||||
Log::debug(sprintf('Collect expenses for category #%d ("%s")', $category->id, $category->name));
|
||||
$spent = $this->opsRepos->sumExpenses($this->start, $this->end, $accounts, new Collection([$category]));
|
||||
$tempData = [];
|
||||
foreach ($spent as $currency) {
|
||||
Log::debug(sprintf('Spent %s %s', $currency['currency_code'], $currency['sum']));
|
||||
$this->addCurrency($currency);
|
||||
$tempData[] = [
|
||||
'name' => $category->name,
|
||||
'sum' => $currency['sum'],
|
||||
'sum_float' => round((float) $currency['sum'], $currency['currency_decimal_places']),
|
||||
'currency_id' => (int) $currency['currency_id'],
|
||||
];
|
||||
}
|
||||
|
||||
return $tempData;
|
||||
return $this->insertValues($currencyData, $collection);
|
||||
}
|
||||
|
||||
private function addCurrency(array $currency): void
|
||||
{
|
||||
$currencyId = (int) $currency['currency_id'];
|
||||
$currencyId = (int)$currency['currency_id'];
|
||||
|
||||
$this->currencies[$currencyId] ??= [
|
||||
'currency_id' => $currencyId,
|
||||
@@ -133,8 +105,8 @@ class FrontpageChartGenerator
|
||||
$tempData[] = [
|
||||
'name' => trans('firefly.no_category'),
|
||||
'sum' => $currency['sum'],
|
||||
'sum_float' => round((float) $currency['sum'], $currency['currency_decimal_places'] ?? 2), // intentional float
|
||||
'currency_id' => (int) $currency['currency_id'],
|
||||
'sum_float' => round((float)$currency['sum'], $currency['currency_decimal_places'] ?? 2), // intentional float
|
||||
'currency_id' => (int)$currency['currency_id'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -152,7 +124,7 @@ class FrontpageChartGenerator
|
||||
foreach ($this->currencies as $currencyId => $currency) {
|
||||
$key = sprintf('spent-%d', $currencyId);
|
||||
$return[$key] = [
|
||||
'label' => sprintf('%s (%s)', (string) trans('firefly.spent'), $currency['currency_name']),
|
||||
'label' => sprintf('%s (%s)', (string)trans('firefly.spent'), $currency['currency_name']),
|
||||
'type' => 'bar',
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'entries' => $names,
|
||||
@@ -175,4 +147,28 @@ class FrontpageChartGenerator
|
||||
|
||||
return $currencyData;
|
||||
}
|
||||
|
||||
private function collectExpensesAll(Collection $categories, Collection $accounts): array
|
||||
{
|
||||
Log::debug(sprintf('Collect expenses for %d category(ies).', count($categories)));
|
||||
$spent = $this->opsRepos->collectExpenses($this->start, $this->end, $accounts, $categories);
|
||||
$tempData = [];
|
||||
foreach ($categories as $category) {
|
||||
$sums = $this->opsRepos->sumCollectedTransactionsByCategory($spent, $category, 'negative', $this->convertToPrimary);
|
||||
if (0 === count($sums)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($sums as $currency) {
|
||||
$this->addCurrency($currency);
|
||||
$tempData[] = [
|
||||
'name' => $category->name,
|
||||
'sum' => $currency['sum'],
|
||||
'sum_float' => round((float)$currency['sum'], $currency['currency_decimal_places']),
|
||||
'currency_id' => (int)$currency['currency_id'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $tempData;
|
||||
}
|
||||
}
|
||||
|
@@ -73,10 +73,12 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
public function enrich(Collection $collection): Collection
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->collectIds();
|
||||
$this->collectCurrencies();
|
||||
$this->collectSpentInfo();
|
||||
$this->appendCollectedData();
|
||||
if ($this->collection->count() > 0) {
|
||||
$this->collectIds();
|
||||
$this->collectCurrencies();
|
||||
$this->collectSpentInfo();
|
||||
$this->appendCollectedData();
|
||||
}
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
@@ -85,7 +87,7 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection([$model]);
|
||||
$collection = new Collection()->push($model);
|
||||
$collection = $this->enrich($collection);
|
||||
|
||||
return $collection->first();
|
||||
@@ -119,8 +121,8 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectSpentInfo(): void
|
||||
{
|
||||
$start = $this->collection->min('start_date');
|
||||
$end = $this->collection->max('end_date');
|
||||
$start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
|
||||
$end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth();
|
||||
$allActive = $this->repository->getActiveBudgets();
|
||||
$spentInBudgets = $this->opsRepository->collectExpenses($start, $end, null, $allActive, null);
|
||||
$spentOutsideBudgets = $this->noBudgetRepository->collectExpenses($start, $end, null, null, null);
|
||||
@@ -139,14 +141,7 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
$this->pcSpentInBudgets[$id] = array_values($pcFilteredSpentInBudgets);
|
||||
$this->pcSpentOutsideBudgets[$id] = array_values($pcFilteredSpentOutsideBudgets);
|
||||
}
|
||||
|
||||
|
||||
// filter arrays on date.
|
||||
// send them to sumCollection thing.
|
||||
// save.
|
||||
}
|
||||
|
||||
// first collect, then filter and append.
|
||||
}
|
||||
|
||||
private function appendCollectedData(): void
|
||||
|
@@ -464,7 +464,7 @@ class Navigation
|
||||
$displayFormat = (string) trans('config.month_and_day_js', [], $locale);
|
||||
$diff = $start->diffInMonths($end, true);
|
||||
// increment by month (for year)
|
||||
if ($diff >= 1.0001) {
|
||||
if ($diff >= 1.0001 && $diff < 12.001) {
|
||||
$increment = 'addMonth';
|
||||
$displayFormat = (string) trans('config.month_js');
|
||||
}
|
||||
@@ -495,7 +495,7 @@ class Navigation
|
||||
$format = 'Y-m-d';
|
||||
$diff = $start->diffInMonths($end, true);
|
||||
// Log::debug(sprintf('preferredCarbonFormat(%s, %s) = %f', $start->format('Y-m-d'), $end->format('Y-m-d'), $diff));
|
||||
if ($diff >= 1.001) {
|
||||
if ($diff >= 1.001 && $diff < 12.001) {
|
||||
// Log::debug(sprintf('Return Y-m because %s', $diff));
|
||||
$format = 'Y-m';
|
||||
}
|
||||
@@ -566,7 +566,7 @@ class Navigation
|
||||
{
|
||||
$locale = app('steam')->getLocale();
|
||||
$diff = $start->diffInMonths($end, true);
|
||||
if ($diff >= 1.001) {
|
||||
if ($diff >= 1.001 && $diff < 12.001) {
|
||||
return (string) trans('config.month_js', [], $locale);
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ class Navigation
|
||||
public function preferredEndOfPeriod(Carbon $start, Carbon $end): string
|
||||
{
|
||||
$diff = $start->diffInMonths($end, true);
|
||||
if ($diff >= 1.001) {
|
||||
if ($diff >= 1.001 && $diff < 12.001) {
|
||||
return 'endOfMonth';
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ class Navigation
|
||||
public function preferredRangeFormat(Carbon $start, Carbon $end): string
|
||||
{
|
||||
$diff = $start->diffInMonths($end, true);
|
||||
if ($diff >= 1.001) {
|
||||
if ($diff >= 1.001 && $diff < 12.001) {
|
||||
return '1M';
|
||||
}
|
||||
|
||||
@@ -620,7 +620,7 @@ class Navigation
|
||||
public function preferredSqlFormat(Carbon $start, Carbon $end): string
|
||||
{
|
||||
$diff = $start->diffInMonths($end, true);
|
||||
if ($diff >= 1.001) {
|
||||
if ($diff >= 1.001 && $diff < 12.001) {
|
||||
return '%Y-%m';
|
||||
}
|
||||
|
||||
|
@@ -66,7 +66,7 @@ trait UserGroupTrait
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
if (null === $user->userGroup) {
|
||||
throw new FireflyException(sprintf('User #%d has no user group.', $user->id));
|
||||
throw new FireflyException(sprintf('User #%d ("%s") has no user group.', $user->id, $user->email));
|
||||
}
|
||||
$this->userGroup = $user->userGroup;
|
||||
|
||||
|
@@ -24,10 +24,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\Request;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
|
||||
trait GetFilterInstructions
|
||||
{
|
||||
private const string INVALID_FILTER = '%INVALID_JAMES_%';
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
final public function getFilterInstructions(string $key): array
|
||||
{
|
||||
$config = config(sprintf('firefly.filters.allowed.%s', $key));
|
||||
@@ -48,7 +53,7 @@ trait GetFilterInstructions
|
||||
|
||||
switch ($filterType) {
|
||||
default:
|
||||
exit(sprintf('Do not support filter type "%s"', $filterType));
|
||||
throw new FireflyException(sprintf('Do not support filter type "%s"', $filterType));
|
||||
|
||||
case 'boolean':
|
||||
$filterValue = $this->booleanInstruction($filterValue);
|
||||
|
@@ -74,7 +74,7 @@ class User extends Authenticatable
|
||||
use HasApiTokens;
|
||||
use Notifiable;
|
||||
use ReturnsIntegerIdTrait;
|
||||
protected $fillable = ['email', 'password', 'blocked', 'blocked_code'];
|
||||
protected $fillable = ['email', 'password', 'blocked', 'blocked_code', 'user_group_id'];
|
||||
protected $hidden = ['password', 'remember_token'];
|
||||
protected $table = 'users';
|
||||
|
||||
|
14
composer.lock
generated
14
composer.lock
generated
@@ -11771,16 +11771,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "12.3.4",
|
||||
"version": "12.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "429095031bd38cb5070ca44166bd9dd5a9245dd6"
|
||||
"reference": "f10ba5f12a256026ad3c7ee4894ffe47f60d7dc7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/429095031bd38cb5070ca44166bd9dd5a9245dd6",
|
||||
"reference": "429095031bd38cb5070ca44166bd9dd5a9245dd6",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f10ba5f12a256026ad3c7ee4894ffe47f60d7dc7",
|
||||
"reference": "f10ba5f12a256026ad3c7ee4894ffe47f60d7dc7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11802,7 +11802,7 @@
|
||||
"sebastian/cli-parser": "^4.0.0",
|
||||
"sebastian/comparator": "^7.1.2",
|
||||
"sebastian/diff": "^7.0.0",
|
||||
"sebastian/environment": "^8.0.2",
|
||||
"sebastian/environment": "^8.0.3",
|
||||
"sebastian/exporter": "^7.0.0",
|
||||
"sebastian/global-state": "^8.0.0",
|
||||
"sebastian/object-enumerator": "^7.0.0",
|
||||
@@ -11848,7 +11848,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.4"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11872,7 +11872,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-08-12T07:35:30+00:00"
|
||||
"time": "2025-08-16T05:20:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
|
@@ -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-16',
|
||||
'build_time' => 1755317476,
|
||||
'version' => 'develop/2025-08-17',
|
||||
'build_time' => 1755423185,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 26,
|
||||
|
||||
|
@@ -57,6 +57,7 @@ return [
|
||||
'liability_direction_credit_short',
|
||||
'liability_direction_null_short',
|
||||
'interest_calc_yearly',
|
||||
'loading',
|
||||
'interest_calc_',
|
||||
'interest_calc_null',
|
||||
'interest_calc_daily',
|
||||
@@ -246,12 +247,19 @@ return [
|
||||
'multi_account_warning_withdrawal',
|
||||
'multi_account_warning_deposit',
|
||||
'multi_account_warning_transfer',
|
||||
|
||||
'webhook_trigger_STORE_TRANSACTION',
|
||||
'webhook_trigger_UPDATE_TRANSACTION',
|
||||
'webhook_trigger_DESTROY_TRANSACTION',
|
||||
|
||||
'webhook_trigger_STORE_BUDGET',
|
||||
'webhook_trigger_UPDATE_BUDGET',
|
||||
'webhook_trigger_DESTROY_BUDGET',
|
||||
'webhook_trigger_STORE_UPDATE_BUDGET_LIMIT',
|
||||
|
||||
'webhook_response_TRANSACTIONS',
|
||||
'webhook_response_ACCOUNTS',
|
||||
'webhook_response_none_NONE',
|
||||
'webhook_response_NONE',
|
||||
'webhook_delivery_JSON',
|
||||
'actions',
|
||||
'meta_data',
|
||||
|
@@ -31,12 +31,18 @@
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
processIsolation="false"
|
||||
stopOnError="true"
|
||||
stopOnFailure="true">
|
||||
<php>
|
||||
<env name="APP_ENV" value="testing"/>
|
||||
<env name="DB_CONNECTION" value="sqlite"/>
|
||||
<env name="APP_LOG_ENV" value="notice"/>
|
||||
<env name="DB_DATABASE" value=""/>
|
||||
<env name="APP_LOG_LEVEL" value="notice"/>
|
||||
<env name="AUDIT_LOG_LEVEL" value="emergency" />
|
||||
|
||||
|
||||
<env name="QUERY_PARSER_IMPLEMENTATION" value="new"/>
|
||||
<ini name="xdebug.mode" value="coverage"/>
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="unit">
|
||||
|
@@ -24,7 +24,10 @@
|
||||
{{ $t('form.webhook_delivery') }}
|
||||
</label>
|
||||
<div class="col-sm-8">
|
||||
<select
|
||||
<div v-if="loading" class="form-control-static">
|
||||
<em class="fa fa-spinner fa-spin"></em> {{ $t('firefly.loading') }}
|
||||
</div>
|
||||
<select v-if="!loading"
|
||||
ref="bill"
|
||||
v-model="delivery"
|
||||
:title="$t('form.webhook_delivery')"
|
||||
@@ -49,6 +52,7 @@ export default {
|
||||
name: "WebhookDelivery",
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
delivery : 0,
|
||||
deliveries: [
|
||||
|
||||
@@ -71,8 +75,24 @@ export default {
|
||||
mounted() {
|
||||
this.delivery = this.value;
|
||||
this.deliveries = [
|
||||
{id: 300, name: this.$t('firefly.webhook_delivery_JSON')},
|
||||
//{id: 300, name: this.$t('firefly.webhook_delivery_JSON')},
|
||||
];
|
||||
axios.get('./api/v1/configuration/webhook.deliveries').then((response) => {
|
||||
for (let key in response.data.data.value) {
|
||||
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
this.deliveries.push(
|
||||
{
|
||||
id: response.data.data.value[key],
|
||||
name: this.$t('firefly.webhook_delivery_' + key),
|
||||
}
|
||||
);
|
||||
}
|
||||
this.loading = false;
|
||||
}).catch((error) => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
|
@@ -19,73 +19,89 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
||||
<label class="col-sm-4 control-label">
|
||||
{{ $t('form.webhook_response') }}
|
||||
</label>
|
||||
<div class="col-sm-8">
|
||||
<select
|
||||
ref="bill"
|
||||
v-model="response"
|
||||
:title="$t('form.webhook_response')"
|
||||
class="form-control"
|
||||
name="webhook_response"
|
||||
>
|
||||
<option v-for="response in this.responses"
|
||||
:label="response.name"
|
||||
:value="response.id">{{ response.name }}
|
||||
</option>
|
||||
</select>
|
||||
<p class="help-block" v-text="$t('firefly.webhook_response_form_help')"></p>
|
||||
<ul v-for="error in this.error" class="list-unstyled">
|
||||
<li class="text-danger">{{ error }}</li>
|
||||
</ul>
|
||||
<div class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
||||
<label class="col-sm-4 control-label">
|
||||
{{ $t('form.webhook_response') }}
|
||||
</label>
|
||||
<div class="col-sm-8">
|
||||
<div v-if="loading" class="form-control-static">
|
||||
<em class="fa fa-spinner fa-spin"></em> {{ $t('firefly.loading') }}
|
||||
</div>
|
||||
<select v-if="!loading"
|
||||
ref="response"
|
||||
v-model="response"
|
||||
:title="$t('form.webhook_response')"
|
||||
class="form-control"
|
||||
name="webhook_response"
|
||||
>
|
||||
<option v-for="response in this.responses"
|
||||
:label="response.name"
|
||||
:value="response.id">{{ response.name }}
|
||||
</option>
|
||||
</select>
|
||||
<p class="help-block" v-text="$t('firefly.webhook_response_form_help')"></p>
|
||||
<ul v-for="error in this.error" class="list-unstyled">
|
||||
<li class="text-danger">{{ error }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "WebhookResponse",
|
||||
data() {
|
||||
return {
|
||||
response: 0,
|
||||
responses: [],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
error: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
name: "WebhookResponse",
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
response: 0,
|
||||
responses: [],
|
||||
};
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
this.response = this.value;
|
||||
props: {
|
||||
error: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
this.response = this.value;
|
||||
},
|
||||
response(newValue) {
|
||||
this.$emit('input', newValue);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.response = this.value;
|
||||
this.responses = [];
|
||||
axios.get('./api/v1/configuration/webhook.responses').then((response) => {
|
||||
for (let key in response.data.data.value) {
|
||||
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
this.responses.push(
|
||||
{
|
||||
id: response.data.data.value[key],
|
||||
name: this.$t('firefly.webhook_response_' + key),
|
||||
}
|
||||
);
|
||||
}
|
||||
this.loading = false;
|
||||
}).catch((error) => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
hasError() {
|
||||
return this.error?.length > 0;
|
||||
}
|
||||
},
|
||||
response(newValue) {
|
||||
this.$emit('input', newValue);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.response = this.value;
|
||||
this.responses = [
|
||||
{id: 200, name: this.$t('firefly.webhook_response_TRANSACTIONS')},
|
||||
{id: 210, name: this.$t('firefly.webhook_response_ACCOUNTS')},
|
||||
{id: 220, name: this.$t('firefly.webhook_response_none_NONE')},
|
||||
];
|
||||
},
|
||||
methods: {
|
||||
hasError() {
|
||||
return this.error?.length > 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@@ -19,73 +19,90 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
||||
<label class="col-sm-4 control-label">
|
||||
{{ $t('form.webhook_trigger') }}
|
||||
</label>
|
||||
<div class="col-sm-8">
|
||||
<select
|
||||
ref="bill"
|
||||
v-model="trigger"
|
||||
:title="$t('form.webhook_trigger')"
|
||||
class="form-control"
|
||||
name="webhook_trigger"
|
||||
>
|
||||
<option v-for="trigger in this.triggers"
|
||||
:label="trigger.name"
|
||||
:value="trigger.id">{{ trigger.name }}
|
||||
</option>
|
||||
</select>
|
||||
<p class="help-block" v-text="$t('firefly.webhook_trigger_form_help')"></p>
|
||||
<ul v-for="error in this.error" class="list-unstyled">
|
||||
<li class="text-danger">{{ error }}</li>
|
||||
</ul>
|
||||
<div class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
||||
<label class="col-sm-4 control-label">
|
||||
{{ $t('form.webhook_trigger') }}
|
||||
</label>
|
||||
<div class="col-sm-8">
|
||||
<div v-if="loading" class="form-control-static">
|
||||
<em class="fa fa-spinner fa-spin"></em> {{ $t('firefly.loading') }}
|
||||
</div>
|
||||
<select v-if="!loading"
|
||||
ref="trigger"
|
||||
v-model="trigger"
|
||||
:title="$t('form.webhook_trigger')"
|
||||
class="form-control"
|
||||
name="webhook_trigger"
|
||||
>
|
||||
<option v-for="trigger in this.triggers"
|
||||
:label="trigger.name"
|
||||
:value="trigger.id">{{ trigger.name }}
|
||||
</option>
|
||||
</select>
|
||||
<p class="help-block" v-text="$t('firefly.webhook_trigger_form_help')"></p>
|
||||
<ul v-for="error in this.error" class="list-unstyled">
|
||||
<li class="text-danger">{{ error }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "WebhookTrigger",
|
||||
data() {
|
||||
return {
|
||||
trigger: 0,
|
||||
triggers: [],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
error: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
name: "WebhookTrigger",
|
||||
data() {
|
||||
return {
|
||||
trigger: 0,
|
||||
loading: true,
|
||||
triggers: [],
|
||||
};
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trigger = this.value;
|
||||
this.triggers = [
|
||||
{id: 100, name: this.$t('firefly.webhook_trigger_STORE_TRANSACTION')},
|
||||
{id: 110, name: this.$t('firefly.webhook_trigger_UPDATE_TRANSACTION')},
|
||||
{id: 120, name: this.$t('firefly.webhook_trigger_DESTROY_TRANSACTION')},
|
||||
];
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
this.trigger = this.value;
|
||||
props: {
|
||||
error: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trigger = this.value;
|
||||
this.triggers = [];
|
||||
axios.get('./api/v1/configuration/webhook.triggers').then((response) => {
|
||||
for (let key in response.data.data.value) {
|
||||
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
this.triggers.push(
|
||||
{
|
||||
id: response.data.data.value[key],
|
||||
name: this.$t('firefly.webhook_trigger_' + key),
|
||||
}
|
||||
);
|
||||
console.log('webhook trigger: id=' + response.data.data.value[key] + ', name=' + key);
|
||||
}
|
||||
this.loading = false;
|
||||
}).catch((error) => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
this.trigger = this.value;
|
||||
},
|
||||
trigger(newValue) {
|
||||
this.$emit('input', newValue);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hasError() {
|
||||
return this.error?.length > 0;
|
||||
}
|
||||
},
|
||||
trigger(newValue) {
|
||||
this.$emit('input', newValue);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hasError() {
|
||||
return this.error?.length > 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@@ -19,138 +19,172 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
{{ $t('firefly.webhooks') }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="box-body no-padding">
|
||||
<div style="padding:8px;">
|
||||
<a href="webhooks/create" class="btn btn-success"><span class="fa fa-plus fa-fw"></span>{{ $t('firefly.create_new_webhook') }}</a>
|
||||
</div>
|
||||
|
||||
<table class="table table-responsive table-hover" v-if="webhooks.length > 0" aria-label="A table.">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Responds when</th>
|
||||
<th>Responds with (delivery)</th>
|
||||
<th style="width:20%;">Secret (show / hide)</th>
|
||||
<th>URL</th>
|
||||
<th class="hidden-sm hidden-xs"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="webhook in webhooks" :key="webhook.id">
|
||||
<td>
|
||||
<a :href="'webhooks/show/' + webhook.id">{{ webhook.title }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="webhook.active">{{ triggers[webhook.trigger] }}</span>
|
||||
<span v-if="!webhook.active" class="text-muted"><s>{{ triggers[webhook.trigger] }}</s> ({{ $t('firefly.inactive') }})</span>
|
||||
</td>
|
||||
<td>{{ responses[webhook.response] }} ({{ deliveries[webhook.delivery] }})</td>
|
||||
<td>
|
||||
<em style="cursor:pointer"
|
||||
v-if="webhook.show_secret" class="fa fa-eye" @click="toggleSecret(webhook)"></em>
|
||||
<em style="cursor:pointer"
|
||||
v-if="!webhook.show_secret" class="fa fa-eye-slash" @click="toggleSecret(webhook)"></em>
|
||||
<code v-if="webhook.show_secret">{{ webhook.secret }}</code>
|
||||
<code v-if="!webhook.show_secret">********</code>
|
||||
</td>
|
||||
<td>
|
||||
<code :title="webhook.full_url">{{ webhook.url }}</code>
|
||||
|
||||
</td>
|
||||
<td class="hidden-sm hidden-xs">
|
||||
<div class="btn-group btn-group-xs pull-right">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{ $t('firefly.actions') }} <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<li><a :href="'webhooks/show/' + webhook.id"><span class="fa fa-fw fa-search"></span> {{ $t('firefly.inspect') }}</a></li>
|
||||
<li><a :href="'webhooks/edit/' + webhook.id"><span class="fa fa-fw fa-pencil"></span> {{$t( 'firefly.edit') }}</a></li>
|
||||
<li><a :href="'webhooks/delete/' + webhook.id"><span class="fa fa-fw fa-trash"></span> {{ $t('firefly.delete') }}</a></li>
|
||||
</ul>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
{{ $t('firefly.webhooks') }}
|
||||
</h3>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="box-body no-padding">
|
||||
<div style="padding:8px;">
|
||||
<a href="webhooks/create" class="btn btn-success"><span
|
||||
class="fa fa-plus fa-fw"></span>{{ $t('firefly.create_new_webhook') }}</a>
|
||||
</div>
|
||||
|
||||
<div v-if="webhooks.length > 0" style="padding:8px;">
|
||||
<a href="webhooks/create" class="btn btn-success"><span class="fa fa-plus fa-fw"></span>{{ $t('firefly.create_new_webhook') }}</a>
|
||||
</div>
|
||||
<table class="table table-responsive table-hover" v-if="webhooks.length > 0" aria-label="A table.">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Responds when</th>
|
||||
<th>Responds with (delivery)</th>
|
||||
<th style="width:20%;">Secret (show / hide)</th>
|
||||
<th>URL</th>
|
||||
<th class="hidden-sm hidden-xs"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="webhook in webhooks" :key="webhook.id">
|
||||
<td>
|
||||
<a :href="'webhooks/show/' + webhook.id">{{ webhook.title }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="webhook.active">{{ triggers[webhook.trigger] }}</span>
|
||||
<span v-if="!webhook.active" class="text-muted"><s>{{ triggers[webhook.trigger] }}</s> ({{
|
||||
$t('firefly.inactive')
|
||||
}})</span>
|
||||
</td>
|
||||
<td>{{ responses[webhook.response] }} ({{ deliveries[webhook.delivery] }})</td>
|
||||
<td>
|
||||
<em style="cursor:pointer"
|
||||
v-if="webhook.show_secret" class="fa fa-eye" @click="toggleSecret(webhook)"></em>
|
||||
<em style="cursor:pointer"
|
||||
v-if="!webhook.show_secret" class="fa fa-eye-slash"
|
||||
@click="toggleSecret(webhook)"></em>
|
||||
<code v-if="webhook.show_secret">{{ webhook.secret }}</code>
|
||||
<code v-if="!webhook.show_secret">********</code>
|
||||
</td>
|
||||
<td>
|
||||
<code :title="webhook.full_url">{{ webhook.url }}</code>
|
||||
|
||||
</td>
|
||||
<td class="hidden-sm hidden-xs">
|
||||
<div class="btn-group btn-group-xs pull-right">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
{{ $t('firefly.actions') }} <span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<li><a :href="'webhooks/show/' + webhook.id"><span
|
||||
class="fa fa-fw fa-search"></span> {{ $t('firefly.inspect') }}</a></li>
|
||||
<li><a :href="'webhooks/edit/' + webhook.id"><span
|
||||
class="fa fa-fw fa-pencil"></span> {{ $t('firefly.edit') }}</a></li>
|
||||
<li><a :href="'webhooks/delete/' + webhook.id"><span
|
||||
class="fa fa-fw fa-trash"></span> {{ $t('firefly.delete') }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div v-if="webhooks.length > 0" style="padding:8px;">
|
||||
<a href="webhooks/create" class="btn btn-success"><span
|
||||
class="fa fa-plus fa-fw"></span>{{ $t('firefly.create_new_webhook') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Index",
|
||||
data() {
|
||||
return {
|
||||
webhooks: [],
|
||||
triggers: {
|
||||
STORE_TRANSACTION: this.$t('firefly.webhook_trigger_STORE_TRANSACTION'),
|
||||
UPDATE_TRANSACTION: this.$t('firefly.webhook_trigger_UPDATE_TRANSACTION'),
|
||||
DESTROY_TRANSACTION: this.$t('firefly.webhook_trigger_DESTROY_TRANSACTION'),
|
||||
},
|
||||
responses: {
|
||||
TRANSACTIONS: this.$t('firefly.webhook_response_TRANSACTIONS'),
|
||||
ACCOUNTS: this.$t('firefly.webhook_response_ACCOUNTS'),
|
||||
NONE: this.$t('firefly.webhook_response_none_NONE'),
|
||||
},
|
||||
deliveries: {
|
||||
JSON: this.$t('firefly.webhook_delivery_JSON'),
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getWebhooks();
|
||||
},
|
||||
methods: {
|
||||
getWebhooks: function () {
|
||||
this.webhooks = [];
|
||||
this.downloadWebhooks(1);
|
||||
name: "Index",
|
||||
data() {
|
||||
return {
|
||||
webhooks: [],
|
||||
triggers: {
|
||||
},
|
||||
responses: {
|
||||
},
|
||||
deliveries: {
|
||||
},
|
||||
};
|
||||
},
|
||||
toggleSecret: function (webhook) {
|
||||
webhook.show_secret = !webhook.show_secret;
|
||||
mounted() {
|
||||
this.getOptions();
|
||||
},
|
||||
downloadWebhooks: function (page) {
|
||||
axios.get("./api/v1/webhooks?page=" + page).then((response) => {
|
||||
for (let i in response.data.data) {
|
||||
if (response.data.data.hasOwnProperty(i)) {
|
||||
let current = response.data.data[i];
|
||||
let webhook = {
|
||||
id: current.id,
|
||||
title: current.attributes.title,
|
||||
url: current.attributes.url,
|
||||
active: current.attributes.active,
|
||||
full_url: current.attributes.url,
|
||||
secret: current.attributes.secret,
|
||||
trigger: current.attributes.trigger,
|
||||
response: current.attributes.response,
|
||||
delivery: current.attributes.delivery,
|
||||
show_secret: false,
|
||||
};
|
||||
if(current.attributes.url.length > 20) {
|
||||
webhook.url = current.attributes.url.slice(0, 20) + '...';
|
||||
}
|
||||
this.webhooks.push(webhook);
|
||||
}
|
||||
}
|
||||
methods: {
|
||||
getOptions: function () {
|
||||
// get triggers
|
||||
axios.get('./api/v1/configuration/webhook.triggers').then((response) => {
|
||||
for (let key in response.data.data.value) {
|
||||
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
this.triggers[key] = this.$t('firefly.webhook_trigger_' + key);
|
||||
}
|
||||
|
||||
if (response.data.meta.pagination.current_page < response.data.meta.pagination.total_pages) {
|
||||
this.downloadWebhooks(response.data.meta.pagination.current_page + 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
// get responses
|
||||
axios.get('./api/v1/configuration/webhook.responses').then((response) => {
|
||||
for (let key in response.data.data.value) {
|
||||
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
this.responses[key] = this.$t('firefly.webhook_response_' + key);
|
||||
}
|
||||
// get deliveries
|
||||
axios.get('./api/v1/configuration/webhook.deliveries').then((response) => {
|
||||
for (let key in response.data.data.value) {
|
||||
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
this.deliveries[key] = this.$t('firefly.webhook_delivery_' + key);
|
||||
}
|
||||
// get webhooks
|
||||
this.getWebhooks();
|
||||
})
|
||||
})
|
||||
});
|
||||
},
|
||||
getWebhooks: function () {
|
||||
this.webhooks = [];
|
||||
this.downloadWebhooks(1);
|
||||
},
|
||||
toggleSecret: function (webhook) {
|
||||
webhook.show_secret = !webhook.show_secret;
|
||||
},
|
||||
downloadWebhooks: function (page) {
|
||||
axios.get("./api/v1/webhooks?page=" + page).then((response) => {
|
||||
for (let i in response.data.data) {
|
||||
if (response.data.data.hasOwnProperty(i)) {
|
||||
let current = response.data.data[i];
|
||||
let webhook = {
|
||||
id: current.id,
|
||||
title: current.attributes.title,
|
||||
url: current.attributes.url,
|
||||
active: current.attributes.active,
|
||||
full_url: current.attributes.url,
|
||||
secret: current.attributes.secret,
|
||||
trigger: current.attributes.trigger,
|
||||
response: current.attributes.response,
|
||||
delivery: current.attributes.delivery,
|
||||
show_secret: false,
|
||||
};
|
||||
if (current.attributes.url.length > 20) {
|
||||
webhook.url = current.attributes.url.slice(0, 20) + '...';
|
||||
}
|
||||
this.webhooks.push(webhook);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.data.meta.pagination.current_page < response.data.meta.pagination.total_pages) {
|
||||
this.downloadWebhooks(response.data.meta.pagination.current_page + 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||
"webhook_response_ACCOUNTS": "Account details",
|
||||
"webhook_response_none_NONE": "No details",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Actions",
|
||||
"meta_data": "Meta data",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"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_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"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_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u0627\u0644\u0625\u062c\u0631\u0627\u0621\u0627\u062a",
|
||||
"meta_data": "\u0628\u064a\u0627\u0646\u0627\u062a \u0648\u0635\u0641\u064a\u0629",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||
"webhook_response_ACCOUNTS": "Account details",
|
||||
"webhook_response_none_NONE": "No details",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f",
|
||||
"meta_data": "\u041c\u0435\u0442\u0430 \u0434\u0430\u043d\u043d\u0438",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Despr\u00e9s de crear la transacci\u00f3",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Despr\u00e9s d'actualitzar la transacci\u00f3",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Despr\u00e9s d'eliminar la transacci\u00f3",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Detalls de la transacci\u00f3",
|
||||
"webhook_response_ACCOUNTS": "Detalls del compte",
|
||||
"webhook_response_none_NONE": "Sense detalls",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Accions",
|
||||
"meta_data": "Meta dades",
|
||||
|
@@ -10,7 +10,7 @@
|
||||
"welcome_back": "Jak to jde?",
|
||||
"flash_error": "Chyba!",
|
||||
"flash_warning": "Varov\u00e1n\u00ed!",
|
||||
"flash_success": "\u00dasp\u011b\u0161n\u011b dokon\u010deno!",
|
||||
"flash_success": "V\u00fdborn\u011b!",
|
||||
"close": "Zav\u0159\u00edt",
|
||||
"select_dest_account": "Please select or type a valid destination account name",
|
||||
"select_source_account": "Please select or type a valid source account name",
|
||||
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Po vytvo\u0159en\u00ed transakce",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Po aktualizaci transakce",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Po odstran\u011bn\u00ed transakce",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Podrobnosti transakce",
|
||||
"webhook_response_ACCOUNTS": "Podrobnosti \u00fa\u010dtu",
|
||||
"webhook_response_none_NONE": "\u017d\u00e1dn\u00e9 detaily",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Akce",
|
||||
"meta_data": "Metadata",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Efter oprettelse af transaktion",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Efter opdatering af transaktion",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Efter sletning af transaktion",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaktionsdetaljer",
|
||||
"webhook_response_ACCOUNTS": "Kontodetaljer",
|
||||
"webhook_response_none_NONE": "Ingen detaljer",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Handlinger",
|
||||
"meta_data": "Meta data",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Nach Erstellen einer Buchung",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Nach Aktualisierung einer Buchung",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Nach dem L\u00f6schen einer Buchung",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Buchungsdetails",
|
||||
"webhook_response_ACCOUNTS": "Kontodetails",
|
||||
"webhook_response_none_NONE": "Keine Daten",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Aktionen",
|
||||
"meta_data": "Metadaten",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u039c\u03b5\u03c4\u03ac \u03c4\u03b7 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03c3\u03c5\u03bd\u03b1\u03bb\u03bb\u03b1\u03b3\u03ae\u03c2",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u039c\u03b5\u03c4\u03ac \u03c4\u03b7\u03bd \u03b5\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03c3\u03c5\u03bd\u03b1\u03bb\u03bb\u03b1\u03b3\u03ae\u03c2",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u039c\u03b5\u03c4\u03ac \u03c4\u03b7 \u03b4\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u03c3\u03c5\u03bd\u03b1\u03bb\u03bb\u03b1\u03b3\u03ae\u03c2",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 \u03c3\u03c5\u03bd\u03b1\u03bb\u03bb\u03b1\u03b3\u03ae\u03c2",
|
||||
"webhook_response_ACCOUNTS": "\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd",
|
||||
"webhook_response_none_NONE": "\u0394\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03c5\u03bd \u03bb\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u0395\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b5\u03c2",
|
||||
"meta_data": "\u039c\u03b5\u03c4\u03b1-\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||
"webhook_response_ACCOUNTS": "Account details",
|
||||
"webhook_response_none_NONE": "No details",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Actions",
|
||||
"meta_data": "Meta data",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||
"webhook_response_ACCOUNTS": "Account details",
|
||||
"webhook_response_none_NONE": "No details",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Actions",
|
||||
"meta_data": "Meta data",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Despu\u00e9s de crear la transacci\u00f3n",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Despu\u00e9s de actualizar la transacci\u00f3n",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Despu\u00e9s de eliminar la transacci\u00f3n",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Detalles de la transacci\u00f3n",
|
||||
"webhook_response_ACCOUNTS": "Detalles de la cuenta",
|
||||
"webhook_response_none_NONE": "Sin detalles",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Acciones",
|
||||
"meta_data": "Meta Datos",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u067e\u0633 \u0627\u0632 \u0627\u06cc\u062c\u0627\u062f \u062a\u0631\u0627\u06a9\u0646\u0634\n",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u067e\u0633 \u0627\u0632 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u062a\u0631\u0627\u06a9\u0646\u0634\n",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u067e\u0633 \u0627\u0632 \u062a\u0631\u0627\u06a9\u0646\u0634 \u062d\u0630\u0641 \u0634\u0648\u062f\n",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\u062c\u0632\u0626\u06cc\u0627\u062a \u062a\u0631\u0627\u06a9\u0646\u0634",
|
||||
"webhook_response_ACCOUNTS": "\u062c\u0632\u0626\u06cc\u0627\u062a \u062d\u0633\u0627\u0628",
|
||||
"webhook_response_none_NONE": "\u0628\u062f\u0648\u0646 \u062c\u0632\u0626\u06cc\u0627\u062a",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u0639\u0645\u0644\u06cc\u0627\u062a \u0647\u0627",
|
||||
"meta_data": "\u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u0645\u062a\u0627\n",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||
"webhook_response_ACCOUNTS": "Tilin tiedot",
|
||||
"webhook_response_none_NONE": "No details",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Toiminnot",
|
||||
"meta_data": "Metatieto",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Apr\u00e8s la cr\u00e9ation de l'op\u00e9ration",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Apr\u00e8s la mise \u00e0 jour de l'op\u00e9ration",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Apr\u00e8s la suppression de l'op\u00e9ration",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "D\u00e9tails de l'op\u00e9ration",
|
||||
"webhook_response_ACCOUNTS": "D\u00e9tails du compte",
|
||||
"webhook_response_none_NONE": "Aucun d\u00e9tail",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Actions",
|
||||
"meta_data": "M\u00e9tadonn\u00e9es",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Tranzakci\u00f3 l\u00e9trehoz\u00e1sa ut\u00e1n",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Tranzakci\u00f3 friss\u00edt\u00e9se ut\u00e1n",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Tranzakci\u00f3 t\u00f6rl\u00e9se ut\u00e1n",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Tranzakci\u00f3 r\u00e9szletei",
|
||||
"webhook_response_ACCOUNTS": "Sz\u00e1mlaadatok",
|
||||
"webhook_response_none_NONE": "Nincsenek r\u00e9szletek",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "M\u0171veletek",
|
||||
"meta_data": "Metaadat",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||
"webhook_response_ACCOUNTS": "Account details",
|
||||
"webhook_response_none_NONE": "Tidak ada detil",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Tindakan",
|
||||
"meta_data": "Data meta",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Dopo aver creato la transazione",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Dopo aver aggiornato la transazione",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Dopo aver eliminato la transazione",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Dettagli transazione",
|
||||
"webhook_response_ACCOUNTS": "Dettagli conto",
|
||||
"webhook_response_none_NONE": "Nessun dettaglio",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Azioni",
|
||||
"meta_data": "Meta dati",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u53d6\u5f15\u4f5c\u6210\u5f8c",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u53d6\u5f15\u66f4\u65b0\u5f8c",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u53d6\u5f15\u524a\u9664\u5f8c",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\u53d6\u5f15\u8a73\u7d30",
|
||||
"webhook_response_ACCOUNTS": "\u53e3\u5ea7\u8a73\u7d30",
|
||||
"webhook_response_none_NONE": "\u8a73\u7d30\u306a\u3057",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u64cd\u4f5c",
|
||||
"meta_data": "\u30e1\u30bf\u30c7\u30fc\u30bf",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\uac70\ub798 \uc0dd\uc131 \uc774\ud6c4",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\uac70\ub798 \uc5c5\ub370\uc774\ud2b8 \uc774\ud6c4",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\uac70\ub798 \uc0ad\uc81c \uc774\ud6c4",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\uac70\ub798 \uc138\ubd80 \uc815\ubcf4",
|
||||
"webhook_response_ACCOUNTS": "\uacc4\uc815 \uc815\ubcf4",
|
||||
"webhook_response_none_NONE": "\uc0c1\uc138\uc815\ubcf4 \uc5c6\uc74c",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\uc561\uc158",
|
||||
"meta_data": "\uba54\ud0c0\ub370\uc774\ud130",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Etter transaksjons opprettelse",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Etter transaksjons oppdatering",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Etter transaksjons sletting",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaksjonsdetaljer",
|
||||
"webhook_response_ACCOUNTS": "Kontodetaljer",
|
||||
"webhook_response_none_NONE": "Ingen detaljer",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Handlinger",
|
||||
"meta_data": "Metadata",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Na het maken van een transactie",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Na het updaten van een transactie",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Na het verwijderen van een transactie",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transactiedetails",
|
||||
"webhook_response_ACCOUNTS": "Rekeningdetails",
|
||||
"webhook_response_none_NONE": "Geen details",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Acties",
|
||||
"meta_data": "Metagegevens",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Etter transaksjons opprettelse",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Etter transaksjons oppdatering",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Etter transaksjons sletting",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaksjonsdetaljer",
|
||||
"webhook_response_ACCOUNTS": "Kontodetaljer",
|
||||
"webhook_response_none_NONE": "Ingen detaljer",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Handlinger",
|
||||
"meta_data": "Metadata",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Po utworzeniu transakcji",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Po zmodyfikowaniu transakcji",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Po usuni\u0119ciu transakcji",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Szczeg\u00f3\u0142y transakcji",
|
||||
"webhook_response_ACCOUNTS": "Szczeg\u00f3\u0142y konta",
|
||||
"webhook_response_none_NONE": "Brak szczeg\u00f3\u0142\u00f3w",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Akcje",
|
||||
"meta_data": "Metadane",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Ap\u00f3s cria\u00e7\u00e3o da transa\u00e7\u00e3o",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Ap\u00f3s atualiza\u00e7\u00e3o da transa\u00e7\u00e3o",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Ap\u00f3s exclus\u00e3o da transa\u00e7\u00e3o",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Detalhes da transa\u00e7\u00e3o",
|
||||
"webhook_response_ACCOUNTS": "Detalhes da conta",
|
||||
"webhook_response_none_NONE": "Sem detalhes",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "A\u00e7\u00f5es",
|
||||
"meta_data": "Meta dados",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Ap\u00f3s criar transa\u00e7\u00e3o",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Ap\u00f3s atualizar transa\u00e7\u00e3o",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Ap\u00f3s eliminar transa\u00e7\u00e3o",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Detalhes da transa\u00e7\u00e3o",
|
||||
"webhook_response_ACCOUNTS": "Detalhes da conta",
|
||||
"webhook_response_none_NONE": "Sem dados",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "A\u00e7\u00f5es",
|
||||
"meta_data": "Meta dados",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Dup\u0103 crearea tranzac\u021biei",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Dup\u0103 actualizarea tranzac\u021biei",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Dup\u0103 \u0219tergerea tranzac\u021biei",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Detaliile tranzac\u021biei",
|
||||
"webhook_response_ACCOUNTS": "Detalii cont",
|
||||
"webhook_response_none_NONE": "Fara detalii",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Ac\u021biuni",
|
||||
"meta_data": "Date meta",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u041f\u043e\u0441\u043b\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\u0414\u0435\u0442\u0430\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438",
|
||||
"webhook_response_ACCOUNTS": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e\u0431 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438",
|
||||
"webhook_response_none_NONE": "\u041d\u0435\u0442 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0445 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f",
|
||||
"meta_data": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "After transaction creation",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||
"webhook_response_ACCOUNTS": "Account details",
|
||||
"webhook_response_none_NONE": "No details",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Akcie",
|
||||
"meta_data": "Metadata",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Po ustvarjanju transakcije",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Po posodabljanju transakcije",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Po brisanju transakcije",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Podrobnosti transakcije",
|
||||
"webhook_response_ACCOUNTS": "Podrobnosti ra\u010duna",
|
||||
"webhook_response_none_NONE": "Ni podrobnosti",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Dejanja",
|
||||
"meta_data": "Meta podatki",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Efter skapande av transaktion",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "After transaction update",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Transaktionsdetaljer",
|
||||
"webhook_response_ACCOUNTS": "Kontodetaljer",
|
||||
"webhook_response_none_NONE": "Inga detaljer",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u00c5tg\u00e4rder",
|
||||
"meta_data": "Metadata",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u0130\u015flem olu\u015fturma sonras\u0131",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u0130\u015flem g\u00fcncelleme sonras\u0131",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u0130\u015flem silme sonras\u0131",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\u0130\u015flem detaylar\u0131",
|
||||
"webhook_response_ACCOUNTS": "Hesap detaylar\u0131",
|
||||
"webhook_response_none_NONE": "Detay yok",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Eylemler",
|
||||
"meta_data": "Meta veri",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u041f\u0456\u0441\u043b\u044f \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u041f\u0456\u0441\u043b\u044f \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u041f\u0456\u0441\u043b\u044f \u0432\u0438\u0434\u0430\u043b\u0435\u043d\u043d\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\u0414\u0435\u0442\u0430\u043b\u0456 \u043e\u043f\u0435\u0440\u0430\u0446\u0456\u0457",
|
||||
"webhook_response_ACCOUNTS": "\u0414\u0430\u043d\u0456 \u0440\u0430\u0445\u0443\u043d\u043a\u0443",
|
||||
"webhook_response_none_NONE": "\u041d\u0435\u043c\u0430\u0454 \u0434\u0430\u043d\u0438\u0445",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u0414\u0456\u0457",
|
||||
"meta_data": "\u041c\u0435\u0442\u0430-\u0434\u0430\u043d\u0456",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "Sau khi t\u1ea1o giao d\u1ecbch",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Sau khi c\u1eadp nh\u1eadt giao d\u1ecbch",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Sau khi x\u00f3a giao d\u1ecbch",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Chi ti\u1ebft giao d\u1ecbch",
|
||||
"webhook_response_ACCOUNTS": "Chi ti\u1ebft t\u00e0i kho\u1ea3n",
|
||||
"webhook_response_none_NONE": "Kh\u00f4ng c\u00f3 chi ti\u1ebft",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "H\u00e0nh \u0111\u1ed9ng",
|
||||
"meta_data": "Meta data",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u4ea4\u6613\u521b\u5efa\u540e",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u4ea4\u6613\u66f4\u65b0\u540e",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u4ea4\u6613\u5220\u9664\u540e",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\u4ea4\u6613\u8be6\u60c5",
|
||||
"webhook_response_ACCOUNTS": "\u8d26\u6237\u8be6\u60c5",
|
||||
"webhook_response_none_NONE": "\u65e0\u8be6\u7ec6\u4fe1\u606f",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u64cd\u4f5c",
|
||||
"meta_data": "\u540e\u8bbe\u8d44\u6599",
|
||||
|
@@ -110,9 +110,13 @@
|
||||
"webhook_trigger_STORE_TRANSACTION": "\u5728\u4ea4\u6613\u5efa\u7acb\u5f8c",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "\u5728\u4ea4\u6613\u66f4\u65b0\u5f8c",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "\u5728\u4ea4\u6613\u522a\u9664\u5f8c",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "\u4ea4\u6613\u8a73\u60c5",
|
||||
"webhook_response_ACCOUNTS": "\u5e33\u865f\u8a73\u60c5",
|
||||
"webhook_response_none_NONE": "\u7121\u4efb\u4f55\u8a73\u60c5",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "\u64cd\u4f5c",
|
||||
"meta_data": "\u4e2d\u7e7c\u8cc7\u6599",
|
||||
|
@@ -25,7 +25,7 @@ export default class Dashboard {
|
||||
dashboard(start, end) {
|
||||
let startStr = format(start, 'y-MM-dd');
|
||||
let endStr = format(end, 'y-MM-dd');
|
||||
return api.get('/api/v1/chart/account/dashboard', {params: {start: startStr, end: endStr}});
|
||||
return api.get('/api/v1/chart/account/overview', {params: {start: startStr, end: endStr}});
|
||||
}
|
||||
|
||||
expense(start, end) {
|
||||
|
@@ -25,6 +25,6 @@ export default class Dashboard {
|
||||
dashboard(start, end) {
|
||||
let startStr = format(start, 'y-MM-dd');
|
||||
let endStr = format(end, 'y-MM-dd');
|
||||
return api.get('/api/v1/chart/budget/dashboard', {params: {start: startStr, end: endStr}});
|
||||
return api.get('/api/v1/chart/budget/overview', {params: {start: startStr, end: endStr}});
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,6 @@ export default class Dashboard {
|
||||
dashboard(start, end) {
|
||||
let startStr = format(start, 'y-MM-dd');
|
||||
let endStr = format(end, 'y-MM-dd');
|
||||
return api.get('/api/v1/chart/category/dashboard', {params: {start: startStr, end: endStr}});
|
||||
return api.get('/api/v1/chart/category/overview', {params: {start: startStr, end: endStr}});
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ export default class Dashboard {
|
||||
dashboard(start, end) {
|
||||
let startStr = format(start, 'y-MM-dd');
|
||||
let endStr = format(end, 'y-MM-dd');
|
||||
return api.get('/api/v1/chart/account/dashboard', {params: {start: startStr, end: endStr}});
|
||||
return api.get('/api/v1/chart/account/overview', {params: {start: startStr, end: endStr}});
|
||||
}
|
||||
|
||||
expense(start, end) {
|
||||
|
@@ -25,6 +25,6 @@ export default class Dashboard {
|
||||
dashboard(start, end) {
|
||||
let startStr = format(start, 'y-MM-dd');
|
||||
let endStr = format(end, 'y-MM-dd');
|
||||
return api.get('/api/v1/chart/budget/dashboard', {params: {start: startStr, end: endStr}});
|
||||
return api.get('/api/v1/chart/budget/overview', {params: {start: startStr, end: endStr}});
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,6 @@ export default class Dashboard {
|
||||
dashboard(start, end) {
|
||||
let startStr = format(start, 'y-MM-dd');
|
||||
let endStr = format(end, 'y-MM-dd');
|
||||
return api.get('/api/v1/chart/category/dashboard', {params: {start: startStr, end: endStr}});
|
||||
return api.get('/api/v1/chart/category/overview', {params: {start: startStr, end: endStr}});
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,9 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'webhook_budget_info' => 'Cannot deliver budget information for transaction related webhooks.',
|
||||
'webhook_account_info' => 'Cannot deliver account information for budget related webhooks.',
|
||||
'webhook_transaction_info' => 'Cannot deliver transaction information for budget related webhooks.',
|
||||
'invalid_account_type' => 'A piggy bank can only be linked to asset accounts and liabilities',
|
||||
'invalid_account_currency' => 'This account does not use the currency you have selected',
|
||||
'current_amount_too_much' => 'The combined amount in "current_amount" cannot exceed the "target_amount".',
|
||||
|
@@ -102,10 +102,10 @@ Route::group(
|
||||
[
|
||||
'namespace' => 'FireflyIII\Api\V1\Controllers\Chart',
|
||||
'prefix' => 'v1/chart/balance',
|
||||
'as' => 'api.v1.chart.balance',
|
||||
'as' => 'api.v1.chart.balance.',
|
||||
],
|
||||
static function (): void {
|
||||
Route::get('balance', ['uses' => 'BalanceController@balance', 'as' => 'balance.balance']);
|
||||
Route::get('balance', ['uses' => 'BalanceController@balance', 'as' => 'balance']);
|
||||
}
|
||||
);
|
||||
|
||||
|
@@ -28,8 +28,6 @@ use FireflyIII\Models\Bill;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
use FireflyIII\User;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use Override;
|
||||
|
||||
/**
|
||||
* Class BillControllerTest
|
||||
@@ -45,21 +43,6 @@ final class BillControllerTest extends TestCase
|
||||
*/
|
||||
use RefreshDatabase;
|
||||
|
||||
#[Override]
|
||||
protected function createAuthenticatedUser(): User
|
||||
{
|
||||
$userGroup = UserGroup::create(['title' => 'Test Group']);
|
||||
|
||||
$user = User::create([
|
||||
'email' => 'test@email.com',
|
||||
'password' => 'password',
|
||||
]);
|
||||
$user->user_group_id = $userGroup->id;
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function createTestBills(int $count, User $user): void
|
||||
{
|
||||
for ($i = 1; $i <= $count; ++$i) {
|
||||
@@ -96,7 +79,6 @@ final class BillControllerTest extends TestCase
|
||||
$response = $this->get(route('api.v1.autocomplete.bills'), ['Accept' => 'application/json']);
|
||||
$response->assertStatus(200);
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
|
||||
}
|
||||
|
||||
public function testGivenAuthenticatedRequestWhenCallingTheBillsEndpointThenReturnsBills(): void
|
||||
|
@@ -25,11 +25,9 @@ declare(strict_types=1);
|
||||
namespace Tests\integration\Api\Autocomplete;
|
||||
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
use FireflyIII\User;
|
||||
use Override;
|
||||
|
||||
/**
|
||||
* Class BudgetControllerTest
|
||||
@@ -45,21 +43,6 @@ final class BudgetControllerTest extends TestCase
|
||||
*/
|
||||
use RefreshDatabase;
|
||||
|
||||
#[Override]
|
||||
protected function createAuthenticatedUser(): User
|
||||
{
|
||||
$userGroup = UserGroup::create(['title' => 'Test Group']);
|
||||
|
||||
$user = User::create([
|
||||
'email' => 'test@email.com',
|
||||
'password' => 'password',
|
||||
]);
|
||||
$user->user_group_id = $userGroup->id;
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function createTestBudgets(int $count, User $user): void
|
||||
{
|
||||
for ($i = 1; $i <= $count; ++$i) {
|
||||
|
@@ -28,8 +28,6 @@ use FireflyIII\Models\Category;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
use FireflyIII\User;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use Override;
|
||||
|
||||
/**
|
||||
* Class CategoryControllerTest
|
||||
@@ -45,21 +43,6 @@ final class CategoryControllerTest extends TestCase
|
||||
*/
|
||||
use RefreshDatabase;
|
||||
|
||||
#[Override]
|
||||
protected function createAuthenticatedUser(): User
|
||||
{
|
||||
$userGroup = UserGroup::create(['title' => 'Test Group']);
|
||||
|
||||
$user = User::create([
|
||||
'email' => 'test@email.com',
|
||||
'password' => 'password',
|
||||
]);
|
||||
$user->user_group_id = $userGroup->id;
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function createTestCategories(int $count, User $user): void
|
||||
{
|
||||
for ($i = 1; $i <= $count; ++$i) {
|
||||
|
@@ -28,8 +28,6 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
use FireflyIII\User;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use Override;
|
||||
|
||||
/**
|
||||
* Class CurrencyControllerTest
|
||||
@@ -45,22 +43,6 @@ final class CurrencyControllerTest extends TestCase
|
||||
*/
|
||||
use RefreshDatabase;
|
||||
|
||||
#[Override]
|
||||
protected function createAuthenticatedUser(): User
|
||||
{
|
||||
$userGroup = UserGroup::create(['title' => 'Test Group']);
|
||||
|
||||
|
||||
$user = User::create([
|
||||
'email' => 'test@email.com',
|
||||
'password' => 'password',
|
||||
]);
|
||||
$user->user_group_id = $userGroup->id;
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function createTestCurrencies(int $count, bool $enabled): void
|
||||
{
|
||||
for ($i = 1; $i <= $count; ++$i) {
|
||||
|
@@ -28,8 +28,6 @@ use FireflyIII\Models\ObjectGroup;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
use FireflyIII\User;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use Override;
|
||||
|
||||
/**
|
||||
* Class ObjectGroupControllerTest
|
||||
@@ -45,22 +43,6 @@ final class ObjectGroupControllerTest extends TestCase
|
||||
*/
|
||||
use RefreshDatabase;
|
||||
|
||||
#[Override]
|
||||
protected function createAuthenticatedUser(): User
|
||||
{
|
||||
$userGroup = UserGroup::create(['title' => 'Test Group']);
|
||||
|
||||
|
||||
$user = User::create([
|
||||
'email' => 'test@email.com',
|
||||
'password' => 'password',
|
||||
]);
|
||||
$user->user_group_id = $userGroup->id;
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function createTestObjectGroups(int $count, User $user): void
|
||||
{
|
||||
for ($i = 1; $i <= $count; ++$i) {
|
||||
|
164
tests/integration/Api/Autocomplete/PiggyBankControllerTest.php
Normal file
164
tests/integration/Api/Autocomplete/PiggyBankControllerTest.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* BudgetControllerTest.php
|
||||
* Copyright (c) 2024 tasnim0tantawi
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\integration\Api\Autocomplete;
|
||||
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
|
||||
/**
|
||||
* Class BudgetControllerTest
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
final class PiggyBankControllerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \FireflyIII\Api\V1\Controllers\Autocomplete\BudgetController
|
||||
*/
|
||||
use RefreshDatabase;
|
||||
|
||||
private function createTestPiggyBanks(int $count, User $user): void
|
||||
{
|
||||
$type = AccountType::whereType(AccountTypeEnum::DEFAULT->value)->first();
|
||||
if (null === $type) {
|
||||
$type = AccountType::create(['type' => AccountTypeEnum::DEFAULT->value]);
|
||||
}
|
||||
$currency = TransactionCurrency::whereCode('EUR')->first();
|
||||
if (null === $currency) {
|
||||
$currency = TransactionCurrency::create(
|
||||
[
|
||||
'code' => 'EUR',
|
||||
'name' => 'Euro',
|
||||
'symbol' => '€',
|
||||
]
|
||||
);
|
||||
}
|
||||
for ($i = 1; $i <= $count; ++$i) {
|
||||
$piggyBank = PiggyBank::create(
|
||||
[
|
||||
'user_id' => $user->id,
|
||||
'name' => 'Piggy bank '.$i,
|
||||
'target_amount' => 1000,
|
||||
'transaction_currency_id' => $currency->id,
|
||||
'target_date' => now()->addDays(30),
|
||||
'user_group_id' => $user->user_group_id,
|
||||
'active' => 1,
|
||||
]
|
||||
);
|
||||
$account = Account::create(
|
||||
[
|
||||
'user_id' => $user->id,
|
||||
'name' => 'Account '.$i,
|
||||
'user_group_id' => $user->user_group_id,
|
||||
'account_type_id' => $type->id,
|
||||
'active' => 1,
|
||||
]
|
||||
);
|
||||
$piggyBank->accounts()->save($account);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGivenAnUnauthenticatedRequestWhenCallingTheBudgetsEndpointThenReturns401HttpCode(): void
|
||||
{
|
||||
// test API
|
||||
$response = $this->get(route('api.v1.autocomplete.piggy-banks'), ['Accept' => 'application/json']);
|
||||
$response->assertStatus(401);
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
$response->assertContent('{"message":"Unauthenticated.","exception":"AuthenticationException"}');
|
||||
}
|
||||
|
||||
public function testGivenAuthenticatedRequestWhenCallingTheBudgetsEndpointThenReturns200HttpCode(): void
|
||||
{
|
||||
// act as a user
|
||||
$user = $this->createAuthenticatedUser();
|
||||
$this->actingAs($user);
|
||||
|
||||
$response = $this->get(route('api.v1.autocomplete.piggy-banks'), ['Accept' => 'application/json']);
|
||||
$response->assertStatus(200);
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
|
||||
}
|
||||
|
||||
public function testGivenAuthenticatedRequestWhenCallingTheBudgetsEndpointThenReturnsBudgets(): void
|
||||
{
|
||||
$user = $this->createAuthenticatedUser();
|
||||
$this->actingAs($user);
|
||||
|
||||
$this->createTestPiggyBanks(5, $user);
|
||||
$response = $this->get(route('api.v1.autocomplete.piggy-banks'), ['Accept' => 'application/json']);
|
||||
$response->assertStatus(200);
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
$response->assertJsonCount(5);
|
||||
$response->assertJsonFragment(['name' => 'Piggy bank 1']);
|
||||
$response->assertJsonStructure([
|
||||
'*' => [
|
||||
'id',
|
||||
'name',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function testGivenAuthenticatedRequestWhenCallingTheBudgetsEndpointWithQueryThenReturnsBudgetsWithLimit(): void
|
||||
{
|
||||
$user = $this->createAuthenticatedUser();
|
||||
$this->actingAs($user);
|
||||
|
||||
$this->createTestPiggyBanks(5, $user);
|
||||
$response = $this->get(route('api.v1.autocomplete.piggy-banks', [
|
||||
'query' => 'Piggy',
|
||||
'limit' => 3,
|
||||
]), ['Accept' => 'application/json']);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
$response->assertJsonCount(3);
|
||||
}
|
||||
|
||||
public function testGivenAuthenticatedRequestWhenCallingTheBudgetsEndpointWithQueryThenReturnsBudgetsThatMatchQuery(): void
|
||||
{
|
||||
$user = $this->createAuthenticatedUser();
|
||||
$this->actingAs($user);
|
||||
|
||||
$this->createTestPiggyBanks(20, $user);
|
||||
$response = $this->get(route('api.v1.autocomplete.piggy-banks', [
|
||||
'query' => 'Piggy bank 1',
|
||||
'limit' => 20,
|
||||
]), ['Accept' => 'application/json']);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertHeader('Content-Type', 'application/json');
|
||||
// Budget 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 (11)
|
||||
$response->assertJsonCount(11);
|
||||
$response->assertJsonMissing(['name' => 'Piggy bank 2']);
|
||||
}
|
||||
}
|
50
tests/integration/Api/Chart/AccountControllerTest.php
Normal file
50
tests/integration/Api/Chart/AccountControllerTest.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\integration\Api\Chart;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
final class AccountControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
private $user;
|
||||
|
||||
#[Override]
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!isset($this->user)) {
|
||||
$this->user = $this->createAuthenticatedUser();
|
||||
}
|
||||
$this->actingAs($this->user);
|
||||
}
|
||||
|
||||
public function testGetOverviewChartFails(): void
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$response = $this->getJson(route('api.v1.chart.account.overview'));
|
||||
$response->assertStatus(422);
|
||||
|
||||
}
|
||||
|
||||
public function testGetOverviewChart(): void
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$params = [
|
||||
'start' => '2024-01-01',
|
||||
'end' => '2024-01-31',
|
||||
];
|
||||
$response = $this->getJson(route('api.v1.chart.account.overview').'?'.http_build_query($params));
|
||||
$response->assertStatus(200);
|
||||
|
||||
}
|
||||
}
|
50
tests/integration/Api/Chart/BalanceControllerTest.php
Normal file
50
tests/integration/Api/Chart/BalanceControllerTest.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\integration\Api\Chart;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
final class BalanceControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
private $user;
|
||||
|
||||
#[Override]
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!isset($this->user)) {
|
||||
$this->user = $this->createAuthenticatedUser();
|
||||
}
|
||||
$this->actingAs($this->user);
|
||||
}
|
||||
|
||||
public function testGetOverviewChartFails(): void
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$response = $this->getJson(route('api.v1.chart.balance.balance'));
|
||||
$response->assertStatus(422);
|
||||
|
||||
}
|
||||
|
||||
public function testGetOverviewChart(): void
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$params = [
|
||||
'start' => '2024-01-01',
|
||||
'end' => '2024-01-31',
|
||||
];
|
||||
$response = $this->getJson(route('api.v1.chart.balance.balance').'?'.http_build_query($params));
|
||||
$response->assertStatus(200);
|
||||
|
||||
}
|
||||
}
|
50
tests/integration/Api/Chart/BudgetControllerTest.php
Normal file
50
tests/integration/Api/Chart/BudgetControllerTest.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\integration\Api\Chart;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
final class BudgetControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
private $user;
|
||||
|
||||
#[Override]
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!isset($this->user)) {
|
||||
$this->user = $this->createAuthenticatedUser();
|
||||
}
|
||||
$this->actingAs($this->user);
|
||||
}
|
||||
|
||||
public function testGetOverviewChartFails(): void
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$response = $this->getJson(route('api.v1.chart.budget.overview'));
|
||||
$response->assertStatus(422);
|
||||
|
||||
}
|
||||
|
||||
public function testGetOverviewChart(): void
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$params = [
|
||||
'start' => '2024-01-01',
|
||||
'end' => '2024-01-31',
|
||||
];
|
||||
$response = $this->getJson(route('api.v1.chart.budget.overview').'?'.http_build_query($params));
|
||||
$response->assertStatus(200);
|
||||
|
||||
}
|
||||
}
|
50
tests/integration/Api/Chart/CategoryControllerTest.php
Normal file
50
tests/integration/Api/Chart/CategoryControllerTest.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\integration\Api\Chart;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\integration\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
final class CategoryControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
private $user;
|
||||
|
||||
#[Override]
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!isset($this->user)) {
|
||||
$this->user = $this->createAuthenticatedUser();
|
||||
}
|
||||
$this->actingAs($this->user);
|
||||
}
|
||||
|
||||
public function testGetOverviewChartFails(): void
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$response = $this->getJson(route('api.v1.chart.category.overview'));
|
||||
$response->assertStatus(422);
|
||||
|
||||
}
|
||||
|
||||
public function testGetOverviewChart(): void
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$params = [
|
||||
'start' => '2024-01-01',
|
||||
'end' => '2024-01-31',
|
||||
];
|
||||
$response = $this->getJson(route('api.v1.chart.category.overview').'?'.http_build_query($params));
|
||||
$response->assertStatus(200);
|
||||
|
||||
}
|
||||
}
|
@@ -23,7 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace Tests\integration;
|
||||
|
||||
use FireflyIII\Models\GroupMembership;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Models\UserRole;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||
@@ -54,14 +56,30 @@ abstract class TestCase extends BaseTestCase
|
||||
];
|
||||
}
|
||||
|
||||
protected function getAuthenticatedUser(): User
|
||||
{
|
||||
return User::where('email', 'james@firefly')->first();
|
||||
}
|
||||
|
||||
protected function createAuthenticatedUser(): User
|
||||
{
|
||||
$group = UserGroup::create(['title' => 'test@email.com']);
|
||||
|
||||
return User::create([
|
||||
$role = UserRole::where('title', 'owner')->first();
|
||||
$user = User::create([
|
||||
'email' => 'test@email.com',
|
||||
'password' => 'password',
|
||||
'user_group_id' => $group->id,
|
||||
]);
|
||||
|
||||
GroupMembership::create(
|
||||
[
|
||||
'user_id' => $user->id,
|
||||
'user_group_id' => $group->id,
|
||||
'user_role_id' => $role->id,
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user