diff --git a/app/Helpers/Csv/Converter/AccountIban.php b/app/Helpers/Csv/Converter/AccountIban.php index 6aa7494c62..bbca8ac0ee 100644 --- a/app/Helpers/Csv/Converter/AccountIban.php +++ b/app/Helpers/Csv/Converter/AccountIban.php @@ -11,6 +11,7 @@ namespace FireflyIII\Helpers\Csv\Converter; use Auth; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; +use Log; /** * Class AccountIban @@ -36,9 +37,13 @@ class AccountIban extends BasicConverter implements ConverterInterface 'name' => $this->value, //'iban' => $this->value, 'user_id' => Auth::user()->id, - 'account_type_id' => $accountType->id + 'account_type_id' => $accountType->id, + 'active' => true, ] ); + if ($account->getErrors()->count() > 0) { + Log::error('Create or find asset account: ' . json_encode($account->getErrors()->all())); + } } return $account; diff --git a/app/Helpers/Csv/Converter/Description.php b/app/Helpers/Csv/Converter/Description.php new file mode 100644 index 0000000000..19bede19a0 --- /dev/null +++ b/app/Helpers/Csv/Converter/Description.php @@ -0,0 +1,21 @@ +data['description'] . ' ' . $this->value); + } +} \ No newline at end of file diff --git a/app/Helpers/Csv/Importer.php b/app/Helpers/Csv/Importer.php index 644daaebea..4d8ac5c1b4 100644 --- a/app/Helpers/Csv/Importer.php +++ b/app/Helpers/Csv/Importer.php @@ -3,10 +3,18 @@ namespace FireflyIII\Helpers\Csv; use App; +use Auth; use Carbon\Carbon; use Config; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Csv\Converter\ConverterInterface; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; +use Illuminate\Support\MessageBag; +use Log; /** * Class Importer @@ -18,13 +26,12 @@ class Importer /** @var Data */ protected $data; - + /** @var array */ + protected $errors; /** @var array */ protected $map; - /** @var array */ protected $mapped; - /** @var array */ protected $roles; @@ -48,22 +55,29 @@ class Importer $this->map = $this->data->getMap(); $this->roles = $this->data->getRoles(); $this->mapped = $this->data->getMapped(); - foreach ($this->data->getReader() as $row) { - $this->importRow($row); + foreach ($this->data->getReader() as $index => $row) { + $result = $this->importRow($row); + if (!($result === true)) { + $this->errors[$index] = $result; + Log::error('ImportRow: ' . $result); + } } + + return count($this->errors); } /** * @param $row * * @throws FireflyException + * @return string|bool */ protected function importRow($row) { /* * These fields are necessary to create a new transaction journal. Some are optional: */ - $data = $this->getFiller(); + $data = $this->getFiller(); foreach ($row as $index => $value) { $role = isset($this->roles[$index]) ? $this->roles[$index] : '_ignore'; $class = Config::get('csv.roles.' . $role . '.converter'); @@ -91,37 +105,19 @@ class Importer $data[$field] = $converter->convert(); // } - - // case 'description': - // $data['description'] .= ' ' . $value; - // break; - // case '_ignore': - // ignore! (duh) - // break; - // case 'account-iban': - // $data['asset-account'] = $this->findAssetAccount($index, $value); - // break; - // case 'currency-code': - // $data['currency'] = $this->findCurrency($index, $value, $role); - // break; - // case 'date-transaction': - // $data['date'] = $this->parseDate($value); - // break; - // case 'rabo-debet-credit': - // $data['amount-modifier'] = $this->parseRaboDebetCredit($value); - // break; - // default: - // throw new FireflyException('Cannot process row of type "' . $role . '".'); - // break; - - } - $data = $this->postProcess($data); - var_dump($data); + $data = $this->postProcess($data); + $result = $this->validateData($data); + if ($result === true) { + $result = $this->createTransactionJournal($data); + } else { + Log::error('Validator: ' . $result); + } + if ($result instanceof TransactionJournal) { + return true; + } - - - exit; + return 'Not a journal.'; } @@ -131,13 +127,16 @@ class Importer protected function getFiller() { return [ - 'description' => '', - 'asset-account' => null, - 'date' => null, - 'currency' => null, - 'amount' => null, - 'amount-modifier' => 1, - 'ignored' => null, + 'description' => '', + 'asset-account' => null, + 'opposing-account' => '', + 'opposing-account-object' => null, + 'date' => null, + 'currency' => null, + 'amount' => null, + 'amount-modifier' => 1, + 'ignored' => null, + 'date-rent' => null, ]; } @@ -149,12 +148,109 @@ class Importer */ protected function postProcess(array $data) { + bcscale(2); $data['description'] = trim($data['description']); + $data['amount'] = bcmul($data['amount'], $data['amount-modifier']); + if ($data['amount'] < 0) { + // create expense account: + $accountType = AccountType::where('type', 'Expense account')->first(); + } else { + // create revenue account: + $accountType = AccountType::where('type', 'Revenue account')->first(); + } + $data['opposing-account-object'] = Account::firstOrCreateEncrypted( + [ + 'user_id' => Auth::user()->id, + 'name' => ucwords($data['opposing-account']), + 'account_type_id' => $accountType->id, + 'active' => 1, + ] + ); return $data; } + /** + * @param $data + * + * @return bool|string + */ + protected function validateData($data) + { + if (is_null($data['date']) && is_null($data['date-rent'])) { + return 'No date value for this row.'; + } + if (strlen($data['description']) == 0) { + return 'No valid description'; + } + if (is_null($data['opposing-account-object'])) { + return 'Opposing account is null'; + } + + return true; + } + + /** + * @param array $data + * + * @return static + */ + protected function createTransactionJournal(array $data) + { + bcscale(2); + $date = $data['date']; + if (is_null($data['date'])) { + $date = $data['date-rent']; + } + if ($data['amount'] < 0) { + $transactionType = TransactionType::where('type', 'Withdrawal')->first(); + } else { + $transactionType = TransactionType::where('type', 'Deposit')->first(); + } + $errors = new MessageBag; + $journal = TransactionJournal::create( + [ + 'user_id' => Auth::user()->id, + 'transaction_type_id' => $transactionType->id, + 'bill_id' => null, + 'transaction_currency_id' => $data['currency']->id, + 'description' => $data['description'], + 'completed' => 0, + 'date' => $date, + ] + ); + $errors = $journal->getErrors()->merge($errors); + if ($journal->getErrors()->count() == 0) { + // create both transactions: + $transaction = Transaction::create( + [ + 'transaction_journal_id' => $journal->id, + 'account_id' => $data['asset-account']->id, + 'amount' => $data['amount'] + ] + ); + $errors = $transaction->getErrors()->merge($errors); + + $transaction = Transaction::create( + [ + 'transaction_journal_id' => $journal->id, + 'account_id' => $data['opposing-account-object']->id, + 'amount' => bcmul($data['amount'], -1) + ] + ); + $errors = $transaction->getErrors()->merge($errors); + } + if($errors->count() == 0) { + $journal->completed = 1; + $journal->save(); + } + + return $journal; + + + } + /** * @param Data $data */ diff --git a/config/csv.php b/config/csv.php index dea1edb42f..78b4121dcb 100644 --- a/config/csv.php +++ b/config/csv.php @@ -34,8 +34,10 @@ return [ 'mappable' => true, ], 'description' => [ - 'name' => 'Description', - 'mappable' => false, + 'name' => 'Description', + 'mappable' => false, + 'converter' => 'Description', + 'field' => 'description', ], 'date-transaction' => [ 'name' => 'Date', @@ -44,8 +46,8 @@ return [ 'field' => 'date', ], 'date-rent' => [ - 'name' => 'Rent calculation date', - 'mappable' => false, + 'name' => 'Rent calculation date', + 'mappable' => false, 'converter' => 'Date', 'field' => 'date-rent', ], @@ -114,16 +116,22 @@ return [ 'field' => 'amount', ], 'sepa-ct-id' => [ - 'name' => 'SEPA Credit Transfer end-to-end ID', - 'mappable' => false, + 'name' => 'SEPA Credit Transfer end-to-end ID', + 'mappable' => false, + 'converter' => 'Description', + 'field' => 'description', ], 'sepa-ct-op' => [ - 'name' => 'SEPA Credit Transfer opposing account', - 'mappable' => false, + 'name' => 'SEPA Credit Transfer opposing account', + 'mappable' => false, + 'converter' => 'Description', + 'field' => 'description', ], 'sepa-db' => [ - 'name' => 'SEPA Direct Debet', - 'mappable' => false, + 'name' => 'SEPA Direct Debet', + 'mappable' => false, + 'converter' => 'Description', + 'field' => 'description', ], ] ]; \ No newline at end of file