diff --git a/app/Http/Controllers/AttachmentController.php b/app/Http/Controllers/AttachmentController.php index cd8de38752..8e1bba3a03 100644 --- a/app/Http/Controllers/AttachmentController.php +++ b/app/Http/Controllers/AttachmentController.php @@ -98,10 +98,14 @@ class AttachmentController extends Controller */ public function download(AttachmentRepositoryInterface $repository, Attachment $attachment) { + + if ($repository->exists($attachment)) { $content = $repository->getContent($attachment); $quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\')); + + /** @var LaravelResponse $response */ $response = response($content, 200); $response @@ -149,6 +153,7 @@ class AttachmentController extends Controller { $image = 'images/page_green.png'; + if ($attachment->mime == 'application/pdf') { $image = 'images/page_white_acrobat.png'; } diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 36fedaf8ae..2df3afcc36 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -51,25 +51,6 @@ class ImportController extends Controller } ); } - // - // /** - // * This is the last step before the import starts. - // * - // * @param ImportJob $job - // * - // * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View - // */ - // public function complete(ImportJob $job) - // { - // Log::debug('Now in complete()', ['job' => $job->key]); - // if (!$this->jobInCorrectStep($job, 'complete')) { - // return $this->redirectToCorrectStep($job); - // } - // $subTitle = trans('firefly.import_complete'); - // $subTitleIcon = 'fa-star'; - // - // return view('import.complete', compact('job', 'subTitle', 'subTitleIcon')); - // } /** * This is step 3. This repeats until the job is configured. @@ -107,9 +88,13 @@ class ImportController extends Controller { Log::debug('Now in download()', ['job' => $job->key]); $config = $job->configuration; + + // TODO this is CSV import specific: $config['column-roles-complete'] = false; $config['column-mapping-complete'] = false; + $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', '"\\')); @@ -129,26 +114,6 @@ class ImportController extends Controller } - // /** - // * @param ImportJob $job - // * - // * @return View - // */ - // public function finished(ImportJob $job) - // { - // if (!$this->jobInCorrectStep($job, 'finished')) { - // return $this->redirectToCorrectStep($job); - // } - // - // // if there is a tag (there might not be), we can link to it: - // $tagId = $job->extended_status['importTag'] ?? 0; - // - // $subTitle = trans('firefly.import_finished'); - // $subTitleIcon = 'fa-star'; - // - // return view('import.finished', compact('job', 'subTitle', 'subTitleIcon', 'tagId')); - // } - /** * This is step 1. Upload a file. * @@ -263,69 +228,6 @@ class ImportController extends Controller return redirect(route('import.configure', [$job->key])); } - // /** - // * This step 6. Depending on the importer, this will process the - // * settings given and store them. - // * - // * @param Request $request - // * @param ImportJob $job - // * - // * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - // * @throws FireflyException - // */ - // public function postSettings(Request $request, ImportJob $job) - // { - // Log::debug('Now in postSettings()', ['job' => $job->key]); - // if (!$this->jobInCorrectStep($job, 'store-settings')) { - // return $this->redirectToCorrectStep($job); - // } - // $importer = $this->makeImporter($job); - // $importer->storeSettings($request); - // - // // return redirect to settings (for more settings perhaps) - // return redirect(route('import.settings', [$job->key])); - // } - - // /** - // * Step 5. Depending on the importer, this will show the user settings to - // * fill in. - // * - // * @param ImportJobRepositoryInterface $repository - // * @param ImportJob $job - // * - // * @return View - // */ - // public function settings(ImportJobRepositoryInterface $repository, ImportJob $job) - // { - // Log::debug('Now in settings()', ['job' => $job->key]); - // if (!$this->jobInCorrectStep($job, 'settings')) { - // return $this->redirectToCorrectStep($job); - // } - // Log::debug('Continue in settings()'); - // $importer = $this->makeImporter($job); - // $subTitle = trans('firefly.settings_for_import'); - // $subTitleIcon = 'fa-wrench'; - // - // // now show settings screen to user. - // if ($importer->requireUserSettings()) { - // Log::debug('Job requires user config.'); - // $data = $importer->getDataForSettings(); - // $view = $importer->getViewForSettings(); - // - // return view($view, compact('data', 'job', 'subTitle', 'subTitleIcon')); - // } - // Log::debug('Job does NOT require user config.'); - // - // $repository->updateStatus($job, 'settings_complete'); - // - // // if no more settings, save job and continue to process thing. - // return redirect(route('import.complete', [$job->key])); - // - // // ask the importer for the requested action. - // // for example pick columns or map data. - // // depends of course on the data in the job. - // } - /** * @param ImportJob $job */ @@ -335,10 +237,8 @@ class ImportController extends Controller $type = $job->file_type; $class = config(sprintf('firefly.import_processors.%s', $type)); /** @var FileProcessorInterface $processor */ - $processor = new $class($job); - - echo 'x';exit; - + $processor = app($class); + $processor->setJob($job); set_time_limit(0); if ($job->status == 'configured') { $processor->run(); @@ -364,36 +264,6 @@ class ImportController extends Controller return view('import.status', compact('job', 'subTitle', 'subTitleIcon')); } - // /** - // * @param ImportJob $job - // * @param string $method - // * - // * @return bool - // */ - // private function jobInCorrectStep(ImportJob $job, string $method): bool - // { - // Log::debug('Now in jobInCorrectStep()', ['job' => $job->key, 'method' => $method]); - // switch ($method) { - // case 'configure': - // case 'process': - // return $job->status === 'import_status_never_started'; - // case 'settings': - // case 'store-settings': - // Log::debug(sprintf('Job %d with key %s has status %s', $job->id, $job->key, $job->status)); - // - // return $job->status === 'import_configuration_saved'; - // case 'finished': - // return $job->status === 'import_complete'; - // case 'complete': - // return $job->status === 'settings_complete'; - // case 'status': - // return ($job->status === 'settings_complete') || ($job->status === 'import_running'); - // } - // - // return false; // @codeCoverageIgnore - // - // } - /** * @param ImportJob $job * @@ -412,62 +282,4 @@ class ImportController extends Controller return $configurator; } - - // /** - // * @param ImportJob $job - // * - // * @return SetupInterface - // * @throws FireflyException - // */ - // private function makeImporter(ImportJob $job): SetupInterface - // { - // // create proper importer (depends on job) - // $type = strtolower($job->file_type); - // - // // validate type: - // $validTypes = array_keys(config('firefly.import_formats')); - // - // - // if (in_array($type, $validTypes)) { - // /** @var SetupInterface $importer */ - // $importer = app('FireflyIII\Import\Setup\\' . ucfirst($type) . 'Setup'); - // $importer->setJob($job); - // - // return $importer; - // } - // throw new FireflyException(sprintf('"%s" is not a valid file type', $type)); // @codeCoverageIgnore - // - // } - - // /** - // * @param ImportJob $job - // * - // * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - // * @throws FireflyException - // */ - // private function redirectToCorrectStep(ImportJob $job) - // { - // Log::debug('Now in redirectToCorrectStep()', ['job' => $job->key]); - // switch ($job->status) { - // case 'import_status_never_started': - // Log::debug('Will redirect to configure()'); - // - // return redirect(route('import.configure', [$job->key])); - // case 'import_configuration_saved': - // Log::debug('Will redirect to settings()'); - // - // return redirect(route('import.settings', [$job->key])); - // case 'settings_complete': - // Log::debug('Will redirect to complete()'); - // - // return redirect(route('import.complete', [$job->key])); - // case 'import_complete': - // Log::debug('Will redirect to finished()'); - // - // return redirect(route('import.finished', [$job->key])); - // } - // - // throw new FireflyException('Cannot redirect for job state ' . $job->status); // @codeCoverageIgnore - // - // } } diff --git a/app/Import/Configurator/CsvConfigurator.php b/app/Import/Configurator/CsvConfigurator.php index c0ab0d6f27..4933a8afca 100644 --- a/app/Import/Configurator/CsvConfigurator.php +++ b/app/Import/Configurator/CsvConfigurator.php @@ -14,6 +14,9 @@ namespace FireflyIII\Import\Configurator; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; +use FireflyIII\Support\Import\Configuration\Csv\Initial; +use FireflyIII\Support\Import\Configuration\Csv\Map; +use FireflyIII\Support\Import\Configuration\Csv\Roles; use Log; /** @@ -118,13 +121,13 @@ class CsvConfigurator implements ConfiguratorInterface $class = false; switch (true) { case(!$this->job->configuration['initial-config-complete']): - $class = 'FireflyIII\\Support\\Import\\Configuration\\Csv\\Initial'; + $class = Initial::class; break; case (!$this->job->configuration['column-roles-complete']): - $class = 'FireflyIII\\Support\\Import\\Configuration\\Csv\\Roles'; + $class = Roles::class; break; case (!$this->job->configuration['column-mapping-complete']): - $class = 'FireflyIII\\Support\\Import\\Configuration\\Csv\\Map'; + $class = Map::class; break; default: break; diff --git a/app/Import/FileProcessor/CsvProcessor.php b/app/Import/FileProcessor/CsvProcessor.php index b874d89823..27161a0999 100644 --- a/app/Import/FileProcessor/CsvProcessor.php +++ b/app/Import/FileProcessor/CsvProcessor.php @@ -39,12 +39,9 @@ class CsvProcessor implements FileProcessorInterface /** * FileProcessorInterface constructor. - * - * @param ImportJob $job */ - public function __construct(ImportJob $job) + public function __construct() { - $this->job = $job; $this->objects = new Collection; $this->validSpecifics = array_keys(config('csv.import_specifics')); $this->validConverters = array_keys(config('csv.import_roles')); @@ -55,10 +52,7 @@ class CsvProcessor implements FileProcessorInterface */ public function getObjects(): Collection { - - // TODO: Implement getObjects() method. - throw new NotImplementedException; - + return $this->objects; } /** @@ -70,11 +64,14 @@ class CsvProcessor implements FileProcessorInterface $this->job->status = 'running'; $this->job->save(); + Log::debug('Mapping config: ', $this->job->configuration['column-mapping-config']); + $entries = $this->getImportArray(); $count = 0; Log::notice('Building importable objects from CSV file.'); foreach ($entries as $index => $row) { - $this->objects->push($this->importRow($index, $row)); + $importObject = $this->importRow($index, $row); + $this->objects->push($importObject); /** * 1. Build import entry. * 2. Validate import entry. @@ -85,13 +82,22 @@ class CsvProcessor implements FileProcessorInterface $this->job->addStepsDone(1); $count++; } - Log::debug(sprintf('Done building importable objects from CSV file. Processed %d rows, created %d entries.', $count, $this->objects->count())); - - exit; return true; } + /** + * @param ImportJob $job + * + * @return FileProcessorInterface + */ + public function setJob(ImportJob $job): FileProcessorInterface + { + $this->job = $job; + + return $this; + } + /** * @param int $index * @param string $value @@ -152,14 +158,9 @@ class CsvProcessor implements FileProcessorInterface $annotated = $this->annotateValue($rowIndex, $value); Log::debug('Annotated value: ', $annotated); $object->setValue($annotated); - - //$result = $this->importValue($rowIndex, $value); - //$object->setValue($result['role'], $result['certainty'], $result['value']); } - - return new ImportObject(); - + return $object; } /** diff --git a/app/Import/FileProcessor/FileProcessorInterface.php b/app/Import/FileProcessor/FileProcessorInterface.php index 6a90f36fff..5dfccd4dd7 100644 --- a/app/Import/FileProcessor/FileProcessorInterface.php +++ b/app/Import/FileProcessor/FileProcessorInterface.php @@ -21,12 +21,12 @@ use Illuminate\Support\Collection; */ interface FileProcessorInterface { + + /** - * FileProcessorInterface constructor. - * - * @param ImportJob $job + * @return Collection */ - public function __construct(ImportJob $job); + public function getObjects(): Collection; /** * @return bool @@ -34,7 +34,9 @@ interface FileProcessorInterface public function run(): bool; /** - * @return Collection + * @param ImportJob $job + * + * @return FileProcessorInterface */ - public function getObjects(): Collection; + public function setJob(ImportJob $job): FileProcessorInterface; } \ No newline at end of file diff --git a/app/Import/Object/ImportAccount.php b/app/Import/Object/ImportAccount.php index 967adb619b..12ca9621a2 100644 --- a/app/Import/Object/ImportAccount.php +++ b/app/Import/Object/ImportAccount.php @@ -15,11 +15,49 @@ namespace FireflyIII\Import\Object; class ImportAccount { - /** @var array */ - private $accountIds = []; + /** @var array */ + private $accountId = []; - public function setAccountId(string $value) + /** @var array */ + private $accountIban = []; + /** @var array */ + private $accountName = []; + + /** @var array */ + private $accountNumber = []; + + /** + * @param array $accountNumber + */ + public function setAccountNumber(array $accountNumber) { - $this->accountIds[] = $value; + $this->accountNumber = $accountNumber; } + + /** + * @param array $accountName + */ + public function setAccountName(array $accountName) + { + $this->accountName = $accountName; + } + + + /** + * @param array $value + */ + public function setAccountId(array $value) + { + $this->accountId = $value; + } + + /** + * @param array $accountIban + */ + public function setAccountIban(array $accountIban) + { + $this->accountIban = $accountIban; + } + + } \ No newline at end of file diff --git a/app/Import/Object/ImportBill.php b/app/Import/Object/ImportBill.php new file mode 100644 index 0000000000..40c511e1d4 --- /dev/null +++ b/app/Import/Object/ImportBill.php @@ -0,0 +1,40 @@ +id = $id; + } + + /** + * @param array $name + */ + public function setName(array $name) + { + $this->name = $name; + } + + +} \ No newline at end of file diff --git a/app/Import/Object/ImportBudget.php b/app/Import/Object/ImportBudget.php new file mode 100644 index 0000000000..bebfda12cf --- /dev/null +++ b/app/Import/Object/ImportBudget.php @@ -0,0 +1,40 @@ +id = $id; + } + + /** + * @param array $name + */ + public function setName(array $name) + { + $this->name = $name; + } + + +} \ No newline at end of file diff --git a/app/Import/Object/ImportCategory.php b/app/Import/Object/ImportCategory.php new file mode 100644 index 0000000000..c59b457724 --- /dev/null +++ b/app/Import/Object/ImportCategory.php @@ -0,0 +1,40 @@ +id = $id; + } + + /** + * @param array $name + */ + public function setName(array $name) + { + $this->name = $name; + } + + +} \ No newline at end of file diff --git a/app/Import/Object/ImportCurrency.php b/app/Import/Object/ImportCurrency.php new file mode 100644 index 0000000000..ab228249fc --- /dev/null +++ b/app/Import/Object/ImportCurrency.php @@ -0,0 +1,55 @@ +code = $code; + } + + /** + * @param array $symbol + */ + public function setSymbol(array $symbol) + { + $this->symbol = $symbol; + } + + /** + * @param array $name + */ + public function setName(array $name) + { + $this->name = $name; + } + + /** + * @param array $id + */ + public function setId(array $id) + { + $this->id = $id; + } + + +} \ No newline at end of file diff --git a/app/Import/Object/ImportObject.php b/app/Import/Object/ImportObject.php index 2f9eb83c79..93f342e814 100644 --- a/app/Import/Object/ImportObject.php +++ b/app/Import/Object/ImportObject.php @@ -22,10 +22,20 @@ class ImportObject public $errors; /** @var ImportAccount */ private $asset; + /** @var ImportBill */ + private $bill; + /** @var ImportBudget */ + private $budget; + /** @var ImportCategory */ + private $category; + /** @var string */ + private $description; + private $externalId = ''; /** @var string */ private $hash; /** @var ImportAccount */ private $opposing; + private $tags = []; /** @var ImportTransaction */ private $transaction; /** @var User */ @@ -40,6 +50,9 @@ class ImportObject $this->transaction = new ImportTransaction; $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) @@ -57,6 +70,8 @@ class ImportObject /** * @param array $array + * + * @throws FireflyException */ public function setValue(array $array) { @@ -64,11 +79,83 @@ class ImportObject default: throw new FireflyException(sprintf('ImportObject cannot handle "%s" with value "%s".', $array['role'], $array['value'])); case 'account-id': - $this->asset->setAccountId($array['value']); + $this->asset->setAccountId($array); + break; + case 'amount': + $this->transaction->setAmount($array['value']); + break; + case 'account-iban': + $this->asset->setAccountIban($array); + break; + case 'account-name': + $this->asset->setAccountName($array); + break; + case 'account-number': + $this->asset->setAccountNumber($array); + break; + case 'bill-id': + $this->bill->setId($array); + break; + case 'bill-name': + $this->bill->setName($array); + break; + case 'budget-id': + $this->budget->setId($array); + break; + case 'budget-name': + $this->budget->setName($array); + break; + case 'category-id': + $this->category->setId($array); + break; + case 'category-name': + $this->category->setName($array); + break; + case 'currency-code': + $this->transaction->getCurrency()->setCode($array); + break; + case 'currency-id': + $this->transaction->getCurrency()->setId($array); + break; + case 'currency-name': + $this->transaction->getCurrency()->setName($array); + break; + case 'currency-symbol': + $this->transaction->getCurrency()->setSymbol($array); + break; + case 'date-transaction': + $this->transaction->setDate($array['value']); + break; + case 'description': + $this->description = $array['value']; + $this->transaction->setDescription($array['value']); + break; + case 'external-id': + $this->externalId = $array['value']; + break; + case '_ignore': + break; + case 'ing-debet-credit': + case 'rabo-debet-credit': + $this->transaction->addToModifier($array); + break; + case 'opposing-iban': + $this->opposing->setAccountIban($array); + break; + case 'opposing-name': + $this->opposing->setAccountName($array); + break; + case 'opposing-number': + $this->opposing->setAccountNumber($array); + break; + case 'opposing-id': + $this->opposing->setAccountId($array); + break; + case 'tags-comma': + case 'tags-space': + $this->tags[] = $array; break; } - //var_dump($array); - //exit; } } \ No newline at end of file diff --git a/app/Import/Object/ImportTransaction.php b/app/Import/Object/ImportTransaction.php index ccc875363d..c273acdedf 100644 --- a/app/Import/Object/ImportTransaction.php +++ b/app/Import/Object/ImportTransaction.php @@ -14,5 +14,77 @@ namespace FireflyIII\Import\Object; class ImportTransaction { + /** @var string */ + private $amount; + + /** @var ImportCurrency */ + private $currency; + + /** @var string */ + private $date; + + /** @var string */ + private $description; + private $modifiers = []; + /** @var bool */ + private $positive = true; + + public function __construct() + { + $this->currency = new ImportCurrency; + } + + public function addToModifier(array $modifier) + { + $this->modifiers[] = $modifier; + } + + /** + * @return ImportCurrency + */ + public function getCurrency(): ImportCurrency + { + return $this->currency; + } + + /** + * @param ImportCurrency $currency + */ + public function setCurrency(ImportCurrency $currency) + { + $this->currency = $currency; + } + + /** + * @param string $amount + */ + public function setAmount(string $amount) + { + $this->amount = $amount; + } + + /** + * @param string $date + */ + public function setDate(string $date) + { + $this->date = $date; + } + + /** + * @param string $description + */ + public function setDescription(string $description) + { + $this->description = $description; + } + + /** + * @param bool $positive + */ + public function setPositive(bool $positive) + { + $this->positive = $positive; + } } \ No newline at end of file diff --git a/app/Repositories/ImportJob/ImportJobRepository.php b/app/Repositories/ImportJob/ImportJobRepository.php index c1f597c346..74eeb508da 100644 --- a/app/Repositories/ImportJob/ImportJobRepository.php +++ b/app/Repositories/ImportJob/ImportJobRepository.php @@ -103,7 +103,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); // demo user's configuration upload is ignored completely. - if ($repository->hasRole($this->user, 'demo')) { + if (!$repository->hasRole($this->user, 'demo')) { Log::debug( 'Uploaded configuration file', ['name' => $file->getClientOriginalName(), 'size' => $file->getSize(), 'mime' => $file->getClientMimeType()] ); diff --git a/app/Support/Import/Configuration/Csv/Initial.php b/app/Support/Import/Configuration/Csv/Initial.php index 2dfe625b69..096d997f5e 100644 --- a/app/Support/Import/Configuration/Csv/Initial.php +++ b/app/Support/Import/Configuration/Csv/Initial.php @@ -101,6 +101,7 @@ class Initial implements ConfigurationInterface Log::debug('Found account.', ['id' => $account->id, 'name' => $account->name]); $config['import-account'] = $account->id; } + if (is_null($account->id)) { Log::error('Could not find anything for csv_import_account.', ['id' => $importId]); } diff --git a/config/firefly.php b/config/firefly.php index ff609a999a..d27ccc0773 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -24,7 +24,7 @@ return [ ], 'encryption' => (is_null(env('USE_ENCRYPTION')) || env('USE_ENCRYPTION') === true), 'version' => '4.5.0', - 'maxUploadSize' => 5242880, + 'maxUploadSize' => 15242880, 'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'], 'list_length' => 10, 'export_formats' => [