mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Lots of new code to test the import routine.
Signed-off-by: James Cole <thegrumpydictator@gmail.com>
This commit is contained in:
@@ -36,6 +36,7 @@ class AssetAccountName extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
$this->setCertainty(0);
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
||||
@@ -49,6 +50,7 @@ class AssetAccountName extends BasicConverter implements ConverterInterface
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by ID', ['id' => $account->id]);
|
||||
$this->setCertainty(100);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
@@ -56,7 +58,7 @@ class AssetAccountName extends BasicConverter implements ConverterInterface
|
||||
// not mapped? Still try to find it first:
|
||||
$account = $repository->findByName($value, [AccountType::ASSET]);
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by name', ['id' => $account->id]);
|
||||
Log::debug('Found asset account by name', ['value' => $value, 'id' => $account->id]);
|
||||
|
||||
return $account;
|
||||
}
|
||||
@@ -68,6 +70,8 @@ class AssetAccountName extends BasicConverter implements ConverterInterface
|
||||
);
|
||||
$this->setCertainty(100);
|
||||
|
||||
Log::debug('Created new asset account ', ['name' => $account->name, 'id' => $account->id]);
|
||||
|
||||
return $account;
|
||||
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class BillName extends BasicConverter implements ConverterInterface
|
||||
'name' => $value,
|
||||
'match' => $value,
|
||||
'amount_min' => 1,
|
||||
'user_id' => $this->user->id,
|
||||
'user' => $this->user->id,
|
||||
'amount_max' => 10,
|
||||
'date' => date('Ymd'),
|
||||
'repeat_freq' => 'monthly',
|
||||
|
||||
@@ -64,7 +64,7 @@ class BudgetName extends BasicConverter implements ConverterInterface
|
||||
$budget = $repository->store(
|
||||
[
|
||||
'name' => $value,
|
||||
'user_id' => $this->user->id,
|
||||
'user' => $this->user->id,
|
||||
]
|
||||
);
|
||||
$this->setCertainty(100);
|
||||
|
||||
@@ -64,7 +64,7 @@ class CategoryName extends BasicConverter implements ConverterInterface
|
||||
$category = $repository->store(
|
||||
[
|
||||
'name' => $value,
|
||||
'user_id' => $this->user->id,
|
||||
'user' => $this->user->id,
|
||||
]
|
||||
);
|
||||
$this->setCertainty(100);
|
||||
|
||||
@@ -54,7 +54,7 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface
|
||||
// not mapped? Still try to find it first:
|
||||
$account = $repository->findByName($value, []);
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by name', ['id' => $account->id]);
|
||||
Log::debug('Found opposing account by name', ['id' => $account->id]);
|
||||
Log::warning(
|
||||
'The match between name and account is uncertain because the type of transactions may not have been determined.',
|
||||
['id' => $account->id, 'name' => $value]
|
||||
@@ -70,6 +70,8 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface
|
||||
);
|
||||
$this->setCertainty(100);
|
||||
|
||||
Log::debug('Created new opposing account ', ['name' => $account->name, 'id' => $account->id]);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ class ImportStorage
|
||||
public function store()
|
||||
{
|
||||
foreach ($this->entries as $entry) {
|
||||
Log::debug('--- import store start ---');
|
||||
$this->storeSingle($entry);
|
||||
}
|
||||
|
||||
@@ -80,9 +81,17 @@ class ImportStorage
|
||||
|
||||
/**
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function storeSingle(ImportEntry $entry)
|
||||
{
|
||||
if ($entry->valid === false) {
|
||||
Log::error('Cannot import entry, because valid=false');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Log::debug('Going to store entry!');
|
||||
$billId = is_null($entry->fields['bill']) ? null : $entry->fields['bill']->id;
|
||||
$journalData = [
|
||||
@@ -145,7 +154,8 @@ class ImportStorage
|
||||
|
||||
$one = Transaction::create($sourceData);
|
||||
$two = Transaction::create($destinationData);
|
||||
Log::debug('Created transactions', ['source' => $one->id,'destination' => $two->id]);
|
||||
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();
|
||||
@@ -153,6 +163,5 @@ class ImportStorage
|
||||
// now attach budget and so on.
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -50,8 +50,10 @@ class ImportValidator
|
||||
*/
|
||||
public function clean(): Collection
|
||||
{
|
||||
$newCollection = new Collection;
|
||||
/** @var ImportEntry $entry */
|
||||
foreach ($this->entries as $entry) {
|
||||
Log::debug('--- import validator start ---');
|
||||
/*
|
||||
* X Adds the date (today) if no date is present.
|
||||
* X Determins the types of accounts involved (asset, expense, revenue).
|
||||
@@ -59,15 +61,20 @@ class ImportValidator
|
||||
* - Determins the currency of the transaction.
|
||||
* X Adds a default description if there isn't one present.
|
||||
*/
|
||||
$this->checkAmount($entry);
|
||||
$this->setDate($entry);
|
||||
$this->setAssetAccount($entry);
|
||||
$this->setOpposingAccount($entry);
|
||||
$this->cleanDescription($entry);
|
||||
$this->setTransactionType($entry);
|
||||
$this->setTransactionCurrency($entry);
|
||||
$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);
|
||||
}
|
||||
return $this->entries;
|
||||
|
||||
return $newCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,42 +95,52 @@ class ImportValidator
|
||||
|
||||
/**
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @return ImportEntry
|
||||
*/
|
||||
private function checkAmount(ImportEntry $entry)
|
||||
private function checkAmount(ImportEntry $entry): ImportEntry
|
||||
{
|
||||
if ($entry->fields['amount'] == 0) {
|
||||
$entry->valid = false;
|
||||
Log::error('Amount of transaction is zero, cannot handle.');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
Log::debug('Amount is OK.');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @return ImportEntry
|
||||
*/
|
||||
private function cleanDescription(ImportEntry $entry)
|
||||
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)';
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
if (is_null($entry->fields['description'])) {
|
||||
Log::debug('Set empty transaction description because field was null.');
|
||||
$entry->fields['description'] = '(empty transaction description)';
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
|
||||
if (strlen($entry->fields['description']) == 0) {
|
||||
Log::debug('Set empty transaction description because field was empty.');
|
||||
$entry->fields['description'] = '(empty transaction description)';
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
Log::debug('Transaction description is OK.');
|
||||
$entry->fields['description'] = trim($entry->fields['description']);
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,6 +153,8 @@ class ImportValidator
|
||||
{
|
||||
$accountType = $account->accountType->type;
|
||||
if ($accountType === $type) {
|
||||
Log::debug(sprintf('Account %s already of type %s', $account->name, $type));
|
||||
|
||||
return $account;
|
||||
}
|
||||
// find it first by new type:
|
||||
@@ -144,7 +163,9 @@ class ImportValidator
|
||||
$result = $repository->findByName($account->name, [$type]);
|
||||
if (is_null($result->id)) {
|
||||
// can convert account:
|
||||
Log::debug(sprintf('No account named %s of type %s, will convert.', $account->name, $type));
|
||||
$result = $repository->updateAccountType($account, $type);
|
||||
|
||||
}
|
||||
|
||||
return $result;
|
||||
@@ -194,29 +215,36 @@ class ImportValidator
|
||||
|
||||
/**
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @return ImportEntry
|
||||
*/
|
||||
private function setAssetAccount(ImportEntry $entry)
|
||||
private function setAssetAccount(ImportEntry $entry): ImportEntry
|
||||
{
|
||||
if (is_null($entry->fields['asset-account'])) {
|
||||
if (!is_null($this->defaultImportAccount)) {
|
||||
Log::debug('Set asset account from default asset account');
|
||||
$entry->fields['asset-account'] = $this->defaultImportAccount;
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
// default import is null? should not happen. Entry cannot be imported.
|
||||
// set error message and block.
|
||||
$entry->valid = false;
|
||||
Log::error('Cannot import entry. Asset account is NULL and import account is also NULL.');
|
||||
|
||||
}
|
||||
Log::debug('Asset account is OK.');
|
||||
Log::debug('Asset account is OK.', ['id' => $entry->fields['asset-account']->id, 'name' => $entry->fields['asset-account']->name]);
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @return ImportEntry
|
||||
*/
|
||||
private function setDate(ImportEntry $entry)
|
||||
private function setDate(ImportEntry $entry): ImportEntry
|
||||
{
|
||||
if (is_null($entry->fields['date-transaction'])) {
|
||||
// empty date field? find alternative.
|
||||
@@ -226,24 +254,26 @@ class ImportValidator
|
||||
Log::debug(sprintf('Copied date-transaction from %s.', $alternative));
|
||||
$entry->fields['date-transaction'] = clone $entry->fields[$alternative];
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
// date is still null at this point
|
||||
Log::debug('Set date-transaction to today.');
|
||||
$entry->fields['date-transaction'] = new Carbon;
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
Log::debug('Date-transaction is OK');
|
||||
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @return ImportEntry
|
||||
*/
|
||||
private function setOpposingAccount(ImportEntry $entry)
|
||||
private function setOpposingAccount(ImportEntry $entry): ImportEntry
|
||||
{
|
||||
// empty opposing account. Create one based on amount.
|
||||
if (is_null($entry->fields['opposing-account'])) {
|
||||
@@ -253,12 +283,12 @@ class ImportValidator
|
||||
Log::debug('Created fallback expense account');
|
||||
$entry->fields['opposing-account'] = $this->fallbackExpenseAccount();
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
Log::debug('Created fallback revenue account');
|
||||
$entry->fields['opposing-account'] = $this->fallbackRevenueAccount();
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
|
||||
// opposing is of type "import". Convert to correct type (by amount):
|
||||
@@ -268,14 +298,14 @@ class ImportValidator
|
||||
$entry->fields['opposing-account'] = $account;
|
||||
Log::debug('Converted import account to expense account');
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
if ($type == AccountType::IMPORT && $entry->fields['amount'] > 0) {
|
||||
$account = $this->convertAccount($entry->fields['opposing-account'], AccountType::REVENUE);
|
||||
$entry->fields['opposing-account'] = $account;
|
||||
Log::debug('Converted import account to revenue account');
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
// amount < 0, but opposing is revenue
|
||||
if ($type == AccountType::REVENUE && $entry->fields['amount'] < 0) {
|
||||
@@ -283,7 +313,7 @@ class ImportValidator
|
||||
$entry->fields['opposing-account'] = $account;
|
||||
Log::debug('Converted revenue account to expense account');
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
|
||||
// amount > 0, but opposing is expense
|
||||
@@ -292,45 +322,65 @@ class ImportValidator
|
||||
$entry->fields['opposing-account'] = $account;
|
||||
Log::debug('Converted expense account to revenue account');
|
||||
|
||||
return;
|
||||
return $entry;
|
||||
}
|
||||
// account type is OK
|
||||
Log::debug('Opposing account is OK.');
|
||||
|
||||
return $entry;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @return ImportEntry
|
||||
*/
|
||||
private function setTransactionCurrency(ImportEntry $entry)
|
||||
private function setTransactionCurrency(ImportEntry $entry): ImportEntry
|
||||
{
|
||||
if (is_null($entry->fields['currency'])) {
|
||||
/** @var CurrencyRepositoryInterface $repository */
|
||||
$repository = app(CurrencyRepositoryInterface::class);
|
||||
$entry->fields['currency'] = $repository->findByCode(env('DEFAULT_CURRENCY', 'EUR'));
|
||||
Log::debug('Set currency to EUR');
|
||||
return;
|
||||
|
||||
return $entry;
|
||||
}
|
||||
Log::debug('Currency is OK');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportEntry $entry
|
||||
*
|
||||
* @return ImportEntry
|
||||
*/
|
||||
private function setTransactionType(ImportEntry $entry)
|
||||
private function setTransactionType(ImportEntry $entry): ImportEntry
|
||||
{
|
||||
Log::debug(sprintf('Opposing account is of type %s', $entry->fields['opposing-account']->accountType->type));
|
||||
$type = $entry->fields['opposing-account']->accountType->type;
|
||||
switch ($type) {
|
||||
case AccountType::EXPENSE:
|
||||
$entry->fields['transaction-type'] = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
|
||||
break;
|
||||
Log::debug('Transaction type is now withdrawal.');
|
||||
|
||||
return $entry;
|
||||
case AccountType::REVENUE:
|
||||
$entry->fields['transaction-type'] = TransactionType::whereType(TransactionType::DEPOSIT)->first();
|
||||
break;
|
||||
Log::debug('Transaction type is now deposit.');
|
||||
|
||||
return $entry;
|
||||
case AccountType::ASSET:
|
||||
$entry->fields['transaction-type'] = TransactionType::whereType(TransactionType::TRANSFER)->first();
|
||||
break;
|
||||
Log::debug('Transaction type is now transfer.');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
Log::error(sprintf('Opposing account is of type %s, cannot handle this.', $type));
|
||||
$entry->valid = false;
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ class CsvImporter implements ImporterInterface
|
||||
$collection = new Collection;
|
||||
foreach ($results as $index => $row) {
|
||||
if ($index >= $start) {
|
||||
Log::debug('----- import entry build start --');
|
||||
Log::debug(sprintf('Now going to import row %d.', $index));
|
||||
$importEntry = $this->importSingleRow($index, $row);
|
||||
$collection->push($importEntry);
|
||||
|
||||
Reference in New Issue
Block a user