mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-04 12:01:57 +00:00
Merge branch 'release/5.2.7'
This commit is contained in:
29
.env.example
29
.env.example
@@ -58,13 +58,24 @@ APP_LOG_LEVEL=notice
|
|||||||
# For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq
|
# For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq
|
||||||
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||||
# Use "mysql" for MySQL and MariaDB. Use "sqlite" for SQLite.
|
# Use "mysql" for MySQL and MariaDB. Use "sqlite" for SQLite.
|
||||||
DB_CONNECTION=pgsql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=fireflyiiidb
|
DB_HOST=fireflyiiidb
|
||||||
DB_PORT=5432
|
DB_PORT=3306
|
||||||
DB_DATABASE=firefly
|
DB_DATABASE=firefly
|
||||||
DB_USERNAME=firefly
|
DB_USERNAME=firefly
|
||||||
DB_PASSWORD=secret_firefly_password
|
DB_PASSWORD=secret_firefly_password
|
||||||
|
|
||||||
|
# MySQL supports SSL. You can configure it here.
|
||||||
|
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||||
|
MYSQL_USE_SSL=false
|
||||||
|
MYSQL_SSL_VERIFY_SERVER_CERT=true
|
||||||
|
# You need to set at least of these options
|
||||||
|
MYSQL_SSL_CAPATH=/etc/ssl/certs/
|
||||||
|
MYSQL_SSL_CA=
|
||||||
|
MYSQL_SSL_CERT=
|
||||||
|
MYSQL_SSL_KEY=
|
||||||
|
MYSQL_SSL_CIPHER=
|
||||||
|
|
||||||
# PostgreSQL supports SSL. You can configure it here.
|
# PostgreSQL supports SSL. You can configure it here.
|
||||||
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||||
PGSQL_SSL_MODE=prefer
|
PGSQL_SSL_MODE=prefer
|
||||||
@@ -170,8 +181,16 @@ ADLDAP_PORT=389
|
|||||||
ADLDAP_TIMEOUT=5
|
ADLDAP_TIMEOUT=5
|
||||||
ADLDAP_BASEDN=""
|
ADLDAP_BASEDN=""
|
||||||
ADLDAP_FOLLOW_REFFERALS=false
|
ADLDAP_FOLLOW_REFFERALS=false
|
||||||
|
|
||||||
|
# SSL/TLS settings
|
||||||
ADLDAP_USE_SSL=false
|
ADLDAP_USE_SSL=false
|
||||||
ADLDAP_USE_TLS=false
|
ADLDAP_USE_TLS=false
|
||||||
|
ADLDAP_SSL_CACERTDIR=
|
||||||
|
ADLDAP_SSL_CACERTFILE=
|
||||||
|
ADLDAP_SSL_CERTFILE=
|
||||||
|
ADLDAP_SSL_KEYFILE=
|
||||||
|
ADLDAP_SSL_CIPHER_SUITE=
|
||||||
|
ADLDAP_SSL_REQUIRE_CERT=
|
||||||
|
|
||||||
# You can set the following variables from a file by appending them with _FILE:
|
# You can set the following variables from a file by appending them with _FILE:
|
||||||
ADLDAP_ADMIN_USERNAME=
|
ADLDAP_ADMIN_USERNAME=
|
||||||
@@ -219,8 +238,9 @@ TRACKER_SITE_ID=
|
|||||||
TRACKER_URL=
|
TRACKER_URL=
|
||||||
|
|
||||||
#
|
#
|
||||||
# Firefly III could (in the future) collect telemetry on how you use Firefly III.
|
# Firefly III can collect telemetry on how you use Firefly III. This is opt-in.
|
||||||
# In order to allow this, change the following variable to true:
|
# In order to allow this, change the following variable to true.
|
||||||
|
# To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry
|
||||||
SEND_TELEMETRY=false
|
SEND_TELEMETRY=false
|
||||||
|
|
||||||
# You can fine tune the start-up of a Docker container by editing these environment variables.
|
# You can fine tune the start-up of a Docker container by editing these environment variables.
|
||||||
@@ -268,7 +288,6 @@ DEMO_USERNAME=
|
|||||||
DEMO_PASSWORD=
|
DEMO_PASSWORD=
|
||||||
USE_ENCRYPTION=false
|
USE_ENCRYPTION=false
|
||||||
IS_SANDSTORM=false
|
IS_SANDSTORM=false
|
||||||
IS_DOCKER=false
|
|
||||||
IS_HEROKU=false
|
IS_HEROKU=false
|
||||||
BUNQ_USE_SANDBOX=false
|
BUNQ_USE_SANDBOX=false
|
||||||
|
|
||||||
|
|||||||
@@ -83,8 +83,6 @@ class CorrectDatabase extends Command
|
|||||||
echo $result;
|
echo $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,8 +77,6 @@ class CorrectOpeningBalanceCurrencies extends Command
|
|||||||
$this->info('There was nothing to fix in the opening balance transactions.');
|
$this->info('There was nothing to fix in the opening balance transactions.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,8 +78,6 @@ class CreateAccessTokens extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verify access tokens in %s seconds.', $end));
|
$this->info(sprintf('Verify access tokens in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,8 +79,6 @@ class CreateLinkTypes extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified link types in %s seconds', $end));
|
$this->info(sprintf('Verified link types in %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,8 +76,6 @@ class DeleteEmptyGroups extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified empty groups in %s seconds', $end));
|
$this->info(sprintf('Verified empty groups in %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,6 @@ class DeleteEmptyJournals extends Command
|
|||||||
$this->deleteUnevenJournals();
|
$this->deleteUnevenJournals();
|
||||||
$this->deleteEmptyJournals();
|
$this->deleteEmptyJournals();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ class DeleteOrphanedTransactions extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified orphans in %s seconds', $end));
|
$this->info(sprintf('Verified orphans in %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,8 +78,6 @@ class DeleteZeroAmount extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified zero-amount integrity in %s seconds', $end));
|
$this->info(sprintf('Verified zero-amount integrity in %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,8 +101,6 @@ class EnableCurrencies extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified currencies in %s seconds.', $end));
|
$this->info(sprintf('Verified currencies in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ class FixAccountTypes extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verifying account types took %s seconds', $end));
|
$this->info(sprintf('Verifying account types took %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ class FixLongDescriptions extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified all transaction group and journal title lengths in %s seconds.', $end));
|
$this->info(sprintf('Verified all transaction group and journal title lengths in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ class FixPiggies extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->line(sprintf('Verified the content of %d piggy bank events in %s seconds.', $set->count(), $end));
|
$this->line(sprintf('Verified the content of %d piggy bank events in %s seconds.', $set->count(), $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ class FixRecurringTransactions extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Corrected recurring transactions %s seconds.', $end));
|
$this->info(sprintf('Corrected recurring transactions %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ class FixUnevenAmount extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified amount integrity in %s seconds', $end));
|
$this->info(sprintf('Verified amount integrity in %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ class RemoveBills extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified bills / journals in %s seconds', $end));
|
$this->info(sprintf('Verified bills / journals in %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ class RenameMetaFields extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Renamed meta fields in %s seconds', $end));
|
$this->info(sprintf('Renamed meta fields in %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ class TransferBudgets extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified budget/journals in %s seconds.', $end));
|
$this->info(sprintf('Verified budget/journals in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,6 @@ class DecryptDatabase extends Command
|
|||||||
}
|
}
|
||||||
$this->info('Done!');
|
$this->info('Done!');
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,11 +137,11 @@ class ExportData extends Command
|
|||||||
} catch (FireflyException $e) {
|
} catch (FireflyException $e) {
|
||||||
$this->error(sprintf('Could not store data: %s', $e->getMessage()));
|
$this->error(sprintf('Could not store data: %s', $e->getMessage()));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command-with-error', $this->signature);
|
app('telemetry')->feature('system.command.errored', $this->signature);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
app('telemetry')->feature('system.command.executed', $this->signature);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,279 +63,14 @@ class CreateCSVImport extends Command
|
|||||||
{configuration? : The configuration file to use for the import.}
|
{configuration? : The configuration file to use for the import.}
|
||||||
{--user=1 : The user ID that the import should import for.}
|
{--user=1 : The user ID that the import should import for.}
|
||||||
{--token= : The user\'s access token.}';
|
{--token= : The user\'s access token.}';
|
||||||
/** @var ImportJob */
|
|
||||||
private $importJob;
|
|
||||||
/** @var ImportJobRepositoryInterface */
|
|
||||||
private $importRepository;
|
|
||||||
/** @var UserRepositoryInterface */
|
|
||||||
private $userRepository;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the command.
|
* Run the command.
|
||||||
*/
|
*/
|
||||||
public function handle(): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
$this->stupidLaravel();
|
$this->error('This command is disabled.');
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
if (!$this->verifyAccessToken()) {
|
|
||||||
$this->errorLine('Invalid access token.');
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->validArguments()) {
|
|
||||||
$this->errorLine('Invalid arguments.');
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
/** @var User $user */
|
|
||||||
$user = $this->userRepository->findNull((int) $this->option('user'));
|
|
||||||
$file = (string) $this->argument('file');
|
|
||||||
$configuration = (string) $this->argument('configuration');
|
|
||||||
|
|
||||||
$this->importRepository->setUser($user);
|
|
||||||
|
|
||||||
$configurationData = json_decode(file_get_contents($configuration), true, 512, JSON_THROW_ON_ERROR);
|
|
||||||
$this->importJob = $this->importRepository->create('file');
|
|
||||||
|
|
||||||
|
|
||||||
// inform user (and log it)
|
|
||||||
$this->infoLine(sprintf('Import file : %s', $file));
|
|
||||||
$this->infoLine(sprintf('Configuration file : %s', $configuration));
|
|
||||||
$this->infoLine(sprintf('User : #%d (%s)', $user->id, $user->email));
|
|
||||||
$this->infoLine(sprintf('Job : %s', $this->importJob->key));
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->storeFile($file);
|
|
||||||
} catch (FireflyException $e) {
|
|
||||||
$this->errorLine($e->getMessage());
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// job is ready to go
|
|
||||||
$this->importRepository->setConfiguration($this->importJob, $configurationData);
|
|
||||||
$this->importRepository->setStatus($this->importJob, 'ready_to_run');
|
|
||||||
|
|
||||||
$this->infoLine('The import routine has started. The process is not visible. Please wait.');
|
|
||||||
Log::debug('Go for import!');
|
|
||||||
|
|
||||||
|
|
||||||
// keep repeating this call until job lands on "provider_finished"
|
|
||||||
try {
|
|
||||||
$this->processFile();
|
|
||||||
} catch (FireflyException $e) {
|
|
||||||
$this->errorLine($e->getMessage());
|
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command-with-error', $this->signature);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// then store data:
|
|
||||||
try {
|
|
||||||
$this->storeData();
|
|
||||||
} catch (FireflyException $e) {
|
|
||||||
$this->errorLine($e->getMessage());
|
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command-with-error', $this->signature);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// give feedback:
|
|
||||||
$this->giveFeedback();
|
|
||||||
|
|
||||||
// clear cache for user:
|
|
||||||
app('preferences')->setForUser($user, 'lastActivity', microtime());
|
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $message
|
|
||||||
* @param array|null $data
|
|
||||||
*
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
private function errorLine(string $message, array $data = null): void
|
|
||||||
{
|
|
||||||
Log::error($message, $data ?? []);
|
|
||||||
$this->error($message);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private function giveFeedback(): void
|
|
||||||
{
|
|
||||||
$this->infoLine('Job has finished.');
|
|
||||||
|
|
||||||
|
|
||||||
if (null !== $this->importJob->tag) {
|
|
||||||
$this->infoLine(sprintf('%d transaction(s) have been imported.', $this->importJob->tag->transactionJournals->count()));
|
|
||||||
$this->infoLine(sprintf('You can find your transactions under tag "%s"', $this->importJob->tag->tag));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null === $this->importJob->tag) {
|
|
||||||
$this->errorLine('No transactions have been imported :(.');
|
|
||||||
}
|
|
||||||
if (count($this->importJob->errors) > 0) {
|
|
||||||
$this->infoLine(sprintf('%d error(s) occurred:', count($this->importJob->errors)));
|
|
||||||
foreach ($this->importJob->errors as $err) {
|
|
||||||
$this->errorLine('- ' . $err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $message
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
private function infoLine(string $message, array $data = null): void
|
|
||||||
{
|
|
||||||
Log::info($message, $data ?? []);
|
|
||||||
$this->line($message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keep repeating import call until job lands on "provider_finished".
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
private function processFile(): void
|
|
||||||
{
|
|
||||||
$className = config('import.routine.file');
|
|
||||||
$valid = ['provider_finished'];
|
|
||||||
$count = 0;
|
|
||||||
|
|
||||||
while (!in_array($this->importJob->status, $valid, true) && $count < 6) {
|
|
||||||
Log::debug(sprintf('Now in loop #%d.', $count + 1));
|
|
||||||
/** @var RoutineInterface $routine */
|
|
||||||
$routine = app($className);
|
|
||||||
$routine->setImportJob($this->importJob);
|
|
||||||
try {
|
|
||||||
$routine->run();
|
|
||||||
} catch (FireflyException|Exception $e) {
|
|
||||||
$message = 'The import routine crashed: ' . $e->getMessage();
|
|
||||||
Log::error($message);
|
|
||||||
Log::error($e->getTraceAsString());
|
|
||||||
|
|
||||||
// set job errored out:
|
|
||||||
$this->importRepository->setStatus($this->importJob, 'error');
|
|
||||||
throw new FireflyException($message);
|
|
||||||
}
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
$this->importRepository->setStatus($this->importJob, 'provider_finished');
|
|
||||||
$this->importJob->status = 'provider_finished';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
private function storeData(): void
|
|
||||||
{
|
|
||||||
if ('provider_finished' === $this->importJob->status) {
|
|
||||||
$this->infoLine('Import has finished. Please wait for storage of data.');
|
|
||||||
// set job to be storing data:
|
|
||||||
$this->importRepository->setStatus($this->importJob, 'storing_data');
|
|
||||||
|
|
||||||
/** @var ImportArrayStorage $storage */
|
|
||||||
$storage = app(ImportArrayStorage::class);
|
|
||||||
$storage->setImportJob($this->importJob);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$storage->store();
|
|
||||||
} catch (FireflyException|Exception $e) {
|
|
||||||
$message = 'The import routine crashed: ' . $e->getMessage();
|
|
||||||
Log::error($message);
|
|
||||||
Log::error($e->getTraceAsString());
|
|
||||||
|
|
||||||
// set job errored out:
|
|
||||||
$this->importRepository->setStatus($this->importJob, 'error');
|
|
||||||
throw new FireflyException($message);
|
|
||||||
|
|
||||||
}
|
|
||||||
// set storage to be finished:
|
|
||||||
$this->importRepository->setStatus($this->importJob, 'storage_finished');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store the supplied file as an attachment to this job.
|
|
||||||
*
|
|
||||||
* @param string $file
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
private function storeFile(string $file): void
|
|
||||||
{
|
|
||||||
// store file as attachment.
|
|
||||||
if ('' !== $file) {
|
|
||||||
$messages = $this->importRepository->storeCLIUpload($this->importJob, 'import_file', $file);
|
|
||||||
if ($messages->count() > 0) {
|
|
||||||
throw new FireflyException($messages->first());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
|
|
||||||
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
|
|
||||||
* be called from the handle method instead of using the constructor to initialize the command.
|
|
||||||
*
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
private function stupidLaravel(): void
|
|
||||||
{
|
|
||||||
$this->userRepository = app(UserRepositoryInterface::class);
|
|
||||||
$this->importRepository = app(ImportJobRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify user inserts correct arguments.
|
|
||||||
*
|
|
||||||
* @noinspection MultipleReturnStatementsInspection
|
|
||||||
* @return bool
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
private function validArguments(): bool
|
|
||||||
{
|
|
||||||
$file = (string) $this->argument('file');
|
|
||||||
$configuration = (string) $this->argument('configuration');
|
|
||||||
$cwd = getcwd();
|
|
||||||
$enabled = (bool) config('import.enabled.file');
|
|
||||||
|
|
||||||
if (false === $enabled) {
|
|
||||||
$this->errorLine('CSV Provider is not enabled.');
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists($file)) {
|
|
||||||
$this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists($configuration)) {
|
|
||||||
$this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$configurationData = json_decode(file_get_contents($configuration), true, 512, JSON_THROW_ON_ERROR);
|
|
||||||
if (null === $configurationData) {
|
|
||||||
$this->errorLine(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ class ReportEmptyObjects extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Report on empty objects finished in %s seconds', $end));
|
$this->info(sprintf('Report on empty objects finished in %s seconds', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ class ReportIntegrity extends Command
|
|||||||
echo $result;
|
echo $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ class ReportSum extends Command
|
|||||||
{
|
{
|
||||||
$this->reportSum();
|
$this->reportSum();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace FireflyIII\Console\Commands\Integrity;
|
|||||||
|
|
||||||
use FireflyIII\Support\System\OAuthKeys;
|
use FireflyIII\Support\System\OAuthKeys;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RestoreOAuthKeys
|
* Class RestoreOAuthKeys
|
||||||
@@ -52,7 +53,6 @@ class RestoreOAuthKeys extends Command
|
|||||||
{
|
{
|
||||||
$this->restoreOAuthKeys();
|
$this->restoreOAuthKeys();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,9 @@ class RestoreOAuthKeys extends Command
|
|||||||
*/
|
*/
|
||||||
private function restoreOAuthKeys(): void
|
private function restoreOAuthKeys(): void
|
||||||
{
|
{
|
||||||
|
Log::debug('Going to restoreOAuthKeys()');
|
||||||
if (!$this->keysInDatabase() && !$this->keysOnDrive()) {
|
if (!$this->keysInDatabase() && !$this->keysOnDrive()) {
|
||||||
|
Log::debug('Keys are not in DB and keys are not on the drive.');
|
||||||
$this->generateKeys();
|
$this->generateKeys();
|
||||||
$this->storeKeysInDB();
|
$this->storeKeysInDB();
|
||||||
$this->line('Generated and stored new keys.');
|
$this->line('Generated and stored new keys.');
|
||||||
@@ -101,12 +103,14 @@ class RestoreOAuthKeys extends Command
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($this->keysInDatabase() && !$this->keysOnDrive()) {
|
if ($this->keysInDatabase() && !$this->keysOnDrive()) {
|
||||||
|
Log::debug('Keys are in DB and keys are not on the drive. Restore.');
|
||||||
$this->restoreKeysFromDB();
|
$this->restoreKeysFromDB();
|
||||||
$this->line('Restored OAuth keys from database.');
|
$this->line('Restored OAuth keys from database.');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!$this->keysInDatabase() && $this->keysOnDrive()) {
|
if (!$this->keysInDatabase() && $this->keysOnDrive()) {
|
||||||
|
Log::debug('Keys are not in DB and keys are on the drive. Save in DB.');
|
||||||
$this->storeKeysInDB();
|
$this->storeKeysInDB();
|
||||||
$this->line('Stored OAuth keys in database.');
|
$this->line('Stored OAuth keys in database.');
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class ScanAttachments extends Command
|
|||||||
$this->line(sprintf('Fixed attachment #%d', $attachment->id));
|
$this->line(sprintf('Fixed attachment #%d', $attachment->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
app('telemetry')->feature('system.command.executed', $this->signature);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class SetLatestVersion extends Command
|
|||||||
app('fireflyconfig')->set('ff3_version', config('firefly.version'));
|
app('fireflyconfig')->set('ff3_version', config('firefly.version'));
|
||||||
$this->line('Updated version.');
|
$this->line('Updated version.');
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
app('telemetry')->feature('system.command.executed', $this->signature);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ class ApplyRules extends Command
|
|||||||
|
|
||||||
$result = $this->verifyInput();
|
$result = $this->verifyInput();
|
||||||
if (false === $result) {
|
if (false === $result) {
|
||||||
// app('telemetry')->feature('executed-command-with-error', $this->signature);
|
app('telemetry')->feature('system.command.errored', $this->signature);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ class ApplyRules extends Command
|
|||||||
$this->warn(' --rule_groups=1,2,...');
|
$this->warn(' --rule_groups=1,2,...');
|
||||||
$this->warn(' --all_rules');
|
$this->warn(' --all_rules');
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command-with-error', $this->signature);
|
app('telemetry')->feature('system.command.errored', $this->signature);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ class ApplyRules extends Command
|
|||||||
$this->line('');
|
$this->line('');
|
||||||
$this->line('Done!');
|
$this->line('Done!');
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
app('telemetry')->feature('system.command.executed', $this->signature);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,10 +94,10 @@ class Cron extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fire telemetry cron job (disabled):
|
* Fire telemetry cron job
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
//$this->telemetryCronJob($force, $date);
|
$this->telemetryCronJob($force, $date);
|
||||||
} catch (FireflyException $e) {
|
} catch (FireflyException $e) {
|
||||||
Log::error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
Log::error($e->getTraceAsString());
|
Log::error($e->getTraceAsString());
|
||||||
@@ -106,7 +106,7 @@ class Cron extends Command
|
|||||||
|
|
||||||
$this->info('More feedback on the cron jobs can be found in the log files.');
|
$this->info('More feedback on the cron jobs can be found in the log files.');
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
app('telemetry')->feature('system.command.executed', $this->signature);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ class AccountCurrencies extends Command
|
|||||||
$this->info(sprintf('Verified and fixed account currencies in %s seconds.', $end));
|
$this->info(sprintf('Verified and fixed account currencies in %s seconds.', $end));
|
||||||
$this->markAsExecuted();
|
$this->markAsExecuted();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,8 +78,6 @@ class BackToJournals extends Command
|
|||||||
$this->info(sprintf('Updated category and budget info for all transaction journals in %s seconds.', $end));
|
$this->info(sprintf('Updated category and budget info for all transaction journals in %s seconds.', $end));
|
||||||
$this->markAsExecuted();
|
$this->markAsExecuted();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ class BudgetLimitCurrency extends Command
|
|||||||
|
|
||||||
$this->markAsExecuted();
|
$this->markAsExecuted();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ class CCLiabilities extends Command
|
|||||||
$this->info(sprintf('Verified credit card liabilities in %s seconds', $end));
|
$this->info(sprintf('Verified credit card liabilities in %s seconds', $end));
|
||||||
$this->markAsExecuted();
|
$this->markAsExecuted();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,8 +101,6 @@ class MigrateAttachments extends Command
|
|||||||
$this->info(sprintf('Migrated attachment notes in %s seconds.', $end));
|
$this->info(sprintf('Migrated attachment notes in %s seconds.', $end));
|
||||||
$this->markAsExecuted();
|
$this->markAsExecuted();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,8 +100,6 @@ class MigrateJournalNotes extends Command
|
|||||||
$this->info(sprintf('Migrated notes in %s seconds.', $end));
|
$this->info(sprintf('Migrated notes in %s seconds.', $end));
|
||||||
$this->markAsExecuted();
|
$this->markAsExecuted();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,8 +72,6 @@ class MigrateRecurrenceMeta extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Migrated recurrence meta data in %s seconds.', $end));
|
$this->info(sprintf('Migrated recurrence meta data in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ class MigrateTagLocations extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Migrated tag locations in %s seconds.', $end));
|
$this->info(sprintf('Migrated tag locations in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,8 +112,6 @@ class MigrateToGroups extends Command
|
|||||||
|
|
||||||
$this->markAsMigrated();
|
$this->markAsMigrated();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ class MigrateToRules extends Command
|
|||||||
$this->info(sprintf('Verified and fixed bills in %s seconds.', $end));
|
$this->info(sprintf('Verified and fixed bills in %s seconds.', $end));
|
||||||
$this->markAsExecuted();
|
$this->markAsExecuted();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ class OtherCurrenciesCorrections extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified and fixed transaction currencies in %s seconds.', $end));
|
$this->info(sprintf('Verified and fixed transaction currencies in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ class RenameAccountMeta extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Fixed account meta data in %s seconds.', $end));
|
$this->info(sprintf('Fixed account meta data in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ class TransactionIdentifier extends Command
|
|||||||
$this->info(sprintf('Verified and fixed transaction identifiers in %s seconds.', $end));
|
$this->info(sprintf('Verified and fixed transaction identifiers in %s seconds.', $end));
|
||||||
$this->markAsExecuted();
|
$this->markAsExecuted();
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ class TransferCurrenciesCorrections extends Command
|
|||||||
$end = round(microtime(true) - $start, 2);
|
$end = round(microtime(true) - $start, 2);
|
||||||
$this->info(sprintf('Verified and fixed currency information for transfers in %s seconds.', $end));
|
$this->info(sprintf('Verified and fixed currency information for transfers in %s seconds.', $end));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ class UpgradeDatabase extends Command
|
|||||||
// index will set FF3 version.
|
// index will set FF3 version.
|
||||||
app('fireflyconfig')->set('ff3_version', (string) config('firefly.version'));
|
app('fireflyconfig')->set('ff3_version', (string) config('firefly.version'));
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Console\Commands;
|
namespace FireflyIII\Console\Commands;
|
||||||
|
|
||||||
|
use FireflyIII\Support\System\GeneratesInstallationId;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,6 +33,8 @@ use Illuminate\Console\Command;
|
|||||||
*/
|
*/
|
||||||
class UpgradeFireflyInstructions extends Command
|
class UpgradeFireflyInstructions extends Command
|
||||||
{
|
{
|
||||||
|
use GeneratesInstallationId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
*
|
*
|
||||||
@@ -50,6 +53,7 @@ class UpgradeFireflyInstructions extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle(): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
|
$this->generateInstallationId();
|
||||||
if ('update' === (string) $this->argument('task')) {
|
if ('update' === (string) $this->argument('task')) {
|
||||||
$this->updateInstructions();
|
$this->updateInstructions();
|
||||||
}
|
}
|
||||||
@@ -57,7 +61,14 @@ class UpgradeFireflyInstructions extends Command
|
|||||||
$this->installInstructions();
|
$this->installInstructions();
|
||||||
}
|
}
|
||||||
|
|
||||||
// app('telemetry')->feature('executed-command', $this->signature);
|
// collect system telemetry
|
||||||
|
$isDocker = true === env('IS_DOCKER', false) ? 'true' : 'false';
|
||||||
|
app('telemetry')->feature('system.php.version', PHP_VERSION);
|
||||||
|
app('telemetry')->feature('system.os.version', PHP_OS);
|
||||||
|
app('telemetry')->feature('system.database.driver', env('DB_CONNECTION', '(unknown)'));
|
||||||
|
app('telemetry')->feature('system.os.is_docker', $isDocker);
|
||||||
|
app('telemetry')->feature('system.command.executed', $this->signature);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ class LoginController extends Controller
|
|||||||
return redirect(route('register')); // @codeCoverageIgnore
|
return redirect(route('register')); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// is allowed to?
|
// is allowed to?
|
||||||
$singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
|
$singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
|
||||||
$allowRegistration = true;
|
$allowRegistration = true;
|
||||||
@@ -148,6 +149,9 @@ class LoginController extends Controller
|
|||||||
$email = $request->old('email');
|
$email = $request->old('email');
|
||||||
$remember = $request->old('remember');
|
$remember = $request->old('remember');
|
||||||
|
|
||||||
|
// todo must forget 2FA if user ends up here.
|
||||||
|
|
||||||
|
|
||||||
return view('auth.login', compact('allowRegistration', 'email', 'remember', 'allowReset', 'title'));
|
return view('auth.login', compact('allowRegistration', 'email', 'remember', 'allowReset', 'title'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ class RegisterController extends Controller
|
|||||||
|
|
||||||
$this->registered($request, $user);
|
$this->registered($request, $user);
|
||||||
|
|
||||||
|
// telemetry
|
||||||
|
\Telemetry::feature('system.users.count', User::count());
|
||||||
|
|
||||||
return redirect($this->redirectPath());
|
return redirect($this->redirectPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ class BillController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$request->session()->flash('success', (string) trans('firefly.rescanned_bill', ['total' => $total]));
|
$request->session()->flash('success', (string) trans_choice('firefly.rescanned_bill', $total));
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
|
|
||||||
return redirect(route('bills.show', [$bill->id]));
|
return redirect(route('bills.show', [$bill->id]));
|
||||||
|
|||||||
@@ -177,12 +177,26 @@ class AvailableBudgetController extends Controller
|
|||||||
$end = session()->get('end');
|
$end = session()->get('end');
|
||||||
Log::info($e->getMessage());
|
Log::info($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate amount
|
||||||
|
$amount = (string) $request->get('amount');
|
||||||
|
if ('' === $amount) {
|
||||||
|
session()->flash('error', trans('firefly.invalid_amount'));
|
||||||
|
|
||||||
|
return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||||
|
}
|
||||||
|
if (0 === bccomp('0', $amount)) {
|
||||||
|
session()->flash('error', trans('firefly.invalid_amount'));
|
||||||
|
|
||||||
|
return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||||
|
}
|
||||||
|
|
||||||
// find currency
|
// find currency
|
||||||
$currency = $this->currencyRepos->find((int) $request->get('currency_id'));
|
$currency = $this->currencyRepos->find((int) $request->get('currency_id'));
|
||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
session()->flash('error', trans('firefly.invalid_currency'));
|
session()->flash('error', trans('firefly.invalid_currency'));
|
||||||
|
|
||||||
return redirect(route('budgets.index'));
|
return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// find existing AB
|
// find existing AB
|
||||||
@@ -190,7 +204,7 @@ class AvailableBudgetController extends Controller
|
|||||||
if (null === $existing) {
|
if (null === $existing) {
|
||||||
$this->abRepository->store(
|
$this->abRepository->store(
|
||||||
[
|
[
|
||||||
'amount' => $request->get('amount'),
|
'amount' => $amount,
|
||||||
'currency' => $currency,
|
'currency' => $currency,
|
||||||
'start' => $start,
|
'start' => $start,
|
||||||
'end' => $end,
|
'end' => $end,
|
||||||
@@ -199,7 +213,7 @@ class AvailableBudgetController extends Controller
|
|||||||
}
|
}
|
||||||
if (null !== $existing) {
|
if (null !== $existing) {
|
||||||
// update amount:
|
// update amount:
|
||||||
$this->abRepository->update($existing, ['amount' => $request->get('amount')]);
|
$this->abRepository->update($existing, ['amount' => $amount]);
|
||||||
}
|
}
|
||||||
session()->flash('success', trans('firefly.set_ab'));
|
session()->flash('success', trans('firefly.set_ab'));
|
||||||
|
|
||||||
@@ -217,7 +231,21 @@ class AvailableBudgetController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(Request $request, AvailableBudget $availableBudget, Carbon $start, Carbon $end)
|
public function update(Request $request, AvailableBudget $availableBudget, Carbon $start, Carbon $end)
|
||||||
{
|
{
|
||||||
$this->abRepository->update($availableBudget, ['amount' => $request->get('amount')]);
|
// validate amount
|
||||||
|
$amount = (string) $request->get('amount');
|
||||||
|
if ('' === $amount) {
|
||||||
|
session()->flash('error', trans('firefly.invalid_amount'));
|
||||||
|
|
||||||
|
return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||||
|
}
|
||||||
|
if (0 === bccomp('0', $amount)) {
|
||||||
|
session()->flash('error', trans('firefly.invalid_amount'));
|
||||||
|
|
||||||
|
return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$this->abRepository->update($availableBudget, ['amount' => $amount]);
|
||||||
session()->flash('success', trans('firefly.updated_ab'));
|
session()->flash('success', trans('firefly.updated_ab'));
|
||||||
|
|
||||||
return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')]));
|
return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ class BudgetLimitController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
Log::debug('Going to store new budget-limit.', $request->all());
|
||||||
// first search for existing one and update it if necessary.
|
// first search for existing one and update it if necessary.
|
||||||
$currency = $this->currencyRepos->find((int) $request->get('transaction_currency_id'));
|
$currency = $this->currencyRepos->find((int) $request->get('transaction_currency_id'));
|
||||||
$budget = $this->repository->findNull((int) $request->get('budget_id'));
|
$budget = $this->repository->findNull((int) $request->get('budget_id'));
|
||||||
@@ -143,7 +144,6 @@ class BudgetLimitController extends Controller
|
|||||||
$start->startOfDay();
|
$start->startOfDay();
|
||||||
$end->endOfDay();
|
$end->endOfDay();
|
||||||
|
|
||||||
|
|
||||||
Log::debug(sprintf('Start: %s, end: %s', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('Start: %s, end: %s', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
|
|
||||||
$limit = $this->blRepository->find($budget, $currency, $start, $end);
|
$limit = $this->blRepository->find($budget, $currency, $start, $end);
|
||||||
|
|||||||
@@ -121,11 +121,11 @@ class DebugController extends Controller
|
|||||||
$search = ['~', '#'];
|
$search = ['~', '#'];
|
||||||
$replace = ['\~', '# '];
|
$replace = ['\~', '# '];
|
||||||
|
|
||||||
|
$now = Carbon::now()->format('Y-m-d H:i:s e');
|
||||||
$installationId = app('fireflyconfig')->get('installation_id', '')->data;
|
$installationId = app('fireflyconfig')->get('installation_id', '')->data;
|
||||||
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
||||||
$phpOs = str_replace($search, $replace, PHP_OS);
|
$phpOs = str_replace($search, $replace, PHP_OS);
|
||||||
$interface = PHP_SAPI;
|
$interface = PHP_SAPI;
|
||||||
$now = Carbon::now()->format('Y-m-d H:i:s e');
|
|
||||||
$drivers = implode(', ', DB::availableDrivers());
|
$drivers = implode(', ', DB::availableDrivers());
|
||||||
$currentDriver = DB::getDriverName();
|
$currentDriver = DB::getDriverName();
|
||||||
$userAgent = $request->header('user-agent');
|
$userAgent = $request->header('user-agent');
|
||||||
@@ -137,7 +137,15 @@ class DebugController extends Controller
|
|||||||
$logChannel = config('logging.default');
|
$logChannel = config('logging.default');
|
||||||
$appLogLevel = config('logging.level');
|
$appLogLevel = config('logging.level');
|
||||||
$cacheDriver = config('cache.default');
|
$cacheDriver = config('cache.default');
|
||||||
$loginProvider = config('auth.driver');
|
$loginProvider = config('auth.providers.users.driver');
|
||||||
|
|
||||||
|
// some new vars.
|
||||||
|
$telemetry = true === config('firefly.send_telemetry') && true === config('firefly.feature_flags.telemetry');
|
||||||
|
$defaultLanguage = (string) config('firefly.default_language');
|
||||||
|
$defaultLocale = (string) config('firefly.default_locale');
|
||||||
|
$userLanguage = app('steam')->getLanguage();
|
||||||
|
$userLocale = app('steam')->getLocale();
|
||||||
|
$isDocker = env('IS_DOCKER', false);
|
||||||
|
|
||||||
// set languages, see what happens:
|
// set languages, see what happens:
|
||||||
$original = setlocale(LC_ALL, 0);
|
$original = setlocale(LC_ALL, 0);
|
||||||
@@ -145,6 +153,7 @@ class DebugController extends Controller
|
|||||||
$parts = app('steam')->getLocaleArray(app('steam')->getLocale());
|
$parts = app('steam')->getLocaleArray(app('steam')->getLocale());
|
||||||
foreach ($parts as $code) {
|
foreach ($parts as $code) {
|
||||||
$code = trim($code);
|
$code = trim($code);
|
||||||
|
Log::debug(sprintf('Trying to set %s', $code));
|
||||||
$localeAttempts[$code] = var_export(setlocale(LC_ALL, $code), true);
|
$localeAttempts[$code] = var_export(setlocale(LC_ALL, $code), true);
|
||||||
}
|
}
|
||||||
setlocale(LC_ALL, $original);
|
setlocale(LC_ALL, $original);
|
||||||
@@ -194,7 +203,14 @@ class DebugController extends Controller
|
|||||||
'interface',
|
'interface',
|
||||||
'logContent',
|
'logContent',
|
||||||
'cacheDriver',
|
'cacheDriver',
|
||||||
'trustedProxies'
|
'trustedProxies',
|
||||||
|
'telemetry',
|
||||||
|
'userLanguage',
|
||||||
|
'userLocale',
|
||||||
|
'defaultLanguage',
|
||||||
|
'defaultLocale',
|
||||||
|
'isDocker'
|
||||||
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class HomeController extends Controller
|
|||||||
if (0 === $count) {
|
if (0 === $count) {
|
||||||
return redirect(route('new-user.index'));
|
return redirect(route('new-user.index'));
|
||||||
}
|
}
|
||||||
$subTitle = (string) trans('firefly.welcomeBack');
|
$subTitle = (string) trans('firefly.welcome_back');
|
||||||
$transactions = [];
|
$transactions = [];
|
||||||
$frontPage = app('preferences')->get(
|
$frontPage = app('preferences')->get(
|
||||||
'frontPageAccounts',
|
'frontPageAccounts',
|
||||||
|
|||||||
@@ -124,6 +124,11 @@ class NewUserController extends Controller
|
|||||||
'invoice_date' => false, 'internal_reference' => false, 'notes' => true, 'attachments' => true,];
|
'invoice_date' => false, 'internal_reference' => false, 'notes' => true, 'attachments' => true,];
|
||||||
app('preferences')->set('transaction_journal_optional_fields', $visibleFields);
|
app('preferences')->set('transaction_journal_optional_fields', $visibleFields);
|
||||||
|
|
||||||
|
// telemetry: user language preference + default language.
|
||||||
|
app('telemetry')->feature('config.firefly.default_language', config('firefly.default_language', 'en_US'));
|
||||||
|
app('telemetry')->feature('user.preferences.language', app('steam')->getLanguage());
|
||||||
|
app('telemetry')->feature('user.preferences.locale', app('steam')->getLocale());
|
||||||
|
|
||||||
session()->flash('success', (string) trans('firefly.stored_new_accounts_new_user'));
|
session()->flash('success', (string) trans('firefly.stored_new_accounts_new_user'));
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
|||||||
@@ -92,9 +92,7 @@ class PiggyBankController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function add(PiggyBank $piggyBank)
|
public function add(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
/** @var Carbon $date */
|
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, new Carbon);
|
||||||
$date = session('end', Carbon::now()->endOfMonth());
|
|
||||||
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $date);
|
|
||||||
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank);
|
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||||
@@ -113,7 +111,7 @@ class PiggyBankController extends Controller
|
|||||||
public function addMobile(PiggyBank $piggyBank)
|
public function addMobile(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
$date = session('end', Carbon::now()->endOfMonth());
|
$date = session('end', new Carbon);
|
||||||
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $date);
|
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $date);
|
||||||
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank);
|
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||||
|
|||||||
@@ -210,6 +210,11 @@ class PreferencesController extends Controller
|
|||||||
session()->flash('success', (string) trans('firefly.saved_preferences'));
|
session()->flash('success', (string) trans('firefly.saved_preferences'));
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
// telemetry: user language preference + default language.
|
||||||
|
app('telemetry')->feature('config.firefly.default_language', config('firefly.default_language', 'en_US'));
|
||||||
|
app('telemetry')->feature('user.preferences.language', app('steam')->getLanguage());
|
||||||
|
app('telemetry')->feature('user.preferences.locale', app('steam')->getLocale());
|
||||||
|
|
||||||
return redirect(route('preferences.index'));
|
return redirect(route('preferences.index'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class CronController
|
|||||||
$results = [];
|
$results = [];
|
||||||
$results[] = $this->runRecurring();
|
$results[] = $this->runRecurring();
|
||||||
$results[] = $this->runAutoBudget();
|
$results[] = $this->runAutoBudget();
|
||||||
|
$results[] = $this->runTelemetry();
|
||||||
|
|
||||||
return implode("<br>\n", $results);
|
return implode("<br>\n", $results);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ class TagController extends Controller
|
|||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
session()->flash('success', (string) trans('firefly.deleted_x_tags', ['count' => $count]));
|
session()->flash('success', (string) trans_choice('firefly.deleted_x_tags', $count));
|
||||||
|
|
||||||
return redirect(route('tags.index'));
|
return redirect(route('tags.index'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ class BulkController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
$request->session()->flash('success', (string) trans('firefly.mass_edited_transactions_success', ['amount' => $count]));
|
$request->session()->flash('success', (string) trans_choice('firefly.mass_edited_transactions_success', $count));
|
||||||
|
|
||||||
// redirect to previous URL:
|
// redirect to previous URL:
|
||||||
return redirect($this->getPreviousUri('transactions.bulk-edit.uri'));
|
return redirect($this->getPreviousUri('transactions.bulk-edit.uri'));
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class MassController extends Controller
|
|||||||
|
|
||||||
|
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
session()->flash('success', (string) trans('firefly.mass_deleted_transactions_success', ['amount' => $count]));
|
session()->flash('success', (string) trans_choice('firefly.mass_deleted_transactions_success', $count));
|
||||||
|
|
||||||
// redirect to previous URL:
|
// redirect to previous URL:
|
||||||
return redirect($this->getPreviousUri('transactions.mass-delete.uri'));
|
return redirect($this->getPreviousUri('transactions.mass-delete.uri'));
|
||||||
@@ -188,7 +188,7 @@ class MassController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
session()->flash('success', (string) trans('firefly.mass_edited_transactions_success', ['amount' => $count]));
|
session()->flash('success', (string) trans_choice('firefly.mass_edited_transactions_success', $count ));
|
||||||
|
|
||||||
// redirect to previous URL:
|
// redirect to previous URL:
|
||||||
return redirect($this->getPreviousUri('transactions.mass-edit.uri'));
|
return redirect($this->getPreviousUri('transactions.mass-edit.uri'));
|
||||||
|
|||||||
@@ -99,8 +99,9 @@ class ShowController extends Controller
|
|||||||
$transformer->setParameters(new ParameterBag);
|
$transformer->setParameters(new ParameterBag);
|
||||||
$groupArray = $transformer->transformObject($transactionGroup);
|
$groupArray = $transformer->transformObject($transactionGroup);
|
||||||
|
|
||||||
// do some amount calculations:
|
// do some calculations:
|
||||||
$amounts = $this->getAmounts($groupArray);
|
$amounts = $this->getAmounts($groupArray);
|
||||||
|
$accounts = $this->getAccounts($groupArray);
|
||||||
|
|
||||||
// make sure notes are escaped but not double escaped.
|
// make sure notes are escaped but not double escaped.
|
||||||
foreach ($groupArray['transactions'] as $index => $transaction) {
|
foreach ($groupArray['transactions'] as $index => $transaction) {
|
||||||
@@ -127,7 +128,8 @@ class ShowController extends Controller
|
|||||||
'groupArray',
|
'groupArray',
|
||||||
'events',
|
'events',
|
||||||
'attachments',
|
'attachments',
|
||||||
'links'
|
'links',
|
||||||
|
'accounts',
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -166,4 +168,31 @@ class ShowController extends Controller
|
|||||||
|
|
||||||
return $amounts;
|
return $amounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $group
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getAccounts(array $group): array
|
||||||
|
{
|
||||||
|
$accounts = [];
|
||||||
|
|
||||||
|
foreach ($group['transactions'] as $index => $transaction) {
|
||||||
|
$accounts['source'][] = [
|
||||||
|
'type' => $transaction['source_type'],
|
||||||
|
'id' => $transaction['source_id'],
|
||||||
|
'name' => $transaction['source_name'],
|
||||||
|
'iban' => $transaction['source_iban'] ];
|
||||||
|
$accounts['destination'][] = [
|
||||||
|
'type' => $transaction['destination_type'],
|
||||||
|
'id' => $transaction['destination_id'],
|
||||||
|
'name' => $transaction['destination_name'],
|
||||||
|
'iban' => $transaction['destination_iban'] ];
|
||||||
|
}
|
||||||
|
|
||||||
|
$accounts['source'] = array_unique($accounts['source'], SORT_REGULAR);
|
||||||
|
$accounts['destination'] = array_unique($accounts['destination'], SORT_REGULAR);
|
||||||
|
return $accounts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,7 @@ namespace FireflyIII\Http\Middleware;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use Log;
|
use FireflyIII\Support\System\GeneratesInstallationId;
|
||||||
use Ramsey\Uuid\Uuid;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -35,6 +34,7 @@ use Ramsey\Uuid\Uuid;
|
|||||||
*/
|
*/
|
||||||
class InstallationId
|
class InstallationId
|
||||||
{
|
{
|
||||||
|
use GeneratesInstallationId;
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
*
|
*
|
||||||
@@ -48,13 +48,7 @@ class InstallationId
|
|||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
$config = app('fireflyconfig')->get('installation_id', null);
|
$this->generateInstallationId();
|
||||||
if (null === $config) {
|
|
||||||
$uuid5 = Uuid::uuid5(Uuid::NAMESPACE_URL, 'firefly-iii.org');
|
|
||||||
$uniqueId = (string) $uuid5;
|
|
||||||
Log::info(sprintf('Created Firefly III installation ID %s', $uniqueId));
|
|
||||||
app('fireflyconfig')->set('installation_id', $uniqueId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use Closure;
|
|||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
use FireflyIII\Support\Http\Controllers\RequestInformation;
|
use FireflyIII\Support\Http\Controllers\RequestInformation;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SessionFilter.
|
* Class SessionFilter.
|
||||||
@@ -87,6 +88,7 @@ class Range
|
|||||||
|
|
||||||
// send error to view if could not set money format
|
// send error to view if could not set money format
|
||||||
if (false === $moneyResult) {
|
if (false === $moneyResult) {
|
||||||
|
Log::error('Could not set locale. The following array doesnt work: ', $localeArray);
|
||||||
app('view')->share('invalidMonetaryLocale', true); // @codeCoverageIgnore
|
app('view')->share('invalidMonetaryLocale', true); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class MailError extends Job implements ShouldQueue
|
|||||||
$args,
|
$args,
|
||||||
function (Message $message) use ($email) {
|
function (Message $message) use ($email) {
|
||||||
if ('mail@example.com' !== $email) {
|
if ('mail@example.com' !== $email) {
|
||||||
$message->to($email, $email)->subject('Caught an error in Firefly III');
|
$message->to($email, $email)->subject((string) trans('email.error_subject'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace FireflyIII\Jobs;
|
|||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Telemetry;
|
use FireflyIII\Models\Telemetry;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\Exception\GuzzleException;
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
@@ -33,7 +34,9 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
|||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use JsonException;
|
||||||
use Log;
|
use Log;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SubmitTelemetryData
|
* Class SubmitTelemetryData
|
||||||
@@ -61,7 +64,7 @@ class SubmitTelemetryData implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
@@ -77,9 +80,17 @@ class SubmitTelemetryData implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$json = $this->parseJson($telemetry);
|
$json = $this->parseJson($telemetry);
|
||||||
|
try {
|
||||||
|
$body = json_encode($json, JSON_THROW_ON_ERROR, 512);
|
||||||
|
} catch (JsonException $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
Log::error('Could not parse JSON.');
|
||||||
|
throw new FireflyException(sprintf('Could not parse telemetry JSON: %s', $e->getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
$client = new Client;
|
$client = new Client;
|
||||||
$options = [
|
$options = [
|
||||||
'body' => json_encode($json, JSON_THROW_ON_ERROR, 512),
|
'body' => $body,
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'Content-Type' => 'application/json',
|
'Content-Type' => 'application/json',
|
||||||
'Accept' => 'application/json',
|
'Accept' => 'application/json',
|
||||||
@@ -89,11 +100,11 @@ class SubmitTelemetryData implements ShouldQueue
|
|||||||
];
|
];
|
||||||
try {
|
try {
|
||||||
$result = $client->post($url, $options);
|
$result = $client->post($url, $options);
|
||||||
} catch (GuzzleException $e) {
|
} catch (GuzzleException|Exception $e) {
|
||||||
Log::error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
Log::error($e->getTraceAsString());
|
Log::error($e->getTraceAsString());
|
||||||
Log::error('Could not submit telemetry.');
|
Log::error('Could not submit telemetry.');
|
||||||
return;
|
throw new FireflyException(sprintf('Could not submit telemetry: %s', $e->getMessage()));
|
||||||
}
|
}
|
||||||
$body = (string) $result->getBody();
|
$body = (string) $result->getBody();
|
||||||
$statusCode = $result->getStatusCode();
|
$statusCode = $result->getStatusCode();
|
||||||
@@ -156,6 +167,7 @@ class SubmitTelemetryData implements ShouldQueue
|
|||||||
foreach ($telemetry as $entry) {
|
foreach ($telemetry as $entry) {
|
||||||
$array[] = [
|
$array[] = [
|
||||||
'installation_id' => $entry->installation_id,
|
'installation_id' => $entry->installation_id,
|
||||||
|
'collected_at' => $entry->created_at->format('r'),
|
||||||
'type' => $entry->type,
|
'type' => $entry->type,
|
||||||
'key' => $entry->key,
|
'key' => $entry->key,
|
||||||
'value' => $entry->value,
|
'value' => $entry->value,
|
||||||
|
|||||||
@@ -63,6 +63,6 @@ class AccessTokenCreatedMail extends Mailable
|
|||||||
public function build(): self
|
public function build(): self
|
||||||
{
|
{
|
||||||
return $this->view('emails.access-token-created-html')->text('emails.access-token-created-text')
|
return $this->view('emails.access-token-created-html')->text('emails.access-token-created-text')
|
||||||
->subject('A new access token was created');
|
->subject((string) trans('email.access_token_created_subject'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,6 @@ class AdminTestMail extends Mailable
|
|||||||
public function build(): self
|
public function build(): self
|
||||||
{
|
{
|
||||||
return $this->view('emails.admin-test-html')->text('emails.admin-test-text')
|
return $this->view('emails.admin-test-html')->text('emails.admin-test-text')
|
||||||
->subject('A test message from your Firefly III installation');
|
->subject((string) trans('email.admin_test_subject'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,6 @@ class ConfirmEmailChangeMail extends Mailable
|
|||||||
public function build(): self
|
public function build(): self
|
||||||
{
|
{
|
||||||
return $this->view('emails.confirm-email-change-html')->text('emails.confirm-email-change-text')
|
return $this->view('emails.confirm-email-change-html')->text('emails.confirm-email-change-text')
|
||||||
->subject('Your Firefly III email address has changed');
|
->subject((string) trans('email.email_change_subject'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,6 @@ class OAuthTokenCreatedMail extends Mailable
|
|||||||
public function build(): self
|
public function build(): self
|
||||||
{
|
{
|
||||||
return $this->view('emails.oauth-client-created-html')->text('emails.oauth-client-created-text')
|
return $this->view('emails.oauth-client-created-html')->text('emails.oauth-client-created-text')
|
||||||
->subject('A new OAuth client has been created');
|
->subject((string) trans('email.oauth_created_subject'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,6 @@ class RegisteredUser extends Mailable
|
|||||||
*/
|
*/
|
||||||
public function build(): self
|
public function build(): self
|
||||||
{
|
{
|
||||||
return $this->view('emails.registered-html')->text('emails.registered-text')->subject('Welcome to Firefly III!');
|
return $this->view('emails.registered-html')->text('emails.registered-text')->subject((string) trans('email.registered_subject'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class ReportNewJournalsMail extends Mailable
|
|||||||
$this->transform();
|
$this->transform();
|
||||||
|
|
||||||
return $this->view('emails.report-new-journals-html')->text('emails.report-new-journals-text')
|
return $this->view('emails.report-new-journals-html')->text('emails.report-new-journals-text')
|
||||||
->subject($subject);
|
->subject((string) trans_choice('email.new_journals_subject', $this->groups->count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function transform(): void
|
private function transform(): void
|
||||||
|
|||||||
@@ -60,6 +60,6 @@ class RequestedNewPassword extends Mailable
|
|||||||
*/
|
*/
|
||||||
public function build(): self
|
public function build(): self
|
||||||
{
|
{
|
||||||
return $this->view('emails.password-html')->text('emails.password-text')->subject('Your password reset request');
|
return $this->view('emails.password-html')->text('emails.password-text')->subject((string) trans('email.reset_pw_subject'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,6 @@ class UndoEmailChangeMail extends Mailable
|
|||||||
public function build(): self
|
public function build(): self
|
||||||
{
|
{
|
||||||
return $this->view('emails.undo-email-change-html')->text('emails.undo-email-change-text')
|
return $this->view('emails.undo-email-change-html')->text('emails.undo-email-change-text')
|
||||||
->subject('Your Firefly III email address has changed');
|
->subject((string) trans('email.email_change_subject'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
app/Models/ObjectGroup.php
Normal file
21
app/Models/ObjectGroup.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ObjectGroup
|
||||||
|
*/
|
||||||
|
class ObjectGroup extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||||
|
*/
|
||||||
|
public function piggyBanks()
|
||||||
|
{
|
||||||
|
return $this->morphedByMany(PiggyBank::class, 'object_groupable');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -126,6 +126,14 @@ class PiggyBank extends Model
|
|||||||
throw new NotFoundHttpException;
|
throw new NotFoundHttpException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the tags for the post.
|
||||||
|
*/
|
||||||
|
public function objectGroups()
|
||||||
|
{
|
||||||
|
return $this->morphToMany(ObjectGroup::class, 'object_groupable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return MorphMany
|
* @return MorphMany
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
// create initial budget limit.
|
// create initial budget limit.
|
||||||
$today = new Carbon;
|
$today = new Carbon;
|
||||||
$start = app('navigation')->startOfPeriod($today, $autoBudget->period);
|
$start = app('navigation')->startOfPeriod($today, $autoBudget->period);
|
||||||
$end = app('navigation')->startOfPeriod($start, $autoBudget->period);
|
$end = app('navigation')->endOfPeriod($start, $autoBudget->period);
|
||||||
|
|
||||||
$limitRepos = app(BudgetLimitRepositoryInterface::class);
|
$limitRepos = app(BudgetLimitRepositoryInterface::class);
|
||||||
$limitRepos->setUser($this->user);
|
$limitRepos->setUser($this->user);
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ class UpdateRequest implements UpdateRequestInterface
|
|||||||
'headers' => [
|
'headers' => [
|
||||||
'User-Agent' => sprintf('FireflyIII/%s/%s', config('firefly.version'), $channel),
|
'User-Agent' => sprintf('FireflyIII/%s/%s', config('firefly.version'), $channel),
|
||||||
],
|
],
|
||||||
|
'timeout' => 3.1415
|
||||||
];
|
];
|
||||||
$res = $client->request('GET', $uri, $options);
|
$res = $client->request('GET', $uri, $options);
|
||||||
} catch (GuzzleException|Exception $e) {
|
} catch (GuzzleException|Exception $e) {
|
||||||
|
|||||||
@@ -52,11 +52,10 @@ class AccountList implements BinderInterface
|
|||||||
/** @var Collection $collection */
|
/** @var Collection $collection */
|
||||||
$collection = auth()->user()->accounts()
|
$collection = auth()->user()->accounts()
|
||||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||||
->where('account_types.type', AccountType::ASSET)
|
->whereIn('account_types.type', [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE])
|
||||||
->orderBy('accounts.name', 'ASC')
|
->orderBy('accounts.name', 'ASC')
|
||||||
->get(['accounts.*']);
|
->get(['accounts.*']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('allAssetAccounts' !== $value) {
|
if ('allAssetAccounts' !== $value) {
|
||||||
$incoming = array_map('\intval', explode(',', $value));
|
$incoming = array_map('\intval', explode(',', $value));
|
||||||
$list = array_merge(array_unique($incoming), [0]);
|
$list = array_merge(array_unique($incoming), [0]);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Support\Cronjobs;
|
namespace FireflyIII\Support\Cronjobs;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Jobs\SubmitTelemetryData;
|
use FireflyIII\Jobs\SubmitTelemetryData;
|
||||||
use FireflyIII\Models\Configuration;
|
use FireflyIII\Models\Configuration;
|
||||||
use Log;
|
use Log;
|
||||||
@@ -35,9 +36,17 @@ class TelemetryCronjob extends AbstractCronjob
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function fire(): bool
|
public function fire(): bool
|
||||||
{
|
{
|
||||||
|
// do not fire if telemetry is disabled.
|
||||||
|
if (false === config('firefly.send_telemetry') || false === config('firefly.feature_flags.telemetry')) {
|
||||||
|
Log::warning('Telemetry is disabled. The cron job will do nothing.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @var Configuration $config */
|
/** @var Configuration $config */
|
||||||
$config = app('fireflyconfig')->get('last_tm_job', 0);
|
$config = app('fireflyconfig')->get('last_tm_job', 0);
|
||||||
$lastTime = (int) $config->data;
|
$lastTime = (int) $config->data;
|
||||||
@@ -46,8 +55,8 @@ class TelemetryCronjob extends AbstractCronjob
|
|||||||
if (0 === $lastTime) {
|
if (0 === $lastTime) {
|
||||||
Log::info('Telemetry cron-job has never fired before.');
|
Log::info('Telemetry cron-job has never fired before.');
|
||||||
}
|
}
|
||||||
// less than half a day ago:
|
// less than a week ago:
|
||||||
if ($lastTime > 0 && $diff <= 43200) {
|
if ($lastTime > 0 && $diff <= 604800) {
|
||||||
Log::info(sprintf('It has been %s since the telemetry cron-job has fired.', $diffForHumans));
|
Log::info(sprintf('It has been %s since the telemetry cron-job has fired.', $diffForHumans));
|
||||||
if (false === $this->force) {
|
if (false === $this->force) {
|
||||||
Log::info('The cron-job will not fire now.');
|
Log::info('The cron-job will not fire now.');
|
||||||
@@ -60,8 +69,8 @@ class TelemetryCronjob extends AbstractCronjob
|
|||||||
Log::info('Execution of the telemetry cron-job has been FORCED.');
|
Log::info('Execution of the telemetry cron-job has been FORCED.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// more than a week ago.
|
||||||
if ($lastTime > 0 && $diff > 43200) {
|
if ($lastTime > 0 && $diff > 604799) {
|
||||||
Log::info(sprintf('It has been %s since the telemetry cron-job has fired. It will fire now!', $diffForHumans));
|
Log::info(sprintf('It has been %s since the telemetry cron-job has fired. It will fire now!', $diffForHumans));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +83,7 @@ class TelemetryCronjob extends AbstractCronjob
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
private function fireTelemetry(): void
|
private function fireTelemetry(): void
|
||||||
{
|
{
|
||||||
@@ -84,6 +93,9 @@ class TelemetryCronjob extends AbstractCronjob
|
|||||||
$job->setDate($this->date);
|
$job->setDate($this->date);
|
||||||
$job->setForce($this->force);
|
$job->setForce($this->force);
|
||||||
$job->handle();
|
$job->handle();
|
||||||
|
|
||||||
|
// TODO remove old, submitted telemetry data.
|
||||||
|
|
||||||
app('fireflyconfig')->set('last_tm_job', (int) $this->date->format('U'));
|
app('fireflyconfig')->set('last_tm_job', (int) $this->date->format('U'));
|
||||||
Log::info('Done with telemetry cron job task.');
|
Log::info('Done with telemetry cron job task.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -436,4 +436,33 @@ class ExpandedForm
|
|||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null $value
|
||||||
|
* @param array|null $options
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function objectGroup($value = null, array $options = null): string
|
||||||
|
{
|
||||||
|
$name = 'object_group';
|
||||||
|
$label = $this->label($name, $options);
|
||||||
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
|
$classes = $this->getHolderClasses($name);
|
||||||
|
$value = $this->fillFieldValue($name, $value);
|
||||||
|
$options['rows'] = 4;
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
$value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$html = view('form.object_group', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Log::debug(sprintf('Could not render objectGroup(): %s', $e->getMessage()));
|
||||||
|
$html = 'Could not render objectGroup.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Support\Http\Controllers;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Support\Cronjobs\AutoBudgetCronjob;
|
use FireflyIII\Support\Cronjobs\AutoBudgetCronjob;
|
||||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||||
|
use FireflyIII\Support\Cronjobs\TelemetryCronjob;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trait CronRunner
|
* Trait CronRunner
|
||||||
@@ -51,6 +52,24 @@ trait CronRunner
|
|||||||
return 'The recurring transaction cron job fired successfully.';
|
return 'The recurring transaction cron job fired successfully.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function runTelemetry(): string {
|
||||||
|
/** @var TelemetryCronjob $telemetry */
|
||||||
|
$telemetry = app(TelemetryCronjob::class);
|
||||||
|
try {
|
||||||
|
$result = $telemetry->fire();
|
||||||
|
} catch (FireflyException $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
if (false === $result) {
|
||||||
|
return 'The telemetry cron job did not fire.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'The telemetry cron job fired successfully.';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class Steam
|
|||||||
|
|
||||||
$transactions = $account->transactions()
|
$transactions = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
|
||||||
->where('transactions.transaction_currency_id', $currencyId)
|
->where('transactions.transaction_currency_id', $currencyId)
|
||||||
->get(['transactions.amount'])->toArray();
|
->get(['transactions.amount'])->toArray();
|
||||||
$nativeBalance = $this->sumTransactions($transactions, 'amount');
|
$nativeBalance = $this->sumTransactions($transactions, 'amount');
|
||||||
@@ -131,7 +131,7 @@ class Steam
|
|||||||
// get all balances in foreign currency:
|
// get all balances in foreign currency:
|
||||||
$transactions = $account->transactions()
|
$transactions = $account->transactions()
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
|
||||||
->where('transactions.foreign_currency_id', $currencyId)
|
->where('transactions.foreign_currency_id', $currencyId)
|
||||||
->where('transactions.transaction_currency_id', '!=', $currencyId)
|
->where('transactions.transaction_currency_id', '!=', $currencyId)
|
||||||
->get(['transactions.foreign_amount'])->toArray();
|
->get(['transactions.foreign_amount'])->toArray();
|
||||||
|
|||||||
28
app/Support/System/GeneratesInstallationId.php
Normal file
28
app/Support/System/GeneratesInstallationId.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\System;
|
||||||
|
|
||||||
|
use Log;
|
||||||
|
use Ramsey\Uuid\Uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trait GeneratesInstallationId
|
||||||
|
*/
|
||||||
|
trait GeneratesInstallationId
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function generateInstallationId(): void
|
||||||
|
{
|
||||||
|
$config = app('fireflyconfig')->get('installation_id', null);
|
||||||
|
if (null === $config) {
|
||||||
|
$uuid5 = Uuid::uuid5(Uuid::NAMESPACE_URL, 'firefly-iii.org');
|
||||||
|
$uniqueId = (string) $uuid5;
|
||||||
|
Log::info(sprintf('Created Firefly III installation ID %s', $uniqueId));
|
||||||
|
app('fireflyconfig')->set('installation_id', $uniqueId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ namespace FireflyIII\Support;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Models\Telemetry as TelemetryModel;
|
use FireflyIII\Models\Telemetry as TelemetryModel;
|
||||||
|
use FireflyIII\Support\System\GeneratesInstallationId;
|
||||||
use JsonException;
|
use JsonException;
|
||||||
use Log;
|
use Log;
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ use Log;
|
|||||||
*/
|
*/
|
||||||
class Telemetry
|
class Telemetry
|
||||||
{
|
{
|
||||||
|
use GeneratesInstallationId;
|
||||||
/**
|
/**
|
||||||
* Feature telemetry stores a $value for the given $feature.
|
* Feature telemetry stores a $value for the given $feature.
|
||||||
* Will only store the given $feature / $value combination once.
|
* Will only store the given $feature / $value combination once.
|
||||||
@@ -166,9 +168,12 @@ class Telemetry
|
|||||||
*/
|
*/
|
||||||
private function storeEntry(string $type, string $name, string $value): void
|
private function storeEntry(string $type, string $name, string $value): void
|
||||||
{
|
{
|
||||||
|
$this->generateInstallationId();
|
||||||
|
$config = app('fireflyconfig')->get('installation_id', null);
|
||||||
|
$installationId = null !== $config ? $config->data : 'empty';
|
||||||
TelemetryModel::create(
|
TelemetryModel::create(
|
||||||
[
|
[
|
||||||
'installation_id' => \FireflyConfig::get('installation_id', '')->data,
|
'installation_id' => $installationId,
|
||||||
'key' => $name,
|
'key' => $name,
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
'value' => $value,
|
'value' => $value,
|
||||||
|
|||||||
99
app/TransactionRules/Triggers/ForeignCurrencyIs.php
Normal file
99
app/TransactionRules/Triggers/ForeignCurrencyIs.php
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ForeignCurrencyIs.php
|
||||||
|
* Copyright (c) 2019 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\TransactionRules\Triggers;
|
||||||
|
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ForeignCurrencyIs.
|
||||||
|
*/
|
||||||
|
final class ForeignCurrencyIs extends AbstractTrigger implements TriggerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A trigger is said to "match anything", or match any given transaction,
|
||||||
|
* when the trigger value is very vague or has no restrictions. Easy examples
|
||||||
|
* are the "AmountMore"-trigger combined with an amount of 0: any given transaction
|
||||||
|
* has an amount of more than zero! Other examples are all the "Description"-triggers
|
||||||
|
* which have hard time handling empty trigger values such as "" or "*" (wild cards).
|
||||||
|
*
|
||||||
|
* If the user tries to create such a trigger, this method MUST return true so Firefly III
|
||||||
|
* can stop the storing / updating the trigger. If the trigger is in any way restrictive
|
||||||
|
* (even if it will still include 99.9% of the users transactions), this method MUST return
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function willMatchEverything($value = null): bool
|
||||||
|
{
|
||||||
|
if (null !== $value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::error(sprintf('Cannot use %s with a null value.', self::class));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when description is X
|
||||||
|
*
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function triggered(TransactionJournal $journal): bool
|
||||||
|
{
|
||||||
|
/** @var CurrencyRepositoryInterface $repository */
|
||||||
|
$repository = app(CurrencyRepositoryInterface::class);
|
||||||
|
|
||||||
|
// if currency name contains " ("
|
||||||
|
if (0 === strpos($this->triggerValue, ' (')) {
|
||||||
|
$parts = explode(' (', $this->triggerValue);
|
||||||
|
$this->triggerValue = $parts[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$currency = $repository->findByNameNull($this->triggerValue);
|
||||||
|
$hit = true;
|
||||||
|
if (null !== $currency) {
|
||||||
|
/** @var Transaction $transaction */
|
||||||
|
foreach ($journal->transactions as $transaction) {
|
||||||
|
if ((int)$transaction->foreign_currency_id !== (int)$currency->id) {
|
||||||
|
Log::debug(
|
||||||
|
sprintf(
|
||||||
|
'Trigger ForeignCurrencyIs: Transaction #%d in journal #%d uses currency %d instead of sought for #%d. No hit!',
|
||||||
|
$transaction->id, $journal->id, $transaction->foreign_currency_id, $currency->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$hit = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hit;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
changelog.md
39
changelog.md
@@ -2,10 +2,45 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [5.2.7 (API 1.1.0) - 2020-06-01
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Firefly III **optional + opt-in** telemetry can now be enabled, if you want to. Read more about it [here](https://docs.firefly-iii.org/support/telemetry).
|
||||||
|
- [Issue 3133](https://github.com/firefly-iii/firefly-iii/issues/3133) You can remove attachments before you create a transaction.
|
||||||
|
- [Issue 3395](https://github.com/firefly-iii/firefly-iii/issues/3395) Emails sent by Firefly III have been translated. See the note at the bottom. Thanks to @sephrat
|
||||||
|
- [Issue 3393](https://github.com/firefly-iii/firefly-iii/issues/3393) New SSL options for LDAP and MySQL. Thanks to @sephrat
|
||||||
|
- [Issue 3413](https://github.com/firefly-iii/firefly-iii/issues/3413) Better string pluralization. Thanks to @sephrat
|
||||||
|
- [Issue 3297](https://github.com/firefly-iii/firefly-iii/issues/3297) Rule trigger for foreign currency ID
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- The default Docker Compose configuration and documentation switched from PostgreSQL to MariaDB. This will NOT affect existing installations unless you
|
||||||
|
change your docker compose file.
|
||||||
|
- [Issue 3404](https://github.com/firefly-iii/firefly-iii/issues/3404) The profile page has been translated. See the note at the bottom. Thanks to @sephrat
|
||||||
|
- [Issue 3405](https://github.com/firefly-iii/firefly-iii/issues/3405) All error pages have been translated. See the note at the bottom. Thanks to @sephrat
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
- Initial release.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Initial release.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [Issue 3309](https://github.com/firefly-iii/firefly-iii/issues/3309) New budgets would create bad budget limits.
|
||||||
|
- [Issue 3390](https://github.com/firefly-iii/firefly-iii/issues/3390) Typos and minor text inconsistencies fixed by @sephrat
|
||||||
|
- [Issue 3407](https://github.com/firefly-iii/firefly-iii/issues/3407) [issue 3408](https://github.com/firefly-iii/firefly-iii/issues/3408) The total transaction amount displayed is no longer empty for opening balances by @sephrat
|
||||||
|
- [Issue 3409](https://github.com/firefly-iii/firefly-iii/issues/3409) [issue 3420](https://github.com/firefly-iii/firefly-iii/issues/3420) Double accounts no longer listed by @sephrat
|
||||||
|
- [Issue 3427](https://github.com/firefly-iii/firefly-iii/issues/3427) Add a time-out to version update check. More improvements are coming.
|
||||||
|
- [Issue 3419](https://github.com/firefly-iii/firefly-iii/issues/3419) Error fixed which would prevent you from adding money to a piggy bank, by @sephrat
|
||||||
|
- [Issue 3425](https://github.com/firefly-iii/firefly-iii/issues/3425) Budget amount had no validation.
|
||||||
|
- [Issue 3428](https://github.com/firefly-iii/firefly-iii/issues/3428) Reconciliation "select all"-button would miscalculate.
|
||||||
|
- [Issue 3415](https://github.com/firefly-iii/firefly-iii/issues/3415) New error views
|
||||||
|
|
||||||
|
A note about new translations: text you see in errors and emails may still be in English. This is not a bug. Translated text is sometimes generated outside of
|
||||||
|
what's called the user's "session". When Firefly III operates outside of your session, it can't access your preferences or your data. It doesn't know what
|
||||||
|
language to pick. You can set the `DEFAULT_LANGUAGE`-environment variable. But user specific preferences may be ignored.
|
||||||
|
|
||||||
## [5.2.6 (API 1.1.0)] - 2020-05-22
|
## [5.2.6 (API 1.1.0)] - 2020-05-22
|
||||||
|
|
||||||
|
|
||||||
## [3.4.2] - 2015-05-25
|
|
||||||
### Added
|
### Added
|
||||||
- [Issue 3049](https://github.com/firefly-iii/firefly-iii/issues/3049) New transaction triggers for dates.
|
- [Issue 3049](https://github.com/firefly-iii/firefly-iii/issues/3049) New transaction triggers for dates.
|
||||||
- Warning if recurring transactions no longer run.
|
- Warning if recurring transactions no longer run.
|
||||||
|
|||||||
@@ -94,11 +94,7 @@
|
|||||||
"laravelcollective/html": "6.*",
|
"laravelcollective/html": "6.*",
|
||||||
"league/commonmark": "1.*",
|
"league/commonmark": "1.*",
|
||||||
"league/csv": "9.*",
|
"league/csv": "9.*",
|
||||||
"league/flysystem-replicate-adapter": "1.*",
|
|
||||||
"league/flysystem-sftp": "1.*",
|
|
||||||
"league/fractal": "0.*",
|
"league/fractal": "0.*",
|
||||||
"litipk/flysystem-fallback-adapter": "0.*",
|
|
||||||
"mschindler83/fints-hbci-php": "1.*",
|
|
||||||
"pragmarx/google2fa": "^7.0",
|
"pragmarx/google2fa": "^7.0",
|
||||||
"pragmarx/recovery": "^0.1.0",
|
"pragmarx/recovery": "^0.1.0",
|
||||||
"predis/predis": "^1.1",
|
"predis/predis": "^1.1",
|
||||||
|
|||||||
745
composer.lock
generated
745
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,38 @@ if (!(false === $databaseUrl)) {
|
|||||||
$database = substr($options['path'] ?? '/firefly', 1);
|
$database = substr($options['path'] ?? '/firefly', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get SSL parameters from .env file.
|
||||||
|
*/
|
||||||
|
$mysql_ssl_ca_dir = envNonEmpty('MYSQL_SSL_CAPATH', null);
|
||||||
|
$mysql_ssl_ca_file = envNonEmpty('MYSQL_SSL_CA', null);
|
||||||
|
$mysql_ssl_cert = envNonEmpty('MYSQL_SSL_CERT', null);
|
||||||
|
$mysql_ssl_key = envNonEmpty('MYSQL_SSL_KEY', null);
|
||||||
|
$mysql_ssl_ciphers = envNonEmpty('MYSQL_SSL_CIPHER', null);
|
||||||
|
$mysql_ssl_verify = envNonEmpty('MYSQL_SSL_VERIFY_SERVER_CERT', null);
|
||||||
|
|
||||||
|
$mySqlSSLOptions = [];
|
||||||
|
if (false !== envNonEmpty('MYSQL_USE_SSL', false)) {
|
||||||
|
if (null !== $mysql_ssl_ca_dir) {
|
||||||
|
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CAPATH] = $mysql_ssl_ca_dir;
|
||||||
|
}
|
||||||
|
if (null !== $mysql_ssl_ca_file) {
|
||||||
|
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CA] = $mysql_ssl_ca_file;
|
||||||
|
}
|
||||||
|
if (null !== $mysql_ssl_cert) {
|
||||||
|
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CERT] = $mysql_ssl_cert;
|
||||||
|
}
|
||||||
|
if (null !== $mysql_ssl_key) {
|
||||||
|
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_KEY] = $mysql_ssl_key;
|
||||||
|
}
|
||||||
|
if (null !== $mysql_ssl_ciphers) {
|
||||||
|
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_CIPHER] = $mysql_ssl_ciphers;
|
||||||
|
}
|
||||||
|
if (null !== $mysql_ssl_verify) {
|
||||||
|
$mySqlSSLOptions[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $mysql_ssl_verify;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'default' => envNonEmpty('DB_CONNECTION', 'pgsql'),
|
'default' => envNonEmpty('DB_CONNECTION', 'pgsql'),
|
||||||
'connections' => [
|
'connections' => [
|
||||||
@@ -60,6 +92,7 @@ return [
|
|||||||
'prefix' => '',
|
'prefix' => '',
|
||||||
'strict' => true,
|
'strict' => true,
|
||||||
'engine' => 'InnoDB',
|
'engine' => 'InnoDB',
|
||||||
|
'options' => $mySqlSSLOptions,
|
||||||
],
|
],
|
||||||
'pgsql' => [
|
'pgsql' => [
|
||||||
'driver' => 'pgsql',
|
'driver' => 'pgsql',
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ use FireflyIII\TransactionRules\Triggers\AmountMore;
|
|||||||
use FireflyIII\TransactionRules\Triggers\BudgetIs;
|
use FireflyIII\TransactionRules\Triggers\BudgetIs;
|
||||||
use FireflyIII\TransactionRules\Triggers\CategoryIs;
|
use FireflyIII\TransactionRules\Triggers\CategoryIs;
|
||||||
use FireflyIII\TransactionRules\Triggers\CurrencyIs;
|
use FireflyIII\TransactionRules\Triggers\CurrencyIs;
|
||||||
|
use FireflyIII\TransactionRules\Triggers\ForeignCurrencyIs;
|
||||||
use FireflyIII\TransactionRules\Triggers\DateIs;
|
use FireflyIII\TransactionRules\Triggers\DateIs;
|
||||||
use FireflyIII\TransactionRules\Triggers\DateBefore;
|
use FireflyIII\TransactionRules\Triggers\DateBefore;
|
||||||
use FireflyIII\TransactionRules\Triggers\DateAfter;
|
use FireflyIII\TransactionRules\Triggers\DateAfter;
|
||||||
@@ -139,11 +140,11 @@ return [
|
|||||||
],
|
],
|
||||||
'feature_flags' => [
|
'feature_flags' => [
|
||||||
'export' => true,
|
'export' => true,
|
||||||
'telemetry' => false,
|
'telemetry' => true,
|
||||||
],
|
],
|
||||||
|
|
||||||
'encryption' => null === env('USE_ENCRYPTION') || true === env('USE_ENCRYPTION'),
|
'encryption' => null === env('USE_ENCRYPTION') || true === env('USE_ENCRYPTION'),
|
||||||
'version' => '5.2.6',
|
'version' => '5.2.7',
|
||||||
'api_version' => '1.1.0',
|
'api_version' => '1.1.0',
|
||||||
'db_version' => 13,
|
'db_version' => 13,
|
||||||
'maxUploadSize' => 15242880,
|
'maxUploadSize' => 15242880,
|
||||||
@@ -479,6 +480,7 @@ return [
|
|||||||
'budget_is' => BudgetIs::class,
|
'budget_is' => BudgetIs::class,
|
||||||
'tag_is' => TagIs::class,
|
'tag_is' => TagIs::class,
|
||||||
'currency_is' => CurrencyIs::class,
|
'currency_is' => CurrencyIs::class,
|
||||||
|
'foreign_currency_is' => ForeignCurrencyIs::class,
|
||||||
'has_attachments' => HasAttachment::class,
|
'has_attachments' => HasAttachment::class,
|
||||||
'has_no_category' => HasNoCategory::class,
|
'has_no_category' => HasNoCategory::class,
|
||||||
'has_any_category' => HasAnyCategory::class,
|
'has_any_category' => HasAnyCategory::class,
|
||||||
|
|||||||
@@ -38,6 +38,36 @@ if ('ActiveDirectory' === envNonEmpty('ADLDAP_CONNECTION_SCHEME', 'OpenLDAP')) {
|
|||||||
$schema = ActiveDirectory::class;
|
$schema = ActiveDirectory::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get SSL parameters from .env file.
|
||||||
|
*/
|
||||||
|
$ssl_ca_dir = envNonEmpty('ADLDAP_SSL_CACERTDIR', null);
|
||||||
|
$ssl_ca_file = envNonEmpty('ADLDAP_SSL_CACERTFILE', null);
|
||||||
|
$ssl_cert = envNonEmpty('ADLDAP_SSL_CERTFILE', null);
|
||||||
|
$ssl_key = envNonEmpty('ADLDAP_SSL_KEYFILE', null);
|
||||||
|
$ssl_ciphers = envNonEmpty('ADLDAP_SSL_CIPHER_SUITE', null);
|
||||||
|
$ssl_require = envNonEmpty('ADLDAP_SSL_REQUIRE_CERT', null);
|
||||||
|
|
||||||
|
$sslOptions = [];
|
||||||
|
if (null !== $ssl_ca_dir) {
|
||||||
|
$sslOptions[LDAP_OPT_X_TLS_CACERTDIR] = $ssl_ca_dir;
|
||||||
|
}
|
||||||
|
if (null !== $ssl_ca_file) {
|
||||||
|
$sslOptions[LDAP_OPT_X_TLS_CACERTFILE] = $ssl_ca_file;
|
||||||
|
}
|
||||||
|
if (null !== $ssl_cert) {
|
||||||
|
$sslOptions[LDAP_OPT_X_TLS_CERTFILE] = $ssl_cert;
|
||||||
|
}
|
||||||
|
if (null !== $ssl_key) {
|
||||||
|
$sslOptions[LDAP_OPT_X_TLS_KEYFILE] = $ssl_key;
|
||||||
|
}
|
||||||
|
if (null !== $ssl_ciphers) {
|
||||||
|
$sslOptions[LDAP_OPT_X_TLS_CIPHER_SUITE] = $ssl_ciphers;
|
||||||
|
}
|
||||||
|
if (null !== $ssl_require) {
|
||||||
|
$sslOptions[LDAP_OPT_X_TLS_REQUIRE_CERT] = $ssl_require;
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
@@ -254,6 +284,7 @@ return [
|
|||||||
'use_ssl' => env('ADLDAP_USE_SSL', false),
|
'use_ssl' => env('ADLDAP_USE_SSL', false),
|
||||||
'use_tls' => env('ADLDAP_USE_TLS', false),
|
'use_tls' => env('ADLDAP_USE_TLS', false),
|
||||||
|
|
||||||
|
'custom_options' => $sslOptions,
|
||||||
],
|
],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|||||||
22
public/v1/css/firefly.css
vendored
22
public/v1/css/firefly.css
vendored
@@ -108,26 +108,6 @@ body.waiting * {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ff-error-page {
|
|
||||||
width: 1000px;
|
|
||||||
margin: 20px auto 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ff-error-page > .error-content {
|
|
||||||
margin-left: 190px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ff-error-page > .error-content > h3 {
|
|
||||||
font-weight: 300;
|
|
||||||
font-size: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ff-error-box {
|
|
||||||
width: 460px;
|
|
||||||
margin: 7% auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cursors */
|
/* cursors */
|
||||||
.rule-triggers {
|
.rule-triggers {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
@@ -152,7 +132,7 @@ body.waiting * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.loading {
|
.loading {
|
||||||
background: url('/images/loading-small.gif') no-repeat center center;
|
background: url('/v1/images/loading-small.gif') no-repeat center center;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
public/v1/js/app.js
vendored
2
public/v1/js/app.js
vendored
File diff suppressed because one or more lines are too long
2
public/v1/js/app_vue.js
vendored
2
public/v1/js/app_vue.js
vendored
File diff suppressed because one or more lines are too long
2
public/v1/js/create_transaction.js
vendored
2
public/v1/js/create_transaction.js
vendored
File diff suppressed because one or more lines are too long
2
public/v1/js/edit_transaction.js
vendored
2
public/v1/js/edit_transaction.js
vendored
File diff suppressed because one or more lines are too long
4
public/v1/js/ff/accounts/reconcile.js
vendored
4
public/v1/js/ff/accounts/reconcile.js
vendored
@@ -90,6 +90,10 @@ function selectAllReconcile(e) {
|
|||||||
var identifier = 'checked_' + journalId;
|
var identifier = 'checked_' + journalId;
|
||||||
console.log('in selectAllReconcile(' + journalId + ') with amount ' + amount + ' and selected amount ' + selectedAmount);
|
console.log('in selectAllReconcile(' + journalId + ') with amount ' + amount + ' and selected amount ' + selectedAmount);
|
||||||
|
|
||||||
|
// do nothing if line is already in target state
|
||||||
|
if (check.prop('checked') === doCheck )
|
||||||
|
return;
|
||||||
|
|
||||||
check.prop('checked', doCheck);
|
check.prop('checked', doCheck);
|
||||||
// if checked, add to selected amount
|
// if checked, add to selected amount
|
||||||
if (doCheck === true && check.data('younger') === false) {
|
if (doCheck === true && check.data('younger') === false) {
|
||||||
|
|||||||
4
public/v1/js/ff/import/status.js
vendored
4
public/v1/js/ff/import/status.js
vendored
@@ -282,10 +282,10 @@ function reportOnErrors(data) {
|
|||||||
|
|
||||||
if (data.errors.length === 1) {
|
if (data.errors.length === 1) {
|
||||||
$('#import-status-error-intro').text(langImportSingleError);
|
$('#import-status-error-intro').text(langImportSingleError);
|
||||||
//'An error has occured during the import. The import can continue, however.'
|
//'An error has occurred during the import. The import can continue, however.'
|
||||||
}
|
}
|
||||||
if (data.errors.length > 1) {
|
if (data.errors.length > 1) {
|
||||||
// 'Errors have occured during the import. The import can continue, however.'
|
// 'Errors have occurred during the import. The import can continue, however.'
|
||||||
$('#import-status-error-intro').text(langImportMultiError);
|
$('#import-status-error-intro').text(langImportMultiError);
|
||||||
}
|
}
|
||||||
$('.info_errors').show();
|
$('.info_errors').show();
|
||||||
|
|||||||
1
public/v1/js/ff/rules/create-edit.js
vendored
1
public/v1/js/ff/rules/create-edit.js
vendored
@@ -350,6 +350,7 @@ function updateTriggerInput(selectList) {
|
|||||||
inputResult.typeahead('destroy');
|
inputResult.typeahead('destroy');
|
||||||
break;
|
break;
|
||||||
case 'currency_is':
|
case 'currency_is':
|
||||||
|
case 'foreign_currency_is':
|
||||||
console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.');
|
console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.');
|
||||||
createAutoComplete(inputResult, 'json/currency-names');
|
createAutoComplete(inputResult, 'json/currency-names');
|
||||||
break;
|
break;
|
||||||
|
|||||||
2
public/v1/js/profile.js
vendored
2
public/v1/js/profile.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,139 +0,0 @@
|
|||||||
<!--
|
|
||||||
- Index.vue
|
|
||||||
- Copyright (c) 2019 james@firefly-iii.org
|
|
||||||
-
|
|
||||||
- This file is part of Firefly III (https://github.com/firefly-iii).
|
|
||||||
-
|
|
||||||
- This program is free software: you can redistribute it and/or modify
|
|
||||||
- it under the terms of the GNU Affero General Public License as
|
|
||||||
- published by the Free Software Foundation, either version 3 of the
|
|
||||||
- License, or (at your option) any later version.
|
|
||||||
-
|
|
||||||
- This program is distributed in the hope that it will be useful,
|
|
||||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
- GNU Affero General Public License for more details.
|
|
||||||
-
|
|
||||||
- You should have received a copy of the GNU Affero General Public License
|
|
||||||
- along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<table class="table table-hover sortable">
|
|
||||||
<caption>Bills table</caption>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col" class="hidden-sm hidden-xs" data-defaultsort="disabled"> </th>
|
|
||||||
<th scope="col">{{ 'list.name' | trans }}</th>
|
|
||||||
<th scope="col"data-defaultsign="az" class="hidden-sm hidden-md hidden-xs">{{ 'list.matchesOn' | trans }}</th>
|
|
||||||
<th scope="col" data-defaultsign="_19" colspan="2">{{ 'list.amount' | trans }}</th>
|
|
||||||
<th scope="col" data-defaultsign="month" class="hidden-sm hidden-xs">{{ 'list.paid_current_period' | trans }}</th>
|
|
||||||
<th scope="col" data-defaultsign="month" class="hidden-sm hidden-xs">{{ 'list.next_expected_match' | trans }}</th>
|
|
||||||
<th scope="col" class="hidden-sm hidden-xs hidden-md">{{ 'list.active' | trans }}</th>
|
|
||||||
<th scope="col" class="hidden-sm hidden-xs hidden-md">{{ 'list.automatch' | trans }}</th>
|
|
||||||
<th scope="col" data-defaultsign="az" class="hidden-sm hidden-xs">{{ 'list.repeat_freq' | trans }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="(bill, index) in list">
|
|
||||||
<td class="hidden-sm hidden-xs">
|
|
||||||
<div class="btn-group btn-group-xs edit_tr_buttons"><a href="x" class="btn btn-default btn-xs"><i class="fa fa-fw fa-pencil"></i></a><a href="x" class="btn btn-danger btn-xs"><i class="fa fa-fw fa-trash-o"></i></a></div>
|
|
||||||
</td>
|
|
||||||
<td :data-value="bill.attributes.name">
|
|
||||||
<a href="x" :title="bill.attributes.name">{{ bill.attributes.name }}</a>
|
|
||||||
<i v-if='bill.attributes.attachments_count > 0' class="fa fa-paperclip"></i>
|
|
||||||
</td>
|
|
||||||
<td class="hidden-sm hidden-md hidden-xs">
|
|
||||||
<span v-for="(word) in bill.attributes.match"><span class="label label-info">{{ word }}</span> </span>
|
|
||||||
</td>
|
|
||||||
<td :data-value="bill.attributes.amount_min" style="text-align: right;">
|
|
||||||
<span style="margin-right:5px;" v-html="formatAmount(bill.attributes.amount_min)"></span>
|
|
||||||
</td>
|
|
||||||
<td :data-value="bill.attributes.amount_max" style="text-align: right;">
|
|
||||||
<span style="margin-right:5px;" v-html="formatAmount(bill.attributes.amount_max)"></span>
|
|
||||||
</td>
|
|
||||||
<!-- first two -->
|
|
||||||
<td v-if="bill.attributes.paid_dates.length == 0 && bill.attributes.pay_dates.length == 0 && bill.attributes.active" class="paid_in_period text-muted">
|
|
||||||
{{ 'components.not_expected_period' | trans }}
|
|
||||||
</td>
|
|
||||||
<td v-if="bill.attributes.paid_dates.length == 0 && bill.attributes.pay_dates.length == 0 && bill.attributes.active" class="expected_in_period hidden-sm hidden-xs">
|
|
||||||
{{ bill.attributes.next_expected_match|formatDate }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<!-- second set -->
|
|
||||||
<td v-if="bill.attributes.paid_dates.length == 0 && bill.attributes.pay_dates.length > 0 && bill.attributes.active" class="paid_in_period text-danger">
|
|
||||||
{{ 'components.not_or_not_yet' | trans }}
|
|
||||||
</td>
|
|
||||||
<td v-if="bill.attributes.paid_dates.length == 0 && bill.attributes.pay_dates.length > 0 && bill.attributes.active" class="expected_in_period hidden-sm hidden-xs">
|
|
||||||
{{ bill.attributes.next_expected_match|formatDate }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<!-- third set -->
|
|
||||||
<td v-if="bill.attributes.paid_dates.length > 0 && bill.attributes.active" class="paid_in_period text-success">
|
|
||||||
<span v-for="date in bill.attributes.paid_dates">{{ date|formatDate }}<br /></span>
|
|
||||||
</td>
|
|
||||||
<td v-if="bill.attributes.paid_dates.length > 0 && bill.attributes.active" class="expected_in_period hidden-sm hidden-xs">
|
|
||||||
{{ bill.attributes.next_expected_match|formatDate }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<!-- last set -->
|
|
||||||
<td v-if="bill.attributes.active === false" class="paid_in_period text-muted" data-value="0000-00-00 00-00-00">
|
|
||||||
~
|
|
||||||
</td>
|
|
||||||
<td v-if="bill.attributes.active === false" class="expected_in_period text-muted hidden-sm hidden-xs" data-value="0">
|
|
||||||
~
|
|
||||||
</td>
|
|
||||||
<td class="hidden-sm hidden-xs hidden-md" :data-value="bill.attributes.active">
|
|
||||||
<i v-if="bill.attributes.active === true" class="fa fa-fw fa-check"></i>
|
|
||||||
<i v-if="bill.attributes.active === false" class="fa fa-fw fa-ban"></i>
|
|
||||||
</td>
|
|
||||||
<td class="hidden-sm hidden-xs hidden-md" :data-value="bill.attributes.automatch">
|
|
||||||
<i v-if="bill.attributes.automatch === true" class="fa fa-fw fa-check"></i>
|
|
||||||
<i v-if="bill.attributes.automatch === false" class="fa fa-fw fa-ban"></i>
|
|
||||||
</td>
|
|
||||||
<td class="hidden-sm hidden-xs" :data-value="bill.attributes.repeat_freq + bill.attributes.skip">
|
|
||||||
{{ bill.attributes.repeat_freq }}
|
|
||||||
<span v-if="bill.attributes.skip > 0">Skips over {{ bill.attributes.skip }}</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<!--<button @click="deleteBill(bill.attributes.id)" class="btn btn-danger btn-xs pull-right">Delete</button>-->
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
list: [],
|
|
||||||
bill: {
|
|
||||||
id: '',
|
|
||||||
name: ''
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.fetchBillList();
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
formatAmount: Vue.filter('formatAmount'),
|
|
||||||
trans: Vue.filter('trans'),
|
|
||||||
fetchBillList() {
|
|
||||||
axios.get('api/v1/bill', {params: {start: window.sessionStart, end: window.sessionEnd}}).then((res) => {
|
|
||||||
this.list = res.data.data;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
deleteBill(id) {
|
|
||||||
axios.delete('api/bills/' + id)
|
|
||||||
.then((res) => {
|
|
||||||
this.fetchBillList()
|
|
||||||
})
|
|
||||||
.catch((err) => console.error(err));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user