Merge branch 'release/4.6.2'

This commit is contained in:
James Cole 2017-07-08 09:55:44 +02:00
commit e82deddefb
123 changed files with 1070 additions and 937 deletions

View File

@ -2,6 +2,12 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [4.6.2] - 2017-07-08
### Added
- Links added to boxes, idea by @simonsmiley
### Fixed
- Various bugs in import routine
## [4.6.1] - 2017-07-02
### Fixed

View File

@ -16,9 +16,7 @@ namespace FireflyIII\Console\Commands;
use FireflyIII\Import\Logging\CommandHandler;
use FireflyIII\Import\Routine\ImportRoutine;
use FireflyIII\Models\ImportJob;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
use Log;

View File

@ -163,7 +163,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
/** @var Transaction $journal */
foreach ($journals as $transaction) {
$transaction->before = $startBalance;
$transactionAmount = $transaction->transaction_amount;
$transactionAmount = $transaction->transaction_amount;
if ($currency->id === $transaction->foreign_currency_id) {
$transactionAmount = $transaction->transaction_foreign_amount;

View File

@ -53,4 +53,4 @@ class AmountFilter implements FilterInterface
}
);
}
}
}

View File

@ -31,4 +31,4 @@ class EmptyFilter implements FilterInterface
{
return $set;
}
}
}

View File

@ -23,4 +23,4 @@ interface FilterInterface
*/
public function filter(Collection $set): Collection;
}
}

View File

@ -70,4 +70,4 @@ class InternalTransferFilter implements FilterInterface
}
}
}

View File

@ -44,4 +44,4 @@ class NegativeAmountFilter implements FilterInterface
}
);
}
}
}

View File

@ -60,4 +60,4 @@ class OpposingAccountFilter implements FilterInterface
}
);
}
}
}

View File

@ -47,4 +47,4 @@ class PositiveAmountFilter implements FilterInterface
}
);
}
}
}

View File

@ -55,4 +55,4 @@ class TransferFilter implements FilterInterface
return $new;
}
}
}

View File

@ -196,4 +196,4 @@ class PopupReport implements PopupReportInterface
return $journals;
}
}
}

View File

@ -80,4 +80,4 @@ interface PopupReportInterface
* @return Collection
*/
public function byIncome(Account $account, array $attributes): Collection;
}
}

View File

@ -105,7 +105,6 @@ class AttachmentController extends Controller
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
/** @var LaravelResponse $response */
$response = response($content, 200);
$response

View File

@ -364,4 +364,4 @@ class TagReportController extends Controller
return $grouped;
}
}
}

View File

@ -246,7 +246,7 @@ class ImportController extends Controller
/** @var ImportRoutine $routine */
$routine = app(ImportRoutine::class);
$routine->setJob($job);
$result = $routine->run();
$result = $routine->run();
if ($result) {
return Response::json(['run' => 'ok']);
}

View File

@ -62,4 +62,4 @@ class ExchangeController extends Controller
return Response::json($return);
}
}
}

View File

@ -329,8 +329,8 @@ class PiggyBankController extends Controller
Session::flash(
'error', strval(
trans('firefly.cannot_remove_from_piggy', ['amount' => Amount::formatAnything($currency, $amount, false), 'name' => e($piggyBank->name)])
)
trans('firefly.cannot_remove_from_piggy', ['amount' => Amount::formatAnything($currency, $amount, false), 'name' => e($piggyBank->name)])
)
);
return redirect(route('piggy-banks.index'));
@ -397,7 +397,7 @@ class PiggyBankController extends Controller
// @codeCoverageIgnoreEnd
}
return redirect($this->getPreviousUri('piggy-banks.edit.uri'));
return redirect($this->getPreviousUri('piggy-banks.create.uri'));
}
/**

View File

@ -120,7 +120,7 @@ class CategoryController extends Controller
foreach ($categories as $category) {
$spent = $repository->spentInPeriod(new Collection([$category]), $accounts, $start, $end);
if (bccomp($spent, '0') !== 0) {
$report[$category->id] = ['name' => $category->name, 'spent' => $spent,'id' => $category->id];
$report[$category->id] = ['name' => $category->name, 'spent' => $spent, 'id' => $category->id];
}
}

View File

@ -21,6 +21,7 @@ use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@ -90,39 +91,42 @@ class SingleController extends Controller
public function cloneTransaction(TransactionJournal $journal)
{
$source = $journal->sourceAccountList()->first();
$destination = $journal->destinationAccountList()->first();
$budget = $journal->budgets()->first();
$budgetId = is_null($budget) ? 0 : $budget->id;
$category = $journal->categories()->first();
$categoryName = is_null($category) ? '' : $category->name;
$tags = join(',', $journal->tags()->get()->pluck('tag')->toArray());
$source = $journal->sourceAccountList()->first();
$destination = $journal->destinationAccountList()->first();
$budget = $journal->budgets()->first();
$budgetId = is_null($budget) ? 0 : $budget->id;
$category = $journal->categories()->first();
$categoryName = is_null($category) ? '' : $category->name;
$tags = join(',', $journal->tags()->get()->pluck('tag')->toArray());
/** @var Transaction $transaction */
$transaction = $journal->transactions()->first();
$amount = Steam::positive($transaction->amount);
$foreignAmount = is_null($transaction->foreign_amount) ? null : Steam::positive($transaction->foreign_amount);
$preFilled = [
'description' => $journal->description,
'source_account_id' => $source->id,
'source_account_name' => $source->name,
'destination_account_id' => $destination->id,
'destination_account_name' => $destination->name,
'amount' => $amount,
'source_amount' => $amount,
'destination_amount' => $foreignAmount,
'foreign_amount' => $foreignAmount,
'date' => $journal->date->format('Y-m-d'),
'budget_id' => $budgetId,
'category' => $categoryName,
'tags' => $tags,
'interest_date' => $journal->getMeta('interest_date'),
'book_date' => $journal->getMeta('book_date'),
'process_date' => $journal->getMeta('process_date'),
'due_date' => $journal->getMeta('due_date'),
'payment_date' => $journal->getMeta('payment_date'),
'invoice_date' => $journal->getMeta('invoice_date'),
'internal_reference' => $journal->getMeta('internal_reference'),
'notes' => $journal->getMeta('notes'),
'description' => $journal->description,
'source_account_id' => $source->id,
'source_account_name' => $source->name,
'destination_account_id' => $destination->id,
'destination_account_name' => $destination->name,
'amount' => $amount,
'source_amount' => $amount,
'destination_amount' => $foreignAmount,
'foreign_amount' => $foreignAmount,
'native_amount' => $foreignAmount,
'amount_currency_id_amount' => $transaction->foreign_currency_id ?? 0,
'date' => $journal->date->format('Y-m-d'),
'budget_id' => $budgetId,
'category' => $categoryName,
'tags' => $tags,
'interest_date' => $journal->getMeta('interest_date'),
'book_date' => $journal->getMeta('book_date'),
'process_date' => $journal->getMeta('process_date'),
'due_date' => $journal->getMeta('due_date'),
'payment_date' => $journal->getMeta('payment_date'),
'invoice_date' => $journal->getMeta('invoice_date'),
'internal_reference' => $journal->getMeta('internal_reference'),
'notes' => $journal->getMeta('notes'),
];
Session::flash('preFilled', $preFilled);

View File

@ -86,7 +86,7 @@ class TransactionController extends Controller
$first = $repository->first();
$start = $first->date ?? new Carbon;
$end = new Carbon;
$path = '/transactions/'.$what.'/all/';
$path = '/transactions/' . $what . '/all/';
}
// prep for "specific date" view.

View File

@ -34,13 +34,6 @@ interface ConfiguratorInterface
*/
public function configureJob(array $data): bool;
/**
* @param ImportJob $job
*
* @return void
*/
public function setJob(ImportJob $job);
/**
* Return the data required for the next step in the job configuration.
*
@ -62,4 +55,11 @@ interface ConfiguratorInterface
*/
public function isJobConfigured(): bool;
}
/**
* @param ImportJob $job
*
* @return void
*/
public function setJob(ImportJob $job);
}

View File

@ -156,4 +156,4 @@ class CsvConfigurator implements ConfiguratorInterface
return $class;
}
}
}

View File

@ -232,4 +232,4 @@ class CsvProcessor implements FileProcessorInterface
return $row;
}
}
}

View File

@ -39,4 +39,4 @@ interface FileProcessorInterface
* @return FileProcessorInterface
*/
public function setJob(ImportJob $job): FileProcessorInterface;
}
}

View File

@ -67,6 +67,22 @@ class ImportAccount
return $this->account;
}
/**
* @return string
*/
public function getExpectedType(): string
{
return $this->expectedType;
}
/**
* @param string $expectedType
*/
public function setExpectedType(string $expectedType)
{
$this->expectedType = $expectedType;
}
/**
* @param array $accountIban
*/
@ -99,14 +115,6 @@ class ImportAccount
$this->accountNumber = $accountNumber;
}
/**
* @param string $expectedType
*/
public function setExpectedType(string $expectedType)
{
$this->expectedType = $expectedType;
}
/**
* @param User $user
*/
@ -241,6 +249,16 @@ class ImportAccount
$search = intval($array['mapped']);
$account = $this->repository->find($search);
if ($account->accountType->type !== $this->expectedType) {
Log::error(
sprintf(
'Mapped account #%d is of type "%s" but we expect a "%s"-account. Mapping will be ignored.', $account->id, $account->accountType->type,
$this->expectedType
)
);
return new Account;
}
Log::debug(sprintf('Found account! #%d ("%s"). Return it', $account->id, $account->name));
return $account;
@ -296,4 +314,4 @@ class ImportAccount
}
}
}

View File

@ -225,4 +225,4 @@ class ImportBill
return true;
}
}
}

View File

@ -226,4 +226,4 @@ class ImportBudget
}
}
}

View File

@ -30,33 +30,17 @@ class ImportCategory
private $repository;
/** @var User */
private $user;
/**
* @param array $id
*/
public function setId(array $id)
{
$this->id = $id;
}
/**
* ImportCategory constructor.
*/
public function __construct()
{
$this->category = new Category();
$this->category = new Category();
$this->repository = app(CategoryRepositoryInterface::class);
Log::debug('Created ImportCategory.');
}
/**
* @param array $name
*/
public function setName(array $name)
{
$this->name = $name;
}
/**
* @return Category
*/
@ -68,6 +52,23 @@ class ImportCategory
return $this->category;
}
/**
* @param array $id
*/
public function setId(array $id)
{
$this->id = $id;
}
/**
* @param array $name
*/
public function setName(array $name)
{
$this->name = $name;
}
/**
* @param User $user
*/
@ -100,7 +101,7 @@ class ImportCategory
if (count($this->name) === 3) {
/** @var Collection $categories */
$categories = $this->repository->getCategories();
$name = $this->name['value'];
$name = $this->name['value'];
Log::debug(sprintf('Finding category with name %s', $name));
$filtered = $categories->filter(
function (Category $category) use ($name) {
@ -219,4 +220,4 @@ class ImportCategory
}
}
}

View File

@ -53,7 +53,7 @@ class ImportCurrency
}
Log::debug('In createCurrency()');
// check if any of them is mapped:
$mapped = $this->findMappedObject();
$mapped = $this->findMappedObject();
if (!is_null($mapped->id)) {
@ -77,7 +77,7 @@ class ImportCurrency
'decimal_places' => 2,
];
if (is_null($data['code'])) {
Log::info('Need at least a code to create currency, return nothing.');
Log::debug('Need at least a code to create currency, return nothing.');
return new TransactionCurrency();
}
@ -215,4 +215,4 @@ class ImportCurrency
}
}
}

View File

@ -19,6 +19,8 @@ use FireflyIII\Import\Converter\ConverterInterface;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\User;
use Illuminate\Support\Collection;
use InvalidArgumentException;
use Log;
use Steam;
/**
@ -30,22 +32,26 @@ class ImportJournal
{
/** @var ImportAccount */
public $asset;
/** @var ImportBill */
public $bill;
/** @var ImportBudget */
public $budget;
/** @var ImportCategory */
public $category;
/** @var string */
public $description = '';
/** @var Collection */
public $errors;
/** @var string */
public $hash;
/** @var array */
public $metaDates = [];
/** @var string */
public $notes = '';
/** @var ImportAccount */
public $opposing;
/** @var string */
private $amount = '0';
/** @var ImportBill */
public $bill;
/** @var ImportCategory */
public $category;
/** @var ImportCurrency */
private $currency;
/** @var string */
@ -54,16 +60,10 @@ class ImportJournal
private $externalId = '';
/** @var array */
private $modifiers = [];
/** @var array */
private $tags = [];
/** @var string */
public $notes = '';
/** @var string */
private $transactionType = '';
/** @var array */
private $tags = [];
/** @var User */
private $user;
/** @var array */
public $metaDates = [];
/**
* ImportEntry constructor.
@ -133,7 +133,15 @@ class ImportJournal
*/
public function getDate(string $format): Carbon
{
return Carbon::createFromFormat($format, $this->date);
$date = new Carbon;
try {
$date = Carbon::createFromFormat($format, $this->date);
} catch (InvalidArgumentException $e) {
// don't care, just log.
Log::error(sprintf('Import journal cannot parse date "%s" from value "%s" so will return current date instead.', $format, $this->date));
}
return $date;
}
/**
@ -223,7 +231,7 @@ class ImportJournal
case 'sepa-ct-op':
case 'sepa-ct-id':
case 'sepa-db':
$this->notes .= ' '.$array['value'];
$this->notes .= ' ' . $array['value'];
$this->notes = trim($this->notes);
break;
case 'external-id':
@ -262,4 +270,4 @@ class ImportJournal
break;
}
}
}
}

View File

@ -1,157 +0,0 @@
<?php
/**
* ImportTransaction.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Import\Object;
use FireflyIII\Import\Converter\ConverterInterface;
use Steam;
class ImportTransaction
{
/** @var string */
private $amount;
/** @var ImportCurrency */
private $currency;
/** @var string */
private $date;
/** @var string */
private $description;
private $modifiers = [];
/** @var bool */
private $positive = true;
public function __construct()
{
$this->currency = new ImportCurrency;
}
public function addToModifier(array $modifier)
{
$this->modifiers[] = $modifier;
}
/**
* @return string
*/
public function getAmount(): string
{
// use converter:
$this->amount = strval($this->parseAmount());
// also apply modifiers:
$this->amount = Steam::positive($this->amount);
// Can handle ING
foreach ($this->modifiers as $modifier) {
$class = sprintf('FireflyIII\Import\Converter\%s', config(sprintf('csv.import_roles.%s.converter', $modifier['role'])));
/** @var ConverterInterface $converter */
$converter = app($class);
if ($converter->convert($modifier['value']) === -1) {
$this->amount = Steam::negative($this->amount);
}
}
return $this->amount;
}
/**
* @param string $amount
*/
public function setAmount(string $amount)
{
$this->amount = $amount;
}
/**
* @return ImportCurrency
*/
public function getCurrency(): ImportCurrency
{
return $this->currency;
}
/**
* @param ImportCurrency $currency
*/
public function setCurrency(ImportCurrency $currency)
{
$this->currency = $currency;
}
/**
* @param string $date
*/
public function setDate(string $date)
{
$this->date = $date;
}
/**
* @param string $description
*/
public function setDescription(string $description)
{
$this->description = $description;
}
/**
* @param bool $positive
*/
public function setPositive(bool $positive)
{
$this->positive = $positive;
}
/**
* Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
* - Jamie Zawinski
*
* @return float
*/
private function parseAmount()
{
$value = $this->amount;
$len = strlen($value);
$decimalPosition = $len - 3;
$decimal = null;
if (($len > 2 && $value{$decimalPosition} == '.') || ($len > 2 && strpos($value, '.') > $decimalPosition)) {
$decimal = '.';
}
if ($len > 2 && $value{$decimalPosition} == ',') {
$decimal = ',';
}
// if decimal is dot, replace all comma's and spaces with nothing. then parse as float (round to 4 pos)
if ($decimal === '.') {
$search = [',', ' '];
$value = str_replace($search, '', $value);
}
if ($decimal === ',') {
$search = ['.', ' '];
$value = str_replace($search, '', $value);
$value = str_replace(',', '.', $value);
}
if (is_null($decimal)) {
// replace all:
$search = ['.', ' ', ','];
$value = str_replace($search, '', $value);
}
return round(floatval($value), 12);
}
}

View File

@ -44,15 +44,6 @@ class ImportRoutine
$this->errors = new Collection;
}
/**
* @param ImportJob $job
*/
public function setJob(ImportJob $job)
{
$this->job = $job;
}
/**
*
*/
@ -86,9 +77,18 @@ class ImportRoutine
Log::info(sprintf('Done with import job %s', $this->job->key));
return true;
}
/**
* @param ImportJob $job
*/
public function setJob(ImportJob $job)
{
$this->job = $job;
}
/**
* @return Collection
*/
@ -163,4 +163,4 @@ class ImportRoutine
return $storage;
}
}
}

View File

@ -27,9 +27,9 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Rules\Processor;
use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
use Log;
use Steam;
@ -44,6 +44,8 @@ class ImportStorage
/** @var Collection */
public $errors;
public $journals;
/** @var CurrencyRepositoryInterface */
private $currencyRepository;
/** @var string */
private $dateFormat = 'Ymd';
/** @var TransactionCurrency */
@ -78,8 +80,11 @@ class ImportStorage
*/
public function setJob(ImportJob $job)
{
$this->job = $job;
$this->rules = $this->getUserRules();
$this->job = $job;
$repository = app(CurrencyRepositoryInterface::class);
$repository->setUser($job->user);
$this->currencyRepository = $repository;
$this->rules = $this->getUserRules();
}
/**
@ -107,6 +112,7 @@ class ImportStorage
$this->storeImportJournal($index, $object);
} catch (FireflyException $e) {
$this->errors->push($e->getMessage());
Log::error(sprintf('Cannot import row #%d because: %s', $index, $e->getMessage()));
}
}
@ -168,13 +174,23 @@ class ImportStorage
*
* @return TransactionCurrency
*/
private function getCurrency(ImportJournal $importJournal): TransactionCurrency
private function getCurrency(ImportJournal $importJournal, Account $account): TransactionCurrency
{
$currency = $importJournal->getCurrency()->getTransactionCurrency();
if (is_null($currency->id)) {
$currency = $this->defaultCurrency;
// start with currency pref of account, if any:
$currency = $this->currencyRepository->find(intval($account->getMeta('currency_id')));
if (!is_null($currency->id)) {
return $currency;
}
// use given currency
$currency = $importJournal->getCurrency()->getTransactionCurrency();
if (!is_null($currency->id)) {
return $currency;
}
// backup to default
$currency = $this->defaultCurrency;
return $currency;
}
@ -196,7 +212,9 @@ class ImportStorage
// amount is positive, it's a deposit, opposing is an revenue:
$account->setExpectedType(AccountType::REVENUE);
return $account->getAccount();
$databaseAccount = $account->getAccount();
return $databaseAccount;
}
@ -286,7 +304,7 @@ class ImportStorage
$asset = $importJournal->asset->getAccount();
$amount = $importJournal->getAmount();
$currency = $this->getCurrency($importJournal);
$currency = $this->getCurrency($importJournal, $asset);
$date = $importJournal->getDate($this->dateFormat);
$transactionType = $this->getTransactionType($amount);
$opposing = $this->getOpposingAccount($importJournal->opposing, $amount);
@ -297,6 +315,11 @@ class ImportStorage
$transactionType = TransactionType::whereType(TransactionType::TRANSFER)->first();
}
// verify that opposing account is of the correct type:
if ($opposing->accountType->type === AccountType::EXPENSE && $transactionType->type !== TransactionType::WITHDRAWAL) {
Log::error(sprintf('Row #%d is imported as a %s but opposing is an expense account. This cannot be!', $index, $transactionType->type));
}
/*** First step done! */
$this->job->addStepsDone(1);
@ -351,6 +374,13 @@ class ImportStorage
$this->journals->push($journal);
Log::info(
sprintf(
'Imported new journal #%d with description "%s" and amount %s %s.', $journal->id, $journal->description, $journal->transactionCurrency->code,
$amount
)
);
return true;
}
@ -372,4 +402,4 @@ class ImportStorage
}
}
}
}

View File

@ -22,8 +22,8 @@ class RegisteredUser extends Mailable
*/
public function __construct(string $address, string $ipAddress)
{
$this->address = $address;
$this->ipAddress = $ipAddress;
$this->address = $address;
$this->ipAddress = $ipAddress;
}
/**

View File

@ -50,4 +50,4 @@ class CurrencyExchangeRate extends Model
return $this->belongsTo(User::class);
}
}
}

View File

@ -86,7 +86,7 @@ class ImportJob extends Model
*/
public function addStepsDone(int $count)
{
$status = $this->extended_status;
$status = $this->extended_status;
$status['done'] += $count;
$this->extended_status = $status;
$this->save();

View File

@ -133,9 +133,10 @@ class Tag extends Model
*/
public function getTagAttribute($value)
{
if(is_null($value)) {
if (is_null($value)) {
return null;
}
return Crypt::decrypt($value);
}

View File

@ -212,4 +212,4 @@ trait FindAccountsTrait
return $account;
}
}
}

View File

@ -160,42 +160,19 @@ class CategoryRepository implements CategoryRepositoryInterface
*/
public function lastUseDate(Category $category, Collection $accounts): Carbon
{
$last = null;
$last = new Carbon('1900-01-01');
$lastJournalDate = $this->getLastJournalDate($category, $accounts);
/** @var TransactionJournal $first */
$lastJournalQuery = $category->transactionJournals()->orderBy('date', 'DESC');
if ($accounts->count() > 0) {
// filter journals:
$ids = $accounts->pluck('id')->toArray();
$lastJournalQuery->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id');
$lastJournalQuery->whereIn('t.account_id', $ids);
if ($lastJournalDate->year !== 1900) {
$last = clone $lastJournalDate;
unset($lastJournalDate);
}
$lastJournal = $lastJournalQuery->first(['transaction_journals.*']);
$lastTransactionDate = $this->getLastTransactionDate($category, $accounts);
if ($lastJournal) {
$last = $lastJournal->date;
}
// check transactions:
$lastTransactionQuery = $category->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->orderBy('transaction_journals.date', 'DESC');
if ($accounts->count() > 0) {
// filter journals:
$ids = $accounts->pluck('id')->toArray();
$lastTransactionQuery->whereIn('transactions.account_id', $ids);
}
$lastTransaction = $lastTransactionQuery->first(['transaction_journals.*']);
if (!is_null($lastTransaction) && ((!is_null($last) && $lastTransaction->date < $last) || is_null($last))) {
$last = new Carbon($lastTransaction->date);
}
if (is_null($last)) {
return new Carbon('1900-01-01');
if ($lastTransactionDate->year !== 1900 && $lastTransactionDate < $last) {
$last = clone $lastTransactionDate;
unset($lastTransactionDate);
}
return $last;
@ -479,4 +456,53 @@ class CategoryRepository implements CategoryRepositoryInterface
return $category;
}
/**
* @param Category $category
* @param Collection $accounts
*
* @return Carbon
*/
private function getLastJournalDate(Category $category, Collection $accounts): Carbon
{
$query = $category->transactionJournals()->orderBy('date', 'DESC');
if ($accounts->count() > 0) {
$query->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id');
$query->whereIn('t.account_id', $accounts->pluck('id')->toArray());
}
$result = $query->first(['transaction_journals.*']);
if (!is_null($result)) {
return $result->date;
}
return new Carbon('1900-01-01');
}
/**
* @param Category $category
* @param Collection $accounts
*
* @return Carbon
*/
private function getLastTransactionDate(Category $category, Collection $accounts): Carbon
{
// check transactions:
$query = $category->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->orderBy('transaction_journals.date', 'DESC');
if ($accounts->count() > 0) {
// filter journals:
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
}
$lastTransaction = $query->first(['transaction_journals.*']);
if (!is_null($lastTransaction)) {
return new Carbon($lastTransaction->date);
}
return new Carbon('1900-01-01');
}
}

View File

@ -42,17 +42,17 @@ interface ImportJobRepositoryInterface
* @param ImportJob $job
* @param UploadedFile $file
*
* @return mixed
* @return bool
*/
public function processFile(ImportJob $job, UploadedFile $file): bool;
public function processConfiguration(ImportJob $job, UploadedFile $file): bool;
/**
* @param ImportJob $job
* @param UploadedFile $file
*
* @return bool
* @return mixed
*/
public function processConfiguration(ImportJob $job, UploadedFile $file): bool;
public function processFile(ImportJob $job, UploadedFile $file): bool;
/**
* @param ImportJob $job

View File

@ -188,4 +188,4 @@ trait CreateJournalsTrait
}
}
}

View File

@ -243,4 +243,4 @@ trait SupportJournalsTrait
return $data;
}
}
}

View File

@ -153,4 +153,4 @@ trait UpdateJournalsTrait
return true;
}
}
}

View File

@ -58,4 +58,4 @@ class HasAttachment extends AbstractTrigger implements TriggerInterface
return false;
}
}
}

View File

@ -35,4 +35,4 @@ interface ExchangeRateInterface
*/
public function setUser(User $user);
}
}

View File

@ -68,4 +68,4 @@ class FixerIO implements ExchangeRateInterface
{
$this->user = $user;
}
}
}

View File

@ -36,4 +36,4 @@ class CurrencyCode implements BinderInterface
}
throw new NotFoundHttpException;
}
}
}

View File

@ -565,6 +565,19 @@ class ExpandedForm
unset($options['currency']);
unset($options['placeholder']);
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
$preFilled = session('preFilled');
$key = 'amount_currency_id_' . $name;
$sentCurrencyId = isset($preFilled[$key]) ? intval($preFilled[$key]) : $defaultCurrency->id;
// find this currency in set of currencies:
foreach ($currencies as $currency) {
if ($currency->id === $sentCurrencyId) {
$defaultCurrency = $currency;
break;
}
}
// make sure value is formatted nicely:
if (!is_null($value) && $value !== '') {
$value = round($value, $defaultCurrency->decimal_places);

View File

@ -43,4 +43,4 @@ interface ConfigurationInterface
*/
public function storeConfiguration(array $data): bool;
}
}

View File

@ -26,6 +26,7 @@ use Log;
class Initial implements ConfigurationInterface
{
private $job;
/**
* @return array
*/
@ -106,6 +107,21 @@ class Initial implements ConfigurationInterface
Log::error('Could not find anything for csv_import_account.', ['id' => $importId]);
}
$config = $this->storeSpecifics($data, $config);
$this->job->configuration = $config;
$this->job->save();
return true;
}
/**
* @param array $data
* @param array $config
*
* @return array
*/
private function storeSpecifics(array $data, array $config): array
{
// loop specifics.
if (isset($data['specifics']) && is_array($data['specifics'])) {
foreach ($data['specifics'] as $name => $enabled) {
@ -116,9 +132,7 @@ class Initial implements ConfigurationInterface
}
}
}
$this->job->configuration = $config;
$this->job->save();
return true;
return $config;
}
}
}

View File

@ -266,4 +266,4 @@ class Map implements ConfigurationInterface
return $column;
}
}
}

View File

@ -68,6 +68,18 @@ class Roles implements ConfigurationInterface
return $this->data;
}
/**
* @param ImportJob $job
*
* @return ConfigurationInterface
*/
public function setJob(ImportJob $job): ConfigurationInterface
{
$this->job = $job;
return $this;
}
/**
* Store the result.
*
@ -217,16 +229,20 @@ class Roles implements ConfigurationInterface
*/
private function setRolesComplete(): bool
{
$config = $this->job->configuration;
$count = $config['column-count'];
$assigned = 0;
$config = $this->job->configuration;
$count = $config['column-count'];
$assigned = 0;
$hasAmount = false;
for ($i = 0; $i < $count; $i++) {
$role = $config['column-roles'][$i] ?? '_ignore';
if ($role !== '_ignore') {
$assigned++;
}
if ($role === 'amount') {
$hasAmount = true;
}
}
if ($assigned > 0) {
if ($assigned > 0 && $hasAmount) {
$config['column-roles-complete'] = true;
$this->job->configuration = $config;
$this->job->save();
@ -248,16 +264,4 @@ class Roles implements ConfigurationInterface
return true;
}
/**
* @param ImportJob $job
*
* @return ConfigurationInterface
*/
public function setJob(ImportJob $job): ConfigurationInterface
{
$this->job = $job;
return $this;
}
}
}

View File

@ -208,4 +208,4 @@ class Modifier
return self::stringCompare($journalCategory, $search) || self::stringCompare($transactionCategory, $search);
}
}
}

View File

@ -53,7 +53,7 @@ class Search implements SearchInterface
public function __construct()
{
$this->modifiers = new Collection;
$this->validModifiers = (array) config('firefly.search_modifiers');
$this->validModifiers = (array)config('firefly.search_modifiers');
}
/**

View File

@ -13,7 +13,7 @@ declare(strict_types=1);
namespace FireflyIII\Support;
use \Amount as GlobalAmount;
use Amount as GlobalAmount;
use Carbon\Carbon;
use Crypt;
use DB;

View File

@ -265,4 +265,4 @@ class AmountFormat extends Twig_Extension
);
}
}
}

132
composer.lock generated
View File

@ -622,16 +622,16 @@
},
{
"name": "erusev/parsedown",
"version": "1.6.2",
"version": "1.6.3",
"source": {
"type": "git",
"url": "https://github.com/erusev/parsedown.git",
"reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01"
"reference": "728952b90a333b5c6f77f06ea9422b94b585878d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/1bf24f7334fe16c88bf9d467863309ceaf285b01",
"reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/728952b90a333b5c6f77f06ea9422b94b585878d",
"reference": "728952b90a333b5c6f77f06ea9422b94b585878d",
"shasum": ""
},
"require": {
@ -660,7 +660,7 @@
"markdown",
"parser"
],
"time": "2017-03-29T16:04:15+00:00"
"time": "2017-05-14T14:47:48+00:00"
},
{
"name": "laravel/framework",
@ -1636,16 +1636,16 @@
},
{
"name": "symfony/console",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "70d2a29b2911cbdc91a7e268046c395278238b2e"
"reference": "a97e45d98c59510f085fa05225a1acb74dfe0546"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/70d2a29b2911cbdc91a7e268046c395278238b2e",
"reference": "70d2a29b2911cbdc91a7e268046c395278238b2e",
"url": "https://api.github.com/repos/symfony/console/zipball/a97e45d98c59510f085fa05225a1acb74dfe0546",
"reference": "a97e45d98c59510f085fa05225a1acb74dfe0546",
"shasum": ""
},
"require": {
@ -1701,7 +1701,7 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2017-06-02T19:24:58+00:00"
"time": "2017-07-03T13:19:36+00:00"
},
{
"name": "symfony/css-selector",
@ -1758,16 +1758,16 @@
},
{
"name": "symfony/debug",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "e9c50482841ef696e8fa1470d950a79c8921f45d"
"reference": "63b85a968486d95ff9542228dc2e4247f16f9743"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/e9c50482841ef696e8fa1470d950a79c8921f45d",
"reference": "e9c50482841ef696e8fa1470d950a79c8921f45d",
"url": "https://api.github.com/repos/symfony/debug/zipball/63b85a968486d95ff9542228dc2e4247f16f9743",
"reference": "63b85a968486d95ff9542228dc2e4247f16f9743",
"shasum": ""
},
"require": {
@ -1810,11 +1810,11 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2017-06-01T21:01:25+00:00"
"time": "2017-07-05T13:02:37+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v2.8.22",
"version": "v2.8.24",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@ -1874,7 +1874,7 @@
},
{
"name": "symfony/finder",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
@ -1923,16 +1923,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "80eb5a1f968448b77da9e8b2c0827f6e8d767846"
"reference": "f347a5f561b03db95ed666959db42bbbf429b7e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/80eb5a1f968448b77da9e8b2c0827f6e8d767846",
"reference": "80eb5a1f968448b77da9e8b2c0827f6e8d767846",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f347a5f561b03db95ed666959db42bbbf429b7e5",
"reference": "f347a5f561b03db95ed666959db42bbbf429b7e5",
"shasum": ""
},
"require": {
@ -1972,7 +1972,7 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
"time": "2017-06-05T13:06:51+00:00"
"time": "2017-06-24T09:29:48+00:00"
},
{
"name": "symfony/http-kernel",
@ -2228,16 +2228,16 @@
},
{
"name": "symfony/process",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "8e30690c67aafb6c7992d6d8eb0d707807dd3eaf"
"reference": "5ab8949b682b1bf9d4511a228b5e045c96758c30"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/8e30690c67aafb6c7992d6d8eb0d707807dd3eaf",
"reference": "8e30690c67aafb6c7992d6d8eb0d707807dd3eaf",
"url": "https://api.github.com/repos/symfony/process/zipball/5ab8949b682b1bf9d4511a228b5e045c96758c30",
"reference": "5ab8949b682b1bf9d4511a228b5e045c96758c30",
"shasum": ""
},
"require": {
@ -2273,20 +2273,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2017-05-22T12:32:03+00:00"
"time": "2017-07-03T08:12:02+00:00"
},
{
"name": "symfony/routing",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
"reference": "39804eeafea5cca851946e1eed122eb94459fdb4"
"reference": "dc70bbd0ca7b19259f63cdacc8af370bc32a4728"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/39804eeafea5cca851946e1eed122eb94459fdb4",
"reference": "39804eeafea5cca851946e1eed122eb94459fdb4",
"url": "https://api.github.com/repos/symfony/routing/zipball/dc70bbd0ca7b19259f63cdacc8af370bc32a4728",
"reference": "dc70bbd0ca7b19259f63cdacc8af370bc32a4728",
"shasum": ""
},
"require": {
@ -2351,20 +2351,20 @@
"uri",
"url"
],
"time": "2017-06-02T09:51:43+00:00"
"time": "2017-06-24T09:29:48+00:00"
},
{
"name": "symfony/translation",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "dc3b2a0c6cfff60327ba1c043a82092735397543"
"reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/dc3b2a0c6cfff60327ba1c043a82092735397543",
"reference": "dc3b2a0c6cfff60327ba1c043a82092735397543",
"url": "https://api.github.com/repos/symfony/translation/zipball/35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
"reference": "35dd5fb003c90e8bd4d8cabdf94bf9c96d06fdc3",
"shasum": ""
},
"require": {
@ -2416,20 +2416,20 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
"time": "2017-05-22T07:42:36+00:00"
"time": "2017-06-24T16:45:30+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "347c4247a3e40018810b476fcd5dec36d46d08dc"
"reference": "9ee920bba1d2ce877496dcafca7cbffff4dbe08a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/347c4247a3e40018810b476fcd5dec36d46d08dc",
"reference": "347c4247a3e40018810b476fcd5dec36d46d08dc",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/9ee920bba1d2ce877496dcafca7cbffff4dbe08a",
"reference": "9ee920bba1d2ce877496dcafca7cbffff4dbe08a",
"shasum": ""
},
"require": {
@ -2484,7 +2484,7 @@
"debug",
"dump"
],
"time": "2017-06-02T09:10:29+00:00"
"time": "2017-07-05T13:02:37+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@ -3833,16 +3833,16 @@
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "3.4.3",
"version": "3.4.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24"
"reference": "a23b761686d50a560cc56233b9ecf49597cc9118"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24",
"reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118",
"reference": "a23b761686d50a560cc56233b9ecf49597cc9118",
"shasum": ""
},
"require": {
@ -3888,7 +3888,7 @@
"mock",
"xunit"
],
"time": "2016-12-08T20:27:08+00:00"
"time": "2017-06-30T09:13:00+00:00"
},
{
"name": "satooshi/php-coveralls",
@ -4463,7 +4463,7 @@
},
{
"name": "symfony/class-loader",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/class-loader.git",
@ -4519,16 +4519,16 @@
},
{
"name": "symfony/config",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "35716d4904e0506a7a5a9bcf23f854aeb5719bca"
"reference": "a094618deb9a3fe1c3cf500a796e167d0495a274"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/35716d4904e0506a7a5a9bcf23f854aeb5719bca",
"reference": "35716d4904e0506a7a5a9bcf23f854aeb5719bca",
"url": "https://api.github.com/repos/symfony/config/zipball/a094618deb9a3fe1c3cf500a796e167d0495a274",
"reference": "a094618deb9a3fe1c3cf500a796e167d0495a274",
"shasum": ""
},
"require": {
@ -4536,10 +4536,12 @@
"symfony/filesystem": "~2.8|~3.0"
},
"conflict": {
"symfony/dependency-injection": "<3.3"
"symfony/dependency-injection": "<3.3",
"symfony/finder": "<3.3"
},
"require-dev": {
"symfony/dependency-injection": "~3.3",
"symfony/finder": "~3.3",
"symfony/yaml": "~3.0"
},
"suggest": {
@ -4575,7 +4577,7 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2017-06-02T18:07:20+00:00"
"time": "2017-06-16T12:40:34+00:00"
},
{
"name": "symfony/dom-crawler",
@ -4635,16 +4637,16 @@
},
{
"name": "symfony/filesystem",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "c709670bf64721202ddbe4162846f250735842c0"
"reference": "311fa718389efbd8b627c272b9324a62437018cc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/c709670bf64721202ddbe4162846f250735842c0",
"reference": "c709670bf64721202ddbe4162846f250735842c0",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/311fa718389efbd8b627c272b9324a62437018cc",
"reference": "311fa718389efbd8b627c272b9324a62437018cc",
"shasum": ""
},
"require": {
@ -4680,11 +4682,11 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2017-05-28T14:08:56+00:00"
"time": "2017-06-24T09:29:48+00:00"
},
{
"name": "symfony/stopwatch",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
@ -4733,16 +4735,16 @@
},
{
"name": "symfony/yaml",
"version": "v3.3.2",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063"
"reference": "1f93a8d19b8241617f5074a123e282575b821df8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/9752a30000a8ca9f4b34b5227d15d0101b96b063",
"reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063",
"url": "https://api.github.com/repos/symfony/yaml/zipball/1f93a8d19b8241617f5074a123e282575b821df8",
"reference": "1f93a8d19b8241617f5074a123e282575b821df8",
"shasum": ""
},
"require": {
@ -4784,7 +4786,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2017-06-02T22:05:06+00:00"
"time": "2017-06-15T12:58:50+00:00"
},
{
"name": "webmozart/assert",

View File

@ -23,7 +23,7 @@ return [
'is_demo_site' => false,
],
'encryption' => (is_null(env('USE_ENCRYPTION')) || env('USE_ENCRYPTION') === true),
'version' => '4.6.1',
'version' => '4.6.2',
'maxUploadSize' => 15242880,
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
'list_length' => 10,

View File

@ -244,4 +244,4 @@ $factory->define(
'foreign_currency_symbol' => null,
];
}
);
);

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

View File

@ -43,20 +43,20 @@ table.sortable span.arrow, span.reversed, th.arrow.down:after, th.reversedarrow.
margin-top: -2px;
}
table.sortable span.arrow.up, th.arrow.up:after {
border-color: transparent transparent #ccc transparent;
margin-top: -7px;
}
table.sortable span.arrow.up, th.arrow.up:after {
border-color: transparent transparent #ccc transparent;
margin-top: -7px;
}
table.sortable span.reversed, th.reversedarrow.down:after {
border-color: transparent transparent #ccc transparent;
margin-top: -7px;
}
table.sortable span.reversed.up, th.reversedarrow.up:after {
border-color: #ccc transparent transparent transparent;
margin-top: -2px;
}
table.sortable span.reversed.up, th.reversedarrow.up:after {
border-color: #ccc transparent transparent transparent;
margin-top: -2px;
}
table.sortable span.az:before, th.az.down:after {
content: "a .. z";
@ -94,17 +94,17 @@ table.sortable span.month.up:before, th.month.up:after {
content: "dec .. jan";
}
table.sortable>thead th:not([data-defaultsort=disabled]) {
table.sortable > thead th:not([data-defaultsort=disabled]) {
cursor: pointer;
position: relative;
top: 0;
left: 0;
}
table.sortable>thead th:hover:not([data-defaultsort=disabled]) {
table.sortable > thead th:hover:not([data-defaultsort=disabled]) {
background: #efefef;
}
table.sortable>thead th div.mozilla {
table.sortable > thead th div.mozilla {
position: relative;
}

View File

@ -4,57 +4,67 @@
*/
.bootstrap-tagsinput {
background-color: #fff;
border: 1px solid #ccc;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
display: inline-block;
padding: 4px 6px;
color: #555;
vertical-align: middle;
border-radius: 4px;
max-width: 100%;
line-height: 22px;
cursor: text;
background-color: #fff;
border: 1px solid #ccc;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
display: inline-block;
padding: 4px 6px;
color: #555;
vertical-align: middle;
border-radius: 4px;
max-width: 100%;
line-height: 22px;
cursor: text;
}
.bootstrap-tagsinput input {
border: none;
box-shadow: none;
outline: none;
background-color: transparent;
padding: 0 6px;
margin: 0;
width: auto;
max-width: inherit;
border: none;
box-shadow: none;
outline: none;
background-color: transparent;
padding: 0 6px;
margin: 0;
width: auto;
max-width: inherit;
}
.bootstrap-tagsinput.form-control input::-moz-placeholder {
color: #777;
opacity: 1;
color: #777;
opacity: 1;
}
.bootstrap-tagsinput.form-control input:-ms-input-placeholder {
color: #777;
color: #777;
}
.bootstrap-tagsinput.form-control input::-webkit-input-placeholder {
color: #777;
color: #777;
}
.bootstrap-tagsinput input:focus {
border: none;
box-shadow: none;
border: none;
box-shadow: none;
}
.bootstrap-tagsinput .tag {
margin-right: 2px;
color: white;
margin-right: 2px;
color: white;
}
.bootstrap-tagsinput .tag [data-role="remove"] {
margin-left: 8px;
cursor: pointer;
margin-left: 8px;
cursor: pointer;
}
.bootstrap-tagsinput .tag [data-role="remove"]:after {
content: "x";
padding: 0px 2px;
content: "x";
padding: 0px 2px;
}
.bootstrap-tagsinput .tag [data-role="remove"]:hover {
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.bootstrap-tagsinput .tag [data-role="remove"]:hover:active {
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}

View File

@ -1,141 +1,213 @@
.daterangepicker {
position: absolute;
color: inherit;
background: #fff;
border-radius: 4px;
width: 278px;
padding: 4px;
margin-top: 1px;
top: 100px;
left: 20px;
/* Calendars */ }
.daterangepicker:before, .daterangepicker:after {
position: absolute;
color: inherit;
background: #fff;
border-radius: 4px;
width: 278px;
padding: 4px;
margin-top: 1px;
top: 100px;
left: 20px;
/* Calendars */
}
.daterangepicker:before, .daterangepicker:after {
position: absolute;
display: inline-block;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: ''; }
.daterangepicker:before {
content: '';
}
.daterangepicker:before {
top: -7px;
border-right: 7px solid transparent;
border-left: 7px solid transparent;
border-bottom: 7px solid #ccc; }
.daterangepicker:after {
border-bottom: 7px solid #ccc;
}
.daterangepicker:after {
top: -6px;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent; }
.daterangepicker.opensleft:before {
right: 9px; }
.daterangepicker.opensleft:after {
right: 10px; }
.daterangepicker.openscenter:before {
border-left: 6px solid transparent;
}
.daterangepicker.opensleft:before {
right: 9px;
}
.daterangepicker.opensleft:after {
right: 10px;
}
.daterangepicker.openscenter:before {
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto; }
.daterangepicker.openscenter:after {
margin-right: auto;
}
.daterangepicker.openscenter:after {
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto; }
.daterangepicker.opensright:before {
left: 9px; }
.daterangepicker.opensright:after {
left: 10px; }
.daterangepicker.dropup {
margin-top: -5px; }
.daterangepicker.dropup:before {
top: initial;
bottom: -7px;
border-bottom: initial;
border-top: 7px solid #ccc; }
.daterangepicker.dropup:after {
top: initial;
bottom: -6px;
border-bottom: initial;
border-top: 6px solid #fff; }
.daterangepicker.dropdown-menu {
margin-right: auto;
}
.daterangepicker.opensright:before {
left: 9px;
}
.daterangepicker.opensright:after {
left: 10px;
}
.daterangepicker.dropup {
margin-top: -5px;
}
.daterangepicker.dropup:before {
top: initial;
bottom: -7px;
border-bottom: initial;
border-top: 7px solid #ccc;
}
.daterangepicker.dropup:after {
top: initial;
bottom: -6px;
border-bottom: initial;
border-top: 6px solid #fff;
}
.daterangepicker.dropdown-menu {
max-width: none;
z-index: 3001; }
.daterangepicker.single .ranges, .daterangepicker.single .calendar {
float: none; }
.daterangepicker.show-calendar .calendar {
display: block; }
.daterangepicker .calendar {
z-index: 3001;
}
.daterangepicker.single .ranges, .daterangepicker.single .calendar {
float: none;
}
.daterangepicker.show-calendar .calendar {
display: block;
}
.daterangepicker .calendar {
display: none;
max-width: 270px;
margin: 4px; }
.daterangepicker .calendar.single .calendar-table {
border: none; }
.daterangepicker .calendar th, .daterangepicker .calendar td {
white-space: nowrap;
text-align: center;
min-width: 32px; }
.daterangepicker .calendar-table {
margin: 4px;
}
.daterangepicker .calendar.single .calendar-table {
border: none;
}
.daterangepicker .calendar th, .daterangepicker .calendar td {
white-space: nowrap;
text-align: center;
min-width: 32px;
}
.daterangepicker .calendar-table {
border: 1px solid #fff;
padding: 4px;
border-radius: 4px;
background: #fff; }
.daterangepicker table {
background: #fff;
}
.daterangepicker table {
width: 100%;
margin: 0; }
.daterangepicker td, .daterangepicker th {
margin: 0;
}
.daterangepicker td, .daterangepicker th {
text-align: center;
width: 20px;
height: 20px;
border-radius: 4px;
border: 1px solid transparent;
white-space: nowrap;
cursor: pointer; }
.daterangepicker td.available:hover, .daterangepicker th.available:hover {
background-color: #eee;
border-color: transparent;
color: inherit; }
.daterangepicker td.week, .daterangepicker th.week {
font-size: 80%;
color: #ccc; }
.daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date {
cursor: pointer;
}
.daterangepicker td.available:hover, .daterangepicker th.available:hover {
background-color: #eee;
border-color: transparent;
color: inherit;
}
.daterangepicker td.week, .daterangepicker th.week {
font-size: 80%;
color: #ccc;
}
.daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date {
background-color: #fff;
border-color: transparent;
color: #999; }
.daterangepicker td.in-range {
color: #999;
}
.daterangepicker td.in-range {
background-color: #ebf4f8;
border-color: transparent;
color: #000;
border-radius: 0; }
.daterangepicker td.start-date {
border-radius: 4px 0 0 4px; }
.daterangepicker td.end-date {
border-radius: 0 4px 4px 0; }
.daterangepicker td.start-date.end-date {
border-radius: 4px; }
.daterangepicker td.active, .daterangepicker td.active:hover {
border-radius: 0;
}
.daterangepicker td.start-date {
border-radius: 4px 0 0 4px;
}
.daterangepicker td.end-date {
border-radius: 0 4px 4px 0;
}
.daterangepicker td.start-date.end-date {
border-radius: 4px;
}
.daterangepicker td.active, .daterangepicker td.active:hover {
background-color: #357ebd;
border-color: transparent;
color: #fff; }
.daterangepicker th.month {
width: auto; }
.daterangepicker td.disabled, .daterangepicker option.disabled {
color: #fff;
}
.daterangepicker th.month {
width: auto;
}
.daterangepicker td.disabled, .daterangepicker option.disabled {
color: #999;
cursor: not-allowed;
text-decoration: line-through; }
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
text-decoration: line-through;
}
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
font-size: 12px;
padding: 1px;
height: auto;
margin: 0;
cursor: default; }
.daterangepicker select.monthselect {
cursor: default;
}
.daterangepicker select.monthselect {
margin-right: 2%;
width: 56%; }
.daterangepicker select.yearselect {
width: 40%; }
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
width: 56%;
}
.daterangepicker select.yearselect {
width: 40%;
}
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
width: 50px;
margin-bottom: 0; }
.daterangepicker .input-mini {
margin-bottom: 0;
}
.daterangepicker .input-mini {
border: 1px solid #ccc;
border-radius: 4px;
color: #555;
@ -145,43 +217,62 @@
vertical-align: middle;
margin: 0 0 5px 0;
padding: 0 6px 0 28px;
width: 100%; }
.daterangepicker .input-mini.active {
border: 1px solid #08c;
border-radius: 4px; }
.daterangepicker .daterangepicker_input {
position: relative; }
.daterangepicker .daterangepicker_input i {
position: absolute;
left: 8px;
top: 8px; }
.daterangepicker.rtl .input-mini {
width: 100%;
}
.daterangepicker .input-mini.active {
border: 1px solid #08c;
border-radius: 4px;
}
.daterangepicker .daterangepicker_input {
position: relative;
}
.daterangepicker .daterangepicker_input i {
position: absolute;
left: 8px;
top: 8px;
}
.daterangepicker.rtl .input-mini {
padding-right: 28px;
padding-left: 6px; }
.daterangepicker.rtl .daterangepicker_input i {
padding-left: 6px;
}
.daterangepicker.rtl .daterangepicker_input i {
left: auto;
right: 8px; }
.daterangepicker .calendar-time {
right: 8px;
}
.daterangepicker .calendar-time {
text-align: center;
margin: 5px auto;
line-height: 30px;
position: relative;
padding-left: 28px; }
.daterangepicker .calendar-time select.disabled {
color: #ccc;
cursor: not-allowed; }
padding-left: 28px;
}
.daterangepicker .calendar-time select.disabled {
color: #ccc;
cursor: not-allowed;
}
.ranges {
font-size: 11px;
float: none;
margin: 4px;
text-align: left; }
.ranges ul {
font-size: 11px;
float: none;
margin: 4px;
text-align: left;
}
.ranges ul {
list-style: none;
margin: 0 auto;
padding: 0;
width: 100%; }
.ranges li {
width: 100%;
}
.ranges li {
font-size: 13px;
background: #f5f5f5;
border: 1px solid #f5f5f5;
@ -189,81 +280,139 @@
color: #08c;
padding: 3px 12px;
margin-bottom: 8px;
cursor: pointer; }
.ranges li:hover {
background: #08c;
border: 1px solid #08c;
color: #fff; }
.ranges li.active {
background: #08c;
border: 1px solid #08c;
color: #fff; }
cursor: pointer;
}
.ranges li:hover {
background: #08c;
border: 1px solid #08c;
color: #fff;
}
.ranges li.active {
background: #08c;
border: 1px solid #08c;
color: #fff;
}
/* Larger Screen Styling */
@media (min-width: 564px) {
.daterangepicker {
width: auto; }
.daterangepicker {
width: auto;
}
.daterangepicker .ranges ul {
width: 160px; }
width: 160px;
}
.daterangepicker.single .ranges ul {
width: 100%; }
width: 100%;
}
.daterangepicker.single .calendar.left {
clear: none; }
clear: none;
}
.daterangepicker.single.ltr .ranges, .daterangepicker.single.ltr .calendar {
float: left; }
float: left;
}
.daterangepicker.single.rtl .ranges, .daterangepicker.single.rtl .calendar {
float: right; }
float: right;
}
.daterangepicker.ltr {
direction: ltr;
text-align: left; }
.daterangepicker.ltr .calendar.left {
direction: ltr;
text-align: left;
}
.daterangepicker.ltr .calendar.left {
clear: left;
margin-right: 0; }
.daterangepicker.ltr .calendar.left .calendar-table {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0; }
.daterangepicker.ltr .calendar.right {
margin-left: 0; }
.daterangepicker.ltr .calendar.right .calendar-table {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0; }
.daterangepicker.ltr .left .daterangepicker_input {
padding-right: 12px; }
.daterangepicker.ltr .calendar.left .calendar-table {
padding-right: 12px; }
.daterangepicker.ltr .ranges, .daterangepicker.ltr .calendar {
float: left; }
margin-right: 0;
}
.daterangepicker.ltr .calendar.left .calendar-table {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.daterangepicker.ltr .calendar.right {
margin-left: 0;
}
.daterangepicker.ltr .calendar.right .calendar-table {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.daterangepicker.ltr .left .daterangepicker_input {
padding-right: 12px;
}
.daterangepicker.ltr .calendar.left .calendar-table {
padding-right: 12px;
}
.daterangepicker.ltr .ranges, .daterangepicker.ltr .calendar {
float: left;
}
.daterangepicker.rtl {
direction: rtl;
text-align: right; }
.daterangepicker.rtl .calendar.left {
clear: right;
margin-left: 0; }
.daterangepicker.rtl .calendar.left .calendar-table {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0; }
.daterangepicker.rtl .calendar.right {
margin-right: 0; }
.daterangepicker.rtl .calendar.right .calendar-table {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0; }
.daterangepicker.rtl .left .daterangepicker_input {
padding-left: 12px; }
.daterangepicker.rtl .calendar.left .calendar-table {
padding-left: 12px; }
.daterangepicker.rtl .ranges, .daterangepicker.rtl .calendar {
direction: rtl;
text-align: right;
float: right; } }
}
.daterangepicker.rtl .calendar.left {
clear: right;
margin-left: 0;
}
.daterangepicker.rtl .calendar.left .calendar-table {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.daterangepicker.rtl .calendar.right {
margin-right: 0;
}
.daterangepicker.rtl .calendar.right .calendar-table {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.daterangepicker.rtl .left .daterangepicker_input {
padding-left: 12px;
}
.daterangepicker.rtl .calendar.left .calendar-table {
padding-left: 12px;
}
.daterangepicker.rtl .ranges, .daterangepicker.rtl .calendar {
text-align: right;
float: right;
}
}
@media (min-width: 730px) {
.daterangepicker .ranges {
width: auto; }
.daterangepicker.ltr .ranges {
float: left; }
.daterangepicker.rtl .ranges {
float: right; }
.daterangepicker .calendar.left {
clear: none !important; } }
.daterangepicker .ranges {
width: auto;
}
.daterangepicker.ltr .ranges {
float: left;
}
.daterangepicker.rtl .ranges {
float: right;
}
.daterangepicker .calendar.left {
clear: none !important;
}
}

View File

@ -9,7 +9,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
/*
|--------------------------------------------------------------------------
@ -23,7 +23,7 @@ declare(strict_types = 1);
|
*/
require __DIR__.'/../bootstrap/autoload.php';
require __DIR__ . '/../bootstrap/autoload.php';
/*
|--------------------------------------------------------------------------
@ -37,7 +37,7 @@ require __DIR__.'/../bootstrap/autoload.php';
|
*/
$app = require_once __DIR__.'/../bootstrap/app.php';
$app = require_once __DIR__ . '/../bootstrap/app.php';
/*
|--------------------------------------------------------------------------

View File

@ -69,13 +69,13 @@ function updateBudgetedAmounts(e) {
var spentAmount = parseFloat(spentCell.data('spent'));
var newAmountLeft = spentAmount + parseFloat(value);
var amountLeftString = accounting.formatMoney(newAmountLeft);
if(newAmountLeft < 0) {
if (newAmountLeft < 0) {
leftCell.html('<span class="text-danger">' + amountLeftString + '</span>');
}
if(newAmountLeft > 0) {
if (newAmountLeft > 0) {
leftCell.html('<span class="text-success">' + amountLeftString + '</span>');
}
if(newAmountLeft === 0.0) {
if (newAmountLeft === 0.0) {
leftCell.html('<span style="color:#999">' + amountLeftString + '</span>');
}

View File

@ -25,6 +25,4 @@ $(function () {
pieChart(expenseExpenseUri, 'budget-expense-out');
});

View File

@ -8,6 +8,8 @@
/** global: Modernizr, accountInfo, currencyInfo, accountInfo, transferInstructions, what */
var countConversions = 0;
$(document).ready(function () {
"use strict";
setCommonAutocomplete();
@ -118,6 +120,12 @@ function convertForeignToNative() {
* @param data
*/
function updateNativeAmount(data) {
// if native amount is already filled in, even though we do this for the first time:
// don't overrule it.
if (countConversions === 0 && $('#ffInput_native_amount').val().length > 0) {
countConversions++;
return;
}
$('#ffInput_native_amount').val(data.amount);
}

View File

@ -23,7 +23,6 @@ $(document).ready(function () {
updateForm();
updateLayout();
updateDescription();
updateNativeCurrency();
// when user changes source account or destination, native currency may be different.
@ -60,16 +59,21 @@ function getExchangeInstructions() {
* There is an input that shows the currency symbol that is native to the selected
* acccount. So when the user changes the selected account, the native currency is updated:
*/
function updateNativeCurrency() {
var newAccountId = getAccountId();
var nativeCurrencyId = accountInfo[newAccountId].preferredCurrency;
function updateNativeCurrency(useAccountCurrency) {
var nativeCurrencyId;
if (useAccountCurrency) {
var newAccountId = getAccountId();
nativeCurrencyId = accountInfo[newAccountId].preferredCurrency;
}
if (!useAccountCurrency) {
nativeCurrencyId = overruleCurrency;
}
$('.currency-option[data-id="' + nativeCurrencyId + '"]').click();
$('[data-toggle="dropdown"]').parent().removeClass('open');
if (what !== 'transfer') {
$('select[name="source_account_id"]').focus();
}
validateCurrencyForTransfer();
}
@ -180,7 +184,9 @@ function updateForm() {
default:
break;
}
updateNativeCurrency();
// get instructions all the time.
updateNativeCurrency(useAccountCurrency);
selectsForeignCurrency();
}
/**

View File

@ -20,8 +20,8 @@ $(document).ready(function () {
$('#ffInput_amount').on('change', convertForeignToNative);
// respond to transfer changes:
$('#ffInput_source_account_id').on('change',validateCurrencyForTransfer);
$('#ffInput_destination_account_id').on('change',validateCurrencyForTransfer);
$('#ffInput_source_account_id').on('change', validateCurrencyForTransfer);
$('#ffInput_destination_account_id').on('change', validateCurrencyForTransfer);
// convert source currency to destination currency (slightly different routine for transfers)
$('#ffInput_source_amount').on('change', convertSourceToDestination);
@ -64,7 +64,6 @@ function updateInitialPage() {
}
/**
* Get accountID based on some meta info.
*/

View File

@ -139,10 +139,10 @@ function resetDivSplits() {
row.attr('data-split', i);
// add or remove class with bg thing
if(i % 2 === 0) {
if (i % 2 === 0) {
row.removeClass('bg-gray-light');
}
if(i % 2 === 1) {
if (i % 2 === 1) {
row.addClass('bg-gray-light');
}

View File

@ -17,5 +17,4 @@
"display": "standalone",
"start_url": "/",
"orientation": "portrait"
}

View File

@ -1,15 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M89 4009 c-17 -4 -43 -19 -58 -33 l-26 -26 -2 -1383 -3 -1383 28 -33
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M89 4009 c-17 -4 -43 -19 -58 -33 l-26 -26 -2 -1383 -3 -1383 28 -33
c19 -23 39 -35 67 -39 22 -4 1144 -7 2493 -6 2449 0 2452 0 2480 21 15 11 33
31 39 44 10 19 13 325 13 1389 0 1064 -3 1370 -13 1389 -6 13 -24 33 -39 44
-28 21 -31 21 -2487 21 -1353 1 -2474 -2 -2492 -5z m683 -218 c8 -1 -18 -100
@ -28,7 +28,7 @@ m-4527 -1947 c161 -65 301 -202 369 -359 21 -48 25 -61 36 -114 3 -14 7 -28
-7 c22 -4 67 -18 100 -31z m4539 -239 c0 -213 -3 -275 -12 -276 -18 -1 -499
-1 -525 0 -21 1 -22 2 -9 46 8 25 12 45 10 45 -8 0 58 134 86 175 45 66 128
147 190 187 73 46 191 93 243 97 16 1 17 -18 17 -274z"/>
<path d="M1448 3348 c-46 -9 -74 -46 -82 -108 -17 -129 -102 -204 -239 -209
<path d="M1448 3348 c-46 -9 -74 -46 -82 -108 -17 -129 -102 -204 -239 -209
-10 -1 -32 -14 -48 -30 l-29 -29 0 -401 c0 -230 4 -410 10 -425 12 -34 46 -54
100 -61 106 -13 192 -94 205 -193 8 -64 19 -88 50 -108 25 -16 101 -18 1118
-18 601 -1 1109 2 1131 5 54 9 73 33 90 117 24 117 91 181 206 197 54 8 74 18
@ -39,14 +39,14 @@ m2125 -218 c48 -124 120 -204 229 -255 l73 -33 -2 -269 c-1 -147 -2 -275 -2
-1004 0 -14 35 c-46 116 -118 195 -220 242 -38 18 -70 35 -73 39 -4 6 -5 456
-1 545 1 15 15 26 56 43 30 12 72 36 94 51 49 36 114 120 137 180 10 25 21 47
25 50 4 3 456 5 1005 5 l997 0 10 -25z"/>
<path d="M2013 3012 c-34 -5 -73 -58 -73 -99 0 -52 55 -102 104 -94 4 1 16 -1
<path d="M2013 3012 c-34 -5 -73 -58 -73 -99 0 -52 55 -102 104 -94 4 1 16 -1
25 -4 16 -5 17 -32 17 -319 0 -242 3 -320 13 -339 35 -66 137 -65 172 0 10 19
13 107 14 386 1 199 -3 378 -8 397 -14 57 -45 73 -151 74 -50 1 -101 0 -113
-2z"/>
<path d="M2608 3012 c-35 -9 -58 -28 -71 -56 -12 -25 -14 -101 -12 -406 1
<path d="M2608 3012 c-35 -9 -58 -28 -71 -56 -12 -25 -14 -101 -12 -406 1
-206 5 -383 9 -392 4 -9 20 -25 34 -34 24 -16 57 -18 276 -19 282 -1 302 3
322 65 15 45 17 731 3 777 -20 63 -37 67 -306 68 -132 0 -247 -1 -255 -3z
m370 -453 l2 -256 -128 1 -129 0 -1 250 c0 138 1 253 3 256 2 4 59 6 127 6
l123 -1 3 -256z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -14,34 +14,34 @@ declare(strict_types=1);
return [
// initial config
'initial_title' => 'Import setup (1/3) - Basic CSV import setup',
'initial_text' => 'To be able to import your file correctly, please validate the options below.',
'initial_box' => 'Basic CSV import setup',
'initial_header_help' => 'Check this box if the first row of your CSV file are the column titles.',
'initial_date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.',
'initial_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
'initial_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
'initial_submit' => 'Continue with step 2/3',
'initial_title' => 'Import Einrichten (1/3) - Grundlegende Einstellungen',
'initial_text' => 'Um Ihre Datei korrekt importieren zu können, überprüfen Sie die folgenden Optionen.',
'initial_box' => 'Standard CSV Importeinstellungen',
'initial_header_help' => 'Hier auswählen, wenn die ersten Zeilen der CSV-Datei die Spaltenüberschriften sind.',
'initial_date_help' => 'Datumsformat in ihrer CSV-Datei. Geben Sie das Format so an, wie es <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">diese Seite</a> zeigt. Die Standardeinstellung ergibt Daten die so aussehen: :dateExample.',
'initial_delimiter_help' => 'Wählen Sie das Trennzeichen, welches in ihrer Datei genutzt wird. Wenn Sie nicht sicher sind ist Komma die sicherste Option.',
'initial_import_account_help' => 'Wenn ihre CSV-Datei KEINE Informationen über ihre Girokonten enthält nutzen Sie bitte diese Dropdown-Liste um anzugeben, zu welchem Girokonto die Transaktionen in der CSV-Datei gehören.',
'initial_submit' => 'Fortfahren mit Schritt 2/3',
// roles config
'roles_title' => 'Import setup (2/3) - Define each column\'s role',
'roles_text' => 'Each column in your CSV file contains certain data. Please indicate what kind of data the importer should expect. The option to "map" data means that you will link each entry found in the column to a value in your database. An often mapped column is the column that contains the IBAN of the opposing account. That can be easily matched to IBAN\'s present in your database already.',
'roles_table' => 'Table',
'roles_column_name' => 'Name of column',
'roles_column_example' => 'Column example data',
'roles_column_role' => 'Column data meaning',
'roles_do_map_value' => 'Map these values',
'roles_column' => 'Column',
'roles_no_example_data' => 'No example data available',
'roles_submit' => 'Continue with step 3/3',
'roles_title' => 'Import Einrichten (2/3) - Jeder Spalte eine Rolle zuordnen',
'roles_text' => 'Jede Spalte in Ihrer CSV-Datei enthält bestimmte Daten. Bitte geben Sie an, welche Art von Daten enthalten sind. Die Option "Daten zuordnen" bedeutet, dass jeder Eintrag in der Spalte mit einem Wert aus Ihrer der Datenbank ersetzt wird. Eine oft zugeordnete Spalte ist die Spalte, welche die IBAN des fremden Kontos enthält. Diese können leicht mit bereits angelegten IBANs in Ihrer Datenbank verglichen werden.',
'roles_table' => 'Tabelle',
'roles_column_name' => 'Name der Spalte',
'roles_column_example' => 'Beispieldaten',
'roles_column_role' => 'Bedeutung der Spalte',
'roles_do_map_value' => 'Ordnen Sie diese Werte zu',
'roles_column' => 'Spalte',
'roles_no_example_data' => 'Keine Beispieldaten vorhanden',
'roles_submit' => 'Fortfahren mit Schritt 3/3',
// map data
'map_title' => 'Import setup (3/3) - Connect import data to Firefly III data',
'map_title' => 'Import Einrichten (3/3) - Import mit bereits vorhandenen Daten verknüpfen',
'map_text' => 'In den folgenden Tabellen zeigt der linke Wert Informationen, die sich in Ihrer hochgeladenen CSV-Datei befinden. Es ist Ihre Aufgabe, diesen Wert, wenn möglich, einem bereits in der Datenbank vorhandem zuzuordnen. Firefly wird sich an diese Zuordnung halten. Wenn kein Wert für die Zuordnung vorhanden ist oder Sie den bestimmten Wert nicht abbilden möchten, wählen Sie nichts aus.',
'map_field_value' => 'Field value',
'map_field_mapped_to' => 'Mapped to',
'map_do_not_map' => '(do not map)',
'map_submit' => 'Start the import',
'map_field_value' => 'Feldwert',
'map_field_mapped_to' => 'Zugeordnet zu',
'map_do_not_map' => '(keine Zuordnung)',
'map_submit' => 'Starte den Import',
// map things.
'column__ignore' => '(diese Spalte ignorieren)',

View File

@ -11,13 +11,13 @@ return [
'no_demo_text' => 'Leider gibt es keine zusätzlichen Demoerklärungen für <abbr title=":route">diese Seite</abbr>.',
'see_help_icon' => 'Trotzdem kann der <i class="fa fa-question-circle"></i>-Icon in der oberen rechten Ecke mehr erzählen.',
'index' => 'Wilkommen bei <strong>Firefly III</strong>! Auf dieser Seite erhalten Sie einen schnellen Überblick über Ihre Finanzen. Für weitere Informationen, besuchen Sie die Accounts &rarr; <a href=":asset">Girokonten</a> und natürlich <a href=":budgets">Budgets</a> und <a href=":reports">Berichte</a> Seiten. Oder sehen Sie sich einfach um und schauen wo Sie landen.',
'accounts-index' => 'Asset accounts are your personal bank accounts. Expense accounts are the accounts you spend money at, such as stores and friends. Revenue accounts are accounts you receive money from, such as your job, the government or other sources of income. On this page you can edit or remove them.',
'budgets-index' => 'This page shows you an overview of your budgets. The top bar shows the amount that is available to be budgeted. This can be customized for any period by clicking the amount on the right. The amount you\'ve actually spent is shown in the bar below. Below that are the expenses per budget and what you\'ve budgeted for them.',
'reports-index-start' => 'Firefly III supports four types of reports. Read about them by clicking on the <i class="fa fa-question-circle"></i>-icon in the top right corner.',
'reports-index-examples' => 'Be sure to check out these examples: <a href=":one">a monthly financial overview</a>, <a href=":two">a yearly financial overview</a> and <a href=":three">a budget overview</a>.',
'currencies-index' => 'Firefly III supports multiple currencies. Although it defaults to the Euro it can be set to the US Dollar and many other currencies. As you can see a small selection of currencies has been included but you can add your own if you wish to. Changing the default currency will not change the currency of existing transactions however: Firefly III supports the use of multiple currencies at the same time.',
'transactions-index' => 'These expenses, deposits and transfers are not particularly imaginative. They have been generated automatically.',
'piggy-banks-index' => 'As you can see, there are three piggy banks. Use the plus and minus buttons to influence the amount of money in each piggy bank. Click the name of the piggy bank to see the administration for each piggy bank.',
'accounts-index' => 'Vermögenskonten sind Ihre persönlichen Bank-Konten. Aufwandskonten sind Konten, denen Sie Geld zahlen, z. B. Läden und Freunde. Einnahmekonten sind Konten von denen Sie Geld erhalten, z. B. Ihr Arbeitgeber und andere Einkommensquellen. Auf dieser Seite können Sie diese bearbeiten oder entfernen.',
'budgets-index' => 'Diese Seite zeigt Ihnen einen Überblick über Ihre Budgets. Die obere Leiste zeigt den Betrag, der zur Verfügung steht. Dieser kann für einen Zeitraum angepasst werden, indem Sie auf den Betrag auf der rechten Seite klicken. Wieviel bisher ausgegeb wurde wird darunter angezeigt. Darunter sind die Aufwendungen pro Haushalt und wieviel dafür veranschlagt ist.',
'reports-index-start' => 'Firefly III unterstützt vier Berichtarten. Mehr Informationen hirzu können durch ein Klick auf das <i class="fa fa-question-circle"></i> Symbol in der oberen rechten Ecke aufgerufen werden.',
'reports-index-examples' => 'Achten Sie darauf, diese Beispiele anzusehen: <a href=":one"> eine monatliche Finanzübersicht</a>, <a href=":two"> eine jährliche Finanzübersicht</a> und <a href=":three"> eine Haushaltsübersicht</a>.',
'currencies-index' => 'Firefly III unterstützt mehrere Währungen. Obwohl es den Euro standardmäßig nutzt, ist es möglich US-Dollar oder viele andere Währungen zu verwenden. Wie Sie sehen können, ist eine kleine Auswahl an Währungen aufgenommen worden, aber Sie können Ihre Eigenen hinzufügen. Die Standardwährung zu ändern, wird die Währung der vorhandenen Buchungen jedoch nicht ändern: Firefly III unterstützt die Verwendung mehrerer Währungen zur gleichen Zeit.',
'transactions-index' => 'Diese Aufwendungen, Einzahlungen und Überweisungen sind nicht besonders einfallsreich. Sie wurden automatisch generiert.',
'piggy-banks-index' => 'Wie Sie sehen können, gibt es drei Sparschweine. Benutzen die Plus- und Minusknöpfe um die Menge des Geldes in den Sparschweinen zu beeinflussen. Klicken Sie auf den Namen des Sparschweins um Details einzusehen.',
'import-index' => 'Natürlich kann eine CSV-Datei in Firefly III importiert werden ',
'import-configure-security' => 'Aufgrund von Sicherheitsbedenken wurde der Upload mit einer lokalen Datei ersetzt.',
'import-configure-configuration' => 'Die unten stehende Konfiguration für die lokale Datei ist korrekt.',

View File

@ -20,7 +20,7 @@ return [
'everything' => 'Alle',
'customRange' => 'Individueller Bereich',
'apply' => 'Übernehmen',
'select_date' => 'Select date..',
'select_date' => 'Wähle ein Datum..',
'cancel' => 'Abbrechen',
'from' => 'Von',
'to' => 'Bis',
@ -110,11 +110,11 @@ return [
'current_period' => 'Aktuelle Periode',
'show_the_current_period_and_overview' => 'Zeigen Sie die aktuelle Periode und die Übersicht',
'pref_languages_locale' => 'Damit eine andere Sprache als Englisch richtig funktioniert muss Ihr Betriebssystem mit den korrekten Gebietsschema-Informationen ausgestattet werden. Wenn diese nicht vorhanden sind, können die Währungsdaten, Terminen und Mengen falsch formatiert.',
'budget_in_period' => 'All transactions for budget ":name" between :start and :end',
'chart_budget_in_period' => 'Chart for all transactions for budget ":name" between :start and :end',
'chart_account_in_period' => 'Chart for all transactions for account ":name" between :start and :end',
'chart_category_in_period' => 'Chart for all transactions for category ":name" between :start and :end',
'chart_category_all' => 'Chart for all transactions for category ":name"',
'budget_in_period' => 'Alle Transaktionen für Haushalt :name zwischen :start und :end',
'chart_budget_in_period' => 'Diagramm für alle Transaktionen des Haushalts ":name" zwischen :start und :end',
'chart_account_in_period' => 'Diagramm für alle Transaktionen des Kontos ":name" zwischen :start und :end',
'chart_category_in_period' => 'Diagramm für alle Transaktionen der Kategorie ":name" zwischen :start und :end',
'chart_category_all' => 'Diagramm für alle Transaktionen der Kategorie ":name"',
'budget_in_period_breadcrumb' => 'Zwischen :start und :end',
'clone_withdrawal' => 'Diese Ausgabe klonen',
'clone_deposit' => 'Diese Einnahme klonen',
@ -129,9 +129,9 @@ return [
'all_journals_without_category' => 'Alle Transaktionen ohne Kategorie',
'journals_without_category' => 'Transaktionen ohne Kategorie',
'all_journals_for_account' => 'Alle Transaktionen für Konto :name',
'chart_all_journals_for_account' => 'Chart of all transactions for account :name',
'chart_all_journals_for_account' => 'Diagramm für alle Transaktionen des Kontos :name',
'journals_in_period_for_account' => 'Alle Transaktionen für Konto :name zwischen :start und :end',
'transferred' => 'Transferred',
'transferred' => 'Überwiesen',
'all_withdrawal' => 'Alle Ausgaben',
'all_transactions' => 'Alle Transaktionen',
'title_withdrawal_between' => 'Alle Ausgabe zwischen :start und :end',
@ -143,14 +143,14 @@ return [
'all_journals_for_tag' => 'Alle Transaktionen für Tag ":tag"',
'title_transfer_between' => 'Alle Transfers zwischen :start und :end',
'all_journals_for_category' => 'Alle Transaktionen für Kategorie :name',
'all_journals_for_budget' => 'All transactions for budget :name',
'chart_all_journals_for_budget' => 'Chart of all transactions for budget :name',
'all_journals_for_budget' => 'Alle Transaktionen des Haushalts :name',
'chart_all_journals_for_budget' => 'Diagramm für alle Transaktionen des Haushalts :name',
'journals_in_period_for_category' => 'Alle Transaktionen für Kategorie :name zwischen :start und :end',
'journals_in_period_for_tag' => 'Alle Transaktionen für Tag :tag zwischen :start und :end',
'not_available_demo_user' => 'Die Funktionen, auf welche sie zugreifen wollen, steht Demo-Benutzer nicht zur Verfügung.',
'exchange_rate_instructions' => 'Das Girokonto "@name" akzeptiert nur Transaktionen in @native_currency. Wenn Sie stattdessen @foreign_currency verwenden wollen, sollten Sie sicherstellen, dass der Betrag auch in @native_currency angengeben ist:',
'transfer_exchange_rate_instructions' => 'Das Quellkonto "@source_name" akzeptiert nur Transaktionen in @source_currency. Das Zielkonto "@dest_name" akzeptiert nur Transaktionen in @dest_currency. Sie müssen den Betrag in beiden Währungen korrenkt angeben.',
'transaction_data' => 'Transaction data',
'transaction_data' => 'Transaktionsdaten',
// repeat frequencies:
'repeat_freq_yearly' => 'Jährlich',
@ -480,7 +480,7 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?',
'create_new_withdrawal' => 'Erstelle eine neue Ausgabe',
'create_new_deposit' => 'Erstelle ein neues Einkommen',
'create_new_transfer' => 'Eine neue Überweisung erstellen',
'create_new_asset' => 'Erstellen Sie ein neuen Girokonto',
'create_new_asset' => 'Neues Girokonto erstellen',
'create_new_expense' => 'Neuen Debitor (Ausgabe) erstellen',
'create_new_revenue' => 'Neuen Schuldner erstellen',
'create_new_piggy_bank' => 'Ein neues Sparschwein erstellen',
@ -577,7 +577,7 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?',
'update_asset_account' => 'Girokonto aktualisieren',
'update_expense_account' => 'Debitor (Ausgabe) bearbeiten',
'update_revenue_account' => 'Schuldner bearbeiten',
'make_new_asset_account' => 'Erstellen Sie ein neuen Girokonto',
'make_new_asset_account' => 'Neues Girokonto erstellen',
'make_new_expense_account' => 'Neuen Debitor (Ausgabe) erstellen',
'make_new_revenue_account' => 'Neuen Schuldner erstellen',
'asset_accounts' => 'Girokonten',
@ -598,7 +598,7 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?',
'select_more_than_one_tag' => 'Bitte wählen Sie mehr als einen Tag aus',
'from_to' => 'Von :start bis :end',
'from_to_breadcrumb' => 'von :start bis :end',
'account_default_currency' => 'If you select another currency, new transactions from this account will have this currency pre-selected.',
'account_default_currency' => 'Wenn Sie eine andere Währung auswählen, werden neue Transaktionen von diesem Konto standardmäßig diese Währung ausgewählt haben.',
// categories:
'new_category' => 'Neue Kategorie',

View File

@ -68,7 +68,7 @@ return [
'exchanged_amount' => 'Ausgetauschter Betrag',
'source_amount' => 'Betrag (Quelle)',
'destination_amount' => 'Betrag (Ziel)',
'native_amount' => 'Native amount',
'native_amount' => 'Nativer Betrag',
'revenue_account_source' => 'Ertragskonto (Quelle)',
'source_account_asset' => 'Quellkonto (Bestandskonto)',

View File

@ -20,15 +20,15 @@ return [
'everything' => 'Wszystko',
'customRange' => 'Niestandardowy zakres',
'apply' => 'Zastosuj',
'select_date' => 'Select date..',
'select_date' => 'Wybierz datę...',
'cancel' => 'Anuluj',
'from' => 'Z',
'to' => 'Do',
'showEverything' => 'Pokaż wszystko',
'never' => 'Nigdy',
'search_results_for' => 'Wyniki wyszukiwania dla ":query"',
'advanced_search' => 'Advanced search',
'advanced_search_intro' => 'There are several modifiers that you can use in your search to narrow down the results. If you use any of these, the search will <em>only</em> return transactions. Please click the <i class="fa fa-question-circle"></i>-icon for more information.',
'advanced_search' => 'Wyszukiwanie zaawansowane',
'advanced_search_intro' => 'Istnieje kilka modyfikatorów, których można użyć w wyszukiwaniu, aby zawęzić wyniki. Jeśli używasz któregoś z nich, wyszukiwanie będzie zwracać <em>tylko</em> transakcje. Kliknij ikonę <i class="fa fa-question-circle"></i>, aby uzyskać więcej informacji.',
'bounced_error' => 'Wiadomość wysłana na adres :email została odrzucona, więc nie ma dostępu dla Ciebie.',
'deleted_error' => 'Te poświadczenia nie zgadzają się z naszymi danymi.',
'general_blocked_error' => 'Twoje konto zostało zablokowane. Dlatego nie możesz się zalogować.',

View File

@ -31,4 +31,4 @@
</div>
</div>
{% endif %}
{% endblock %}
{% endblock %}

View File

@ -7,7 +7,7 @@
<button type="button"
class="btn btn-default dropdown-toggle currency-dropdown" id="currency_dropdown_{{ name }}" data-toggle="dropdown"
aria-expanded="false">
<span id="currency_select_symbol_{{ name }}">{{ defaultCurrency.symbol|raw }}</span> <span class="caret"></span>
<span id="currency_select_symbol_{{ name }}">{{ defaultCurrency.symbol|raw }}X</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu currency-dropdown-menu" role="menu">
{% for currency in currencies %}

View File

@ -20,4 +20,4 @@
</div>
</div>
</div>
</div>

View File

@ -231,6 +231,10 @@
button['{{ type }}'] = '{{ trans('form.store_new_' ~ type) }}';
{% endfor %}
// some code for the foreign amount logic:
var useAccountCurrency = {% if preFilled.amount_currency_id_amount > 0 %}false{% else %}true{% endif %};
var overruleCurrency = {{ preFilled.amount_currency_id_amount|default(0) }};
</script>
<script type="text/javascript" src="js/lib/bootstrap3-typeahead.min.js"></script>
<script type="text/javascript" src="js/lib/bootstrap-tagsinput.min.js"></script>

View File

@ -9,9 +9,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
use Illuminate\Http\Request;
declare(strict_types=1);
/*
|--------------------------------------------------------------------------

View File

@ -9,7 +9,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
/*
|--------------------------------------------------------------------------

View File

@ -394,15 +394,12 @@ Route::group(
Route::post('start/{importJob}', ['uses' => 'ImportController@start', 'as' => 'start']);
//Route::get('settings/{importJob}', ['uses' => 'ImportController@settings', 'as' => 'settings']);
//Route::get('complete/{importJob}', ['uses' => 'ImportController@complete', 'as' => 'complete']);
//Route::get('finished/{importJob}', ['uses' => 'ImportController@finished', 'as' => 'finished']);
//Route::post('settings/{importJob}', ['uses' => 'ImportController@postSettings', 'as' => 'post-settings']);
}
);

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers\Admin;

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers\Admin;

View File

@ -81,9 +81,9 @@ class UserControllerTest extends TestCase
$repository = $this->mock(UserRepositoryInterface::class);
$repository->shouldReceive('changePassword')->once();
$repository->shouldReceive('changeStatus')->once();
$data = [
$data = [
'id' => 1,
'email' => 'test@example.com',
'email' => 'test@example.com',
'password' => 'james',
'password_confirmation' => 'james',
'blocked_code' => 'blocked',

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers;

View File

@ -48,4 +48,4 @@ class ForgotPasswordControllerTest extends TestCase
$response = $this->post(route('password.email'), $data);
$response->assertStatus(302);
}
}
}

View File

@ -101,7 +101,7 @@ class TwoFactorControllerTest extends TestCase
*/
public function testPostIndex()
{
$data = ['code' => '123456'];
$data = ['code' => '123456'];
$google = $this->mock(Google2FA::class);
$google->shouldReceive('verifyKey')->andReturn(true)->once();

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers;

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers;
@ -126,6 +126,46 @@ class BudgetControllerTest extends TestCase
$response->assertSee('<ol class="breadcrumb">');
}
/**
* @covers \FireflyIII\Http\Controllers\BudgetController::index
* @covers \FireflyIII\Http\Controllers\BudgetController::collectBudgetInformation
* @covers \FireflyIII\Http\Controllers\BudgetController::__construct
* @dataProvider dateRangeProvider
*
* @param string $range
*/
public function testIndex(string $range)
{
// mock stuff
$budget = factory(Budget::class)->make();
$budgetLimit = factory(BudgetLimit::class)->make();
// set budget limit to current month:
$budgetLimit->start_date = Carbon::now()->startOfMonth();
$budgetLimit->end_date = Carbon::now()->endOfMonth();
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$repository = $this->mock(BudgetRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$journalRepos->shouldReceive('first')->once()->andReturn(new TransactionJournal);
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
$repository->shouldReceive('cleanupBudgets');
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
$this->be($this->user());
$this->changeDateRange($this->user(), $range);
$response = $this->get(route('budgets.index'));
$response->assertStatus(200);
// has bread crumb
$response->assertSee('<ol class="breadcrumb">');
}
/**
* @covers \FireflyIII\Http\Controllers\BudgetController::index
* @covers \FireflyIII\Http\Controllers\BudgetController::collectBudgetInformation
@ -206,46 +246,6 @@ class BudgetControllerTest extends TestCase
$response->assertSee('<ol class="breadcrumb">');
}
/**
* @covers \FireflyIII\Http\Controllers\BudgetController::index
* @covers \FireflyIII\Http\Controllers\BudgetController::collectBudgetInformation
* @covers \FireflyIII\Http\Controllers\BudgetController::__construct
* @dataProvider dateRangeProvider
*
* @param string $range
*/
public function testIndex(string $range)
{
// mock stuff
$budget = factory(Budget::class)->make();
$budgetLimit = factory(BudgetLimit::class)->make();
// set budget limit to current month:
$budgetLimit->start_date = Carbon::now()->startOfMonth();
$budgetLimit->end_date = Carbon::now()->endOfMonth();
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$repository = $this->mock(BudgetRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$journalRepos->shouldReceive('first')->once()->andReturn(new TransactionJournal);
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
$repository->shouldReceive('cleanupBudgets');
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
$this->be($this->user());
$this->changeDateRange($this->user(), $range);
$response = $this->get(route('budgets.index'));
$response->assertStatus(200);
// has bread crumb
$response->assertSee('<ol class="breadcrumb">');
}
/**
* @covers \FireflyIII\Http\Controllers\BudgetController::noBudget
* @covers \FireflyIII\Http\Controllers\BudgetController::getPeriodOverview

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers;

View File

@ -327,7 +327,7 @@ class AccountControllerTest extends TestCase
*/
public function testRevenueAccounts(string $range)
{
$account = factory(Account::class)->make();
$account = factory(Account::class)->make();
$generator = $this->mock(GeneratorInterface::class);
$accountRepos = $this->mock(AccountRepositoryInterface::class);

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers\Chart;
@ -54,8 +54,8 @@ class BillControllerTest extends TestCase
public function testSingle()
{
$transaction = factory(Transaction::class)->make();
$generator = $this->mock(GeneratorInterface::class);
$collector = $this->mock(JournalCollectorInterface::class);
$generator = $this->mock(GeneratorInterface::class);
$collector = $this->mock(JournalCollectorInterface::class);
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf()->once();
$collector->shouldReceive('setBills')->andReturnSelf()->once();

View File

@ -139,7 +139,7 @@ class BudgetControllerTest extends TestCase
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$transactions = factory(Transaction::class, 10)->make();
$categories = factory(Category::class, 10)->make();
$categories = factory(Category::class, 10)->make();
$collector->shouldReceive('setAllAssetAccounts')->once()->andReturnSelf();
$collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->once()->andReturnSelf();

View File

@ -35,8 +35,8 @@ class BudgetReportControllerTest extends TestCase
*/
public function testAccountExpense()
{
$generator = $this->mock(GeneratorInterface::class);
$pieChart = $this->mock(MetaPieChartInterface::class);
$generator = $this->mock(GeneratorInterface::class);
$pieChart = $this->mock(MetaPieChartInterface::class);
$pieChart->shouldReceive('setAccounts')->once()->andReturnSelf();
$pieChart->shouldReceive('setBudgets')->once()->andReturnSelf();
@ -56,8 +56,8 @@ class BudgetReportControllerTest extends TestCase
*/
public function testBudgetExpense()
{
$generator = $this->mock(GeneratorInterface::class);
$pieChart = $this->mock(MetaPieChartInterface::class);
$generator = $this->mock(GeneratorInterface::class);
$pieChart = $this->mock(MetaPieChartInterface::class);
$pieChart->shouldReceive('setAccounts')->once()->andReturnSelf();
$pieChart->shouldReceive('setBudgets')->once()->andReturnSelf();
@ -118,4 +118,4 @@ class BudgetReportControllerTest extends TestCase
$response->assertStatus(200);
}
}
}

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers\Chart;

View File

@ -7,7 +7,7 @@
* See the LICENSE file for details.
*/
declare(strict_types = 1);
declare(strict_types=1);
namespace Tests\Feature\Controllers\Chart;

Some files were not shown because too many files have changed in this diff Show More