mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
Extend rule set for import.
This commit is contained in:
@@ -66,9 +66,17 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface
|
||||
|
||||
|
||||
$account = $repository->store(
|
||||
['name' => 'Account with IBAN ' . $value, 'iban' => $value, 'user' => $this->user->id, 'accountType' => 'asset', 'virtualBalance' => 0,
|
||||
'active' => true]
|
||||
['name' => 'Asset account with IBAN ' . $value, 'iban' => $value, 'user' => $this->user->id, 'accountType' => 'asset', 'virtualBalance' => 0,
|
||||
'active' => true, 'openingBalance' => 0]
|
||||
);
|
||||
|
||||
if (is_null($account->id)) {
|
||||
$this->setCertainty(0);
|
||||
Log::info('Could not store new asset account by IBAN', $account->getErrors()->toArray());
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $account;
|
||||
|
@@ -68,6 +68,14 @@ class AssetAccountName extends BasicConverter implements ConverterInterface
|
||||
['name' => $value, 'iban' => null, 'openingBalance' => 0, 'user' => $this->user->id, 'accountType' => 'asset', 'virtualBalance' => 0,
|
||||
'active' => true]
|
||||
);
|
||||
|
||||
if (is_null($account->id)) {
|
||||
$this->setCertainty(0);
|
||||
Log::info('Could not store new asset account by name', $account->getErrors()->toArray());
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
$this->setCertainty(100);
|
||||
|
||||
Log::debug('Created new asset account ', ['name' => $account->name, 'id' => $account->id]);
|
||||
|
@@ -32,7 +32,7 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface
|
||||
public function convert($value)
|
||||
{
|
||||
$value = trim($value);
|
||||
Log::debug('Going to convert using AssetAccountName', ['value' => $value]);
|
||||
Log::debug('Going to convert using AssetAccountNumber', ['value' => $value]);
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
return new Account;
|
||||
@@ -77,6 +77,14 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface
|
||||
'accountType' => 'asset',
|
||||
'virtualBalance' => 0, 'accountNumber' => $value, 'active' => true]
|
||||
);
|
||||
|
||||
if (is_null($account->id)) {
|
||||
$this->setCertainty(0);
|
||||
Log::notice('Could not store new asset account by account number', $account->getErrors()->toArray());
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $account;
|
||||
|
@@ -63,6 +63,7 @@ class BillId extends BasicConverter implements ConverterInterface
|
||||
}
|
||||
|
||||
// should not really happen. If the ID does not match FF, what is FF supposed to do?
|
||||
Log::info(sprintf('Could not find bill with ID %d. Will return NULL', $value));
|
||||
|
||||
$this->setCertainty(0);
|
||||
|
||||
|
@@ -76,6 +76,13 @@ class BillName extends BasicConverter implements ConverterInterface
|
||||
|
||||
]
|
||||
);
|
||||
if (is_null($bill->id)) {
|
||||
$this->setCertainty(0);
|
||||
Log::info('Could not store new bill by name', $bill->getErrors()->toArray());
|
||||
|
||||
return new Bill;
|
||||
}
|
||||
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $bill;
|
||||
|
@@ -63,6 +63,9 @@ class BudgetId extends BasicConverter implements ConverterInterface
|
||||
|
||||
// should not really happen. If the ID does not match FF, what is FF supposed to do?
|
||||
$this->setCertainty(0);
|
||||
|
||||
Log::info(sprintf('Could not find budget with ID %d. Will return NULL', $value));
|
||||
|
||||
return new Budget;
|
||||
|
||||
}
|
||||
|
@@ -62,6 +62,9 @@ class CategoryId extends BasicConverter implements ConverterInterface
|
||||
|
||||
// should not really happen. If the ID does not match FF, what is FF supposed to do?
|
||||
$this->setCertainty(0);
|
||||
|
||||
Log::info(sprintf('Could not find category with ID %d. Will return NULL', $value));
|
||||
|
||||
return new Category;
|
||||
|
||||
}
|
||||
|
@@ -61,6 +61,9 @@ class CurrencyId extends BasicConverter implements ConverterInterface
|
||||
}
|
||||
$this->setCertainty(0);
|
||||
// should not really happen. If the ID does not match FF, what is FF supposed to do?
|
||||
|
||||
Log::info(sprintf('Could not find category with ID %d. Will return NULL', $value));
|
||||
|
||||
return new TransactionCurrency;
|
||||
|
||||
}
|
||||
|
@@ -37,9 +37,10 @@ class Date extends BasicConverter implements ConverterInterface
|
||||
try {
|
||||
$date = Carbon::createFromFormat($this->config['date-format'], $value);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::critical($e->getMessage());
|
||||
Log::critical('Cannot convert this string using the given format.', ['value' => $value, 'format' => $this->config['date-format']]);
|
||||
throw new FireflyException(sprintf('Cannot convert "%s" to a valid date using format "%s".', $value, $this->config['date-format']));
|
||||
Log::notice($e->getMessage());
|
||||
Log::notice('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);
|
||||
|
@@ -56,7 +56,7 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface
|
||||
$account = $repository->findByIban($value, []);
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by IBAN', ['id' => $account->id]);
|
||||
Log::warning(
|
||||
Log::notice(
|
||||
'The match between IBAN and account is uncertain because the type of transactions may not have been determined.',
|
||||
['id' => $account->id, 'iban' => $value]
|
||||
);
|
||||
|
@@ -47,6 +47,7 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by ID', ['id' => $account->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
@@ -55,11 +56,12 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface
|
||||
$account = $repository->findByName($value, []);
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found opposing account by name', ['id' => $account->id]);
|
||||
Log::warning(
|
||||
Log::info(
|
||||
'The match between name and account is uncertain because the type of transactions may not have been determined.',
|
||||
['id' => $account->id, 'name' => $value]
|
||||
);
|
||||
$this->setCertainty(50);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
@@ -68,6 +70,11 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface
|
||||
'openingBalance' => 0,
|
||||
]
|
||||
);
|
||||
if (is_null($account->id)) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Account;
|
||||
}
|
||||
$this->setCertainty(100);
|
||||
|
||||
Log::debug('Created new opposing account ', ['name' => $account->name, 'id' => $account->id]);
|
||||
|
@@ -221,7 +221,7 @@ class ImportEntry
|
||||
|
||||
return;
|
||||
}
|
||||
Log::error(sprintf('Will not set %s based on certainty %d (current certainty is %d) or NULL id.', $field, $certainty, $this->certain[$field]));
|
||||
Log::info(sprintf('Will not set %s based on certainty %d (current certainty is %d) or NULL id.', $field, $certainty, $this->certain[$field]));
|
||||
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ class ImportEntry
|
||||
|
||||
return;
|
||||
}
|
||||
Log::error(sprintf('Will not set %s based on certainty %d (current certainty is %d).', $field, $certainty, $this->certain[$field]));
|
||||
Log::info(sprintf('Will not set %s based on certainty %d (current certainty is %d).', $field, $certainty, $this->certain[$field]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,7 +256,7 @@ class ImportEntry
|
||||
|
||||
return;
|
||||
}
|
||||
Log::error(sprintf('Will not set %s based on certainty %d (current certainty is %d) or NULL id.', $field, $certainty, $this->certain[$field]));
|
||||
Log::info(sprintf('Will not set %s based on certainty %d (current certainty is %d) or NULL id.', $field, $certainty, $this->certain[$field]));
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -57,9 +57,9 @@ class ImportStorage
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
foreach ($this->entries as $entry) {
|
||||
Log::debug('--- import store start ---');
|
||||
$this->storeSingle($entry);
|
||||
foreach ($this->entries as $index => $entry) {
|
||||
Log::debug(sprintf('--- import store start for row %d ---', $index));
|
||||
$this->storeSingle($index, $entry);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -80,19 +80,20 @@ class ImportStorage
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function storeSingle(ImportEntry $entry)
|
||||
private function storeSingle(int $index, ImportEntry $entry)
|
||||
{
|
||||
if ($entry->valid === false) {
|
||||
Log::error('Cannot import entry, because valid=false');
|
||||
Log::error(sprintf('Cannot import row %d, because valid=false', $index));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Log::debug('Going to store entry!');
|
||||
Log::debug(sprintf('Going to store row %d', $index));
|
||||
$billId = is_null($entry->fields['bill']) ? null : $entry->fields['bill']->id;
|
||||
$journalData = [
|
||||
'user_id' => $entry->user->id,
|
||||
@@ -108,7 +109,12 @@ class ImportStorage
|
||||
];
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = TransactionJournal::create($journalData);
|
||||
$amount = $this->makePositive($entry->fields['amount']);
|
||||
|
||||
foreach ($journal->getErrors()->all() as $err) {
|
||||
Log::error($err);
|
||||
}
|
||||
|
||||
$amount = $this->makePositive($entry->fields['amount']);
|
||||
|
||||
Log::debug('Created journal', ['id' => $journal->id]);
|
||||
|
||||
@@ -154,13 +160,30 @@ class ImportStorage
|
||||
|
||||
$one = Transaction::create($sourceData);
|
||||
$two = Transaction::create($destinationData);
|
||||
Log::debug('Created transaction 1', ['id' => $one->id, 'account' => $one->account_id,'account_name' => $source->name]);
|
||||
Log::debug('Created transaction 2', ['id' => $two->id, 'account' => $two->account_id,'account_name' => $destination->name]);
|
||||
Log::debug('Created transaction 1', ['id' => $one->id, 'account' => $one->account_id, 'account_name' => $source->name]);
|
||||
Log::debug('Created transaction 2', ['id' => $two->id, 'account' => $two->account_id, 'account_name' => $destination->name]);
|
||||
|
||||
$journal->completed = 1;
|
||||
$journal->save();
|
||||
|
||||
// now attach budget and so on.
|
||||
if (!is_null($entry->fields['budget']) && !is_null($entry->fields['budget']->id)) {
|
||||
$journal->budgets()->save($entry->fields['budget']);
|
||||
Log::debug('Attached budget', ['id' => $entry->fields['budget']->id, 'name' => $entry->fields['budget']->name]);
|
||||
$journal->save();
|
||||
}
|
||||
|
||||
if (!is_null($entry->fields['category']) && !is_null($entry->fields['category']->id)) {
|
||||
$journal->categories()->save($entry->fields['category']);
|
||||
Log::debug('Attached category', ['id' => $entry->fields['category']->id, 'name' => $entry->fields['category']->name]);
|
||||
$journal->save();
|
||||
}
|
||||
|
||||
if (!is_null($entry->fields['bill']) && !is_null($entry->fields['bill']->id)) {
|
||||
$journal->bill()->associate($entry->fields['bill']);
|
||||
Log::debug('Attached bill', ['id' => $entry->fields['bill']->id, 'name' => $entry->fields['bill']->name]);
|
||||
$journal->save();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -52,8 +52,8 @@ class ImportValidator
|
||||
{
|
||||
$newCollection = new Collection;
|
||||
/** @var ImportEntry $entry */
|
||||
foreach ($this->entries as $entry) {
|
||||
Log::debug('--- import validator start ---');
|
||||
foreach ($this->entries as $index => $entry) {
|
||||
Log::debug(sprintf('--- import validator start for row %d ---', $index));
|
||||
/*
|
||||
* X Adds the date (today) if no date is present.
|
||||
* X Determins the types of accounts involved (asset, expense, revenue).
|
||||
@@ -64,14 +64,12 @@ class ImportValidator
|
||||
$entry = $this->checkAmount($entry);
|
||||
$entry = $this->setDate($entry);
|
||||
$entry = $this->setAssetAccount($entry);
|
||||
Log::debug(sprintf('Opposing account is of type %s', $entry->fields['opposing-account']->accountType->type));
|
||||
$entry = $this->setOpposingAccount($entry);
|
||||
Log::debug(sprintf('Opposing account is of type %s', $entry->fields['opposing-account']->accountType->type));
|
||||
$entry = $this->cleanDescription($entry);
|
||||
$entry = $this->setTransactionType($entry);
|
||||
$entry = $this->setTransactionCurrency($entry);
|
||||
|
||||
$newCollection->push($entry);
|
||||
$newCollection->put($index, $entry);
|
||||
}
|
||||
|
||||
return $newCollection;
|
||||
@@ -118,6 +116,7 @@ class ImportValidator
|
||||
*/
|
||||
private function cleanDescription(ImportEntry $entry): ImportEntry
|
||||
{
|
||||
|
||||
if (!isset($entry->fields['description'])) {
|
||||
Log::debug('Set empty transaction description because field was not set.');
|
||||
$entry->fields['description'] = '(empty transaction description)';
|
||||
@@ -130,6 +129,7 @@ class ImportValidator
|
||||
|
||||
return $entry;
|
||||
}
|
||||
$entry->fields['description'] = trim($entry->fields['description']);
|
||||
|
||||
if (strlen($entry->fields['description']) == 0) {
|
||||
Log::debug('Set empty transaction description because field was empty.');
|
||||
@@ -137,8 +137,7 @@ class ImportValidator
|
||||
|
||||
return $entry;
|
||||
}
|
||||
Log::debug('Transaction description is OK.');
|
||||
$entry->fields['description'] = trim($entry->fields['description']);
|
||||
Log::debug('Transaction description is OK.', ['description' => $entry->fields['description']]);
|
||||
|
||||
return $entry;
|
||||
}
|
||||
@@ -246,7 +245,7 @@ class ImportValidator
|
||||
*/
|
||||
private function setDate(ImportEntry $entry): ImportEntry
|
||||
{
|
||||
if (is_null($entry->fields['date-transaction'])) {
|
||||
if (is_null($entry->fields['date-transaction']) || $entry->certain['date-transaction'] == 0) {
|
||||
// empty date field? find alternative.
|
||||
$alternatives = ['date-book', 'date-interest', 'date-process'];
|
||||
foreach ($alternatives as $alternative) {
|
||||
@@ -263,6 +262,9 @@ class ImportValidator
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
// confidence is zero?
|
||||
|
||||
Log::debug('Date-transaction is OK');
|
||||
|
||||
return $entry;
|
||||
|
@@ -51,11 +51,10 @@ class CsvImporter implements ImporterInterface
|
||||
Log::debug('----- import entry build start --');
|
||||
Log::debug(sprintf('Now going to import row %d.', $index));
|
||||
$importEntry = $this->importSingleRow($index, $row);
|
||||
$collection->push($importEntry);
|
||||
$collection->put($index, $importEntry);
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Collection contains %d entries', $collection->count()));
|
||||
Log::debug('This call should be intercepted somehow.');
|
||||
Log::debug(sprintf('Import collection contains %d entries', $collection->count()));
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ namespace FireflyIII\Import\Logging;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Monolog\Handler\AbstractProcessingHandler;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Class CommandHandler
|
||||
@@ -32,7 +33,9 @@ class CommandHandler extends AbstractProcessingHandler
|
||||
*/
|
||||
public function __construct(Command $command)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->command = $command;
|
||||
$this->changeLevel(env('LOG_LEVEL', 'debug'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,6 +47,39 @@ class CommandHandler extends AbstractProcessingHandler
|
||||
*/
|
||||
protected function write(array $record)
|
||||
{
|
||||
$this->command->line((string) trim($record['formatted']));
|
||||
$this->command->line((string)trim($record['formatted']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $level
|
||||
*/
|
||||
private function changeLevel(string $level)
|
||||
{
|
||||
switch ($level) {
|
||||
case 'debug':
|
||||
$this->setLevel(Logger::DEBUG);
|
||||
break;
|
||||
case 'info':
|
||||
$this->setLevel(Logger::INFO);
|
||||
break;
|
||||
case 'notice':
|
||||
$this->setLevel(Logger::NOTICE);
|
||||
break;
|
||||
case 'warning':
|
||||
$this->setLevel(Logger::WARNING);
|
||||
break;
|
||||
case 'error':
|
||||
$this->setLevel(Logger::ERROR);
|
||||
break;
|
||||
case 'critical':
|
||||
$this->setLevel(Logger::CRITICAL);
|
||||
break;
|
||||
case 'alert':
|
||||
$this->setLevel(Logger::ALERT);
|
||||
break;
|
||||
case 'emergency':
|
||||
$this->setLevel(Logger::EMERGENCY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user