Merge branch 'feature/new-csv-import' into develop

# Conflicts:
#	app/Helpers/Csv/Importer.php
This commit is contained in:
James Cole
2016-06-23 12:15:19 +02:00
75 changed files with 693 additions and 4065 deletions

View File

@@ -1,35 +0,0 @@
<?php
/**
* AccountId.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Account;
/**
* Class AccountId
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class AccountId extends BasicConverter implements ConverterInterface
{
/**
* @return Account
*/
public function convert(): Account
{
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
$var = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
$account = $crud->find($var);
return $account;
}
}

View File

@@ -1,32 +0,0 @@
<?php
/**
* Amount.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
/**
* Class Amount
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class Amount extends BasicConverter implements ConverterInterface
{
/**
* @return string
*/
public function convert(): string
{
if (is_numeric($this->value)) {
return strval($this->value);
}
return '0';
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* AmountComma.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
/**
* Class AmountComma
*
* Parses the input as the amount with a comma as decimal separator
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class AmountComma extends BasicConverter implements ConverterInterface
{
/**
* @return float|int
*/
public function convert(): string
{
$value = str_replace(',', '.', strval($this->value));
if (is_numeric($value)) {
return strval($value);
}
return '0';
}
}

View File

@@ -1,89 +0,0 @@
<?php
/**
* AssetAccountIban.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use Auth;
use Carbon\Carbon;
use FireflyIII\Crud\Account\AccountCrudInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
/**
* Class AssetAccountIban
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class AssetAccountIban extends BasicConverter implements ConverterInterface
{
/**
* @return Account
*/
public function convert(): Account
{
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
// is mapped? Then it's easy!
if (isset($this->mapped[$this->index][$this->value])) {
$account = $crud->find(intval($this->mapped[$this->index][$this->value]));
return $account;
}
if (strlen($this->value) > 0) {
$account = $this->searchOrCreate($crud);
return $account;
}
return new Account;
}
/**
* @param AccountCrudInterface $crud
*
* @return Account
*/
private function searchOrCreate(AccountCrudInterface $crud)
{
// find or create new account:
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
/** @var Account $entry */
foreach ($set as $entry) {
if ($entry->iban == $this->value) {
return $entry;
}
}
// create it if doesn't exist.
$accountData = [
'name' => $this->value,
'accountType' => 'asset',
'virtualBalance' => 0,
'virtualBalanceCurrency' => 1, // hard coded.
'active' => true,
'user' => Auth::user()->id,
'iban' => $this->value,
'accountNumber' => $this->value,
'accountRole' => null,
'openingBalance' => 0,
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => 1, // hard coded.
];
$account = $crud->store($accountData);
return $account;
}
}

View File

@@ -1,65 +0,0 @@
<?php
/**
* AssetAccountName.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use Auth;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
/**
* Class AssetAccountName
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class AssetAccountName extends BasicConverter implements ConverterInterface
{
/**
* @return Account|null
*/
public function convert(): Account
{
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
if (isset($this->mapped[$this->index][$this->value])) {
$account = $crud->find(intval($this->mapped[$this->index][$this->value]));
return $account;
}
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
/** @var Account $entry */
foreach ($set as $entry) {
if ($entry->name == $this->value) {
return $entry;
}
}
$accountData = [
'name' => $this->value,
'accountType' => 'asset',
'virtualBalance' => 0,
'virtualBalanceCurrency' => 1, // hard coded.
'active' => true,
'user' => Auth::user()->id,
'iban' => null,
'accountNumber' => $this->value,
'accountRole' => null,
'openingBalance' => 0,
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => 1, // hard coded.
];
$account = $crud->store($accountData);
return $account;
}
}

View File

@@ -1,77 +0,0 @@
<?php
/**
* AssetAccountNumber.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use Auth;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
/**
* Class AssetAccountNumber
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class AssetAccountNumber extends BasicConverter implements ConverterInterface
{
/**
* @return Account|null
*/
public function convert(): Account
{
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
// is mapped? Then it's easy!
if (isset($this->mapped[$this->index][$this->value])) {
$account = $crud->find(intval($this->mapped[$this->index][$this->value]));
return $account;
}
// if not, search for it (or create it):
$value = $this->value ?? '';
if (strlen($value) > 0) {
// find or create new account:
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
/** @var Account $entry */
foreach ($set as $entry) {
$accountNumber = $entry->getMeta('accountNumber');
if ($accountNumber == $this->value) {
return $entry;
}
}
$accountData = [
'name' => $this->value,
'accountType' => 'asset',
'virtualBalance' => 0,
'virtualBalanceCurrency' => 1, // hard coded.
'active' => true,
'user' => Auth::user()->id,
'iban' => null,
'accountNumber' => $this->value,
'accountRole' => null,
'openingBalance' => 0,
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => 1, // hard coded.
];
$account = $crud->store($accountData);
return $account;
}
return null; // is this accepted?
}
}

View File

@@ -1,114 +0,0 @@
<?php
/**
* BasicConverter.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
/**
* Class BasicConverter
*
*
* @SuppressWarnings(PHPMD.NumberOfChildren)
* @package FireflyIII\Helpers\Csv\Converter
*/
class BasicConverter
{
/** @var array */
protected $data;
/** @var string */
protected $field;
/** @var int */
protected $index;
/** @var array */
protected $mapped;
/** @var string */
protected $value;
/**
* @return array
*/
public function getData(): array
{
return $this->data;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
/**
* @return string
*/
public function getField(): string
{
return $this->field;
}
/**
* @param string $field
*/
public function setField(string $field)
{
$this->field = $field;
}
/**
* @return int
*/
public function getIndex(): int
{
return $this->index;
}
/**
* @param int $index
*/
public function setIndex(int $index)
{
$this->index = $index;
}
/**
* @return array
*/
public function getMapped(): array
{
return $this->mapped;
}
/**
* @param array $mapped
*/
public function setMapped(array $mapped)
{
$this->mapped = $mapped;
}
/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}
/**
* @param string $value
*/
public function setValue(string $value)
{
$this->value = $value;
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* BillId.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
/**
* Class BillId
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class BillId extends BasicConverter implements ConverterInterface
{
/**
* @return Bill
*/
public function convert(): Bill
{
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
$bill = $repository->find($value);
return $bill;
}
}

View File

@@ -1,47 +0,0 @@
<?php
/**
* BillName.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
/**
* Class BillName
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class BillName extends BasicConverter implements ConverterInterface
{
/**
* @return Bill
*/
public function convert(): Bill
{
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
// is mapped? Then it's easy!
if (isset($this->mapped[$this->index][$this->value])) {
return $repository->find($this->mapped[$this->index][$this->value]);
}
$bills = $repository->getBills();
/** @var Bill $bill */
foreach ($bills as $bill) {
if ($bill->name == $this->value) {
return $bill;
}
}
return new Bill;
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* BudgetId.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
/**
* Class BudgetId
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class BudgetId extends BasicConverter implements ConverterInterface
{
/**
* @return Budget
*/
public function convert(): Budget
{
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
$budget = $repository->find($value);
return $budget;
}
}

View File

@@ -1,44 +0,0 @@
<?php
/**
* BudgetName.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use Auth;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
/**
* Class BudgetName
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class BudgetName extends BasicConverter implements ConverterInterface
{
/**
* @return Budget
*/
public function convert(): Budget
{
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
// is mapped? Then it's easy!
if (isset($this->mapped[$this->index][$this->value])) {
$budget = $repository->find($this->mapped[$this->index][$this->value]);
return $budget;
}
$budget = $repository->store(['name' => $this->value, 'user' => Auth::user()->id]);
return $budget;
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* CategoryId.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
/**
* Class CategoryId
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class CategoryId extends BasicConverter implements ConverterInterface
{
/**
* @return Category
*/
public function convert(): Category
{
/** @var CategoryRepositoryInterface $repository */
$repository = app(CategoryRepositoryInterface::class);
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
$category = $repository->find($value);
return $category;
}
}

View File

@@ -1,49 +0,0 @@
<?php
/**
* CategoryName.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use Auth;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
/**
* Class CategoryName
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class CategoryName extends BasicConverter implements ConverterInterface
{
/**
* @return Category
*/
public function convert(): Category
{
/** @var CategoryRepositoryInterface $repository */
$repository = app(CategoryRepositoryInterface::class);
// is mapped? Then it's easy!
if (isset($this->mapped[$this->index][$this->value])) {
$category = $repository->find($this->mapped[$this->index][$this->value]);
return $category;
}
$data = [
'name' => $this->value,
'user' => Auth::user()->id,
];
$category = $repository->store($data);
return $category;
}
}

View File

@@ -1,52 +0,0 @@
<?php
/**
* ConverterInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
/**
* Interface ConverterInterface
*
* @package FireflyIII\Helpers\Csv\Converter
*/
interface ConverterInterface
{
/**
* @return mixed
*/
public function convert();
/**
* @param array $data
*/
public function setData(array $data);
/**
* @param string $field
*
*/
public function setField(string $field);
/**
* @param int $index
*/
public function setIndex(int $index);
/**
* @param array $mapped
*/
public function setMapped(array $mapped);
/**
* @param string $value
*/
public function setValue(string $value);
}

View File

@@ -1,43 +0,0 @@
<?php
/**
* CurrencyCode.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
/**
* Class CurrencyCode
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class CurrencyCode extends BasicConverter implements ConverterInterface
{
/**
* @return TransactionCurrency
*/
public function convert(): TransactionCurrency
{
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
if (isset($this->mapped[$this->index][$this->value])) {
$currency = $repository->find(intval($this->mapped[$this->index][$this->value]));
return $currency;
}
$currency = $repository->findByCode($this->value);
return $currency;
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* CurrencyId.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
/**
* Class CurrencyId
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class CurrencyId extends BasicConverter implements ConverterInterface
{
/**
* @return TransactionCurrency
*/
public function convert(): TransactionCurrency
{
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
$currency = $repository->find($value);
return $currency;
}
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* CurrencyName.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
/**
* Class CurrencyName
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class CurrencyName extends BasicConverter implements ConverterInterface
{
/**
* @return TransactionCurrency
*/
public function convert(): TransactionCurrency
{
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
if (isset($this->mapped[$this->index][$this->value])) {
$currency = $repository->find($this->mapped[$this->index][$this->value]);
return $currency;
}
$currency = $repository->findByName($this->value);
return $currency;
}
}

View File

@@ -1,43 +0,0 @@
<?php
/**
* CurrencySymbol.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
/**
* Class CurrencySymbol
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class CurrencySymbol extends BasicConverter implements ConverterInterface
{
/**
* @return TransactionCurrency
*/
public function convert(): TransactionCurrency
{
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
if (isset($this->mapped[$this->index][$this->value])) {
$currency = $repository->find($this->mapped[$this->index][$this->value]);
return $currency;
}
$currency = $repository->findBySymbol($this->value);
return $currency;
}
}

View File

@@ -1,46 +0,0 @@
<?php
/**
* Date.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use InvalidArgumentException;
use Log;
/**
* Class Date
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class Date extends BasicConverter implements ConverterInterface
{
/**
* @return Carbon
* @throws FireflyException
*/
public function convert(): Carbon
{
$format = session('csv-date-format');
try {
$date = Carbon::createFromFormat($format, $this->value);
} catch (InvalidArgumentException $e) {
Log::error('Date conversion error: ' . $e->getMessage() . '. Value was "' . $this->value . '", format was "' . $format . '".');
$message = trans('firefly.csv_date_parse_error', ['format' => $format, 'value' => $this->value]);
throw new FireflyException($message);
}
return $date;
}
}

View File

@@ -1,31 +0,0 @@
<?php
/**
* Description.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
/**
* Class Description
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class Description extends BasicConverter implements ConverterInterface
{
/**
* @return string
*/
public function convert(): string
{
$description = $this->data['description'] ?? '';
return trim($description . ' ' . $this->value);
}
}

View File

@@ -1,34 +0,0 @@
<?php
/**
* INGDebetCredit.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
/**
* Class INGDebetCredit
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class INGDebetCredit extends BasicConverter implements ConverterInterface
{
/**
* @return int
*/
public function convert(): int
{
if ($this->value === 'Af') {
return -1;
}
return 1;
}
}

View File

@@ -1,28 +0,0 @@
<?php
/**
* Ignore.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
/**
* Class Amount
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class Ignore extends BasicConverter implements ConverterInterface
{
/**
* @return null
*/
public function convert()
{
return null;
}
}

View File

@@ -1,64 +0,0 @@
<?php
/**
* OpposingAccountIban.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Crud\Account\AccountCrudInterface;
use FireflyIII\Models\Account;
/**
* Class OpposingAccountIban
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class OpposingAccountIban extends BasicConverter implements ConverterInterface
{
/**
* If mapped, return account. Otherwise, only return the name itself.
*
* @return Account|string
*/
public function convert()
{
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
if (isset($this->mapped[$this->index][$this->value])) {
$account = $crud->find($this->mapped[$this->index][$this->value]);
return $account;
}
return $this->findAccount($crud);
}
/**
* @param AccountCrudInterface $crud
*
* @return Account|string
*/
private function findAccount(AccountCrudInterface $crud)
{
if (strlen($this->value) > 0) {
$set = $crud->getAccountsByType([]);
/** @var Account $account */
foreach ($set as $account) {
if ($account->iban == $this->value) {
return $account;
}
}
}
return $this->value;
}
}

View File

@@ -1,35 +0,0 @@
<?php
/**
* OpposingAccountId.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Account;
/**
* Class OpposingAccountId
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class OpposingAccountId extends BasicConverter implements ConverterInterface
{
/**
* @return Account
*/
public function convert(): Account
{
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
$value = isset($this->mapped[$this->index][$this->value]) ? $this->mapped[$this->index][$this->value] : $this->value;
$account = $crud->find($value);
return $account;
}
}

View File

@@ -1,41 +0,0 @@
<?php
/**
* OpposingAccountName.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Account;
/**
* Class OpposingAccountName
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class OpposingAccountName extends BasicConverter implements ConverterInterface
{
/**
* If mapped, return account. Otherwise, only return the name itself.
*
* @return Account|string
*/
public function convert()
{
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
if (isset($this->mapped[$this->index][$this->value])) {
$account = $crud->find($this->mapped[$this->index][$this->value]);
return $account;
}
return $this->value;
}
}

View File

@@ -1,34 +0,0 @@
<?php
/**
* RabobankDebetCredit.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
/**
* Class RabobankDebetCredit
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class RabobankDebetCredit extends BasicConverter implements ConverterInterface
{
/**
* @return int
*/
public function convert(): int
{
if ($this->value == 'D') {
return -1;
}
return 1;
}
}

View File

@@ -1,53 +0,0 @@
<?php
/**
* TagsComma.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Support\Collection;
/**
* Class TagsComma
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class TagsComma extends BasicConverter implements ConverterInterface
{
/**
* @return Collection
*/
public function convert(): Collection
{
/** @var TagRepositoryInterface $repository */
$repository = app(TagRepositoryInterface::class);
$tags = new Collection;
$strings = explode(',', $this->value);
foreach ($strings as $string) {
$data = [
'tag' => $string,
'date' => null,
'description' => null,
'latitude' => null,
'longitude' => null,
'zoomLevel' => null,
'tagMode' => 'nothing',
];
if (strlen($string) > 0) {
$tag = $repository->store($data); // should validate first?
$tags->push($tag);
}
}
$tags = $tags->merge($this->data['tags']);
return $tags;
}
}

View File

@@ -1,54 +0,0 @@
<?php
/**
* TagsSpace.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Support\Collection;
/**
* Class TagsSpace
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class TagsSpace extends BasicConverter implements ConverterInterface
{
/**
* @return Collection
*/
public function convert(): Collection
{
/** @var TagRepositoryInterface $repository */
$repository = app(TagRepositoryInterface::class);
$tags = new Collection;
$strings = explode(' ', $this->value);
foreach ($strings as $string) {
$data = [
'tag' => $string,
'date' => null,
'description' => null,
'latitude' => null,
'longitude' => null,
'zoomLevel' => null,
'tagMode' => 'nothing',
];
if (strlen($string) > 0) {
$tag = $repository->store($data); // should validate first?
$tags->push($tag);
}
}
$tags = $tags->merge($this->data['tags']);
return $tags;
}
}

View File

@@ -1,336 +0,0 @@
<?php
/**
* Data.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv;
use Crypt;
use League\Csv\Reader;
use Session;
use Storage;
/**
* Class Data
*
* @package FireflyIII\Helpers\Csv
*/
class Data
{
/** @var string */
protected $csvFileContent = '';
/** @var string */
protected $csvFileLocation = '';
/** @var string */
protected $dateFormat = '';
/** @var string */
protected $delimiter = '';
/** @var bool */
protected $hasHeaders;
/** @var int */
protected $importAccount = 0;
/** @var array */
protected $map = [];
/** @var array */
protected $mapped = [];
/** @var Reader */
protected $reader;
/** @var array */
protected $roles = [];
/** @var array */
protected $specifix = [];
/**
*/
public function __construct()
{
$this->sessionHasHeaders();
$this->sessionDateFormat();
$this->sessionCsvFileLocation();
$this->sessionMap();
$this->sessionRoles();
$this->sessionMapped();
$this->sessionSpecifix();
$this->sessionImportAccount();
$this->sessionDelimiter();
}
/**
*
* @return string
*/
public function getCsvFileContent(): string
{
return $this->csvFileContent ?? '';
}
/**
*
* @param string $csvFileContent
*/
public function setCsvFileContent(string $csvFileContent)
{
$this->csvFileContent = $csvFileContent;
}
/**
* FIXxME may return null
*
* @return string
*/
public function getCsvFileLocation(): string
{
return $this->csvFileLocation;
}
/**
*
* @param string $csvFileLocation
*/
public function setCsvFileLocation(string $csvFileLocation)
{
Session::put('csv-file', $csvFileLocation);
$this->csvFileLocation = $csvFileLocation;
}
/**
* FIXxME may return null
*
* @return string
*/
public function getDateFormat(): string
{
return $this->dateFormat;
}
/**
*
* @param string $dateFormat
*/
public function setDateFormat(string $dateFormat)
{
Session::put('csv-date-format', $dateFormat);
$this->dateFormat = $dateFormat;
}
/**
* FIXxME may return null
*
* @return string
*/
public function getDelimiter(): string
{
return $this->delimiter;
}
/**
*
* @param string $delimiter
*/
public function setDelimiter(string $delimiter)
{
Session::put('csv-delimiter', $delimiter);
$this->delimiter = $delimiter;
}
/**
*
* @return array
*/
public function getMap(): array
{
return $this->map;
}
/**
*
* @param array $map
*/
public function setMap(array $map)
{
Session::put('csv-map', $map);
$this->map = $map;
}
/**
*
* @return array
*/
public function getMapped(): array
{
return $this->mapped;
}
/**
*
* @param array $mapped
*/
public function setMapped(array $mapped)
{
Session::put('csv-mapped', $mapped);
$this->mapped = $mapped;
}
/**
*
* @return Reader
*/
public function getReader(): Reader
{
if (!is_null($this->csvFileContent) && strlen($this->csvFileContent) === 0) {
$this->loadCsvFile();
}
if (is_null($this->reader)) {
$this->reader = Reader::createFromString($this->getCsvFileContent());
$this->reader->setDelimiter($this->delimiter);
}
return $this->reader;
}
/**
*
* @return array
*/
public function getRoles(): array
{
return $this->roles;
}
/**
*
* @param array $roles
*/
public function setRoles(array $roles)
{
Session::put('csv-roles', $roles);
$this->roles = $roles;
}
/**
*
* @return array
*/
public function getSpecifix(): array
{
return is_array($this->specifix) ? $this->specifix : [];
}
/**
*
* @param array $specifix
*/
public function setSpecifix(array $specifix)
{
Session::put('csv-specifix', $specifix);
$this->specifix = $specifix;
}
/**
*
* @return bool
*/
public function hasHeaders(): bool
{
return $this->hasHeaders;
}
/**
*
* @param bool $hasHeaders
*/
public function setHasHeaders(bool $hasHeaders)
{
Session::put('csv-has-headers', $hasHeaders);
$this->hasHeaders = $hasHeaders;
}
/**
*
* @param int $importAccount
*/
public function setImportAccount(int $importAccount)
{
Session::put('csv-import-account', $importAccount);
$this->importAccount = $importAccount;
}
protected function loadCsvFile()
{
$file = $this->getCsvFileLocation();
$disk = Storage::disk('upload');
$content = $disk->get($file);
$contentDecrypted = Crypt::decrypt($content);
$this->setCsvFileContent($contentDecrypted);
}
protected function sessionCsvFileLocation()
{
if (Session::has('csv-file')) {
$this->csvFileLocation = (string)session('csv-file');
}
}
protected function sessionDateFormat()
{
if (Session::has('csv-date-format')) {
$this->dateFormat = (string)session('csv-date-format');
}
}
protected function sessionDelimiter()
{
if (Session::has('csv-delimiter')) {
$this->delimiter = session('csv-delimiter');
}
}
protected function sessionHasHeaders()
{
if (Session::has('csv-has-headers')) {
$this->hasHeaders = (bool)session('csv-has-headers');
}
}
protected function sessionImportAccount()
{
if (Session::has('csv-import-account')) {
$this->importAccount = intval(session('csv-import-account'));
}
}
protected function sessionMap()
{
if (Session::has('csv-map')) {
$this->map = (array)session('csv-map');
}
}
protected function sessionMapped()
{
if (Session::has('csv-mapped')) {
$this->mapped = (array)session('csv-mapped');
}
}
protected function sessionRoles()
{
if (Session::has('csv-roles')) {
$this->roles = (array)session('csv-roles');
}
}
protected function sessionSpecifix()
{
if (Session::has('csv-specifix')) {
$this->specifix = (array)session('csv-specifix');
}
}
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* AnyAccount.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Mapper;
use Auth;
use FireflyIII\Models\Account;
/**
* Class AnyAccount
*
* @package FireflyIII\Helpers\Csv\Mapper
*/
class AnyAccount implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
$result = Auth::user()->accounts()->with('accountType')->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
$list = [];
/** @var Account $account */
foreach ($result as $account) {
$list[$account->id] = $account->name . ' (' . $account->accountType->type . ')';
}
asort($list);
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
return $list;
}
}

View File

@@ -1,54 +0,0 @@
<?php
/**
* AssetAccount.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Mapper;
use Auth;
use FireflyIII\Models\Account;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Class AssetAccount
*
* @package FireflyIII\Helpers\Csv\Mapper
*/
class AssetAccount implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
$result = Auth::user()->accounts()->with(
['accountmeta' => function (HasMany $query) {
$query->where('name', 'accountRole');
}]
)->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
$list = [];
/** @var Account $account */
foreach ($result as $account) {
$name = $account->name;
$iban = $account->iban ?? '';
if (strlen($iban) > 0) {
$name .= ' (' . $account->iban . ')';
}
$list[$account->id] = $name;
}
asort($list);
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
return $list;
}
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* Bill.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Mapper;
use Auth;
use FireflyIII\Models\Bill as BillModel;
/**
* Class Bill
*
* @package FireflyIII\Helpers\Csv\Mapper
*/
class Bill implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
$result = Auth::user()->bills()->get(['bills.*']);
$list = [];
/** @var BillModel $bill */
foreach ($result as $bill) {
$list[$bill->id] = $bill->name . ' [' . $bill->match . ']';
}
asort($list);
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
return $list;
}
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* Budget.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Mapper;
use Auth;
use FireflyIII\Models\Budget as BudgetModel;
/**
* Class Budget
*
* @package FireflyIII\Helpers\Csv\Mapper
*/
class Budget implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
$result = Auth::user()->budgets()->get(['budgets.*']);
$list = [];
/** @var BudgetModel $budget */
foreach ($result as $budget) {
$list[$budget->id] = $budget->name;
}
asort($list);
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
return $list;
}
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* Category.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Mapper;
use Auth;
use FireflyIII\Models\Category as CategoryModel;
/**
* Class Category
*
* @package FireflyIII\Helpers\Csv\Mapper
*/
class Category implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
$result = Auth::user()->categories()->get(['categories.*']);
$list = [];
/** @var CategoryModel $category */
foreach ($result as $category) {
$list[$category->id] = $category->name;
}
asort($list);
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
return $list;
}
}

View File

@@ -1,24 +0,0 @@
<?php
/**
* MapperInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Mapper;
/**
* Interface MapperInterface
*
* @package FireflyIII\Helpers\Csv\Mapper
*/
interface MapperInterface
{
/**
* @return array
*/
public function getMap(): array;
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* Tag.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Mapper;
use Auth;
use FireflyIII\Models\Tag as TagModel;
/**
* Class Tag
*
* @package FireflyIII\Helpers\Csv\Mapper
*/
class Tag implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
$result = Auth::user()->budgets()->get(['tags.*']);
$list = [];
/** @var TagModel $tag */
foreach ($result as $tag) {
$list[$tag->id] = $tag->tag;
}
asort($list);
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
return $list;
}
}

View File

@@ -1,40 +0,0 @@
<?php
/**
* TransactionCurrency.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Mapper;
use FireflyIII\Models\TransactionCurrency as TC;
/**
* Class TransactionCurrency
*
* @package FireflyIII\Helpers\Csv\Mapper
*/
class TransactionCurrency implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
$currencies = TC::get();
$list = [];
foreach ($currencies as $currency) {
$list[$currency->id] = $currency->name . ' (' . $currency->code . ')';
}
asort($list);
$list = [0 => trans('firefly.csv_do_not_map')] + $list;
return $list;
}
}

View File

@@ -1,44 +0,0 @@
<?php
/**
* Amount.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\PostProcessing;
/**
* Class Amount
*
* @package FireflyIII\Helpers\Csv\PostProcessing
*/
class Amount implements PostProcessorInterface
{
/** @var array */
protected $data;
/**
* @return array
*/
public function process(): array
{
$amount = $this->data['amount'] ?? '0';
$modifier = strval($this->data['amount-modifier']);
$this->data['amount'] = bcmul($amount, $modifier);
return $this->data;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
}

View File

@@ -1,274 +0,0 @@
<?php
/**
* AssetAccount.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\PostProcessing;
use Auth;
use Carbon\Carbon;
use FireflyIII\Crud\Account\AccountCrudInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use Validator;
/**
* Class AssetAccount
*
* @package FireflyIII\Helpers\Csv\PostProcessing
*/
class AssetAccount implements PostProcessorInterface
{
/** @var array */
protected $data;
/**
* @return array
*/
public function process(): array
{
$result = $this->checkIdNameObject(); // has object in ID or Name?
if (!is_null($result)) {
return $result;
}
// no object? maybe asset-account-iban is a string and we can find the matching account.
$result = $this->checkIbanString();
if (!is_null($result)) {
return $result;
}
// no object still? maybe we can find the account by name.
$result = $this->checkNameString();
if (!is_null($result)) {
return $result;
}
// still nothing? Perhaps the account number can lead us to an account:
$result = $this->checkAccountNumberString();
if (!is_null($result)) {
return $result;
}
return null;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
/**
* @return array|null
*/
protected function checkAccountNumberString()
{
$accountNumber = $this->data['asset-account-number'] ?? null;
if ($accountNumber instanceof Account) { // fourth: try to find account based on name, if any.
$this->data['asset-account-object'] = $accountNumber;
return $this->data;
}
if (is_string($accountNumber)) { // it's an actual account number
$this->data['asset-account-object'] = $this->parseAccountNumberString();
return $this->data;
}
return null;
}
/**
* @return array|null
*/
protected function checkIbanString()
{
$iban = $this->data['asset-account-iban'] ?? '';
$rules = ['iban' => 'iban'];
$check = ['iban' => $iban];
$validator = Validator::make($check, $rules);
if (!$validator->fails()) {
$this->data['asset-account-object'] = $this->parseIbanString();
return $this->data;
}
return null;
}
/**
* @return array
*/
protected function checkIdNameObject()
{
$accountId = $this->data['asset-account-id'] ?? null;
$accountIban = $this->data['asset-account-iban'] ?? null;
$accountNumber = $this->data['asset-account-number'] ?? null;
if ($accountId instanceof Account) { // first priority. try to find the account based on ID, if any
$this->data['asset-account-object'] = $accountId;
return $this->data;
}
if ($accountIban instanceof Account) { // second: try to find the account based on IBAN, if any.
$this->data['asset-account-object'] = $accountIban;
return $this->data;
}
if ($accountNumber instanceof Account) { // second: try to find the account based on account number, if any.
$this->data['asset-account-object'] = $accountNumber;
return $this->data;
}
return null;
}
/**
* @return array|null
*/
protected function checkNameString()
{
$accountName = $this->data['asset-account-name'] ?? null;
if ($accountName instanceof Account) { // third: try to find account based on name, if any.
$this->data['asset-account-object'] = $accountName;
return $this->data;
}
if (is_string($accountName)) {
$this->data['asset-account-object'] = $this->parseNameString();
return $this->data;
}
return null;
}
/**
* @return Account|null
*/
protected function createAccount()
{
$accountType = $this->getAccountType();
$name = $this->data['asset-account-name'] ?? '';
$iban = $this->data['asset-account-iban'] ?? '';
// create if not exists: // See issue #180
$name = strlen($name) > 0 ? $name : $iban;
$account = Account::firstOrCreateEncrypted(
[
'user_id' => Auth::user()->id,
'account_type_id' => $accountType->id,
'name' => $name,
'iban' => $iban,
'active' => true,
]
);
return $account;
}
/**
*
* @return AccountType
*/
protected function getAccountType()
{
return AccountType::where('type', 'Asset account')->first();
}
/**
* @return Account|null
*/
protected function parseIbanString()
{
// create by name and/or iban.
$iban = $this->data['asset-account-iban'] ?? '';
$accounts = Auth::user()->accounts()->get();
foreach ($accounts as $entry) {
if ($iban !== '' && $entry->iban === $iban) {
return $entry;
}
}
$account = $this->createAccount();
return $account;
}
/**
* @return Account|null
*/
protected function parseNameString()
{
$accountType = $this->getAccountType();
$accounts = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get();
foreach ($accounts as $entry) {
if ($entry->name == $this->data['asset-account-name']) {
return $entry;
}
}
// create if not exists:
// See issue #180
$account = Account::firstOrCreateEncrypted(
[
'user_id' => Auth::user()->id,
'account_type_id' => $accountType->id,
'name' => $this->data['asset-account-name'],
'iban' => '',
'active' => true,
]
);
return $account;
}
/**
* @return Account|null
*/
private function parseAccountNumberString()
{
/** @var AccountCrudInterface $crud */
$crud = app(AccountCrudInterface::class);
$accountNumber = $this->data['asset-account-number'] ?? '';
$accountType = $this->getAccountType();
$accounts = Auth::user()->accounts()->with(['accountmeta'])->where('account_type_id', $accountType->id)->get();
/** @var Account $entry */
foreach ($accounts as $entry) {
$metaFieldValue = $entry->getMeta('accountNumber');
if ($metaFieldValue === $accountNumber && $metaFieldValue !== '') {
return $entry;
}
}
// create new if not exists and return that one:
$accountData = [
'name' => $accountNumber,
'accountType' => 'asset',
'virtualBalance' => 0,
'virtualBalanceCurrency' => 1, // hard coded.
'active' => true,
'user' => Auth::user()->id,
'iban' => null,
'accountNumber' => $accountNumber,
'accountRole' => null,
'openingBalance' => 0,
'openingBalanceDate' => new Carbon,
'openingBalanceCurrency' => 1, // hard coded.
];
$account = $crud->store($accountData);
return $account;
}
}

View File

@@ -1,45 +0,0 @@
<?php
/**
* Bill.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\PostProcessing;
/**
* Class Bill
*
* @package FireflyIII\Helpers\Csv\PostProcessing
*/
class Bill implements PostProcessorInterface
{
/** @var array */
protected $data;
/**
* @return array
*/
public function process(): array
{
// get bill id.
if (!is_null($this->data['bill']) && !is_null($this->data['bill']->id)) {
$this->data['bill-id'] = $this->data['bill']->id;
}
return $this->data;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
}

View File

@@ -1,49 +0,0 @@
<?php
/**
* Currency.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\PostProcessing;
use FireflyIII\Models\TransactionCurrency;
use Preferences;
/**
* Class Currency
*
* @package FireflyIII\Helpers\Csv\PostProcessing
*/
class Currency implements PostProcessorInterface
{
/** @var array */
protected $data;
/**
* @return array
*/
public function process(): array
{
// fix currency
if (is_null($this->data['currency'])) {
$currencyPreference = Preferences::get('currencyPreference', env('DEFAULT_CURRENCY', 'EUR'));
$this->data['currency'] = TransactionCurrency::whereCode($currencyPreference->data)->first();
}
return $this->data;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
}

View File

@@ -1,47 +0,0 @@
<?php
/**
* Description.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\PostProcessing;
/**
* Class Description
*
* @package FireflyIII\Helpers\Csv\PostProcessing
*/
class Description implements PostProcessorInterface
{
/** @var array */
protected $data;
/**
* @return array
*/
public function process(): array
{
$description = $this->data['description'] ?? '';
$this->data['description'] = trim($description);
if (strlen($this->data['description']) == 0) {
$this->data['description'] = trans('firefly.csv_empty_description');
}
return $this->data;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
}

View File

@@ -1,210 +0,0 @@
<?php
/**
* OpposingAccount.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\PostProcessing;
use Auth;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use Validator;
/**
* Class OpposingAccount
*
* @package FireflyIII\Helpers\Csv\PostProcessing
*/
class OpposingAccount implements PostProcessorInterface
{
/** @var array */
protected $data;
/**
* @return array
*/
public function process(): array
{
// three values:
// opposing-account-id, opposing-account-iban, opposing-account-name
$result = $this->checkIdNameObject();
if (!is_null($result)) {
return $result;
}
$result = $this->checkIbanString();
if (!is_null($result)) {
return $result;
}
$result = $this->checkNameString();
if (!is_null($result)) {
return $result;
}
return null;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
/**
* @return array|null
*/
protected function checkIbanString()
{
$rules = ['iban' => 'iban'];
$iban = $this->data['opposing-account-iban'];
$check = ['iban' => $iban];
$validator = Validator::make($check, $rules);
if (is_string($iban) && strlen($iban) > 0 && !$validator->fails()) {
$this->data['opposing-account-object'] = $this->parseIbanString();
return $this->data;
}
return null;
}
/**
* @return array
*/
protected function checkIdNameObject()
{
if ($this->data['opposing-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any
$this->data['opposing-account-object'] = $this->data['opposing-account-id'];
return $this->data;
}
if ($this->data['opposing-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any.
$this->data['opposing-account-object'] = $this->data['opposing-account-iban'];
return $this->data;
}
return null;
}
/**
* @return array|null
*/
protected function checkNameString()
{
if ($this->data['opposing-account-name'] instanceof Account) { // third: try to find account based on name, if any.
$this->data['opposing-account-object'] = $this->data['opposing-account-name'];
return $this->data;
}
if (is_string($this->data['opposing-account-name'])) {
$this->data['opposing-account-object'] = $this->parseNameString();
return $this->data;
}
return null;
}
/**
* @return Account|null
*/
protected function createAccount()
{
$accountType = $this->getAccountType();
// create if not exists:
$name = is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) > 0 ? $this->data['opposing-account-name']
: $this->data['opposing-account-iban'];
$account = Account::firstOrCreateEncrypted( // See issue #180
[
'user_id' => Auth::user()->id,
'account_type_id' => $accountType->id,
'name' => $name,
'iban' => $this->data['opposing-account-iban'],
'active' => true,
]
);
return $account;
}
/**
*
* @return AccountType
*/
protected function getAccountType()
{
// opposing account type:
if ($this->data['amount'] < 0) {
// create expense account:
return AccountType::where('type', 'Expense account')->first();
}
// create revenue account:
return AccountType::where('type', 'Revenue account')->first();
}
/**
* @return Account|null
*/
protected function parseIbanString()
{
// create by name and/or iban.
$accounts = Auth::user()->accounts()->get();
foreach ($accounts as $entry) {
if ($entry->iban == $this->data['opposing-account-iban']) {
return $entry;
}
}
$account = $this->createAccount();
return $account;
}
/**
* @return Account|null
*/
protected function parseNameString()
{
$accountType = $this->getAccountType();
$accounts = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get();
foreach ($accounts as $entry) {
if ($entry->name == $this->data['opposing-account-name']) {
return $entry;
}
}
// create if not exists:
$account = Account::firstOrCreateEncrypted( // See issue #180
[
'user_id' => Auth::user()->id,
'account_type_id' => $accountType->id,
'name' => $this->data['opposing-account-name'],
'iban' => '',
'active' => true,
]
);
return $account;
}
}

View File

@@ -1,31 +0,0 @@
<?php
/**
* PostProcessorInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\PostProcessing;
/**
* Interface PostProcessorInterface
*
* @package FireflyIII\Helpers\Csv\PostProcessing
*/
interface PostProcessorInterface
{
/**
* @return array
*/
public function process(): array;
/**
* @param array $data
*/
public function setData(array $data);
}

View File

@@ -1,226 +0,0 @@
<?php
/**
* AbnAmroDescription.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Specifix;
/**
* Parses the description from txt files for ABN AMRO bank accounts.
*
* Based on the logic as described in the following Gist:
* https://gist.github.com/vDorst/68d555a6a90f62fec004
*
* @package FireflyIII\Helpers\Csv\Specifix
*/
class AbnAmroDescription extends Specifix implements SpecifixInterface
{
/** @var array */
protected $data;
/** @var array */
protected $row;
/**
* AbnAmroDescription constructor.
*/
public function __construct()
{
$this->setProcessorType(self::POST_PROCESSOR);
}
/**
* @return array
*/
public function fix(): array
{
// Try to parse the description in known formats.
$parsed = $this->parseSepaDescription() || $this->parseTRTPDescription() || $this->parseGEABEADescription() || $this->parseABNAMRODescription();
// If the description could not be parsed, specify an unknown opposing
// account, as an opposing account is required
if (!$parsed) {
$this->data['opposing-account-name'] = trans('firefly.unknown');
}
return $this->data;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
/**
* @param array $row
*/
public function setRow(array $row)
{
$this->row = $row;
}
/**
* Parses the current description with costs from ABN AMRO itself
*
* @return bool true if the description is GEA/BEA-format, false otherwise
*/
protected function parseABNAMRODescription()
{
// See if the current description is formatted in ABN AMRO format
if (preg_match('/ABN AMRO.{24} (.*)/', $this->data['description'], $matches)) {
$this->data['opposing-account-name'] = 'ABN AMRO';
$this->data['description'] = $matches[1];
return true;
}
return false;
}
/**
* Parses the current description in GEA/BEA format
*
* @return bool true if the description is GEA/BEAformat, false otherwise
*/
protected function parseGEABEADescription()
{
// See if the current description is formatted in GEA/BEA format
if (preg_match('/([BG]EA) +(NR:[a-zA-Z:0-9]+) +([0-9.\/]+) +([^,]*)/', $this->data['description'], $matches)) {
// description and opposing account will be the same.
$this->data['opposing-account-name'] = $matches[4];
$this->data['description'] = $matches[4];
if ($matches[1] == 'GEA') {
$this->data['description'] = 'GEA ' . $matches[4];
}
return true;
}
return false;
}
/**
* Parses the current description in SEPA format
*
* @return bool true if the description is SEPA format, false otherwise
*/
protected function parseSepaDescription()
{
// See if the current description is formatted as a SEPA plain description
if (preg_match('/^SEPA(.{28})/', $this->data['description'], $matches)) {
$type = $matches[1];
$reference = '';
$name = '';
$newDescription = '';
// SEPA plain descriptions contain several key-value pairs, split by a colon
preg_match_all('/([A-Za-z]+(?=:\s)):\s([A-Za-z 0-9._#-]+(?=\s|$))/', $this->data['description'], $matches, PREG_SET_ORDER);
if (is_array($matches)) {
foreach ($matches as $match) {
$key = $match[1];
$value = trim($match[2]);
switch (strtoupper($key)) {
case 'OMSCHRIJVING':
$newDescription = $value;
break;
case 'NAAM':
$this->data['opposing-account-name'] = $value;
$name = $value;
break;
case 'KENMERK':
$reference = $value;
break;
case 'IBAN':
$this->data['opposing-account-iban'] = $value;
break;
default:
// Ignore the rest
}
}
}
// Set a new description for the current transaction. If none was given
// set the description to type, name and reference
$this->data['description'] = $newDescription;
if (strlen($newDescription) === 0) {
$this->data['description'] = sprintf('%s - %s (%s)', $type, $name, $reference);
}
return true;
}
return false;
}
/**
* Parses the current description in TRTP format
*
* @return bool true if the description is TRTP format, false otherwise
*/
protected function parseTRTPDescription()
{
// See if the current description is formatted in TRTP format
if (preg_match_all('!\/([A-Z]{3,4})\/([^/]*)!', $this->data['description'], $matches, PREG_SET_ORDER)) {
$type = '';
$name = '';
$reference = '';
$newDescription = '';
// Search for properties specified in the TRTP format. If no description
// is provided, use the type, name and reference as new description
if (is_array($matches)) {
foreach ($matches as $match) {
$key = $match[1];
$value = trim($match[2]);
switch (strtoupper($key)) {
case 'NAME':
$this->data['opposing-account-name'] = $name = $value;
break;
case 'REMI':
$newDescription = $value;
break;
case 'IBAN':
$this->data['opposing-account-iban'] = $value;
break;
case 'EREF':
$reference = $value;
break;
case 'TRTP':
$type = $value;
break;
default:
// Ignore the rest
}
}
// Set a new description for the current transaction. If none was given
// set the description to type, name and reference
$this->data['description'] = $newDescription;
if (strlen($newDescription) === 0) {
$this->data['description'] = sprintf('%s - %s (%s)', $type, $name, $reference);
}
}
return true;
}
return false;
}
}

View File

@@ -1,60 +0,0 @@
<?php
/**
* Dummy.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Specifix;
/**
* Class Dummy
*
* @package FireflyIII\Helpers\Csv\Specifix
*/
class Dummy extends Specifix implements SpecifixInterface
{
/** @var array */
protected $data;
/** @var array */
protected $row;
/**
* Dummy constructor.
*/
public function __construct()
{
$this->setProcessorType(self::POST_PROCESSOR);
}
/**
* @return array
*/
public function fix(): array
{
return $this->data;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
/**
* @param array $row
*/
public function setRow(array $row)
{
$this->row = $row;
}
}

View File

@@ -1,76 +0,0 @@
<?php
/**
* RabobankDescription.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Specifix;
/**
* Class RabobankDescription
*
* @package FireflyIII\Helpers\Csv\Specifix
*/
class RabobankDescription extends Specifix implements SpecifixInterface
{
/** @var array */
protected $data;
/** @var array */
protected $row;
/**
* RabobankDescription constructor.
*/
public function __construct()
{
$this->setProcessorType(self::POST_PROCESSOR);
}
/**
* @return array
*/
public function fix(): array
{
$this->rabobankFixEmptyOpposing();
return $this->data;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
/**
* @param array $row
*/
public function setRow(array $row)
{
$this->row = $row;
}
/**
* Fixes Rabobank specific thing.
*/
protected function rabobankFixEmptyOpposing()
{
if (is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) == 0) {
$this->data['opposing-account-name'] = $this->row[10];
$this->data['description'] = trim(str_replace($this->row[10], '', $this->data['description']));
}
}
}

View File

@@ -1,46 +0,0 @@
<?php
/**
* Specifix.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Specifix;
/**
* Class Specifix
*
* @package FireflyIII\Helpers\Csv\Specifix
*/
class Specifix
{
/** @var int */
protected $processorType;
/**
* @return int
*/
public function getProcessorType(): int
{
return $this->processorType;
}
/**
* @param int $processorType
*
* @return $this
*/
public function setProcessorType(int $processorType)
{
$this->processorType = $processorType;
return $this;
}
}

View File

@@ -1,49 +0,0 @@
<?php
/**
* SpecifixInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv\Specifix;
/**
* Interface SpecifixInterface
*
* @package FireflyIII\Helpers\Csv\Specifix
*/
interface SpecifixInterface
{
const PRE_PROCESSOR = 1;
const POST_PROCESSOR = 2;
/**
* Implement bank and locale related fixes.
*/
public function fix();
/**
* @return int
*/
public function getProcessorType(): int;
/**
* @param array $data
*/
public function setData(array $data);
/**
* @param int $processorType
*
* @return $this
*/
public function setProcessorType(int $processorType);
/**
* @param array $row
*/
public function setRow(array $row);
}

View File

@@ -1,202 +0,0 @@
<?php
/**
* Wizard.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv;
use Auth;
use Crypt;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Csv\Mapper\MapperInterface;
use League\Csv\Reader;
use Log;
use ReflectionException;
use Session;
use SplFileObject;
use Storage;
/**
* Class Wizard
*
* @package FireflyIII\Helpers\Csv
*/
class Wizard implements WizardInterface
{
/**
* @param Reader $reader
* @param array $map
* @param bool $hasHeaders
*
* @return array
*/
public function getMappableValues(Reader $reader, array $map, bool $hasHeaders): array
{
$values = [];
/*
* Loop over the CSV and collect mappable data:
*/
$keys = array_keys($map);
foreach ($reader as $index => $row) {
if ($this->useRow($hasHeaders, $index)) {
// collect all map values
foreach ($keys as $column) {
$values[$column][] = $row[$column];
}
}
}
/*
* Make each one unique.
*/
$values = $this->uniqueRecursive($values);
return $values;
}
/**
* @param array $roles
* @param array $map
*
* @return array
*/
public function processSelectedMapping(array $roles, array $map): array
{
$configRoles = config('csv.roles');
$maps = [];
$keys = array_keys($map);
foreach ($keys as $index) {
if (isset($roles[$index])) {
$name = $roles[$index];
if ($configRoles[$name]['mappable']) {
$maps[$index] = $name;
}
}
}
return $maps;
}
/**
* @param array $input
*
* @return array
*/
public function processSelectedRoles(array $input): array
{
$roles = [];
/*
* Store all rows for each column:
*/
if (is_array($input)) {
foreach ($input as $index => $role) {
if ($role != '_ignore') {
$roles[$index] = $role;
}
}
}
return $roles;
}
/**
* @param array $fields
*
* @return bool
*/
public function sessionHasValues(array $fields): bool
{
foreach ($fields as $field) {
if (!Session::has($field)) {
Log::error('Session is missing field: ' . $field);
return false;
}
}
return true;
}
/**
* @param array $map
*
* @return array
* @throws FireflyException
*/
public function showOptions(array $map): array
{
$options = [];
foreach ($map as $index => $columnRole) {
$mapper = config('csv.roles.' . $columnRole . '.mapper');
if (is_null($mapper)) {
throw new FireflyException('Cannot map field of type "' . $columnRole . '".');
}
$class = 'FireflyIII\Helpers\Csv\Mapper\\' . $mapper;
try {
/** @var MapperInterface $mapObject */
$mapObject = app($class);
} catch (ReflectionException $e) {
throw new FireflyException('Column "' . $columnRole . '" cannot be mapped because mapper class ' . $mapper . ' does not exist.');
}
$set = $mapObject->getMap();
$options[$index] = $set;
}
return $options;
}
/**
* @param string $path
*
* @return string
*/
public function storeCsvFile(string $path): string
{
$time = str_replace(' ', '-', microtime());
$fileName = 'csv-upload-' . Auth::user()->id . '-' . $time . '.csv.encrypted';
$disk = Storage::disk('upload');
$file = new SplFileObject($path, 'r');
$content = $file->fread($file->getSize());
$contentEncrypted = Crypt::encrypt($content);
$disk->put($fileName, $contentEncrypted);
return $fileName;
}
/**
* @param array $array
*
* @return array
*/
protected function uniqueRecursive(array $array)
{
foreach ($array as $column => $found) {
$array[$column] = array_unique($found);
}
return $array;
}
/**
* @param bool $hasHeaders
* @param int $index
*
* @return bool
*/
protected function useRow(bool $hasHeaders, int $index)
{
return ($hasHeaders && $index > 1) || !$hasHeaders;
}
}

View File

@@ -1,68 +0,0 @@
<?php
/**
* WizardInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Helpers\Csv;
use League\Csv\Reader;
/**
* Interface WizardInterface
*
* @package FireflyIII\Helpers\Csv
*/
interface WizardInterface
{
/**
* @param Reader $reader
* @param array $map
* @param bool $hasHeaders
*
* @return array
*/
public function getMappableValues(Reader $reader, array $map, bool $hasHeaders): array;
/**
* @param array $roles
* @param array $map
*
* @return array
*/
public function processSelectedMapping(array $roles, array $map): array;
/**
* @param array $input
*
* @return array
*/
public function processSelectedRoles(array $input): array;
/**
* @param array $fields
*
* @return bool
*/
public function sessionHasValues(array $fields): bool;
/**
* @param array $map
*
* @return array
*/
public function showOptions(array $map): array;
/**
* @param string $path
*
* @return string
*/
public function storeCsvFile(string $path): string;
}

View File

@@ -1,444 +0,0 @@
<?php
/**
* CsvController.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Http\Controllers;
use ExpandedForm;
use FireflyIII\Crud\Account\AccountCrudInterface;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Csv\Data;
use FireflyIII\Helpers\Csv\Importer;
use FireflyIII\Helpers\Csv\WizardInterface;
use FireflyIII\Models\AccountType;
use Illuminate\Http\Request;
use Input;
use Log;
use Preferences;
use Session;
use View;
/**
* Class CsvController
*
* @package FireflyIII\Http\Controllers
*/
class CsvController extends Controller
{
/** @var Data */
protected $data;
/** @var WizardInterface */
protected $wizard;
/**
*
*/
public function __construct()
{
parent::__construct();
View::share('title', trans('firefly.csv'));
View::share('mainTitleIcon', 'fa-file-text-o');
if (config('firefly.csv_import_enabled') === false) {
throw new FireflyException('CSV Import is not enabled.');
}
$this->wizard = app(WizardInterface::class);
$this->data = app(Data::class);
}
/**
* Define column roles and mapping.
*
* STEP THREE
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/
public function columnRoles()
{
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-import-account', 'csv-specifix', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Log::error('Could not recover upload.');
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
$subTitle = trans('firefly.csv_define_column_roles');
$firstRow = $this->data->getReader()->fetchOne();
$count = count($firstRow);
$headers = [];
$example = $this->data->getReader()->fetchOne(1);
$availableRoles = [];
$roles = $this->data->getRoles();
$map = $this->data->getMap();
for ($i = 1; $i <= $count; $i++) {
$headers[] = trans('firefly.csv_column') . ' #' . $i;
}
if ($this->data->hasHeaders()) {
$headers = $firstRow;
}
$keys = array_keys(config('csv.roles'));
foreach ($keys as $name) {
$availableRoles[$name] = trans('firefly.csv_column_' . $name);
}
asort($availableRoles);
return view('csv.column-roles', compact('availableRoles', 'map', 'roles', 'headers', 'example', 'subTitle'));
}
/**
* Optional download of mapping.
*
* STEP FOUR THREE-A
*
* @return \Illuminate\Http\RedirectResponse|string
*/
public function downloadConfig()
{
$fields = ['csv-date-format', 'csv-has-headers', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
$data = [
'date-format' => session('csv-date-format'),
'has-headers' => session('csv-has-headers'),
];
if (Session::has('csv-map')) {
$data['map'] = session('csv-map');
}
if (Session::has('csv-roles')) {
$data['roles'] = session('csv-roles');
}
if (Session::has('csv-mapped')) {
$data['mapped'] = session('csv-mapped');
}
if (Session::has('csv-specifix')) {
$data['specifix'] = session('csv-specifix');
}
$result = json_encode($data, JSON_PRETTY_PRINT);
$name = sprintf('"%s"', addcslashes('csv-configuration-' . date('Y-m-d') . '.json', '"\\'));
return response($result, 200)
->header('Content-disposition', 'attachment; filename=' . $name)
->header('Content-Type', 'application/json')
->header('Content-Description', 'File Transfer')
->header('Connection', 'Keep-Alive')
->header('Expires', '0')
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
->header('Pragma', 'public')
->header('Content-Length', strlen($result));
}
/**
* @return \Illuminate\View\View
*/
public function downloadConfigPage()
{
$fields = ['csv-date-format', 'csv-has-headers', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
$subTitle = trans('firefly.csv_download_config_title');
return view('csv.download-config', compact('subTitle'));
}
/**
* This method shows the initial upload form.
*
* STEP ONE
*
* @param AccountCrudInterface $crud
*
* @return \Illuminate\View\View
*/
public function index(AccountCrudInterface $crud)
{
$subTitle = trans('firefly.csv_import');
Session::forget('csv-date-format');
Session::forget('csv-has-headers');
Session::forget('csv-file');
Session::forget('csv-import-account');
Session::forget('csv-map');
Session::forget('csv-roles');
Session::forget('csv-mapped');
Session::forget('csv-specifix');
Session::forget('csv-delimiter');
// get list of supported specifix
$specifix = [];
foreach (config('csv.specifix') as $entry) {
$specifix[$entry] = trans('firefly.csv_specifix_' . $entry);
}
// get a list of delimiters:
$delimiters = [
',' => trans('form.csv_comma'),
';' => trans('form.csv_semicolon'),
'tab' => trans('form.csv_tab'),
];
// get a list of asset accounts:
$accounts = ExpandedForm::makeSelectList($crud->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]));
// can actually upload?
$uploadPossible = is_writable(storage_path('upload'));
$path = storage_path('upload');
return view('csv.index', compact('subTitle', 'uploadPossible', 'path', 'specifix', 'accounts', 'delimiters'));
}
/**
* Parse the file.
*
* STEP FOUR
*
* @return \Illuminate\Http\RedirectResponse
*/
public function initialParse()
{
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
// process given roles and mapping:
$inputMap = Input::get('map') ?? [];
$inputRoles = Input::get('role') ?? [];
$roles = $this->wizard->processSelectedRoles($inputRoles);
$maps = $this->wizard->processSelectedMapping($roles, $inputMap);
Session::put('csv-map', $maps);
Session::put('csv-roles', $roles);
// Go back when no roles defined:
if (count($roles) === 0) {
Session::flash('warning', strval(trans('firefly.must_select_roles')));
return redirect(route('csv.column-roles'));
}
/*
* Continue with map specification when necessary.
*/
if (count($maps) > 0) {
return redirect(route('csv.map'));
}
/*
* Or simply start processing.
*/
// proceed to download config
return redirect(route('csv.download-config-page'));
}
/**
*
* Map first if necessary,
*
* STEP FIVE.
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
* @throws FireflyException
*/
public function map()
{
// Make sure all fields we need are accounted for.
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
/*
* The "options" array contains all options the user has
* per column, where the key represents the column.
*
* For each key there is an array which in turn represents
* all the options available: grouped by ID.
*
* options[column index] = [
* field id => field identifier.
* ]
*/
$options = $this->wizard->showOptions($this->data->getMap());
// After these values are prepped, read the actual CSV file
$reader = $this->data->getReader();
$map = $this->data->getMap();
$hasHeaders = $this->data->hasHeaders();
$values = $this->wizard->getMappableValues($reader, $map, $hasHeaders);
$map = $this->data->getMap();
$mapped = $this->data->getMapped();
$subTitle = trans('firefly.csv_map_values');
return view('csv.map', compact('map', 'options', 'values', 'mapped', 'subTitle'));
}
/**
*
* Finally actually process the CSV file.
*
* STEP SEVEN
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/
public function process()
{
/*
* Make sure all fields we need are accounted for.
*/
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles', 'csv-mapped', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
/** @var Importer $importer */
$importer = app(Importer::class);
$importer->setData($this->data);
$importer->run();
$rows = $importer->getRows();
$errors = $importer->getErrors();
$imported = $importer->getImported();
$journals = $importer->getJournals();
Preferences::mark();
$subTitle = trans('firefly.csv_process_title');
return view('csv.process', compact('rows', 'errors', 'imported', 'subTitle', 'journals'));
}
/**
* Store the mapping the user has made. This is
*
* STEP SIX
*
*
* @return \Illuminate\Http\RedirectResponse
*/
public function saveMapping()
{
/*
* Make sure all fields we need are accounted for.
*/
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
// save mapping to session.
$mapped = [];
if (!is_array(Input::get('mapping'))) {
Session::flash('warning', strval(trans('firefly.invalid_mapping')));
return redirect(route('csv.map'));
}
foreach (Input::get('mapping') as $index => $data) {
$mapped[$index] = [];
foreach ($data as $value => $mapping) {
if (intval($mapping) !== 0) {
$mapped[$index][$value] = $mapping;
}
}
}
Session::put('csv-mapped', $mapped);
// proceed to process.
return redirect(route('csv.download-config-page'));
}
/**
*
* This method processes the file, puts it away somewhere safe
* and sends you onwards.
*
* STEP TWO
*
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function upload(Request $request)
{
if (!$request->hasFile('csv')) {
Session::flash('warning', strval(trans('firefly.no_file_uploaded')));
return redirect(route('csv.index'));
}
$path = $this->wizard->storeCsvFile($request->file('csv')->getRealPath());
$settings = [];
$settings['date-format'] = Input::get('date_format');
$settings['has-headers'] = intval(Input::get('has_headers')) === 1;
$settings['specifix'] = is_array(Input::get('specifix')) ? Input::get('specifix') : [];
$settings['import-account'] = intval(Input::get('csv_import_account'));
$settings['delimiter'] = Input::get('csv_delimiter', ',');
// A tab character cannot be used itself as option value in HTML
// See http://stackoverflow.com/questions/6064135/valid-characters-in-option-value
if ($settings['delimiter'] == 'tab') {
$settings['delimiter'] = "\t";
}
$settings['map'] = [];
$settings['mapped'] = [];
$settings['roles'] = [];
if ($request->hasFile('csv_config')) { // Process config file if present.
$size = $request->file('csv_config')->getSize();
$data = $request->file('csv_config')->openFile()->fread($size);
$json = json_decode($data, true);
if (is_array($json)) {
$settings = array_merge($settings, $json);
}
}
$this->data->setCsvFileLocation($path);
$this->data->setDateFormat($settings['date-format']);
$this->data->setHasHeaders($settings['has-headers']);
$this->data->setMap($settings['map']);
$this->data->setMapped($settings['mapped']);
$this->data->setRoles($settings['roles']);
$this->data->setSpecifix($settings['specifix']);
$this->data->setImportAccount($settings['import-account']);
$this->data->setDelimiter($settings['delimiter']);
return redirect(route('csv.column-roles'));
}
}

View File

@@ -2,7 +2,14 @@
namespace FireflyIII\Http\Controllers;
use Crypt;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\ImportUploadRequest;
use FireflyIII\Import\Importer\ImporterInterface;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use SplFileObject;
use Storage;
use View;
/**
@@ -22,6 +29,26 @@ class ImportController extends Controller
View::share('title', trans('firefly.import_data'));
}
/**
* @param ImportJob $job
*
* @return View
*/
public function configure(ImportJob $job)
{
// create proper importer (depends on job)
$type = $job->file_type;
/** @var ImporterInterface $importer */
$importer = app('FireflyIII\Import\Importer\\' . ucfirst($type) . 'Importer');
$importer->setJob($job);
$importer->configure();
$data = $importer->getConfigurationData();
return view('import.' . $type . '.configure', compact('data', 'job'));
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
@@ -38,4 +65,27 @@ class ImportController extends Controller
return view('import.index', compact('subTitle', 'subTitleIcon', 'importFileTypes', 'defaultImportType'));
}
/**
* @param ImportUploadRequest $request
* @param ImportJobRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function upload(ImportUploadRequest $request, ImportJobRepositoryInterface $repository)
{
// create import job:
$type = $request->get('import_file_type');
$job = $repository->create($type);
$upload = $request->files->get('import_file');
$newName = $job->key . '.upload';
$uploaded = new SplFileObject($upload->getRealPath());
$content = $uploaded->fread($uploaded->getSize());
$contentEncrypted = Crypt::encrypt($content);
$disk = Storage::disk('upload');
$disk->put($newName, $contentEncrypted);
return redirect(route('import.configure', [$job->key]));
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* ImportUploadRequest.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Http\Requests;
use Auth;
/**
* Class ImportUploadRequest
*
*
* @package FireflyIII\Http\Requests
*/
class ImportUploadRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return Auth::check();
}
/**
* @return array
*/
public function rules()
{
$types = array_keys(config('firefly.import_formats'));
return [
'import_file' => 'required|file',
'import_file_type' => 'required|in:' . join(',', $types),
];
}
}

View File

@@ -269,44 +269,6 @@ Breadcrumbs::register(
}
);
/**
* CSV CONTROLLER
*/
Breadcrumbs::register(
'csv.index', function (BreadCrumbGenerator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push(trans('firefly.csv_index_title'), route('csv.index'));
}
);
Breadcrumbs::register(
'csv.column-roles', function (BreadCrumbGenerator $breadcrumbs) {
$breadcrumbs->parent('csv.index');
$breadcrumbs->push(trans('firefly.csv_define_column_roles'), route('csv.column-roles'));
}
);
Breadcrumbs::register(
'csv.map', function (BreadCrumbGenerator $breadcrumbs) {
$breadcrumbs->parent('csv.index');
$breadcrumbs->push(trans('firefly.csv_map_values'), route('csv.map'));
}
);
Breadcrumbs::register(
'csv.download-config-page', function (BreadCrumbGenerator $breadcrumbs) {
$breadcrumbs->parent('csv.index');
$breadcrumbs->push(trans('firefly.csv_download_config'), route('csv.download-config-page'));
}
);
Breadcrumbs::register(
'csv.process', function (BreadCrumbGenerator $breadcrumbs) {
$breadcrumbs->parent('csv.index');
$breadcrumbs->push(trans('firefly.csv_process_title'), route('csv.process'));
}
);
/**
* CURRENCIES
*/

View File

@@ -157,21 +157,6 @@ Route::group(
Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']);
Route::post('/categories/destroy/{category}', ['uses' => 'CategoryController@destroy', 'as' => 'categories.destroy']);
/**
* CSV controller
*/
Route::get('/csv', ['uses' => 'CsvController@index', 'as' => 'csv.index']);
Route::post('/csv/upload', ['uses' => 'CsvController@upload', 'as' => 'csv.upload']);
Route::get('/csv/column_roles', ['uses' => 'CsvController@columnRoles', 'as' => 'csv.column-roles']);
Route::post('/csv/initial_parse', ['uses' => 'CsvController@initialParse', 'as' => 'csv.initial_parse']);
Route::get('/csv/map', ['uses' => 'CsvController@map', 'as' => 'csv.map']);
Route::get('/csv/download-config', ['uses' => 'CsvController@downloadConfig', 'as' => 'csv.download-config']);
Route::get('/csv/download', ['uses' => 'CsvController@downloadConfigPage', 'as' => 'csv.download-config-page']);
Route::post('/csv/save_mapping', ['uses' => 'CsvController@saveMapping', 'as' => 'csv.save_mapping']);
Route::get('/csv/process', ['uses' => 'CsvController@process', 'as' => 'csv.process']);
/**
* Currency Controller
*/
@@ -238,8 +223,9 @@ Route::group(
/**
* IMPORT CONTROLLER
*/
Route::get('/import', ['uses' => 'ImportController@index', 'as' => 'import.index']);
Route::post('/import/upload', ['uses' => 'ImportController@upload', 'as' => 'import.upload']);
Route::get('/import', ['uses' => 'ImportController@index','as' => 'import.index']);
Route::post('/import/upload', ['uses' => 'ImportController@upload','as' => 'import.upload']);
Route::get('/import/configure/{importJob}', ['uses' => 'ImportController@configure','as' => 'import.configure']);
/**
* Help Controller

View File

@@ -0,0 +1,83 @@
<?php
/**
* CsvImporter.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import\Importer;
use ExpandedForm;
use FireflyIII\Import\Role\Map;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\ImportJob;
/**
* Class CsvImporter
*
* @package FireflyIII\Import\Importer
*/
class CsvImporter implements ImporterInterface
{
/** @var ImportJob */
public $job;
/**
* @return bool
*/
public function configure(): bool
{
// need to do nothing, for now.
return true;
}
/**
* @return array
*/
public function getConfigurationData(): array
{
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface');
$accounts = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$delimiters = [
',' => trans('form.csv_comma'),
';' => trans('form.csv_semicolon'),
'tab' => trans('form.csv_tab'),
];
$data = [
'accounts' => ExpandedForm::makeSelectList($accounts),
'specifix' => [],
'delimiters' => $delimiters,
'upload_path' => storage_path('upload'),
'is_upload_possible' => is_writable(storage_path('upload')),
];
return $data;
}
/**
* Returns a Map thing used to allow the user to
* define roles for each entry.
*
* @return Map
*/
public function prepareRoles(): Map
{
return 'do not work';
exit;
}
/**
* @param ImportJob $job
*/
public function setJob(ImportJob $job)
{
$this->job = $job;
}
}

View File

@@ -0,0 +1,52 @@
<?php
/**
* ImporterInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import\Importer;
use FireflyIII\Import\Role\Map;
use FireflyIII\Models\ImportJob;
/**
* Interface ImporterInterface
*
* @package FireflyIII\Import\Importer
*/
interface ImporterInterface
{
/**
* After uploading, and after setJob(), prepare anything that is
* necessary for the configure() line.
*
* @return bool
*/
public function configure(): bool;
/**
* Returns any data necessary to do the configuration.
*
* @return array
*/
public function getConfigurationData(): array;
/**
* Returns a Map thing used to allow the user to
* define roles for each entry.
*
* @return Map
*/
public function prepareRoles(): Map;
/**
* @param ImportJob $job
*
*/
public function setJob(ImportJob $job);
}

18
app/Import/Role/Map.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
/**
* Map.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import\Role;
class Map
{
}

18
app/Import/Role/Role.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
/**
* Role.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import\Role;
class Role
{
}

75
app/Models/ImportJob.php Normal file
View File

@@ -0,0 +1,75 @@
<?php
/**
* ImportJob.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Models;
use Auth;
use Illuminate\Database\Eloquent\Model;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class ImportJob
*
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property string $key
* @property string $file_type
* @property string $status
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereKey($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereFileType($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereStatus($value)
* @mixin \Eloquent
*/
class ImportJob extends Model
{
/**
* @param $value
*
* @return mixed
* @throws NotFoundHttpException
*/
public static function routeBinder($value)
{
if (Auth::check()) {
$model = self::where('key', $value)->where('user_id', Auth::user()->id)->first();
if (!is_null($model)) {
return $model;
}
}
throw new NotFoundHttpException;
}
/**
* @param $status
*/
public function change($status)
{
$this->status = $status;
$this->save();
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('FireflyIII\User');
}
}

View File

@@ -31,6 +31,27 @@ class ExportJobServiceProvider extends ServiceProvider
*/
public function boot()
{
$this->exportJob();
$this->importJob();
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}
/**
*
*/
private function exportJob()
{
$this->app->bind(
'FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface',
function (Application $app, array $arguments) {
@@ -46,13 +67,20 @@ class ExportJobServiceProvider extends ServiceProvider
);
}
/**
* Register the application services.
*
* @return void
*/
public function register()
private function importJob()
{
//
$this->app->bind(
'FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface',
function (Application $app, array $arguments) {
if (!isset($arguments[0]) && $app->auth->check()) {
return app('FireflyIII\Repositories\ImportJob\ImportJobRepository', [$app->auth->user()]);
}
if (!isset($arguments[0]) && !$app->auth->check()) {
throw new FireflyException('There is no user present.');
}
return app('FireflyIII\Repositories\ImportJob\ImportJobRepository', $arguments);
}
);
}
}

View File

@@ -87,7 +87,6 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository');
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
$this->app->bind('FireflyIII\Repositories\User\UserRepositoryInterface', 'FireflyIII\Repositories\User\UserRepository');
$this->app->bind('FireflyIII\Helpers\Csv\WizardInterface', 'FireflyIII\Helpers\Csv\Wizard');
$this->app->bind('FireflyIII\Helpers\Attachments\AttachmentHelperInterface', 'FireflyIII\Helpers\Attachments\AttachmentHelper');
$this->app->bind(
'FireflyIII\Generator\Chart\Account\AccountChartGeneratorInterface', 'FireflyIII\Generator\Chart\Account\ChartJsAccountChartGenerator'

View File

@@ -0,0 +1,81 @@
<?php
/**
* ImportJobRepository.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Repositories\ImportJob;
use FireflyIII\Models\ImportJob;
use FireflyIII\User;
use Illuminate\Support\Str;
/**
* Class ImportJobRepository
*
* @package FireflyIII\Repositories\ImportJob
*/
class ImportJobRepository implements ImportJobRepositoryInterface
{
/** @var User */
private $user;
/**
* ExportJobRepository constructor.
*
* @param User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* @param string $fileType
*
* @return ImportJob
*/
public function create(string $fileType): ImportJob
{
$count = 0;
while ($count < 30) {
$key = Str::random(12);
$existing = $this->findByKey($key);
if (is_null($existing->id)) {
$importJob = new ImportJob;
$importJob->user()->associate($this->user);
$importJob->file_type = $fileType;
$importJob->key = Str::random(12);
$importJob->status = 'import_status_never_started';
$importJob->save();
// breaks the loop:
return $importJob;
}
$count++;
}
return new ImportJob;
}
/**
* @param string $key
*
* @return ImportJob
*/
public function findByKey(string $key): ImportJob
{
$result = $this->user->importJobs()->where('key', $key)->first();
if (is_null($result)) {
return new ImportJob;
}
return $result;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* ImportJobRepositoryInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Repositories\ImportJob;
use FireflyIII\Models\ImportJob;
/**
* Interface ImportJobRepositoryInterface
*
* @package FireflyIII\Repositories\ImportJob
*/
interface ImportJobRepositoryInterface
{
/**
* @param string $fileType
*
* @return ImportJob
*/
public function create(string $fileType): ImportJob;
/**
* @param string $key
*
* @return ImportJob
*/
public function findByKey(string $key): ImportJob;
}

View File

@@ -54,6 +54,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereBlocked($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereBlockedCode($value)
* @mixin \Eloquent
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\ImportJob[] $importjobs
*/
class User extends Authenticatable
{
@@ -145,6 +146,14 @@ class User extends Authenticatable
return $this->hasMany('FireflyIII\Models\ExportJob');
}
/**
* @return HasMany
*/
public function importjobs(): HasMany
{
return $this->hasMany('FireflyIII\Models\ImportJob');
}
/**
* Checks if the user has a role by its name.
*