Files
firefly-iii/app/Import/Storage/ImportStorage.php

227 lines
6.9 KiB
PHP
Raw Normal View History

<?php
/**
* ImportStorage.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Import\Storage;
2017-06-24 07:21:10 +02:00
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Import\Object\ImportJournal;
2017-06-20 21:04:25 +02:00
use FireflyIII\Models\ImportJob;
2017-08-12 19:03:42 +02:00
use FireflyIII\Models\TransactionType;
use Illuminate\Support\Collection;
use Log;
/**
* Is capable of storing individual ImportJournal objects.
* Class ImportStorage
*
* @package FireflyIII\Import\Storage
*/
class ImportStorage
{
2017-08-12 19:03:42 +02:00
use ImportSupport;
2017-06-21 20:04:35 +02:00
/** @var Collection */
public $errors;
2017-07-16 07:45:20 +02:00
/** @var Collection */
2017-06-21 20:04:35 +02:00
public $journals;
2017-08-12 16:42:29 +02:00
/** @var int */
2017-08-12 19:03:42 +02:00
protected $defaultCurrencyId = 1;
/** @var string */
private $dateFormat = 'Ymd'; // yes, hard coded
2017-06-20 21:04:25 +02:00
/** @var ImportJob */
private $job;
/** @var Collection */
private $objects;
2017-06-22 21:50:10 +02:00
/** @var Collection */
private $rules;
2017-08-12 19:03:42 +02:00
/** @var array */
private $transfers = [];
/**
* ImportStorage constructor.
*/
public function __construct()
{
2017-06-21 20:04:35 +02:00
$this->objects = new Collection;
$this->journals = new Collection;
$this->errors = new Collection;
}
/**
* @param string $dateFormat
*/
public function setDateFormat(string $dateFormat)
{
$this->dateFormat = $dateFormat;
}
2017-06-20 21:04:25 +02:00
/**
* @param ImportJob $job
*/
public function setJob(ImportJob $job)
{
2017-08-12 16:42:29 +02:00
$this->job = $job;
$currency = app('amount')->getDefaultCurrencyByUser($this->job->user);
$this->defaultCurrencyId = $currency->id;
2017-08-12 19:03:42 +02:00
$this->transfers = $this->getTransfers();
$this->rules = $this->getRules();
2017-06-20 21:04:25 +02:00
}
/**
* @param Collection $objects
*/
public function setObjects(Collection $objects)
{
$this->objects = $objects;
}
/**
2017-08-12 16:40:51 +02:00
* Do storage of import objects. Is the main function.
2017-06-22 21:50:10 +02:00
*
* @return bool
*/
2017-08-12 16:40:51 +02:00
public function store(): bool
2017-06-22 21:50:10 +02:00
{
2017-08-12 16:40:51 +02:00
$this->objects->each(
function (ImportJournal $importJournal, int $index) {
try {
$this->storeImportJournal($index, $importJournal);
} catch (FireflyException $e) {
$this->errors->push($e->getMessage());
Log::error(sprintf('Cannot import row #%d because: %s', $index, $e->getMessage()));
2017-06-22 21:50:10 +02:00
}
}
2017-07-16 07:45:20 +02:00
);
2017-08-12 16:40:51 +02:00
Log::info('ImportStorage has finished.');
2017-08-12 07:47:42 +02:00
2017-08-12 16:40:51 +02:00
return true;
2017-06-24 07:21:10 +02:00
}
/**
2017-08-12 16:40:51 +02:00
* @param int $index
* @param ImportJournal $importJournal
2017-06-24 07:21:10 +02:00
*
2017-08-12 16:40:51 +02:00
* @return bool
* @throws FireflyException
2017-06-24 07:30:05 +02:00
*/
2017-08-12 19:03:42 +02:00
protected function storeImportJournal(int $index, ImportJournal $importJournal): bool
2017-06-24 07:21:10 +02:00
{
Log::debug(sprintf('Going to store object #%d with description "%s"', $index, $importJournal->getDescription()));
2017-08-12 19:03:42 +02:00
$assetAccount = $importJournal->asset->getAccount();
$amount = $importJournal->getAmount();
$currencyId = $this->getCurrencyId($importJournal);
$foreignCurrencyId = $this->getForeignCurrencyId($importJournal, $currencyId);
$date = $importJournal->getDate($this->dateFormat)->format('Y-m-d');
$opposingAccount = $this->getOpposingAccount($importJournal->opposing, $assetAccount->id, $amount);
$transactionType = $this->getTransactionType($amount, $opposingAccount);
$description = $importJournal->getDescription();
/*** First step done! */
$this->job->addStepsDone(1);
/**
* Check for double transfer.
*/
$parameters = [
'type' => $transactionType,
'description' => $description,
'amount' => $amount,
'date' => $date,
'asset' => $assetAccount->name,
'opposing' => $opposingAccount->name,
];
2017-08-13 08:49:45 +02:00
if ($this->isDoubleTransfer($parameters) || $this->hashAlreadyImported($importJournal->hash)) {
2017-08-12 19:03:42 +02:00
$this->job->addStepsDone(3);
// throw error
throw new FireflyException('Detected a possible duplicate, skip this one.');
}
unset($parameters);
// store journal and create transactions:
$parameters = [
'type' => $transactionType,
'currency' => $currencyId,
'foreign_currency' => $foreignCurrencyId,
'asset' => $assetAccount,
'opposing' => $opposingAccount,
'description' => $description,
'date' => $date,
'hash' => $importJournal->hash,
'amount' => $amount,
];
$journal = $this->storeJournal($parameters);
unset($parameters);
/*** Another step done! */
$this->job->addStepsDone(1);
// store meta object things:
$this->storeCategory($journal, $importJournal->category->getCategory());
$this->storeBudget($journal, $importJournal->budget->getBudget());
$this->storeBill($journal, $importJournal->bill->getBill());
$this->storeMeta($journal, $importJournal->metaDates);
$journal->setMeta('notes', $importJournal->notes);
$this->storeTags($importJournal->tags, $journal);
// set journal completed:
$journal->completed = true;
$journal->save();
/*** Another step done! */
$this->job->addStepsDone(1);
// run rules:
$this->applyRules($journal);
/*** Another step done! */
$this->job->addStepsDone(1);
$this->journals->push($journal);
2017-08-13 08:49:45 +02:00
Log::info(sprintf('Imported new journal #%d: "%s", amount %s %s.', $journal->id, $journal->description, $journal->transactionCurrency->code, $amount));
2017-07-07 08:04:21 +02:00
2017-06-24 07:21:10 +02:00
return true;
}
2017-08-12 19:03:42 +02:00
/**
* @param array $parameters
*
* @return bool
*/
private function isDoubleTransfer(array $parameters): bool
{
if ($parameters['type'] !== TransactionType::TRANSFER) {
return false;
}
2017-08-12 16:40:51 +02:00
2017-08-12 19:03:42 +02:00
$amount = app('steam')->positive($parameters['amount']);
$names = [$parameters['asset'], $parameters['opposing']];
sort($names);
2017-08-12 16:40:51 +02:00
2017-08-12 19:03:42 +02:00
foreach ($this->transfers as $transfer) {
if ($parameters['description'] !== $transfer['description']) {
return false;
}
if ($names !== $transfer['names']) {
return false;
}
if (bccomp($amount, $transfer['amount']) !== 0) {
return false;
}
if ($parameters['date'] !== $transfer['date']) {
return false;
}
}
2017-08-12 19:03:42 +02:00
return true;
}
2017-07-07 08:09:42 +02:00
}