From b9f110ac2b8ecb63a07b10380bb9dd9d7b7fab3b Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 17 Jun 2017 22:49:44 +0200 Subject: [PATCH] Refactor and rename some import things. --- app/Http/Controllers/ImportController.php | 27 +-- app/Import/FileProcessor/CsvProcessor.php | 120 ++++++----- app/Import/Object/ImportAccount.php | 189 ++++++++++++++++-- app/Import/Object/ImportCurrency.php | 176 +++++++++++++++- .../{ImportObject.php => ImportJournal.php} | 80 +++++--- app/Import/Object/ImportTransaction.php | 83 +++++++- app/Import/Routine/ImportRoutine.php | 74 +++++++ app/Import/Storage/ImportStorage.php | 75 +++++++ app/Models/ImportJob.php | 1 + app/Support/Steam.php | 16 +- 10 files changed, 707 insertions(+), 134 deletions(-) rename app/Import/Object/{ImportObject.php => ImportJournal.php} (66%) create mode 100644 app/Import/Routine/ImportRoutine.php create mode 100644 app/Import/Storage/ImportStorage.php diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 2df3afcc36..c230ee241f 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -17,6 +17,8 @@ use FireflyIII\Http\Requests\ImportUploadRequest; use FireflyIII\Import\Configurator\ConfiguratorInterface; use FireflyIII\Import\FileProcessor\FileProcessorInterface; use FireflyIII\Import\ImportProcedureInterface; +use FireflyIII\Import\Routine\ImportRoutine; +use FireflyIII\Import\Storage\ImportStorage; use FireflyIII\Models\ImportJob; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; @@ -26,6 +28,7 @@ use Illuminate\Http\Response as LaravelResponse; use Illuminate\Support\Collection; use Log; use Response; +use Validator; use View; /** @@ -87,7 +90,7 @@ class ImportController extends Controller public function download(ImportJob $job) { Log::debug('Now in download()', ['job' => $job->key]); - $config = $job->configuration; + $config = $job->configuration; // TODO this is CSV import specific: $config['column-roles-complete'] = false; @@ -95,8 +98,8 @@ class ImportController extends Controller $config['initial-config-complete'] = false; $config['delimiter'] = $config['delimiter'] === "\t" ? 'tab' : $config['delimiter']; - $result = json_encode($config, JSON_PRETTY_PRINT); - $name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\')); + $result = json_encode($config, JSON_PRETTY_PRINT); + $name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\')); /** @var LaravelResponse $response */ $response = response($result, 200); @@ -230,23 +233,15 @@ class ImportController extends Controller /** * @param ImportJob $job + * + * @return string */ public function start(ImportJob $job) { - $objects = new Collection(); - $type = $job->file_type; - $class = config(sprintf('firefly.import_processors.%s', $type)); - /** @var FileProcessorInterface $processor */ - $processor = app($class); - $processor->setJob($job); - set_time_limit(0); - if ($job->status == 'configured') { - $processor->run(); - $objects = $processor->getObjects(); - } - - // once done, use storage thing to actually store them: + $routine = new ImportRoutine($job); + $routine->run(); + return 'ok dan'; } /** diff --git a/app/Import/FileProcessor/CsvProcessor.php b/app/Import/FileProcessor/CsvProcessor.php index 27161a0999..64bda5b06c 100644 --- a/app/Import/FileProcessor/CsvProcessor.php +++ b/app/Import/FileProcessor/CsvProcessor.php @@ -13,16 +13,19 @@ namespace FireflyIII\Import\FileProcessor; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Import\Converter\ConverterInterface; -use FireflyIII\Import\Object\ImportObject; +use FireflyIII\Import\Object\ImportJournal; use FireflyIII\Import\Specifics\SpecificInterface; use FireflyIII\Models\ImportJob; +use FireflyIII\Models\TransactionJournalMeta; use Illuminate\Support\Collection; use Iterator; use League\Csv\Reader; use Log; /** - * Class CsvProcessor + * Class CsvProcessor, as the name suggests, goes over CSV file line by line and creates + * "ImportJournal" objects, which are used in another step to create new journals and transactions + * and what-not. * * @package FireflyIII\Import\FileProcessor */ @@ -56,22 +59,27 @@ class CsvProcessor implements FileProcessorInterface } /** + * Does the actual job: + * * @return bool */ public function run(): bool { - // update the job and say we started: - $this->job->status = 'running'; - $this->job->save(); - - Log::debug('Mapping config: ', $this->job->configuration['column-mapping-config']); + // TODO update the job and say we started: + //$this->job->status = 'running'; + //$this->job->save(); + Log::debug('Now in CsvProcessor run(). Job is now running...'); $entries = $this->getImportArray(); $count = 0; Log::notice('Building importable objects from CSV file.'); foreach ($entries as $index => $row) { - $importObject = $this->importRow($index, $row); - $this->objects->push($importObject); + // verify if not exists already: + if ($this->hashPresent($row)) { + Log::info(sprintf('Row #%d has already been imported.', $index)); + continue; + } + $this->objects->push($this->importRow($index, $row)); /** * 1. Build import entry. * 2. Validate import entry. @@ -99,6 +107,8 @@ class CsvProcessor implements FileProcessorInterface } /** + * Add meta data to the individual value and verify that it can be handled in a later stage. + * * @param int $index * @param string $value * @@ -116,6 +126,7 @@ class CsvProcessor implements FileProcessorInterface if (!in_array($role, $this->validConverters)) { throw new FireflyException(sprintf('"%s" is not a valid role.', $role)); } + $entry = [ 'role' => $role, 'value' => $value, @@ -136,79 +147,64 @@ class CsvProcessor implements FileProcessorInterface $reader->setDelimiter($config['delimiter']); $start = $config['has-headers'] ? 1 : 0; $results = $reader->setOffset($start)->fetch(); + Log::debug(sprintf('Created a CSV reader starting at offset %d', $start)); return $results; } /** - * @param int $index - * @param array $row + * Checks if the row has not been imported before. * - * @return ImportObject + * TODO for debugging, will always return false. + * + * @param array $array + * + * @noinspection PhpUnreachableStatementInspection + * @return bool */ - private function importRow(int $index, array $row): ImportObject + private function hashPresent(array $array): bool { - Log::debug(sprintf('Now at row %d', $index)); - $row = $this->specifics($row); - $object = new ImportObject(); - $object->setUser($this->job->user); - $object->setHash(hash('sha256', json_encode($row))); + $string = json_encode($array); + $hash = hash('sha256', json_encode($string)); + $json = json_encode($hash); + $entry = TransactionJournalMeta:: + leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') + ->where('data', $json) + ->where('name', 'importHash') + ->first(); - foreach ($row as $rowIndex => $value) { - $annotated = $this->annotateValue($rowIndex, $value); - Log::debug('Annotated value: ', $annotated); - $object->setValue($annotated); + return false; + if (!is_null($entry)) { + return true; } - return $object; + return false; + } /** - * @param int $index - * @param string $value + * Take a row, build import journal by annotating each value and storing it in the import journal. + * @param int $index + * @param array $row * - * @return array - * @throws FireflyException + * @return ImportJournal */ - private function importValue(int $index, string $value): array + private function importRow(int $index, array $row): ImportJournal { - $config = $this->job->configuration; - $role = $config['column-roles'][$index] ?? '_ignore'; - $doMap = $config['column-do-mapping'][$index] ?? false; + Log::debug(sprintf('Now at row %d', $index)); + $row = $this->specifics($row); + $journal = new ImportJournal; + $journal->setUser($this->job->user); + $journal->setHash(hash('sha256', json_encode($row))); - // throw error when not a valid converter. - if (!in_array($role, $this->validConverters)) { - throw new FireflyException(sprintf('"%s" is not a valid role.', $role)); + foreach ($row as $rowIndex => $value) { + $annotated = $this->annotateValue($rowIndex, $value); + Log::debug('Annotated value', $annotated); + $journal->setValue($annotated); } + Log::debug('ImportJournal complete, returning.'); - $converterClass = config(sprintf('csv.import_roles.%s.converter', $role)); - $mapping = $config['column-mapping-config'][$index] ?? []; - $className = sprintf('FireflyIII\\Import\\Converter\\%s', $converterClass); - - /** @var ConverterInterface $converter */ - $converter = app($className); - // set some useful values for the converter: - $converter->setMapping($mapping); - $converter->setDoMap($doMap); - $converter->setUser($this->job->user); - $converter->setConfig($config); - - // run the converter for this value: - $convertedValue = $converter->convert($value); - $certainty = $converter->getCertainty(); - - // log it. - Log::debug('Value ', ['index' => $index, 'value' => $value, 'role' => $role]); - - // store in import entry: - Log::debug('Going to import', ['role' => $role, 'value' => $value, 'certainty' => $certainty]); - - return [ - 'role' => $role, - 'certainty' => $certainty, - 'value' => $convertedValue, - ]; - + return $journal; } /** diff --git a/app/Import/Object/ImportAccount.php b/app/Import/Object/ImportAccount.php index 12ca9621a2..b2ac54c1b9 100644 --- a/app/Import/Object/ImportAccount.php +++ b/app/Import/Object/ImportAccount.php @@ -12,43 +12,119 @@ declare(strict_types=1); namespace FireflyIII\Import\Object; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\User; +use Log; + +/** + * Class ImportAccount + * + * @package FireflyIII\Import\Object + */ class ImportAccount { - /** @var array */ - private $accountId = []; - + /** @var Account */ + private $account; /** @var array */ private $accountIban = []; + /** @var array */ + private $accountId = []; /** @var array */ private $accountName = []; - /** @var array */ private $accountNumber = []; + /** @var AccountRepositoryInterface */ + private $repository; + /** @var User */ + private $user; /** - * @param array $accountNumber + * ImportAccount constructor. */ - public function setAccountNumber(array $accountNumber) + public function __construct() { - $this->accountNumber = $accountNumber; + $this->account = new Account; + $this->repository = app(AccountRepositoryInterface::class); + Log::debug('Created ImportAccount.'); + } /** - * @param array $accountName + * @return bool */ - public function setAccountName(array $accountName) + public function convertToExpense(): bool { - $this->accountName = $accountName; + if ($this->getAccount()->accountType->type === AccountType::EXPENSE) { + return true; + } + // maybe that an account of expense account type already exists? + $expenseType = AccountType::whereType(AccountType::EXPENSE)->first(); + $this->account->account_type_id = $expenseType->id; + $this->account->save(); + + return true; } + public function convertToRevenue(): bool + { + if ($this->getAccount()->accountType->type === AccountType::REVENUE) { + return true; + } + // maybe that an account of revenue account type already exists? + $revenueType = AccountType::whereType(AccountType::REVENUE)->first(); + $this->account->account_type_id = $revenueType->id; + $this->account->save(); + + return true; + } /** - * @param array $value + * @return Account */ - public function setAccountId(array $value) + public function createAccount(): Account { - $this->accountId = $value; + if (!is_null($this->account->id)) { + return $this->account; + } + Log::debug('In createAccount()'); + // check if any of them is mapped: + $mapped = $this->findMappedObject(); + + if (is_null($mapped->id)) { + // none are, create new object! + $data = [ + 'accountType' => 'import', + 'name' => $this->accountName['value'] ?? '(no name)', + 'iban' => $this->accountIban['value'] ?? null, + 'active' => true, + 'virtualBalance' => null, + ]; + if (!is_null($data['iban']) && $data['name'] === '(no name)') { + $data['name'] = $data['iban']; + } + Log::debug('Search for maps resulted in nothing, create new one based on', $data); + $account = $this->repository->store($data); + $this->account = $account; + Log::info('Made new account.', ['input' => $data, 'new' => $account->toArray()]); + + + return $account; + } + Log::debug('Mapped existing account.', ['new' => $mapped->toArray()]); + $this->account = $mapped; + + return $mapped; + } + + /** + * @return Account + */ + public function getAccount(): Account + { + return $this->account; } /** @@ -59,5 +135,92 @@ class ImportAccount $this->accountIban = $accountIban; } + /** + * @param array $value + */ + public function setAccountId(array $value) + { + $this->accountId = $value; + } + + /** + * @param array $accountName + */ + public function setAccountName(array $accountName) + { + $this->accountName = $accountName; + } + + /** + * @param array $accountNumber + */ + public function setAccountNumber(array $accountNumber) + { + $this->accountNumber = $accountNumber; + } + + /** + * @param User $user + */ + public function setUser(User $user) + { + $this->user = $user; + $this->repository->setUser($user); + } + + /** + * @return Account + */ + private function findMappedObject(): Account + { + Log::debug('In findMappedObject()'); + $fields = ['accountId', 'accountIban', 'accountNumber', 'accountName']; + foreach ($fields as $field) { + $array = $this->$field; + Log::debug(sprintf('Find mapped account based on field "%s" with value', $field), $array); + // check if a pre-mapped object exists. + $mapped = $this->getMappedObject($array); + if (!is_null($mapped->id)) { + Log::debug(sprintf('Found account #%d!', $mapped->id)); + + return $mapped; + } + + } + Log::debug('Found no account on mapped data or no map present.'); + + return new Account; + } + + /** + * @param array $array + * + * @return Account + */ + private function getMappedObject(array $array): Account + { + Log::debug('In getMappedObject()'); + if (count($array) === 0) { + Log::debug('Array is empty, nothing will come of this.'); + + return new Account; + } + + if (array_key_exists('mapped', $array) && is_null($array['mapped'])) { + Log::debug(sprintf('No map present for value "%s". Return NULL.', $array['value'])); + + return new Account; + } + + Log::debug('Finding a mapped object based on', $array); + + $search = intval($array['mapped']); + $account = $this->repository->find($search); + + Log::debug(sprintf('Found account! #%d ("%s"). Return it', $account->id, $account->name)); + + return $account; + } + } \ No newline at end of file diff --git a/app/Import/Object/ImportCurrency.php b/app/Import/Object/ImportCurrency.php index ab228249fc..4bb53c0c4d 100644 --- a/app/Import/Object/ImportCurrency.php +++ b/app/Import/Object/ImportCurrency.php @@ -12,12 +12,80 @@ declare(strict_types=1); namespace FireflyIII\Import\Object; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\User; +use Log; + class ImportCurrency { - private $code = []; + /** @var array */ + private $code = []; + /** @var TransactionCurrency */ + private $currency; + /** @var array */ + private $id = []; + /** @var array */ + private $name = []; + /** @var CurrencyRepositoryInterface */ + private $repository; + /** @var array */ private $symbol = []; - private $name = []; - private $id = []; + /** @var User */ + private $user; + + /** + * ImportCurrency constructor. + */ + public function __construct() + { + $this->currency = new TransactionCurrency; + $this->repository = app(CurrencyRepositoryInterface::class); + } + + /** + * @return TransactionCurrency + */ + public function createCurrency(): TransactionCurrency + { + if (!is_null($this->currency->id)) { + return $this->currency; + } + Log::debug('In createCurrency()'); + // check if any of them is mapped: + $mapped = $this->findMappedObject(); + $searched = null; + + if (!is_null($mapped->id)) { + + Log::debug('Mapped existing currency.', ['new' => $mapped->toArray()]); + $this->currency = $mapped; + + return $mapped; + } + + $searched = $this->findExistingObject(); + if (!is_null($searched->id)) { + Log::debug('Found existing currency.', ['found' => $searched->toArray()]); + $this->currency = $searched; + + return $searched; + } + $data = [ + 'code' => $this->code['value'] ?? null, + 'symbol' => $this->symbol['value'] ?? null, + 'name' => $this->name['value'] ?? null, + 'decimal_places' => 2, + ]; + Log::debug('Search for maps resulted in nothing, create new one based on', $data); + $currency = $this->repository->store($data); + $this->currency = $currency; + Log::info('Made new currency.', ['input' => $data, 'new' => $currency->toArray()]); + + + return $currency; + + } /** * @param array $code @@ -28,11 +96,12 @@ class ImportCurrency } /** - * @param array $symbol + * @param array $id */ - public function setSymbol(array $symbol) + public function setId(array $id) { - $this->symbol = $symbol; + $id['value'] = intval($id['value']); + $this->id = $id; } /** @@ -44,11 +113,100 @@ class ImportCurrency } /** - * @param array $id + * @param array $symbol */ - public function setId(array $id) + public function setSymbol(array $symbol) { - $this->id = $id; + $this->symbol = $symbol; + } + + /** + * @param User $user + */ + public function setUser(User $user) + { + $this->user = $user; + $this->repository->setUser($user); + } + + /** + * @return TransactionCurrency + */ + private function findExistingObject(): TransactionCurrency + { + $search = [ + 'id' => 'find', + 'code' => 'findByCode', + 'symbol' => 'findBySymbol', + 'name' => 'findByName', + ]; + foreach ($search as $field => $function) { + $value = $this->$field['value'] ?? null; + if (!is_null($value)) { + Log::debug(sprintf('Searching for %s using function %s and value %s', $field, $function, $value)); + $currency = $this->repository->$function($value); + + if (!is_null($currency->id)) { + return $currency; + } + } + } + + return new TransactionCurrency(); + } + + /** + * @return TransactionCurrency + */ + private function findMappedObject(): TransactionCurrency + { + Log::debug('In findMappedObject()'); + $fields = ['id', 'code', 'name', 'symbol']; + foreach ($fields as $field) { + $array = $this->$field; + Log::debug(sprintf('Find mapped currency based on field "%s" with value', $field), $array); + // check if a pre-mapped object exists. + $mapped = $this->getMappedObject($array); + if (!is_null($mapped->id)) { + Log::debug(sprintf('Found currency #%d!', $mapped->id)); + + return $mapped; + } + + } + Log::debug('Found no currency on mapped data or no map present.'); + + return new TransactionCurrency; + } + + /** + * @param array $array + * + * @return TransactionCurrency + */ + private function getMappedObject(array $array): TransactionCurrency + { + Log::debug('In getMappedObject()'); + if (count($array) === 0) { + Log::debug('Array is empty, nothing will come of this.'); + + return new TransactionCurrency; + } + + if (array_key_exists('mapped', $array) && is_null($array['mapped'])) { + Log::debug(sprintf('No map present for value "%s". Return NULL.', $array['value'])); + + return new TransactionCurrency; + } + + Log::debug('Finding a mapped object based on', $array); + + $search = intval($array['mapped']); + $currency = $this->repository->find($search); + + Log::debug(sprintf('Found currency! #%d ("%s"). Return it', $currency->id, $currency->name)); + + return $currency; } diff --git a/app/Import/Object/ImportObject.php b/app/Import/Object/ImportJournal.php similarity index 66% rename from app/Import/Object/ImportObject.php rename to app/Import/Object/ImportJournal.php index 93f342e814..e83921f0ee 100644 --- a/app/Import/Object/ImportObject.php +++ b/app/Import/Object/ImportJournal.php @@ -1,6 +1,6 @@ errors = new Collection; - $this->transaction = new ImportTransaction; - $this->asset = new ImportAccount; - $this->opposing = new ImportAccount; - $this->bill = new ImportBill; - $this->category = new ImportCategory; - $this->budget = new ImportBudget; + $this->errors = new Collection; + $this->asset = new ImportAccount; + $this->opposing = new ImportAccount; + $this->bill = new ImportBill; + $this->category = new ImportCategory; + $this->budget = new ImportBudget; } - public function setHash(string $hash) + /** + * @param array $modifier + */ + public function addToModifier(array $modifier) { - $this->hash = $hash; + $this->modifiers[] = $modifier; + } + + /** + * @return TransactionJournal + * @throws FireflyException + */ + public function createTransactionJournal(): TransactionJournal + { + exit('does not work yet'); } /** @@ -66,6 +97,9 @@ class ImportObject public function setUser(User $user) { $this->user = $user; + // set user for related objects: + $this->asset->setUser($user); + $this->opposing->setUser($user); } /** @@ -77,12 +111,12 @@ class ImportObject { switch ($array['role']) { default: - throw new FireflyException(sprintf('ImportObject cannot handle "%s" with value "%s".', $array['role'], $array['value'])); + throw new FireflyException(sprintf('ImportJournal cannot handle "%s" with value "%s".', $array['role'], $array['value'])); case 'account-id': $this->asset->setAccountId($array); break; case 'amount': - $this->transaction->setAmount($array['value']); + $this->amount = $array['value']; break; case 'account-iban': $this->asset->setAccountIban($array); @@ -112,23 +146,22 @@ class ImportObject $this->category->setName($array); break; case 'currency-code': - $this->transaction->getCurrency()->setCode($array); + $this->currency->setCode($array); break; case 'currency-id': - $this->transaction->getCurrency()->setId($array); + $this->currency->setId($array); break; case 'currency-name': - $this->transaction->getCurrency()->setName($array); + $this->currency->setName($array); break; case 'currency-symbol': - $this->transaction->getCurrency()->setSymbol($array); + $this->currency->setSymbol($array); break; case 'date-transaction': - $this->transaction->setDate($array['value']); + $this->date = $array['value']; break; case 'description': $this->description = $array['value']; - $this->transaction->setDescription($array['value']); break; case 'external-id': $this->externalId = $array['value']; @@ -137,7 +170,7 @@ class ImportObject break; case 'ing-debet-credit': case 'rabo-debet-credit': - $this->transaction->addToModifier($array); + $this->addToModifier($array); break; case 'opposing-iban': $this->opposing->setAccountIban($array); @@ -157,5 +190,4 @@ class ImportObject break; } } - } \ No newline at end of file diff --git a/app/Import/Object/ImportTransaction.php b/app/Import/Object/ImportTransaction.php index c273acdedf..cbb6a453cd 100644 --- a/app/Import/Object/ImportTransaction.php +++ b/app/Import/Object/ImportTransaction.php @@ -12,6 +12,9 @@ declare(strict_types=1); namespace FireflyIII\Import\Object; +use FireflyIII\Import\Converter\ConverterInterface; +use Steam; + class ImportTransaction { /** @var string */ @@ -39,6 +42,39 @@ class ImportTransaction $this->modifiers[] = $modifier; } + /** + * @return string + */ + public function getAmount(): string + { + // use converter: + $this->amount = strval($this->parseAmount()); + + + // also apply modifiers: + $this->amount = Steam::positive($this->amount); + + // Can handle ING + foreach ($this->modifiers as $modifier) { + $class = sprintf('FireflyIII\Import\Converter\%s', config(sprintf('csv.import_roles.%s.converter', $modifier['role']))); + /** @var ConverterInterface $converter */ + $converter = app($class); + if ($converter->convert($modifier['value']) === -1) { + $this->amount = Steam::negative($this->amount); + } + } + + return $this->amount; + } + + /** + * @param string $amount + */ + public function setAmount(string $amount) + { + $this->amount = $amount; + } + /** * @return ImportCurrency */ @@ -55,14 +91,6 @@ class ImportTransaction $this->currency = $currency; } - /** - * @param string $amount - */ - public function setAmount(string $amount) - { - $this->amount = $amount; - } - /** * @param string $date */ @@ -87,4 +115,43 @@ class ImportTransaction $this->positive = $positive; } + /** + * Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. + * - Jamie Zawinski + * + * @return float + */ + private function parseAmount() + { + $value = $this->amount; + $len = strlen($value); + $decimalPosition = $len - 3; + $decimal = null; + + if (($len > 2 && $value{$decimalPosition} == '.') || ($len > 2 && strpos($value, '.') > $decimalPosition)) { + $decimal = '.'; + } + if ($len > 2 && $value{$decimalPosition} == ',') { + $decimal = ','; + } + + // if decimal is dot, replace all comma's and spaces with nothing. then parse as float (round to 4 pos) + if ($decimal === '.') { + $search = [',', ' ']; + $value = str_replace($search, '', $value); + } + if ($decimal === ',') { + $search = ['.', ' ']; + $value = str_replace($search, '', $value); + $value = str_replace(',', '.', $value); + } + if (is_null($decimal)) { + // replace all: + $search = ['.', ' ', ',']; + $value = str_replace($search, '', $value); + } + + return round(floatval($value), 12); + } + } \ No newline at end of file diff --git a/app/Import/Routine/ImportRoutine.php b/app/Import/Routine/ImportRoutine.php new file mode 100644 index 0000000000..b74eb338bf --- /dev/null +++ b/app/Import/Routine/ImportRoutine.php @@ -0,0 +1,74 @@ +job = $job; + } + + /** + * + */ + public function run(): bool + { + if ($this->job->status !== 'configured') { + Log::error(sprintf('Job %s is in state %s so it cannot be started.', $this->job->key, $this->job->status)); + + return false; + } + + Log::debug(sprintf('Start with import job %s', $this->job->key)); + $objects = new Collection; + $type = $this->job->file_type; + $class = config(sprintf('firefly.import_processors.%s', $type)); + /** @var FileProcessorInterface $processor */ + $processor = app($class); + $processor->setJob($this->job); + set_time_limit(0); + if ($this->job->status == 'configured') { + Log::debug('Job is configured, start with run()'); + $processor->run(); + $objects = $processor->getObjects(); + } + + $storage = new ImportStorage; + $storage->setDateFormat($this->job->configuration['date-format']); + $storage->setObjects($objects); + $storage->store(); + + // once done, use storage thing to actually store them: + Log::debug(sprintf('Returned %d valid objects from file processor', $objects->count())); + + Log::debug(sprintf('Done with import job %s', $this->job->key)); + + return true; + } +} \ No newline at end of file diff --git a/app/Import/Storage/ImportStorage.php b/app/Import/Storage/ImportStorage.php new file mode 100644 index 0000000000..6223c33643 --- /dev/null +++ b/app/Import/Storage/ImportStorage.php @@ -0,0 +1,75 @@ +objects = new Collection; + } + + /** + * @param string $dateFormat + */ + public function setDateFormat(string $dateFormat) + { + $this->dateFormat = $dateFormat; + } + + + /** + * @param Collection $objects + */ + public function setObjects(Collection $objects) + { + $this->objects = $objects; + } + + + /** + * Do storage of import objects + */ + public function store() + { + /** + * @var int $index + * @var ImportJournal $object + */ + foreach ($this->objects as $index => $object) { + Log::debug(sprintf('Going to store object #%d', $index)); + + die('Cannot actually store yet.'); + } + } + +} \ No newline at end of file diff --git a/app/Models/ImportJob.php b/app/Models/ImportJob.php index fb1ae18c15..1feb065e20 100644 --- a/app/Models/ImportJob.php +++ b/app/Models/ImportJob.php @@ -45,6 +45,7 @@ class ImportJob extends Model 'new', 'initialized', 'configured', + 'running', ]; /** diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 7294b07bde..6baac5685a 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -270,6 +270,20 @@ class Steam return $list; } + /** + * @param string $amount + * + * @return string + */ + public function negative(string $amount): string + { + if (bccomp($amount, '0') === 1) { + $amount = bcmul($amount, '-1'); + } + + return $amount; + } + /** * @param $string * @@ -305,8 +319,6 @@ class Steam } - // parse PHP size: - /** * @param string $amount *