mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/3.10.1'
This commit is contained in:
commit
c03f5f5ff0
@ -1,50 +0,0 @@
|
||||
---
|
||||
engines:
|
||||
csslint:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- ruby
|
||||
- javascript
|
||||
- python
|
||||
- php
|
||||
eslint:
|
||||
enabled: true
|
||||
fixme:
|
||||
enabled: true
|
||||
phpmd:
|
||||
enabled: true
|
||||
ratings:
|
||||
paths:
|
||||
- "**.css"
|
||||
- "**.inc"
|
||||
- "**.js"
|
||||
- "**.jsx"
|
||||
- "**.module"
|
||||
- "**.php"
|
||||
- "**.py"
|
||||
- "**.rb"
|
||||
exclude_paths:
|
||||
- gulpfile.js
|
||||
- public/packages/maximebf/php-debugbar/debugbar.js
|
||||
- public/packages/maximebf/php-debugbar/widgets.js
|
||||
- public/packages/maximebf/php-debugbar/openhandler.js
|
||||
- public/packages/maximebf/php-debugbar/widgets/sqlqueries/widget.js
|
||||
- public/js/bootstrap3-typeahead.min.js
|
||||
- public/js/bootstrap-sortable.js
|
||||
- public/js/bootstrap-tagsinput.min.js
|
||||
- public/js/bootstrap-tagsinput.min.js.map
|
||||
- public/js/daterangepicker.js
|
||||
- public/js/jquery-2.1.3.min.js
|
||||
- public/js/jquery-2.1.3.min.js.map
|
||||
- public/js/jquery-ui.min.js
|
||||
- public/js/metisMenu.js
|
||||
- public/js/moment.min.js
|
||||
- public/js/sb-admin-2.js
|
||||
- public/bootstrap/*
|
||||
- resources/lang/*
|
||||
- tests/*
|
||||
- database/*
|
||||
- storage/*
|
@ -4,3 +4,4 @@ tools:
|
||||
filter:
|
||||
excluded_paths:
|
||||
- app/Support/Migration/*
|
||||
- app/database/migrations/*
|
||||
|
20
CHANGELOG.md
20
CHANGELOG.md
@ -5,6 +5,26 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
## [Unreleased]
|
||||
- No unreleased changes yet.
|
||||
|
||||
## [3.10.1] - 2016-08-25
|
||||
### Added
|
||||
- More feedback in the import procedure.
|
||||
- Extended model for import job.
|
||||
- Web bases import procedure.
|
||||
|
||||
|
||||
### Changed
|
||||
- Scrutinizer configuration
|
||||
- Various code clean up.
|
||||
|
||||
### Removed
|
||||
- Code climate YAML file.
|
||||
|
||||
### Fixed
|
||||
- Fixed a bug where a migration would check an empty table name.
|
||||
- Fixed various bugs in the import routine.
|
||||
- Fixed various bugs in the piggy banks pages.
|
||||
- Fixed a bug in the ``firefly:verify`` routine
|
||||
|
||||
## [3.10] - 2015-05-25
|
||||
### Added
|
||||
- New charts in year report
|
||||
|
@ -11,10 +11,8 @@ declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Crud\Account\AccountCrud;
|
||||
use FireflyIII\Import\Importer\ImporterInterface;
|
||||
use FireflyIII\Import\ImportStorage;
|
||||
use FireflyIII\Import\ImportValidator;
|
||||
use FireflyIII\Import\ImportProcedure;
|
||||
use FireflyIII\Import\ImportResult;
|
||||
use FireflyIII\Import\Logging\CommandHandler;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use Illuminate\Console\Command;
|
||||
@ -59,55 +57,55 @@ class Import extends Command
|
||||
{
|
||||
$jobKey = $this->argument('key');
|
||||
$job = ImportJob::whereKey($jobKey)->first();
|
||||
if (!$this->isValid($job)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->line('Going to import job with key "' . $job->key . '" of type ' . $job->file_type);
|
||||
|
||||
$monolog = Log::getMonolog();
|
||||
$handler = new CommandHandler($this);
|
||||
$monolog->pushHandler($handler);
|
||||
|
||||
$result = ImportProcedure::run($job);
|
||||
|
||||
/**
|
||||
* @var int $index
|
||||
* @var ImportResult $entry
|
||||
*/
|
||||
foreach ($result as $index => $entry) {
|
||||
if ($entry->isSuccess()) {
|
||||
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $entry->journal->id));
|
||||
continue;
|
||||
}
|
||||
$errors = join(', ', $entry->errors->all());
|
||||
$this->error(sprintf('Could not store line #%d, because: %s', $index, $errors));
|
||||
}
|
||||
|
||||
|
||||
$this->line('The import has completed.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isValid(ImportJob $job): bool
|
||||
{
|
||||
if (is_null($job)) {
|
||||
$this->error('This job does not seem to exist.');
|
||||
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($job->status != 'settings_complete') {
|
||||
$this->error('This job is not ready to be imported.');
|
||||
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->line('Going to import job with key "' . $job->key . '" of type ' . $job->file_type);
|
||||
$valid = array_keys(config('firefly.import_formats'));
|
||||
$class = 'INVALID';
|
||||
if (in_array($job->file_type, $valid)) {
|
||||
$class = config('firefly.import_formats.' . $job->file_type);
|
||||
}
|
||||
|
||||
/** @var ImporterInterface $importer */
|
||||
$importer = app($class);
|
||||
$importer->setJob($job);
|
||||
// intercept logging by importer.
|
||||
$monolog = Log::getMonolog();
|
||||
$handler = new CommandHandler($this);
|
||||
|
||||
$monolog->pushHandler($handler);
|
||||
|
||||
// create import entries
|
||||
$collection = $importer->createImportEntries();
|
||||
|
||||
// validate / clean collection:
|
||||
$validator = new ImportValidator($collection);
|
||||
$validator->setUser($job->user);
|
||||
if ($job->configuration['import-account'] != 0) {
|
||||
$repository = app(AccountCrud::class, [$job->user]);
|
||||
$validator->setDefaultImportAccount($repository->find($job->configuration['import-account']));
|
||||
}
|
||||
|
||||
$cleaned = $validator->clean();
|
||||
|
||||
// then import collection:
|
||||
$storage = new ImportStorage($cleaned);
|
||||
$storage->setUser($job->user);
|
||||
|
||||
// and run store routine:
|
||||
$storage->store();
|
||||
|
||||
|
||||
$this->line('Something something import: ' . $jobKey);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -93,12 +93,16 @@ class VerifyDatabase extends Command
|
||||
->leftJoin('users', 'accounts.user_id', '=', 'users.id')
|
||||
->groupBy('accounts.id')
|
||||
->having('transaction_count', '=', 0)
|
||||
->get(['accounts.id', 'accounts.name', 'accounts.user_id', 'users.email', DB::raw('COUNT(`transactions`.`id`) AS `transaction_count`')]);
|
||||
->get(
|
||||
['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email',
|
||||
DB::raw('COUNT(`transactions`.`id`) AS `transaction_count`')]
|
||||
);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$line = 'User #' . $entry->user_id . ' (' . $entry->email . ') has account #' . $entry->id . ' ("' . Crypt::decrypt($entry->name)
|
||||
. '") which has no transactions.';
|
||||
$name = $entry->name;
|
||||
$line = 'User #%d (%s) has account #%d ("%s") which has no transactions.';
|
||||
$line = sprintf($line, $entry->user_id, $entry->email, $entry->id, $name);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ use Log;
|
||||
/**
|
||||
* Class AccountCrud
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
*
|
||||
* @package FireflyIII\Crud\Account
|
||||
*/
|
||||
class AccountCrud implements AccountCrudInterface
|
||||
@ -56,15 +58,12 @@ class AccountCrud implements AccountCrudInterface
|
||||
public function destroy(Account $account, Account $moveTo): bool
|
||||
{
|
||||
if (!is_null($moveTo->id)) {
|
||||
// update all transactions:
|
||||
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
|
||||
}
|
||||
if (!is_null($account)) {
|
||||
Log::debug('Now trigger account delete #' . $account->id);
|
||||
$account->delete();
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -75,7 +74,6 @@ class AccountCrud implements AccountCrudInterface
|
||||
*/
|
||||
public function find(int $accountId): Account
|
||||
{
|
||||
Log::debug('Searching for user ', ['user' => $this->user->id]);
|
||||
$account = $this->user->accounts()->find($accountId);
|
||||
if (is_null($account)) {
|
||||
return new Account;
|
||||
@ -146,7 +144,6 @@ class AccountCrud implements AccountCrudInterface
|
||||
public function findByName(string $name, array $types): Account
|
||||
{
|
||||
$query = $this->user->accounts();
|
||||
Log::debug('Now in findByName()', ['name' => $name, 'types' => $types]);
|
||||
|
||||
if (count($types) > 0) {
|
||||
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
|
||||
@ -154,16 +151,13 @@ class AccountCrud implements AccountCrudInterface
|
||||
}
|
||||
|
||||
$accounts = $query->get(['accounts.*']);
|
||||
Log::debug(sprintf('Total set count is %d ', $accounts->count()));
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
if ($account->name === $name) {
|
||||
Log::debug('Account name is an exact match. ', ['db' => $account->name, 'source' => $name, 'id' => $account->id]);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
Log::debug('Found nothing in findByName()', ['name' => $name, 'types' => $types]);
|
||||
|
||||
return new Account;
|
||||
}
|
||||
@ -187,7 +181,6 @@ class AccountCrud implements AccountCrudInterface
|
||||
}
|
||||
|
||||
$result = $query->get(['accounts.*']);
|
||||
|
||||
$result = $result->sortBy(
|
||||
function (Account $account) {
|
||||
return strtolower($account->name);
|
||||
@ -215,7 +208,6 @@ class AccountCrud implements AccountCrudInterface
|
||||
}
|
||||
|
||||
$result = $query->get(['accounts.*']);
|
||||
|
||||
$result = $result->sortBy(
|
||||
function (Account $account) {
|
||||
return strtolower($account->name);
|
||||
@ -229,8 +221,6 @@ class AccountCrud implements AccountCrudInterface
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function store(array $data): Account
|
||||
{
|
||||
@ -330,6 +320,7 @@ class AccountCrud implements AccountCrudInterface
|
||||
$existingAccount = Account::firstOrNullEncrypted($searchData);
|
||||
if (!$existingAccount) {
|
||||
Log::error('Account create error', $newAccount->getErrors()->toArray());
|
||||
|
||||
return new Account;
|
||||
}
|
||||
$newAccount = $existingAccount;
|
||||
@ -402,8 +393,6 @@ class AccountCrud implements AccountCrudInterface
|
||||
);
|
||||
$metaData->save();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ class UpdateJournalConnection
|
||||
* Handle the event.
|
||||
*
|
||||
* @param TransactionJournalUpdated $event
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -46,7 +47,7 @@ class UpdateJournalConnection
|
||||
}
|
||||
$piggyBank = $event->piggyBank()->first();
|
||||
$repetition = null;
|
||||
if ($piggyBank) {
|
||||
if (!is_null($piggyBank)) {
|
||||
/** @var PiggyBankRepetition $repetition */
|
||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||
}
|
||||
|
@ -41,46 +41,61 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param BudgetLine $budgetLine
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addBudgetLine(BudgetLine $budgetLine)
|
||||
public function addBudgetLine(BudgetLine $budgetLine): Budget
|
||||
{
|
||||
$this->budgetLines->push($budgetLine);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addBudgeted(string $add)
|
||||
public function addBudgeted(string $add): Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->budgeted = bcadd($this->budgeted, $add);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addLeft(string $add)
|
||||
public function addLeft(string $add): Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->left = bcadd($this->left, $add);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addOverspent(string $add)
|
||||
public function addOverspent(string $add): Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->overspent = bcadd($this->overspent, $add);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $add
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function addSpent(string $add)
|
||||
public function addSpent(string $add): Budget
|
||||
{
|
||||
$add = strval(round($add, 2));
|
||||
$this->spent = bcadd($this->spent, $add);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,10 +116,14 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param string $budgeted
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function setBudgeted(string $budgeted)
|
||||
public function setBudgeted(string $budgeted): Budget
|
||||
{
|
||||
$this->budgeted = $budgeted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,10 +136,14 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param string $left
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function setLeft(string $left)
|
||||
public function setLeft(string $left): Budget
|
||||
{
|
||||
$this->left = $left;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,10 +156,14 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param string $overspent
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function setOverspent(string $overspent)
|
||||
public function setOverspent(string $overspent): Budget
|
||||
{
|
||||
$this->overspent = strval(round($overspent, 2));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,10 +176,14 @@ class Budget
|
||||
|
||||
/**
|
||||
* @param string $spent
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function setSpent(string $spent)
|
||||
public function setSpent(string $spent): Budget
|
||||
{
|
||||
$this->spent = strval(round($spent, 2));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,10 +45,13 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param BudgetModel $budget
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setBudget(BudgetModel $budget)
|
||||
public function setBudget(BudgetModel $budget): BudgetLine
|
||||
{
|
||||
$this->budget = $budget;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,10 +64,13 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param string $budgeted
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setBudgeted(string $budgeted)
|
||||
public function setBudgeted(string $budgeted): BudgetLine
|
||||
{
|
||||
$this->budgeted = $budgeted;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,10 +83,13 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param string $left
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setLeft(string $left)
|
||||
public function setLeft(string $left): BudgetLine
|
||||
{
|
||||
$this->left = $left;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,10 +102,13 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param string $overspent
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setOverspent(string $overspent)
|
||||
public function setOverspent(string $overspent): BudgetLine
|
||||
{
|
||||
$this->overspent = $overspent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,10 +121,13 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param LimitRepetition $repetition
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setRepetition(LimitRepetition $repetition)
|
||||
public function setRepetition(LimitRepetition $repetition): BudgetLine
|
||||
{
|
||||
$this->repetition = $repetition;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,10 +140,13 @@ class BudgetLine
|
||||
|
||||
/**
|
||||
* @param string $spent
|
||||
*
|
||||
* @return BudgetLine
|
||||
*/
|
||||
public function setSpent(string $spent)
|
||||
public function setSpent(string $spent): BudgetLine
|
||||
{
|
||||
$this->spent = $spent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
@ -261,7 +261,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
|
||||
/**
|
||||
* @param Balance $balance
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
* @return Balance
|
||||
*/
|
||||
private function removeUnusedBudgets(Balance $balance): Balance
|
||||
|
@ -42,6 +42,9 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // at 43, its ok.
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Collection $accounts
|
||||
@ -59,38 +62,22 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
$headers = [];
|
||||
|
||||
$current = clone $start;
|
||||
$return = new Collection;
|
||||
$set = $this->repository->getBudgets();
|
||||
$budgets = [];
|
||||
$spent = [];
|
||||
while ($current < $end) {
|
||||
$short = $current->format('m-Y');
|
||||
$headers[$short] = $current->formatLocalized((string)trans('config.month'));
|
||||
$current->addMonth();
|
||||
}
|
||||
|
||||
$headers = $this->createYearHeaders($current, $end);
|
||||
|
||||
/** @var Budget $budget */
|
||||
foreach ($set as $budget) {
|
||||
$id = $budget->id;
|
||||
$budgets[$id] = $budget->name;
|
||||
$spent[$id] = [];
|
||||
$current = clone $start;
|
||||
$sum = '0';
|
||||
|
||||
|
||||
while ($current < $end) {
|
||||
$currentEnd = clone $current;
|
||||
$currentEnd->endOfMonth();
|
||||
$format = $current->format('m-Y');
|
||||
$budgetSpent = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $current, $currentEnd);
|
||||
$spent[$id][$format] = $budgetSpent;
|
||||
$sum = bcadd($sum, $budgetSpent);
|
||||
$current->addMonth();
|
||||
}
|
||||
$budgetData = $this->getBudgetSpentData($current, $end, $budget, $accounts);
|
||||
$sum = $budgetData['sum'];
|
||||
$spent[$id] = $budgetData['spent'];
|
||||
|
||||
if (bccomp('0', $sum) === 0) {
|
||||
// not spent anything.
|
||||
@ -131,10 +118,8 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
|
||||
if ($spent > 0) {
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setBudget($budget);
|
||||
$budgetLine->setOverspent($spent);
|
||||
$object->addOverspent($spent);
|
||||
$object->addBudgetLine($budgetLine);
|
||||
$budgetLine->setBudget($budget)->setOverspent($spent);
|
||||
$object->addOverspent($spent)->addBudgetLine($budgetLine);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -144,18 +129,12 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
$data = $this->calculateExpenses($budget, $repetition, $accounts);
|
||||
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setBudget($budget);
|
||||
$budgetLine->setRepetition($repetition);
|
||||
$budgetLine->setLeft($data['left']);
|
||||
$budgetLine->setSpent($data['expenses']);
|
||||
$budgetLine->setOverspent($data['overspent']);
|
||||
$budgetLine->setBudgeted($repetition->amount);
|
||||
$budgetLine->setBudget($budget)->setRepetition($repetition)
|
||||
->setLeft($data['left'])->setSpent($data['expenses'])->setOverspent($data['overspent'])
|
||||
->setBudgeted(strval($repetition->amount));
|
||||
|
||||
$object->addBudgeted($repetition->amount);
|
||||
$object->addSpent($data['spent']);
|
||||
$object->addLeft($data['left']);
|
||||
$object->addOverspent($data['overspent']);
|
||||
$object->addBudgetLine($budgetLine);
|
||||
$object->addBudgeted(strval($repetition->amount))->addSpent($data['spent'])
|
||||
->addLeft($data['left'])->addOverspent($data['overspent'])->addBudgetLine($budgetLine);
|
||||
|
||||
}
|
||||
|
||||
@ -165,10 +144,8 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
|
||||
$noBudget = $this->repository->spentInPeriodWithoutBudget($accounts, $start, $end);
|
||||
$budgetLine = new BudgetLine;
|
||||
$budgetLine->setOverspent($noBudget);
|
||||
$budgetLine->setSpent($noBudget);
|
||||
$object->addOverspent($noBudget);
|
||||
$object->addBudgetLine($budgetLine);
|
||||
$budgetLine->setOverspent($noBudget)->setSpent($noBudget);
|
||||
$object->addOverspent($noBudget)->addBudgetLine($budgetLine);
|
||||
|
||||
return $object;
|
||||
}
|
||||
@ -249,4 +226,50 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
return $array;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $current
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function createYearHeaders(Carbon $current, Carbon $end): array
|
||||
{
|
||||
$headers = [];
|
||||
while ($current < $end) {
|
||||
$short = $current->format('m-Y');
|
||||
$headers[$short] = $current->formatLocalized((string)trans('config.month'));
|
||||
$current->addMonth();
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $current
|
||||
* @param Carbon $end
|
||||
* @param Budget $budget
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getBudgetSpentData(Carbon $current, Carbon $end, Budget $budget, Collection $accounts): array
|
||||
{
|
||||
$sum = '0';
|
||||
$spent = [];
|
||||
while ($current < $end) {
|
||||
$currentEnd = clone $current;
|
||||
$currentEnd->endOfMonth();
|
||||
$format = $current->format('m-Y');
|
||||
$budgetSpent = $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $current, $currentEnd);
|
||||
$spent[$format] = $budgetSpent;
|
||||
$sum = bcadd($sum, $budgetSpent);
|
||||
$current->addMonth();
|
||||
}
|
||||
|
||||
return [
|
||||
'spent' => $spent,
|
||||
'sum' => $sum,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -11,13 +11,15 @@ namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Crypt;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\ImportUploadRequest;
|
||||
use FireflyIII\Import\ImportProcedure;
|
||||
use FireflyIII\Import\Setup\SetupInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Response;
|
||||
use SplFileObject;
|
||||
use Storage;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
@ -53,7 +55,7 @@ class ImportController extends Controller
|
||||
if (!$this->jobInCorrectStep($job, 'complete')) {
|
||||
return $this->redirectToCorrectStep($job);
|
||||
}
|
||||
$subTitle = trans('firefy.import_complete');
|
||||
$subTitle = trans('firefly.import_complete');
|
||||
$subTitleIcon = 'fa-star';
|
||||
|
||||
return view('import.complete', compact('job', 'subTitle', 'subTitleIcon'));
|
||||
@ -119,6 +121,25 @@ class ImportController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function finished(ImportJob $job)
|
||||
{
|
||||
if (!$this->jobInCorrectStep($job, 'finished')) {
|
||||
Log::debug('Job is not in correct state for finished()', ['status' => $job->status]);
|
||||
|
||||
return $this->redirectToCorrectStep($job);
|
||||
}
|
||||
|
||||
$subTitle = trans('firefly.import_finished');
|
||||
$subTitleIcon = 'fa-star';
|
||||
|
||||
return view('import.finished', compact('job', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is step 1. Upload a file.
|
||||
*
|
||||
@ -139,6 +160,48 @@ class ImportController extends Controller
|
||||
return view('import.index', compact('subTitle', 'subTitleIcon', 'importFileTypes', 'defaultImportType'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function json(ImportJob $job)
|
||||
{
|
||||
$result = [
|
||||
'showPercentage' => false,
|
||||
'started' => false,
|
||||
'finished' => false,
|
||||
'running' => false,
|
||||
'errors' => $job->extended_status['errors'],
|
||||
'percentage' => 0,
|
||||
'steps' => $job->extended_status['total_steps'],
|
||||
'stepsDone' => $job->extended_status['steps_done'],
|
||||
'statusText' => trans('firefly.import_status_' . $job->status),
|
||||
'finishedText' => '',
|
||||
];
|
||||
$percentage = 0;
|
||||
if ($job->extended_status['total_steps'] !== 0) {
|
||||
$percentage = round(($job->extended_status['steps_done'] / $job->extended_status['total_steps']) * 100, 0);
|
||||
}
|
||||
if ($job->status === 'import_complete') {
|
||||
$tagId = $job->extended_status['importTag'];
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$tag = $repository->find($tagId);
|
||||
$result['finished'] = true;
|
||||
$result['finishedText'] = trans('firefly.import_finished_link', ['link' => route('tags.show', [$tag->id]), 'tag' => $tag->tag]);
|
||||
}
|
||||
|
||||
if ($job->status === 'import_running') {
|
||||
$result['started'] = true;
|
||||
$result['running'] = true;
|
||||
$result['showPercentage'] = true;
|
||||
$result['percentage'] = $percentage;
|
||||
}
|
||||
|
||||
return Response::json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 4. Save the configuration.
|
||||
*
|
||||
@ -237,6 +300,35 @@ class ImportController extends Controller
|
||||
// depends of course on the data in the job.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*/
|
||||
public function start(ImportJob $job)
|
||||
{
|
||||
if ($job->status == "settings_complete") {
|
||||
ImportProcedure::run($job);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the last step before the import starts.
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||
*/
|
||||
public function status(ImportJob $job)
|
||||
{
|
||||
Log::debug('Now in status()', ['job' => $job->key]);
|
||||
if (!$this->jobInCorrectStep($job, 'status')) {
|
||||
return $this->redirectToCorrectStep($job);
|
||||
}
|
||||
$subTitle = trans('firefly.import_status');
|
||||
$subTitleIcon = 'fa-star';
|
||||
|
||||
return view('import.status', compact('job', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is step 2. It creates an Import Job. Stores the import.
|
||||
*
|
||||
@ -306,8 +398,12 @@ class ImportController extends Controller
|
||||
case 'settings':
|
||||
case 'store-settings':
|
||||
return $job->status === 'import_configuration_saved';
|
||||
case 'finished':
|
||||
return $job->status === 'import_complete';
|
||||
case 'complete':
|
||||
return $job->status === 'settings_complete';
|
||||
case 'status':
|
||||
return ($job->status === 'settings_complete') || ($job->status === 'import_running');
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -353,6 +449,11 @@ class ImportController extends Controller
|
||||
Log::debug('Will redirect to complete()');
|
||||
|
||||
return redirect(route('import.complete', [$job->key]));
|
||||
case
|
||||
'import_complete':
|
||||
Log::debug('Will redirect to finished()');
|
||||
|
||||
return redirect(route('import.finished', [$job->key]));
|
||||
}
|
||||
|
||||
throw new FireflyException('Cannot redirect for job state ' . $job->status);
|
||||
|
@ -48,26 +48,6 @@ class PiggyBankController extends Controller
|
||||
View::share('mainTitleIcon', 'fa-sort-amount-asc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add money to piggy bank (for mobile devices)
|
||||
*
|
||||
* @param ARI $repository
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addMobile(ARI $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', Carbon::now()->endOfMonth());
|
||||
$leftOnAccount = $repository->leftOnAccount($piggyBank->account, $date);
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||
|
||||
return view('piggy-banks.add-mobile', compact('piggyBank', 'maxAmount'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add money to piggy bank
|
||||
*
|
||||
@ -81,13 +61,33 @@ class PiggyBankController extends Controller
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', Carbon::now()->endOfMonth());
|
||||
$leftOnAccount = $repository->leftOnAccount($piggyBank->account, $date);
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount ?? '0';
|
||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||
|
||||
return view('piggy-banks.add', compact('piggyBank', 'maxAmount'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add money to piggy bank (for mobile devices)
|
||||
*
|
||||
* @param ARI $repository
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addMobile(ARI $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', Carbon::now()->endOfMonth());
|
||||
$leftOnAccount = $repository->leftOnAccount($piggyBank->account, $date);
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount?? '0';
|
||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||
|
||||
return view('piggy-banks.add-mobile', compact('piggyBank', 'maxAmount'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountCrudInterface $crud
|
||||
*
|
||||
@ -262,7 +262,8 @@ class PiggyBankController extends Controller
|
||||
|
||||
if ($amount <= $maxAmount) {
|
||||
$repetition = $piggyBank->currentRelevantRep();
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
||||
$currentAmount = $repetition->currentamount ?? '0';
|
||||
$repetition->currentamount = bcadd($currentAmount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
// create event
|
||||
@ -326,6 +327,18 @@ class PiggyBankController extends Controller
|
||||
return view('piggy-banks.remove', compact('piggyBank'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove money from piggy bank (for mobile devices)
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeMobile(PiggyBank $piggyBank)
|
||||
{
|
||||
return view('piggy-banks.remove-mobile', compact('piggyBank'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBankRepositoryInterface $repository
|
||||
* @param PiggyBank $piggyBank
|
||||
@ -351,12 +364,12 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
|
||||
$piggyBankData = [
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => new Carbon,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => round($request->get('targetamount'), 2),
|
||||
'order' => $repository->getMaxOrder() + 1,
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => new Carbon,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => round($request->get('targetamount'), 2),
|
||||
'order' => $repository->getMaxOrder() + 1,
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
];
|
||||
|
||||
$piggyBank = $repository->store($piggyBankData);
|
||||
@ -385,11 +398,11 @@ class PiggyBankController extends Controller
|
||||
public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank)
|
||||
{
|
||||
$piggyBankData = [
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => round($request->get('targetamount'), 2),
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => round($request->get('targetamount'), 2),
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
];
|
||||
|
||||
$piggyBank = $repository->update($piggyBank, $piggyBankData);
|
||||
|
@ -232,6 +232,11 @@ Route::group(
|
||||
Route::get('/import/complete/{importJob}', ['uses' => 'ImportController@complete', 'as' => 'import.complete']);
|
||||
Route::get('/import/download/{importJob}', ['uses' => 'ImportController@download', 'as' => 'import.download']);
|
||||
|
||||
Route::get('/import/status/{importJob}', ['uses' => 'ImportController@status', 'as' => 'import.status']);
|
||||
Route::get('/import/json/{importJob}', ['uses' => 'ImportController@json', 'as' => 'import.json']);
|
||||
|
||||
Route::post('/import/start/{importJob}', ['uses' => 'ImportController@start', 'as' => 'import.start']);
|
||||
Route::get('/import/finished/{importJob}', ['uses' => 'ImportController@finished', 'as' => 'import.finished']);
|
||||
|
||||
/**
|
||||
* Help Controller
|
||||
@ -269,13 +274,10 @@ Route::group(
|
||||
Route::get('/piggy-banks', ['uses' => 'PiggyBankController@index', 'as' => 'piggy-banks.index']);
|
||||
Route::get('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@add', 'as' => 'piggy-banks.addMoney']);
|
||||
Route::get('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@remove', 'as' => 'piggy-banks.removeMoney']);
|
||||
|
||||
Route::get('/piggy-banks/add-money/{piggyBank}', ['uses' => 'PiggyBankController@addMobile', 'as' => 'piggy-banks.add-money-mobile']);
|
||||
Route::get('/piggy-banks/remove-money/{piggyBank}', ['uses' => 'PiggyBankController@removeMobile', 'as' => 'piggy-banks.remove-money-mobile']);
|
||||
|
||||
Route::post('/piggy-banks/add-money/{piggyBank}', ['uses' => 'PiggyBankController@postAddMobile', 'as' => 'piggy-banks.post-add-mobile']);
|
||||
Route::post('/piggy-banks/remove-money/{piggyBank}', ['uses' => 'PiggyBankController@postRemoveMobile', 'as' => 'piggy-banks.post-remove-mobile']);
|
||||
|
||||
// Route::post('/piggy-banks/add-money/{piggyBank}', ['uses' => 'PiggyBankController@postAddMobile', 'as' => 'piggy-banks.post-add-mobile']);
|
||||
// Route::post('/piggy-banks/remove-money/{piggyBank}', ['uses' => 'PiggyBankController@postRemoveMobile', 'as' => 'piggy-banks.post-remove-mobile']);
|
||||
Route::get('/piggy-banks/create', ['uses' => 'PiggyBankController@create', 'as' => 'piggy-banks.create']);
|
||||
Route::get('/piggy-banks/edit/{piggyBank}', ['uses' => 'PiggyBankController@edit', 'as' => 'piggy-banks.edit']);
|
||||
Route::get('/piggy-banks/delete/{piggyBank}', ['uses' => 'PiggyBankController@delete', 'as' => 'piggy-banks.delete']);
|
||||
@ -283,8 +285,10 @@ Route::group(
|
||||
Route::post('/piggy-banks/store', ['uses' => 'PiggyBankController@store', 'as' => 'piggy-banks.store']);
|
||||
Route::post('/piggy-banks/update/{piggyBank}', ['uses' => 'PiggyBankController@update', 'as' => 'piggy-banks.update']);
|
||||
Route::post('/piggy-banks/destroy/{piggyBank}', ['uses' => 'PiggyBankController@destroy', 'as' => 'piggy-banks.destroy']);
|
||||
|
||||
Route::post('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@postAdd', 'as' => 'piggy-banks.add']);
|
||||
Route::post('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@postRemove', 'as' => 'piggy-banks.remove']);
|
||||
|
||||
Route::post('/piggy-banks/sort', ['uses' => 'PiggyBankController@order', 'as' => 'piggy-banks.order']);
|
||||
|
||||
/**
|
||||
|
@ -80,7 +80,7 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface
|
||||
|
||||
if (is_null($account->id)) {
|
||||
$this->setCertainty(0);
|
||||
Log::notice('Could not store new asset account by account number', $account->getErrors()->toArray());
|
||||
Log::info('Could not store new asset account by account number', $account->getErrors()->toArray());
|
||||
|
||||
return new Account;
|
||||
}
|
||||
|
@ -37,8 +37,8 @@ class Date extends BasicConverter implements ConverterInterface
|
||||
try {
|
||||
$date = Carbon::createFromFormat($this->config['date-format'], $value);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::notice($e->getMessage());
|
||||
Log::notice('Cannot convert this string using the given format.', ['value' => $value, 'format' => $this->config['date-format']]);
|
||||
Log::info($e->getMessage());
|
||||
Log::info('Cannot convert this string using the given format.', ['value' => $value, 'format' => $this->config['date-format']]);
|
||||
$this->setCertainty(0);
|
||||
return new Carbon;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface
|
||||
$account = $repository->findByIban($value, []);
|
||||
if (!is_null($account->id)) {
|
||||
Log::debug('Found account by IBAN', ['id' => $account->id]);
|
||||
Log::notice(
|
||||
Log::info(
|
||||
'The match between IBAN and account is uncertain because the type of transactions may not have been determined.',
|
||||
['id' => $account->id, 'iban' => $value]
|
||||
);
|
||||
|
@ -13,7 +13,6 @@ namespace FireflyIII\Import;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@ -27,15 +26,18 @@ class ImportEntry
|
||||
{
|
||||
/** @var array */
|
||||
public $certain = [];
|
||||
/** @var Collection */
|
||||
public $errors;
|
||||
/** @var string */
|
||||
public $externalID;
|
||||
/** @var array */
|
||||
public $fields = [];
|
||||
/** @var string */
|
||||
public $hash;
|
||||
/** @var User */
|
||||
public $user;
|
||||
/** @var bool */
|
||||
public $valid = true;
|
||||
|
||||
/** @var int */
|
||||
private $amountMultiplier = 0;
|
||||
|
||||
@ -60,6 +62,8 @@ class ImportEntry
|
||||
$this->fields[$value] = null;
|
||||
$this->certain[$value] = 0;
|
||||
}
|
||||
$this->errors = new Collection;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,6 +79,10 @@ class ImportEntry
|
||||
default:
|
||||
Log::error('Import entry cannot handle object.', ['role' => $role]);
|
||||
throw new FireflyException('Import entry cannot handle object of type "' . $role . '".');
|
||||
case 'hash':
|
||||
$this->hash = $convertedValue;
|
||||
|
||||
return;
|
||||
case 'amount':
|
||||
/*
|
||||
* Easy enough.
|
||||
@ -136,12 +144,12 @@ class ImportEntry
|
||||
case 'ing-debet-credit':
|
||||
case 'rabo-debet-credit':
|
||||
$this->manipulateFloat('amount', 'multiply', $convertedValue);
|
||||
$this->applyMultiplier('amount'); // if present.
|
||||
$this->applyMultiplier('amount'); // if present.
|
||||
break;
|
||||
case 'tags-comma':
|
||||
case 'tags-space':
|
||||
$this->appendCollection('tags', $convertedValue);
|
||||
break;
|
||||
break;
|
||||
case 'external-id':
|
||||
$this->externalID = $convertedValue;
|
||||
break;
|
||||
|
81
app/Import/ImportProcedure.php
Normal file
81
app/Import/ImportProcedure.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* ImportProcedure.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;
|
||||
|
||||
use FireflyIII\Crud\Account\AccountCrud;
|
||||
use FireflyIII\Import\Importer\ImporterInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class ImportProcedure
|
||||
*
|
||||
* @package FireflyIII\Import
|
||||
*/
|
||||
class ImportProcedure
|
||||
{
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public static function run(ImportJob $job): Collection
|
||||
{
|
||||
// update job to say we started.
|
||||
$job->status = 'import_running';
|
||||
$job->save();
|
||||
|
||||
// create Importer
|
||||
$valid = array_keys(config('firefly.import_formats'));
|
||||
$class = 'INVALID';
|
||||
if (in_array($job->file_type, $valid)) {
|
||||
$class = config('firefly.import_formats.' . $job->file_type);
|
||||
}
|
||||
|
||||
/** @var ImporterInterface $importer */
|
||||
$importer = app($class);
|
||||
$importer->setJob($job);
|
||||
|
||||
// create import entries
|
||||
$collection = $importer->createImportEntries();
|
||||
|
||||
// validate / clean collection:
|
||||
$validator = new ImportValidator($collection);
|
||||
$validator->setUser($job->user);
|
||||
$validator->setJob($job);
|
||||
if ($job->configuration['import-account'] != 0) {
|
||||
$repository = app(AccountCrud::class, [$job->user]);
|
||||
$validator->setDefaultImportAccount($repository->find($job->configuration['import-account']));
|
||||
}
|
||||
|
||||
$cleaned = $validator->clean();
|
||||
|
||||
// then import collection:
|
||||
$storage = new ImportStorage($cleaned);
|
||||
$storage->setJob($job);
|
||||
$storage->setUser($job->user);
|
||||
|
||||
// and run store routine:
|
||||
$result = $storage->store();
|
||||
|
||||
// grab import tag:
|
||||
$status = $job->extended_status;
|
||||
$status['importTag'] = $storage->importTag->id;
|
||||
$job->extended_status = $status;
|
||||
$job->status = 'import_complete';
|
||||
$job->save();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
@ -25,6 +27,8 @@ class ImportResult
|
||||
|
||||
/** @var Collection */
|
||||
public $errors;
|
||||
/** @var TransactionJournal */
|
||||
public $journal;
|
||||
/** @var Collection */
|
||||
public $messages;
|
||||
/** @var int */
|
||||
@ -102,6 +106,14 @@ class ImportResult
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSuccess(): bool
|
||||
{
|
||||
return $this->status === self::IMPORT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $errors
|
||||
*/
|
||||
@ -110,6 +122,14 @@ class ImportResult
|
||||
$this->errors = $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
public function setJournal(TransactionJournal $journal)
|
||||
{
|
||||
$this->journal = $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $messages
|
||||
*/
|
||||
|
@ -12,9 +12,13 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@ -29,7 +33,10 @@ class ImportStorage
|
||||
|
||||
/** @var Collection */
|
||||
public $entries;
|
||||
|
||||
/** @var Tag */
|
||||
public $importTag;
|
||||
/** @var ImportJob */
|
||||
public $job;
|
||||
/** @var User */
|
||||
public $user;
|
||||
|
||||
@ -44,6 +51,14 @@ class ImportStorage
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*/
|
||||
public function setJob(ImportJob $job)
|
||||
{
|
||||
$this->job = $job;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
@ -53,15 +68,60 @@ class ImportStorage
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function store()
|
||||
public function store(): Collection
|
||||
{
|
||||
// create a tag to join the transactions.
|
||||
$this->importTag = $this->createImportTag();
|
||||
$collection = new Collection;
|
||||
Log::notice(sprintf('Started storing %d entry(ies).', $this->entries->count()));
|
||||
foreach ($this->entries as $index => $entry) {
|
||||
Log::debug(sprintf('--- import store start for row %d ---', $index));
|
||||
$this->storeSingle($index, $entry);
|
||||
$result = $this->storeSingle($index, $entry);
|
||||
$this->job->addStepsDone(1);
|
||||
$collection->put($index, $result);
|
||||
}
|
||||
Log::notice(sprintf('Finished storing %d entry(ies).', $collection->count()));
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $hash
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
private function alreadyImported(string $hash): TransactionJournal
|
||||
{
|
||||
|
||||
$meta = TransactionJournalMeta::where('name', 'originalImportHash')->where('data', json_encode($hash))->first(['journal_meta.*']);
|
||||
if (!is_null($meta)) {
|
||||
return $meta->transactionjournal;
|
||||
}
|
||||
|
||||
return new TransactionJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tag
|
||||
*/
|
||||
private function createImportTag(): Tag
|
||||
{
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$data = [
|
||||
'tag' => trans('firefly.import_with_key', ['key' => $this->job->key]),
|
||||
'date' => null,
|
||||
'description' => null,
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoomLevel' => null,
|
||||
'tagMode' => 'nothing',
|
||||
];
|
||||
$tag = $repository->store($data);
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,6 +226,7 @@ class ImportStorage
|
||||
*/
|
||||
private function storeJournal($entry): TransactionJournal
|
||||
{
|
||||
|
||||
$billId = is_null($entry->fields['bill']) ? null : $entry->fields['bill']->id;
|
||||
$journalData = [
|
||||
'user_id' => $entry->user->id,
|
||||
@ -187,6 +248,13 @@ class ImportStorage
|
||||
}
|
||||
Log::debug('Created journal', ['id' => $journal->id]);
|
||||
|
||||
// save hash as meta value:
|
||||
$meta = new TransactionJournalMeta;
|
||||
$meta->name = 'originalImportHash';
|
||||
$meta->data = $entry->hash;
|
||||
$meta->transactionjournal()->associate($journal);
|
||||
$meta->save();
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
@ -200,13 +268,37 @@ class ImportStorage
|
||||
private function storeSingle(int $index, ImportEntry $entry): ImportResult
|
||||
{
|
||||
if ($entry->valid === false) {
|
||||
Log::error(sprintf('Cannot import row %d, because valid=false', $index));
|
||||
Log::warning(sprintf('Cannot import row %d, because the entry is not valid.', $index));
|
||||
$result = new ImportResult();
|
||||
$result->failed();
|
||||
$result->appendError(sprintf('Cannot import row %d, because valid=false', $index));
|
||||
$errors = join(', ', $entry->errors->all());
|
||||
$errorText = sprintf('Row #%d: ' . $errors, $index);
|
||||
$result->appendError($errorText);
|
||||
$extendedStatus = $this->job->extended_status;
|
||||
$extendedStatus['errors'][] = $errorText;
|
||||
$this->job->extended_status = $extendedStatus;
|
||||
$this->job->save();
|
||||
|
||||
return $result;
|
||||
}
|
||||
$alreadyImported = $this->alreadyImported($entry->hash);
|
||||
if (!is_null($alreadyImported->id)) {
|
||||
Log::warning(sprintf('Cannot import row %d, because it has already been imported (journal #%d).', $index, $alreadyImported->id));
|
||||
$result = new ImportResult();
|
||||
$result->failed();
|
||||
$errorText = trans(
|
||||
'firefly.import_double',
|
||||
['row' => $index, 'link' => route('transactions.show', [$alreadyImported->id]), 'description' => $alreadyImported->description]
|
||||
);
|
||||
$result->appendError($errorText);
|
||||
$extendedStatus = $this->job->extended_status;
|
||||
$extendedStatus['errors'][] = $errorText;
|
||||
$this->job->extended_status = $extendedStatus;
|
||||
$this->job->save();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
Log::debug(sprintf('Going to store row %d', $index));
|
||||
|
||||
|
||||
@ -237,11 +329,21 @@ class ImportStorage
|
||||
$journal->completed = 1;
|
||||
$journal->save();
|
||||
|
||||
// attach import tag.
|
||||
$journal->tags()->save($this->importTag);
|
||||
|
||||
// now attach budget and so on.
|
||||
$this->storeBudget($journal, $entry);
|
||||
$this->storeCategory($journal, $entry);
|
||||
$this->storeBill($journal, $entry);
|
||||
|
||||
$result = new ImportResult();
|
||||
$result->success();
|
||||
$result->appendMessage(sprintf('Journal titled "%s" imported.', $journal->description));
|
||||
$result->setJournal($journal);
|
||||
|
||||
return $result;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
@ -35,6 +36,19 @@ class ImportValidator
|
||||
/** @var User */
|
||||
protected $user;
|
||||
|
||||
/** @var ImportJob */
|
||||
public $job;
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*/
|
||||
public function setJob(ImportJob $job)
|
||||
{
|
||||
$this->job = $job;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ImportValidator constructor.
|
||||
*
|
||||
@ -50,6 +64,7 @@ class ImportValidator
|
||||
*/
|
||||
public function clean(): Collection
|
||||
{
|
||||
Log::notice(sprintf('Started validating %d entry(ies).', $this->entries->count()));
|
||||
$newCollection = new Collection;
|
||||
/** @var ImportEntry $entry */
|
||||
foreach ($this->entries as $index => $entry) {
|
||||
@ -70,7 +85,9 @@ class ImportValidator
|
||||
$entry = $this->setTransactionCurrency($entry);
|
||||
|
||||
$newCollection->put($index, $entry);
|
||||
$this->job->addStepsDone(1);
|
||||
}
|
||||
Log::notice(sprintf('Finished validating %d entry(ies).', $newCollection->count()));
|
||||
|
||||
return $newCollection;
|
||||
}
|
||||
@ -100,7 +117,8 @@ class ImportValidator
|
||||
{
|
||||
if ($entry->fields['amount'] == 0) {
|
||||
$entry->valid = false;
|
||||
Log::error('Amount of transaction is zero, cannot handle.');
|
||||
$entry->errors->push('Amount of transaction is zero, cannot handle.');
|
||||
Log::warning('Amount of transaction is zero, cannot handle.');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
@ -229,7 +247,7 @@ class ImportValidator
|
||||
// default import is null? should not happen. Entry cannot be imported.
|
||||
// set error message and block.
|
||||
$entry->valid = false;
|
||||
Log::error('Cannot import entry. Asset account is NULL and import account is also NULL.');
|
||||
Log::warning('Cannot import entry. Asset account is NULL and import account is also NULL.');
|
||||
|
||||
}
|
||||
Log::debug('Asset account is OK.', ['id' => $entry->fields['asset-account']->id, 'name' => $entry->fields['asset-account']->name]);
|
||||
@ -379,8 +397,9 @@ class ImportValidator
|
||||
|
||||
return $entry;
|
||||
}
|
||||
Log::error(sprintf('Opposing account is of type %s, cannot handle this.', $type));
|
||||
Log::warning(sprintf('Opposing account is of type %s, cannot handle this.', $type));
|
||||
$entry->valid = false;
|
||||
$entry->errors->push(sprintf('Opposing account is of type %s, cannot handle this.', $type));
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
@ -54,15 +54,22 @@ class CsvImporter implements ImporterInterface
|
||||
$reader->setDelimiter($config['delimiter']);
|
||||
$start = $config['has-headers'] ? 1 : 0;
|
||||
$results = $reader->fetch();
|
||||
|
||||
Log::notice('Building importable objects from CSV file.');
|
||||
|
||||
foreach ($results as $index => $row) {
|
||||
if ($index >= $start) {
|
||||
$line = $index + 1;
|
||||
Log::debug('----- import entry build start --');
|
||||
Log::debug(sprintf('Now going to import row %d.', $index));
|
||||
$importEntry = $this->importSingleRow($index, $row);
|
||||
$this->collection->put($index, $importEntry);
|
||||
$this->collection->put($line, $importEntry);
|
||||
$this->job->addTotalSteps(3);
|
||||
$this->job->addStepsDone(1);
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Import collection contains %d entries', $this->collection->count()));
|
||||
Log::notice(sprintf('Built %d importable object(s) from your CSV file.', $this->collection->count()));
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
@ -92,6 +99,10 @@ class CsvImporter implements ImporterInterface
|
||||
$object->setUser($this->job->user);
|
||||
$config = $this->job->configuration;
|
||||
|
||||
// hash the row:
|
||||
$hash = hash('sha256', json_encode($row));
|
||||
$object->importValue('hash', 100, $hash);
|
||||
|
||||
// and this is the point where the specifix go to work.
|
||||
foreach ($config['specifics'] as $name => $enabled) {
|
||||
/** @var SpecificInterface $specific */
|
||||
|
@ -28,7 +28,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
* @property string $key
|
||||
* @property string $file_type
|
||||
* @property string $status
|
||||
* @property array $configuration
|
||||
* @property array $configuration
|
||||
* @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)
|
||||
@ -39,10 +39,21 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereStatus($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereConfiguration($value)
|
||||
* @mixin \Eloquent
|
||||
* @property string $extended_status
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\ImportJob whereExtendedStatus($value)
|
||||
*/
|
||||
class ImportJob extends Model
|
||||
{
|
||||
|
||||
protected $validStatus
|
||||
= [
|
||||
'import_status_never_started', // initial state
|
||||
'import_configuration_saved', // import configuration saved. This step is going to be obsolete.
|
||||
'settings_complete', // aka: ready for import.
|
||||
'import_running', // import currently underway
|
||||
'import_complete', // done with everything
|
||||
];
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
@ -60,6 +71,30 @@ class ImportJob extends Model
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
*/
|
||||
public function addStepsDone(int $count)
|
||||
{
|
||||
$status = $this->extended_status;
|
||||
$status['steps_done'] += $count;
|
||||
$this->extended_status = $status;
|
||||
$this->save();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
*/
|
||||
public function addTotalSteps(int $count)
|
||||
{
|
||||
$status = $this->extended_status;
|
||||
$status['total_steps'] += $count;
|
||||
$this->extended_status = $status;
|
||||
$this->save();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $status
|
||||
*/
|
||||
@ -83,6 +118,20 @@ class ImportJob extends Model
|
||||
return json_decode($value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExtendedStatusAttribute($value)
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return json_decode($value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
@ -91,6 +140,24 @@ class ImportJob extends Model
|
||||
$this->attributes['configuration'] = json_encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setExtendedStatusAttribute($value)
|
||||
{
|
||||
$this->attributes['extended_status'] = json_encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setStatusAttribute(string $value)
|
||||
{
|
||||
if (in_array($value, $this->validStatus)) {
|
||||
$this->attributes['status'] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@ -51,17 +51,32 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value)
|
||||
* @mixin \Eloquent
|
||||
* @property boolean $active
|
||||
* @property boolean $active
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereActive($value)
|
||||
*/
|
||||
class PiggyBank extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'startdate', 'targetdate'];
|
||||
protected $fillable
|
||||
= ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate'];
|
||||
protected $hidden = ['targetamount_encrypted', 'encrypted'];
|
||||
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'startdate', 'targetdate'];
|
||||
|
||||
/**
|
||||
* @param PiggyBank $value
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public static function routeBinder(PiggyBank $value)
|
||||
{
|
||||
if (Auth::check()) {
|
||||
if ($value->account->user_id == Auth::user()->id) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
@ -76,13 +91,16 @@ class PiggyBank extends Model
|
||||
*
|
||||
* @returns PiggyBankRepetition
|
||||
*/
|
||||
public function currentRelevantRep()
|
||||
public function currentRelevantRep(): PiggyBankRepetition
|
||||
{
|
||||
if (!is_null($this->currentRep)) {
|
||||
return $this->currentRep;
|
||||
}
|
||||
// repeating piggy banks are no longer supported.
|
||||
$rep = $this->piggyBankRepetitions()->first(['piggy_bank_repetitions.*']);
|
||||
$rep = $this->piggyBankRepetitions()->first(['piggy_bank_repetitions.*']);
|
||||
if (is_null($rep)) {
|
||||
return new PiggyBankRepetition();
|
||||
}
|
||||
$this->currentRep = $rep;
|
||||
|
||||
return $rep;
|
||||
@ -90,14 +108,6 @@ class PiggyBank extends Model
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function piggyBankRepetitions()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\PiggyBankRepetition');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $value
|
||||
@ -122,6 +132,14 @@ class PiggyBank extends Model
|
||||
return $this->hasMany('FireflyIII\Models\PiggyBankEvent');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function piggyBankRepetitions()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\PiggyBankRepetition');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $value
|
||||
@ -139,19 +157,4 @@ class PiggyBank extends Model
|
||||
{
|
||||
$this->attributes['targetamount'] = strval(round($value, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $value
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public static function routeBinder(PiggyBank $value)
|
||||
{
|
||||
if (Auth::check()) {
|
||||
if ($value->account->user_id == Auth::user()->id) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class TransactionJournalMeta extends Model
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function transactionjournal(): BelongsTo
|
||||
public function transactionJournal(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
@ -438,7 +438,9 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$balance = Steam::balanceIgnoreVirtual($account, $date);
|
||||
/** @var PiggyBank $p */
|
||||
foreach ($account->piggybanks()->get() as $p) {
|
||||
$balance = bcsub($balance, $p->currentRelevantRep()->currentamount);
|
||||
$currentAmount = $p->currentRelevantRep()->currentamount ?? '0';
|
||||
|
||||
$balance = bcsub($balance, $currentAmount);
|
||||
}
|
||||
|
||||
return $balance;
|
||||
|
@ -49,9 +49,16 @@ class ImportJobRepository implements ImportJobRepositoryInterface
|
||||
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->file_type = $fileType;
|
||||
$importJob->key = Str::random(12);
|
||||
$importJob->status = 'import_status_never_started';
|
||||
$importJob->extended_status = [
|
||||
'total_steps' => 0,
|
||||
'steps_done' => 0,
|
||||
'import_count' => 0,
|
||||
'importTag' => 0,
|
||||
'errors' => [],
|
||||
];
|
||||
$importJob->save();
|
||||
|
||||
// breaks the loop:
|
||||
|
@ -118,7 +118,8 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
{
|
||||
$set = $this->getPiggyBanks();
|
||||
foreach ($set as $piggy) {
|
||||
$piggy->name = $piggy->name . ' (' . Amount::format($piggy->currentRelevantRep()->currentamount, false) . ')';
|
||||
$currentAmount = $piggy->currentRelevantRep()->currentamount ?? '0';
|
||||
$piggy->name = $piggy->name . ' (' . Amount::format($currentAmount, false) . ')';
|
||||
}
|
||||
|
||||
return $set;
|
||||
|
@ -271,13 +271,14 @@ class TestData
|
||||
$insert = [];
|
||||
foreach ($this->data['import-jobs'] as $job) {
|
||||
$insert[] = [
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $job['user_id'],
|
||||
'file_type' => $job['file_type'],
|
||||
'key' => $job['key'],
|
||||
'status' => $job['status'],
|
||||
'configuration' => json_encode($job['configuration']),
|
||||
'created_at' => $this->time,
|
||||
'updated_at' => $this->time,
|
||||
'user_id' => $job['user_id'],
|
||||
'file_type' => $job['file_type'],
|
||||
'key' => $job['key'],
|
||||
'status' => $job['status'],
|
||||
'extended_status' => json_encode($job['extended_status']),
|
||||
'configuration' => json_encode($job['configuration']),
|
||||
];
|
||||
}
|
||||
DB::table('import_jobs')->insert($insert);
|
||||
|
219
composer.lock
generated
219
composer.lock
generated
@ -855,16 +855,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "5.2.41",
|
||||
"version": "v5.2.44",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "29ba2e310cfeb42ab6545bcd81ff4c2ec1f6b5c2"
|
||||
"reference": "f24b7acfb494437ef00bdd062bed61eb21535546"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/29ba2e310cfeb42ab6545bcd81ff4c2ec1f6b5c2",
|
||||
"reference": "29ba2e310cfeb42ab6545bcd81ff4c2ec1f6b5c2",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/f24b7acfb494437ef00bdd062bed61eb21535546",
|
||||
"reference": "f24b7acfb494437ef00bdd062bed61eb21535546",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -945,7 +945,7 @@
|
||||
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).",
|
||||
"symfony/css-selector": "Required to use some of the crawler integration testing tools (2.8.*|3.0.*).",
|
||||
"symfony/dom-crawler": "Required to use most of the crawler integration testing tools (2.8.*|3.0.*).",
|
||||
"symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)."
|
||||
"symfony/psr-http-message-bridge": "Required to use psr7 bridging features (0.2.*)."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -981,7 +981,7 @@
|
||||
"framework",
|
||||
"laravel"
|
||||
],
|
||||
"time": "2016-07-20 13:13:06"
|
||||
"time": "2016-08-23 13:03:29"
|
||||
},
|
||||
{
|
||||
"name": "laravelcollective/html",
|
||||
@ -1165,16 +1165,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
"version": "1.0.25",
|
||||
"version": "1.0.27",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/flysystem.git",
|
||||
"reference": "a76afa4035931be0c78ca8efc6abf3902362f437"
|
||||
"reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a76afa4035931be0c78ca8efc6abf3902362f437",
|
||||
"reference": "a76afa4035931be0c78ca8efc6abf3902362f437",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/50e2045ed70a7e75a5e30bc3662904f3b67af8a9",
|
||||
"reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1244,20 +1244,20 @@
|
||||
"sftp",
|
||||
"storage"
|
||||
],
|
||||
"time": "2016-07-18 12:22:57"
|
||||
"time": "2016-08-10 08:55:11"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "1.20.0",
|
||||
"version": "1.21.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Seldaek/monolog.git",
|
||||
"reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037"
|
||||
"reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/55841909e2bcde01b5318c35f2b74f8ecc86e037",
|
||||
"reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952",
|
||||
"reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1322,7 +1322,7 @@
|
||||
"logging",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2016-07-02 14:02:10"
|
||||
"time": "2016-07-29 03:23:52"
|
||||
},
|
||||
{
|
||||
"name": "mtdowling/cron-expression",
|
||||
@ -1680,21 +1680,21 @@
|
||||
},
|
||||
{
|
||||
"name": "rcrowe/twigbridge",
|
||||
"version": "v0.9.2",
|
||||
"version": "v0.9.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rcrowe/TwigBridge.git",
|
||||
"reference": "78a4b7da75042660258a3269751c259eee81c34a"
|
||||
"reference": "6226d33331bbb1cdf64593a786f7efd1670200a7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/78a4b7da75042660258a3269751c259eee81c34a",
|
||||
"reference": "78a4b7da75042660258a3269751c259eee81c34a",
|
||||
"url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/6226d33331bbb1cdf64593a786f7efd1670200a7",
|
||||
"reference": "6226d33331bbb1cdf64593a786f7efd1670200a7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "5.0.*|5.1.*|5.2.*",
|
||||
"illuminate/view": "5.0.*|5.1.*|5.2.*",
|
||||
"illuminate/support": "5.0.*|5.1.*|5.2.*|5.3.*",
|
||||
"illuminate/view": "5.0.*|5.1.*|5.2.*|5.3.*",
|
||||
"php": ">=5.4.0",
|
||||
"twig/twig": "~1.15|~2.0"
|
||||
},
|
||||
@ -1740,7 +1740,7 @@
|
||||
"laravel",
|
||||
"twig"
|
||||
],
|
||||
"time": "2016-02-22 07:48:48"
|
||||
"time": "2016-05-01 16:43:38"
|
||||
},
|
||||
{
|
||||
"name": "rmccue/requests",
|
||||
@ -1897,16 +1897,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "a7abb7153f6d1da47f87ec50274844e246b09d9f"
|
||||
"reference": "926061e74229e935d3c5b4e9ba87237316c6693f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/a7abb7153f6d1da47f87ec50274844e246b09d9f",
|
||||
"reference": "a7abb7153f6d1da47f87ec50274844e246b09d9f",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/926061e74229e935d3c5b4e9ba87237316c6693f",
|
||||
"reference": "926061e74229e935d3c5b4e9ba87237316c6693f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1953,20 +1953,20 @@
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 07:02:21"
|
||||
"time": "2016-07-30 07:22:48"
|
||||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/debug.git",
|
||||
"reference": "c54bc3539c3b87e86799533801e8ae0e971d78c2"
|
||||
"reference": "697c527acd9ea1b2d3efac34d9806bf255278b0a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/c54bc3539c3b87e86799533801e8ae0e971d78c2",
|
||||
"reference": "c54bc3539c3b87e86799533801e8ae0e971d78c2",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/697c527acd9ea1b2d3efac34d9806bf255278b0a",
|
||||
"reference": "697c527acd9ea1b2d3efac34d9806bf255278b0a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2010,20 +2010,20 @@
|
||||
],
|
||||
"description": "Symfony Debug Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 05:40:00"
|
||||
"time": "2016-07-30 07:22:48"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v3.1.2",
|
||||
"version": "v3.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "7f9839ede2070f53e7e2f0849b9bd14748c434c5"
|
||||
"reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7f9839ede2070f53e7e2f0849b9bd14748c434c5",
|
||||
"reference": "7f9839ede2070f53e7e2f0849b9bd14748c434c5",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c0c00c80b3a69132c4e55c3e7db32b4a387615e5",
|
||||
"reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2070,11 +2070,11 @@
|
||||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 05:41:56"
|
||||
"time": "2016-07-19 10:45:57"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
@ -2123,16 +2123,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "1341139f906d295baa4f4abd55293d07e25a065a"
|
||||
"reference": "49ba00f8ede742169cb6b70abe33243f4d673f82"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/1341139f906d295baa4f4abd55293d07e25a065a",
|
||||
"reference": "1341139f906d295baa4f4abd55293d07e25a065a",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/49ba00f8ede742169cb6b70abe33243f4d673f82",
|
||||
"reference": "49ba00f8ede742169cb6b70abe33243f4d673f82",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2172,20 +2172,20 @@
|
||||
],
|
||||
"description": "Symfony HttpFoundation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 07:02:21"
|
||||
"time": "2016-07-17 13:54:30"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-kernel.git",
|
||||
"reference": "177b63b2d50b63fa6d82ea41359ed9928cc7a1fb"
|
||||
"reference": "d97ba4425e36e79c794e7d14ff36f00f081b37b3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/177b63b2d50b63fa6d82ea41359ed9928cc7a1fb",
|
||||
"reference": "177b63b2d50b63fa6d82ea41359ed9928cc7a1fb",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/d97ba4425e36e79c794e7d14ff36f00f081b37b3",
|
||||
"reference": "d97ba4425e36e79c794e7d14ff36f00f081b37b3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2254,7 +2254,7 @@
|
||||
],
|
||||
"description": "Symfony HttpKernel Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-30 16:30:17"
|
||||
"time": "2016-07-30 09:10:37"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
@ -2425,16 +2425,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "d7cde1f9d94d87060204f863779389b61c382eeb"
|
||||
"reference": "768debc5996f599c4372b322d9061dba2a4bf505"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/d7cde1f9d94d87060204f863779389b61c382eeb",
|
||||
"reference": "d7cde1f9d94d87060204f863779389b61c382eeb",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/768debc5996f599c4372b322d9061dba2a4bf505",
|
||||
"reference": "768debc5996f599c4372b322d9061dba2a4bf505",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2470,11 +2470,11 @@
|
||||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 05:40:00"
|
||||
"time": "2016-07-28 11:13:34"
|
||||
},
|
||||
{
|
||||
"name": "symfony/routing",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/routing.git",
|
||||
@ -2549,16 +2549,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8"
|
||||
"reference": "eee6c664853fd0576f21ae25725cfffeafe83f26"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/6bf844e1ee3c820c012386c10427a5c67bbefec8",
|
||||
"reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/eee6c664853fd0576f21ae25725cfffeafe83f26",
|
||||
"reference": "eee6c664853fd0576f21ae25725cfffeafe83f26",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2609,20 +2609,20 @@
|
||||
],
|
||||
"description": "Symfony Translation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 05:40:00"
|
||||
"time": "2016-07-30 07:22:48"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-dumper.git",
|
||||
"reference": "2f046e9a9d571f22cc8b26783564876713b06579"
|
||||
"reference": "1f7e071aafc6676fcb6e3f0497f87c2397247377"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/2f046e9a9d571f22cc8b26783564876713b06579",
|
||||
"reference": "2f046e9a9d571f22cc8b26783564876713b06579",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/1f7e071aafc6676fcb6e3f0497f87c2397247377",
|
||||
"reference": "1f7e071aafc6676fcb6e3f0497f87c2397247377",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2672,7 +2672,7 @@
|
||||
"debug",
|
||||
"dump"
|
||||
],
|
||||
"time": "2016-06-29 05:40:00"
|
||||
"time": "2016-07-26 08:03:56"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
@ -2844,21 +2844,21 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "barryvdh/laravel-debugbar",
|
||||
"version": "v2.2.2",
|
||||
"version": "V2.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/barryvdh/laravel-debugbar.git",
|
||||
"reference": "c291e58d0a13953e0f68d99182ee77ebc693edc0"
|
||||
"reference": "ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/c291e58d0a13953e0f68d99182ee77ebc693edc0",
|
||||
"reference": "c291e58d0a13953e0f68d99182ee77ebc693edc0",
|
||||
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd",
|
||||
"reference": "ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "5.1.*|5.2.*",
|
||||
"maximebf/debugbar": "~1.11.0",
|
||||
"illuminate/support": "5.1.*|5.2.*|5.3.*",
|
||||
"maximebf/debugbar": "~1.11.0|~1.12.0",
|
||||
"php": ">=5.5.9",
|
||||
"symfony/finder": "~2.7|~3.0"
|
||||
},
|
||||
@ -2894,7 +2894,7 @@
|
||||
"profiler",
|
||||
"webprofiler"
|
||||
],
|
||||
"time": "2016-05-11 13:54:43"
|
||||
"time": "2016-07-29 15:00:36"
|
||||
},
|
||||
{
|
||||
"name": "barryvdh/laravel-ide-helper",
|
||||
@ -3163,16 +3163,16 @@
|
||||
},
|
||||
{
|
||||
"name": "maximebf/debugbar",
|
||||
"version": "v1.11.1",
|
||||
"version": "v1.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maximebf/php-debugbar.git",
|
||||
"reference": "d9302891c1f0a0ac5a4f66725163a00537c6359f"
|
||||
"reference": "e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/d9302891c1f0a0ac5a4f66725163a00537c6359f",
|
||||
"reference": "d9302891c1f0a0ac5a4f66725163a00537c6359f",
|
||||
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988",
|
||||
"reference": "e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3191,7 +3191,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.11-dev"
|
||||
"dev-master": "1.12-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -3220,7 +3220,7 @@
|
||||
"debug",
|
||||
"debugbar"
|
||||
],
|
||||
"time": "2016-01-22 12:22:23"
|
||||
"time": "2016-05-15 13:11:34"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
@ -3984,23 +3984,23 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
"version": "1.3.7",
|
||||
"version": "1.3.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/environment.git",
|
||||
"reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
|
||||
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
|
||||
"reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
|
||||
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
"php": "^5.3.3 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.4"
|
||||
"phpunit/phpunit": "^4.8 || ^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -4030,7 +4030,7 @@
|
||||
"environment",
|
||||
"hhvm"
|
||||
],
|
||||
"time": "2016-05-17 03:18:57"
|
||||
"time": "2016-08-18 05:49:44"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
@ -4240,16 +4240,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/class-loader",
|
||||
"version": "v3.1.2",
|
||||
"version": "v3.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/class-loader.git",
|
||||
"reference": "0d0ac77c336eb73f35bebdf3e1f3695ac741bbc9"
|
||||
"reference": "817f09b4c37b7688fa4342cb4642d8f2d81c1097"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/class-loader/zipball/0d0ac77c336eb73f35bebdf3e1f3695ac741bbc9",
|
||||
"reference": "0d0ac77c336eb73f35bebdf3e1f3695ac741bbc9",
|
||||
"url": "https://api.github.com/repos/symfony/class-loader/zipball/817f09b4c37b7688fa4342cb4642d8f2d81c1097",
|
||||
"reference": "817f09b4c37b7688fa4342cb4642d8f2d81c1097",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -4292,11 +4292,11 @@
|
||||
],
|
||||
"description": "Symfony ClassLoader Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 05:41:56"
|
||||
"time": "2016-07-10 08:05:47"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
@ -4349,16 +4349,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v3.0.8",
|
||||
"version": "v3.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dom-crawler.git",
|
||||
"reference": "62769e3409006b937bb333b29da8df9a8b262975"
|
||||
"reference": "dff8fecf1f56990d88058e3a1885c2a5f1b8e970"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/62769e3409006b937bb333b29da8df9a8b262975",
|
||||
"reference": "62769e3409006b937bb333b29da8df9a8b262975",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/dff8fecf1f56990d88058e3a1885c2a5f1b8e970",
|
||||
"reference": "dff8fecf1f56990d88058e3a1885c2a5f1b8e970",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -4401,20 +4401,20 @@
|
||||
],
|
||||
"description": "Symfony DomCrawler Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 05:40:00"
|
||||
"time": "2016-07-30 07:22:48"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v3.1.2",
|
||||
"version": "v3.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de"
|
||||
"reference": "1819adf2066880c7967df7180f4f662b6f0567ac"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de",
|
||||
"reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/1819adf2066880c7967df7180f4f662b6f0567ac",
|
||||
"reference": "1819adf2066880c7967df7180f4f662b6f0567ac",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -4450,32 +4450,33 @@
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-29 05:41:56"
|
||||
"time": "2016-07-17 14:02:08"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozart/assert.git",
|
||||
"reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde"
|
||||
"reference": "bb2d123231c095735130cc8f6d31385a44c7b308"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde",
|
||||
"reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde",
|
||||
"url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308",
|
||||
"reference": "bb2d123231c095735130cc8f6d31385a44c7b308",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
"php": "^5.3.3|^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.6"
|
||||
"phpunit/phpunit": "^4.6",
|
||||
"sebastian/version": "^1.0.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
"dev-master": "1.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -4499,7 +4500,7 @@
|
||||
"check",
|
||||
"validate"
|
||||
],
|
||||
"time": "2015-08-24 13:29:44"
|
||||
"time": "2016-08-09 15:02:57"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
@ -4,7 +4,7 @@ declare(strict_types = 1);
|
||||
|
||||
return [
|
||||
'chart' => 'chartjs',
|
||||
'version' => '3.10',
|
||||
'version' => '3.10.1',
|
||||
'csv_import_enabled' => true,
|
||||
'maxUploadSize' => 5242880,
|
||||
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
|
||||
|
@ -290,103 +290,6 @@ class CreateMainTables extends Migration
|
||||
|
||||
}
|
||||
|
||||
private function createJournalTables()
|
||||
{
|
||||
if (!Schema::hasTable('transaction_journals')) {
|
||||
Schema::create(
|
||||
'transaction_journals', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->integer('user_id', false, true);
|
||||
$table->integer('transaction_type_id', false, true);
|
||||
$table->integer('bill_id', false, true)->nullable();
|
||||
$table->integer('transaction_currency_id', false, true);
|
||||
|
||||
$table->string('description', 1024);
|
||||
|
||||
$table->date('date');
|
||||
$table->date('interest_date')->nullable();
|
||||
$table->date('book_date')->nullable();
|
||||
$table->date('process_date')->nullable();
|
||||
|
||||
$table->integer('order', false, true);
|
||||
$table->integer('tag_count', false, true);
|
||||
|
||||
$table->boolean('encrypted')->default(1);
|
||||
$table->boolean('completed')->default(1);
|
||||
|
||||
// links to other tables:
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->foreign('transaction_type_id')->references('id')->on('transaction_types')->onDelete('cascade');
|
||||
$table->foreign('bill_id')->references('id')->on('bills')->onDelete('set null');
|
||||
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('journal_meta')) {
|
||||
Schema::create(
|
||||
'journal_meta', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
$table->string('name', 255);
|
||||
$table->text('data');
|
||||
$table->string('hash', 64);
|
||||
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function createMoreJournalTables()
|
||||
{
|
||||
if (!Schema::hasTable('tag_transaction_journal')) {
|
||||
Schema::create(
|
||||
'tag_transaction_journal', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('tag_id', false, true);
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
|
||||
$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('budget_transaction_journal')) {
|
||||
Schema::create(
|
||||
'budget_transaction_journal', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('budget_id', false, true);
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
|
||||
$table->foreign('budget_id')->references('id')->on('budgets')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('category_transaction_journal')) {
|
||||
Schema::create(
|
||||
'category_transaction_journal', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('category_id', false, true);
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
|
||||
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -401,8 +304,8 @@ class CreateMainTables extends Migration
|
||||
$table->integer('account_id', false, true);
|
||||
$table->string('name', 1024);
|
||||
$table->decimal('targetamount', 10, 4);
|
||||
$table->date('startdate');
|
||||
$table->date('targetdate');
|
||||
$table->date('startdate')->nullable();
|
||||
$table->date('targetdate')->nullable();
|
||||
$table->integer('order', false, true);
|
||||
$table->boolean('active')->default(0);
|
||||
$table->boolean('encrypted')->default(1);
|
||||
@ -419,8 +322,8 @@ class CreateMainTables extends Migration
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->integer('piggy_bank_id', false, true);
|
||||
$table->date('startdate');
|
||||
$table->date('targetdate');
|
||||
$table->date('startdate')->nullable();
|
||||
$table->date('targetdate')->nullable();
|
||||
$table->decimal('currentamount', 10, 4);
|
||||
|
||||
$table->foreign('piggy_bank_id')->references('id')->on('piggy_banks')->onDelete('cascade');
|
||||
@ -594,8 +497,95 @@ class CreateMainTables extends Migration
|
||||
*/
|
||||
private function createTransactionTables()
|
||||
{
|
||||
$this->createJournalTables();
|
||||
$this->createMoreJournalTables();
|
||||
if (!Schema::hasTable('transaction_journals')) {
|
||||
Schema::create(
|
||||
'transaction_journals', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->integer('user_id', false, true);
|
||||
$table->integer('transaction_type_id', false, true);
|
||||
$table->integer('bill_id', false, true)->nullable();
|
||||
$table->integer('transaction_currency_id', false, true);
|
||||
|
||||
$table->string('description', 1024);
|
||||
|
||||
$table->date('date');
|
||||
$table->date('interest_date')->nullable();
|
||||
$table->date('book_date')->nullable();
|
||||
$table->date('process_date')->nullable();
|
||||
|
||||
$table->integer('order', false, true);
|
||||
$table->integer('tag_count', false, true);
|
||||
|
||||
$table->boolean('encrypted')->default(1);
|
||||
$table->boolean('completed')->default(1);
|
||||
|
||||
// links to other tables:
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->foreign('transaction_type_id')->references('id')->on('transaction_types')->onDelete('cascade');
|
||||
$table->foreign('bill_id')->references('id')->on('bills')->onDelete('set null');
|
||||
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('journal_meta')) {
|
||||
Schema::create(
|
||||
'journal_meta', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
$table->string('name', 255);
|
||||
$table->text('data');
|
||||
$table->string('hash', 64);
|
||||
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('tag_transaction_journal')) {
|
||||
Schema::create(
|
||||
'tag_transaction_journal', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('tag_id', false, true);
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
|
||||
$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('budget_transaction_journal')) {
|
||||
Schema::create(
|
||||
'budget_transaction_journal', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('budget_id', false, true);
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
|
||||
$table->foreign('budget_id')->references('id')->on('budgets')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('category_transaction_journal')) {
|
||||
Schema::create(
|
||||
'category_transaction_journal', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('category_id', false, true);
|
||||
$table->integer('transaction_journal_id', false, true);
|
||||
|
||||
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (!Schema::hasTable('piggy_bank_events')) {
|
||||
@ -645,7 +635,7 @@ class CreateMainTables extends Migration
|
||||
);
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('')) {
|
||||
if (!Schema::hasTable('category_transaction')) {
|
||||
Schema::create(
|
||||
'category_transaction', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
|
34
database/migrations/2016_08_25_091522_changes_for_3101.php
Normal file
34
database/migrations/2016_08_25_091522_changes_for_3101.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
/**
|
||||
* Class ChangesFor3101
|
||||
*/
|
||||
class ChangesFor3101 extends Migration
|
||||
{
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table(
|
||||
'import_jobs', function (Blueprint $table) {
|
||||
$table->text('extended_status');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
189
public/js/ff/import/status.js
Normal file
189
public/js/ff/import/status.js
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* status.js
|
||||
* 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.
|
||||
*/
|
||||
/* globals $, jobImportUrl, jobStartUrl, token, langImportMultiError, langImportSingleError, langImportFatalError, langImportTimeOutError */
|
||||
|
||||
|
||||
var startedImport = false;
|
||||
var startInterval = 2000;
|
||||
var interval = 500;
|
||||
var timeoutLimit = 5000;
|
||||
var currentLimit = 0;
|
||||
var stepCount = 0;
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
$('#import-status-intro').hide();
|
||||
$('#import-status-more-info').hide();
|
||||
|
||||
// check status, every 500 ms.
|
||||
setTimeout(checkImportStatus, startInterval);
|
||||
|
||||
});
|
||||
|
||||
|
||||
function checkImportStatus() {
|
||||
"use strict";
|
||||
console.log('checkImportStatus()');
|
||||
$.getJSON(jobImportUrl).success(reportOnJobImport).fail(failedJobImport);
|
||||
}
|
||||
|
||||
function importComplete(data) {
|
||||
"use strict";
|
||||
console.log('importComplete()');
|
||||
var bar = $('#import-status-bar');
|
||||
bar.removeClass('active');
|
||||
}
|
||||
|
||||
function updateBar(data) {
|
||||
"use strict";
|
||||
console.log('updateBar()');
|
||||
var bar = $('#import-status-bar');
|
||||
if (data.showPercentage) {
|
||||
bar.addClass('progress-bar-success').removeClass('progress-bar-info');
|
||||
bar.attr('aria-valuenow', data.percentage);
|
||||
bar.css('width', data.percentage + '%');
|
||||
$('#import-status-bar').text(data.stepsDone + '/' + data.steps);
|
||||
|
||||
if (data.percentage >= 100) {
|
||||
importComplete(data);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// dont show percentage:
|
||||
bar.removeClass('progress-bar-success').addClass('progress-bar-info');
|
||||
bar.attr('aria-valuenow', 100);
|
||||
bar.css('width', '100%');
|
||||
}
|
||||
|
||||
function reportErrors(data) {
|
||||
"use strict";
|
||||
console.log('reportErrors()');
|
||||
if (data.errors.length == 1) {
|
||||
$('#import-status-error-intro').text(langImportSingleError);
|
||||
//'An error has occured during the import. The import can continue, however.'
|
||||
}
|
||||
if (data.errors.length > 1) {
|
||||
// 'Errors have occured during the import. The import can continue, however.'
|
||||
$('#import-status-error-intro').text(langImportMultiError);
|
||||
}
|
||||
|
||||
// fill the list with error texts
|
||||
$('#import-status-error-list').empty();
|
||||
for (var i = 0; i < data.errors.length; i++) {
|
||||
var item = $('<li>').html(data.errors[i]);
|
||||
$('#import-status-error-list').append(item);
|
||||
}
|
||||
}
|
||||
|
||||
function reportStatus(data) {
|
||||
"use strict";
|
||||
console.log('reportStatus()');
|
||||
$('#import-status-txt').removeClass('text-danger').text(data.statusText);
|
||||
}
|
||||
|
||||
function kickStartJob() {
|
||||
"use strict";
|
||||
console.log('kickStartJob()');
|
||||
$.post(jobStartUrl, {_token: token});
|
||||
startedTheImport();
|
||||
startedImport = true;
|
||||
}
|
||||
|
||||
function updateTimeout(data) {
|
||||
"use strict";
|
||||
console.log('updateTimeout()');
|
||||
if (data.stepsDone != stepCount) {
|
||||
stepCount = data.stepsDone;
|
||||
currentLimit = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
currentLimit = currentLimit + interval;
|
||||
// console.log("stepCount: " + stepCount + ", stepsDone: " + data.stepsDone + ", currentLimit: " + currentLimit);
|
||||
}
|
||||
|
||||
function timeoutError() {
|
||||
"use strict";
|
||||
console.log('timeoutError()');
|
||||
// set status
|
||||
$('#import-status-txt').addClass('text-danger').text(langImportTimeOutError);
|
||||
|
||||
// remove progress bar.
|
||||
$('#import-status-holder').hide();
|
||||
|
||||
}
|
||||
|
||||
function importJobFinished(data) {
|
||||
"use strict";
|
||||
console.log('importJobFinished() = ' + data.finished);
|
||||
return data.finished;
|
||||
}
|
||||
|
||||
function finishedJob(data) {
|
||||
"use strict";
|
||||
console.log('finishedJob()');
|
||||
// "There was an error during the import routine. Please check the log files. The error seems to be: '"
|
||||
$('#import-status-txt').removeClass('text-danger').addClass('text-success').text(langImportFinished);
|
||||
|
||||
// remove progress bar.
|
||||
$('#import-status-holder').hide();
|
||||
|
||||
// show info:
|
||||
$('#import-status-intro').show();
|
||||
$('#import-status-more-info').html(data.finishedText).show();
|
||||
|
||||
}
|
||||
|
||||
function reportOnJobImport(data) {
|
||||
"use strict";
|
||||
console.log('reportOnJobImport()');
|
||||
updateBar(data);
|
||||
reportErrors(data);
|
||||
reportStatus(data);
|
||||
updateTimeout(data);
|
||||
|
||||
if (importJobFinished(data)) {
|
||||
finishedJob(data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// same number of steps as last time?
|
||||
if (currentLimit > timeoutLimit) {
|
||||
timeoutError();
|
||||
return;
|
||||
}
|
||||
|
||||
// if the job has not actually started, do so now:
|
||||
if (!data.started && !startedImport) {
|
||||
kickStartJob();
|
||||
return;
|
||||
}
|
||||
|
||||
// trigger another check.
|
||||
setTimeout(checkImportStatus, interval);
|
||||
|
||||
}
|
||||
|
||||
function startedTheImport() {
|
||||
"use strict";
|
||||
console.log('startedTheImport()');
|
||||
setTimeout(checkImportStatus, interval);
|
||||
}
|
||||
|
||||
function failedJobImport(jqxhr, textStatus, error) {
|
||||
"use strict";
|
||||
console.log('failedJobImport()');
|
||||
// set status
|
||||
// "There was an error during the import routine. Please check the log files. The error seems to be: '"
|
||||
$('#import-status-txt').addClass('text-danger').text(langImportFatalError + ' ' + textStatus + ' ' + error);
|
||||
|
||||
// remove progress bar.
|
||||
$('#import-status-holder').hide();
|
||||
}
|
@ -767,8 +767,10 @@ return [
|
||||
'configure_import' => 'Further configure your import',
|
||||
'import_finish_configuration' => 'Finish configuration',
|
||||
'settings_for_import' => 'Settings',
|
||||
'import_status' => 'Import status',
|
||||
'import_status_text' => 'The import is currently running, or will start momentarily.',
|
||||
'import_complete' => 'Import configuration complete!',
|
||||
'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you need to execute the following command in your console. Unfortunately, a web-based import is not yet possible.',
|
||||
'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.',
|
||||
'import_download_config' => 'Download configuration',
|
||||
'import_start_import' => 'Start import',
|
||||
'import_intro_beta' => 'The import function of Firefly III is in beta. Many users of Firefly III have tried many different files. Although each individual compontent of this import routine works (really), the combination might break. If your file cannot be imported by Firefly, please read <a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">this wiki page</a> so I can fix the problem you have run into.',
|
||||
@ -777,4 +779,20 @@ return [
|
||||
'import' => 'Import',
|
||||
'import_intro_text' => 'Welcome to the Firefly III data import routine. At the moment, this routine can help you import files into Firefly. To do so, you must download or export transactions from other systems or software, and upload them here. The next steps will let you help Firefly III determin what the content is of your file, and how to handle it. Please select a file, and read all instructions carefully.',
|
||||
'import_file_help' => 'Select your file',
|
||||
'import_status_settings_complete' => 'The import is ready to start.',
|
||||
'import_status_import_complete' => 'The import has completed.',
|
||||
'import_status_import_running' => 'The import is currently running. Please be patient.',
|
||||
'import_status_header' => 'Import status and progress',
|
||||
'import_status_errors' => 'Import errors',
|
||||
'import_status_report' => 'Import report',
|
||||
'import_finished' => 'Import has finished',
|
||||
'import_error_single' => 'An error has occured during the import.',
|
||||
'import_error_multi' => 'Some errors occured during the import.',
|
||||
'import_error_fatal' => 'There was an error during the import routine. Please check the log files. The error seems to be:',
|
||||
'import_error_timeout' => 'The import seems to have timed out. If this error persists, please import your data using the console command.',
|
||||
'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.',
|
||||
'import_finished_all' => 'The import has finished. Please check out the results below.',
|
||||
'import_with_key' => 'Import with key \':key\'',
|
||||
'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ',
|
||||
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
|
||||
];
|
||||
|
@ -22,7 +22,7 @@
|
||||
<a href="{{ route('import.download', [job.key]) }}" class="btn btn-default"><i class="fa fa-fw fa-download"></i> {{ 'import_download_config'|_ }}</a>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<!-- <a href="#" class="btn btn-default"><i class="fa fa-fw fa-gears"></i> {{ 'import_start_import'|_ }}</a>-->
|
||||
<a href="{{ route('import.status', [job.key]) }}" class="btn btn-success"><i class="fa fa-fw fa-gears"></i> {{ 'import_start_import'|_ }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
25
resources/views/import/finished.twig
Normal file
25
resources/views/import/finished.twig
Normal file
@ -0,0 +1,25 @@
|
||||
{% extends "./layout/default.twig" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ Breadcrumbs.renderIfExists }}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'import_finished'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
|
||||
This import has beeen done. Link to tag or set of transactions.
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
{% block styles %}
|
||||
{% endblock %}
|
77
resources/views/import/status.twig
Normal file
77
resources/views/import/status.twig
Normal file
@ -0,0 +1,77 @@
|
||||
{% extends "./layout/default.twig" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ Breadcrumbs.renderIfExists }}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'import_status_header'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="progress" id="import-status-holder">
|
||||
<div id="import-status-bar" class="progress-bar progress-bar-info active progress-bar-striped" role="progressbar"
|
||||
aria-valuenow="100" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: 100%">
|
||||
</div>
|
||||
</div>
|
||||
<p id="import-status-txt">{{ 'import_status_settings_complete'|_ }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
||||
<div class="box box-danger">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'import_status_errors'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<p id="import-status-error-intro">
|
||||
No errors detected.
|
||||
</p>
|
||||
<ul id="import-status-error-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'import_status_report'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<p id="import-status-intro">
|
||||
{{ 'import_finished_report'|_ }}
|
||||
</p>
|
||||
<p id="import-status-more-info"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script type="text/javascript">
|
||||
|
||||
// some useful translations.
|
||||
var langImportSingleError = '{{ 'import_error_single'|_ }}';
|
||||
var langImportMultiError = '{{ 'import_error_multi'|_ }}';
|
||||
var langImportFatalError = '{{ 'import_error_fatal'|_ }}';
|
||||
var langImportTimeOutError = '{{ 'import_error_timeout'|_ }}';
|
||||
var langImportFinished = '{{ 'import_finished_all'|_ }}';
|
||||
|
||||
var jobKey = '{{ job.key }}';
|
||||
var jobImportUrl = '{{ route('import.json', [job.key]) }}';
|
||||
var jobStartUrl = '{{ route('import.start', [job.key]) }}';
|
||||
var token = '{{ csrf_token() }}';
|
||||
</script>
|
||||
<script type="text/javascript" src="js/ff/import/status.js"></script>
|
||||
{% endblock %}
|
||||
{% block styles %}
|
||||
{% endblock %}
|
@ -5,7 +5,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ Form.open({'class' : 'form-horizontal','id' : 'store','url' : route('piggy-banks.post-add-mobile', piggyBank.id)}) }}
|
||||
{{ Form.open({'class' : 'form-horizontal','id' : 'store','url' : route('piggy-banks.add', piggyBank.id)}) }}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box box-primary">
|
||||
|
40
resources/views/piggy-banks/remove-mobile.twig
Normal file
40
resources/views/piggy-banks/remove-mobile.twig
Normal file
@ -0,0 +1,40 @@
|
||||
{% extends "./layout/default.twig" %}
|
||||
{% block breadcrumbs %}
|
||||
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form id="remove" class="form-horizontal" action="{{ route('piggy-banks.remove', piggyBank.id) }}" method="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ trans('firefly.remove_money_from_piggy_title', {name: piggyBank.name}) }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
|
||||
<p>
|
||||
{{ 'max_amount_remove'|_ }}: {{ currentRelevantRepAmount(piggyBank)|formatAmount }}.
|
||||
</p>
|
||||
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">{{ getCurrencySymbol()|raw }}</div>
|
||||
<input step="any" class="form-control" id="amount" autocomplete="off" name="amount" max="{{ currentRelevantRepAmount(piggyBank) }}"
|
||||
type="number"/>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<button type="submit" class="btn btn-success pull-right">
|
||||
{{ 'remove'|_ }}
|
||||
</button>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
@ -96,6 +96,13 @@
|
||||
"key": "testImport",
|
||||
"file_type": "csv",
|
||||
"status": "settings_complete",
|
||||
"extended_status": {
|
||||
"steps_done": 0,
|
||||
"total_steps": 0,
|
||||
"errors": [],
|
||||
"import_count": 0,
|
||||
"importTag": 0
|
||||
},
|
||||
"configuration": {
|
||||
"has-headers": false,
|
||||
"date-format": "Ymd",
|
||||
|
Loading…
Reference in New Issue
Block a user