mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/3.10.2'
This commit is contained in:
commit
fa110279de
@ -1,6 +1,7 @@
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_FORCE_SSL=false
|
||||
APP_FORCE_ROOT=
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
LOG_LEVEL=warning
|
||||
|
||||
@ -40,5 +41,4 @@ SHOW_INCOMPLETE_TRANSLATIONS=false
|
||||
SHOW_DEMO_WARNING=false
|
||||
|
||||
ANALYTICS_ID=
|
||||
RUNCLEANUP=true
|
||||
SITE_OWNER=mail@example.com
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ _development
|
||||
result.html
|
||||
test-import.sh
|
||||
test-import-report.txt
|
||||
public/google*.html
|
||||
|
15
CHANGELOG.md
15
CHANGELOG.md
@ -5,6 +5,21 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
## [Unreleased]
|
||||
- No unreleased changes yet.
|
||||
|
||||
## [3.10.2] - 2016-08-29
|
||||
### Added
|
||||
- New Chinese translations. Set Firefly III to show incomplete translations to follow the progress. Want to translate Firefly III in Chinese, or in any other language? Then check out [the Crowdin project](https://crowdin.com/project/firefly-iii).
|
||||
- Added more admin pages. They do nothing yet.
|
||||
|
||||
### Changed
|
||||
- Import routine will now also apply user rules.
|
||||
- Various code cleanup.
|
||||
- Some small HTML changes.
|
||||
|
||||
### Fixed
|
||||
- Bug in the mass edit routines.
|
||||
- Firefly III over a proxy will now work (see [issue #290](https://github.com/JC5/firefly-iii/issues/290)), thanks @dfiel for reporting.
|
||||
- Sneaky bug in the import routine, fixed by @Bonno
|
||||
|
||||
## [3.10.1] - 2016-08-25
|
||||
### Added
|
||||
- More feedback in the import procedure.
|
||||
|
@ -46,8 +46,6 @@ class EncryptFile extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@ -64,6 +62,5 @@ class EncryptFile extends Command
|
||||
$path = storage_path('upload') . '/' . $newName;
|
||||
file_put_contents($path, $content);
|
||||
$this->line(sprintf('Encrypted "%s" and put it in "%s"', $file, $path));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Import\ImportProcedure;
|
||||
use FireflyIII\Import\ImportResult;
|
||||
use FireflyIII\Import\Logging\CommandHandler;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Log;
|
||||
|
||||
@ -67,24 +67,33 @@ class Import extends Command
|
||||
$handler = new CommandHandler($this);
|
||||
$monolog->pushHandler($handler);
|
||||
|
||||
$result = ImportProcedure::run($job);
|
||||
$result = ImportProcedure::runImport($job);
|
||||
|
||||
|
||||
/**
|
||||
* @var int $index
|
||||
* @var ImportResult $entry
|
||||
* @var int $index
|
||||
* @var TransactionJournal $journal
|
||||
*/
|
||||
foreach ($result as $index => $entry) {
|
||||
if ($entry->isSuccess()) {
|
||||
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $entry->journal->id));
|
||||
foreach ($result as $index => $journal) {
|
||||
if (!is_null($journal->id)) {
|
||||
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
|
||||
continue;
|
||||
}
|
||||
$errors = join(', ', $entry->errors->all());
|
||||
$this->error(sprintf('Could not store line #%d, because: %s', $index, $errors));
|
||||
$this->error(sprintf('Could not store line #%d', $index));
|
||||
}
|
||||
|
||||
|
||||
$this->line('The import has completed.');
|
||||
|
||||
// get any errors from the importer:
|
||||
$extendedStatus = $job->extended_status;
|
||||
if (isset($extendedStatus['errors']) && count($extendedStatus['errors']) > 0) {
|
||||
$this->line(sprintf('The following %d error(s) occured during the import:', count($extendedStatus['errors'])));
|
||||
foreach ($extendedStatus['errors'] as $error) {
|
||||
$this->error($error);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,8 +44,6 @@ class UpgradeFireflyInstructions extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
@ -55,8 +55,6 @@ class VerifyDatabase extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
@ -92,6 +92,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
'amount' => Amount::formatJournal($journal, false),
|
||||
];
|
||||
$string = trans('firefly.attachment_explanation', $args) . "\n";
|
||||
Log::debug('Appended explanation string', ['string' => $string]);
|
||||
$this->explanationString .= $string;
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
private $expected;
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
private $exportDisk;
|
||||
private $importKeys = [];
|
||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||
private $uploadDisk;
|
||||
|
||||
@ -42,10 +43,17 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
{
|
||||
parent::__construct($job);
|
||||
|
||||
Log::debug('Going to collect attachments', ['key' => $job->key]);
|
||||
|
||||
// make storage:
|
||||
$this->uploadDisk = Storage::disk('upload');
|
||||
$this->exportDisk = Storage::disk('export');
|
||||
$this->expected = 'csv-upload-' . Auth::user()->id . '-';
|
||||
|
||||
// file names associated with the old import routine.
|
||||
$this->expected = 'csv-upload-' . Auth::user()->id . '-';
|
||||
|
||||
// for the new import routine:
|
||||
$this->getImportKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,12 +65,26 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
$files = $this->uploadDisk->files();
|
||||
|
||||
foreach ($files as $entry) {
|
||||
$this->processOldUpload($entry);
|
||||
$this->processUpload($entry);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function getImportKeys()
|
||||
{
|
||||
$set = Auth::user()->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
|
||||
if ($set->count() > 0) {
|
||||
$keys = $set->pluck('key')->toArray();
|
||||
$this->importKeys = $keys;
|
||||
|
||||
}
|
||||
Log::debug('Valid import keys are ', $this->importKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*
|
||||
@ -83,9 +105,28 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isValidFile(string $entry): bool
|
||||
private function isImportFile(string $entry): bool
|
||||
{
|
||||
$name = str_replace('.upload', '', $entry);
|
||||
if (in_array($name, $this->importKeys)) {
|
||||
Log::debug(sprintf('Import file "%s" is in array', $name), $this->importKeys);
|
||||
|
||||
return true;
|
||||
}
|
||||
Log::debug(sprintf('Import file "%s" is NOT in array', $name), $this->importKeys);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isOldImport(string $entry): bool
|
||||
{
|
||||
$len = strlen($this->expected);
|
||||
// file is part of the old import routine:
|
||||
if (substr($entry, 0, $len) === $this->expected) {
|
||||
|
||||
return true;
|
||||
@ -97,23 +138,63 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
/**
|
||||
* @param $entry
|
||||
*/
|
||||
private function processOldUpload(string $entry)
|
||||
private function processUpload(string $entry)
|
||||
{
|
||||
$content = '';
|
||||
|
||||
if ($this->isValidFile($entry)) {
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get($entry));
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt old CSV import file ' . $entry . '. Skipped because ' . $e->getMessage());
|
||||
}
|
||||
// file is old import:
|
||||
if ($this->isOldImport($entry)) {
|
||||
$this->saveOldImportFile($entry);
|
||||
}
|
||||
if (strlen($content) > 0) {
|
||||
// continue with file:
|
||||
$date = $this->getOriginalUploadDate($entry);
|
||||
$file = $this->job->key . '-Old CSV import dated ' . $date . '.csv';
|
||||
|
||||
// file is current import.
|
||||
if ($this->isImportFile($entry)) {
|
||||
$this->saveImportFile($entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*/
|
||||
private function saveImportFile(string $entry)
|
||||
{
|
||||
// find job associated with import file:
|
||||
$name = str_replace('.upload', '', $entry);
|
||||
$job = Auth::user()->importJobs()->where('key', $name)->first();
|
||||
$content = '';
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get($entry));
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt old import file ' . $entry . '. Skipped because ' . $e->getMessage());
|
||||
}
|
||||
|
||||
if (!is_null($job) && strlen($content) > 0) {
|
||||
// add to export disk.
|
||||
$date = $job->created_at->format('Y-m-d');
|
||||
$file = sprintf('%s-Old %s import dated %s.%s', $this->job->key, strtoupper($job->file_type), $date, $job->file_type);
|
||||
$this->exportDisk->put($file, $content);
|
||||
$this->getFiles()->push($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry
|
||||
*/
|
||||
private function saveOldImportFile(string $entry)
|
||||
{
|
||||
$content = '';
|
||||
try {
|
||||
$content = Crypt::decrypt($this->uploadDisk->get($entry));
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt old CSV import file ' . $entry . '. Skipped because ' . $e->getMessage());
|
||||
}
|
||||
|
||||
if (strlen($content) > 0) {
|
||||
// add to export disk.
|
||||
$date = $this->getOriginalUploadDate($entry);
|
||||
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
|
||||
$this->exportDisk->put($file, $content);
|
||||
$this->getFiles()->push($file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class ConnectJournalToPiggyBank
|
||||
$piggyBankId = $event->piggyBankId;
|
||||
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = Auth::user()->piggybanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||
$piggyBank = Auth::user()->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||
|
||||
if (is_null($piggyBank)) {
|
||||
return true;
|
||||
|
@ -37,7 +37,7 @@ class ConnectTransactionToPiggyBank
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$transaction = $event->transaction;
|
||||
|
||||
$piggyBank = $repository->find($transaction['piggy_bank_id']);
|
||||
$piggyBank = $repository->find($transaction['piggy_bank_id']);
|
||||
|
||||
// valid piggy:
|
||||
if (is_null($piggyBank->id)) {
|
||||
|
@ -13,7 +13,6 @@ namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\UserIsConfirmed;
|
||||
use FireflyIII\Events\UserRegistration;
|
||||
use FireflyIII\User;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
@ -32,20 +31,6 @@ class UserSaveIpAddress
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserRegistration $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveFromRegistration(UserRegistration $event): bool
|
||||
{
|
||||
Preferences::setForUser($event->user, 'registration_ip_address', $event->ipAddress);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
@ -59,4 +44,18 @@ class UserSaveIpAddress
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserRegistration $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveFromRegistration(UserRegistration $event): bool
|
||||
{
|
||||
Preferences::setForUser($event->user, 'registration_ip_address', $event->ipAddress);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -250,6 +250,8 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
/**
|
||||
* @param array $files
|
||||
*
|
||||
* @param Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function processFiles(array $files, Model $model): bool
|
||||
|
@ -32,14 +32,12 @@ class BalanceLine
|
||||
|
||||
/** @var BudgetModel */
|
||||
protected $budget;
|
||||
|
||||
/** @var Carbon */
|
||||
protected $startDate;
|
||||
/** @var Carbon */
|
||||
protected $endDate;
|
||||
|
||||
/** @var int */
|
||||
protected $role = self::ROLE_DEFAULTROLE;
|
||||
/** @var Carbon */
|
||||
protected $startDate;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -90,6 +88,22 @@ class BalanceLine
|
||||
$this->budget = $budget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getEndDate()
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $endDate
|
||||
*/
|
||||
public function setEndDate($endDate)
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
@ -106,6 +120,22 @@ class BalanceLine
|
||||
$this->role = $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getStartDate()
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $startDate
|
||||
*/
|
||||
public function setStartDate($startDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -127,39 +157,6 @@ class BalanceLine
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getStartDate()
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $startDate
|
||||
*/
|
||||
public function setStartDate($startDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getEndDate()
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $endDate
|
||||
*/
|
||||
public function setEndDate($endDate)
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If a BalanceLine has a budget/repetition, each BalanceEntry in this BalanceLine
|
||||
* should have a "spent" value, which is the amount of money that has been spent
|
||||
|
@ -47,6 +47,7 @@ class Budget
|
||||
public function addBudgetLine(BudgetLine $budgetLine): Budget
|
||||
{
|
||||
$this->budgetLines->push($budgetLine);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -59,6 +60,7 @@ class Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->budgeted = bcadd($this->budgeted, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -71,6 +73,7 @@ class Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->left = bcadd($this->left, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -83,6 +86,7 @@ class Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->overspent = bcadd($this->overspent, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -95,6 +99,7 @@ class Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->spent = bcadd($this->spent, $add);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ class BudgetLine
|
||||
public function setBudget(BudgetModel $budget): BudgetLine
|
||||
{
|
||||
$this->budget = $budget;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -70,6 +71,7 @@ class BudgetLine
|
||||
public function setBudgeted(string $budgeted): BudgetLine
|
||||
{
|
||||
$this->budgeted = $budgeted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -89,6 +91,7 @@ class BudgetLine
|
||||
public function setLeft(string $left): BudgetLine
|
||||
{
|
||||
$this->left = $left;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -108,6 +111,7 @@ class BudgetLine
|
||||
public function setOverspent(string $overspent): BudgetLine
|
||||
{
|
||||
$this->overspent = $overspent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -127,6 +131,7 @@ class BudgetLine
|
||||
public function setRepetition(LimitRepetition $repetition): BudgetLine
|
||||
{
|
||||
$this->repetition = $repetition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -146,6 +151,7 @@ class BudgetLine
|
||||
public function setSpent(string $spent): BudgetLine
|
||||
{
|
||||
$this->spent = $spent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -1,385 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Importer.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
namespace FireflyIII\Helpers\Csv;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\TransactionJournalStored;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Converter\ConverterInterface;
|
||||
use FireflyIII\Helpers\Csv\PostProcessing\PostProcessorInterface;
|
||||
use FireflyIII\Helpers\Csv\Specifix\SpecifixInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class Importer
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
class Importer
|
||||
{
|
||||
|
||||
/** @var Data */
|
||||
protected $data;
|
||||
/** @var array */
|
||||
protected $errors = [];
|
||||
/** @var array */
|
||||
protected $importData;
|
||||
/** @var array */
|
||||
protected $importRow;
|
||||
/** @var int */
|
||||
protected $imported = 0;
|
||||
/** @var Collection */
|
||||
protected $journals;
|
||||
/** @var array */
|
||||
protected $map;
|
||||
/** @var array */
|
||||
protected $mapped;
|
||||
/** @var array */
|
||||
protected $roles;
|
||||
/** @var int */
|
||||
protected $rows = 0;
|
||||
/** @var array */
|
||||
protected $specifix = [];
|
||||
|
||||
/**
|
||||
* Used by CsvController.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors(): array
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by CsvController
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getImported(): int
|
||||
{
|
||||
return $this->imported;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournals(): Collection
|
||||
{
|
||||
return $this->journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by CsvController
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRows(): int
|
||||
{
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSpecifix(): array
|
||||
{
|
||||
return is_array($this->specifix) ? $this->specifix : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
$this->journals = new Collection;
|
||||
$this->map = $this->data->getMap();
|
||||
$this->roles = $this->data->getRoles();
|
||||
$this->mapped = $this->data->getMapped();
|
||||
$this->specifix = $this->data->getSpecifix();
|
||||
|
||||
foreach ($this->data->getReader() as $index => $row) {
|
||||
if ($this->parseRow($index)) {
|
||||
$this->rows++;
|
||||
$result = $this->importRow($row);
|
||||
if (!($result instanceof TransactionJournal)) {
|
||||
Log::error('Caught error at row #' . $index . ': ' . $result);
|
||||
$this->errors[$index] = $result;
|
||||
} else {
|
||||
$this->imported++;
|
||||
$this->journals->push($result);
|
||||
event(new TransactionJournalStored($result, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Data $data
|
||||
*/
|
||||
public function setData(Data $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TransactionJournal|string
|
||||
*/
|
||||
protected function createTransactionJournal()
|
||||
{
|
||||
$date = $this->importData['date'];
|
||||
if (is_null($this->importData['date'])) {
|
||||
$date = $this->importData['date-rent'];
|
||||
}
|
||||
|
||||
|
||||
$transactionType = $this->getTransactionType(); // defaults to deposit
|
||||
$errors = new MessageBag;
|
||||
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'transaction_type_id' => $transactionType->id,
|
||||
'transaction_currency_id' => $this->importData['currency']->id,
|
||||
'description' => $this->importData['description'],
|
||||
'completed' => 0,
|
||||
'date' => $date,
|
||||
'bill_id' => $this->importData['bill-id'],
|
||||
]
|
||||
);
|
||||
if ($journal->getErrors()->count() == 0) {
|
||||
// first transaction
|
||||
$accountId = $this->importData['asset-account-object']->id; // create first transaction:
|
||||
$amount = $this->importData['amount'];
|
||||
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
|
||||
$errors = $transaction->getErrors();
|
||||
|
||||
// second transaction
|
||||
$accountId = $this->importData['opposing-account-object']->id; // create second transaction:
|
||||
$amount = bcmul($this->importData['amount'], '-1');
|
||||
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
|
||||
$errors = $transaction->getErrors()->merge($errors);
|
||||
}
|
||||
if ($errors->count() == 0) {
|
||||
$journal->completed = 1;
|
||||
$journal->save();
|
||||
} else {
|
||||
$text = join(',', $errors->all());
|
||||
|
||||
return $text;
|
||||
}
|
||||
$this->saveBudget($journal);
|
||||
$this->saveCategory($journal);
|
||||
$this->saveTags($journal);
|
||||
|
||||
// some debug info:
|
||||
$journalId = $journal->id;
|
||||
$type = $journal->transaction_type_type ?? $journal->transactionType->type;
|
||||
/** @var Account $asset */
|
||||
$asset = $this->importData['asset-account-object'];
|
||||
/** @var Account $opposing */
|
||||
$opposing = $this->importData['opposing-account-object'];
|
||||
|
||||
Log::info('Created journal #' . $journalId . ' of type ' . $type . '!');
|
||||
Log::info('Asset account #' . $asset->id . ' lost/gained: ' . $this->importData['amount']);
|
||||
Log::info($opposing->accountType->type . ' #' . $opposing->id . ' lost/gained: ' . bcmul($this->importData['amount'], '-1'));
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TransactionType
|
||||
*/
|
||||
protected function getTransactionType()
|
||||
{
|
||||
$transactionType = TransactionType::where('type', TransactionType::DEPOSIT)->first();
|
||||
if ($this->importData['amount'] < 0) {
|
||||
$transactionType = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
}
|
||||
|
||||
if (in_array($this->importData['opposing-account-object']->accountType->type, ['Asset account', 'Default account'])) {
|
||||
$transactionType = TransactionType::where('type', TransactionType::TRANSFER)->first();
|
||||
}
|
||||
|
||||
return $transactionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @return string|bool
|
||||
*/
|
||||
protected function importRow(array $row)
|
||||
{
|
||||
|
||||
$data = $this->getFiller(); // These fields are necessary to create a new transaction journal. Some are optional
|
||||
foreach ($row as $index => $value) {
|
||||
$role = $this->roles[$index] ?? '_ignore';
|
||||
$class = config('csv.roles.' . $role . '.converter');
|
||||
$field = config('csv.roles.' . $role . '.field');
|
||||
|
||||
|
||||
// here would be the place where preprocessors would fire.
|
||||
|
||||
/** @var ConverterInterface $converter */
|
||||
$converter = app('FireflyIII\Helpers\Csv\Converter\\' . $class);
|
||||
$converter->setData($data); // the complete array so far.
|
||||
$converter->setField($field);
|
||||
$converter->setIndex($index);
|
||||
$converter->setMapped($this->mapped);
|
||||
$converter->setValue($value);
|
||||
$data[$field] = $converter->convert();
|
||||
}
|
||||
// move to class vars.
|
||||
$this->importData = $data;
|
||||
$this->importRow = $row;
|
||||
unset($data, $row);
|
||||
// post processing and validating.
|
||||
$this->postProcess();
|
||||
$result = $this->validateData();
|
||||
|
||||
if (!($result === true)) {
|
||||
return $result; // return error.
|
||||
}
|
||||
$journal = $this->createTransactionJournal();
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseRow(int $index)
|
||||
{
|
||||
return (($this->data->hasHeaders() && $index >= 1) || !$this->data->hasHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* Row denotes the original data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function postProcess()
|
||||
{
|
||||
// do bank specific fixes (must be enabled but now all of them.
|
||||
|
||||
foreach ($this->getSpecifix() as $className) {
|
||||
/** @var SpecifixInterface $specifix */
|
||||
$specifix = app('FireflyIII\Helpers\Csv\Specifix\\' . $className);
|
||||
if ($specifix->getProcessorType() == SpecifixInterface::POST_PROCESSOR) {
|
||||
$specifix->setData($this->importData);
|
||||
$specifix->setRow($this->importRow);
|
||||
$this->importData = $specifix->fix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$set = config('csv.post_processors');
|
||||
foreach ($set as $className) {
|
||||
/** @var PostProcessorInterface $postProcessor */
|
||||
$postProcessor = app('FireflyIII\Helpers\Csv\PostProcessing\\' . $className);
|
||||
$array = $this->importData ?? [];
|
||||
$postProcessor->setData($array);
|
||||
$this->importData = $postProcessor->process();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveBudget(TransactionJournal $journal)
|
||||
{
|
||||
// add budget:
|
||||
if (!is_null($this->importData['budget'])) {
|
||||
$journal->budgets()->save($this->importData['budget']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveCategory(TransactionJournal $journal)
|
||||
{
|
||||
// add category:
|
||||
if (!is_null($this->importData['category'])) {
|
||||
$journal->categories()->save($this->importData['category']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveTags(TransactionJournal $journal)
|
||||
{
|
||||
if (!is_null($this->importData['tags'])) {
|
||||
foreach ($this->importData['tags'] as $tag) {
|
||||
$journal->tags()->save($tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function validateData()
|
||||
{
|
||||
$date = $this->importData['date'] ?? null;
|
||||
$rentDate = $this->importData['date-rent'] ?? null;
|
||||
if (is_null($date) && is_null($rentDate)) {
|
||||
return 'No date value for this row.';
|
||||
}
|
||||
if (is_null($this->importData['opposing-account-object'])) {
|
||||
return 'Opposing account is null';
|
||||
}
|
||||
|
||||
if (!($this->importData['asset-account-object'] instanceof Account)) {
|
||||
return 'No asset account to import into.';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getFiller()
|
||||
{
|
||||
$filler = [];
|
||||
foreach (config('csv.roles') as $role) {
|
||||
if (isset($role['field'])) {
|
||||
$fieldName = $role['field'];
|
||||
$filler[$fieldName] = null;
|
||||
}
|
||||
}
|
||||
// some extra's:
|
||||
$filler['bill-id'] = null;
|
||||
$filler['opposing-account-object'] = null;
|
||||
$filler['asset-account-object'] = null;
|
||||
$filler['amount-modifier'] = '1';
|
||||
|
||||
return $filler;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -262,6 +262,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
/**
|
||||
* @param Balance $balance
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
*
|
||||
* @return Balance
|
||||
*/
|
||||
private function removeUnusedBudgets(Balance $balance): Balance
|
||||
|
@ -82,8 +82,8 @@ class ReportHelper implements ReportHelperInterface
|
||||
$billLine = new BillLine;
|
||||
$billLine->setBill($bill);
|
||||
$billLine->setActive(intval($bill->active) === 1);
|
||||
$billLine->setMin($bill->amount_min);
|
||||
$billLine->setMax($bill->amount_max);
|
||||
$billLine->setMin(strval($bill->amount_min));
|
||||
$billLine->setMax(strval($bill->amount_max));
|
||||
$billLine->setHit(false);
|
||||
// is hit in period?
|
||||
|
||||
|
@ -50,7 +50,7 @@ class AccountController extends Controller
|
||||
/**
|
||||
* @param string $what
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function create(string $what = 'asset')
|
||||
{
|
||||
@ -116,7 +116,7 @@ class AccountController extends Controller
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(ARI $repository, Account $account)
|
||||
{
|
||||
@ -172,7 +172,9 @@ class AccountController extends Controller
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$types = config('firefly.accountTypesByIdentifier.' . $what);
|
||||
$accounts = $crud->getAccountsByType($types);
|
||||
/** @var Carbon $start */
|
||||
$start = clone session('start', Carbon::now()->startOfMonth());
|
||||
/** @var Carbon $end */
|
||||
$end = clone session('end', Carbon::now()->endOfMonth());
|
||||
$start->subDay();
|
||||
|
||||
@ -196,7 +198,7 @@ class AccountController extends Controller
|
||||
* @param ARI $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function show(ARI $repository, Account $account)
|
||||
{
|
||||
@ -204,7 +206,9 @@ class AccountController extends Controller
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$subTitle = $account->name;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$page = intval(Input::get('page'));
|
||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||
@ -287,7 +291,7 @@ class AccountController extends Controller
|
||||
* @param AccountFormRequest $request
|
||||
* @param AccountCrudInterface $crud
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function store(AccountFormRequest $request, AccountCrudInterface $crud)
|
||||
{
|
||||
@ -335,7 +339,7 @@ class AccountController extends Controller
|
||||
* @param AccountCrudInterface $crud
|
||||
* @param Account $account
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(AccountFormRequest $request, AccountCrudInterface $crud, Account $account)
|
||||
{
|
||||
|
49
app/Http/Controllers/Admin/ConfigurationController.php
Normal file
49
app/Http/Controllers/Admin/ConfigurationController.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* ConfigurationController.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class ConfigurationController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers\Admin
|
||||
*/
|
||||
class ConfigurationController extends Controller
|
||||
{
|
||||
/**
|
||||
* ConfigurationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
View::share('title', strval(trans('firefly.administration')));
|
||||
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$subTitle = strval(trans('firefly.instance_configuration'));
|
||||
$subTitleIcon = 'fa-wrench';
|
||||
|
||||
return view('admin.configuration.index', compact('subTitle', 'subTitleIcon'));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -35,7 +35,7 @@ class DomainController extends Controller
|
||||
$title = strval(trans('firefly.administration'));
|
||||
$mainTitleIcon = 'fa-hand-spock-o';
|
||||
$subTitle = strval(trans('firefly.blocked_domains'));
|
||||
$subTitleIcon = 'fa-users';
|
||||
$subTitleIcon = 'fa-exclamation-circle';
|
||||
$domains = FireflyConfig::get('blocked-domains', [])->data;
|
||||
|
||||
// known domains
|
||||
|
@ -47,7 +47,7 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Attachment $attachment)
|
||||
{
|
||||
@ -93,10 +93,10 @@ class AttachmentController extends Controller
|
||||
|
||||
if ($disk->exists($file)) {
|
||||
|
||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||
$content = Crypt::decrypt($disk->get($file));
|
||||
|
||||
Log::debug('Send file to user', ['file' => $quoted, 'size' => strlen($content)]);
|
||||
Log::debug('Send file to user', ['file' => $quoted, 'size' => strlen($content)]);
|
||||
|
||||
return response($content, 200)
|
||||
->header('Content-Description', 'File Transfer')
|
||||
@ -116,7 +116,7 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Attachment $attachment)
|
||||
{
|
||||
|
@ -223,7 +223,7 @@ class AuthController extends Controller
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $message
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function sendFailedLoginResponse(Request $request, string $message)
|
||||
{
|
||||
|
@ -68,6 +68,8 @@ class ConfirmationController extends Controller
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function resendConfirmation(Request $request)
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ class PasswordController extends Controller
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function sendResetLinkEmail(Request $request)
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
@ -66,7 +66,7 @@ class BillController extends Controller
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Bill $bill)
|
||||
{
|
||||
@ -99,7 +99,7 @@ class BillController extends Controller
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Bill $bill)
|
||||
{
|
||||
@ -123,11 +123,13 @@ class BillController extends Controller
|
||||
/**
|
||||
* @param BillRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function index(BillRepositoryInterface $repository)
|
||||
{
|
||||
/** @var Carbon $start */
|
||||
$start = session('start');
|
||||
/** @var Carbon $end */
|
||||
$end = session('end');
|
||||
|
||||
$bills = $repository->getBills();
|
||||
@ -187,7 +189,7 @@ class BillController extends Controller
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function show(BillRepositoryInterface $repository, Bill $bill)
|
||||
{
|
||||
@ -195,7 +197,7 @@ class BillController extends Controller
|
||||
$date = session('start');
|
||||
$year = $date->year;
|
||||
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
|
||||
$pageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$journals = $repository->getJournals($bill, $page, $pageSize);
|
||||
$yearAverage = $repository->getYearAverage($bill, $date);
|
||||
$overallAverage = $repository->getOverallAverage($bill);
|
||||
|
@ -82,7 +82,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
@ -101,7 +101,7 @@ class BudgetController extends Controller
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Budget $budget)
|
||||
{
|
||||
@ -138,7 +138,7 @@ class BudgetController extends Controller
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Budget $budget)
|
||||
{
|
||||
@ -237,7 +237,7 @@ class BudgetController extends Controller
|
||||
/**
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function noBudget(BudgetRepositoryInterface $repository)
|
||||
{
|
||||
@ -411,7 +411,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function updateIncome()
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ class CategoryController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
@ -66,7 +66,7 @@ class CategoryController extends Controller
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Category $category)
|
||||
{
|
||||
@ -101,7 +101,7 @@ class CategoryController extends Controller
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Category $category)
|
||||
{
|
||||
@ -122,7 +122,7 @@ class CategoryController extends Controller
|
||||
/**
|
||||
* @param CRI $repository
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function index(CRI $repository)
|
||||
{
|
||||
@ -140,7 +140,7 @@ class CategoryController extends Controller
|
||||
/**
|
||||
* @param CRI $repository
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function noCategory(CRI $repository)
|
||||
{
|
||||
@ -166,9 +166,10 @@ class CategoryController extends Controller
|
||||
*/
|
||||
public function show(CRI $repository, AccountCrudInterface $crud, Category $category)
|
||||
{
|
||||
/** @var Carbon $carbon */
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$hideCategory = true; // used in list.
|
||||
$page = intval(Input::get('page'));
|
||||
@ -232,7 +233,7 @@ class CategoryController extends Controller
|
||||
*
|
||||
* @param $date
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function showWithDate(CRI $repository, Category $category, string $date)
|
||||
{
|
||||
|
@ -214,8 +214,9 @@ class BudgetController extends Controller
|
||||
$repetitions = $repetitions->filter(
|
||||
function (LimitRepetition $repetition) use ($budgetIds) {
|
||||
if (in_array(strval($repetition->budget_id), $budgetIds)) {
|
||||
return $repetition;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
/** @var LimitRepetition $repetition */
|
||||
@ -289,8 +290,9 @@ class BudgetController extends Controller
|
||||
$reps = $repetitions->filter(
|
||||
function (LimitRepetition $repetition) use ($budget, $currentStart) {
|
||||
if ($repetition->budget_id === $budget->id && $repetition->startdate == $currentStart) {
|
||||
return $repetition;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
$budgeted = $reps->sum('amount');
|
||||
@ -325,8 +327,9 @@ class BudgetController extends Controller
|
||||
return $repetitions->filter(
|
||||
function (LimitRepetition $repetition) use ($budget, $start, $end) {
|
||||
if ($repetition->startdate < $end && $repetition->enddate > $start && $repetition->budget_id === $budget->id) {
|
||||
return $repetition;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class CurrencyController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
@ -131,7 +131,7 @@ class CurrencyController extends Controller
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(TransactionCurrency $currency)
|
||||
{
|
||||
@ -154,7 +154,7 @@ class CurrencyController extends Controller
|
||||
/**
|
||||
* @param CurrencyRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function index(CurrencyRepositoryInterface $repository)
|
||||
{
|
||||
@ -175,7 +175,7 @@ class CurrencyController extends Controller
|
||||
* @param CurrencyFormRequest $request
|
||||
* @param CurrencyRepositoryInterface $repository
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function store(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository)
|
||||
{
|
||||
|
@ -10,7 +10,6 @@
|
||||
declare(strict_types = 1);
|
||||
|
||||
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
@ -18,7 +17,6 @@ use ExpandedForm;
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Export\Processor;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\ExportFormRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
@ -94,7 +92,7 @@ class ExportController extends Controller
|
||||
* @param AccountCrudInterface $crud
|
||||
* @param EJRI $jobs
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function index(AccountCrudInterface $crud, EJRI $jobs)
|
||||
{
|
||||
|
@ -97,7 +97,7 @@ class HomeController extends Controller
|
||||
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
foreach ($tag->transactionjournals()->get() as $journal) {
|
||||
foreach ($tag->transactionJournals()->get() as $journal) {
|
||||
$count = $journal->tags()->count();
|
||||
$journal->tag_count = $count;
|
||||
$journal->save();
|
||||
|
@ -263,7 +263,7 @@ class ImportController extends Controller
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return View
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function settings(ImportJob $job)
|
||||
@ -305,8 +305,9 @@ class ImportController extends Controller
|
||||
*/
|
||||
public function start(ImportJob $job)
|
||||
{
|
||||
set_time_limit(0);
|
||||
if ($job->status == "settings_complete") {
|
||||
ImportProcedure::run($job);
|
||||
ImportProcedure::runImport($job);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ class NewUserController extends Controller
|
||||
/**
|
||||
* @param ARI $repository
|
||||
*
|
||||
* @@return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
* @@return View
|
||||
*/
|
||||
public function index(ARI $repository)
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ class PiggyBankController extends Controller
|
||||
* @param ARI $repository
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return $this
|
||||
* @return View
|
||||
*/
|
||||
public function add(ARI $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
@ -74,7 +74,7 @@ class PiggyBankController extends Controller
|
||||
* @param ARI $repository
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return $this
|
||||
* @return View
|
||||
*/
|
||||
public function addMobile(ARI $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
@ -113,7 +113,7 @@ class PiggyBankController extends Controller
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return $this
|
||||
* @return View
|
||||
*/
|
||||
public function delete(PiggyBank $piggyBank)
|
||||
{
|
||||
@ -254,6 +254,7 @@ class PiggyBankController extends Controller
|
||||
public function postAdd(PiggyBankRepositoryInterface $repository, ARI $accounts, PiggyBank $piggyBank)
|
||||
{
|
||||
$amount = strval(round(Input::get('amount'), 2));
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', Carbon::now()->endOfMonth());
|
||||
$leftOnAccount = $accounts->leftOnAccount($piggyBank->account, $date);
|
||||
$savedSoFar = strval($piggyBank->currentRelevantRep()->currentamount);
|
||||
@ -320,7 +321,7 @@ class PiggyBankController extends Controller
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function remove(PiggyBank $piggyBank)
|
||||
{
|
||||
@ -332,7 +333,7 @@ class PiggyBankController extends Controller
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return $this
|
||||
* @return View
|
||||
*/
|
||||
public function removeMobile(PiggyBank $piggyBank)
|
||||
{
|
||||
@ -358,7 +359,7 @@ class PiggyBankController extends Controller
|
||||
* @param PiggyBankFormRequest $request
|
||||
* @param PiggyBankRepositoryInterface $repository
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
|
@ -110,8 +110,9 @@ class ReportController extends Controller
|
||||
function (TransactionJournal $journal) {
|
||||
$tags = $journal->tags()->where('tagMode', 'balancingAct')->count();
|
||||
if ($tags === 0) {
|
||||
return $journal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
break;
|
||||
@ -191,8 +192,9 @@ class ReportController extends Controller
|
||||
$journals = $journals->filter(
|
||||
function (TransactionJournal $journal) use ($account) {
|
||||
if ($journal->destination_account_id === $account->id) {
|
||||
return $journal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
@ -225,8 +227,9 @@ class ReportController extends Controller
|
||||
$journal->source_account_id === $account->id
|
||||
&& in_array($journal->destination_account_id, $destinations)
|
||||
) {
|
||||
return $journal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -46,6 +46,7 @@ class PreferencesController extends Controller
|
||||
public function code(Google2FA $google2fa)
|
||||
{
|
||||
$domain = $this->getDomain();
|
||||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
$secret = $google2fa->generateSecretKey(16, Auth::user()->id);
|
||||
Session::flash('two-factor-secret', $secret);
|
||||
$image = $google2fa->getQRCodeInline('Firefly III at ' . $domain, null, $secret, 150);
|
||||
|
@ -19,6 +19,7 @@ use FireflyIII\User;
|
||||
use Hash;
|
||||
use Preferences;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class ProfileController
|
||||
@ -36,7 +37,7 @@ class ProfileController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function changePassword()
|
||||
{
|
||||
@ -46,7 +47,7 @@ class ProfileController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function deleteAccount()
|
||||
{
|
||||
@ -56,7 +57,7 @@ class ProfileController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*
|
||||
*/
|
||||
public function index()
|
||||
|
@ -233,7 +233,7 @@ class RuleController extends Controller
|
||||
* @param RuleRepositoryInterface $repository
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function store(RuleFormRequest $request, RuleRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||
{
|
||||
@ -281,7 +281,7 @@ class RuleController extends Controller
|
||||
*
|
||||
* @param TestRuleFormRequest $request
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function testTriggers(TestRuleFormRequest $request)
|
||||
{
|
||||
@ -336,7 +336,7 @@ class RuleController extends Controller
|
||||
* @param RuleFormRequest $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(RuleRepositoryInterface $repository, RuleFormRequest $request, Rule $rule)
|
||||
{
|
||||
|
@ -200,7 +200,7 @@ class RuleGroupController extends Controller
|
||||
* @param RuleGroupFormRequest $request
|
||||
* @param RuleGroupRepositoryInterface $repository
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function store(RuleGroupFormRequest $request, RuleGroupRepositoryInterface $repository)
|
||||
{
|
||||
@ -245,7 +245,7 @@ class RuleGroupController extends Controller
|
||||
* @param RuleGroupRepositoryInterface $repository
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(RuleGroupFormRequest $request, RuleGroupRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ class TagController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
@ -88,7 +88,7 @@ class TagController extends Controller
|
||||
/**
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Tag $tag)
|
||||
{
|
||||
@ -123,7 +123,7 @@ class TagController extends Controller
|
||||
/**
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Tag $tag)
|
||||
{
|
||||
@ -220,14 +220,14 @@ class TagController extends Controller
|
||||
/**
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function show(Tag $tag)
|
||||
{
|
||||
$subTitle = $tag->tag;
|
||||
$subTitleIcon = 'fa-tag';
|
||||
/** @var Collection $journals */
|
||||
$journals = $tag->transactionjournals()->sortCorrectly()->expanded()->get(TransactionJournal::queryFields());
|
||||
$journals = $tag->transactionJournals()->sortCorrectly()->expanded()->get(TransactionJournal::queryFields());
|
||||
|
||||
$sum = $journals->sum(
|
||||
function (TransactionJournal $journal) {
|
||||
|
@ -75,7 +75,7 @@ class MassController extends Controller
|
||||
/** @var int $journalId */
|
||||
foreach ($ids as $journalId) {
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $repository->find($journalId);
|
||||
$journal = $repository->find(intval($journalId));
|
||||
if (!is_null($journal->id) && $journalId == $journal->id) {
|
||||
$set->push($journal);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ class SplitController extends Controller
|
||||
* @param JournalInterface $repository
|
||||
* @param AttachmentHelperInterface $att
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(TransactionJournal $journal, SplitJournalFormRequest $request, JournalInterface $repository, AttachmentHelperInterface $att)
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ class TransactionController extends Controller
|
||||
/**
|
||||
* @param string $what
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function create(string $what = TransactionType::DEPOSIT)
|
||||
{
|
||||
@ -88,7 +88,7 @@ class TransactionController extends Controller
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function delete(TransactionJournal $journal)
|
||||
{
|
||||
@ -273,7 +273,7 @@ class TransactionController extends Controller
|
||||
|
||||
// store the journal only, flash the rest.
|
||||
if ($doSplit) {
|
||||
$journal = $repository->storeJournal($journalData);
|
||||
$journal = $repository->storeJournal($journalData);
|
||||
$journal->completed = false;
|
||||
$journal->save();
|
||||
|
||||
@ -336,7 +336,7 @@ class TransactionController extends Controller
|
||||
* @param AttachmentHelperInterface $att
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att, TransactionJournal $journal)
|
||||
{
|
||||
|
@ -120,6 +120,14 @@ Breadcrumbs::register(
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'admin.configuration.index', function (BreadCrumbGenerator $breadcrumbs) {
|
||||
$breadcrumbs->parent('admin.index');
|
||||
$breadcrumbs->push(trans('firefly.instance_configuration'), route('admin.configuration.index'));
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* ATTACHMENTS
|
||||
*/
|
||||
|
@ -295,10 +295,10 @@ Route::group(
|
||||
* Preferences Controller
|
||||
*/
|
||||
Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']);
|
||||
Route::post('/preferences', ['uses' => 'PreferencesController@postIndex']);
|
||||
Route::post('/preferences', ['uses' => 'PreferencesController@postIndex', 'as' => 'preferences.update']);
|
||||
Route::get('/preferences/code', ['uses' => 'PreferencesController@code', 'as' => 'preferences.code']);
|
||||
Route::get('/preferences/delete-code', ['uses' => 'PreferencesController@deleteCode', 'as' => 'preferences.delete-code']);
|
||||
Route::post('/preferences/code', ['uses' => 'PreferencesController@postCode']);
|
||||
Route::post('/preferences/code', ['uses' => 'PreferencesController@postCode', 'as' => 'preferences.code.store']);
|
||||
|
||||
/**
|
||||
* Profile Controller
|
||||
@ -306,8 +306,8 @@ Route::group(
|
||||
Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']);
|
||||
Route::get('/profile/change-password', ['uses' => 'ProfileController@changePassword', 'as' => 'profile.change-password']);
|
||||
Route::get('/profile/delete-account', ['uses' => 'ProfileController@deleteAccount', 'as' => 'profile.delete-account']);
|
||||
Route::post('/profile/delete-account', ['uses' => 'ProfileController@postDeleteAccount', 'as' => 'delete-account-post']);
|
||||
Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']);
|
||||
Route::post('/profile/delete-account', ['uses' => 'ProfileController@postDeleteAccount', 'as' => 'profile.delete-account.post']);
|
||||
Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'profile.change-password.store']);
|
||||
|
||||
/**
|
||||
* Report Controller
|
||||
@ -435,5 +435,8 @@ Route::group(
|
||||
Route::get('/admin/domains/toggle/{domain}', ['uses' => 'Admin\DomainController@toggleDomain', 'as' => 'admin.users.domains.block-toggle']);
|
||||
Route::post('/admin/domains/manual', ['uses' => 'Admin\DomainController@manual', 'as' => 'admin.users.domains.manual']);
|
||||
|
||||
// FF configuration:
|
||||
Route::get('/admin/configuration', ['uses' => 'Admin\ConfigurationController@index', 'as' => 'admin.configuration.index']);
|
||||
|
||||
}
|
||||
);
|
||||
|
@ -27,6 +27,7 @@ class BillName extends BasicConverter implements ConverterInterface
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return Bill
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function convert($value)
|
||||
@ -36,6 +37,7 @@ class BillName extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Bill;
|
||||
}
|
||||
|
||||
@ -48,6 +50,7 @@ class BillName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($bill->id)) {
|
||||
Log::debug('Found bill by ID', ['id' => $bill->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $bill;
|
||||
}
|
||||
}
|
||||
@ -57,6 +60,7 @@ class BillName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($bill->id)) {
|
||||
Log::debug('Found bill by name ', ['id' => $bill->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $bill;
|
||||
}
|
||||
|
||||
@ -66,7 +70,7 @@ class BillName extends BasicConverter implements ConverterInterface
|
||||
'name' => $value,
|
||||
'match' => $value,
|
||||
'amount_min' => 1,
|
||||
'user' => $this->user->id,
|
||||
'user' => $this->user->id,
|
||||
'amount_max' => 10,
|
||||
'date' => date('Ymd'),
|
||||
'repeat_freq' => 'monthly',
|
||||
|
@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Converter;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Log;
|
||||
@ -36,6 +35,7 @@ class BudgetId extends BasicConverter implements ConverterInterface
|
||||
|
||||
if ($value === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Budget;
|
||||
}
|
||||
|
||||
@ -58,6 +58,7 @@ class BudgetId extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($budget->id)) {
|
||||
Log::debug('Found budget by ID ', ['id' => $budget->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $budget;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Converter;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Log;
|
||||
@ -36,6 +35,7 @@ class BudgetName extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Budget;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ class BudgetName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($budget->id)) {
|
||||
Log::debug('Found budget by ID', ['id' => $budget->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $budget;
|
||||
}
|
||||
}
|
||||
@ -57,14 +58,15 @@ class BudgetName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($budget->id)) {
|
||||
Log::debug('Found budget by name ', ['id' => $budget->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $budget;
|
||||
}
|
||||
|
||||
// create new budget. Use a lot of made up values.
|
||||
$budget = $repository->store(
|
||||
[
|
||||
'name' => $value,
|
||||
'user' => $this->user->id,
|
||||
'name' => $value,
|
||||
'user' => $this->user->id,
|
||||
]
|
||||
);
|
||||
$this->setCertainty(100);
|
||||
|
@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Converter;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use Log;
|
||||
@ -36,6 +35,7 @@ class CategoryId extends BasicConverter implements ConverterInterface
|
||||
|
||||
if ($value === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Category;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ class CategoryId extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($category->id)) {
|
||||
Log::debug('Found category by ID', ['id' => $category->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
@ -57,6 +58,7 @@ class CategoryId extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($category->id)) {
|
||||
Log::debug('Found category by ID ', ['id' => $category->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Converter;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use Log;
|
||||
@ -36,6 +35,7 @@ class CategoryName extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Category;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ class CategoryName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($category->id)) {
|
||||
Log::debug('Found category by ID', ['id' => $category->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
@ -57,13 +58,14 @@ class CategoryName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($category->id)) {
|
||||
Log::debug('Found category by name ', ['id' => $category->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
// create new category. Use a lot of made up values.
|
||||
$category = $repository->store(
|
||||
[
|
||||
'name' => $value,
|
||||
'name' => $value,
|
||||
'user' => $this->user->id,
|
||||
]
|
||||
);
|
||||
|
@ -26,16 +26,16 @@ interface ConverterInterface
|
||||
*/
|
||||
public function convert($value);
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function setConfig(array $config);
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCertainty(): int;
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function setConfig(array $config);
|
||||
|
||||
/**
|
||||
* @param bool $doMap
|
||||
*/
|
||||
|
@ -41,6 +41,7 @@ class CurrencyCode extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($currency->id)) {
|
||||
Log::debug('Found currency by ID', ['id' => $currency->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
||||
@ -50,6 +51,7 @@ class CurrencyCode extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($currency->id)) {
|
||||
Log::debug('Found currency by code', ['id' => $currency->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
$currency = $repository->store(
|
||||
|
@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Converter;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Log;
|
||||
@ -36,6 +35,7 @@ class CurrencyId extends BasicConverter implements ConverterInterface
|
||||
|
||||
if ($value === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new TransactionCurrency;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ class CurrencyId extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($currency->id)) {
|
||||
Log::debug('Found currency by ID', ['id' => $currency->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
||||
@ -57,6 +58,7 @@ class CurrencyId extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($currency->id)) {
|
||||
Log::debug('Found currency by ID ', ['id' => $currency->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
$this->setCertainty(0);
|
||||
|
@ -35,6 +35,7 @@ class CurrencyName extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new TransactionCurrency;
|
||||
}
|
||||
|
||||
@ -47,6 +48,7 @@ class CurrencyName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($currency->id)) {
|
||||
Log::debug('Found currency by ID', ['id' => $currency->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
||||
@ -56,6 +58,7 @@ class CurrencyName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($currency->id)) {
|
||||
Log::debug('Found currency by name ', ['id' => $currency->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ class CurrencySymbol extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new TransactionCurrency;
|
||||
}
|
||||
|
||||
@ -47,6 +48,7 @@ class CurrencySymbol extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($currency->id)) {
|
||||
Log::debug('Found currency by ID', ['id' => $currency->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
||||
@ -56,6 +58,7 @@ class CurrencySymbol extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($currency->id)) {
|
||||
Log::debug('Found currency by symbol ', ['id' => $currency->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
|
||||
|
@ -40,10 +40,12 @@ class Date extends BasicConverter implements ConverterInterface
|
||||
Log::info($e->getMessage());
|
||||
Log::info('Cannot convert this string using the given format.', ['value' => $value, 'format' => $this->config['date-format']]);
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Carbon;
|
||||
}
|
||||
Log::debug('Converted date', ['converted' => $date->toAtomString()]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Converter;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
@ -34,11 +33,13 @@ class INGDebetCredit extends BasicConverter implements ConverterInterface
|
||||
if ($value === 'Af') {
|
||||
Log::debug('Return -1');
|
||||
$this->setCertainty(100);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
$this->setCertainty(100);
|
||||
Log::debug('Return 1');
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
@ -48,6 +49,7 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by ID', ['id' => $account->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Import\Converter;
|
||||
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use Log;
|
||||
@ -37,6 +36,7 @@ class OpposingAccountNumber extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ class OpposingAccountNumber extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by ID', ['id' => $account->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
@ -59,6 +60,7 @@ class OpposingAccountNumber extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by number', ['id' => $account->id]);
|
||||
$this->setCertainty(50);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
@ -79,6 +81,7 @@ class OpposingAccountNumber extends BasicConverter implements ConverterInterface
|
||||
'virtualBalance' => 0, 'accountNumber' => $value, 'active' => true]
|
||||
);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $account;
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class ImportProcedure
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public static function run(ImportJob $job): Collection
|
||||
public static function runImport(ImportJob $job): Collection
|
||||
{
|
||||
// update job to say we started.
|
||||
$job->status = 'import_running';
|
||||
@ -61,9 +61,8 @@ class ImportProcedure
|
||||
$cleaned = $validator->clean();
|
||||
|
||||
// then import collection:
|
||||
$storage = new ImportStorage($cleaned);
|
||||
$storage = new ImportStorage($job->user, $cleaned);
|
||||
$storage->setJob($job);
|
||||
$storage->setUser($job->user);
|
||||
|
||||
// and run store routine:
|
||||
$result = $storage->store();
|
||||
@ -78,4 +77,4 @@ class ImportProcedure
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,188 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ImportResult.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class ImportResult
|
||||
*
|
||||
* @package FireflyIII\Import
|
||||
*/
|
||||
class ImportResult
|
||||
{
|
||||
const IMPORT_SUCCESS = 1;
|
||||
const IMPORT_FAILED = 0;
|
||||
const IMPORT_VALID = 2;
|
||||
|
||||
/** @var Collection */
|
||||
public $errors;
|
||||
/** @var TransactionJournal */
|
||||
public $journal;
|
||||
/** @var Collection */
|
||||
public $messages;
|
||||
/** @var int */
|
||||
public $status = 0;
|
||||
/** @var string */
|
||||
public $title = 'No result yet.';
|
||||
/** @var Collection */
|
||||
public $warnings;
|
||||
|
||||
/**
|
||||
* ImportResult constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->errors = new Collection;
|
||||
$this->warnings = new Collection;
|
||||
$this->messages = new Collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $error
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function appendError(string $error)
|
||||
{
|
||||
$this->errors->push($error);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function appendMessage(string $message)
|
||||
{
|
||||
$this->messages->push($message);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function appendTitle(string $title)
|
||||
{
|
||||
$this->title .= $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $warning
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function appendWarning(string $warning)
|
||||
{
|
||||
$this->warnings->push($warning);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function failed()
|
||||
{
|
||||
$this->status = self::IMPORT_FAILED;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSuccess(): bool
|
||||
{
|
||||
return $this->status === self::IMPORT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $errors
|
||||
*/
|
||||
public function setErrors(Collection $errors)
|
||||
{
|
||||
$this->errors = $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
public function setJournal(TransactionJournal $journal)
|
||||
{
|
||||
$this->journal = $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $messages
|
||||
*/
|
||||
public function setMessages(Collection $messages)
|
||||
{
|
||||
$this->messages = $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTitle(string $title)
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $warnings
|
||||
*/
|
||||
public function setWarnings(Collection $warnings)
|
||||
{
|
||||
$this->warnings = $warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function success()
|
||||
{
|
||||
$this->status = self::IMPORT_SUCCESS;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->status === self::IMPORT_VALID;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function validated()
|
||||
{
|
||||
$this->status = self::IMPORT_VALID;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -13,12 +13,14 @@ namespace FireflyIII\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Rules\Processor;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@ -40,14 +42,20 @@ class ImportStorage
|
||||
/** @var User */
|
||||
public $user;
|
||||
|
||||
/** @var Collection */
|
||||
private $rules;
|
||||
|
||||
/**
|
||||
* ImportStorage constructor.
|
||||
*
|
||||
* @param User $user
|
||||
* @param Collection $entries
|
||||
*/
|
||||
public function __construct(Collection $entries)
|
||||
public function __construct(User $user, Collection $entries)
|
||||
{
|
||||
$this->entries = $entries;
|
||||
$this->user = $user;
|
||||
$this->rules = $this->getUserRules();
|
||||
|
||||
}
|
||||
|
||||
@ -78,9 +86,16 @@ class ImportStorage
|
||||
Log::notice(sprintf('Started storing %d entry(ies).', $this->entries->count()));
|
||||
foreach ($this->entries as $index => $entry) {
|
||||
Log::debug(sprintf('--- import store start for row %d ---', $index));
|
||||
$result = $this->storeSingle($index, $entry);
|
||||
|
||||
// store entry:
|
||||
$journal = $this->storeSingle($index, $entry);
|
||||
$this->job->addStepsDone(1);
|
||||
$collection->put($index, $result);
|
||||
|
||||
// apply rules:
|
||||
$this->applyRules($journal);
|
||||
$this->job->addStepsDone(1);
|
||||
|
||||
$collection->put($index, $journal);
|
||||
}
|
||||
Log::notice(sprintf('Finished storing %d entry(ies).', $collection->count()));
|
||||
|
||||
@ -103,13 +118,37 @@ class ImportStorage
|
||||
return new TransactionJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function applyRules(TransactionJournal $journal): bool
|
||||
{
|
||||
if ($this->rules->count() > 0) {
|
||||
|
||||
/** @var Rule $rule */
|
||||
foreach ($this->rules as $rule) {
|
||||
Log::debug(sprintf('Going to apply rule #%d to journal %d.', $rule->id, $journal->id));
|
||||
$processor = Processor::make($rule);
|
||||
$processor->handleTransactionJournal($journal);
|
||||
|
||||
if ($rule->stop_processing) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tag
|
||||
*/
|
||||
private function createImportTag(): Tag
|
||||
{
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$repository = app(TagRepositoryInterface::class, [$this->user]);
|
||||
$data = [
|
||||
'tag' => trans('firefly.import_with_key', ['key' => $this->job->key]),
|
||||
'date' => null,
|
||||
@ -124,6 +163,28 @@ class ImportStorage
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getUserRules(): Collection
|
||||
{
|
||||
$set = Rule::distinct()
|
||||
->where('rules.user_id', $this->user->id)
|
||||
->leftJoin('rule_groups', 'rule_groups.id', '=', 'rules.rule_group_id')
|
||||
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
||||
->where('rule_groups.active', 1)
|
||||
->where('rule_triggers.trigger_type', 'user_action')
|
||||
->where('rule_triggers.trigger_value', 'store-journal')
|
||||
->where('rules.active', 1)
|
||||
->orderBy('rule_groups.order', 'ASC')
|
||||
->orderBy('rules.order', 'ASC')
|
||||
->get(['rules.*']);
|
||||
Log::debug(sprintf('Found %d user rules.', $set->count()));
|
||||
|
||||
return $set;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $amount
|
||||
*
|
||||
@ -252,7 +313,7 @@ class ImportStorage
|
||||
$meta = new TransactionJournalMeta;
|
||||
$meta->name = 'originalImportHash';
|
||||
$meta->data = $entry->hash;
|
||||
$meta->transactionjournal()->associate($journal);
|
||||
$meta->transactionJournal()->associate($journal);
|
||||
$meta->save();
|
||||
|
||||
return $journal;
|
||||
@ -262,41 +323,35 @@ class ImportStorage
|
||||
* @param int $index
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @return ImportResult
|
||||
* @return TransactionJournal
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function storeSingle(int $index, ImportEntry $entry): ImportResult
|
||||
private function storeSingle(int $index, ImportEntry $entry): TransactionJournal
|
||||
{
|
||||
if ($entry->valid === false) {
|
||||
Log::warning(sprintf('Cannot import row %d, because the entry is not valid.', $index));
|
||||
$result = new ImportResult();
|
||||
$result->failed();
|
||||
$errors = join(', ', $entry->errors->all());
|
||||
$errorText = sprintf('Row #%d: ' . $errors, $index);
|
||||
$result->appendError($errorText);
|
||||
$errors = join(', ', $entry->errors->all());
|
||||
$errorText = sprintf('Row #%d: ' . $errors, $index);
|
||||
$extendedStatus = $this->job->extended_status;
|
||||
$extendedStatus['errors'][] = $errorText;
|
||||
$this->job->extended_status = $extendedStatus;
|
||||
$this->job->save();
|
||||
|
||||
return $result;
|
||||
return new TransactionJournal;
|
||||
}
|
||||
$alreadyImported = $this->alreadyImported($entry->hash);
|
||||
if (!is_null($alreadyImported->id)) {
|
||||
Log::warning(sprintf('Cannot import row %d, because it has already been imported (journal #%d).', $index, $alreadyImported->id));
|
||||
$result = new ImportResult();
|
||||
$result->failed();
|
||||
$errorText = trans(
|
||||
$errorText = trans(
|
||||
'firefly.import_double',
|
||||
['row' => $index, 'link' => route('transactions.show', [$alreadyImported->id]), 'description' => $alreadyImported->description]
|
||||
);
|
||||
$result->appendError($errorText);
|
||||
$extendedStatus = $this->job->extended_status;
|
||||
$extendedStatus['errors'][] = $errorText;
|
||||
$this->job->extended_status = $extendedStatus;
|
||||
$this->job->save();
|
||||
|
||||
return $result;
|
||||
return new TransactionJournal;
|
||||
}
|
||||
|
||||
Log::debug(sprintf('Going to store row %d', $index));
|
||||
@ -337,13 +392,6 @@ class ImportStorage
|
||||
$this->storeCategory($journal, $entry);
|
||||
$this->storeBill($journal, $entry);
|
||||
|
||||
$result = new ImportResult();
|
||||
$result->success();
|
||||
$result->appendMessage(sprintf('Journal titled "%s" imported.', $journal->description));
|
||||
$result->setJournal($journal);
|
||||
|
||||
return $result;
|
||||
|
||||
|
||||
return $journal;
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ use Log;
|
||||
*/
|
||||
class ImportValidator
|
||||
{
|
||||
/** @var ImportJob */
|
||||
public $job;
|
||||
/** @var Account */
|
||||
protected $defaultImportAccount;
|
||||
/** @var Collection */
|
||||
@ -36,19 +38,6 @@ class ImportValidator
|
||||
/** @var User */
|
||||
protected $user;
|
||||
|
||||
/** @var ImportJob */
|
||||
public $job;
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*/
|
||||
public function setJob(ImportJob $job)
|
||||
{
|
||||
$this->job = $job;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ImportValidator constructor.
|
||||
*
|
||||
@ -100,6 +89,14 @@ class ImportValidator
|
||||
$this->defaultImportAccount = $defaultImportAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*/
|
||||
public function setJob(ImportJob $job)
|
||||
{
|
||||
$this->job = $job;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
@ -337,7 +334,7 @@ class ImportValidator
|
||||
}
|
||||
|
||||
// amount > 0, but opposing is expense
|
||||
if ($type == AccountType::EXPENSE && $entry->fields['amount'] < 0) {
|
||||
if ($type == AccountType::EXPENSE && $entry->fields['amount'] > 0) {
|
||||
$account = $this->convertAccount($entry->fields['opposing-account'], AccountType::REVENUE);
|
||||
$entry->fields['opposing-account'] = $account;
|
||||
Log::debug('Converted expense account to revenue account');
|
||||
|
@ -64,7 +64,13 @@ class CsvImporter implements ImporterInterface
|
||||
Log::debug(sprintf('Now going to import row %d.', $index));
|
||||
$importEntry = $this->importSingleRow($index, $row);
|
||||
$this->collection->put($line, $importEntry);
|
||||
$this->job->addTotalSteps(3);
|
||||
/**
|
||||
* 1. Build import entry.
|
||||
* 2. Validate import entry.
|
||||
* 3. Store journal.
|
||||
* 4. Run rules.
|
||||
*/
|
||||
$this->job->addTotalSteps(4);
|
||||
$this->job->addStepsDone(1);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Importer;
|
||||
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
@ -29,13 +29,14 @@ class OpposingAccountIbans implements MapperInterface
|
||||
public function getMap(): array
|
||||
{
|
||||
/** @var AccountCrudInterface $crud */
|
||||
$crud = app(AccountCrudInterface::class);
|
||||
$set = $crud->getAccountsByType(
|
||||
$crud = app(AccountCrudInterface::class);
|
||||
$set = $crud->getAccountsByType(
|
||||
[
|
||||
AccountType::DEFAULT, AccountType::ASSET,
|
||||
AccountType::EXPENSE, AccountType::BENEFICIARY,
|
||||
AccountType::REVENUE
|
||||
]);
|
||||
AccountType::REVENUE,
|
||||
]
|
||||
);
|
||||
$topList = [];
|
||||
$list = [];
|
||||
|
||||
|
@ -34,8 +34,9 @@ class OpposingAccounts implements MapperInterface
|
||||
[
|
||||
AccountType::DEFAULT, AccountType::ASSET,
|
||||
AccountType::EXPENSE, AccountType::BENEFICIARY,
|
||||
AccountType::REVENUE
|
||||
]);
|
||||
AccountType::REVENUE,
|
||||
]
|
||||
);
|
||||
$list = [];
|
||||
|
||||
/** @var Account $account */
|
||||
|
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Map.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Role;
|
||||
|
||||
|
||||
class Map
|
||||
{
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Role.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Role;
|
||||
|
||||
|
||||
class Role
|
||||
{
|
||||
|
||||
}
|
@ -184,7 +184,9 @@ class CsvSetup implements SetupInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
*
|
||||
* @param FileBag $files
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -11,7 +11,6 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Setup;
|
||||
|
||||
use FireflyIII\Import\Role\Map;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\FileBag;
|
||||
@ -46,14 +45,6 @@ interface SetupInterface
|
||||
*/
|
||||
public function getDataForSettings(): array;
|
||||
|
||||
/**
|
||||
* Store the settings filled in by the user, if applicable.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
*/
|
||||
public function storeSettings(Request $request);
|
||||
|
||||
/**
|
||||
* This method returns the name of the view that will be shown to the user to further configure
|
||||
* the import job.
|
||||
@ -71,7 +62,9 @@ interface SetupInterface
|
||||
public function requireUserSettings(): bool;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
*
|
||||
* @param FileBag $files
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -82,4 +75,12 @@ interface SetupInterface
|
||||
*
|
||||
*/
|
||||
public function setJob(ImportJob $job);
|
||||
|
||||
/**
|
||||
* Store the settings filled in by the user, if applicable.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
*/
|
||||
public function storeSettings(Request $request);
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ class AbnAmroDescription implements SpecificInterface
|
||||
break;
|
||||
case 'NAAM':
|
||||
$this->row[8] = $value;
|
||||
$name = $value;
|
||||
$name = $value;
|
||||
break;
|
||||
case 'KENMERK':
|
||||
$reference = $value;
|
||||
|
@ -21,12 +21,12 @@ interface SpecificInterface
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getName(): string;
|
||||
public static function getDescription(): string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getDescription(): string;
|
||||
public static function getName(): string;
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
|
@ -183,6 +183,7 @@ class Account extends Model
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function getIbanAttribute($value): string
|
||||
{
|
||||
|
@ -156,7 +156,7 @@ class Bill extends Model
|
||||
/**
|
||||
* @return HasMany
|
||||
*/
|
||||
public function transactionjournals(): HasMany
|
||||
public function transactionJournals(): HasMany
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
@ -22,21 +22,21 @@ use Watson\Validating\ValidatingTrait;
|
||||
/**
|
||||
* FireflyIII\Models\Budget
|
||||
*
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property \Carbon\Carbon $deleted_at
|
||||
* @property string $name
|
||||
* @property integer $user_id
|
||||
* @property boolean $active
|
||||
* @property boolean $encrypted
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|BudgetLimit[] $budgetlimits
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|TransactionJournal[] $transactionjournals
|
||||
* @property-read \FireflyIII\User $user
|
||||
* @property string $dateFormatted
|
||||
* @property string $budgeted
|
||||
* @property float $amount
|
||||
* @property \Carbon\Carbon $date
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property \Carbon\Carbon $deleted_at
|
||||
* @property string $name
|
||||
* @property integer $user_id
|
||||
* @property boolean $active
|
||||
* @property boolean $encrypted
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|BudgetLimit[] $budgetlimits
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|TransactionJournal[] $transactionjournals
|
||||
* @property-read \FireflyIII\User $user
|
||||
* @property string $dateFormatted
|
||||
* @property string $budgeted
|
||||
* @property float $amount
|
||||
* @property \Carbon\Carbon $date
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereUpdatedAt($value)
|
||||
@ -46,7 +46,7 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereActive($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereEncrypted($value)
|
||||
* @mixin \Eloquent
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\LimitRepetition[] $limitrepetitions
|
||||
*/
|
||||
class Budget extends Model
|
||||
@ -146,7 +146,7 @@ class Budget extends Model
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
public function transactionJournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'budget_transaction_journal', 'budget_id');
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ class Category extends Model
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
public function transactionJournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'category_transaction_journal', 'category_id');
|
||||
}
|
||||
|
@ -18,12 +18,12 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* FireflyIII\Models\Configuration
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
* @property integer $id
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property \Carbon\Carbon $deleted_at
|
||||
* @property string $name
|
||||
* @property string $data
|
||||
* @property string $name
|
||||
* @property string $data
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Configuration whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Configuration whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Configuration whereUpdatedAt($value)
|
||||
@ -35,9 +35,8 @@ class Configuration extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $table = 'configuration';
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||
protected $table = 'configuration';
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
@ -58,5 +57,4 @@ class Configuration extends Model
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class LimitRepetition extends Model
|
||||
{
|
||||
if (Auth::check()) {
|
||||
$object = LimitRepetition::where('limit_repetitions.id', $value)
|
||||
->leftjoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
|
||||
->leftJoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->where('budgets.user_id', Auth::user()->id)
|
||||
->first(['limit_repetitions.*']);
|
||||
|
@ -40,9 +40,9 @@ use Illuminate\Database\Eloquent\Model;
|
||||
class PiggyBankRepetition extends Model
|
||||
{
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'startdate', 'targetdate'];
|
||||
protected $fillable = ['piggy_bank_id', 'startdate', 'targetdate', 'currentamount'];
|
||||
protected $hidden = ['currentamount_encrypted'];
|
||||
protected $dates = ['created_at', 'updated_at', 'startdate', 'targetdate'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
@ -57,7 +57,7 @@ class PiggyBankRepetition extends Model
|
||||
* @param Carbon $start
|
||||
* @param Carbon $target
|
||||
*
|
||||
* @return $this
|
||||
* @return EloquentBuilder
|
||||
*/
|
||||
public function scopeOnDates(EloquentBuilder $query, Carbon $start, Carbon $target)
|
||||
{
|
||||
|
@ -16,6 +16,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* FireflyIII\Models\Preference
|
||||
*
|
||||
@ -54,7 +55,7 @@ class Preference extends Model
|
||||
try {
|
||||
$data = Crypt::decrypt($value);
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt preference.', ['id' => $this->id,'name' => $this->name,'data' => $this->data]);
|
||||
Log::error('Could not decrypt preference.', ['id' => $this->id, 'name' => $this->name, 'data' => $this->data]);
|
||||
throw new FireflyException('Could not decrypt preference #' . $this->id . '.');
|
||||
}
|
||||
|
||||
|
@ -52,38 +52,6 @@ class Rule extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function ruleGroup()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\RuleGroup');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function ruleActions()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\RuleAction');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function ruleTriggers()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\RuleTrigger');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Rule $value
|
||||
*
|
||||
@ -99,4 +67,36 @@ class Rule extends Model
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function ruleActions()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\RuleAction');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function ruleGroup()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\RuleGroup');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function ruleTriggers()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\RuleTrigger');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,27 +48,10 @@ class RuleGroup extends Model
|
||||
|
||||
protected $fillable = ['user_id', 'order', 'title', 'description', 'active'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\Rule');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RuleGroup $value
|
||||
*
|
||||
* @return Rule
|
||||
* @return RuleGroup
|
||||
*/
|
||||
public static function routeBinder(RuleGroup $value)
|
||||
{
|
||||
@ -79,4 +62,20 @@ class RuleGroup extends Model
|
||||
}
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\Rule');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ class Tag extends TagSupport
|
||||
*/
|
||||
public function save(array $options = [])
|
||||
{
|
||||
foreach ($this->transactionjournals()->get() as $journal) {
|
||||
foreach ($this->transactionJournals()->get() as $journal) {
|
||||
$count = $journal->tags()->count();
|
||||
$journal->tag_count = $count;
|
||||
$journal->save();
|
||||
@ -185,7 +185,7 @@ class Tag extends TagSupport
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
public function transactionJournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class TransactionGroup extends Model
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
public function transactionJournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
* @mixin \Eloquent
|
||||
* @property string $hash
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournalMeta whereHash($value)
|
||||
* @property-read \FireflyIII\Models\TransactionJournal $transactionJournal
|
||||
*/
|
||||
class TransactionJournalMeta extends Model
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ namespace FireflyIII\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Log;
|
||||
use URL;
|
||||
|
||||
/**
|
||||
* Class AppServiceProvider
|
||||
@ -28,9 +29,16 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
|
||||
// force root URL.
|
||||
$forcedUrl = env('APP_FORCE_ROOT', '');
|
||||
if (strlen($forcedUrl) > 0) {
|
||||
URL::forceRootUrl($forcedUrl);
|
||||
}
|
||||
|
||||
// force https urls
|
||||
if (env('APP_FORCE_SSL', false)) {
|
||||
\URL::forceSchema('https');
|
||||
URL::forceSchema('https');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,10 +12,8 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Providers;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use Illuminate\Auth\AuthManager;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class CrudServiceProvider
|
||||
@ -58,6 +56,7 @@ class CrudServiceProvider extends ServiceProvider
|
||||
if (!isset($arguments[0]) && !$app->auth->check()) {
|
||||
throw new FireflyException('There is no user present.');
|
||||
}
|
||||
|
||||
return app('FireflyIII\Crud\Account\AccountCrud', $arguments);
|
||||
}
|
||||
);
|
||||
|
@ -37,8 +37,6 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
/** @var array */
|
||||
private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber'];
|
||||
|
||||
/**
|
||||
* AttachmentRepository constructor.
|
||||
@ -76,7 +74,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
public function earnedFromInPeriod(Collection $accounts, Carbon $start, Carbon $end): string
|
||||
{
|
||||
$query = $this->user->transactionjournals()->expanded()->sortCorrectly()
|
||||
$query = $this->user->transactionJournals()->expanded()->sortCorrectly()
|
||||
->transactionTypes([TransactionType::DEPOSIT]);
|
||||
|
||||
if ($end >= $start) {
|
||||
@ -113,7 +111,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
public function earnedInPeriod(Collection $accounts, Carbon $start, Carbon $end): string
|
||||
{
|
||||
$query = $this->user->transactionjournals()->expanded()->sortCorrectly()
|
||||
$query = $this->user->transactionJournals()->expanded()->sortCorrectly()
|
||||
->transactionTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]);
|
||||
|
||||
if ($end >= $start) {
|
||||
@ -144,7 +142,6 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$ids = $query->get(['transaction_journals.id'])->pluck('id')->toArray();
|
||||
|
||||
|
||||
|
||||
// that should do it:
|
||||
$sum = $this->user->transactions()
|
||||
->whereIn('transaction_journal_id', $ids)
|
||||
@ -179,15 +176,16 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$journals = $journals->filter(
|
||||
function (TransactionJournal $journal) use ($accountIds) {
|
||||
if ($journal->transaction_type_type == TransactionType::WITHDRAWAL) {
|
||||
return $journal;
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* The source of a transfer must be one of the $accounts in order to
|
||||
* be included. Otherwise, it would not be an expense.
|
||||
*/
|
||||
if (in_array($journal->source_account_id, $accountIds)) {
|
||||
return $journal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
@ -363,15 +361,16 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$journals = $journals->filter(
|
||||
function (TransactionJournal $journal) use ($accountIds) {
|
||||
if ($journal->transaction_type_type == TransactionType::DEPOSIT) {
|
||||
return $journal;
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* The destination of a transfer must be one of the $accounts in order to
|
||||
* be included. Otherwise, it would not be income.
|
||||
*/
|
||||
if (in_array($journal->destination_account_id, $accountIds)) {
|
||||
return $journal;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
@ -389,7 +388,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
public function journalsInPeriod(Collection $accounts, array $types, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
// first collect actual transaction journals (fairly easy)
|
||||
$query = $this->user->transactionjournals()->expanded()->sortCorrectly();
|
||||
$query = $this->user->transactionJournals()->expanded()->sortCorrectly();
|
||||
|
||||
if ($end >= $start) {
|
||||
$query->before($end)->after($start);
|
||||
@ -437,7 +436,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
|
||||
$balance = Steam::balanceIgnoreVirtual($account, $date);
|
||||
/** @var PiggyBank $p */
|
||||
foreach ($account->piggybanks()->get() as $p) {
|
||||
foreach ($account->piggyBanks()->get() as $p) {
|
||||
$currentAmount = $p->currentRelevantRep()->currentamount ?? '0';
|
||||
|
||||
$balance = bcsub($balance, $currentAmount);
|
||||
@ -528,7 +527,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
public function spentAtInPeriod(Collection $accounts, Carbon $start, Carbon $end): string
|
||||
{
|
||||
/** @var HasMany $query */
|
||||
$query = $this->user->transactionjournals()->expanded()->sortCorrectly()
|
||||
$query = $this->user->transactionJournals()->expanded()->sortCorrectly()
|
||||
->transactionTypes([TransactionType::WITHDRAWAL]);
|
||||
if ($end >= $start) {
|
||||
$query->before($end)->after($start);
|
||||
@ -564,7 +563,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
public function spentInPeriod(Collection $accounts, Carbon $start, Carbon $end): string
|
||||
{
|
||||
/** @var HasMany $query */
|
||||
$query = $this->user->transactionjournals()->expanded()->sortCorrectly()
|
||||
$query = $this->user->transactionJournals()->expanded()->sortCorrectly()
|
||||
->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]);
|
||||
if ($end >= $start) {
|
||||
$query->before($end)->after($start);
|
||||
|
@ -125,7 +125,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
{
|
||||
$ids = $bills->pluck('id')->toArray();
|
||||
|
||||
$set = $this->user->transactionjournals()
|
||||
$set = $this->user->transactionJournals()
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
|
||||
@ -221,7 +221,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
$ranges = $this->getRanges($bill, $start, $end);
|
||||
|
||||
foreach ($ranges as $range) {
|
||||
$paid = $bill->transactionjournals()
|
||||
$paid = $bill->transactionJournals()
|
||||
->before($range['end'])
|
||||
->after($range['start'])
|
||||
->leftJoin(
|
||||
@ -256,7 +256,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
$ranges = $this->getRanges($bill, $start, $end);
|
||||
$paidBill = '0';
|
||||
foreach ($ranges as $range) {
|
||||
$paid = $bill->transactionjournals()
|
||||
$paid = $bill->transactionJournals()
|
||||
->before($range['end'])
|
||||
->after($range['start'])
|
||||
->leftJoin(
|
||||
@ -290,7 +290,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
public function getJournals(Bill $bill, int $page, int $pageSize = 50): LengthAwarePaginator
|
||||
{
|
||||
$offset = ($page - 1) * $pageSize;
|
||||
$query = $bill->transactionjournals()
|
||||
$query = $bill->transactionJournals()
|
||||
->expanded()
|
||||
->sortCorrectly();
|
||||
$count = $query->count();
|
||||
@ -311,7 +311,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
*/
|
||||
public function getJournalsInRange(Bill $bill, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
return $bill->transactionjournals()->before($end)->after($start)->get();
|
||||
return $bill->transactionJournals()->before($end)->after($start)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -321,7 +321,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
*/
|
||||
public function getOverallAverage($bill): string
|
||||
{
|
||||
$journals = $bill->transactionjournals()->get();
|
||||
$journals = $bill->transactionJournals()->get();
|
||||
$sum = '0';
|
||||
$count = strval($journals->count());
|
||||
/** @var TransactionJournal $journal */
|
||||
@ -351,7 +351,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
|
||||
$journals = new Collection;
|
||||
if (count($ids) > 0) {
|
||||
$journals = $this->user->transactionjournals()->transactionTypes([TransactionType::WITHDRAWAL])->whereIn('transaction_journals.id', $ids)->get(
|
||||
$journals = $this->user->transactionJournals()->transactionTypes([TransactionType::WITHDRAWAL])->whereIn('transaction_journals.id', $ids)->get(
|
||||
['transaction_journals.*']
|
||||
);
|
||||
}
|
||||
@ -409,7 +409,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
*/
|
||||
public function getYearAverage(Bill $bill, Carbon $date): string
|
||||
{
|
||||
$journals = $bill->transactionjournals()
|
||||
$journals = $bill->transactionJournals()
|
||||
->where('date', '>=', $date->year . '-01-01')
|
||||
->where('date', '<=', $date->year . '-12-31')
|
||||
->get();
|
||||
@ -434,7 +434,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
*/
|
||||
public function lastFoundMatch(Bill $bill): Carbon
|
||||
{
|
||||
$last = $bill->transactionjournals()->orderBy('date', 'DESC')->first();
|
||||
$last = $bill->transactionJournals()->orderBy('date', 'DESC')->first();
|
||||
if ($last) {
|
||||
return $last->date;
|
||||
}
|
||||
@ -476,7 +476,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
if (($counter % $skip) == 0) {
|
||||
// do something.
|
||||
$end = Navigation::endOfPeriod(clone $start, $bill->repeat_freq);
|
||||
$journalCount = $bill->transactionjournals()->before($end)->after($start)->count();
|
||||
$journalCount = $bill->transactionJournals()->before($end)->after($start)->count();
|
||||
if ($journalCount == 0) {
|
||||
$finalDate = new Carbon($start->format('Y-m-d'));
|
||||
break;
|
||||
|
@ -116,7 +116,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
public function firstUseDate(Budget $budget): Carbon
|
||||
{
|
||||
$oldest = Carbon::create()->startOfYear();
|
||||
$journal = $budget->transactionjournals()->orderBy('date', 'ASC')->first();
|
||||
$journal = $budget->transactionJournals()->orderBy('date', 'ASC')->first();
|
||||
if (!is_null($journal)) {
|
||||
$oldest = $journal->date < $oldest ? $journal->date : $oldest;
|
||||
}
|
||||
@ -225,7 +225,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
}
|
||||
|
||||
// first get all journals for all budget(s):
|
||||
$journalQuery = $this->user->transactionjournals()
|
||||
$journalQuery = $this->user->transactionJournals()
|
||||
->expanded()
|
||||
->sortCorrectly()
|
||||
->before($end)
|
||||
@ -246,7 +246,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
$journals = $journalQuery->get(TransactionJournal::queryFields());
|
||||
|
||||
// then get transactions themselves.
|
||||
$transactionQuery = $this->user->transactionjournals()
|
||||
$transactionQuery = $this->user->transactionJournals()
|
||||
->expanded()
|
||||
->before($end)
|
||||
->sortCorrectly()
|
||||
@ -290,7 +290,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
|
||||
/** @var Collection $set */
|
||||
$query = $this->user
|
||||
->transactionjournals()
|
||||
->transactionJournals()
|
||||
->expanded()
|
||||
->sortCorrectly()
|
||||
->transactionTypes([TransactionType::WITHDRAWAL])
|
||||
@ -322,9 +322,10 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
function (TransactionJournal $journal) {
|
||||
foreach ($journal->transactions as $t) {
|
||||
if ($t->budgets->count() === 0) {
|
||||
return $journal;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
@ -343,7 +344,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
{
|
||||
// first collect actual transaction journals (fairly easy)
|
||||
$query = $this->user
|
||||
->transactionjournals()
|
||||
->transactionJournals()
|
||||
->leftJoin(
|
||||
'transactions as source', function (JoinClause $join) {
|
||||
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', 0);
|
||||
@ -415,7 +416,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
public function spentInPeriodWithoutBudget(Collection $accounts, Carbon $start, Carbon $end): string
|
||||
{
|
||||
$types = [TransactionType::WITHDRAWAL];
|
||||
$query = $this->user->transactionjournals()
|
||||
$query = $this->user->transactionJournals()
|
||||
->distinct()
|
||||
->transactionTypes($types)
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
|
@ -131,7 +131,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
$first = null;
|
||||
|
||||
/** @var TransactionJournal $first */
|
||||
$firstJournalQuery = $category->transactionjournals()->orderBy('date', 'ASC');
|
||||
$firstJournalQuery = $category->transactionJournals()->orderBy('date', 'ASC');
|
||||
|
||||
if ($accounts->count() > 0) {
|
||||
// filter journals:
|
||||
@ -198,13 +198,13 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
{
|
||||
$complete = new Collection;
|
||||
// first collect actual transaction journals (fairly easy)
|
||||
$query = $this->user->transactionjournals()->expanded()->sortCorrectly();
|
||||
$query = $this->user->transactionJournals()->expanded()->sortCorrectly();
|
||||
$query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
$query->where('category_transaction_journal.category_id', $category->id);
|
||||
$first = $query->get(TransactionJournal::queryFields());
|
||||
|
||||
// then collection transactions (harder)
|
||||
$query = $this->user->transactionjournals()->distinct()
|
||||
$query = $this->user->transactionJournals()->distinct()
|
||||
->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id')
|
||||
->where('category_transaction.category_id', $category->id);
|
||||
@ -245,7 +245,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
{
|
||||
$complete = new Collection;
|
||||
// first collect actual transaction journals (fairly easy)
|
||||
$query = $this->user->transactionjournals()->expanded()->sortCorrectly();
|
||||
$query = $this->user->transactionJournals()->expanded()->sortCorrectly();
|
||||
|
||||
if ($end >= $start) {
|
||||
$query->before($end)->after($start);
|
||||
@ -270,7 +270,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
|
||||
|
||||
// then collection transactions (harder)
|
||||
$query = $this->user->transactionjournals()->distinct()
|
||||
$query = $this->user->transactionJournals()->distinct()
|
||||
->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id');
|
||||
|
||||
@ -308,7 +308,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
{
|
||||
/** @var Collection $set */
|
||||
$query = $this->user
|
||||
->transactionjournals();
|
||||
->transactionJournals();
|
||||
if (count($types) > 0) {
|
||||
$query->transactionTypes($types);
|
||||
}
|
||||
@ -348,7 +348,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
// this second set REALLY doesn't have any categories.
|
||||
$secondSet = $secondQuery->get(['transactions.transaction_journal_id']);
|
||||
$allIds = $secondSet->pluck('transaction_journal_id')->toArray();
|
||||
$return = $this->user->transactionjournals()->sortCorrectly()->expanded()->whereIn('transaction_journals.id', $allIds)->get(
|
||||
$return = $this->user->transactionJournals()->sortCorrectly()->expanded()->whereIn('transaction_journals.id', $allIds)->get(
|
||||
TransactionJournal::queryFields()
|
||||
);
|
||||
|
||||
@ -368,7 +368,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
$last = null;
|
||||
|
||||
/** @var TransactionJournal $first */
|
||||
$lastJournalQuery = $category->transactionjournals()->orderBy('date', 'DESC');
|
||||
$lastJournalQuery = $category->transactionJournals()->orderBy('date', 'DESC');
|
||||
|
||||
if ($accounts->count() > 0) {
|
||||
// filter journals:
|
||||
@ -483,7 +483,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
{
|
||||
// first collect actual transaction journals (fairly easy)
|
||||
$query = $this->user
|
||||
->transactionjournals()
|
||||
->transactionJournals()
|
||||
->transactionTypes($types)
|
||||
->leftJoin(
|
||||
'transactions as source', function (JoinClause $join) {
|
||||
@ -548,7 +548,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
*/
|
||||
private function sumInPeriodWithoutCategory(Collection $accounts, array $types, Carbon $start, Carbon $end): string
|
||||
{
|
||||
$query = $this->user->transactionjournals()
|
||||
$query = $this->user->transactionJournals()
|
||||
->distinct()
|
||||
->transactionTypes($types)
|
||||
->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
|
@ -108,7 +108,7 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
*/
|
||||
public function find(int $journalId) : TransactionJournal
|
||||
{
|
||||
$journal = $this->user->transactionjournals()->where('id', $journalId)->first();
|
||||
$journal = $this->user->transactionJournals()->where('id', $journalId)->first();
|
||||
if (is_null($journal)) {
|
||||
return new TransactionJournal;
|
||||
}
|
||||
@ -123,7 +123,7 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
*/
|
||||
public function first(): TransactionJournal
|
||||
{
|
||||
$entry = $this->user->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
|
||||
$entry = $this->user->transactionJournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
|
||||
|
||||
if (is_null($entry)) {
|
||||
|
||||
|
@ -189,8 +189,8 @@ class TagRepository implements TagRepositoryInterface
|
||||
/** @var TransactionType $deposit */
|
||||
$deposit = TransactionType::whereType(TransactionType::DEPOSIT)->first();
|
||||
|
||||
$withdrawals = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->count();
|
||||
$deposits = $tag->transactionjournals()->where('transaction_type_id', $deposit->id)->count();
|
||||
$withdrawals = $tag->transactionJournals()->where('transaction_type_id', $withdrawal->id)->count();
|
||||
$deposits = $tag->transactionJournals()->where('transaction_type_id', $deposit->id)->count();
|
||||
|
||||
if ($journal->transaction_type_id == $transfer->id) { // advance payments cannot accept transfers:
|
||||
return false;
|
||||
@ -229,10 +229,10 @@ class TagRepository implements TagRepositoryInterface
|
||||
{
|
||||
/** @var TransactionType $withdrawal */
|
||||
$withdrawal = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
|
||||
$withdrawals = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->count();
|
||||
$withdrawals = $tag->transactionJournals()->where('transaction_type_id', $withdrawal->id)->count();
|
||||
/** @var TransactionType $transfer */
|
||||
$transfer = TransactionType::whereType(TransactionType::TRANSFER)->first();
|
||||
$transfers = $tag->transactionjournals()->where('transaction_type_id', $transfer->id)->count();
|
||||
$transfers = $tag->transactionJournals()->where('transaction_type_id', $transfer->id)->count();
|
||||
|
||||
|
||||
// only if this is the only withdrawal.
|
||||
|
@ -42,13 +42,6 @@ interface TagRepositoryInterface
|
||||
*/
|
||||
public function destroy(Tag $tag): bool;
|
||||
|
||||
/**
|
||||
* @param string $tag
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public function findByTag(string $tag) : Tag;
|
||||
|
||||
/**
|
||||
* @param int $tagId
|
||||
*
|
||||
@ -56,6 +49,13 @@ interface TagRepositoryInterface
|
||||
*/
|
||||
public function find(int $tagId) : Tag;
|
||||
|
||||
/**
|
||||
* @param string $tag
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public function findByTag(string $tag) : Tag;
|
||||
|
||||
/**
|
||||
* This method returns all the user's tags.
|
||||
*
|
||||
|
@ -12,7 +12,6 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Rules\Actions;
|
||||
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@ -46,7 +45,7 @@ class AddTag implements ActionInterface
|
||||
public function act(TransactionJournal $journal): bool
|
||||
{
|
||||
// journal has this tag maybe?
|
||||
$tag = Tag::firstOrCreateEncrypted(['tag' => $this->action->action_value, 'user_id' => Auth::user()->id]);
|
||||
$tag = Tag::firstOrCreateEncrypted(['tag' => $this->action->action_value, 'user_id' => $journal->user->id]);
|
||||
|
||||
$count = $journal->tags()->where('tag_id', $tag->id)->count();
|
||||
if ($count == 0) {
|
||||
|
@ -12,7 +12,6 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Rules\Actions;
|
||||
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@ -48,7 +47,7 @@ class RemoveTag implements ActionInterface
|
||||
// if tag does not exist, no need to continue:
|
||||
$name = $this->action->action_value;
|
||||
/** @var Tag $tag */
|
||||
$tag = Auth::user()->tags()->get()->filter(
|
||||
$tag = $journal->user->tags()->get()->filter(
|
||||
function (Tag $tag) use ($name) {
|
||||
return $tag->tag == $name;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user