mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-22 12:11:19 +00:00
Compare commits
66 Commits
5.1.0-beta
...
5.1.1
Author | SHA1 | Date | |
---|---|---|---|
|
b398924706 | ||
|
d6f46e23c5 | ||
|
8b4066a981 | ||
|
f8a695d7e1 | ||
|
630b24716d | ||
|
be41049e72 | ||
|
b726e7d106 | ||
|
1058bcd31d | ||
|
8724ba05ca | ||
|
5145707b94 | ||
|
3746cb8c71 | ||
|
624f2d0bfd | ||
|
1c397ad0ad | ||
|
a2c0f0666f | ||
|
72a4e86e2f | ||
|
5e8d94d16a | ||
|
d92b741088 | ||
|
2a4107940f | ||
|
16d5282929 | ||
|
f6ecb143fe | ||
|
f375934b41 | ||
|
9f8bf6d495 | ||
|
9e9b55da8e | ||
|
c1654f1d04 | ||
|
c526c4ae1a | ||
|
dcf1609c61 | ||
|
dd84c7f966 | ||
|
bccde86c0c | ||
|
2f17c45b3f | ||
|
b6bab003cd | ||
|
27d7eb4832 | ||
|
774f7d88c2 | ||
|
086e4d5880 | ||
|
50f4bf568b | ||
|
c218c70b1f | ||
|
a939a5ba30 | ||
|
25be550e6d | ||
|
9331f8985a | ||
|
41e6c8f73e | ||
|
a29f8d5849 | ||
|
9817c0807a | ||
|
4818baee39 | ||
|
379916ee08 | ||
|
60dbd51259 | ||
|
0927b0c8ae | ||
|
40cc510057 | ||
|
d580bf8f43 | ||
|
4434ea40ee | ||
|
2ba6ffccbc | ||
|
ec335ae88c | ||
|
542c64154c | ||
|
e4fa437f78 | ||
|
61f3f995ad | ||
|
8182cf1efa | ||
|
10d578503c | ||
|
75ee331f36 | ||
|
a32c484fd5 | ||
|
62d74e05f2 | ||
|
23ec5cbaa7 | ||
|
21fcb6f853 | ||
|
9b0a890531 | ||
|
af503597e6 | ||
|
e0c99fa80c | ||
|
a486d65893 | ||
|
08a6e22556 | ||
|
2d5c4c8101 |
@@ -24,6 +24,7 @@ DEFAULT_LANGUAGE=en_US
|
||||
|
||||
# Change this value to your preferred time zone.
|
||||
# Example: Europe/Amsterdam
|
||||
# For a list of supported time zones, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
TZ=Europe/Amsterdam
|
||||
|
||||
# This variable must match your installation's external address but keep in mind that
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\TransactionUpdateRequest;
|
||||
use FireflyIII\Events\StoredTransactionGroup;
|
||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@@ -294,10 +295,23 @@ class TransactionController extends Controller
|
||||
],
|
||||
];
|
||||
|
||||
return response()->json($response, 422);
|
||||
} catch(FireflyException $e) {
|
||||
Log::warning('Caught an exception. Return error message.');
|
||||
Log::error($e->getMessage());
|
||||
// return bad validation message.
|
||||
// TODO use Laravel's internal validation thing to do this.
|
||||
$response = [
|
||||
'message' => 'The given data was invalid.',
|
||||
'errors' => [
|
||||
'transactions.0.description' => [sprintf('Internal exception: %s',$e->getMessage())],
|
||||
],
|
||||
];
|
||||
|
||||
return response()->json($response, 422);
|
||||
}
|
||||
app('preferences')->mark();
|
||||
event(new StoredTransactionGroup($transactionGroup));
|
||||
event(new StoredTransactionGroup($transactionGroup, $data['apply_rules'] ?? true));
|
||||
|
||||
$manager = $this->getManager();
|
||||
/** @var User $admin */
|
||||
@@ -341,7 +355,7 @@ class TransactionController extends Controller
|
||||
$manager = $this->getManager();
|
||||
|
||||
app('preferences')->mark();
|
||||
event(new UpdatedTransactionGroup($transactionGroup));
|
||||
event(new UpdatedTransactionGroup($transactionGroup, $data['apply_rules'] ?? true));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
@@ -47,6 +47,7 @@ class TransactionStoreRequest extends Request
|
||||
public function authorize(): bool
|
||||
{
|
||||
Log::debug('Authorize TransactionStoreRequest');
|
||||
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
@@ -62,6 +63,7 @@ class TransactionStoreRequest extends Request
|
||||
$data = [
|
||||
'group_title' => $this->string('group_title'),
|
||||
'error_if_duplicate_hash' => $this->boolean('error_if_duplicate_hash'),
|
||||
'apply_rules' => $this->boolean('apply_rules', true),
|
||||
'transactions' => $this->getTransactionData(),
|
||||
];
|
||||
|
||||
@@ -80,6 +82,7 @@ class TransactionStoreRequest extends Request
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,1000|nullable',
|
||||
'error_if_duplicate_hash' => [new IsBoolean],
|
||||
'apply_rules' => [new IsBoolean],
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
@@ -263,11 +266,11 @@ class TransactionStoreRequest extends Request
|
||||
'tags' => $this->arrayFromValue($object['tags']),
|
||||
|
||||
// all custom fields:
|
||||
'internal_reference' => $this->stringFromValue($object['internal_reference']),
|
||||
'external_id' => $this->stringFromValue($object['external_id']),
|
||||
'internal_reference' => $this->stringFromValue((string)$object['internal_reference']),
|
||||
'external_id' => $this->stringFromValue((string)$object['external_id']),
|
||||
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
|
||||
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
|
||||
'bunq_payment_id' => $this->stringFromValue($object['bunq_payment_id']),
|
||||
'bunq_payment_id' => $this->stringFromValue((string)$object['bunq_payment_id']),
|
||||
|
||||
'sepa_cc' => $this->stringFromValue($object['sepa_cc']),
|
||||
'sepa_ct_op' => $this->stringFromValue($object['sepa_ct_op']),
|
||||
|
@@ -138,6 +138,7 @@ class TransactionUpdateRequest extends Request
|
||||
|
||||
$data = [
|
||||
'transactions' => $this->getTransactionData(),
|
||||
'apply_rules' => $this->boolean('apply_rules', true),
|
||||
];
|
||||
if ($this->has('group_title')) {
|
||||
$data['group_title'] = $this->string('group_title');
|
||||
@@ -156,6 +157,7 @@ class TransactionUpdateRequest extends Request
|
||||
$rules = [
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,1000',
|
||||
'apply_rules' => [new IsBoolean],
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
'transactions.*.type' => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
|
@@ -25,6 +25,9 @@ namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class SetLatestVersion
|
||||
*/
|
||||
class SetLatestVersion extends Command
|
||||
{
|
||||
/**
|
||||
@@ -53,19 +56,22 @@ class SetLatestVersion extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): int
|
||||
{
|
||||
if (!$this->option('james-is-cool')) {
|
||||
$this->error('Am too!');
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
app('fireflyconfig')->set('db_version', config('firefly.db_version'));
|
||||
app('fireflyconfig')->set('ff3_version', config('firefly.version'));
|
||||
$this->line('Updated version.');
|
||||
|
||||
//Telemetry::string('db_version', config('firefly.db_version'));
|
||||
//Telemetry::string('ff3_version', config('firefly.version'));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ class StoredTransactionGroup extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/** @var bool */
|
||||
public $applyRules;
|
||||
/** @var TransactionGroup The group that was stored. */
|
||||
public $transactionGroup;
|
||||
|
@@ -37,6 +37,8 @@ class UpdatedTransactionGroup extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/** @var bool */
|
||||
public $applyRules;
|
||||
/** @var TransactionGroup The group that was stored. */
|
||||
public $transactionGroup;
|
||||
|
||||
@@ -45,8 +47,9 @@ class UpdatedTransactionGroup extends Event
|
||||
*
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*/
|
||||
public function __construct(TransactionGroup $transactionGroup)
|
||||
public function __construct(TransactionGroup $transactionGroup, bool $applyRules = true)
|
||||
{
|
||||
$this->transactionGroup = $transactionGroup;
|
||||
$this->applyRules = $applyRules;
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -225,6 +226,10 @@ class GracefulNotFoundHandler extends ExceptionHandler
|
||||
$type = $journal->transactionType->type;
|
||||
$request->session()->reflash();
|
||||
|
||||
if (TransactionType::RECONCILIATION === $type) {
|
||||
return redirect(route('accounts.index', ['asset']));
|
||||
}
|
||||
|
||||
return redirect(route('transactions.index', [strtolower($type)]));
|
||||
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
@@ -102,12 +103,17 @@ class TransactionFactory
|
||||
/**
|
||||
* Create transaction with negative amount (for source accounts).
|
||||
*
|
||||
* @param string $amount
|
||||
* @param string $amount
|
||||
* @param string|null $foreignAmount
|
||||
* @return Transaction|null
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function createNegative(string $amount, ?string $foreignAmount): ?Transaction
|
||||
public function createNegative(string $amount, ?string $foreignAmount): Transaction
|
||||
{
|
||||
if ('' === $foreignAmount) {
|
||||
$foreignAmount = null;
|
||||
}
|
||||
if (null !== $foreignAmount) {
|
||||
$foreignAmount = app('steam')->negative($foreignAmount);
|
||||
}
|
||||
@@ -118,16 +124,20 @@ class TransactionFactory
|
||||
/**
|
||||
* Create transaction with positive amount (for destination accounts).
|
||||
*
|
||||
* @param string $amount
|
||||
* @param string $amount
|
||||
* @param string|null $foreignAmount
|
||||
* @return Transaction|null
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function createPositive(string $amount, ?string $foreignAmount): ?Transaction
|
||||
public function createPositive(string $amount, ?string $foreignAmount): Transaction
|
||||
{
|
||||
if ('' === $foreignAmount) {
|
||||
$foreignAmount = null;
|
||||
}
|
||||
if (null !== $foreignAmount) {
|
||||
$foreignAmount = app('steam')->positive($foreignAmount);
|
||||
}
|
||||
|
||||
return $this->create(app('steam')->positive($amount), $foreignAmount);
|
||||
}
|
||||
|
||||
@@ -151,14 +161,19 @@ class TransactionFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $amount
|
||||
* @param string $amount
|
||||
* @param string|null $foreignAmount
|
||||
* @return Transaction|null
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function create(string $amount, ?string $foreignAmount): ?Transaction
|
||||
private function create(string $amount, ?string $foreignAmount): Transaction
|
||||
{
|
||||
$result = null;
|
||||
$data = [
|
||||
if ('' === $foreignAmount) {
|
||||
$foreignAmount = null;
|
||||
}
|
||||
$data = [
|
||||
'reconciled' => $this->reconciled,
|
||||
'account_id' => $this->account->id,
|
||||
'transaction_journal_id' => $this->journal->id,
|
||||
@@ -174,6 +189,12 @@ class TransactionFactory
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (QueryException $e) {
|
||||
Log::error(sprintf('Could not create transaction: %s', $e->getMessage()), $data);
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
throw new FireflyException('Query exception when creating transaction.');
|
||||
}
|
||||
if (null === $result) {
|
||||
throw new FireflyException('Transaction is NULL.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
if (null !== $result) {
|
||||
@@ -185,7 +206,7 @@ class TransactionFactory
|
||||
);
|
||||
|
||||
// do foreign currency thing: add foreign currency info to $one and $two if necessary.
|
||||
if (null !== $this->foreignCurrency && null !== $foreignAmount && $this->foreignCurrency->id !== $this->currency->id) {
|
||||
if (null !== $this->foreignCurrency && null !== $foreignAmount && $this->foreignCurrency->id !== $this->currency->id && '' !== $foreignAmount) {
|
||||
$result->foreign_currency_id = $this->foreignCurrency->id;
|
||||
$result->foreign_amount = $foreignAmount;
|
||||
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\User;
|
||||
use Log;
|
||||
@@ -60,7 +61,6 @@ class TransactionGroupFactory
|
||||
{
|
||||
$this->journalFactory->setUser($this->user);
|
||||
$this->journalFactory->setErrorOnHash($data['error_if_duplicate_hash'] ?? false);
|
||||
|
||||
try {
|
||||
$collection = $this->journalFactory->create($data);
|
||||
} catch(DuplicateTransactionException $e) {
|
||||
|
@@ -29,6 +29,7 @@ use Exception;
|
||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
@@ -40,6 +41,7 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
|
||||
use FireflyIII\Services\Internal\Support\JournalServiceTrait;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use FireflyIII\User;
|
||||
@@ -125,6 +127,7 @@ class TransactionJournalFactory
|
||||
*
|
||||
* @return Collection
|
||||
* @throws DuplicateTransactionException
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function create(array $data): Collection
|
||||
{
|
||||
@@ -139,24 +142,30 @@ class TransactionJournalFactory
|
||||
|
||||
return new Collection;
|
||||
}
|
||||
|
||||
/** @var array $row */
|
||||
foreach ($transactions as $index => $row) {
|
||||
Log::debug(sprintf('Now creating journal %d/%d', $index + 1, count($transactions)));
|
||||
|
||||
Log::debug('Going to call createJournal', $row);
|
||||
try {
|
||||
try {
|
||||
/** @var array $row */
|
||||
foreach ($transactions as $index => $row) {
|
||||
Log::debug(sprintf('Now creating journal %d/%d', $index + 1, count($transactions)));
|
||||
$journal = $this->createJournal(new NullArrayObject($row));
|
||||
} catch (DuplicateTransactionException|Exception $e) {
|
||||
Log::warning('TransactionJournalFactory::create() caught a duplicate journal in createJournal()');
|
||||
throw new DuplicateTransactionException($e->getMessage());
|
||||
}
|
||||
if (null !== $journal) {
|
||||
$collection->push($journal);
|
||||
}
|
||||
if (null === $journal) {
|
||||
Log::error('The createJournal() method returned NULL. This may indicate an error.');
|
||||
if (null !== $journal) {
|
||||
$collection->push($journal);
|
||||
}
|
||||
if (null === $journal) {
|
||||
Log::error('The createJournal() method returned NULL. This may indicate an error.');
|
||||
}
|
||||
}
|
||||
} catch (DuplicateTransactionException $e) {
|
||||
Log::warning('TransactionJournalFactory::create() caught a duplicate journal in createJournal()');
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
$this->forceDeleteOnError($collection);
|
||||
throw new DuplicateTransactionException($e->getMessage());
|
||||
} catch (FireflyException $e) {
|
||||
Log::warning('TransactionJournalFactory::create() caught an exception.');
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
$this->forceDeleteOnError($collection);
|
||||
throw new FireflyException($e->getMessage());
|
||||
}
|
||||
|
||||
return $collection;
|
||||
@@ -204,7 +213,7 @@ class TransactionJournalFactory
|
||||
* @param NullArrayObject $row
|
||||
*
|
||||
* @return TransactionJournal|null
|
||||
* @throws Exception
|
||||
* @throws FireflyException
|
||||
* @throws DuplicateTransactionException
|
||||
*/
|
||||
private function createJournal(NullArrayObject $row): ?TransactionJournal
|
||||
@@ -232,36 +241,33 @@ class TransactionJournalFactory
|
||||
try {
|
||||
// validate source and destination using a new Validator.
|
||||
$this->validateAccounts($row);
|
||||
/** create or get source and destination accounts */
|
||||
|
||||
$sourceInfo = [
|
||||
'id' => (int)$row['source_id'],
|
||||
'name' => $row['source_name'],
|
||||
'iban' => $row['source_iban'],
|
||||
'number' => $row['source_number'],
|
||||
'bic' => $row['source_bic'],
|
||||
];
|
||||
|
||||
$destInfo = [
|
||||
'id' => (int)$row['destination_id'],
|
||||
'name' => $row['destination_name'],
|
||||
'iban' => $row['destination_iban'],
|
||||
'number' => $row['destination_number'],
|
||||
'bic' => $row['destination_bic'],
|
||||
];
|
||||
Log::debug('Source info:', $sourceInfo);
|
||||
Log::debug('Destination info:', $destInfo);
|
||||
|
||||
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
|
||||
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo);
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (FireflyException $e) {
|
||||
Log::error('Could not validate source or destination.');
|
||||
Log::error($e->getMessage());
|
||||
|
||||
return null;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
/** create or get source and destination accounts */
|
||||
$sourceInfo = [
|
||||
'id' => (int)$row['source_id'],
|
||||
'name' => $row['source_name'],
|
||||
'iban' => $row['source_iban'],
|
||||
'number' => $row['source_number'],
|
||||
'bic' => $row['source_bic'],
|
||||
];
|
||||
|
||||
$destInfo = [
|
||||
'id' => (int)$row['destination_id'],
|
||||
'name' => $row['destination_name'],
|
||||
'iban' => $row['destination_iban'],
|
||||
'number' => $row['destination_number'],
|
||||
'bic' => $row['destination_bic'],
|
||||
];
|
||||
Log::debug('Source info:', $sourceInfo);
|
||||
Log::debug('Destination info:', $destInfo);
|
||||
|
||||
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
|
||||
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo);
|
||||
|
||||
// TODO AFTER 4.8,0 better handling below:
|
||||
|
||||
@@ -337,7 +343,15 @@ class TransactionJournalFactory
|
||||
$transactionFactory->setCurrency($sourceCurrency);
|
||||
$transactionFactory->setForeignCurrency($sourceForeignCurrency);
|
||||
$transactionFactory->setReconciled($row['reconciled'] ?? false);
|
||||
$transactionFactory->createNegative((string)$row['amount'], (string)$row['foreign_amount']);
|
||||
try {
|
||||
$negative = $transactionFactory->createNegative((string)$row['amount'], (string)$row['foreign_amount']);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error('Exception creating negative transaction.');
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
$this->forceDeleteOnError(new Collection([$journal]));
|
||||
throw new FireflyException($e->getMessage());
|
||||
}
|
||||
|
||||
// and the destination one:
|
||||
/** @var TransactionFactory $transactionFactory */
|
||||
@@ -348,7 +362,18 @@ class TransactionJournalFactory
|
||||
$transactionFactory->setCurrency($destCurrency);
|
||||
$transactionFactory->setForeignCurrency($destForeignCurrency);
|
||||
$transactionFactory->setReconciled($row['reconciled'] ?? false);
|
||||
$transactionFactory->createPositive((string)$row['amount'], (string)$row['foreign_amount']);
|
||||
try {
|
||||
$transactionFactory->createPositive((string)$row['amount'], (string)$row['foreign_amount']);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error('Exception creating positive transaction.');
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
Log::warning('Delete negative transaction.');
|
||||
$this->forceTrDelete($negative);
|
||||
$this->forceDeleteOnError(new Collection([$journal]));
|
||||
throw new FireflyException($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
// verify that journal has two transactions. Otherwise, delete and cancel.
|
||||
// TODO this can't be faked so it can't be tested.
|
||||
@@ -418,6 +443,37 @@ class TransactionJournalFactory
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the deletion of an entire set of transaction journals and their meta object in case of
|
||||
* an error creating a group.
|
||||
*
|
||||
* @param Collection $collection
|
||||
*/
|
||||
private function forceDeleteOnError(Collection $collection): void
|
||||
{
|
||||
Log::debug(sprintf('forceDeleteOnError on collection size %d item(s)', $collection->count()));
|
||||
$service = app(JournalDestroyService::class);
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($collection as $journal) {
|
||||
Log::debug(sprintf('forceDeleteOnError on journal #%d', $journal->id));
|
||||
$service->destroy($journal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Transaction $transaction
|
||||
*/
|
||||
private function forceTrDelete(Transaction $transaction): void
|
||||
{
|
||||
try {
|
||||
$transaction->delete();
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
Log::error('Could not delete negative transaction.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $account
|
||||
|
@@ -35,21 +35,23 @@ class StoredGroupEventHandler
|
||||
/**
|
||||
* This method grabs all the users rules and processes them.
|
||||
*
|
||||
* @param StoredTransactionGroup $storedJournalEvent
|
||||
* @param StoredTransactionGroup $storedGroupEvent
|
||||
*/
|
||||
public function processRules(StoredTransactionGroup $storedJournalEvent): void
|
||||
public function processRules(StoredTransactionGroup $storedGroupEvent): void
|
||||
{
|
||||
if (false === $storedJournalEvent->applyRules) {
|
||||
if (false === $storedGroupEvent->applyRules) {
|
||||
Log::info(sprintf('Will not run rules on group #%d', $storedGroupEvent->transactionGroup->id));
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('Now in StoredGroupEventHandler::processRules()');
|
||||
|
||||
/** @var RuleEngine $ruleEngine */
|
||||
$ruleEngine = app(RuleEngine::class);
|
||||
$ruleEngine->setUser($storedJournalEvent->transactionGroup->user);
|
||||
$ruleEngine->setUser($storedGroupEvent->transactionGroup->user);
|
||||
$ruleEngine->setAllRules(true);
|
||||
$ruleEngine->setTriggerMode(RuleEngine::TRIGGER_STORE);
|
||||
$journals = $storedJournalEvent->transactionGroup->transactionJournals;
|
||||
$journals = $storedGroupEvent->transactionGroup->transactionJournals;
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
|
@@ -35,16 +35,22 @@ class UpdatedGroupEventHandler
|
||||
/**
|
||||
* This method will check all the rules when a journal is updated.
|
||||
*
|
||||
* @param UpdatedTransactionGroup $updatedJournalEvent
|
||||
* @param UpdatedTransactionGroup $updatedGroupEvent
|
||||
*/
|
||||
public function processRules(UpdatedTransactionGroup $updatedJournalEvent): void
|
||||
public function processRules(UpdatedTransactionGroup $updatedGroupEvent): void
|
||||
{
|
||||
if (false === $updatedGroupEvent->applyRules) {
|
||||
Log::info(sprintf('Will not run rules on group #%d', $updatedGroupEvent->transactionGroup->id));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var RuleEngine $ruleEngine */
|
||||
$ruleEngine = app(RuleEngine::class);
|
||||
$ruleEngine->setUser($updatedJournalEvent->transactionGroup->user);
|
||||
$ruleEngine->setUser($updatedGroupEvent->transactionGroup->user);
|
||||
$ruleEngine->setAllRules(true);
|
||||
$ruleEngine->setTriggerMode(RuleEngine::TRIGGER_UPDATE);
|
||||
$journals = $updatedJournalEvent->transactionGroup->transactionJournals;
|
||||
$journals = $updatedGroupEvent->transactionGroup->transactionJournals;
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
|
78
app/Http/Controllers/Admin/TelemetryController.php
Normal file
78
app/Http/Controllers/Admin/TelemetryController.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* TelemetryController.php
|
||||
* Copyright (c) 2020 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
|
||||
/**
|
||||
* Class TelemetryController
|
||||
*/
|
||||
class TelemetryController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
static function ($request, $next) {
|
||||
app('view')->share('title', (string)trans('firefly.administration'));
|
||||
app('view')->share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
session()->flash('info', 'No telemetry to delete. Does not work yet.');
|
||||
|
||||
return redirect(route('admin.telemetry.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
app('view')->share('subTitleIcon', 'fa-eye');
|
||||
app('view')->share('subTitle', (string)trans('firefly.telemetry_admin_index'));
|
||||
$version = config('firefly.version');
|
||||
$enabled = config('firefly.telemetry', false);
|
||||
$count = 1;
|
||||
|
||||
return view('admin.telemetry.index', compact('version', 'enabled', 'count'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function view()
|
||||
{
|
||||
return view('admin.telemetry.view');
|
||||
}
|
||||
|
||||
}
|
@@ -78,7 +78,7 @@ class ResetPasswordController extends Controller
|
||||
$rules = [
|
||||
'token' => 'required',
|
||||
'email' => 'required|email',
|
||||
'password' => 'required|confirmed|min:6|secure_password',
|
||||
'password' => 'required|confirmed|min:16|secure_password',
|
||||
];
|
||||
|
||||
$this->validate($request, $rules, $this->validationErrorMessages());
|
||||
|
@@ -34,6 +34,20 @@ use Preferences;
|
||||
*/
|
||||
class TwoFactorController extends Controller
|
||||
{
|
||||
/**
|
||||
* What to do if 2FA lost?
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function lostTwoFactor()
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$siteOwner = config('firefly.site_owner');
|
||||
$title = (string)trans('firefly.two_factor_forgot_title');
|
||||
return view('auth.lost-two-factor', compact('user', 'siteOwner', 'title'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
@@ -118,27 +132,6 @@ class TwoFactorController extends Controller
|
||||
Preferences::set('mfa_history', $newHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* What to do if 2FA lost?
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function lostTwoFactor()
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$siteOwner = config('firefly.site_owner');
|
||||
$title = (string)trans('firefly.two_factor_forgot_title');
|
||||
|
||||
Log::info(
|
||||
'To reset the two factor authentication for user #' . $user->id .
|
||||
' (' . $user->email . '), simply open the "preferences" table and delete the entries with the names "twoFactorAuthEnabled" and' .
|
||||
' "twoFactorAuthSecret" for user_id ' . $user->id . '. That will take care of it.'
|
||||
);
|
||||
|
||||
return view('auth.lost-two-factor', compact('user', 'siteOwner', 'title'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Each MFA history has a timestamp and a code, saving the MFA entries for 5 minutes. So if the
|
||||
* submitted MFA code has been submitted in the last 5 minutes, it won't work despite being valid.
|
||||
|
@@ -114,7 +114,7 @@ class CategoryController extends Controller
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('chart.category.frontpage');
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
// return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// currency repos:
|
||||
@@ -163,22 +163,24 @@ class CategoryController extends Controller
|
||||
|
||||
// no category per currency:
|
||||
$noCategory = $noCatRepository->sumExpenses($start, $end);
|
||||
if (0 !== bccomp($noCategory[0]['sum'] ?? '0', '0')) {
|
||||
|
||||
foreach ($noCategory as $currency) {
|
||||
$currencyId = $currency['currency_id'];
|
||||
$currencies[$currencyId] = $currencies[$currencyId] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'currency_name' => $currency['currency_name'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_code' => $currency['currency_code'],
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
foreach ($noCategory as $currency) {
|
||||
$currencyId = $currency['currency_id'];
|
||||
$currencies[$currencyId] = $currencies[$currencyId] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'currency_name' => $currency['currency_name'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_code' => $currency['currency_code'],
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
];
|
||||
$tempData[] = [
|
||||
'name' => trans('firefly.no_category'),
|
||||
'sum' => $currency['sum'],
|
||||
'sum_float' => round($currency['sum'], $currency['currency_decimal_places'] ?? 2),
|
||||
'currency_id' => $currency['currency_id'],
|
||||
];
|
||||
$tempData[] = [
|
||||
'name' => trans('firefly.no_category'),
|
||||
'sum' => $currency['sum'],
|
||||
'sum_float' => round($currency['sum'], $currency['currency_decimal_places']),
|
||||
'currency_id' => $currency['currency_id'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// sort temp array by amount.
|
||||
@@ -203,6 +205,7 @@ class CategoryController extends Controller
|
||||
$name = $entry['name'];
|
||||
$chartData[$currencyId]['entries'][$name] = bcmul($entry['sum'], '-1');
|
||||
}
|
||||
|
||||
$data = $this->generator->multiSet($chartData);
|
||||
$cache->store($data);
|
||||
|
||||
|
@@ -59,8 +59,6 @@ class BoxController extends Controller
|
||||
*/
|
||||
public function available(): JsonResponse
|
||||
{
|
||||
/** @var BudgetRepositoryInterface $repository */
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
/** @var OperationsRepositoryInterface $opsRepository */
|
||||
$opsRepository = app(OperationsRepositoryInterface::class);
|
||||
/** @var AvailableBudgetRepositoryInterface $abRepository */
|
||||
@@ -102,13 +100,12 @@ class BoxController extends Controller
|
||||
$spent = $opsRepository->sumExpenses($start, $end, null, null, $currency);
|
||||
$spentAmount = $spent[(int)$currency->id]['sum'] ?? '0';
|
||||
$spentPerDay = '-1';
|
||||
if (1 === $availableBudgets->count()) {
|
||||
if ($availableBudgets->count() > 0) {
|
||||
$display = 0; // assume user overspent
|
||||
$boxTitle = (string)trans('firefly.overspent');
|
||||
/** @var AvailableBudget $availableBudget */
|
||||
$availableBudget = $availableBudgets->first();
|
||||
$totalAvailableSum = (string)$availableBudgets->sum('amount');
|
||||
// calculate with available budget.
|
||||
$leftToSpendAmount = bcadd($availableBudget->amount, $spentAmount);
|
||||
$leftToSpendAmount = bcadd($totalAvailableSum, $spentAmount);
|
||||
if (1 === bccomp($leftToSpendAmount, '0')) {
|
||||
$boxTitle = (string)trans('firefly.left_to_spend');
|
||||
$days = $today->diffInDays($end) + 1;
|
||||
@@ -185,7 +182,7 @@ class BoxController extends Controller
|
||||
foreach ($set as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$expenses[$currencyId] = $expenses[$currencyId] ?? '0';
|
||||
$expenses[$currencyId] = bcadd($expenses[$currencyId], $journal['amount']);
|
||||
$expenses[$currencyId] = bcadd($expenses[$currencyId], $journal['amount'] ?? '0');
|
||||
$sums[$currencyId] = $sums[$currencyId] ?? '0';
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], $journal['amount']);
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
@@ -59,10 +60,29 @@ class PreferencesController extends Controller
|
||||
*/
|
||||
public function index(AccountRepositoryInterface $repository)
|
||||
{
|
||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]);
|
||||
|
||||
// group accounts
|
||||
$groupedAccounts = [];
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$type = $account->accountType->type;
|
||||
$role = sprintf('opt_group_%s', $repository->getMetaValue($account, 'account_role'));
|
||||
|
||||
if (in_array($type, [AccountType::MORTGAGE, AccountType::DEBT, AccountType::LOAN], true)) {
|
||||
$role = sprintf('opt_group_l_%s',$type);
|
||||
}
|
||||
|
||||
if ('' === $role || 'opt_group_' === $role) {
|
||||
$role = 'opt_group_defaultAsset';
|
||||
}
|
||||
$groupedAccounts[trans(sprintf('firefly.%s',$role))][$account->id] = $account->name;
|
||||
}
|
||||
ksort($groupedAccounts);
|
||||
|
||||
$accountIds = $accounts->pluck('id')->toArray();
|
||||
$viewRangePref = app('preferences')->get('viewRange', '1M');
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
|
||||
$viewRange = $viewRangePref->data;
|
||||
$frontPageAccounts = app('preferences')->get('frontPageAccounts', $accountIds);
|
||||
$language = app('preferences')->get('language', config('firefly.default_language', 'en_US'))->data;
|
||||
@@ -82,7 +102,7 @@ class PreferencesController extends Controller
|
||||
'preferences.index',
|
||||
compact(
|
||||
'language',
|
||||
'accounts',
|
||||
'groupedAccounts',
|
||||
'frontPageAccounts',
|
||||
'tjOptionalFields',
|
||||
'viewRange',
|
||||
@@ -135,7 +155,7 @@ class PreferencesController extends Controller
|
||||
// language:
|
||||
/** @var Preference $currentLang */
|
||||
$currentLang = app('preferences')->get('language', 'en_US');
|
||||
$lang = $request->get('language');
|
||||
$lang = $request->get('language');
|
||||
if (array_key_exists($lang, config('firefly.languages'))) {
|
||||
app('preferences')->set('language', $lang);
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Generator\Report\ReportGeneratorFactory;
|
||||
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||
use FireflyIII\Http\Requests\ReportFormRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
@@ -262,11 +263,32 @@ class ReportController extends Controller
|
||||
$start = clone session('first');
|
||||
$months = $this->helper->listOfMonths($start);
|
||||
$customFiscalYear = app('preferences')->get('customFiscalYear', 0)->data;
|
||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$accounts = $repository->getAccountsByType(
|
||||
[AccountType::DEFAULT, AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE]
|
||||
);
|
||||
|
||||
// group accounts by role:
|
||||
$groupedAccounts = [];
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$type = $account->accountType->type;
|
||||
$role = sprintf('opt_group_%s', $repository->getMetaValue($account, 'account_role'));
|
||||
|
||||
if (in_array($type, [AccountType::MORTGAGE, AccountType::DEBT, AccountType::LOAN], true)) {
|
||||
$role = sprintf('opt_group_l_%s',$type);
|
||||
}
|
||||
|
||||
if ('' === $role || 'opt_group_' === $role) {
|
||||
$role = 'opt_group_defaultAsset';
|
||||
}
|
||||
$groupedAccounts[trans(sprintf('firefly.%s',$role))][$account->id] = $account;
|
||||
}
|
||||
ksort($groupedAccounts);
|
||||
|
||||
$accountList = implode(',', $accounts->pluck('id')->toArray());
|
||||
$this->repository->cleanupBudgets();
|
||||
|
||||
return view('reports.index', compact('months', 'accounts', 'start', 'accountList', 'customFiscalYear'));
|
||||
return view('reports.index', compact('months', 'accounts', 'start', 'accountList','groupedAccounts', 'customFiscalYear'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -90,6 +90,9 @@ class CreateController extends Controller
|
||||
{
|
||||
app('preferences')->mark();
|
||||
|
||||
$sourceId = (int)request()->get('source');
|
||||
$destinationId = (int)request()->get('destination');
|
||||
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$cash = $repository->getCashAccount();
|
||||
@@ -112,7 +115,7 @@ class CreateController extends Controller
|
||||
'transactions.create', compact(
|
||||
'subTitleIcon', 'cash', 'objectType', 'subTitle', 'defaultCurrency', 'previousUri', 'optionalFields', 'preFilled',
|
||||
'allowedOpposingTypes',
|
||||
'accountToTypes'
|
||||
'accountToTypes','sourceId','destinationId'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@@ -81,14 +81,14 @@ class ShowController extends Controller
|
||||
public function show(Request $request, TransactionGroup $transactionGroup)
|
||||
{
|
||||
/** @var TransactionJournal $first */
|
||||
$first = $transactionGroup->transactionJournals->first();
|
||||
$splits = $transactionGroup->transactionJournals->count();
|
||||
$first = $transactionGroup->transactionJournals()->first(['transaction_journals.*']);
|
||||
$splits = $transactionGroup->transactionJournals()->count();
|
||||
|
||||
if(null === $first) {
|
||||
throw new FireflyException('This transaction is broken :(.');
|
||||
}
|
||||
|
||||
$type = $first->transactionType->type;
|
||||
$type = (string)trans(sprintf('firefly.%s',$first->transactionType->type));
|
||||
$title = 1 === $splits ? $first->description : $transactionGroup->title;
|
||||
$subTitle = sprintf('%s: "%s"', $type, $title);
|
||||
|
||||
|
@@ -347,6 +347,7 @@ class Request extends FormRequest
|
||||
$longitudeKey = null === $prefix ? 'longitude' : sprintf('%s_longitude', $prefix);
|
||||
$latitudeKey = null === $prefix ? 'latitude' : sprintf('%s_latitude', $prefix);
|
||||
$zoomLevelKey = null === $prefix ? 'zoom_level' : sprintf('%s_zoom_level', $prefix);
|
||||
$hasLocationKey = null === $prefix ? 'has_location' : sprintf('%s_has_location', $prefix);
|
||||
|
||||
// for a POST (store, all fields must be present and accounted for:
|
||||
if (
|
||||
@@ -354,7 +355,8 @@ class Request extends FormRequest
|
||||
&& ($this->has($longitudeKey) && $this->has($latitudeKey) && $this->has($zoomLevelKey))
|
||||
) {
|
||||
Log::debug('Method is POST and all fields present.');
|
||||
$data['store_location'] = true;
|
||||
|
||||
$data['store_location'] = $this->boolean($hasLocationKey);
|
||||
$data['longitude'] = '' === $this->string($longitudeKey) ? null : $this->string($longitudeKey);
|
||||
$data['latitude'] = '' === $this->string($latitudeKey) ? null : $this->string($latitudeKey);
|
||||
$data['zoom_level'] = '' === $this->string($zoomLevelKey) ? null : $this->integer($zoomLevelKey);
|
||||
|
@@ -70,18 +70,22 @@ class IngDescription implements SpecificInterface
|
||||
public function run(array $row): array
|
||||
{
|
||||
$this->row = array_values($row);
|
||||
array_push($this->row); // New column for "Valutadatum"
|
||||
if (count($this->row) >= 8) { // check if the array is correct
|
||||
switch ($this->row[4]) { // Get value for the mutation type
|
||||
case 'GT': // InternetBankieren
|
||||
case 'OV': // Overschrijving
|
||||
case 'VZ': // Verzamelbetaling
|
||||
case 'IC': // Incasso
|
||||
$this->removeIBANIngDescription();
|
||||
$this->removeNameIngDescription();
|
||||
// if "tegenrekening" empty, copy the description. Primitive, but it works.
|
||||
$this->copyDescriptionToOpposite();
|
||||
case 'DV': // Divers
|
||||
$this->removeIBANIngDescription(); // Remove "IBAN:", because it is already at "Tegenrekening"
|
||||
$this->removeNameIngDescription(); // Remove "Naam:", because it is already at "Naam/ Omschrijving"
|
||||
$this->removeIngDescription(); // Remove "Omschrijving", but not the value from description
|
||||
$this->moveValutadatumDescription(); // Move "Valutadatum" from description to new column
|
||||
$this->MoveSavingsAccount(); // Move savings account number and name
|
||||
break;
|
||||
case 'BA': // Betaalautomaat
|
||||
$this->moveValutadatumDescription(); // Move "Valutadatum" from description to new column
|
||||
$this->addNameIngDescription();
|
||||
break;
|
||||
}
|
||||
@@ -99,33 +103,60 @@ class IngDescription implements SpecificInterface
|
||||
$this->row[8] = $this->row[1] . ' ' . $this->row[8];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove "Omschrijving" (and NOT its value) from the description.
|
||||
*/
|
||||
protected function removeIngDescription(): void
|
||||
{
|
||||
$this->row[8] = preg_replace('/Omschrijving: /', '', $this->row[8]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove IBAN number out of the description
|
||||
* Default description of Description is: Naam: <OPPOS NAME> Omschrijving: <DESCRIPTION> IBAN: <OPPOS IBAN NR>.
|
||||
*/
|
||||
protected function removeIBANIngDescription(): void
|
||||
{
|
||||
// Try replace the iban number with nothing. The IBAN nr is found in the third row
|
||||
// Try replace the iban number with nothing. The IBAN nr is found in the third column
|
||||
$this->row[8] = preg_replace('/\sIBAN:\s' . $this->row[3] . '/', '', $this->row[8]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove name from the description (Remove everything before the description incl the word 'Omschrijving' ).
|
||||
* Remove "Naam" (and its value) from the description.
|
||||
*/
|
||||
protected function removeNameIngDescription(): void
|
||||
{
|
||||
// Try remove everything before the 'Omschrijving'
|
||||
$this->row[8] = preg_replace('/.+Omschrijving: /', '', $this->row[8]);
|
||||
$this->row[8] = preg_replace('/Naam:.*?([a-zA-Z\/]+:)/', '$1', $this->row[8]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy description to name of opposite account.
|
||||
* Move "Valutadatum" from the description to new column.
|
||||
*/
|
||||
private function copyDescriptionToOpposite(): void
|
||||
protected function moveValutadatumDescription(): void
|
||||
{
|
||||
$search = ['Naar Oranje Spaarrekening ', 'Afschrijvingen'];
|
||||
$matches = array();
|
||||
preg_match('/Valutadatum: ([0-9-]+)/', $this->row[8], $matches);
|
||||
$this->row[9] = date("Ymd", strtotime($matches[1]));
|
||||
$this->row[8] = preg_replace('/Valutadatum: [0-9-]+/', '', $this->row[8]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move savings account number to column 1 and name to column 3.
|
||||
*/
|
||||
private function MoveSavingsAccount(): void
|
||||
{
|
||||
$matches = array();
|
||||
if ('' === (string)$this->row[3]) {
|
||||
$this->row[3] = trim(str_ireplace($search, '', $this->row[8]));
|
||||
if (preg_match('/(Naar|Van) (.*rekening) ([0-9]+)/', $this->row[8], $matches)) {
|
||||
$matches[3] = sprintf("%010d", $matches[3]);
|
||||
$this->row[1] = $matches[2]; // Savings account name
|
||||
$this->row[3] = $matches[3]; // Savings account number
|
||||
$this->row[8] = preg_replace('/(Naar|Van) (.*rekening) ([0-9]+)/', '', $this->row[8]); // Remove the savings account content from description
|
||||
} elseif (preg_match('/(Naar|Van) (.*rekening) ([0-9]+)/', $this->row[1], $matches)) {
|
||||
$matches[3] = sprintf("%010d", $matches[3]);
|
||||
$this->row[1] = $matches[2]; // Savings account name
|
||||
$this->row[3] = $matches[3]; // Savings account number
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -58,6 +58,7 @@ use FireflyIII\Support\Form\RuleForm;
|
||||
use FireflyIII\Support\Navigation;
|
||||
use FireflyIII\Support\Preferences;
|
||||
use FireflyIII\Support\Steam;
|
||||
use FireflyIII\Support\Telemetry;
|
||||
use FireflyIII\Validation\FireflyValidator;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Validator;
|
||||
@@ -91,33 +92,33 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
{
|
||||
$this->app->bind(
|
||||
'preferences',
|
||||
function () {
|
||||
static function () {
|
||||
return new Preferences;
|
||||
}
|
||||
);
|
||||
|
||||
$this->app->bind(
|
||||
'fireflyconfig',
|
||||
function () {
|
||||
static function () {
|
||||
return new FireflyConfig;
|
||||
}
|
||||
);
|
||||
$this->app->bind(
|
||||
'navigation',
|
||||
function () {
|
||||
static function () {
|
||||
return new Navigation;
|
||||
}
|
||||
);
|
||||
$this->app->bind(
|
||||
'amount',
|
||||
function () {
|
||||
static function () {
|
||||
return new Amount;
|
||||
}
|
||||
);
|
||||
|
||||
$this->app->bind(
|
||||
'steam',
|
||||
function () {
|
||||
static function () {
|
||||
return new Steam;
|
||||
}
|
||||
);
|
||||
@@ -155,6 +156,13 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
}
|
||||
);
|
||||
|
||||
$this->app->bind(
|
||||
'telemetry',
|
||||
static function () {
|
||||
return new Telemetry;
|
||||
}
|
||||
);
|
||||
|
||||
// chart generator:
|
||||
$this->app->bind(GeneratorInterface::class, ChartJsGenerator::class);
|
||||
|
||||
|
@@ -473,7 +473,9 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
if (AccountType::ASSET !== $account->accountType->type) {
|
||||
throw new FireflyException(sprintf('%s is not an asset account.', $account->name));
|
||||
}
|
||||
$name = $account->name . ' reconciliation';
|
||||
|
||||
$name = trans('firefly.reconciliation_account_name', ['name' => $account->name]);
|
||||
|
||||
/** @var AccountType $type */
|
||||
$type = AccountType::where('type', AccountType::RECONCILIATION)->first();
|
||||
$accounts = $this->user->accounts()->where('account_type_id', $type->id)->get();
|
||||
|
@@ -198,7 +198,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface
|
||||
'currency_code' => $journal['currency_code'],
|
||||
'currency_decimal_places' => $journal['currency_decimal_places'],
|
||||
];
|
||||
$array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount']));
|
||||
$array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'] ?? '0'));
|
||||
}
|
||||
|
||||
return $array;
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Repositories\Journal;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Transaction;
|
||||
@@ -386,6 +387,9 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
{
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $journal->transactions()->with('account')->where('amount', '<', 0)->first();
|
||||
if (null === $transaction) {
|
||||
throw new FireflyException(sprintf('Your administration is broken. Transaction journal #%d has no source transaction.', $journal->id));
|
||||
}
|
||||
|
||||
return $transaction->account;
|
||||
}
|
||||
@@ -397,6 +401,9 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
{
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $journal->transactions()->with('account')->where('amount', '>', 0)->first();
|
||||
if (null === $transaction) {
|
||||
throw new FireflyException(sprintf('Your administration is broken. Transaction journal #%d has no destination transaction.', $journal->id));
|
||||
}
|
||||
|
||||
return $transaction->account;
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Repositories\Journal;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@@ -114,7 +115,9 @@ interface JournalRepositoryInterface
|
||||
* Returns the source account of the journal.
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function getSourceAccount(TransactionJournal $journal): Account;
|
||||
|
||||
@@ -123,6 +126,7 @@ interface JournalRepositoryInterface
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function getDestinationAccount(TransactionJournal $journal): Account;
|
||||
|
||||
|
@@ -332,6 +332,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface
|
||||
*
|
||||
* @return TransactionGroup
|
||||
* @throws DuplicateTransactionException
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(array $data): TransactionGroup
|
||||
{
|
||||
@@ -343,6 +344,10 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface
|
||||
} catch (DuplicateTransactionException $e) {
|
||||
Log::warning('Group repository caught group factory with a duplicate exception!');
|
||||
throw new DuplicateTransactionException($e->getMessage());
|
||||
} catch(FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
throw new FireflyException($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
|
41
app/Support/Facades/Telemetry.php
Normal file
41
app/Support/Facades/Telemetry.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Amount.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\Support\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
/**
|
||||
* Class Telemetry
|
||||
*/
|
||||
class Telemetry extends Facade
|
||||
{
|
||||
/**
|
||||
* Get the registered name of the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor(): string
|
||||
{
|
||||
return 'telemetry';
|
||||
}
|
||||
}
|
@@ -97,8 +97,8 @@ trait UserNavigation
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$type = $transaction->account->accountType->type;
|
||||
if (!in_array($type, $ignore)) {
|
||||
return redirect(route('accounts.show', [$transaction->account_id]));
|
||||
if (!in_array($type, $ignore, true)) {
|
||||
return redirect(route('accounts.edit', [$transaction->account_id]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -312,7 +312,7 @@ class Search implements SearchInterface
|
||||
{
|
||||
$parts = explode(':', $string);
|
||||
if (2 === count($parts) && '' !== trim((string)$parts[1]) && '' !== trim((string)$parts[0])) {
|
||||
$type = trim((string)$parts[0]);
|
||||
$type = strtolower(trim((string)$parts[0]));
|
||||
$value = trim((string)$parts[1]);
|
||||
$value = trim(trim($value, '"\''));
|
||||
if (in_array($type, $this->validModifiers, true)) {
|
||||
|
@@ -76,8 +76,15 @@ class Steam
|
||||
->where('transactions.transaction_currency_id', '!=', $currency->id)
|
||||
->sum('transactions.foreign_amount');
|
||||
|
||||
// check:
|
||||
Log::debug(sprintf('Steam::balance. Native balance is "%s"', $nativeBalance));
|
||||
Log::debug(sprintf('Steam::balance. Foreign balance is "%s"', $foreignBalance));
|
||||
|
||||
$balance = bcadd($nativeBalance, $foreignBalance);
|
||||
$virtual = null === $account->virtual_balance ? '0' : (string)$account->virtual_balance;
|
||||
|
||||
Log::debug(sprintf('Steam::balance. Virtual balance is "%s"', $virtual));
|
||||
|
||||
$balance = bcadd($balance, $virtual);
|
||||
$cache->store($balance);
|
||||
|
||||
|
81
app/Support/Telemetry.php
Normal file
81
app/Support/Telemetry.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* Telemetry.php
|
||||
* Copyright (c) 2020 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Support;
|
||||
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class Telemetry
|
||||
*/
|
||||
class Telemetry
|
||||
{
|
||||
/**
|
||||
* Feature telemetry stores a boolean "true" for the given $flag.
|
||||
*
|
||||
* Examples:
|
||||
* - use-help-pages
|
||||
* - has-created-bill
|
||||
* - do-big-import
|
||||
* - first-time-install
|
||||
* - more
|
||||
*
|
||||
* Its use should be limited to exotic and strange use cases in Firefly III.
|
||||
* Because time and date are logged as well, useful to track users' evolution in Firefly III.
|
||||
*
|
||||
* Any meta-data stored is strictly non-financial.
|
||||
*
|
||||
* @param string $flag
|
||||
*/
|
||||
public function feature(string $flag): void
|
||||
{
|
||||
if (false === config('firefly.send_telemetry')) {
|
||||
// hard stop if not allowed to do telemetry.
|
||||
// do nothing!
|
||||
return;
|
||||
}
|
||||
Log::info(sprintf('Logged telemetry feature flag "%s".', $flag));
|
||||
|
||||
// no storage backend yet, do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* String telemetry stores a string value as a telemetry entry. Values could include:
|
||||
*
|
||||
* - "php-version", "php7.3"
|
||||
* - "os-version", "linux"
|
||||
*
|
||||
* Any meta-data stored is strictly non-financial.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*/
|
||||
public function string(string $name, string $value): void
|
||||
{
|
||||
if (false === config('firefly.send_telemetry')) {
|
||||
// hard stop if not allowed to do telemetry.
|
||||
// do nothing!
|
||||
return;
|
||||
}
|
||||
Log::info(sprintf('Logged telemetry string "%s" with value "%s".', $name, $value));
|
||||
}
|
||||
|
||||
}
|
@@ -147,7 +147,7 @@ class General extends AbstractExtension
|
||||
'balance',
|
||||
static function (?Account $account): string {
|
||||
if (null === $account) {
|
||||
return 'NULL';
|
||||
return '0';
|
||||
}
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', Carbon::now()->endOfMonth());
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Transformers;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Transaction;
|
||||
@@ -32,6 +33,7 @@ use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class TransactionGroupTransformer
|
||||
@@ -98,9 +100,11 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
* @param TransactionGroup $group
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function transformObject(TransactionGroup $group): array
|
||||
{
|
||||
try {
|
||||
$result = [
|
||||
'id' => (int)$group->id,
|
||||
'created_at' => $group->created_at->toAtomString(),
|
||||
@@ -115,7 +119,11 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
} catch(FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
throw new FireflyException(sprintf('Transaction group #%d is broken. Please check out your log files.', $group->id));
|
||||
}
|
||||
// do something else.
|
||||
|
||||
return $result;
|
||||
@@ -125,36 +133,47 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getDestinationTransaction(TransactionJournal $journal): Transaction
|
||||
{
|
||||
|
||||
return $journal->transactions->first(
|
||||
$result = $journal->transactions->first(
|
||||
static function (Transaction $transaction) {
|
||||
return (float)$transaction->amount > 0;
|
||||
}
|
||||
);
|
||||
if (null === $result) {
|
||||
throw new FireflyException(sprintf('Journal #%d unexpectedly has no destination transaction.', $journal->id));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return Transaction
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getSourceTransaction(TransactionJournal $journal): Transaction
|
||||
{
|
||||
|
||||
return $journal->transactions->first(
|
||||
$result = $journal->transactions->first(
|
||||
static function (Transaction $transaction) {
|
||||
return (float)$transaction->amount < 0;
|
||||
}
|
||||
);
|
||||
if (null === $result) {
|
||||
throw new FireflyException(sprintf('Journal #%d unexpectedly has no source transaction.', $journal->id));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $transactionJournals
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function transformJournals(Collection $transactionJournals): array
|
||||
{
|
||||
|
31
changelog.md
31
changelog.md
@@ -2,7 +2,31 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [5.1.0 (API 1.0.0)] - 2020-03-xx
|
||||
## [5.1.1 (API 1.0.2)] - 2020-03-xx
|
||||
|
||||
### Added
|
||||
- [Issue 2672](https://github.com/firefly-iii/firefly-iii/issues/2672) Buttons to create transactions from the list of accounts is back.
|
||||
|
||||
### Changed
|
||||
- [Issue 3176](https://github.com/firefly-iii/firefly-iii/issues/3176) Greek language support is enabled again!
|
||||
|
||||
### Fixed
|
||||
- [Issue 3160](https://github.com/firefly-iii/firefly-iii/issues/3160) Deleting a reconciliation won't send you to a 404.
|
||||
- [Issue 3172](https://github.com/firefly-iii/firefly-iii/issues/3172) Remaining amount left calculation is wrong over multiple months.
|
||||
- [Issue 3173](https://github.com/firefly-iii/firefly-iii/issues/3173) Amount is invisible when viewing transactions.
|
||||
- [Issue 3177](https://github.com/firefly-iii/firefly-iii/issues/3177) Fix attachment breadcrumb.
|
||||
- [Issue 3180](https://github.com/firefly-iii/firefly-iii/issues/3180) Improve instructions for when the user loses MFA info.
|
||||
- [Issue 3182](https://github.com/firefly-iii/firefly-iii/issues/3182) Better fallback when transaction errors out.
|
||||
- Search modifiers are now case insensitive.
|
||||
|
||||
### Security
|
||||
- The minimal password length for new users is now 16 characters.
|
||||
- Have I Been Pwnd check is now enabled by default.
|
||||
|
||||
### API
|
||||
- A new call to `apply_rules` is available when submitting transactions.
|
||||
|
||||
## [5.1.0 (API 1.0.1)] - 2020-03-06
|
||||
|
||||
Before this release came out, several alpha and beta versions had been released already:
|
||||
|
||||
@@ -45,6 +69,11 @@ Before this release came out, several alpha and beta versions had been released
|
||||
- [Issue 3137](https://github.com/firefly-iii/firefly-iii/issues/3137) Fix mis-alignment in table rows.
|
||||
- [Issue 3140](https://github.com/firefly-iii/firefly-iii/issues/3140) New user email message had a broken link.
|
||||
- [Issue 3141](https://github.com/firefly-iii/firefly-iii/issues/3141) Cache issue
|
||||
- [Issue 3145](https://github.com/firefly-iii/firefly-iii/issues/3145) Issue with empty charts.
|
||||
- [Issue 3146](https://github.com/firefly-iii/firefly-iii/issues/3146) Better handling of CSV imports from ING.
|
||||
- [Issue 3154](https://github.com/firefly-iii/firefly-iii/issues/3154) Problem with bcadd() in PHP 7.4
|
||||
- [Issue 3159](https://github.com/firefly-iii/firefly-iii/issues/3159) Fixed some untranslatable strings.
|
||||
- Bad redirect when editing opening balances.
|
||||
|
||||
### API
|
||||
- [Issue 3097](https://github.com/firefly-iii/firefly-iii/issues/3097) Unifying API models
|
||||
|
554
composer.lock
generated
554
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -134,11 +134,12 @@ return [
|
||||
],
|
||||
'feature_flags' => [
|
||||
'export' => true,
|
||||
'telemetry' => false,
|
||||
],
|
||||
|
||||
'encryption' => null === env('USE_ENCRYPTION') || true === env('USE_ENCRYPTION'),
|
||||
'version' => '5.1.0-beta.1',
|
||||
'api_version' => '1.0.1',
|
||||
'version' => '5.1.1',
|
||||
'api_version' => '1.0.2',
|
||||
'db_version' => 12,
|
||||
'maxUploadSize' => 15242880,
|
||||
'send_error_message' => env('SEND_ERROR_MESSAGE', true),
|
||||
@@ -160,6 +161,7 @@ return [
|
||||
'login_provider' => envNonEmpty('LOGIN_PROVIDER', 'eloquent'),
|
||||
'cer_provider' => envNonEmpty('CER_PROVIDER', 'fixer'),
|
||||
'update_endpoint' => 'https://version.firefly-iii.org/index.json',
|
||||
'send_telemetry' => env('SEND_TELEMETRY', false),
|
||||
'update_minimum_age' => 6,
|
||||
'default_location' => [
|
||||
'longitude' => env('MAP_DEFAULT_LONG', '5.916667'),
|
||||
@@ -317,6 +319,7 @@ return [
|
||||
// currently enabled languages
|
||||
'en_US' => ['name_locale' => 'English', 'name_english' => 'English'],
|
||||
'cs_CZ' => ['name_locale' => 'Czech', 'name_english' => 'Czech'],
|
||||
'el_GR' => ['name_locale' => 'Ελληνικά', 'name_english' => 'Greek'],
|
||||
'es_ES' => ['name_locale' => 'Español', 'name_english' => 'Spanish'],
|
||||
'de_DE' => ['name_locale' => 'Deutsch', 'name_english' => 'German'],
|
||||
'fr_FR' => ['name_locale' => 'Français', 'name_english' => 'French'],
|
||||
@@ -345,7 +348,7 @@ return [
|
||||
// 'pt_PT' => ['name_locale' => 'Portuguese', 'name_english' => 'Portuguese'],
|
||||
// 'sl_SI' => ['name_locale' => 'Slovenian', 'name_english' => 'Slovenian'],
|
||||
// 'tlh_AA' => ['name_locale' => 'tlhIngan Hol', 'name_english' => 'Klingon'],
|
||||
// 'el_GR' => ['name_locale' => 'Ελληνικά', 'name_english' => 'Greek'],
|
||||
//
|
||||
// 'tr_TR' => ['name_locale' => 'Türkçe', 'name_english' => 'Turkish'],
|
||||
// 'sr_CS' => ['name_locale' => 'Serbian (Latin)', 'name_english' => 'Serbian (Latin)'],
|
||||
// 'uk_UA' => ['name_locale' => 'Ukranian', 'name_english' => 'Ukranian'],
|
||||
|
@@ -70,7 +70,7 @@ return [
|
||||
'allowed_for_user' => [
|
||||
'fake' => false,
|
||||
'file' => true,
|
||||
'bunq' => true,
|
||||
'bunq' => false,
|
||||
'spectre' => true,
|
||||
'ynab' => true,
|
||||
'plaid' => true,
|
||||
@@ -82,7 +82,7 @@ return [
|
||||
'has_prereq' => [
|
||||
'fake' => true,
|
||||
'file' => false,
|
||||
'bunq' => true,
|
||||
'bunq' => false,
|
||||
'spectre' => true,
|
||||
'ynab' => true,
|
||||
'plaid' => true,
|
||||
|
@@ -19,10 +19,8 @@
|
||||
"laravel-mix": "^4.1.2",
|
||||
"laravel-mix-bundle-analyzer": "^1.0.5",
|
||||
"uiv": "^0.31.5",
|
||||
"vue-i18n": "^8.14.1",
|
||||
"vue": "^2.6.10",
|
||||
"vue-i18n": "^8.14.1",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
},
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
|
536
public/v1/css/gf-source.css
vendored
536
public/v1/css/gf-source.css
vendored
@@ -1,523 +1,59 @@
|
||||
/*
|
||||
* gf-source.css
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'), url('../fonts/SourceSansPro-LightItalic-cyrillic-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-LightItalic-cyrillic-ext.woff') format('woff');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'), url('../fonts/SourceSansPro-LightItalic-cyrillic.woff2') format('woff2'), url('../fonts/SourceSansPro-LightItalic-cyrillic.woff') format('woff');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'), url('../fonts/SourceSansPro-LightItalic-greek-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-LightItalic-greek-ext.woff') format('woff');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'), url('../fonts/SourceSansPro-LightItalic-greek.woff2') format('woff2'), url('../fonts/SourceSansPro-LightItalic-greek.woff') format('woff');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'), url('../fonts/SourceSansPro-LightItalic-vietnamese.woff2') format('woff2'), url('../fonts/SourceSansPro-LightItalic-vietnamese.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'), url('../fonts/SourceSansPro-LightItalic-latin-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-LightItalic-latin-ext.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightItalic'), url('../fonts/SourceSansPro-LightItalic-latin.woff2') format('woff2'), url('../fonts/SourceSansPro-LightItalic-latin.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'), url('../fonts/SourceSansPro-Italic-cyrillic-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Italic-cyrillic-ext.woff') format('woff');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'), url('../fonts/SourceSansPro-Italic-cyrillic.woff2') format('woff2'), url('../fonts/SourceSansPro-Italic-cyrillic.woff') format('woff');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'), url('../fonts/SourceSansPro-Italic-greek-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Italic-greek-ext.woff') format('woff');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'), url('../fonts/SourceSansPro-Italic-greek.woff2') format('woff2'), url('../fonts/SourceSansPro-Italic-greek.woff') format('woff');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'), url('../fonts/SourceSansPro-Italic-vietnamese.woff2') format('woff2'), url('../fonts/SourceSansPro-Italic-vietnamese.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'), url('../fonts/SourceSansPro-Italic-latin-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Italic-latin-ext.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'), url('../fonts/SourceSansPro-Italic-latin.woff2') format('woff2'), url('../fonts/SourceSansPro-Italic-latin.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'), url('../fonts/SourceSansPro-SemiBoldItalic-cyrillic-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBoldItalic-cyrillic-ext.woff') format('woff');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'), url('../fonts/SourceSansPro-SemiBoldItalic-cyrillic.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBoldItalic-cyrillic.woff') format('woff');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'), url('../fonts/SourceSansPro-SemiBoldItalic-greek-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBoldItalic-greek-ext.woff') format('woff');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'), url('../fonts/SourceSansPro-SemiBoldItalic-greek.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBoldItalic-greek.woff') format('woff');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'), url('../fonts/SourceSansPro-SemiBoldItalic-vietnamese.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBoldItalic-vietnamese.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'), url('../fonts/SourceSansPro-SemiBoldItalic-latin-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBoldItalic-latin-ext.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'), url('../fonts/SourceSansPro-SemiBoldItalic-latin.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBoldItalic-latin.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldItalic'), url('../fonts/SourceSansPro-BoldItalic-cyrillic-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-BoldItalic-cyrillic-ext.woff') format('woff');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldItalic'), url('../fonts/SourceSansPro-BoldItalic-cyrillic.woff2') format('woff2'), url('../fonts/SourceSansPro-BoldItalic-cyrillic.woff') format('woff');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldItalic'), url('../fonts/SourceSansPro-BoldItalic-greek-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-BoldItalic-greek-ext.woff') format('woff');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldItalic'), url('../fonts/SourceSansPro-BoldItalic-greek.woff2') format('woff2'), url('../fonts/SourceSansPro-BoldItalic-greek.woff') format('woff');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldItalic'), url('../fonts/SourceSansPro-BoldItalic-vietnamese.woff2') format('woff2'), url('../fonts/SourceSansPro-BoldItalic-vietnamese.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldItalic'), url('../fonts/SourceSansPro-BoldItalic-latin-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-BoldItalic-latin-ext.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldItalic'), url('../fonts/SourceSansPro-BoldItalic-latin.woff2') format('woff2'), url('../fonts/SourceSansPro-BoldItalic-latin.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
/* source-sans-pro-300 - greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light-cyrillic-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Light-cyrillic-ext.woff') format('woff');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'),
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light-cyrillic.woff2') format('woff2'), url('../fonts/SourceSansPro-Light-cyrillic.woff') format('woff');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light-greek-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Light-greek-ext.woff') format('woff');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light-greek.woff2') format('woff2'), url('../fonts/SourceSansPro-Light-greek.woff') format('woff');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light-vietnamese.woff2') format('woff2'), url('../fonts/SourceSansPro-Light-vietnamese.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light-latin-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Light-latin-ext.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light-latin.woff2') format('woff2'), url('../fonts/SourceSansPro-Light-latin.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular-cyrillic-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Regular-cyrillic-ext.woff') format('woff');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular-cyrillic.woff2') format('woff2'), url('../fonts/SourceSansPro-Regular-cyrillic.woff') format('woff');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular-greek-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Regular-greek-ext.woff') format('woff');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular-greek.woff2') format('woff2'), url('../fonts/SourceSansPro-Regular-greek.woff') format('woff');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular-vietnamese.woff2') format('woff2'), url('../fonts/SourceSansPro-Regular-vietnamese.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular-latin-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Regular-latin-ext.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular-latin.woff2') format('woff2'), url('../fonts/SourceSansPro-Regular-latin.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
/* source-sans-pro-600 - greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url('../fonts/SourceSansPro-SemiBold-cyrillic-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBold-cyrillic-ext.woff') format('woff');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'),
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
/* source-sans-pro-regular - greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'),
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* source-sans-pro-italic - greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro Italic'), local('SourceSansPro-Italic'),
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* source-sans-pro-600italic - greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url('../fonts/SourceSansPro-SemiBold-cyrillic.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBold-cyrillic.woff') format('woff');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
src: local('Source Sans Pro SemiBold Italic'), local('SourceSansPro-SemiBoldItalic'),
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-600italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-600italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url('../fonts/SourceSansPro-SemiBold-greek-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBold-greek-ext.woff') format('woff');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url('../fonts/SourceSansPro-SemiBold-greek.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBold-greek.woff') format('woff');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url('../fonts/SourceSansPro-SemiBold-vietnamese.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBold-vietnamese.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url('../fonts/SourceSansPro-SemiBold-latin-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBold-latin-ext.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), url('../fonts/SourceSansPro-SemiBold-latin.woff2') format('woff2'), url('../fonts/SourceSansPro-SemiBold-latin.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
/* source-sans-pro-700 - greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('../fonts/SourceSansPro-Bold-cyrillic-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Bold-cyrillic-ext.woff') format('woff');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('../fonts/SourceSansPro-Bold-cyrillic.woff2') format('woff2'), url('../fonts/SourceSansPro-Bold-cyrillic.woff') format('woff');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('../fonts/SourceSansPro-Bold-greek-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Bold-greek-ext.woff') format('woff');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('../fonts/SourceSansPro-Bold-greek.woff2') format('woff2'), url('../fonts/SourceSansPro-Bold-greek.woff') format('woff');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('../fonts/SourceSansPro-Bold-vietnamese.woff2') format('woff2'), url('../fonts/SourceSansPro-Bold-vietnamese.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('../fonts/SourceSansPro-Bold-latin-ext.woff2') format('woff2'), url('../fonts/SourceSansPro-Bold-latin-ext.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('../fonts/SourceSansPro-Bold-latin.woff2') format('woff2'), url('../fonts/SourceSansPro-Bold-latin.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'),
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('../fonts/source-sans-pro-v13-greek_cyrillic-ext_vietnamese_greek-ext_latin-ext_cyrillic_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user