mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/4.1.4'
This commit is contained in:
commit
0a6f299ae6
30
CHANGELOG.md
30
CHANGELOG.md
@ -2,7 +2,37 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [4.1.4] - 2016-10-30
|
||||||
|
### Added
|
||||||
|
- New Dockerfile thanks to @schoentoon
|
||||||
|
- Added changing the destination account as rule action.
|
||||||
|
- Added changing the source account as rule action.
|
||||||
|
- Can convert transactions into different types.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Changed the export routine to be more future-proof.
|
||||||
|
- Improved help routine.
|
||||||
|
- Integrated CrowdIn translations.
|
||||||
|
- Simplified reports
|
||||||
|
- Change error message to refer to solution.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- #367 thanks to @HungryFeline
|
||||||
|
- #366 thanks to @3mz3t
|
||||||
|
- #362 and #341 thanks to @bnw
|
||||||
|
- #355 thanks to @roberthorlings
|
||||||
|
|
||||||
|
## [4.1.3] - 2016-10-22
|
||||||
|
### Fixed
|
||||||
|
- Some event handlers called the wrong method.
|
||||||
|
|
||||||
|
## [4.1.2] - 2016-10-22
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- A bug is fixed in the journal event handler that prevented Firefly III from actually storing journals.
|
||||||
|
|
||||||
## [4.1.1] - 2016-10-22
|
## [4.1.1] - 2016-10-22
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Option to show deposit accounts on the front page.
|
- Option to show deposit accounts on the front page.
|
||||||
- Script to upgrade split transactions
|
- Script to upgrade split transactions
|
||||||
|
42
Dockerfile
Normal file
42
Dockerfile
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
FROM php:7-apache
|
||||||
|
|
||||||
|
RUN apt-get update -y && \
|
||||||
|
apt-get install -y --no-install-recommends libcurl4-openssl-dev \
|
||||||
|
zlib1g-dev \
|
||||||
|
libjpeg62-turbo-dev \
|
||||||
|
libpng12-dev \
|
||||||
|
libicu-dev \
|
||||||
|
libmcrypt-dev \
|
||||||
|
libedit-dev \
|
||||||
|
libtidy-dev \
|
||||||
|
libxml2-dev \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libbz2-dev && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN docker-php-ext-install -j$(nproc) curl gd intl json mcrypt readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2
|
||||||
|
|
||||||
|
# Enable apache mod rewrite..
|
||||||
|
RUN a2enmod rewrite
|
||||||
|
|
||||||
|
# Setup the Composer installer
|
||||||
|
RUN curl -o /tmp/composer-setup.php https://getcomposer.org/installer && \
|
||||||
|
curl -o /tmp/composer-setup.sig https://composer.github.io/installer.sig && \
|
||||||
|
php -r "if (hash('SHA384', file_get_contents('/tmp/composer-setup.php')) !== trim(file_get_contents('/tmp/composer-setup.sig'))) { unlink('/tmp/composer-setup.php'); echo 'Invalid installer' . PHP_EOL; exit(1); }" && \
|
||||||
|
chmod +x /tmp/composer-setup.php && \
|
||||||
|
php /tmp/composer-setup.php && \
|
||||||
|
mv composer.phar /usr/local/bin/composer && \
|
||||||
|
rm -f /tmp/composer-setup.{php,sig}
|
||||||
|
|
||||||
|
ADD . /var/www/firefly-iii
|
||||||
|
RUN chown -R www-data:www-data /var/www/
|
||||||
|
ADD docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
|
||||||
|
|
||||||
|
USER www-data
|
||||||
|
|
||||||
|
WORKDIR /var/www/firefly-iii
|
||||||
|
|
||||||
|
RUN composer install --no-scripts --no-dev
|
||||||
|
|
||||||
|
USER root
|
@ -15,6 +15,7 @@ namespace FireflyIII\Console\Commands;
|
|||||||
|
|
||||||
use Crypt;
|
use Crypt;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
@ -84,6 +85,9 @@ class VerifyDatabase extends Command
|
|||||||
|
|
||||||
// transfers with budgets.
|
// transfers with budgets.
|
||||||
$this->reportTransfersBudgets();
|
$this->reportTransfersBudgets();
|
||||||
|
|
||||||
|
// report on journals with the wrong types of accounts.
|
||||||
|
$this->reportIncorrectJournals();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -202,6 +206,45 @@ class VerifyDatabase extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function reportIncorrectJournals()
|
||||||
|
{
|
||||||
|
$configuration = [
|
||||||
|
// a withdrawal can not have revenue account:
|
||||||
|
TransactionType::WITHDRAWAL => [AccountType::REVENUE],
|
||||||
|
|
||||||
|
// deposit cannot have an expense account:
|
||||||
|
TransactionType::DEPOSIT => [AccountType::EXPENSE],
|
||||||
|
|
||||||
|
// transfer cannot have either:
|
||||||
|
TransactionType::TRANSFER => [AccountType::EXPENSE, AccountType::REVENUE],
|
||||||
|
];
|
||||||
|
foreach ($configuration as $transactionType => $accountTypes) {
|
||||||
|
$set = TransactionJournal
|
||||||
|
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||||
|
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
|
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||||
|
->leftJoin('account_types', 'account_types.id', 'accounts.account_type_id')
|
||||||
|
->leftJoin('users', 'users.id', '=', 'transaction_journals.user_id')
|
||||||
|
->where('transaction_types.type', $transactionType)
|
||||||
|
->whereIn('account_types.type', $accountTypes)
|
||||||
|
->whereNull('transaction_journals.deleted_at')
|
||||||
|
->get(['transaction_journals.id', 'transaction_journals.user_id', 'users.email', 'account_types.type as a_type', 'transaction_types.type']);
|
||||||
|
foreach ($set as $entry) {
|
||||||
|
$this->error(
|
||||||
|
sprintf(
|
||||||
|
'Transaction journal #%d (user #%d, %s) is of type "%s" but ' .
|
||||||
|
'is linked to a "%s". The transaction journal should be recreated.',
|
||||||
|
$entry->id,
|
||||||
|
$entry->user_id,
|
||||||
|
$entry->email,
|
||||||
|
$entry->type,
|
||||||
|
$entry->a_type
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any deleted transaction journals that have transactions that are NOT deleted:
|
* Any deleted transaction journals that have transactions that are NOT deleted:
|
||||||
*/
|
*/
|
||||||
|
@ -13,11 +13,10 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Export\Collector;
|
namespace FireflyIII\Export\Collector;
|
||||||
|
|
||||||
use Amount;
|
use Carbon\Carbon;
|
||||||
use Crypt;
|
use Crypt;
|
||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use FireflyIII\Models\ExportJob;
|
use FireflyIII\Models\ExportJob;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -31,12 +30,14 @@ use Storage;
|
|||||||
*/
|
*/
|
||||||
class AttachmentCollector extends BasicCollector implements CollectorInterface
|
class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var Carbon */
|
||||||
private $explanationString = '';
|
private $end;
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
private $exportDisk;
|
private $exportDisk;
|
||||||
/** @var AttachmentRepositoryInterface */
|
/** @var AttachmentRepositoryInterface */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $start;
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
private $uploadDisk;
|
private $uploadDisk;
|
||||||
|
|
||||||
@ -69,34 +70,17 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
|||||||
$this->exportAttachment($attachment);
|
$this->exportAttachment($attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// put the explanation string in a file and attach it as well.
|
|
||||||
$file = $this->job->key . '-Source of all your attachments explained.txt';
|
|
||||||
$this->exportDisk->put($file, $this->explanationString);
|
|
||||||
$this->getFiles()->push($file);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Attachment $attachment
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
*/
|
*/
|
||||||
private function explain(Attachment $attachment)
|
public function setDates(Carbon $start, Carbon $end)
|
||||||
{
|
{
|
||||||
/** @var TransactionJournal $journal */
|
$this->start = $start;
|
||||||
$journal = $attachment->attachable;
|
$this->end = $end;
|
||||||
$args = [
|
|
||||||
'attachment_name' => e($attachment->filename),
|
|
||||||
'attachment_id' => $attachment->id,
|
|
||||||
'type' => strtolower($journal->transactionType->type),
|
|
||||||
'description' => e($journal->description),
|
|
||||||
'journal_id' => $journal->id,
|
|
||||||
'date' => $journal->date->formatLocalized(strval(trans('config.month_and_day'))),
|
|
||||||
'amount' => Amount::formatJournal($journal, false),
|
|
||||||
];
|
|
||||||
$string = trans('firefly.attachment_explanation', $args) . "\n";
|
|
||||||
Log::debug('Appended explanation string', ['string' => $string]);
|
|
||||||
$this->explanationString .= $string;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,10 +96,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
|||||||
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
|
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
|
||||||
$exportFile = $this->exportFileName($attachment);
|
$exportFile = $this->exportFileName($attachment);
|
||||||
$this->exportDisk->put($exportFile, $decrypted);
|
$this->exportDisk->put($exportFile, $decrypted);
|
||||||
$this->getFiles()->push($exportFile);
|
$this->getEntries()->push($exportFile);
|
||||||
|
|
||||||
// explain:
|
|
||||||
$this->explain($attachment);
|
|
||||||
} catch (DecryptException $e) {
|
} catch (DecryptException $e) {
|
||||||
Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage());
|
Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
@ -143,7 +125,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
|||||||
*/
|
*/
|
||||||
private function getAttachments(): Collection
|
private function getAttachments(): Collection
|
||||||
{
|
{
|
||||||
$attachments = $this->repository->get();
|
$attachments = $this->repository->getBetween($this->start, $this->end);
|
||||||
|
|
||||||
return $attachments;
|
return $attachments;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class BasicCollector
|
|||||||
/** @var ExportJob */
|
/** @var ExportJob */
|
||||||
protected $job;
|
protected $job;
|
||||||
/** @var Collection */
|
/** @var Collection */
|
||||||
private $files;
|
private $entries;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BasicCollector constructor.
|
* BasicCollector constructor.
|
||||||
@ -36,24 +36,24 @@ class BasicCollector
|
|||||||
*/
|
*/
|
||||||
public function __construct(ExportJob $job)
|
public function __construct(ExportJob $job)
|
||||||
{
|
{
|
||||||
$this->files = new Collection;
|
$this->entries = new Collection;
|
||||||
$this->job = $job;
|
$this->job = $job;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getFiles(): Collection
|
public function getEntries(): Collection
|
||||||
{
|
{
|
||||||
return $this->files;
|
return $this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $files
|
* @param Collection $entries
|
||||||
*/
|
*/
|
||||||
public function setFiles(Collection $files)
|
public function setEntries(Collection $entries)
|
||||||
{
|
{
|
||||||
$this->files = $files;
|
$this->entries = $entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ interface CollectorInterface
|
|||||||
/**
|
/**
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getFiles(): Collection;
|
public function getEntries(): Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
@ -33,9 +33,9 @@ interface CollectorInterface
|
|||||||
public function run(): bool;
|
public function run(): bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $files
|
* @param Collection $entries
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function setFiles(Collection $files);
|
public function setEntries(Collection $entries);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
348
app/Export/Collector/JournalCollector.php
Normal file
348
app/Export/Collector/JournalCollector.php
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* JournalCollector.php
|
||||||
|
* Copyright (C) 2016 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\Export\Collector;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Crypt;
|
||||||
|
use DB;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
|
use Illuminate\Database\Query\JoinClause;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class JournalCollector
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Export\Collector
|
||||||
|
*/
|
||||||
|
class JournalCollector extends BasicCollector implements CollectorInterface
|
||||||
|
{
|
||||||
|
/** @var Collection */
|
||||||
|
private $accounts;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $end;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $start;
|
||||||
|
|
||||||
|
/** @var Collection */
|
||||||
|
private $workSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function run(): bool
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Instead of collecting journals we collect transactions for the given accounts.
|
||||||
|
* We left join the OPPOSING transaction AND some journal data.
|
||||||
|
* After that we complement this info with budgets, categories, etc.
|
||||||
|
*
|
||||||
|
* This is way more efficient and will also work on split journals.
|
||||||
|
*/
|
||||||
|
$this->getWorkSet();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract:
|
||||||
|
* possible budget ids for journals
|
||||||
|
* possible category ids journals
|
||||||
|
* possible budget ids for transactions
|
||||||
|
* possible category ids for transactions
|
||||||
|
*
|
||||||
|
* possible IBAN and account numbers?
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$journals = $this->extractJournalIds();
|
||||||
|
$transactions = $this->extractTransactionIds();
|
||||||
|
|
||||||
|
|
||||||
|
// extend work set with category data from journals:
|
||||||
|
$this->categoryDataForJournals($journals);
|
||||||
|
|
||||||
|
// extend work set with category cate from transactions (overrules journals):
|
||||||
|
$this->categoryDataForTransactions($transactions);
|
||||||
|
|
||||||
|
// same for budgets:
|
||||||
|
$this->budgetDataForJournals($journals);
|
||||||
|
$this->budgetDataForTransactions($transactions);
|
||||||
|
|
||||||
|
$this->setEntries($this->workSet);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $accounts
|
||||||
|
*/
|
||||||
|
public function setAccounts(Collection $accounts)
|
||||||
|
{
|
||||||
|
$this->accounts = $accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*/
|
||||||
|
public function setDates(Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
$this->start = $start;
|
||||||
|
$this->end = $end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $journals
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function budgetDataForJournals(array $journals): bool
|
||||||
|
{
|
||||||
|
$set = DB::table('budget_transaction_journal')
|
||||||
|
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||||
|
->whereIn('budget_transaction_journal.transaction_journal_id', $journals)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'budget_transaction_journal.budget_id',
|
||||||
|
'budget_transaction_journal.transaction_journal_id',
|
||||||
|
'budgets.name',
|
||||||
|
'budgets.encrypted',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$set->each(
|
||||||
|
function ($obj) {
|
||||||
|
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$array = [];
|
||||||
|
foreach ($set as $obj) {
|
||||||
|
$array[$obj->transaction_journal_id] = ['id' => $obj->budget_id, 'name' => $obj->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workSet->each(
|
||||||
|
function ($obj) use ($array) {
|
||||||
|
if (isset($array[$obj->transaction_journal_id])) {
|
||||||
|
$obj->budget_id = $array[$obj->transaction_journal_id]['id'];
|
||||||
|
$obj->budget_name = $array[$obj->transaction_journal_id]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $transactions
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function budgetDataForTransactions(array $transactions): bool
|
||||||
|
{
|
||||||
|
$set = DB::table('budget_transaction')
|
||||||
|
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction.budget_id')
|
||||||
|
->whereIn('budget_transaction.transaction_id', $transactions)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'budget_transaction.budget_id',
|
||||||
|
'budget_transaction.transaction_id',
|
||||||
|
'budgets.name',
|
||||||
|
'budgets.encrypted',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$set->each(
|
||||||
|
function ($obj) {
|
||||||
|
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$array = [];
|
||||||
|
foreach ($set as $obj) {
|
||||||
|
$array[$obj->transaction_id] = ['id' => $obj->budget_id, 'name' => $obj->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workSet->each(
|
||||||
|
function ($obj) use ($array) {
|
||||||
|
|
||||||
|
// first transaction
|
||||||
|
if (isset($array[$obj->id])) {
|
||||||
|
$obj->budget_id = $array[$obj->id]['id'];
|
||||||
|
$obj->budget_name = $array[$obj->id]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $journals
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function categoryDataForJournals(array $journals): bool
|
||||||
|
{
|
||||||
|
$set = DB::table('category_transaction_journal')
|
||||||
|
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
|
||||||
|
->whereIn('category_transaction_journal.transaction_journal_id', $journals)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'category_transaction_journal.category_id',
|
||||||
|
'category_transaction_journal.transaction_journal_id',
|
||||||
|
'categories.name',
|
||||||
|
'categories.encrypted',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$set->each(
|
||||||
|
function ($obj) {
|
||||||
|
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$array = [];
|
||||||
|
foreach ($set as $obj) {
|
||||||
|
$array[$obj->transaction_journal_id] = ['id' => $obj->category_id, 'name' => $obj->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workSet->each(
|
||||||
|
function ($obj) use ($array) {
|
||||||
|
if (isset($array[$obj->transaction_journal_id])) {
|
||||||
|
$obj->category_id = $array[$obj->transaction_journal_id]['id'];
|
||||||
|
$obj->category_name = $array[$obj->transaction_journal_id]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $transactions
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function categoryDataForTransactions(array $transactions): bool
|
||||||
|
{
|
||||||
|
$set = DB::table('category_transaction')
|
||||||
|
->leftJoin('categories', 'categories.id', '=', 'category_transaction.category_id')
|
||||||
|
->whereIn('category_transaction.transaction_id', $transactions)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'category_transaction.category_id',
|
||||||
|
'category_transaction.transaction_id',
|
||||||
|
'categories.name',
|
||||||
|
'categories.encrypted',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$set->each(
|
||||||
|
function ($obj) {
|
||||||
|
$obj->name = $obj->encrypted === 1 ? Crypt::decrypt($obj->name) : $obj->name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$array = [];
|
||||||
|
foreach ($set as $obj) {
|
||||||
|
$array[$obj->transaction_id] = ['id' => $obj->category_id, 'name' => $obj->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workSet->each(
|
||||||
|
function ($obj) use ($array) {
|
||||||
|
|
||||||
|
// first transaction
|
||||||
|
if (isset($array[$obj->id])) {
|
||||||
|
$obj->category_id = $array[$obj->id]['id'];
|
||||||
|
$obj->category_name = $array[$obj->id]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function extractJournalIds(): array
|
||||||
|
{
|
||||||
|
return $this->workSet->pluck('transaction_journal_id')->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function extractTransactionIds()
|
||||||
|
{
|
||||||
|
$set = $this->workSet->pluck('id')->toArray();
|
||||||
|
$opposing = $this->workSet->pluck('opposing_id')->toArray();
|
||||||
|
$complete = $set + $opposing;
|
||||||
|
|
||||||
|
return array_unique($complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function getWorkSet()
|
||||||
|
{
|
||||||
|
$accountIds = $this->accounts->pluck('id')->toArray();
|
||||||
|
$this->workSet = Transaction
|
||||||
|
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->leftJoin(
|
||||||
|
'transactions AS opposing', function (JoinClause $join) {
|
||||||
|
$join->on('opposing.transaction_journal_id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->where('opposing.amount', '=', DB::raw('transactions.amount * -1'))
|
||||||
|
->where('transactions.identifier', '=', 'opposing.identifier');
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')
|
||||||
|
->leftJoin('accounts AS opposing_accounts', 'opposing.account_id', '=', 'opposing_accounts.id')
|
||||||
|
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', 'transaction_types.id')
|
||||||
|
->leftJoin('transaction_currencies', 'transaction_journals.transaction_currency_id', '=', 'transaction_currencies.id')
|
||||||
|
->whereIn('transactions.account_id', $accountIds)
|
||||||
|
->where('transaction_journals.user_id', $this->job->user_id)
|
||||||
|
->where('transaction_journals.date', '>=', $this->start->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.date', '<=', $this->end->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.completed', 1)
|
||||||
|
->whereNull('transaction_journals.deleted_at')
|
||||||
|
->whereNull('transactions.deleted_at')
|
||||||
|
->whereNull('opposing.deleted_at')
|
||||||
|
->orderBy('transaction_journals.date', 'DESC')
|
||||||
|
->orderBy('transactions.identifier', 'ASC')
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'transactions.id',
|
||||||
|
'transactions.amount',
|
||||||
|
'transactions.description',
|
||||||
|
'transactions.account_id',
|
||||||
|
'accounts.name as account_name',
|
||||||
|
'accounts.encrypted as account_name_encrypted',
|
||||||
|
'transactions.identifier',
|
||||||
|
|
||||||
|
'opposing.id as opposing_id',
|
||||||
|
'opposing.amount AS opposing_amount',
|
||||||
|
'opposing.description as opposing_description',
|
||||||
|
'opposing.account_id as opposing_account_id',
|
||||||
|
'opposing_accounts.name as opposing_account_name',
|
||||||
|
'opposing_accounts.encrypted as opposing_account_encrypted',
|
||||||
|
'opposing.identifier as opposing_identifier',
|
||||||
|
|
||||||
|
'transaction_journals.id as transaction_journal_id',
|
||||||
|
'transaction_journals.date',
|
||||||
|
'transaction_journals.description as journal_description',
|
||||||
|
'transaction_journals.encrypted as journal_encrypted',
|
||||||
|
'transaction_journals.transaction_type_id',
|
||||||
|
'transaction_types.type as transaction_type',
|
||||||
|
'transaction_journals.transaction_currency_id',
|
||||||
|
'transaction_currencies.code AS transaction_currency_code',
|
||||||
|
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -26,16 +26,14 @@ use Storage;
|
|||||||
*/
|
*/
|
||||||
class UploadCollector extends BasicCollector implements CollectorInterface
|
class UploadCollector extends BasicCollector implements CollectorInterface
|
||||||
{
|
{
|
||||||
/** @var string */
|
|
||||||
private $expected;
|
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
private $exportDisk;
|
private $exportDisk;
|
||||||
private $importKeys = [];
|
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
private $uploadDisk;
|
private $uploadDisk;
|
||||||
|
/** @var string */
|
||||||
|
private $vintageFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* AttachmentCollector constructor.
|
* AttachmentCollector constructor.
|
||||||
*
|
*
|
||||||
* @param ExportJob $job
|
* @param ExportJob $job
|
||||||
@ -51,50 +49,74 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
|||||||
$this->exportDisk = Storage::disk('export');
|
$this->exportDisk = Storage::disk('export');
|
||||||
|
|
||||||
// file names associated with the old import routine.
|
// file names associated with the old import routine.
|
||||||
$this->expected = 'csv-upload-' . auth()->user()->id . '-';
|
$this->vintageFormat = sprintf('csv-upload-%d-', auth()->user()->id);
|
||||||
|
|
||||||
// for the new import routine:
|
|
||||||
$this->getImportKeys();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Is called from the outside to actually start the export.
|
||||||
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function run(): bool
|
public function run(): bool
|
||||||
{
|
{
|
||||||
// grab upload directory.
|
// collect old upload files (names beginning with "csv-upload".
|
||||||
$files = $this->uploadDisk->files();
|
$this->collectVintageUploads();
|
||||||
|
|
||||||
foreach ($files as $entry) {
|
// then collect current upload files:
|
||||||
$this->processUpload($entry);
|
$this->collectModernUploads();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method collects all the uploads that are uploaded using the new importer. So after the summer of 2016.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function collectModernUploads(): bool
|
||||||
|
{
|
||||||
|
$set = $this->job->user->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
|
||||||
|
$keys = [];
|
||||||
|
if ($set->count() > 0) {
|
||||||
|
$keys = $set->pluck('key')->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$this->processModernUpload($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This method collects all the uploads that are uploaded using the "old" importer. So from before the summer of 2016.
|
||||||
*
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function getImportKeys()
|
private function collectVintageUploads():bool
|
||||||
{
|
{
|
||||||
$set = auth()->user()->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
|
// grab upload directory.
|
||||||
if ($set->count() > 0) {
|
$files = $this->uploadDisk->files();
|
||||||
$keys = $set->pluck('key')->toArray();
|
|
||||||
$this->importKeys = $keys;
|
|
||||||
|
|
||||||
|
foreach ($files as $entry) {
|
||||||
|
$this->processVintageUpload($entry);
|
||||||
}
|
}
|
||||||
Log::debug('Valid import keys are ', $this->importKeys);
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This method tells you when the vintage upload file was actually uploaded.
|
||||||
|
*
|
||||||
* @param string $entry
|
* @param string $entry
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function getOriginalUploadDate(string $entry): string
|
private function getVintageUploadDate(string $entry): string
|
||||||
{
|
{
|
||||||
// this is an original upload.
|
// this is an original upload.
|
||||||
$parts = explode('-', str_replace(['.csv.encrypted', $this->expected], '', $entry));
|
$parts = explode('-', str_replace(['.csv.encrypted', $this->vintageFormat], '', $entry));
|
||||||
$originalUpload = intval($parts[1]);
|
$originalUpload = intval($parts[1]);
|
||||||
$date = date('Y-m-d \a\t H-i-s', $originalUpload);
|
$date = date('Y-m-d \a\t H-i-s', $originalUpload);
|
||||||
|
|
||||||
@ -102,33 +124,17 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Tells you if a file name is a vintage upload.
|
||||||
|
*
|
||||||
* @param string $entry
|
* @param string $entry
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function isImportFile(string $entry): bool
|
private function isVintageImport(string $entry): bool
|
||||||
{
|
{
|
||||||
$name = str_replace('.upload', '', $entry);
|
$len = strlen($this->vintageFormat);
|
||||||
if (in_array($name, $this->importKeys)) {
|
|
||||||
Log::debug(sprintf('Import file "%s" is in array', $name), $this->importKeys);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Log::debug(sprintf('Import file "%s" is NOT in array', $name), $this->importKeys);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $entry
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function isOldImport(string $entry): bool
|
|
||||||
{
|
|
||||||
$len = strlen($this->expected);
|
|
||||||
// file is part of the old import routine:
|
// file is part of the old import routine:
|
||||||
if (substr($entry, 0, $len) === $this->expected) {
|
if (substr($entry, 0, $len) === $this->vintageFormat) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -137,49 +143,62 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $entry
|
* @param string $key
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function processUpload(string $entry)
|
private function processModernUpload(string $key): bool
|
||||||
{
|
|
||||||
// file is old import:
|
|
||||||
if ($this->isOldImport($entry)) {
|
|
||||||
$this->saveOldImportFile($entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// file is current import.
|
|
||||||
if ($this->isImportFile($entry)) {
|
|
||||||
$this->saveImportFile($entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $entry
|
|
||||||
*/
|
|
||||||
private function saveImportFile(string $entry)
|
|
||||||
{
|
{
|
||||||
// find job associated with import file:
|
// find job associated with import file:
|
||||||
$name = str_replace('.upload', '', $entry);
|
$job = $this->job->user->importJobs()->where('key', $key)->first();
|
||||||
$job = auth()->user()->importJobs()->where('key', $name)->first();
|
if (is_null($job)) {
|
||||||
$content = '';
|
return false;
|
||||||
try {
|
|
||||||
$content = Crypt::decrypt($this->uploadDisk->get($entry));
|
|
||||||
} catch (DecryptException $e) {
|
|
||||||
Log::error('Could not decrypt old import file ' . $entry . '. Skipped because ' . $e->getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_null($job) && strlen($content) > 0) {
|
// find the file for this import:
|
||||||
|
$content = '';
|
||||||
|
try {
|
||||||
|
$content = Crypt::decrypt($this->uploadDisk->get(sprintf('%s.upload', $key)));
|
||||||
|
} catch (DecryptException $e) {
|
||||||
|
Log::error(sprintf('Could not decrypt old import file "%s". Skipped because: %s', $key, $e->getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($content) > 0) {
|
||||||
// add to export disk.
|
// add to export disk.
|
||||||
$date = $job->created_at->format('Y-m-d');
|
$date = $job->created_at->format('Y-m-d');
|
||||||
$file = sprintf('%s-Old %s import dated %s.%s', $this->job->key, strtoupper($job->file_type), $date, $job->file_type);
|
$file = sprintf('%s-Old %s import dated %s.%s', $this->job->key, strtoupper($job->file_type), $date, $job->file_type);
|
||||||
$this->exportDisk->put($file, $content);
|
$this->exportDisk->put($file, $content);
|
||||||
$this->getFiles()->push($file);
|
$this->getEntries()->push($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* If the file is a vintage upload, process it.
|
||||||
|
*
|
||||||
|
* @param string $entry
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function processVintageUpload(string $entry): bool
|
||||||
|
{
|
||||||
|
if ($this->isVintageImport($entry)) {
|
||||||
|
$this->saveVintageImportFile($entry);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will store the content of the old vintage upload somewhere.
|
||||||
|
*
|
||||||
* @param string $entry
|
* @param string $entry
|
||||||
*/
|
*/
|
||||||
private function saveOldImportFile(string $entry)
|
private function saveVintageImportFile(string $entry)
|
||||||
{
|
{
|
||||||
$content = '';
|
$content = '';
|
||||||
try {
|
try {
|
||||||
@ -190,10 +209,10 @@ class UploadCollector extends BasicCollector implements CollectorInterface
|
|||||||
|
|
||||||
if (strlen($content) > 0) {
|
if (strlen($content) > 0) {
|
||||||
// add to export disk.
|
// add to export disk.
|
||||||
$date = $this->getOriginalUploadDate($entry);
|
$date = $this->getVintageUploadDate($entry);
|
||||||
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
|
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
|
||||||
$this->exportDisk->put($file, $content);
|
$this->exportDisk->put($file, $content);
|
||||||
$this->getFiles()->push($file);
|
$this->getEntries()->push($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* ConfigurationFile.php
|
|
||||||
* Copyright (C) 2016 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\Export;
|
|
||||||
|
|
||||||
use FireflyIII\Export\Entry\Entry;
|
|
||||||
use FireflyIII\Models\ExportJob;
|
|
||||||
use Storage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ConfigurationFile
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export
|
|
||||||
*/
|
|
||||||
class ConfigurationFile
|
|
||||||
{
|
|
||||||
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
|
||||||
private $exportDisk;
|
|
||||||
/** @var ExportJob */
|
|
||||||
private $job;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ConfigurationFile constructor.
|
|
||||||
*
|
|
||||||
* @param ExportJob $job
|
|
||||||
*/
|
|
||||||
public function __construct(ExportJob $job)
|
|
||||||
{
|
|
||||||
$this->job = $job;
|
|
||||||
$this->exportDisk = Storage::disk('export');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function make(): string
|
|
||||||
{
|
|
||||||
$fields = array_keys(Entry::getFieldsAndTypes());
|
|
||||||
$types = Entry::getFieldsAndTypes();
|
|
||||||
|
|
||||||
$configuration = [
|
|
||||||
'date-format' => 'Y-m-d', // unfortunately, this is hard-coded.
|
|
||||||
'has-headers' => true,
|
|
||||||
'map' => [], // we could build a map if necessary for easy re-import.
|
|
||||||
'roles' => [],
|
|
||||||
'mapped' => [],
|
|
||||||
'specifix' => [],
|
|
||||||
];
|
|
||||||
foreach ($fields as $field) {
|
|
||||||
$configuration['roles'][] = $types[$field];
|
|
||||||
}
|
|
||||||
$file = $this->job->key . '-configuration.json';
|
|
||||||
$this->exportDisk->put($file, json_encode($configuration, JSON_PRETTY_PRINT));
|
|
||||||
|
|
||||||
return $file;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -13,8 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Export\Entry;
|
namespace FireflyIII\Export\Entry;
|
||||||
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use Crypt;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To extend the exported object, in case of new features in Firefly III for example,
|
* To extend the exported object, in case of new features in Firefly III for example,
|
||||||
@ -35,98 +34,77 @@ use Illuminate\Support\Collection;
|
|||||||
*/
|
*/
|
||||||
final class Entry
|
final class Entry
|
||||||
{
|
{
|
||||||
/** @var string */
|
// @formatter:off
|
||||||
public $amount;
|
public $journal_id;
|
||||||
/** @var EntryBill */
|
|
||||||
public $bill;
|
|
||||||
/** @var EntryBudget */
|
|
||||||
public $budget;
|
|
||||||
/** @var EntryCategory */
|
|
||||||
public $category;
|
|
||||||
/** @var string */
|
|
||||||
public $date;
|
public $date;
|
||||||
/** @var string */
|
|
||||||
public $description;
|
public $description;
|
||||||
/** @var EntryAccount */
|
|
||||||
public $destinationAccount;
|
public $currency_code;
|
||||||
/** @var Collection */
|
public $amount;
|
||||||
public $destinationAccounts;
|
|
||||||
/** @var EntryAccount */
|
public $transaction_type;
|
||||||
public $sourceAccount;
|
|
||||||
/** @var Collection */
|
public $source_account_id;
|
||||||
public $sourceAccounts;
|
public $source_account_name;
|
||||||
|
|
||||||
|
public $destination_account_id;
|
||||||
|
public $destination_account_name;
|
||||||
|
|
||||||
|
|
||||||
|
public $budget_id;
|
||||||
|
public $budget_name;
|
||||||
|
public $category_id;
|
||||||
|
public $category_name;
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry constructor.
|
* Entry constructor.
|
||||||
*/
|
*/
|
||||||
private function __construct()
|
private function __construct()
|
||||||
{
|
{
|
||||||
$this->sourceAccounts = new Collection;
|
|
||||||
$this->destinationAccounts = new Collection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TransactionJournal $journal
|
* @param $object
|
||||||
*
|
*
|
||||||
* @return Entry
|
* @return Entry
|
||||||
*/
|
*/
|
||||||
public static function fromJournal(TransactionJournal $journal)
|
public static function fromObject($object): Entry
|
||||||
{
|
{
|
||||||
|
$entry = new self;
|
||||||
|
|
||||||
$entry = new self;
|
// journal information:
|
||||||
$entry->description = $journal->description;
|
$entry->journal_id = $object->transaction_journal_id;
|
||||||
$entry->date = $journal->date->format('Y-m-d');
|
$entry->description = $object->journal_encrypted === 1 ? Crypt::decrypt($object->journal_description) : $object->journal_description;
|
||||||
$entry->amount = TransactionJournal::amount($journal);
|
$entry->amount = round($object->amount, 2); // always positive
|
||||||
|
$entry->date = $object->date;
|
||||||
|
$entry->transaction_type = $object->transaction_type;
|
||||||
|
$entry->currency_code = $object->transaction_currency_code;
|
||||||
|
|
||||||
$entry->budget = new EntryBudget($journal->budgets->first());
|
// source information:
|
||||||
$entry->category = new EntryCategory($journal->categories->first());
|
$entry->source_account_id = $object->account_id;
|
||||||
$entry->bill = new EntryBill($journal->bill);
|
$entry->source_account_name = $object->account_name_encrypted === 1 ? Crypt::decrypt($object->account_name) : $object->account_name;
|
||||||
|
|
||||||
$sources = TransactionJournal::sourceAccountList($journal);
|
|
||||||
$destinations = TransactionJournal::destinationAccountList($journal);
|
|
||||||
$entry->sourceAccount = new EntryAccount($sources->first());
|
|
||||||
$entry->destinationAccount = new EntryAccount($destinations->first());
|
|
||||||
|
|
||||||
foreach ($sources as $source) {
|
// destination information
|
||||||
$entry->sourceAccounts->push(new EntryAccount($source));
|
$entry->destination_account_id = $object->opposing_account_id;
|
||||||
}
|
$entry->destination_account_name = $object->opposing_account_encrypted === 1 ? Crypt::decrypt($object->opposing_account_name)
|
||||||
|
: $object->opposing_account_name;
|
||||||
|
|
||||||
foreach ($destinations as $destination) {
|
|
||||||
$entry->destinationAccounts->push(new EntryAccount($destination));
|
// category and budget
|
||||||
|
$entry->category_id = $object->category_id ?? '';
|
||||||
|
$entry->category_name = $object->category_name ?? '';
|
||||||
|
$entry->budget_id = $object->budget_id ?? '';
|
||||||
|
$entry->budget_name = $object->budget_name ?? '';
|
||||||
|
|
||||||
|
|
||||||
|
// update description when transaction description is different:
|
||||||
|
if (!is_null($object->description) && $object->description != $entry->description) {
|
||||||
|
$entry->description = $entry->description . ' (' . $object->description . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $entry;
|
return $entry;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public static function getFieldsAndTypes(): array
|
|
||||||
{
|
|
||||||
// key = field name (see top of class)
|
|
||||||
// value = field type (see csv.php under 'roles')
|
|
||||||
return [
|
|
||||||
'description' => 'description',
|
|
||||||
'amount' => 'amount',
|
|
||||||
'date' => 'date-transaction',
|
|
||||||
'source_account_id' => 'account-id',
|
|
||||||
'source_account_name' => 'account-name',
|
|
||||||
'source_account_iban' => 'account-iban',
|
|
||||||
'source_account_type' => '_ignore',
|
|
||||||
'source_account_number' => 'account-number',
|
|
||||||
'destination_account_id' => 'opposing-id',
|
|
||||||
'destination_account_name' => 'opposing-name',
|
|
||||||
'destination_account_iban' => 'opposing-iban',
|
|
||||||
'destination_account_type' => '_ignore',
|
|
||||||
'destination_account_number' => 'account-number',
|
|
||||||
'budget_id' => 'budget-id',
|
|
||||||
'budget_name' => 'budget-name',
|
|
||||||
'category_id' => 'category-id',
|
|
||||||
'category_name' => 'category-name',
|
|
||||||
'bill_id' => 'bill-id',
|
|
||||||
'bill_name' => 'bill-name',
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* EntryAccount.php
|
|
||||||
* Copyright (C) 2016 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\Export\Entry;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Account;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EntryAccount
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export\Entry
|
|
||||||
*/
|
|
||||||
class EntryAccount
|
|
||||||
{
|
|
||||||
/** @var int */
|
|
||||||
public $accountId;
|
|
||||||
/** @var string */
|
|
||||||
public $iban;
|
|
||||||
/** @var string */
|
|
||||||
public $name;
|
|
||||||
/** @var string */
|
|
||||||
public $number;
|
|
||||||
/** @var string */
|
|
||||||
public $type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EntryAccount constructor.
|
|
||||||
*
|
|
||||||
* @param Account $account
|
|
||||||
*/
|
|
||||||
public function __construct(Account $account)
|
|
||||||
{
|
|
||||||
$this->accountId = $account->id;
|
|
||||||
$this->name = $account->name;
|
|
||||||
$this->iban = $account->iban;
|
|
||||||
$this->type = $account->accountType->type;
|
|
||||||
$this->number = $account->getMeta('accountNumber');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* EntryBill.php
|
|
||||||
* Copyright (C) 2016 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\Export\Entry;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Bill;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EntryBill
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export\Entry
|
|
||||||
*/
|
|
||||||
class EntryBill
|
|
||||||
{
|
|
||||||
/** @var int */
|
|
||||||
public $billId = '';
|
|
||||||
/** @var string */
|
|
||||||
public $name = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EntryBill constructor.
|
|
||||||
*
|
|
||||||
* @param Bill $bill
|
|
||||||
*/
|
|
||||||
public function __construct(Bill $bill = null)
|
|
||||||
{
|
|
||||||
if (!is_null($bill)) {
|
|
||||||
$this->billId = $bill->id;
|
|
||||||
$this->name = $bill->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* EntryBudget.php
|
|
||||||
* Copyright (C) 2016 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\Export\Entry;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Budget;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EntryBudget
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export\Entry
|
|
||||||
*/
|
|
||||||
class EntryBudget
|
|
||||||
{
|
|
||||||
/** @var int */
|
|
||||||
public $budgetId = '';
|
|
||||||
/** @var string */
|
|
||||||
public $name = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EntryBudget constructor.
|
|
||||||
*
|
|
||||||
* @param Budget $budget
|
|
||||||
*/
|
|
||||||
public function __construct(Budget $budget = null)
|
|
||||||
{
|
|
||||||
if (!is_null($budget)) {
|
|
||||||
$this->budgetId = $budget->id;
|
|
||||||
$this->name = $budget->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* EntryCategory.php
|
|
||||||
* Copyright (C) 2016 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\Export\Entry;
|
|
||||||
|
|
||||||
use FireflyIII\Models\Category;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class EntryCategory
|
|
||||||
*
|
|
||||||
* @package FireflyIII\Export\Entry
|
|
||||||
*/
|
|
||||||
class EntryCategory
|
|
||||||
{
|
|
||||||
/** @var int */
|
|
||||||
public $categoryId = '';
|
|
||||||
/** @var string */
|
|
||||||
public $name = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EntryCategory constructor.
|
|
||||||
*
|
|
||||||
* @param Category $category
|
|
||||||
*/
|
|
||||||
public function __construct(Category $category = null)
|
|
||||||
{
|
|
||||||
if (!is_null($category)) {
|
|
||||||
$this->categoryId = $category->id;
|
|
||||||
$this->name = $category->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ namespace FireflyIII\Export\Exporter;
|
|||||||
use FireflyIII\Export\Entry\Entry;
|
use FireflyIII\Export\Entry\Entry;
|
||||||
use FireflyIII\Export\Entry\EntryAccount;
|
use FireflyIII\Export\Entry\EntryAccount;
|
||||||
use FireflyIII\Models\ExportJob;
|
use FireflyIII\Models\ExportJob;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use League\Csv\Writer;
|
use League\Csv\Writer;
|
||||||
use SplFileObject;
|
use SplFileObject;
|
||||||
|
|
||||||
@ -62,110 +61,24 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
|||||||
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
|
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
|
||||||
$rows = [];
|
$rows = [];
|
||||||
|
|
||||||
// Count the maximum number of sources and destinations each entry has. May need to expand the number of export fields:
|
// get field names for header row:
|
||||||
$maxSourceAccounts = 1;
|
$first = $this->getEntries()->first();
|
||||||
$maxDestAccounts = 1;
|
$headers = array_keys(get_object_vars($first));
|
||||||
/** @var Entry $entry */
|
$rows[] = $headers;
|
||||||
foreach ($this->getEntries() as $entry) {
|
|
||||||
$sources = $entry->sourceAccounts->count();
|
|
||||||
$destinations = $entry->destinationAccounts->count();
|
|
||||||
$maxSourceAccounts = max($maxSourceAccounts, $sources);
|
|
||||||
$maxDestAccounts = max($maxDestAccounts, $destinations);
|
|
||||||
}
|
|
||||||
$rows[] = array_keys($this->getFieldsAndTypes($maxSourceAccounts, $maxDestAccounts));
|
|
||||||
|
|
||||||
/** @var Entry $entry */
|
/** @var Entry $entry */
|
||||||
foreach ($this->getEntries() as $entry) {
|
foreach ($this->getEntries() as $entry) {
|
||||||
// order is defined in Entry::getFieldsAndTypes.
|
$line = [];
|
||||||
$current = [$entry->description, $entry->amount, $entry->date];
|
foreach ($headers as $header) {
|
||||||
$sourceData = $this->getAccountData($maxSourceAccounts, $entry->sourceAccounts);
|
$line[] = $entry->$header;
|
||||||
$current = array_merge($current, $sourceData);
|
}
|
||||||
$destData = $this->getAccountData($maxDestAccounts, $entry->destinationAccounts);
|
$rows[] = $line;
|
||||||
$current = array_merge($current, $destData);
|
|
||||||
$rest = [$entry->budget->budgetId, $entry->budget->name, $entry->category->categoryId, $entry->category->name, $entry->bill->billId,
|
|
||||||
$entry->bill->name];
|
|
||||||
$current = array_merge($current, $rest);
|
|
||||||
$rows[] = $current;
|
|
||||||
}
|
}
|
||||||
$writer->insertAll($rows);
|
$writer->insertAll($rows);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $max
|
|
||||||
* @param Collection $accounts
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getAccountData(int $max, Collection $accounts): array
|
|
||||||
{
|
|
||||||
$current = [];
|
|
||||||
for ($i = 0; $i < $max; $i++) {
|
|
||||||
/** @var EntryAccount $source */
|
|
||||||
$source = $accounts->get($i);
|
|
||||||
$currentId = '';
|
|
||||||
$currentName = '';
|
|
||||||
$currentIban = '';
|
|
||||||
$currentType = '';
|
|
||||||
$currentNumber = '';
|
|
||||||
if ($source) {
|
|
||||||
$currentId = $source->accountId;
|
|
||||||
$currentName = $source->name;
|
|
||||||
$currentIban = $source->iban;
|
|
||||||
$currentType = $source->type;
|
|
||||||
$currentNumber = $source->number;
|
|
||||||
}
|
|
||||||
$current[] = $currentId;
|
|
||||||
$current[] = $currentName;
|
|
||||||
$current[] = $currentIban;
|
|
||||||
$current[] = $currentType;
|
|
||||||
$current[] = $currentNumber;
|
|
||||||
}
|
|
||||||
unset($source);
|
|
||||||
|
|
||||||
return $current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $sources
|
|
||||||
* @param int $destinations
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getFieldsAndTypes(int $sources, int $destinations): array
|
|
||||||
{
|
|
||||||
// key = field name (see top of class)
|
|
||||||
// value = field type (see csv.php under 'roles')
|
|
||||||
$array = [
|
|
||||||
'description' => 'description',
|
|
||||||
'amount' => 'amount',
|
|
||||||
'date' => 'date-transaction',
|
|
||||||
];
|
|
||||||
for ($i = 0; $i < $sources; $i++) {
|
|
||||||
$array['source_account_' . $i . '_id'] = 'account-id';
|
|
||||||
$array['source_account_' . $i . '_name'] = 'account-name';
|
|
||||||
$array['source_account_' . $i . '_iban'] = 'account-iban';
|
|
||||||
$array['source_account_' . $i . '_type'] = '_ignore';
|
|
||||||
$array['source_account_' . $i . '_number'] = 'account-number';
|
|
||||||
}
|
|
||||||
for ($i = 0; $i < $destinations; $i++) {
|
|
||||||
$array['destination_account_' . $i . '_id'] = 'account-id';
|
|
||||||
$array['destination_account_' . $i . '_name'] = 'account-name';
|
|
||||||
$array['destination_account_' . $i . '_iban'] = 'account-iban';
|
|
||||||
$array['destination_account_' . $i . '_type'] = '_ignore';
|
|
||||||
$array['destination_account_' . $i . '_number'] = 'account-number';
|
|
||||||
}
|
|
||||||
|
|
||||||
$array['budget_id'] = 'budget-id';
|
|
||||||
$array['budget_name'] = 'budget-name';
|
|
||||||
$array['category_id'] = 'category-id';
|
|
||||||
$array['category_name'] = 'category-name';
|
|
||||||
$array['bill_id'] = 'bill-id';
|
|
||||||
$array['bill_name'] = 'bill-name';
|
|
||||||
|
|
||||||
return $array;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function tempFile()
|
private function tempFile()
|
||||||
{
|
{
|
||||||
|
@ -15,13 +15,13 @@ namespace FireflyIII\Export;
|
|||||||
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Export\Collector\AttachmentCollector;
|
use FireflyIII\Export\Collector\AttachmentCollector;
|
||||||
|
use FireflyIII\Export\Collector\JournalCollector;
|
||||||
use FireflyIII\Export\Collector\UploadCollector;
|
use FireflyIII\Export\Collector\UploadCollector;
|
||||||
use FireflyIII\Export\Entry\Entry;
|
use FireflyIII\Export\Entry\Entry;
|
||||||
use FireflyIII\Models\ExportJob;
|
use FireflyIII\Models\ExportJob;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
|
|
||||||
use Illuminate\Filesystem\FilesystemAdapter;
|
use Illuminate\Filesystem\FilesystemAdapter;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
use Storage;
|
use Storage;
|
||||||
use ZipArchive;
|
use ZipArchive;
|
||||||
|
|
||||||
@ -40,8 +40,6 @@ class Processor
|
|||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $includeAttachments;
|
public $includeAttachments;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $includeConfig;
|
|
||||||
/** @var bool */
|
|
||||||
public $includeOldUploads;
|
public $includeOldUploads;
|
||||||
/** @var ExportJob */
|
/** @var ExportJob */
|
||||||
public $job;
|
public $job;
|
||||||
@ -68,7 +66,6 @@ class Processor
|
|||||||
$this->accounts = $settings['accounts'];
|
$this->accounts = $settings['accounts'];
|
||||||
$this->exportFormat = $settings['exportFormat'];
|
$this->exportFormat = $settings['exportFormat'];
|
||||||
$this->includeAttachments = $settings['includeAttachments'];
|
$this->includeAttachments = $settings['includeAttachments'];
|
||||||
$this->includeConfig = $settings['includeConfig'];
|
|
||||||
$this->includeOldUploads = $settings['includeOldUploads'];
|
$this->includeOldUploads = $settings['includeOldUploads'];
|
||||||
$this->job = $settings['job'];
|
$this->job = $settings['job'];
|
||||||
$this->journals = new Collection;
|
$this->journals = new Collection;
|
||||||
@ -84,8 +81,9 @@ class Processor
|
|||||||
{
|
{
|
||||||
/** @var AttachmentCollector $attachmentCollector */
|
/** @var AttachmentCollector $attachmentCollector */
|
||||||
$attachmentCollector = app(AttachmentCollector::class, [$this->job]);
|
$attachmentCollector = app(AttachmentCollector::class, [$this->job]);
|
||||||
|
$attachmentCollector->setDates($this->settings['startDate'], $this->settings['endDate']);
|
||||||
$attachmentCollector->run();
|
$attachmentCollector->run();
|
||||||
$this->files = $this->files->merge($attachmentCollector->getFiles());
|
$this->files = $this->files->merge($attachmentCollector->getEntries());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -95,9 +93,13 @@ class Processor
|
|||||||
*/
|
*/
|
||||||
public function collectJournals(): bool
|
public function collectJournals(): bool
|
||||||
{
|
{
|
||||||
/** @var JournalTaskerInterface $tasker */
|
/** @var JournalCollector $collector */
|
||||||
$tasker = app(JournalTaskerInterface::class);
|
$collector = app(JournalCollector::class, [$this->job]);
|
||||||
$this->journals = $tasker->getJournalsInRange($this->accounts, $this->settings['startDate'], $this->settings['endDate']);
|
$collector->setDates($this->settings['startDate'], $this->settings['endDate']);
|
||||||
|
$collector->setAccounts($this->settings['accounts']);
|
||||||
|
$collector->run();
|
||||||
|
$this->journals = $collector->getEntries();
|
||||||
|
Log::debug(sprintf('Count %d journals in collectJournals() ', $this->journals->count()));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -111,7 +113,7 @@ class Processor
|
|||||||
$uploadCollector = app(UploadCollector::class, [$this->job]);
|
$uploadCollector = app(UploadCollector::class, [$this->job]);
|
||||||
$uploadCollector->run();
|
$uploadCollector->run();
|
||||||
|
|
||||||
$this->files = $this->files->merge($uploadCollector->getFiles());
|
$this->files = $this->files->merge($uploadCollector->getEntries());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -122,22 +124,11 @@ class Processor
|
|||||||
public function convertJournals(): bool
|
public function convertJournals(): bool
|
||||||
{
|
{
|
||||||
$count = 0;
|
$count = 0;
|
||||||
/** @var TransactionJournal $journal */
|
foreach ($this->journals as $object) {
|
||||||
foreach ($this->journals as $journal) {
|
$this->exportEntries->push(Entry::fromObject($object));
|
||||||
$this->exportEntries->push(Entry::fromJournal($journal));
|
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
|
Log::debug(sprintf('Count %d entries in exportEntries (convertJournals)', $this->exportEntries->count()));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function createConfigFile(): bool
|
|
||||||
{
|
|
||||||
$this->configurationMaker = app(ConfigurationFile::class, [$this->job]);
|
|
||||||
$this->files->push($this->configurationMaker->make());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -26,47 +26,39 @@ class Help implements HelpInterface
|
|||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param string $route
|
||||||
* @param string $key
|
* @param string $language
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFromCache(string $key): string
|
public function getFromCache(string $route, string $language): string
|
||||||
{
|
{
|
||||||
return Cache::get($key);
|
return Cache::get('help.' . $route . '.' . $language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $language
|
* @param string $language
|
||||||
* @param string $route
|
* @param string $route
|
||||||
*
|
*
|
||||||
* @return array
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFromGithub(string $language, string $route): array
|
public function getFromGithub(string $language, string $route): string
|
||||||
{
|
{
|
||||||
|
|
||||||
$uri = sprintf('https://raw.githubusercontent.com/JC5/firefly-iii-help/master/%s/%s.md', $language, $route);
|
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route);
|
||||||
$routeIndex = str_replace('.', '-', $route);
|
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||||
$title = trans('help.' . $routeIndex);
|
$result = Requests::get($uri);
|
||||||
$content = [
|
|
||||||
'text' => '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>',
|
|
||||||
'title' => $title,
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
$result = Requests::get($uri);
|
|
||||||
|
|
||||||
|
|
||||||
if ($result->status_code === 200) {
|
if ($result->status_code === 200) {
|
||||||
$content['text'] = $result->body;
|
$content = $result->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (strlen(trim($content['text'])) == 0) {
|
if (strlen(trim($content)) == 0) {
|
||||||
$content['text'] = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||||
}
|
}
|
||||||
$converter = new CommonMarkConverter();
|
$converter = new CommonMarkConverter();
|
||||||
$content['text'] = $converter->convertToHtml($content['text']);
|
$content = $converter->convertToHtml($content);
|
||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
|
|
||||||
@ -84,27 +76,26 @@ class Help implements HelpInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param string $route
|
* @param string $route
|
||||||
|
* @param string $language
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function inCache(string $route):bool
|
public function inCache(string $route, string $language):bool
|
||||||
{
|
{
|
||||||
return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text');
|
return Cache::has('help.' . $route . '.' . $language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param string $route
|
* @param string $route
|
||||||
* @param string $language
|
* @param string $language
|
||||||
* @param array $content
|
* @param string $content
|
||||||
*
|
*
|
||||||
* @internal param $title
|
* @internal param $title
|
||||||
*/
|
*/
|
||||||
public function putInCache(string $route, string $language, array $content)
|
public function putInCache(string $route, string $language, string $content)
|
||||||
{
|
{
|
||||||
Cache::put('help.' . $route . '.text.' . $language, $content['text'], 10080); // a week.
|
Cache::put('help.' . $route . '.' . $language, $content, 10080); // a week.
|
||||||
Cache::put('help.' . $route . '.title.' . $language, $content['title'], 10080);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,19 +21,20 @@ interface HelpInterface
|
|||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $key
|
* @param string $route
|
||||||
|
* @param string $language
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFromCache(string $key): string;
|
public function getFromCache(string $route, string $language): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $language
|
* @param string $language
|
||||||
* @param string $route
|
* @param string $route
|
||||||
*
|
*
|
||||||
* @return array
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFromGithub(string $language, string $route):array;
|
public function getFromGithub(string $language, string $route):string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $route
|
* @param string $route
|
||||||
@ -44,15 +45,16 @@ interface HelpInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $route
|
* @param string $route
|
||||||
|
* @param string $language
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function inCache(string $route): bool;
|
public function inCache(string $route, string $language ): bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $route
|
* @param string $route
|
||||||
* @param string $language
|
* @param string $language
|
||||||
* @param array $content
|
* @param string $content
|
||||||
*/
|
*/
|
||||||
public function putInCache(string $route, string $language, array $content);
|
public function putInCache(string $route, string $language, string $content);
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,8 @@ class ReportHelper implements ReportHelperInterface
|
|||||||
$billLine->setHit(true);
|
$billLine->setHit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($billLine->isActive()) {
|
// non active AND non hit? do not add:
|
||||||
|
if ($billLine->isActive() || $billLine->isHit()) {
|
||||||
$collection->addBill($billLine);
|
$collection->addBill($billLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,11 @@ namespace FireflyIII\Http\Controllers;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use ExpandedForm;
|
use ExpandedForm;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Http\Requests\AccountFormRequest;
|
use FireflyIII\Http\Requests\AccountFormRequest;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
|
||||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
@ -44,8 +46,16 @@ class AccountController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('mainTitleIcon', 'fa-credit-card');
|
|
||||||
View::share('title', trans('firefly.accounts'));
|
// translations:
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('mainTitleIcon', 'fa-credit-card');
|
||||||
|
View::share('title', trans('firefly.accounts'));
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,7 +156,7 @@ class AccountController extends Controller
|
|||||||
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
|
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
|
||||||
'openingBalanceDate' => $openingBalanceDate,
|
'openingBalanceDate' => $openingBalanceDate,
|
||||||
'openingBalance' => $openingBalanceAmount,
|
'openingBalance' => $openingBalanceAmount,
|
||||||
'virtualBalance' => round($account->virtual_balance, 2),
|
'virtualBalance' => $account->virtual_balance,
|
||||||
];
|
];
|
||||||
Session::flash('preFilled', $preFilled);
|
Session::flash('preFilled', $preFilled);
|
||||||
Session::flash('gaEventCategory', 'accounts');
|
Session::flash('gaEventCategory', 'accounts');
|
||||||
@ -200,6 +210,9 @@ class AccountController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show(AccountTaskerInterface $tasker, ARI $repository, Account $account)
|
public function show(AccountTaskerInterface $tasker, ARI $repository, Account $account)
|
||||||
{
|
{
|
||||||
|
if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
|
||||||
|
return $this->redirectToOriginalAccount($account);
|
||||||
|
}
|
||||||
// show journals from current period only:
|
// show journals from current period only:
|
||||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||||
$subTitle = $account->name;
|
$subTitle = $account->name;
|
||||||
@ -330,7 +343,7 @@ class AccountController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(AccountFormRequest $request, ARI $repository, Account $account)
|
public function update(AccountFormRequest $request, ARI $repository, Account $account)
|
||||||
{
|
{
|
||||||
$data = $request->getAccountData();
|
$data = $request->getAccountData();
|
||||||
$repository->update($account, $data);
|
$repository->update($account, $data);
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name])));
|
Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name])));
|
||||||
@ -363,4 +376,29 @@ class AccountController extends Controller
|
|||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Account $account
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function redirectToOriginalAccount(Account $account)
|
||||||
|
{
|
||||||
|
/** @var Transaction $transaction */
|
||||||
|
$transaction = $account->transactions()->first();
|
||||||
|
if (is_null($transaction)) {
|
||||||
|
throw new FireflyException('Expected a transaction. This account has none. BEEP, error.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$journal = $transaction->transactionJournal;
|
||||||
|
/** @var Transaction $opposingTransaction */
|
||||||
|
$opposingTransaction = $journal->transactions()->where('transactions.id', '!=', $transaction->id)->first();
|
||||||
|
|
||||||
|
if (is_null($opposingTransaction)) {
|
||||||
|
throw new FireflyException('Expected an opposing transaction. This account has none. BEEP, error.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect(route('accounts.show', [$opposingTransaction->account_id]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,15 @@ class ConfigurationController extends Controller
|
|||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
View::share('title', strval(trans('firefly.administration')));
|
|
||||||
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', strval(trans('firefly.administration')));
|
||||||
|
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,10 +73,10 @@ class ConfigurationController extends Controller
|
|||||||
public function store(ConfigurationRequest $request)
|
public function store(ConfigurationRequest $request)
|
||||||
{
|
{
|
||||||
// get config values:
|
// get config values:
|
||||||
$singleUserMode = intval($request->get('single_user_mode')) === 1 ? true : false;
|
$data = $request->getConfigurationData();
|
||||||
|
|
||||||
// store config values
|
// store config values
|
||||||
FireflyConfig::set('single_user_mode', $singleUserMode);
|
FireflyConfig::set('single_user_mode', $data['single_user_mode']);
|
||||||
|
|
||||||
// flash message
|
// flash message
|
||||||
Session::flash('success', strval(trans('firefly.configuration_updated')));
|
Session::flash('success', strval(trans('firefly.configuration_updated')));
|
||||||
|
@ -15,6 +15,7 @@ namespace FireflyIII\Http\Controllers\Admin;
|
|||||||
|
|
||||||
|
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\Support\Facades\FireflyConfig;
|
use FireflyIII\Support\Facades\FireflyConfig;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@ -83,6 +84,7 @@ class DomainController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function toggleDomain(string $domain)
|
public function toggleDomain(string $domain)
|
||||||
{
|
{
|
||||||
|
$domain = strtolower($domain);
|
||||||
$blocked = FireflyConfig::get('blocked-domains', [])->data;
|
$blocked = FireflyConfig::get('blocked-domains', [])->data;
|
||||||
|
|
||||||
if (in_array($domain, $blocked)) {
|
if (in_array($domain, $blocked)) {
|
||||||
@ -111,15 +113,16 @@ class DomainController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function getKnownDomains(): array
|
private function getKnownDomains(): array
|
||||||
{
|
{
|
||||||
$users = User::get();
|
/** @var UserRepositoryInterface $repository */
|
||||||
$set = [];
|
$repository = app(UserRepositoryInterface::class);
|
||||||
$filtered = [];
|
$users = $repository->all();
|
||||||
|
$set = [];
|
||||||
|
$filtered = [];
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$email = $user->email;
|
$email = $user->email;
|
||||||
$parts = explode('@', $email);
|
$parts = explode('@', $email);
|
||||||
$domain = $parts[1];
|
$set[] = strtolower($parts[1]);
|
||||||
$set[] = $domain;
|
|
||||||
}
|
}
|
||||||
$set = array_unique($set);
|
$set = array_unique($set);
|
||||||
// filter for already banned domains:
|
// filter for already banned domains:
|
||||||
@ -131,7 +134,6 @@ class DomainController extends Controller
|
|||||||
$filtered[] = $domain;
|
$filtered[] = $domain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
asort($filtered);
|
|
||||||
|
|
||||||
return $filtered;
|
return $filtered;
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,16 @@ class AttachmentController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('mainTitleIcon', 'fa-paperclip');
|
|
||||||
View::share('title', trans('firefly.attachments'));
|
// translations:
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('mainTitleIcon', 'fa-paperclip');
|
||||||
|
View::share('title', trans('firefly.attachments'));
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,8 +38,16 @@ class BillController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.bills'));
|
|
||||||
View::share('mainTitleIcon', 'fa-calendar-o');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.bills'));
|
||||||
|
View::share('mainTitleIcon', 'fa-calendar-o');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,23 +145,15 @@ class BillController extends Controller
|
|||||||
$bills = $repository->getBills();
|
$bills = $repository->getBills();
|
||||||
$bills->each(
|
$bills->each(
|
||||||
function (Bill $bill) use ($repository, $start, $end) {
|
function (Bill $bill) use ($repository, $start, $end) {
|
||||||
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, new Carbon);
|
|
||||||
$bill->lastFoundMatch = $repository->lastFoundMatch($bill);
|
// paid in this period?
|
||||||
$journals = $repository->getJournalsInRange($bill, $start, $end);
|
$bill->paidDates = $repository->getPaidDatesInRange($bill, $start, $end);
|
||||||
// loop journals, find average:
|
$bill->payDates = $repository->getPayDatesInRange($bill, $start, $end);
|
||||||
$average = '0';
|
$lastDate = clone $start;
|
||||||
$count = $journals->count();
|
if ($bill->paidDates->count() >= $bill->payDates->count()) {
|
||||||
if ($count > 0) {
|
$lastDate = $end;
|
||||||
$sum = '0';
|
|
||||||
foreach ($journals as $journal) {
|
|
||||||
$sum = bcadd($sum, TransactionJournal::amountPositive($journal));
|
|
||||||
}
|
|
||||||
$average = bcdiv($sum, strval($count));
|
|
||||||
}
|
}
|
||||||
|
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, $lastDate);
|
||||||
$bill->lastPaidAmount = $average;
|
|
||||||
$bill->paidInPeriod = ($start <= $bill->lastFoundMatch) && ($end >= $bill->lastFoundMatch);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
|||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Input;
|
use Input;
|
||||||
|
use Log;
|
||||||
use Navigation;
|
use Navigation;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Response;
|
use Response;
|
||||||
@ -47,9 +48,17 @@ class BudgetController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.budgets'));
|
|
||||||
View::share('mainTitleIcon', 'fa-tasks');
|
|
||||||
View::share('hideBudgets', true);
|
View::share('hideBudgets', true);
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.budgets'));
|
||||||
|
View::share('mainTitleIcon', 'fa-tasks');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,10 +200,12 @@ class BudgetController extends Controller
|
|||||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
||||||
$startAsString = $start->format('Y-m-d');
|
$startAsString = $start->format('Y-m-d');
|
||||||
$endAsString = $end->format('Y-m-d');
|
$endAsString = $end->format('Y-m-d');
|
||||||
|
Log::debug('Now at /budgets');
|
||||||
|
|
||||||
// loop the budgets:
|
// loop the budgets:
|
||||||
/** @var Budget $budget */
|
/** @var Budget $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
|
Log::debug(sprintf('Now at budget #%d ("%s")', $budget->id, $budget->name));
|
||||||
$budget->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end);
|
$budget->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end);
|
||||||
$allRepetitions = $repository->getAllBudgetLimitRepetitions($start, $end);
|
$allRepetitions = $repository->getAllBudgetLimitRepetitions($start, $end);
|
||||||
$otherRepetitions = new Collection;
|
$otherRepetitions = new Collection;
|
||||||
@ -282,13 +293,13 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @param BudgetRepositoryInterface $repository
|
||||||
* @param Budget $budget
|
* @param AccountRepositoryInterface $accountRepository
|
||||||
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
*/
|
||||||
public function show(BudgetRepositoryInterface $repository, Budget $budget)
|
public function show(BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository, Budget $budget)
|
||||||
{
|
{
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = session('first', Carbon::create()->startOfYear());
|
$start = session('first', Carbon::create()->startOfYear());
|
||||||
@ -300,6 +311,7 @@ class BudgetController extends Controller
|
|||||||
$count = $journals->count();
|
$count = $journals->count();
|
||||||
$journals = $journals->slice($offset, $pageSize);
|
$journals = $journals->slice($offset, $pageSize);
|
||||||
$journals = new LengthAwarePaginator($journals, $count, $pageSize);
|
$journals = new LengthAwarePaginator($journals, $count, $pageSize);
|
||||||
|
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
||||||
|
|
||||||
$journals->setPath('/budgets/show/' . $budget->id);
|
$journals->setPath('/budgets/show/' . $budget->id);
|
||||||
|
|
||||||
@ -310,7 +322,7 @@ class BudgetController extends Controller
|
|||||||
|
|
||||||
/** @var LimitRepetition $entry */
|
/** @var LimitRepetition $entry */
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$entry->spent = $repository->spentInPeriod(new Collection([$budget]), new Collection, $entry->startdate, $entry->enddate);
|
$entry->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $entry->startdate, $entry->enddate);
|
||||||
$limits->push($entry);
|
$limits->push($entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,15 +330,17 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @param BudgetRepositoryInterface $repository
|
||||||
* @param Budget $budget
|
* @param AccountRepositoryInterface $accountRepository
|
||||||
* @param LimitRepetition $repetition
|
* @param Budget $budget
|
||||||
|
* @param LimitRepetition $repetition
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function showWithRepetition(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
|
public function showWithRepetition(
|
||||||
{
|
BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository, Budget $budget, LimitRepetition $repetition
|
||||||
|
) {
|
||||||
if ($repetition->budgetLimit->budget->id != $budget->id) {
|
if ($repetition->budgetLimit->budget->id != $budget->id) {
|
||||||
throw new FireflyException('This budget limit is not part of this budget.');
|
throw new FireflyException('This budget limit is not part of this budget.');
|
||||||
}
|
}
|
||||||
@ -340,11 +354,13 @@ class BudgetController extends Controller
|
|||||||
$journals = $journals->slice($offset, $pageSize);
|
$journals = $journals->slice($offset, $pageSize);
|
||||||
$journals = new LengthAwarePaginator($journals, $count, $pageSize);
|
$journals = new LengthAwarePaginator($journals, $count, $pageSize);
|
||||||
$subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]);
|
$subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]);
|
||||||
|
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
|
||||||
|
|
||||||
|
|
||||||
$journals->setPath('/budgets/show/' . $budget->id . '/' . $repetition->id);
|
$journals->setPath('/budgets/show/' . $budget->id . '/' . $repetition->id);
|
||||||
|
|
||||||
|
|
||||||
$repetition->spent = $repository->spentInPeriod(new Collection([$budget]), new Collection, $repetition->startdate, $repetition->enddate);
|
$repetition->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $repetition->startdate, $repetition->enddate);
|
||||||
$limits = new Collection([$repetition]);
|
$limits = new Collection([$repetition]);
|
||||||
|
|
||||||
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
|
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
|
||||||
@ -359,8 +375,8 @@ class BudgetController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(BudgetFormRequest $request, BudgetRepositoryInterface $repository)
|
public function store(BudgetFormRequest $request, BudgetRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
$data = $request->getBudgetData();
|
$data = $request->getBudgetData();
|
||||||
$budget = $repository->store($data);
|
$budget = $repository->store($data);
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.stored_new_budget', ['name' => e($budget->name)])));
|
Session::flash('success', strval(trans('firefly.stored_new_budget', ['name' => e($budget->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
@ -43,8 +43,16 @@ class CategoryController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.categories'));
|
|
||||||
View::share('mainTitleIcon', 'fa-bar-chart');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.categories'));
|
||||||
|
View::share('mainTitleIcon', 'fa-bar-chart');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,11 +272,8 @@ class CategoryController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(CategoryFormRequest $request, CRI $repository)
|
public function store(CategoryFormRequest $request, CRI $repository)
|
||||||
{
|
{
|
||||||
$categoryData = [
|
$data = $request->getCategoryData();
|
||||||
'name' => trim($request->input('name')),
|
$category = $repository->store($data);
|
||||||
'user' => auth()->user()->id,
|
|
||||||
];
|
|
||||||
$category = $repository->store($categoryData);
|
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.stored_category', ['name' => e($category->name)])));
|
Session::flash('success', strval(trans('firefly.stored_category', ['name' => e($category->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
@ -292,11 +297,8 @@ class CategoryController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(CategoryFormRequest $request, CRI $repository, Category $category)
|
public function update(CategoryFormRequest $request, CRI $repository, Category $category)
|
||||||
{
|
{
|
||||||
$categoryData = [
|
$data = $request->getCategoryData();
|
||||||
'name' => $request->input('name'),
|
$repository->update($category, $data);
|
||||||
];
|
|
||||||
|
|
||||||
$repository->update($category, $categoryData);
|
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.updated_category', ['name' => e($category->name)])));
|
Session::flash('success', strval(trans('firefly.updated_category', ['name' => e($category->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
@ -46,10 +46,18 @@ class Controller extends BaseController
|
|||||||
View::share('hideBills', false);
|
View::share('hideBills', false);
|
||||||
View::share('hideTags', false);
|
View::share('hideTags', false);
|
||||||
|
|
||||||
// save some formats:
|
|
||||||
$this->monthFormat = (string)trans('config.month');
|
// translations:
|
||||||
$this->monthAndDayFormat = (string)trans('config.month_and_day');
|
|
||||||
$this->dateTimeFormat = (string)trans('config.date_time');
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
$this->monthFormat = (string)trans('config.month');
|
||||||
|
$this->monthAndDayFormat = (string)trans('config.month_and_day');
|
||||||
|
$this->dateTimeFormat = (string)trans('config.date_time');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,16 @@ class CurrencyController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.currencies'));
|
|
||||||
View::share('mainTitleIcon', 'fa-usd');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.currencies'));
|
||||||
|
View::share('mainTitleIcon', 'fa-usd');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,8 +41,16 @@ class ExportController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('mainTitleIcon', 'fa-file-archive-o');
|
|
||||||
View::share('title', trans('firefly.export_data'));
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('mainTitleIcon', 'fa-file-archive-o');
|
||||||
|
View::share('title', trans('firefly.export_data'));
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,7 +141,6 @@ class ExportController extends Controller
|
|||||||
'endDate' => new Carbon($request->get('export_end_range')),
|
'endDate' => new Carbon($request->get('export_end_range')),
|
||||||
'exportFormat' => $request->get('exportFormat'),
|
'exportFormat' => $request->get('exportFormat'),
|
||||||
'includeAttachments' => intval($request->get('include_attachments')) === 1,
|
'includeAttachments' => intval($request->get('include_attachments')) === 1,
|
||||||
'includeConfig' => intval($request->get('include_config')) === 1,
|
|
||||||
'includeOldUploads' => intval($request->get('include_old_uploads')) === 1,
|
'includeOldUploads' => intval($request->get('include_old_uploads')) === 1,
|
||||||
'job' => $job,
|
'job' => $job,
|
||||||
];
|
];
|
||||||
@ -177,15 +184,6 @@ class ExportController extends Controller
|
|||||||
$job->change('export_status_collected_old_uploads');
|
$job->change('export_status_collected_old_uploads');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate / collect config file.
|
|
||||||
*/
|
|
||||||
if ($settings['includeConfig']) {
|
|
||||||
$job->change('export_status_creating_config_file');
|
|
||||||
$processor->createConfigFile();
|
|
||||||
$job->change('export_status_created_config_file');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create ZIP file:
|
* Create ZIP file:
|
||||||
*/
|
*/
|
||||||
|
@ -41,11 +41,9 @@ class HelpController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show(HelpInterface $help, string $route)
|
public function show(HelpInterface $help, string $route)
|
||||||
{
|
{
|
||||||
|
|
||||||
$language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data;
|
$language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data;
|
||||||
$content = [
|
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
|
||||||
'text' => '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>',
|
|
||||||
'title' => 'Help',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!$help->hasRoute($route)) {
|
if (!$help->hasRoute($route)) {
|
||||||
Log::error('No such route: ' . $route);
|
Log::error('No such route: ' . $route);
|
||||||
@ -53,11 +51,9 @@ class HelpController extends Controller
|
|||||||
return Response::json($content);
|
return Response::json($content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($help->inCache($route)) {
|
if ($help->inCache($route, $language)) {
|
||||||
$content = [
|
$content = $help->getFromCache($route, $language);
|
||||||
'text' => $help->getFromCache('help.' . $route . '.text.' . $language),
|
Log::debug('Help text was in cache.');
|
||||||
'title' => $help->getFromCache('help.' . $route . '.title.' . $language),
|
|
||||||
];
|
|
||||||
|
|
||||||
return Response::json($content);
|
return Response::json($content);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ use Log;
|
|||||||
use Preferences;
|
use Preferences;
|
||||||
use Route;
|
use Route;
|
||||||
use Session;
|
use Session;
|
||||||
|
use View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class HomeController
|
* Class HomeController
|
||||||
@ -41,6 +41,8 @@ class HomeController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
View::share('title', 'Firefly III');
|
||||||
|
View::share('mainTitleIcon', 'fa-fire');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,11 +130,9 @@ class HomeController extends Controller
|
|||||||
return redirect(route('new-user.index'));
|
return redirect(route('new-user.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$title = 'Firefly';
|
$subTitle = trans('firefly.welcomeBack');
|
||||||
$subTitle = trans('firefly.welcomeBack');
|
$transactions = [];
|
||||||
$mainTitleIcon = 'fa-fire';
|
$frontPage = Preferences::get(
|
||||||
$transactions = [];
|
|
||||||
$frontPage = Preferences::get(
|
|
||||||
'frontPageAccounts', $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray()
|
'frontPageAccounts', $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray()
|
||||||
);
|
);
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
@ -164,36 +164,29 @@ class HomeController extends Controller
|
|||||||
public function routes()
|
public function routes()
|
||||||
{
|
{
|
||||||
// these routes are not relevant for the help pages:
|
// these routes are not relevant for the help pages:
|
||||||
$ignore = [
|
$ignore = ['login', 'registe', 'logout', 'two-fac', 'lost-two', 'confirm', 'resend', 'do_confirm', 'testFla', 'json.', 'piggy-banks.add',
|
||||||
|
'piggy-banks.remove', 'preferences.', 'rules.rule.up', 'rules.rule.down', 'rules.rule-group.up', 'rules.rule-group.down', 'popup.report',
|
||||||
|
'admin.users.domains.block-', 'import.json', 'help.',
|
||||||
];
|
];
|
||||||
$routes = Route::getRoutes();
|
$routes = Route::getRoutes();
|
||||||
|
|
||||||
|
echo '<pre>';
|
||||||
|
|
||||||
/** @var \Illuminate\Routing\Route $route */
|
/** @var \Illuminate\Routing\Route $route */
|
||||||
foreach ($routes as $route) {
|
foreach ($routes as $route) {
|
||||||
|
|
||||||
$name = $route->getName();
|
$name = $route->getName();
|
||||||
$methods = $route->getMethods();
|
$methods = $route->getMethods();
|
||||||
$search = [
|
|
||||||
'{account}', '{what}', '{rule}', '{tj}', '{category}', '{budget}', '{code}', '{date}', '{attachment}', '{bill}', '{limitrepetition}',
|
|
||||||
'{currency}', '{jobKey}', '{piggyBank}', '{ruleGroup}', '{rule}', '{route}', '{unfinishedJournal}',
|
|
||||||
'{reportType}', '{start_date}', '{end_date}', '{accountList}', '{tag}', '{journalList}',
|
|
||||||
|
|
||||||
];
|
if (!is_null($name) && strlen($name) > 0 && in_array('GET', $methods) && !$this->startsWithAny($ignore, $name)) {
|
||||||
$replace = [1, 'asset', 1, 1, 1, 1, 'abc', '2016-01-01', 1, 1, 1, 1, 1, 1, 1, 1, 'index', 1,
|
echo sprintf('touch %s.md', $name) . "\n";
|
||||||
'default', '20160101', '20160131', '1,2', 1, '1,2',
|
|
||||||
];
|
|
||||||
if (count($search) != count($replace)) {
|
|
||||||
echo 'count';
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
$url = str_replace($search, $replace, $route->getUri());
|
|
||||||
|
|
||||||
if (!is_null($name) && in_array('GET', $methods) && !$this->startsWithAny($ignore, $name)) {
|
|
||||||
echo '<a href="/' . $url . '" title="' . $name . '">' . $name . '</a><br>' . "\n";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
echo '</pre>';
|
||||||
|
|
||||||
return '<hr>';
|
echo '<hr />';
|
||||||
|
|
||||||
|
return ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,8 +41,15 @@ class ImportController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('mainTitleIcon', 'fa-archive');
|
|
||||||
View::share('title', trans('firefly.import_data_full'));
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('mainTitleIcon', 'fa-archive');
|
||||||
|
View::share('title', trans('firefly.import_data_full'));
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,6 +32,13 @@ class NewUserController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -107,7 +114,6 @@ class NewUserController extends Controller
|
|||||||
'accountType' => 'asset',
|
'accountType' => 'asset',
|
||||||
'virtualBalance' => 0,
|
'virtualBalance' => 0,
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'accountRole' => 'defaultAsset',
|
'accountRole' => 'defaultAsset',
|
||||||
'openingBalance' => round($request->input('bank_balance'), 2),
|
'openingBalance' => round($request->input('bank_balance'), 2),
|
||||||
'openingBalanceDate' => new Carbon,
|
'openingBalanceDate' => new Carbon,
|
||||||
@ -133,7 +139,6 @@ class NewUserController extends Controller
|
|||||||
'accountType' => 'asset',
|
'accountType' => 'asset',
|
||||||
'virtualBalance' => 0,
|
'virtualBalance' => 0,
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'accountRole' => 'savingAsset',
|
'accountRole' => 'savingAsset',
|
||||||
'openingBalance' => round($request->input('savings_balance'), 2),
|
'openingBalance' => round($request->input('savings_balance'), 2),
|
||||||
'openingBalanceDate' => new Carbon,
|
'openingBalanceDate' => new Carbon,
|
||||||
@ -158,7 +163,6 @@ class NewUserController extends Controller
|
|||||||
'accountType' => 'asset',
|
'accountType' => 'asset',
|
||||||
'virtualBalance' => round($request->get('credit_card_limit'), 2),
|
'virtualBalance' => round($request->get('credit_card_limit'), 2),
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'accountRole' => 'ccAsset',
|
'accountRole' => 'ccAsset',
|
||||||
'openingBalance' => null,
|
'openingBalance' => null,
|
||||||
'openingBalanceDate' => null,
|
'openingBalanceDate' => null,
|
||||||
|
@ -45,8 +45,16 @@ class PiggyBankController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.piggyBanks'));
|
|
||||||
View::share('mainTitleIcon', 'fa-sort-amount-asc');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.piggyBanks'));
|
||||||
|
View::share('mainTitleIcon', 'fa-sort-amount-asc');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -364,18 +372,8 @@ class PiggyBankController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
|
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
|
$data = $request->getPiggyBankData();
|
||||||
$piggyBankData = [
|
$piggyBank = $repository->store($data);
|
||||||
'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,
|
|
||||||
'note' => $request->get('note'),
|
|
||||||
];
|
|
||||||
|
|
||||||
$piggyBank = $repository->store($piggyBankData);
|
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.stored_piggy_bank', ['name' => e($piggyBank->name)])));
|
Session::flash('success', strval(trans('firefly.stored_piggy_bank', ['name' => e($piggyBank->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
@ -400,16 +398,8 @@ class PiggyBankController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank)
|
public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
$piggyBankData = [
|
$data = $request->getPiggyBankData();
|
||||||
'name' => $request->get('name'),
|
$piggyBank = $repository->update($piggyBank, $data);
|
||||||
'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,
|
|
||||||
'note' => $request->get('note'),
|
|
||||||
];
|
|
||||||
|
|
||||||
$piggyBank = $repository->update($piggyBank, $piggyBankData);
|
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.updated_piggy_bank', ['name' => e($piggyBank->name)])));
|
Session::flash('success', strval(trans('firefly.updated_piggy_bank', ['name' => e($piggyBank->name)])));
|
||||||
Preferences::mark();
|
Preferences::mark();
|
||||||
|
@ -173,7 +173,10 @@ class ReportController extends Controller
|
|||||||
/** @var CategoryRepositoryInterface $repository */
|
/** @var CategoryRepositoryInterface $repository */
|
||||||
$repository = app(CategoryRepositoryInterface::class);
|
$repository = app(CategoryRepositoryInterface::class);
|
||||||
$category = $repository->find(intval($attributes['categoryId']));
|
$category = $repository->find(intval($attributes['categoryId']));
|
||||||
$journals = $repository->journalsInPeriod(new Collection([$category]), $attributes['accounts'], [], $attributes['startDate'], $attributes['endDate']);
|
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
|
||||||
|
$journals = $repository->journalsInPeriod(
|
||||||
|
new Collection([$category]), $attributes['accounts'], $types, $attributes['startDate'], $attributes['endDate']
|
||||||
|
);
|
||||||
$view = view('popup.report.category-entry', compact('journals', 'category'))->render();
|
$view = view('popup.report.category-entry', compact('journals', 'category'))->render();
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
|
@ -35,8 +35,16 @@ class PreferencesController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.preferences'));
|
|
||||||
View::share('mainTitleIcon', 'fa-gear');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.preferences'));
|
||||||
|
View::share('mainTitleIcon', 'fa-gear');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,8 +36,15 @@ class ProfileController extends Controller
|
|||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
View::share('title', trans('firefly.profile'));
|
|
||||||
View::share('mainTitleIcon', 'fa-user');
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.profile'));
|
||||||
|
View::share('mainTitleIcon', 'fa-user');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,9 +52,11 @@ class ProfileController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function changePassword()
|
public function changePassword()
|
||||||
{
|
{
|
||||||
return view('profile.change-password')->with('title', auth()->user()->email)->with('subTitle', trans('firefly.change_your_password'))->with(
|
$title = auth()->user()->email;
|
||||||
'mainTitleIcon', 'fa-user'
|
$subTitle = strval(trans('firefly.change_your_password'));
|
||||||
);
|
$subTitleIcon = 'fa-key';
|
||||||
|
|
||||||
|
return view('profile.change-password', compact('title', 'subTitle', 'subTitleIcon'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,9 +64,11 @@ class ProfileController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function deleteAccount()
|
public function deleteAccount()
|
||||||
{
|
{
|
||||||
return view('profile.delete-account')->with('title', auth()->user()->email)->with('subTitle', trans('firefly.delete_account'))->with(
|
$title = auth()->user()->email;
|
||||||
'mainTitleIcon', 'fa-user'
|
$subTitle = strval(trans('firefly.delete_account'));
|
||||||
);
|
$subTitleIcon = 'fa-trash';
|
||||||
|
|
||||||
|
return view('profile.delete-account', compact('title', 'subTitle', 'subTitleIcon'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +17,7 @@ namespace FireflyIII\Http\Controllers\Report;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||||
|
use FireflyIII\Support\CacheProperties;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,9 +37,23 @@ class AccountController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function accountReport(Carbon $start, Carbon $end, Collection $accounts)
|
public function accountReport(Carbon $start, Carbon $end, Collection $accounts)
|
||||||
{
|
{
|
||||||
|
// chart properties for cache:
|
||||||
|
$cache = new CacheProperties;
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('account-report');
|
||||||
|
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||||
|
if ($cache->has()) {
|
||||||
|
return $cache->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$accountTasker = app(AccountTaskerInterface::class);
|
$accountTasker = app(AccountTaskerInterface::class);
|
||||||
$accountReport = $accountTasker->getAccountReport($start, $end, $accounts);
|
$accountReport = $accountTasker->getAccountReport($start, $end, $accounts);
|
||||||
|
|
||||||
return view('reports.partials.accounts', compact('accountReport'));
|
$result = view('reports.partials.accounts', compact('accountReport'))->render();
|
||||||
|
$cache->store($result);
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
60
app/Http/Controllers/Report/BalanceController.php
Normal file
60
app/Http/Controllers/Report/BalanceController.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* BalanceController.php
|
||||||
|
* Copyright (C) 2016 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\Http\Controllers\Report;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Helpers\Report\BalanceReportHelperInterface;
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BalanceController
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Http\Controllers\Report
|
||||||
|
*/
|
||||||
|
class BalanceController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BalanceReportHelperInterface $helper
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
* @param Collection $accounts
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function balanceReport(BalanceReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// chart properties for cache:
|
||||||
|
$cache = new CacheProperties;
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('balance-report');
|
||||||
|
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||||
|
if ($cache->has()) {
|
||||||
|
return $cache->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
$balance = $helper->getBalanceReport($start, $end, $accounts);
|
||||||
|
|
||||||
|
$result = view('reports.partials.balance', compact('balance'))->render();
|
||||||
|
$cache->store($result);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
59
app/Http/Controllers/Report/CategoryController.php
Normal file
59
app/Http/Controllers/Report/CategoryController.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* CategoryController.php
|
||||||
|
* Copyright (C) 2016 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\Http\Controllers\Report;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CategoryController
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Http\Controllers\Report
|
||||||
|
*/
|
||||||
|
class CategoryController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ReportHelperInterface $helper
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
* @param Collection $accounts
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function categoryReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||||
|
{
|
||||||
|
// chart properties for cache:
|
||||||
|
$cache = new CacheProperties;
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('category-report');
|
||||||
|
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||||
|
if ($cache->has()) {
|
||||||
|
return $cache->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
$categories = $helper->getCategoryReport($start, $end, $accounts);
|
||||||
|
|
||||||
|
$result = view('reports.partials.categories', compact('categories'))->render();
|
||||||
|
$cache->store($result);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
app/Http/Controllers/Report/InOutController.php
Normal file
66
app/Http/Controllers/Report/InOutController.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* InOutController.php
|
||||||
|
* Copyright (C) 2016 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\Http\Controllers\Report;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class InOutController
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Http\Controllers\Report
|
||||||
|
*/
|
||||||
|
class InOutController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ReportHelperInterface $helper
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
* @param Collection $accounts
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function inOutReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
|
||||||
|
{
|
||||||
|
// chart properties for cache:
|
||||||
|
$cache = new CacheProperties;
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('in-out-report');
|
||||||
|
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||||
|
if ($cache->has()) {
|
||||||
|
return Response::json($cache->get());
|
||||||
|
}
|
||||||
|
|
||||||
|
$incomes = $helper->getIncomeReport($start, $end, $accounts);
|
||||||
|
$expenses = $helper->getExpenseReport($start, $end, $accounts);
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'income' => view('reports.partials.income', compact('incomes'))->render(),
|
||||||
|
'expenses' => view('reports.partials.expenses', compact('expenses'))->render(),
|
||||||
|
'incomes_expenses' => view('reports.partials.income-vs-expenses', compact('expenses', 'incomes'))->render(),
|
||||||
|
];
|
||||||
|
$cache->store($result);
|
||||||
|
|
||||||
|
return Response::json($result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,14 +15,12 @@ namespace FireflyIII\Http\Controllers;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Report\BalanceReportHelperInterface;
|
|
||||||
use FireflyIII\Helpers\Report\BudgetReportHelperInterface;
|
use FireflyIII\Helpers\Report\BudgetReportHelperInterface;
|
||||||
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
|
|
||||||
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
@ -39,10 +37,6 @@ use View;
|
|||||||
*/
|
*/
|
||||||
class ReportController extends Controller
|
class ReportController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
/** @var BalanceReportHelperInterface */
|
|
||||||
protected $balanceHelper;
|
|
||||||
|
|
||||||
/** @var BudgetReportHelperInterface */
|
/** @var BudgetReportHelperInterface */
|
||||||
protected $budgetHelper;
|
protected $budgetHelper;
|
||||||
/** @var ReportHelperInterface */
|
/** @var ReportHelperInterface */
|
||||||
@ -55,8 +49,18 @@ class ReportController extends Controller
|
|||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
View::share('title', trans('firefly.reports'));
|
|
||||||
View::share('mainTitleIcon', 'fa-line-chart');
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.reports'));
|
||||||
|
View::share('mainTitleIcon', 'fa-line-chart');
|
||||||
|
|
||||||
|
$this->helper = app(ReportHelperInterface::class);
|
||||||
|
$this->budgetHelper = app(BudgetReportHelperInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +71,7 @@ class ReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(AccountRepositoryInterface $repository)
|
public function index(AccountRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
$this->createRepositories();
|
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = clone session('first');
|
$start = clone session('first');
|
||||||
$months = $this->helper->listOfMonths($start);
|
$months = $this->helper->listOfMonths($start);
|
||||||
@ -98,7 +102,6 @@ class ReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function report(string $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
public function report(string $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
||||||
{
|
{
|
||||||
$this->createRepositories();
|
|
||||||
// throw an error if necessary.
|
// throw an error if necessary.
|
||||||
if ($end < $start) {
|
if ($end < $start) {
|
||||||
throw new FireflyException('End date cannot be before start date, silly!');
|
throw new FireflyException('End date cannot be before start date, silly!');
|
||||||
@ -206,16 +209,6 @@ class ReportController extends Controller
|
|||||||
return view('reports.audit.report', compact('start', 'end', 'reportType', 'accountIds', 'accounts', 'auditData', 'hideable', 'defaultShow'));
|
return view('reports.audit.report', compact('start', 'end', 'reportType', 'accountIds', 'accounts', 'auditData', 'hideable', 'defaultShow'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private function createRepositories()
|
|
||||||
{
|
|
||||||
$this->helper = app(ReportHelperInterface::class);
|
|
||||||
$this->budgetHelper = app(BudgetReportHelperInterface::class);
|
|
||||||
$this->balanceHelper = app(BalanceReportHelperInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $reportType
|
* @param $reportType
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
@ -226,17 +219,10 @@ class ReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function defaultMonth(string $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
private function defaultMonth(string $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
||||||
{
|
{
|
||||||
$incomeTopLength = 8;
|
|
||||||
$expenseTopLength = 8;
|
|
||||||
|
|
||||||
// get report stuff!
|
// get report stuff!
|
||||||
$incomes = $this->helper->getIncomeReport($start, $end, $accounts);
|
$budgets = $this->budgetHelper->getBudgetReport($start, $end, $accounts);
|
||||||
$expenses = $this->helper->getExpenseReport($start, $end, $accounts);
|
$bills = $this->helper->getBillReport($start, $end, $accounts);
|
||||||
$budgets = $this->budgetHelper->getBudgetReport($start, $end, $accounts);
|
$tags = $this->helper->tagReport($start, $end, $accounts);
|
||||||
$categories = $this->helper->getCategoryReport($start, $end, $accounts);
|
|
||||||
$balance = $this->balanceHelper->getBalanceReport($start, $end, $accounts);
|
|
||||||
$bills = $this->helper->getBillReport($start, $end, $accounts);
|
|
||||||
$tags = $this->helper->tagReport($start, $end, $accounts);
|
|
||||||
|
|
||||||
// and some id's, joined:
|
// and some id's, joined:
|
||||||
$accountIds = join(',', $accounts->pluck('id')->toArray());
|
$accountIds = join(',', $accounts->pluck('id')->toArray());
|
||||||
@ -245,12 +231,9 @@ class ReportController extends Controller
|
|||||||
return view(
|
return view(
|
||||||
'reports.default.month',
|
'reports.default.month',
|
||||||
compact(
|
compact(
|
||||||
'start', 'end', 'reportType',
|
'start', 'end',
|
||||||
'tags',
|
'tags',
|
||||||
'incomes', 'incomeTopLength',
|
'budgets',
|
||||||
'expenses', 'expenseTopLength',
|
|
||||||
'budgets', 'balance',
|
|
||||||
'categories',
|
|
||||||
'bills',
|
'bills',
|
||||||
'accountIds', 'reportType'
|
'accountIds', 'reportType'
|
||||||
)
|
)
|
||||||
@ -268,13 +251,8 @@ class ReportController extends Controller
|
|||||||
private function defaultMultiYear(string $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
private function defaultMultiYear(string $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
||||||
{
|
{
|
||||||
|
|
||||||
$incomeTopLength = 8;
|
|
||||||
$expenseTopLength = 8;
|
|
||||||
// list of users stuff:
|
|
||||||
$budgets = app(BudgetRepositoryInterface::class)->getActiveBudgets();
|
$budgets = app(BudgetRepositoryInterface::class)->getActiveBudgets();
|
||||||
$categories = app(CategoryRepositoryInterface::class)->getCategories();
|
$categories = app(CategoryRepositoryInterface::class)->getCategories();
|
||||||
$incomes = $this->helper->getIncomeReport($start, $end, $accounts);
|
|
||||||
$expenses = $this->helper->getExpenseReport($start, $end, $accounts);
|
|
||||||
$tags = $this->helper->tagReport($start, $end, $accounts);
|
$tags = $this->helper->tagReport($start, $end, $accounts);
|
||||||
|
|
||||||
// and some id's, joined:
|
// and some id's, joined:
|
||||||
@ -288,9 +266,7 @@ class ReportController extends Controller
|
|||||||
return view(
|
return view(
|
||||||
'reports.default.multi-year',
|
'reports.default.multi-year',
|
||||||
compact(
|
compact(
|
||||||
'budgets', 'accounts', 'categories', 'start', 'end', 'accountIds', 'reportType',
|
'budgets', 'accounts', 'categories', 'start', 'end', 'accountIds', 'reportType', 'tags'
|
||||||
'incomes', 'expenses',
|
|
||||||
'incomeTopLength', 'expenseTopLength', 'tags'
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -305,13 +281,8 @@ class ReportController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function defaultYear(string $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
private function defaultYear(string $reportType, Carbon $start, Carbon $end, Collection $accounts)
|
||||||
{
|
{
|
||||||
$incomeTopLength = 8;
|
$tags = $this->helper->tagReport($start, $end, $accounts);
|
||||||
$expenseTopLength = 8;
|
$budgets = $this->budgetHelper->budgetYearOverview($start, $end, $accounts);
|
||||||
|
|
||||||
$incomes = $this->helper->getIncomeReport($start, $end, $accounts);
|
|
||||||
$expenses = $this->helper->getExpenseReport($start, $end, $accounts);
|
|
||||||
$tags = $this->helper->tagReport($start, $end, $accounts);
|
|
||||||
$budgets = $this->budgetHelper->budgetYearOverview($start, $end, $accounts);
|
|
||||||
|
|
||||||
Session::flash('gaEventCategory', 'report');
|
Session::flash('gaEventCategory', 'report');
|
||||||
Session::flash('gaEventAction', 'year');
|
Session::flash('gaEventAction', 'year');
|
||||||
@ -328,8 +299,7 @@ class ReportController extends Controller
|
|||||||
return view(
|
return view(
|
||||||
'reports.default.year',
|
'reports.default.year',
|
||||||
compact(
|
compact(
|
||||||
'start', 'incomes', 'reportType', 'accountIds', 'end',
|
'start', 'reportType', 'accountIds', 'end', 'tags', 'budgets'
|
||||||
'expenses', 'incomeTopLength', 'expenseTopLength', 'tags', 'budgets'
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,16 @@ class RuleController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.rules'));
|
|
||||||
View::share('mainTitleIcon', 'fa-random');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.rules'));
|
||||||
|
View::share('mainTitleIcon', 'fa-random');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -238,23 +246,8 @@ class RuleController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(RuleFormRequest $request, RuleRepositoryInterface $repository, RuleGroup $ruleGroup)
|
public function store(RuleFormRequest $request, RuleRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||||
{
|
{
|
||||||
|
$data = $request->getRuleData();
|
||||||
|
$data['rule_group_id'] = $ruleGroup->id;
|
||||||
// process the rule itself:
|
|
||||||
$data = [
|
|
||||||
'rule_group_id' => $ruleGroup->id,
|
|
||||||
'title' => $request->get('title'),
|
|
||||||
'user_id' => auth()->user()->id,
|
|
||||||
'trigger' => $request->get('trigger'),
|
|
||||||
'description' => $request->get('description'),
|
|
||||||
'rule-triggers' => $request->get('rule-trigger'),
|
|
||||||
'rule-trigger-values' => $request->get('rule-trigger-value'),
|
|
||||||
'rule-trigger-stop' => $request->get('rule-trigger-stop'),
|
|
||||||
'rule-actions' => $request->get('rule-action'),
|
|
||||||
'rule-action-values' => $request->get('rule-action-value'),
|
|
||||||
'rule-action-stop' => $request->get('rule-action-stop'),
|
|
||||||
'stop_processing' => $request->get('stop_processing'),
|
|
||||||
];
|
|
||||||
|
|
||||||
$rule = $repository->store($data);
|
$rule = $repository->store($data);
|
||||||
Session::flash('success', trans('firefly.stored_new_rule', ['title' => $rule->title]));
|
Session::flash('success', trans('firefly.stored_new_rule', ['title' => $rule->title]));
|
||||||
@ -341,21 +334,7 @@ class RuleController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(RuleRepositoryInterface $repository, RuleFormRequest $request, Rule $rule)
|
public function update(RuleRepositoryInterface $repository, RuleFormRequest $request, Rule $rule)
|
||||||
{
|
{
|
||||||
|
$data = $request->getRuleData();
|
||||||
// process the rule itself:
|
|
||||||
$data = [
|
|
||||||
'title' => $request->get('title'),
|
|
||||||
'active' => intval($request->get('active')) == 1,
|
|
||||||
'trigger' => $request->get('trigger'),
|
|
||||||
'description' => $request->get('description'),
|
|
||||||
'rule-triggers' => $request->get('rule-trigger'),
|
|
||||||
'rule-trigger-values' => $request->get('rule-trigger-value'),
|
|
||||||
'rule-trigger-stop' => $request->get('rule-trigger-stop'),
|
|
||||||
'rule-actions' => $request->get('rule-action'),
|
|
||||||
'rule-action-values' => $request->get('rule-action-value'),
|
|
||||||
'rule-action-stop' => $request->get('rule-action-stop'),
|
|
||||||
'stop_processing' => intval($request->get('stop_processing')) == 1,
|
|
||||||
];
|
|
||||||
$repository->update($rule, $data);
|
$repository->update($rule, $data);
|
||||||
|
|
||||||
Session::flash('success', trans('firefly.updated_rule', ['title' => $rule->title]));
|
Session::flash('success', trans('firefly.updated_rule', ['title' => $rule->title]));
|
||||||
@ -381,7 +360,6 @@ class RuleController extends Controller
|
|||||||
$data = [
|
$data = [
|
||||||
'rule_group_id' => $repository->getFirstRuleGroup()->id,
|
'rule_group_id' => $repository->getFirstRuleGroup()->id,
|
||||||
'stop_processing' => 0,
|
'stop_processing' => 0,
|
||||||
'user_id' => auth()->user()->id,
|
|
||||||
'title' => trans('firefly.default_rule_name'),
|
'title' => trans('firefly.default_rule_name'),
|
||||||
'description' => trans('firefly.default_rule_description'),
|
'description' => trans('firefly.default_rule_description'),
|
||||||
'trigger' => 'store-journal',
|
'trigger' => 'store-journal',
|
||||||
@ -410,11 +388,10 @@ class RuleController extends Controller
|
|||||||
{
|
{
|
||||||
|
|
||||||
/** @var RuleGroupRepositoryInterface $repository */
|
/** @var RuleGroupRepositoryInterface $repository */
|
||||||
$repository = app('FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface');
|
$repository = app(RuleGroupRepositoryInterface::class);
|
||||||
|
|
||||||
if ($repository->count() === 0) {
|
if ($repository->count() === 0) {
|
||||||
$data = [
|
$data = [
|
||||||
'user_id' => auth()->user()->id,
|
|
||||||
'title' => trans('firefly.default_rule_group_name'),
|
'title' => trans('firefly.default_rule_group_name'),
|
||||||
'description' => trans('firefly.default_rule_group_description'),
|
'description' => trans('firefly.default_rule_group_description'),
|
||||||
];
|
];
|
||||||
|
@ -41,8 +41,16 @@ class RuleGroupController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.rules'));
|
|
||||||
View::share('mainTitleIcon', 'fa-random');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.rules'));
|
||||||
|
View::share('mainTitleIcon', 'fa-random');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -204,12 +212,7 @@ class RuleGroupController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(RuleGroupFormRequest $request, RuleGroupRepositoryInterface $repository)
|
public function store(RuleGroupFormRequest $request, RuleGroupRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
$data = [
|
$data = $request->getRuleGroupData();
|
||||||
'title' => $request->input('title'),
|
|
||||||
'description' => $request->input('description'),
|
|
||||||
'user_id' => auth()->user()->id,
|
|
||||||
];
|
|
||||||
|
|
||||||
$ruleGroup = $repository->store($data);
|
$ruleGroup = $repository->store($data);
|
||||||
|
|
||||||
Session::flash('success', strval(trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])));
|
Session::flash('success', strval(trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])));
|
||||||
|
@ -29,6 +29,13 @@ class SearchController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,15 +50,22 @@ class TagController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', 'Tags');
|
|
||||||
View::share('mainTitleIcon', 'fa-tags');
|
|
||||||
View::share('hideTags', true);
|
View::share('hideTags', true);
|
||||||
$this->tagOptions = [
|
|
||||||
'nothing' => trans('firefly.regular_tag'),
|
$this->middleware(
|
||||||
'balancingAct' => trans('firefly.balancing_act'),
|
function ($request, $next) {
|
||||||
'advancePayment' => trans('firefly.advance_payment'),
|
View::share('title', 'Tags');
|
||||||
];
|
View::share('mainTitleIcon', 'fa-tags');
|
||||||
View::share('tagOptions', $this->tagOptions);
|
$this->tagOptions = [
|
||||||
|
'nothing' => trans('firefly.regular_tag'),
|
||||||
|
'balancingAct' => trans('firefly.balancing_act'),
|
||||||
|
'advancePayment' => trans('firefly.advance_payment'),
|
||||||
|
];
|
||||||
|
View::share('tagOptions', $this->tagOptions);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
241
app/Http/Controllers/Transaction/ConvertController.php
Normal file
241
app/Http/Controllers/Transaction/ConvertController.php
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ConvertController.php
|
||||||
|
* Copyright (C) 2016 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\Http\Controllers\Transaction;
|
||||||
|
|
||||||
|
use ExpandedForm;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Session;
|
||||||
|
use View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ConvertController
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Http\Controllers\Transaction
|
||||||
|
*/
|
||||||
|
class ConvertController extends Controller
|
||||||
|
{
|
||||||
|
/** @var AccountRepositoryInterface */
|
||||||
|
private $accounts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ConvertController constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
// some useful repositories:
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
$this->accounts = app(AccountRepositoryInterface::class);
|
||||||
|
|
||||||
|
View::share('title', trans('firefly.transactions'));
|
||||||
|
View::share('mainTitleIcon', 'fa-exchange');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionType $destinationType
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||||
|
*/
|
||||||
|
public function convert(TransactionType $destinationType, TransactionJournal $journal)
|
||||||
|
{
|
||||||
|
$positiveAmount = TransactionJournal::amountPositive($journal);
|
||||||
|
$assetAccounts = ExpandedForm::makeSelectList($this->accounts->getActiveAccountsByType([AccountType::DEFAULT, AccountType::ASSET]));
|
||||||
|
$sourceType = $journal->transactionType;
|
||||||
|
$subTitle = trans('firefly.convert_to_' . $destinationType->type, ['description' => $journal->description]);
|
||||||
|
$subTitleIcon = 'fa-exchange';
|
||||||
|
|
||||||
|
// cannot convert to its own type.
|
||||||
|
if ($sourceType->type === $destinationType->type) {
|
||||||
|
Session::flash('info', trans('firefly.convert_is_already_type_' . $destinationType->type));
|
||||||
|
|
||||||
|
return redirect(route('transactions.show', [$journal->id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// cannot convert split.
|
||||||
|
if ($journal->transactions()->count() > 2) {
|
||||||
|
Session::flash('error', trans('firefly.cannot_convert_split_journl'));
|
||||||
|
|
||||||
|
return redirect(route('transactions.show', [$journal->id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get source and destination account:
|
||||||
|
$sourceAccount = TransactionJournal::sourceAccountList($journal)->first();
|
||||||
|
$destinationAccount = TransactionJournal::destinationAccountList($journal)->first();
|
||||||
|
|
||||||
|
return view(
|
||||||
|
'transactions.convert',
|
||||||
|
compact(
|
||||||
|
'sourceType', 'destinationType', 'journal', 'assetAccounts',
|
||||||
|
'positiveAmount', 'sourceAccount', 'destinationAccount', 'sourceType',
|
||||||
|
'subTitle', 'subTitleIcon'
|
||||||
|
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// convert withdrawal to deposit requires a new source account ()
|
||||||
|
// or to transfer requires
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param JournalRepositoryInterface $repository
|
||||||
|
* @param TransactionType $destinationType
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
public function submit(Request $request, JournalRepositoryInterface $repository, TransactionType $destinationType, TransactionJournal $journal)
|
||||||
|
{
|
||||||
|
$data = $request->all();
|
||||||
|
|
||||||
|
// cannot convert to its own type.
|
||||||
|
if ($journal->transactionType->type === $destinationType->type) {
|
||||||
|
Session::flash('error', trans('firefly.convert_is_already_type_' . $destinationType->type));
|
||||||
|
|
||||||
|
return redirect(route('transactions.show', [$journal->id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// cannot convert split.
|
||||||
|
if ($journal->transactions()->count() > 2) {
|
||||||
|
Session::flash('error', trans('firefly.cannot_convert_split_journl'));
|
||||||
|
|
||||||
|
return redirect(route('transactions.show', [$journal->id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the new source and destination account:
|
||||||
|
$source = $this->getSourceAccount($journal, $destinationType, $data);
|
||||||
|
$destination = $this->getDestinationAccount($journal, $destinationType, $data);
|
||||||
|
|
||||||
|
// update the journal:
|
||||||
|
$errors = $repository->convert($journal, $destinationType, $source, $destination);
|
||||||
|
|
||||||
|
if ($errors->count() > 0) {
|
||||||
|
return redirect(route('transactions.convert', [strtolower($destinationType->type), $journal->id]))->withErrors($errors)->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::flash('success', trans('firefly.converted_to_' . $destinationType->type));
|
||||||
|
|
||||||
|
return redirect(route('transactions.show', [$journal->id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
* @param TransactionType $destinationType
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return Account
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function getDestinationAccount(TransactionJournal $journal, TransactionType $destinationType, array $data): Account
|
||||||
|
{
|
||||||
|
/** @var AccountRepositoryInterface $accountRepository */
|
||||||
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
$sourceAccount = TransactionJournal::sourceAccountList($journal)->first();
|
||||||
|
$destinationAccount = TransactionJournal::destinationAccountList($journal)->first();
|
||||||
|
$sourceType = $journal->transactionType;
|
||||||
|
$destination = null;
|
||||||
|
$joined = $sourceType->type . '-' . $destinationType->type;
|
||||||
|
switch ($joined) {
|
||||||
|
default:
|
||||||
|
throw new FireflyException('Cannot handle ' . $joined);
|
||||||
|
case TransactionType::WITHDRAWAL . '-' . TransactionType::DEPOSIT: # one
|
||||||
|
$destination = $sourceAccount;
|
||||||
|
break;
|
||||||
|
case TransactionType::WITHDRAWAL . '-' . TransactionType::TRANSFER: # two
|
||||||
|
$destination = $accountRepository->find(intval($data['destination_account_asset']));
|
||||||
|
break;
|
||||||
|
case TransactionType::DEPOSIT . '-' . TransactionType::WITHDRAWAL: # three
|
||||||
|
case TransactionType::TRANSFER . '-' . TransactionType::WITHDRAWAL: #five
|
||||||
|
$data = [
|
||||||
|
'name' => $data['destination_account_expense'],
|
||||||
|
'accountType' => 'expense',
|
||||||
|
'virtualBalance' => 0,
|
||||||
|
'active' => true,
|
||||||
|
'iban' => null,
|
||||||
|
];
|
||||||
|
$destination = $accountRepository->store($data);
|
||||||
|
break;
|
||||||
|
case TransactionType::DEPOSIT . '-' . TransactionType::TRANSFER: # four
|
||||||
|
case TransactionType::TRANSFER . '-' . TransactionType::DEPOSIT: #six
|
||||||
|
$destination = $destinationAccount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
* @param TransactionType $destinationType
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return Account
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function getSourceAccount(TransactionJournal $journal, TransactionType $destinationType, array $data): Account
|
||||||
|
{
|
||||||
|
/** @var AccountRepositoryInterface $accountRepository */
|
||||||
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
$sourceAccount = TransactionJournal::sourceAccountList($journal)->first();
|
||||||
|
$destinationAccount = TransactionJournal::destinationAccountList($journal)->first();
|
||||||
|
$sourceType = $journal->transactionType;
|
||||||
|
$source = new Account;
|
||||||
|
$joined = $sourceType->type . '-' . $destinationType->type;
|
||||||
|
switch ($joined) {
|
||||||
|
default:
|
||||||
|
throw new FireflyException('Cannot handle ' . $joined);
|
||||||
|
case TransactionType::WITHDRAWAL . '-' . TransactionType::DEPOSIT: # one
|
||||||
|
case TransactionType::TRANSFER . '-' . TransactionType::DEPOSIT: #six
|
||||||
|
$data = [
|
||||||
|
'name' => $data['source_account_revenue'],
|
||||||
|
'accountType' => 'revenue',
|
||||||
|
'virtualBalance' => 0,
|
||||||
|
'active' => true,
|
||||||
|
'iban' => null,
|
||||||
|
];
|
||||||
|
$source = $accountRepository->store($data);
|
||||||
|
break;
|
||||||
|
case TransactionType::WITHDRAWAL . '-' . TransactionType::TRANSFER: # two
|
||||||
|
case TransactionType::TRANSFER . '-' . TransactionType::WITHDRAWAL: #five
|
||||||
|
$source = $sourceAccount;
|
||||||
|
break;
|
||||||
|
case TransactionType::DEPOSIT . '-' . TransactionType::WITHDRAWAL: # three
|
||||||
|
$source = $destinationAccount;
|
||||||
|
break;
|
||||||
|
case TransactionType::DEPOSIT . '-' . TransactionType::TRANSFER: # four
|
||||||
|
$source = $accountRepository->find(intval($data['source_account_asset']));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $source;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -41,8 +41,16 @@ class MassController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.transactions'));
|
|
||||||
View::share('mainTitleIcon', 'fa-repeat');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.transactions'));
|
||||||
|
View::share('mainTitleIcon', 'fa-repeat');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -209,7 +217,6 @@ class MassController extends Controller
|
|||||||
'destination_account_id' => intval($destAccountId),
|
'destination_account_id' => intval($destAccountId),
|
||||||
'destination_account_name' => $destAccountName,
|
'destination_account_name' => $destAccountName,
|
||||||
'amount' => round($request->get('amount')[$journal->id], 4),
|
'amount' => round($request->get('amount')[$journal->id], 4),
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'amount_currency_id_amount' => intval($request->get('amount_currency_id_amount_' . $journal->id)),
|
'amount_currency_id_amount' => intval($request->get('amount_currency_id_amount_' . $journal->id)),
|
||||||
'date' => new Carbon($request->get('date')[$journal->id]),
|
'date' => new Carbon($request->get('date')[$journal->id]),
|
||||||
'interest_date' => $journal->interest_date,
|
'interest_date' => $journal->interest_date,
|
||||||
|
@ -59,8 +59,6 @@ class SingleController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.transactions'));
|
|
||||||
View::share('mainTitleIcon', 'fa-repeat');
|
|
||||||
|
|
||||||
$maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize'));
|
$maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize'));
|
||||||
$maxPostSize = Steam::phpBytes(ini_get('post_max_size'));
|
$maxPostSize = Steam::phpBytes(ini_get('post_max_size'));
|
||||||
@ -75,11 +73,13 @@ class SingleController extends Controller
|
|||||||
$this->piggyBanks = app(PiggyBankRepositoryInterface::class);
|
$this->piggyBanks = app(PiggyBankRepositoryInterface::class);
|
||||||
$this->attachments = app(AttachmentHelperInterface::class);
|
$this->attachments = app(AttachmentHelperInterface::class);
|
||||||
|
|
||||||
|
View::share('title', trans('firefly.transactions'));
|
||||||
|
View::share('mainTitleIcon', 'fa-repeat');
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +26,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
|
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Log;
|
||||||
use Preferences;
|
use Preferences;
|
||||||
use Session;
|
use Session;
|
||||||
use Steam;
|
use Steam;
|
||||||
@ -62,8 +63,7 @@ class SplitController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('mainTitleIcon', 'fa-share-alt');
|
|
||||||
View::share('title', trans('firefly.split-transactions'));
|
|
||||||
|
|
||||||
// some useful repositories:
|
// some useful repositories:
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
@ -73,6 +73,8 @@ class SplitController extends Controller
|
|||||||
$this->tasker = app(JournalTaskerInterface::class);
|
$this->tasker = app(JournalTaskerInterface::class);
|
||||||
$this->attachments = app(AttachmentHelperInterface::class);
|
$this->attachments = app(AttachmentHelperInterface::class);
|
||||||
$this->currencies = app(CurrencyRepositoryInterface::class);
|
$this->currencies = app(CurrencyRepositoryInterface::class);
|
||||||
|
View::share('mainTitleIcon', 'fa-share-alt');
|
||||||
|
View::share('title', trans('firefly.split-transactions'));
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
@ -264,6 +266,7 @@ class SplitController extends Controller
|
|||||||
$return = [];
|
$return = [];
|
||||||
$transactions = $request->get('transactions');
|
$transactions = $request->get('transactions');
|
||||||
foreach ($transactions as $transaction) {
|
foreach ($transactions as $transaction) {
|
||||||
|
|
||||||
$return[] = [
|
$return[] = [
|
||||||
'description' => $transaction['description'],
|
'description' => $transaction['description'],
|
||||||
'source_account_id' => $transaction['source_account_id'] ?? 0,
|
'source_account_id' => $transaction['source_account_id'] ?? 0,
|
||||||
@ -273,9 +276,9 @@ class SplitController extends Controller
|
|||||||
'amount' => round($transaction['amount'] ?? 0, 2),
|
'amount' => round($transaction['amount'] ?? 0, 2),
|
||||||
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
|
'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0,
|
||||||
'category' => $transaction['category'] ?? '',
|
'category' => $transaction['category'] ?? '',
|
||||||
'user' => auth()->user()->id, // needed for accounts.
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
Log::debug(sprintf('Found %d splits in request data.', count($return)));
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,16 @@ class TransactionController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
View::share('title', trans('firefly.transactions'));
|
|
||||||
View::share('mainTitleIcon', 'fa-repeat');
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
View::share('title', trans('firefly.transactions'));
|
||||||
|
View::share('mainTitleIcon', 'fa-repeat');
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,17 +70,29 @@ class Range
|
|||||||
// set start, end and finish:
|
// set start, end and finish:
|
||||||
$this->setRange();
|
$this->setRange();
|
||||||
|
|
||||||
|
// set view variables.
|
||||||
|
$this->configureView();
|
||||||
|
|
||||||
// get variables for date range:
|
// get variables for date range:
|
||||||
$this->datePicker();
|
$this->datePicker();
|
||||||
|
|
||||||
// set view variables.
|
// set more view variables:
|
||||||
$this->configureView();
|
$this->configureList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $theNext($request);
|
return $theNext($request);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function configureList()
|
||||||
|
{
|
||||||
|
$pref = Preferences::get('list-length', config('firefly.list_length', 10))->data;
|
||||||
|
View::share('listLength', $pref);
|
||||||
|
}
|
||||||
|
|
||||||
private function configureView()
|
private function configureView()
|
||||||
{
|
{
|
||||||
$pref = Preferences::get('language', config('firefly.default_language', 'en_US'));
|
$pref = Preferences::get('language', config('firefly.default_language', 'en_US'));
|
||||||
|
@ -14,8 +14,7 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AccountFormRequest
|
* Class AccountFormRequest
|
||||||
@ -45,7 +44,6 @@ class AccountFormRequest extends Request
|
|||||||
'accountType' => $this->input('what'),
|
'accountType' => $this->input('what'),
|
||||||
'virtualBalance' => round($this->input('virtualBalance'), 2),
|
'virtualBalance' => round($this->input('virtualBalance'), 2),
|
||||||
'virtualBalanceCurrency' => intval($this->input('amount_currency_id_virtualBalance')),
|
'virtualBalanceCurrency' => intval($this->input('amount_currency_id_virtualBalance')),
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'iban' => trim($this->input('iban')),
|
'iban' => trim($this->input('iban')),
|
||||||
'accountNumber' => trim($this->input('accountNumber')),
|
'accountNumber' => trim($this->input('accountNumber')),
|
||||||
'accountRole' => $this->input('accountRole'),
|
'accountRole' => $this->input('accountRole'),
|
||||||
@ -62,15 +60,17 @@ class AccountFormRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
|
/** @var AccountRepositoryInterface $repository */
|
||||||
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$accountRoles = join(',', array_keys(config('firefly.accountRoles')));
|
$accountRoles = join(',', array_keys(config('firefly.accountRoles')));
|
||||||
$types = join(',', array_keys(config('firefly.subTitlesByIdentifier')));
|
$types = join(',', array_keys(config('firefly.subTitlesByIdentifier')));
|
||||||
$ccPaymentTypes = join(',', array_keys(config('firefly.ccTypes')));
|
$ccPaymentTypes = join(',', array_keys(config('firefly.ccTypes')));
|
||||||
|
|
||||||
$nameRule = 'required|min:1|uniqueAccountForUser';
|
$nameRule = 'required|min:1|uniqueAccountForUser';
|
||||||
$idRule = '';
|
$idRule = '';
|
||||||
if (Account::find(Input::get('id'))) {
|
if (!is_null($repository->find(intval($this->get('id')))->id)) {
|
||||||
$idRule = 'belongsToUser:accounts';
|
$idRule = 'belongsToUser:accounts';
|
||||||
$nameRule = 'required|min:1|uniqueAccountForUser:' . Input::get('id');
|
$nameRule = 'required|min:1|uniqueAccountForUser:' . $this->get('id');
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -14,7 +14,6 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BillFormRequest
|
* Class BillFormRequest
|
||||||
@ -46,7 +45,6 @@ class BillFormRequest extends Request
|
|||||||
'amount_currency_id_amount_max' => intval($this->get('amount_currency_id_amount_max')),
|
'amount_currency_id_amount_max' => intval($this->get('amount_currency_id_amount_max')),
|
||||||
'amount_max' => round($this->get('amount_max'), 2),
|
'amount_max' => round($this->get('amount_max'), 2),
|
||||||
'date' => new Carbon($this->get('date')),
|
'date' => new Carbon($this->get('date')),
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'repeat_freq' => $this->get('repeat_freq'),
|
'repeat_freq' => $this->get('repeat_freq'),
|
||||||
'skip' => intval($this->get('skip')),
|
'skip' => intval($this->get('skip')),
|
||||||
'automatch' => intval($this->get('automatch')) === 1,
|
'automatch' => intval($this->get('automatch')) === 1,
|
||||||
@ -61,9 +59,9 @@ class BillFormRequest extends Request
|
|||||||
{
|
{
|
||||||
$nameRule = 'required|between:1,255|uniqueObjectForUser:bills,name';
|
$nameRule = 'required|between:1,255|uniqueObjectForUser:bills,name';
|
||||||
$matchRule = 'required|between:1,255|uniqueObjectForUser:bills,match';
|
$matchRule = 'required|between:1,255|uniqueObjectForUser:bills,match';
|
||||||
if (intval(Input::get('id')) > 0) {
|
if (intval($this->get('id')) > 0) {
|
||||||
$nameRule .= ',' . intval(Input::get('id'));
|
$nameRule .= ',' . intval($this->get('id'));
|
||||||
$matchRule .= ',' . intval(Input::get('id'));
|
$matchRule .= ',' . intval($this->get('id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules = [
|
$rules = [
|
||||||
|
@ -13,8 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetFormRequest
|
* Class BudgetFormRequest
|
||||||
@ -39,7 +38,6 @@ class BudgetFormRequest extends Request
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => trim($this->input('name')),
|
'name' => trim($this->input('name')),
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'active' => intval($this->input('active')) == 1,
|
'active' => intval($this->input('active')) == 1,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -49,10 +47,11 @@ class BudgetFormRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
|
/** @var BudgetRepositoryInterface $repository */
|
||||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name';
|
$repository = app(BudgetRepositoryInterface::class);
|
||||||
if (Budget::find(Input::get('id'))) {
|
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name';
|
||||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,' . intval(Input::get('id'));
|
if (!is_null($repository->find(intval($this->get('id')))->id)) {
|
||||||
|
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,' . intval($this->get('id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -13,8 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CategoryFormRequest
|
* Class CategoryFormRequest
|
||||||
@ -33,15 +32,26 @@ class CategoryFormRequest extends Request
|
|||||||
return auth()->check();
|
return auth()->check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCategoryData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => trim($this->input('name')),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
|
/** @var CategoryRepositoryInterface $repository */
|
||||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name';
|
$repository = app(CategoryRepositoryInterface::class);
|
||||||
if (Category::find(Input::get('id'))) {
|
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name';
|
||||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,' . intval(Input::get('id'));
|
if (!is_null($repository->find(intval($this->get('id')))->id)) {
|
||||||
|
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,' . intval($this->get('id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -30,6 +30,16 @@ class ConfigurationRequest extends Request
|
|||||||
return auth()->check() && auth()->user()->hasRole('owner');
|
return auth()->check() && auth()->user()->hasRole('owner');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getConfigurationData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'single_user_mode' => intval($this->get('single_user_mode')) === 1,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -13,8 +13,6 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BillFormRequest
|
* Class BillFormRequest
|
||||||
*
|
*
|
||||||
@ -55,7 +53,7 @@ class CurrencyFormRequest extends Request
|
|||||||
'name' => 'required|max:48|min:1|unique:transaction_currencies,name',
|
'name' => 'required|max:48|min:1|unique:transaction_currencies,name',
|
||||||
'symbol' => 'required|min:1|max:8|unique:transaction_currencies,symbol',
|
'symbol' => 'required|min:1|max:8|unique:transaction_currencies,symbol',
|
||||||
];
|
];
|
||||||
if (intval(Input::get('id')) > 0) {
|
if (intval($this->get('id')) > 0) {
|
||||||
$rules = [
|
$rules = [
|
||||||
'code' => 'required|min:3|max:3',
|
'code' => 'required|min:3|max:3',
|
||||||
'name' => 'required|max:48|min:1',
|
'name' => 'required|max:48|min:1',
|
||||||
|
@ -16,7 +16,6 @@ namespace FireflyIII\Http\Requests;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class JournalFormRequest
|
* Class JournalFormRequest
|
||||||
@ -44,7 +43,6 @@ class JournalFormRequest extends Request
|
|||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
'what' => $this->get('what'), // type. can be 'deposit', 'withdrawal' or 'transfer'
|
'what' => $this->get('what'), // type. can be 'deposit', 'withdrawal' or 'transfer'
|
||||||
'user' => auth()->user()->id,
|
|
||||||
'date' => new Carbon($this->get('date')),
|
'date' => new Carbon($this->get('date')),
|
||||||
'tags' => explode(',', $this->getFieldOrEmptyString('tags')),
|
'tags' => explode(',', $this->getFieldOrEmptyString('tags')),
|
||||||
'currency_id' => intval($this->get('amount_currency_id_amount')),
|
'currency_id' => intval($this->get('amount_currency_id_amount')),
|
||||||
@ -80,7 +78,7 @@ class JournalFormRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
$what = Input::get('what');
|
$what = $this->get('what');
|
||||||
$rules = [
|
$rules = [
|
||||||
'what' => 'required|in:withdrawal,deposit,transfer',
|
'what' => 'required|in:withdrawal,deposit,transfer',
|
||||||
'date' => 'required|date',
|
'date' => 'required|date',
|
||||||
|
@ -13,7 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use Input;
|
use Carbon\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PiggyBankFormRequest
|
* Class PiggyBankFormRequest
|
||||||
@ -32,6 +32,21 @@ class PiggyBankFormRequest extends Request
|
|||||||
return auth()->check();
|
return auth()->check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getPiggyBankData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => trim($this->get('name')),
|
||||||
|
'startdate' => new Carbon,
|
||||||
|
'account_id' => intval($this->get('account_id')),
|
||||||
|
'targetamount' => round($this->get('targetamount'), 2),
|
||||||
|
'targetdate' => strlen($this->get('targetdate')) > 0 ? new Carbon($this->get('targetdate')) : null,
|
||||||
|
'note' => trim($this->get('note')),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
@ -40,8 +55,8 @@ class PiggyBankFormRequest extends Request
|
|||||||
|
|
||||||
$nameRule = 'required|between:1,255|uniquePiggyBankForUser';
|
$nameRule = 'required|between:1,255|uniquePiggyBankForUser';
|
||||||
$targetDateRule = 'date';
|
$targetDateRule = 'date';
|
||||||
if (intval(Input::get('id'))) {
|
if (intval($this->get('id'))) {
|
||||||
$nameRule = 'required|between:1,255|uniquePiggyBankForUser:' . intval(Input::get('id'));
|
$nameRule = 'required|between:1,255|uniquePiggyBankForUser:' . intval($this->get('id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,8 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RuleFormRequest
|
* Class RuleFormRequest
|
||||||
@ -33,12 +32,33 @@ class RuleFormRequest extends Request
|
|||||||
return auth()->check();
|
return auth()->check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRuleData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => trim($this->get('title')),
|
||||||
|
'active' => intval($this->get('active')) == 1,
|
||||||
|
'trigger' => trim($this->get('trigger')),
|
||||||
|
'description' => trim($this->get('description')),
|
||||||
|
'rule-triggers' => $this->get('rule-trigger'),
|
||||||
|
'rule-trigger-values' => $this->get('rule-trigger-value'),
|
||||||
|
'rule-trigger-stop' => $this->get('rule-trigger-stop'),
|
||||||
|
'rule-actions' => $this->get('rule-action'),
|
||||||
|
'rule-action-values' => $this->get('rule-action-value'),
|
||||||
|
'rule-action-stop' => $this->get('rule-action-stop'),
|
||||||
|
'stop_processing' => intval($this->get('stop_processing')) === 1,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
|
/** @var RuleGroupRepositoryInterface $repository */
|
||||||
|
$repository = app(RuleGroupRepositoryInterface::class);
|
||||||
$validTriggers = array_keys(config('firefly.rule-triggers'));
|
$validTriggers = array_keys(config('firefly.rule-triggers'));
|
||||||
$validActions = array_keys(config('firefly.rule-actions'));
|
$validActions = array_keys(config('firefly.rule-actions'));
|
||||||
|
|
||||||
@ -46,8 +66,8 @@ class RuleFormRequest extends Request
|
|||||||
$contextActions = join(',', config('firefly.rule-actions-text'));
|
$contextActions = join(',', config('firefly.rule-actions-text'));
|
||||||
|
|
||||||
$titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title';
|
$titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title';
|
||||||
if (RuleGroup::find(Input::get('id'))) {
|
if (!is_null($repository->find(intval($this->get('id')))->id)) {
|
||||||
$titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . intval(Input::get('id'));
|
$titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . intval($this->get('id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules = [
|
$rules = [
|
||||||
|
@ -20,8 +20,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RuleGroupFormRequest
|
* Class RuleGroupFormRequest
|
||||||
@ -40,15 +39,27 @@ class RuleGroupFormRequest extends Request
|
|||||||
return auth()->check();
|
return auth()->check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRuleGroupData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => trim($this->input('title')),
|
||||||
|
'description' => trim($this->input('description')),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
|
/** @var RuleGroupRepositoryInterface $repository */
|
||||||
$titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title';
|
$repository = app(RuleGroupRepositoryInterface::class, [auth()->user()]);
|
||||||
if (RuleGroup::find(Input::get('id'))) {
|
$titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title';
|
||||||
$titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . intval(Input::get('id'));
|
if (!is_null($repository->find(intval($this->get('id')))->id)) {
|
||||||
|
$titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . intval($this->get('id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -13,8 +13,7 @@ declare(strict_types = 1);
|
|||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||||
use Input;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TagFormRequest
|
* Class TagFormRequest
|
||||||
@ -38,7 +37,7 @@ class TagFormRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function collectTagData() :array
|
public function collectTagData() :array
|
||||||
{
|
{
|
||||||
if (Input::get('setTag') == 'true') {
|
if ($this->get('setTag') == 'true') {
|
||||||
$latitude = $this->get('latitude');
|
$latitude = $this->get('latitude');
|
||||||
$longitude = $this->get('longitude');
|
$longitude = $this->get('longitude');
|
||||||
$zoomLevel = $this->get('zoomLevel');
|
$zoomLevel = $this->get('zoomLevel');
|
||||||
@ -69,11 +68,13 @@ class TagFormRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
$idRule = '';
|
/** @var TagRepositoryInterface $repository */
|
||||||
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag';
|
$repository = app(TagRepositoryInterface::class);
|
||||||
if (Tag::find(Input::get('id'))) {
|
$idRule = '';
|
||||||
|
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag';
|
||||||
|
if (!is_null($repository->find(intval($this->get('id')))->id)) {
|
||||||
$idRule = 'belongsToUser:tags';
|
$idRule = 'belongsToUser:tags';
|
||||||
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,' . Input::get('id');
|
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,' . $this->get('id');
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -25,6 +25,7 @@ use FireflyIII\Models\RuleGroup;
|
|||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -595,13 +596,24 @@ Breadcrumbs::register(
|
|||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'transactions.show', function (BreadCrumbGenerator $breadcrumbs, TransactionJournal $journal) {
|
'transactions.show', function (BreadCrumbGenerator $breadcrumbs, TransactionJournal $journal) {
|
||||||
|
|
||||||
$what = strtolower($journal->transaction_type_type ?? $journal->transactionType->type);
|
$what = strtolower($journal->transactionType->type);
|
||||||
$breadcrumbs->parent('transactions.index', $what);
|
$breadcrumbs->parent('transactions.index', $what);
|
||||||
$breadcrumbs->push($journal->description, route('transactions.show', [$journal->id]));
|
$breadcrumbs->push($journal->description, route('transactions.show', [$journal->id]));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Breadcrumbs::register(
|
||||||
|
'transactions.convert', function (BreadCrumbGenerator $breadcrumbs, TransactionType $destinationType, TransactionJournal $journal) {
|
||||||
|
|
||||||
|
$breadcrumbs->parent('transactions.show', $journal);
|
||||||
|
$breadcrumbs->push(
|
||||||
|
trans('firefly.convert_to_' . $destinationType->type, ['description' => $journal->description]),
|
||||||
|
route('transactions.convert', [strtolower($destinationType->type), $journal->id])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SPLIT
|
* SPLIT
|
||||||
*/
|
*/
|
||||||
|
@ -369,6 +369,11 @@ class CsvSetup implements SetupInterface
|
|||||||
|
|
||||||
foreach ($results as $rowIndex => $row) {
|
foreach ($results as $rowIndex => $row) {
|
||||||
|
|
||||||
|
// skip first row?
|
||||||
|
if ($rowIndex === 0 && $config['has-headers']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// run specifics here:
|
// run specifics here:
|
||||||
// and this is the point where the specifix go to work.
|
// and this is the point where the specifix go to work.
|
||||||
foreach ($config['specifics'] as $name => $enabled) {
|
foreach ($config['specifics'] as $name => $enabled) {
|
||||||
|
@ -58,9 +58,12 @@ class Preference extends Model
|
|||||||
$data = Crypt::decrypt($value);
|
$data = Crypt::decrypt($value);
|
||||||
} catch (DecryptException $e) {
|
} catch (DecryptException $e) {
|
||||||
Log::error('Could not decrypt preference.', ['id' => $this->id, 'name' => $this->name, 'data' => $value]);
|
Log::error('Could not decrypt preference.', ['id' => $this->id, 'name' => $this->name, 'data' => $value]);
|
||||||
throw new FireflyException('Could not decrypt preference #' . $this->id . '.');
|
throw new FireflyException(
|
||||||
|
sprintf('Could not decrypt preference #%d. If this error persists, please run "php artisan cache:clear" on the command line.', $this->id)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return json_decode($data);
|
return json_decode($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ namespace FireflyIII\Models;
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\TransactionType
|
* FireflyIII\Models\TransactionType
|
||||||
@ -43,6 +44,25 @@ class TransactionType extends Model
|
|||||||
|
|
||||||
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $type
|
||||||
|
*
|
||||||
|
* @return Model|null|static
|
||||||
|
*/
|
||||||
|
public static function routeBinder(string $type)
|
||||||
|
{
|
||||||
|
if (!auth()->check()) {
|
||||||
|
throw new NotFoundHttpException;
|
||||||
|
}
|
||||||
|
$transactionType = self::where('type', $type)->first();
|
||||||
|
if (!is_null($transactionType)) {
|
||||||
|
return $transactionType;
|
||||||
|
}
|
||||||
|
throw new NotFoundHttpException;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -388,7 +388,7 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
// create it:
|
// create it:
|
||||||
$newAccount = new Account(
|
$newAccount = new Account(
|
||||||
[
|
[
|
||||||
'user_id' => $data['user'],
|
'user_id' => $this->user->id,
|
||||||
'account_type_id' => $accountType->id,
|
'account_type_id' => $accountType->id,
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
'virtual_balance' => $data['virtualBalance'],
|
'virtual_balance' => $data['virtualBalance'],
|
||||||
@ -417,13 +417,12 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
protected function storeInitialBalance(Account $account, array $data): TransactionJournal
|
protected function storeInitialBalance(Account $account, array $data): TransactionJournal
|
||||||
{
|
{
|
||||||
$amount = $data['openingBalance'];
|
$amount = $data['openingBalance'];
|
||||||
$user = $data['user'];
|
|
||||||
$name = $data['name'];
|
$name = $data['name'];
|
||||||
$opposing = $this->storeOpposingAccount($amount, $user, $name);
|
$opposing = $this->storeOpposingAccount($amount, $name);
|
||||||
$transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
|
$transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
|
||||||
$journal = TransactionJournal::create(
|
$journal = TransactionJournal::create(
|
||||||
[
|
[
|
||||||
'user_id' => $data['user'],
|
'user_id' => $this->user->id,
|
||||||
'transaction_type_id' => $transactionType->id,
|
'transaction_type_id' => $transactionType->id,
|
||||||
'transaction_currency_id' => $data['openingBalanceCurrency'],
|
'transaction_currency_id' => $data['openingBalanceCurrency'],
|
||||||
'description' => 'Initial balance for "' . $account->name . '"',
|
'description' => 'Initial balance for "' . $account->name . '"',
|
||||||
@ -458,16 +457,14 @@ class AccountRepository implements AccountRepositoryInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param float $amount
|
* @param float $amount
|
||||||
* @param int $user
|
|
||||||
* @param string $name
|
* @param string $name
|
||||||
*
|
*
|
||||||
* @return Account
|
* @return Account
|
||||||
*/
|
*/
|
||||||
protected function storeOpposingAccount(float $amount, int $user, string $name):Account
|
protected function storeOpposingAccount(float $amount, string $name):Account
|
||||||
{
|
{
|
||||||
$type = $amount < 0 ? 'expense' : 'revenue';
|
$type = $amount < 0 ? 'expense' : 'revenue';
|
||||||
$opposingData = [
|
$opposingData = [
|
||||||
'user' => $user,
|
|
||||||
'accountType' => $type,
|
'accountType' => $type,
|
||||||
'name' => $name . ' initial balance',
|
'name' => $name . ' initial balance',
|
||||||
'active' => false,
|
'active' => false,
|
||||||
|
@ -19,6 +19,7 @@ use DB;
|
|||||||
use FireflyIII\Helpers\Collection\Account as AccountCollection;
|
use FireflyIII\Helpers\Collection\Account as AccountCollection;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Query\JoinClause;
|
use Illuminate\Database\Query\JoinClause;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -305,6 +306,8 @@ class AccountTasker implements AccountTaskerInterface
|
|||||||
* - Expense accounts (where money is spent) should only return earnings (the account gets money).
|
* - Expense accounts (where money is spent) should only return earnings (the account gets money).
|
||||||
* - Revenue accounts (where money comes from) should only return expenses (they spend money).
|
* - Revenue accounts (where money comes from) should only return expenses (they spend money).
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
* @param array $accounts
|
* @param array $accounts
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
@ -325,6 +328,7 @@ class AccountTasker implements AccountTaskerInterface
|
|||||||
$join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0);
|
$join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||||
->where('transaction_journals.user_id', $this->user->id)
|
->where('transaction_journals.user_id', $this->user->id)
|
||||||
@ -361,6 +365,8 @@ class AccountTasker implements AccountTaskerInterface
|
|||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
* @param bool $incoming
|
* @param bool $incoming
|
||||||
*
|
*
|
||||||
|
* Opening balances are ignored.
|
||||||
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
protected function financialReport(array $accounts, Carbon $start, Carbon $end, bool $incoming): Collection
|
protected function financialReport(array $accounts, Carbon $start, Carbon $end, bool $incoming): Collection
|
||||||
@ -371,12 +377,14 @@ class AccountTasker implements AccountTaskerInterface
|
|||||||
$query = Transaction
|
$query = Transaction
|
||||||
::distinct()
|
::distinct()
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||||
->leftJoin(
|
->leftJoin(
|
||||||
'transactions as other_side', function (JoinClause $join) use ($joinModifier) {
|
'transactions as other_side', function (JoinClause $join) use ($joinModifier) {
|
||||||
$join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0);
|
$join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
->leftJoin('accounts as other_account', 'other_account.id', '=', 'other_side.account_id')
|
->leftJoin('accounts as other_account', 'other_account.id', '=', 'other_side.account_id')
|
||||||
|
->where('transaction_types.type','!=', TransactionType::OPENING_BALANCE)
|
||||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||||
->where('transaction_journals.user_id', $this->user->id)
|
->where('transaction_journals.user_id', $this->user->id)
|
||||||
|
@ -13,6 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\Attachment;
|
namespace FireflyIII\Repositories\Attachment;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@ -63,6 +64,24 @@ class AttachmentRepository implements AttachmentRepositoryInterface
|
|||||||
return $this->user->attachments()->get();
|
return $this->user->attachments()->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getBetween(Carbon $start, Carbon $end): Collection
|
||||||
|
{
|
||||||
|
$query = $this->user
|
||||||
|
->attachments()
|
||||||
|
->leftJoin('transaction_journals', 'attachments.attachable_id', '=', 'transaction_journals.id')
|
||||||
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||||
|
->get(['attachments.*']);
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
* @param array $data
|
* @param array $data
|
||||||
|
@ -13,6 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\Attachment;
|
namespace FireflyIII\Repositories\Attachment;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
@ -36,6 +37,14 @@ interface AttachmentRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function get(): Collection;
|
public function get(): Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getBetween(Carbon $start, Carbon $end): Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
* @param array $attachmentData
|
* @param array $attachmentData
|
||||||
|
@ -312,25 +312,11 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all journals that were recorded on this bill between these dates.
|
* @param Bill $bill
|
||||||
*
|
|
||||||
* @param Bill $bill
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function getJournalsInRange(Bill $bill, Carbon $start, Carbon $end): Collection
|
|
||||||
{
|
|
||||||
return $bill->transactionJournals()->before($end)->after($start)->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $bill
|
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getOverallAverage($bill): string
|
public function getOverallAverage(Bill $bill): string
|
||||||
{
|
{
|
||||||
$journals = $bill->transactionJournals()->get();
|
$journals = $bill->transactionJournals()->get();
|
||||||
$sum = '0';
|
$sum = '0';
|
||||||
@ -347,6 +333,21 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
return $avg;
|
return $avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getPaidDatesInRange(Bill $bill, Carbon $start, Carbon $end): Collection
|
||||||
|
{
|
||||||
|
$dates = $bill->transactionJournals()->before($end)->after($start)->get(['transaction_journals.date'])->pluck('date');
|
||||||
|
|
||||||
|
return $dates;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Between start and end, tells you on which date(s) the bill is expected to hit.
|
* Between start and end, tells you on which date(s) the bill is expected to hit.
|
||||||
*
|
*
|
||||||
@ -451,21 +452,6 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
return $avg;
|
return $avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Bill $bill
|
|
||||||
*
|
|
||||||
* @return \Carbon\Carbon
|
|
||||||
*/
|
|
||||||
public function lastFoundMatch(Bill $bill): Carbon
|
|
||||||
{
|
|
||||||
$last = $bill->transactionJournals()->orderBy('date', 'DESC')->first();
|
|
||||||
if ($last) {
|
|
||||||
return $last->date;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Carbon::now()->addDays(2); // in the future!
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a bill and a date, this method will tell you at which moment this bill expects its next
|
* Given a bill and a date, this method will tell you at which moment this bill expects its next
|
||||||
* transaction. Whether or not it is there already, is not relevant.
|
* transaction. Whether or not it is there already, is not relevant.
|
||||||
@ -610,7 +596,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
'match' => $data['match'],
|
'match' => $data['match'],
|
||||||
'amount_min' => $data['amount_min'],
|
'amount_min' => $data['amount_min'],
|
||||||
'user_id' => $data['user'],
|
'user_id' => $this->user->id,
|
||||||
'amount_max' => $data['amount_max'],
|
'amount_max' => $data['amount_max'],
|
||||||
'date' => $data['date'],
|
'date' => $data['date'],
|
||||||
'repeat_freq' => $data['repeat_freq'],
|
'repeat_freq' => $data['repeat_freq'],
|
||||||
|
@ -114,22 +114,20 @@ interface BillRepositoryInterface
|
|||||||
public function getJournals(Bill $bill, int $page, int $pageSize = 50): LengthAwarePaginator;
|
public function getJournals(Bill $bill, int $page, int $pageSize = 50): LengthAwarePaginator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all journals that were recorded on this bill between these dates.
|
* @param Bill $bill
|
||||||
*
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getOverallAverage(Bill $bill): string;
|
||||||
|
|
||||||
|
/**
|
||||||
* @param Bill $bill
|
* @param Bill $bill
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getJournalsInRange(Bill $bill, Carbon $start, Carbon $end): Collection;
|
public function getPaidDatesInRange(Bill $bill, Carbon $start, Carbon $end): Collection;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $bill
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getOverallAverage($bill): string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Between start and end, tells you on which date(s) the bill is expected to hit.
|
* Between start and end, tells you on which date(s) the bill is expected to hit.
|
||||||
@ -157,14 +155,6 @@ interface BillRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function getYearAverage(Bill $bill, Carbon $date): string;
|
public function getYearAverage(Bill $bill, Carbon $date): string;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Bill $bill
|
|
||||||
*
|
|
||||||
* @return \Carbon\Carbon
|
|
||||||
*/
|
|
||||||
public function lastFoundMatch(Bill $bill): Carbon;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a bill and a date, this method will tell you at which moment this bill expects its next
|
* Given a bill and a date, this method will tell you at which moment this bill expects its next
|
||||||
* transaction. Whether or not it is there already, is not relevant.
|
* transaction. Whether or not it is there already, is not relevant.
|
||||||
|
@ -19,6 +19,7 @@ use FireflyIII\Events\UpdatedBudgetLimit;
|
|||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\BudgetLimit;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
use FireflyIII\Models\LimitRepetition;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@ -26,6 +27,7 @@ use Illuminate\Database\Eloquent\Builder;
|
|||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Query\JoinClause;
|
use Illuminate\Database\Query\JoinClause;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetRepository
|
* Class BudgetRepository
|
||||||
@ -347,79 +349,75 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function spentInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) : string
|
public function spentInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) : string
|
||||||
{
|
{
|
||||||
// first collect actual transaction journals (fairly easy)
|
// collect amount of transaction journals, which is easy:
|
||||||
$query = $this->user
|
$budgetIds = $budgets->pluck('id')->toArray();
|
||||||
->transactionJournals()
|
$accountIds = $accounts->pluck('id')->toArray();
|
||||||
|
|
||||||
|
Log::debug('spentInPeriod: Now in spentInPeriod for these budgets: ', $budgetIds);
|
||||||
|
Log::debug('spentInPeriod: and these accounts: ', $accountIds);
|
||||||
|
Log::debug(sprintf('spentInPeriod: Start date is "%s", end date is "%s"', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||||
|
|
||||||
|
$fromJournalsQuery = TransactionJournal
|
||||||
|
::leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
|
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||||
->leftJoin(
|
->leftJoin(
|
||||||
'transactions as source', function (JoinClause $join) {
|
'transactions', function (JoinClause $join) {
|
||||||
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', 0);
|
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', '0');
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
->leftJoin(
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||||
'transactions as destination', function (JoinClause $join) {
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||||
$join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')->where('destination.amount', '>', 0);
|
->whereNull('transaction_journals.deleted_at')
|
||||||
}
|
->whereNull('transactions.deleted_at')
|
||||||
);
|
->where('transaction_journals.user_id', $this->user->id)
|
||||||
$query->whereNull('source.deleted_at');
|
->where('transaction_types.type', 'Withdrawal');
|
||||||
$query->whereNull('destination.deleted_at');
|
|
||||||
$query->where('transaction_journals.completed', 1);
|
|
||||||
|
|
||||||
if ($end >= $start) {
|
// add budgets:
|
||||||
$query->before($end)->after($start);
|
|
||||||
}
|
|
||||||
if ($accounts->count() > 0) {
|
|
||||||
$accountIds = $accounts->pluck('id')->toArray();
|
|
||||||
$query->where(
|
|
||||||
// source.account_id in accountIds XOR destination.account_id in accountIds
|
|
||||||
function (Builder $query) use ($accountIds) {
|
|
||||||
$query->where(
|
|
||||||
function (Builder $q1) use ($accountIds) {
|
|
||||||
$q1->whereIn('source.account_id', $accountIds)
|
|
||||||
->whereNotIn('destination.account_id', $accountIds);
|
|
||||||
}
|
|
||||||
)->orWhere(
|
|
||||||
function (Builder $q2) use ($accountIds) {
|
|
||||||
$q2->whereIn('destination.account_id', $accountIds)
|
|
||||||
->whereNotIn('source.account_id', $accountIds);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($budgets->count() > 0) {
|
if ($budgets->count() > 0) {
|
||||||
$budgetIds = $budgets->pluck('id')->toArray();
|
$fromJournalsQuery->whereIn('budget_transaction_journal.budget_id', $budgetIds);
|
||||||
$query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
|
||||||
$query->whereIn('budget_transaction_journal.budget_id', $budgetIds);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// that should do it:
|
// add accounts:
|
||||||
$ids = $query->distinct()->get(['transaction_journals.id'])->pluck('id')->toArray();
|
|
||||||
$first = '0';
|
|
||||||
if (count($ids) > 0) {
|
|
||||||
$first = strval(
|
|
||||||
$this->user->transactions()
|
|
||||||
->whereIn('transaction_journal_id', $ids)
|
|
||||||
->where('amount', '<', '0')
|
|
||||||
->whereNull('transactions.deleted_at')
|
|
||||||
->sum('amount')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// then collection transactions (harder)
|
|
||||||
$query = $this->user->transactions()
|
|
||||||
->where('transactions.amount', '<', 0)
|
|
||||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
|
|
||||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59'));
|
|
||||||
if ($accounts->count() > 0) {
|
if ($accounts->count() > 0) {
|
||||||
$accountIds = $accounts->pluck('id')->toArray();
|
$fromJournalsQuery->whereIn('transactions.account_id', $accountIds);
|
||||||
$query->whereIn('transactions.account_id', $accountIds);
|
|
||||||
}
|
}
|
||||||
|
$first = strval($fromJournalsQuery->sum('transactions.amount'));
|
||||||
|
Log::debug(sprintf('spentInPeriod: Result from first query: %s', $first));
|
||||||
|
unset($fromJournalsQuery);
|
||||||
|
|
||||||
|
// collect amount from transactions:
|
||||||
|
/**
|
||||||
|
* select transactions.id, budget_transaction.budget_id , transactions.amount
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* and budget_transaction.budget_id in (1,61)
|
||||||
|
* and transactions.account_id in (2)
|
||||||
|
*/
|
||||||
|
$fromTransactionsQuery = Transaction
|
||||||
|
::leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id')
|
||||||
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||||
|
->whereNull('transactions.deleted_at')
|
||||||
|
->whereNull('transaction_journals.deleted_at')
|
||||||
|
->where('transactions.amount', '<', 0)
|
||||||
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.user_id', $this->user->id)
|
||||||
|
->where('transaction_types.type', 'Withdrawal');
|
||||||
|
|
||||||
|
// add budgets:
|
||||||
if ($budgets->count() > 0) {
|
if ($budgets->count() > 0) {
|
||||||
$budgetIds = $budgets->pluck('id')->toArray();
|
$fromTransactionsQuery->whereIn('budget_transaction.budget_id', $budgetIds);
|
||||||
$query->leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id');
|
|
||||||
$query->whereIn('budget_transaction.budget_id', $budgetIds);
|
|
||||||
}
|
}
|
||||||
$second = strval($query->sum('transactions.amount'));
|
|
||||||
|
// add accounts:
|
||||||
|
if ($accounts->count() > 0) {
|
||||||
|
$fromTransactionsQuery->whereIn('transactions.account_id', $accountIds);
|
||||||
|
}
|
||||||
|
$second = strval($fromTransactionsQuery->sum('transactions.amount'));
|
||||||
|
Log::debug(sprintf('spentInPeriod: Result from second query: %s', $second));
|
||||||
|
|
||||||
|
Log::debug(sprintf('spentInPeriod: FINAL: %s', bcadd($first, $second)));
|
||||||
|
|
||||||
return bcadd($first, $second);
|
return bcadd($first, $second);
|
||||||
}
|
}
|
||||||
@ -500,7 +498,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
{
|
{
|
||||||
$newBudget = new Budget(
|
$newBudget = new Budget(
|
||||||
[
|
[
|
||||||
'user_id' => $data['user'],
|
'user_id' => $this->user->id,
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -241,6 +241,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
|||||||
if (count($types) > 0) {
|
if (count($types) > 0) {
|
||||||
$query->transactionTypes($types);
|
$query->transactionTypes($types);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($accounts->count() > 0) {
|
if ($accounts->count() > 0) {
|
||||||
$accountIds = $accounts->pluck('id')->toArray();
|
$accountIds = $accounts->pluck('id')->toArray();
|
||||||
$query->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id');
|
$query->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id');
|
||||||
@ -275,7 +276,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$second = $query->get(['transaction_journals.*']);
|
$second = $query->get(['transaction_journals.*','transaction_types.type as transaction_type_type']);
|
||||||
|
|
||||||
$complete = $complete->merge($first);
|
$complete = $complete->merge($first);
|
||||||
$complete = $complete->merge($second);
|
$complete = $complete->merge($second);
|
||||||
@ -433,7 +434,7 @@ class CategoryRepository implements CategoryRepositoryInterface
|
|||||||
{
|
{
|
||||||
$newCategory = Category::firstOrCreateEncrypted(
|
$newCategory = Category::firstOrCreateEncrypted(
|
||||||
[
|
[
|
||||||
'user_id' => $data['user'],
|
'user_id' => $this->user->id,
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -26,7 +26,9 @@ use FireflyIII\Models\TransactionType;
|
|||||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
use Log;
|
use Log;
|
||||||
|
use Preferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class JournalRepository
|
* Class JournalRepository
|
||||||
@ -51,6 +53,41 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
* @param TransactionType $type
|
||||||
|
* @param Account $source
|
||||||
|
* @param Account $destination
|
||||||
|
*
|
||||||
|
* @return MessageBag
|
||||||
|
*/
|
||||||
|
public function convert(TransactionJournal $journal, TransactionType $type, Account $source, Account $destination): MessageBag
|
||||||
|
{
|
||||||
|
// default message bag that shows errors for everything.
|
||||||
|
$messages = new MessageBag;
|
||||||
|
$messages->add('source_account_revenue', trans('firefly.invalid_convert_selection'));
|
||||||
|
$messages->add('destination_account_asset', trans('firefly.invalid_convert_selection'));
|
||||||
|
$messages->add('destination_account_expense', trans('firefly.invalid_convert_selection'));
|
||||||
|
$messages->add('source_account_asset', trans('firefly.invalid_convert_selection'));
|
||||||
|
|
||||||
|
if ($source->id === $destination->id || is_null($source->id) || is_null($destination->id)) {
|
||||||
|
return $messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||||
|
$destinationTransaction = $journal->transactions()->where('amount', '>', 0)->first();
|
||||||
|
$sourceTransaction->account_id = $source->id;
|
||||||
|
$sourceTransaction->save();
|
||||||
|
$destinationTransaction->account_id = $destination->id;
|
||||||
|
$destinationTransaction->save();
|
||||||
|
$journal->transaction_type_id = $type->id;
|
||||||
|
$journal->save();
|
||||||
|
Preferences::mark();
|
||||||
|
$messages = new MessageBag;
|
||||||
|
|
||||||
|
return $messages;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TransactionJournal $journal
|
* @param TransactionJournal $journal
|
||||||
*
|
*
|
||||||
@ -95,7 +132,6 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
return $entry;
|
return $entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $data
|
* @param array $data
|
||||||
*
|
*
|
||||||
@ -107,7 +143,7 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
$transactionType = TransactionType::where('type', ucfirst($data['what']))->first();
|
$transactionType = TransactionType::where('type', ucfirst($data['what']))->first();
|
||||||
$journal = new TransactionJournal(
|
$journal = new TransactionJournal(
|
||||||
[
|
[
|
||||||
'user_id' => $data['user'],
|
'user_id' => $this->user->id,
|
||||||
'transaction_type_id' => $transactionType->id,
|
'transaction_type_id' => $transactionType->id,
|
||||||
'transaction_currency_id' => $data['currency_id'],
|
'transaction_currency_id' => $data['currency_id'],
|
||||||
'description' => $data['description'],
|
'description' => $data['description'],
|
||||||
@ -182,7 +218,7 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
// store actual journal.
|
// store actual journal.
|
||||||
$journal = new TransactionJournal(
|
$journal = new TransactionJournal(
|
||||||
[
|
[
|
||||||
'user_id' => $data['user'],
|
'user_id' => $this->user->id,
|
||||||
'transaction_type_id' => $transactionType->id,
|
'transaction_type_id' => $transactionType->id,
|
||||||
'transaction_currency_id' => $data['amount_currency_id_amount'],
|
'transaction_currency_id' => $data['amount_currency_id_amount'],
|
||||||
'description' => $data['description'],
|
'description' => $data['description'],
|
||||||
@ -267,6 +303,7 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
$journal->description = $data['journal_description'];
|
$journal->description = $data['journal_description'];
|
||||||
$journal->date = $data['date'];
|
$journal->date = $data['date'];
|
||||||
$journal->save();
|
$journal->save();
|
||||||
|
Log::debug(sprintf('Updated split journal #%d', $journal->id));
|
||||||
|
|
||||||
// unlink all categories:
|
// unlink all categories:
|
||||||
$journal->categories()->detach();
|
$journal->categories()->detach();
|
||||||
@ -282,8 +319,6 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
}
|
}
|
||||||
Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id));
|
Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $journal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -297,6 +332,7 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
|
|
||||||
// store each transaction.
|
// store each transaction.
|
||||||
$identifier = 0;
|
$identifier = 0;
|
||||||
|
Log::debug(sprintf('Count %d transactions in updateSplitJournal()', count($data['transactions'])));
|
||||||
foreach ($data['transactions'] as $transaction) {
|
foreach ($data['transactions'] as $transaction) {
|
||||||
Log::debug(sprintf('Split journal update split transaction %d', $identifier));
|
Log::debug(sprintf('Split journal update split transaction %d', $identifier));
|
||||||
$transaction = $this->appendTransactionData($transaction, $data);
|
$transaction = $this->appendTransactionData($transaction, $data);
|
||||||
@ -478,7 +514,7 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
if (strlen($data['source_account_name']) > 0) {
|
if (strlen($data['source_account_name']) > 0) {
|
||||||
$sourceType = AccountType::where('type', 'Revenue account')->first();
|
$sourceType = AccountType::where('type', 'Revenue account')->first();
|
||||||
$sourceAccount = Account::firstOrCreateEncrypted(
|
$sourceAccount = Account::firstOrCreateEncrypted(
|
||||||
['user_id' => $data['user'], 'account_type_id' => $sourceType->id, 'name' => $data['source_account_name'], 'active' => 1]
|
['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => $data['source_account_name'], 'active' => 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -488,7 +524,7 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
}
|
}
|
||||||
$sourceType = AccountType::where('type', 'Cash account')->first();
|
$sourceType = AccountType::where('type', 'Cash account')->first();
|
||||||
$sourceAccount = Account::firstOrCreateEncrypted(
|
$sourceAccount = Account::firstOrCreateEncrypted(
|
||||||
['user_id' => $data['user'], 'account_type_id' => $sourceType->id, 'name' => 'Cash account', 'active' => 1]
|
['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => 'Cash account', 'active' => 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -587,7 +623,7 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
$destinationType = AccountType::where('type', AccountType::EXPENSE)->first();
|
$destinationType = AccountType::where('type', AccountType::EXPENSE)->first();
|
||||||
$destinationAccount = Account::firstOrCreateEncrypted(
|
$destinationAccount = Account::firstOrCreateEncrypted(
|
||||||
[
|
[
|
||||||
'user_id' => $data['user'],
|
'user_id' => $this->user->id,
|
||||||
'account_type_id' => $destinationType->id,
|
'account_type_id' => $destinationType->id,
|
||||||
'name' => $data['destination_account_name'],
|
'name' => $data['destination_account_name'],
|
||||||
'active' => 1,
|
'active' => 1,
|
||||||
@ -601,7 +637,7 @@ class JournalRepository implements JournalRepositoryInterface
|
|||||||
}
|
}
|
||||||
$destinationType = AccountType::where('type', 'Cash account')->first();
|
$destinationType = AccountType::where('type', 'Cash account')->first();
|
||||||
$destinationAccount = Account::firstOrCreateEncrypted(
|
$destinationAccount = Account::firstOrCreateEncrypted(
|
||||||
['user_id' => $data['user'], 'account_type_id' => $destinationType->id, 'name' => 'Cash account', 'active' => 1]
|
['user_id' => $this->user->id, 'account_type_id' => $destinationType->id, 'name' => 'Cash account', 'active' => 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -13,7 +13,10 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\Journal;
|
namespace FireflyIII\Repositories\Journal;
|
||||||
|
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface JournalRepositoryInterface
|
* Interface JournalRepositoryInterface
|
||||||
@ -32,6 +35,15 @@ interface JournalRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function delete(TransactionJournal $journal): bool;
|
public function delete(TransactionJournal $journal): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
* @param TransactionType $type
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return MessageBag
|
||||||
|
*/
|
||||||
|
public function convert(TransactionJournal $journal, TransactionType $type, Account $source, Account $destination): MessageBag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a specific journal
|
* Find a specific journal
|
||||||
*
|
*
|
||||||
|
@ -16,6 +16,7 @@ namespace FireflyIII\Repositories\Journal;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Crypt;
|
use Crypt;
|
||||||
use DB;
|
use DB;
|
||||||
|
use FireflyIII\Models\PiggyBankEvent;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
|
@ -175,7 +175,8 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function store(array $data): PiggyBank
|
public function store(array $data): PiggyBank
|
||||||
{
|
{
|
||||||
$piggyBank = PiggyBank::create($data);
|
$data['order'] = $this->getMaxOrder() + 1;
|
||||||
|
$piggyBank = PiggyBank::create($data);
|
||||||
|
|
||||||
$this->updateNote($piggyBank, $data['note']);
|
$this->updateNote($piggyBank, $data['note']);
|
||||||
|
|
||||||
@ -232,9 +233,9 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$dbNote= $piggyBank->notes()->first();
|
$dbNote = $piggyBank->notes()->first();
|
||||||
if (is_null($dbNote)) {
|
if (is_null($dbNote)) {
|
||||||
$dbNote= new Note();
|
$dbNote = new Note();
|
||||||
$dbNote->noteable()->associate($piggyBank);
|
$dbNote->noteable()->associate($piggyBank);
|
||||||
}
|
}
|
||||||
$dbNote->text = trim($note);
|
$dbNote->text = trim($note);
|
||||||
|
@ -233,7 +233,7 @@ class RuleRepository implements RuleRepositoryInterface
|
|||||||
|
|
||||||
// start by creating a new rule:
|
// start by creating a new rule:
|
||||||
$rule = new Rule;
|
$rule = new Rule;
|
||||||
$rule->user()->associate($data['user_id']);
|
$rule->user()->associate($this->user->id);
|
||||||
|
|
||||||
$rule->rule_group_id = $data['rule_group_id'];
|
$rule->rule_group_id = $data['rule_group_id'];
|
||||||
$rule->order = ($order + 1);
|
$rule->order = ($order + 1);
|
||||||
|
@ -79,6 +79,21 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $ruleGroupId
|
||||||
|
*
|
||||||
|
* @return RuleGroup
|
||||||
|
*/
|
||||||
|
public function find(int $ruleGroupId): RuleGroup
|
||||||
|
{
|
||||||
|
$group = $this->user->ruleGroups()->find($ruleGroupId);
|
||||||
|
if (is_null($group)) {
|
||||||
|
return new RuleGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $group;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
@ -226,7 +241,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
|
|||||||
|
|
||||||
$newRuleGroup = new RuleGroup(
|
$newRuleGroup = new RuleGroup(
|
||||||
[
|
[
|
||||||
'user_id' => $data['user_id'],
|
'user_id' => $this->user->id,
|
||||||
'title' => $data['title'],
|
'title' => $data['title'],
|
||||||
'description' => $data['description'],
|
'description' => $data['description'],
|
||||||
'order' => ($order + 1),
|
'order' => ($order + 1),
|
||||||
|
@ -42,6 +42,13 @@ interface RuleGroupRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function destroy(RuleGroup $ruleGroup, RuleGroup $moveTo = null): bool;
|
public function destroy(RuleGroup $ruleGroup, RuleGroup $moveTo = null): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $ruleGroupId
|
||||||
|
*
|
||||||
|
* @return RuleGroup
|
||||||
|
*/
|
||||||
|
public function find(int $ruleGroupId): RuleGroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
|
141
app/Rules/Actions/SetDestinationAccount.php
Normal file
141
app/Rules/Actions/SetDestinationAccount.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* SetDestinationAccount.php
|
||||||
|
* Copyright (C) 2016 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\Rules\Actions;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\RuleAction;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SetDestinationAccount
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Rules\Action
|
||||||
|
*/
|
||||||
|
class SetDestinationAccount implements ActionInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
private $action;
|
||||||
|
|
||||||
|
/** @var TransactionJournal */
|
||||||
|
private $journal;
|
||||||
|
|
||||||
|
/** @var Account */
|
||||||
|
private $newDestinationAccount;
|
||||||
|
|
||||||
|
/** @var AccountRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TriggerInterface constructor.
|
||||||
|
*
|
||||||
|
* @param RuleAction $action
|
||||||
|
*/
|
||||||
|
public function __construct(RuleAction $action)
|
||||||
|
{
|
||||||
|
$this->action = $action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function act(TransactionJournal $journal): bool
|
||||||
|
{
|
||||||
|
$this->journal = $journal;
|
||||||
|
$this->repository = app(AccountRepositoryInterface::class, [$journal->user]);
|
||||||
|
$count = $journal->transactions()->count();
|
||||||
|
if ($count > 2) {
|
||||||
|
Log::error(sprintf('Cannot change destination account of journal #%d because it is a split journal.', $journal->id));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// journal type:
|
||||||
|
$type = $journal->transactionType->type;
|
||||||
|
|
||||||
|
// if this is a deposit or a transfer, the destination account must be an asset account or a default account, and it MUST exist:
|
||||||
|
if (($type === TransactionType::DEPOSIT || $type === TransactionType::TRANSFER) && !$this->findAssetAccount()) {
|
||||||
|
Log::error(
|
||||||
|
sprintf(
|
||||||
|
'Cannot change destination account of journal #%d because no asset account with name "%s" exists.',
|
||||||
|
$journal->id, $this->action->action_value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is a withdrawal, the new destination account must be a expense account and may be created:
|
||||||
|
if ($type === TransactionType::WITHDRAWAL) {
|
||||||
|
$this->findExpenseAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(sprintf('New destination account is #%d ("%s").', $this->newDestinationAccount->id, $this->newDestinationAccount->name));
|
||||||
|
|
||||||
|
// update destination transaction with new destination account:
|
||||||
|
// get destination transaction:
|
||||||
|
$transaction = $journal->transactions()->where('amount', '>', 0)->first();
|
||||||
|
$transaction->account_id = $this->newDestinationAccount->id;
|
||||||
|
$transaction->save();
|
||||||
|
Log::debug(sprintf('Updated transaction #%d and gave it new account ID.', $transaction->id));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function findAssetAccount(): bool
|
||||||
|
{
|
||||||
|
$account = $this->repository->findByName($this->action->action_value, [AccountType::DEFAULT, AccountType::ASSET]);
|
||||||
|
|
||||||
|
if (is_null($account->id)) {
|
||||||
|
Log::debug(sprintf('There is NO asset account called "%s".', $this->action->action_value));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('There exists an asset account called "%s". ID is #%d', $this->action->action_value, $account->id));
|
||||||
|
$this->newDestinationAccount = $account;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function findExpenseAccount()
|
||||||
|
{
|
||||||
|
$account = $this->repository->findByName($this->action->action_value, [AccountType::REVENUE]);
|
||||||
|
if (is_null($account->id)) {
|
||||||
|
// create new revenue account with this name:
|
||||||
|
$data = [
|
||||||
|
'name' => $this->action->action_value,
|
||||||
|
'accountType' => 'expense',
|
||||||
|
'virtualBalance' => 0,
|
||||||
|
'active' => true,
|
||||||
|
'iban' => null,
|
||||||
|
];
|
||||||
|
$account = $this->repository->store($data);
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Found or created expense account #%d ("%s")', $account->id, $account->name));
|
||||||
|
$this->newDestinationAccount = $account;
|
||||||
|
}
|
||||||
|
}
|
140
app/Rules/Actions/SetSourceAccount.php
Normal file
140
app/Rules/Actions/SetSourceAccount.php
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* SetSourceAccount.php
|
||||||
|
* Copyright (C) 2016 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\Rules\Actions;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\RuleAction;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SetSourceAccount
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Rules\Action
|
||||||
|
*/
|
||||||
|
class SetSourceAccount implements ActionInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
private $action;
|
||||||
|
|
||||||
|
/** @var TransactionJournal */
|
||||||
|
private $journal;
|
||||||
|
|
||||||
|
/** @var Account */
|
||||||
|
private $newSourceAccount;
|
||||||
|
|
||||||
|
/** @var AccountRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TriggerInterface constructor.
|
||||||
|
*
|
||||||
|
* @param RuleAction $action
|
||||||
|
*/
|
||||||
|
public function __construct(RuleAction $action)
|
||||||
|
{
|
||||||
|
$this->action = $action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TransactionJournal $journal
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function act(TransactionJournal $journal): bool
|
||||||
|
{
|
||||||
|
$this->journal = $journal;
|
||||||
|
$this->repository = app(AccountRepositoryInterface::class, [$journal->user]);
|
||||||
|
$count = $journal->transactions()->count();
|
||||||
|
if ($count > 2) {
|
||||||
|
Log::error(sprintf('Cannot change source account of journal #%d because it is a split journal.', $journal->id));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// journal type:
|
||||||
|
$type = $journal->transactionType->type;
|
||||||
|
// if this is a transfer or a withdrawal, the new source account must be an asset account or a default account, and it MUST exist:
|
||||||
|
if (($type === TransactionType::WITHDRAWAL || $type === TransactionType::TRANSFER) && !$this->findAssetAccount()) {
|
||||||
|
Log::error(
|
||||||
|
sprintf(
|
||||||
|
'Cannot change source account of journal #%d because no asset account with name "%s" exists.',
|
||||||
|
$journal->id, $this->action->action_value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is a deposit, the new source account must be a revenue account and may be created:
|
||||||
|
if ($type === TransactionType::DEPOSIT) {
|
||||||
|
$this->findRevenueAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(sprintf('New source account is #%d ("%s").', $this->newSourceAccount->id, $this->newSourceAccount->name));
|
||||||
|
|
||||||
|
// update source transaction with new source account:
|
||||||
|
// get source transaction:
|
||||||
|
$transaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||||
|
$transaction->account_id = $this->newSourceAccount->id;
|
||||||
|
$transaction->save();
|
||||||
|
Log::debug(sprintf('Updated transaction #%d and gave it new account ID.', $transaction->id));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function findAssetAccount(): bool
|
||||||
|
{
|
||||||
|
$account = $this->repository->findByName($this->action->action_value, [AccountType::DEFAULT, AccountType::ASSET]);
|
||||||
|
|
||||||
|
if (is_null($account->id)) {
|
||||||
|
Log::debug(sprintf('There is NO asset account called "%s".', $this->action->action_value));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('There exists an asset account called "%s". ID is #%d', $this->action->action_value, $account->id));
|
||||||
|
$this->newSourceAccount = $account;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function findRevenueAccount()
|
||||||
|
{
|
||||||
|
$account = $this->repository->findByName($this->action->action_value, [AccountType::REVENUE]);
|
||||||
|
if (is_null($account->id)) {
|
||||||
|
// create new revenue account with this name:
|
||||||
|
$data = [
|
||||||
|
'name' => $this->action->action_value,
|
||||||
|
'accountType' => 'revenue',
|
||||||
|
'virtualBalance' => 0,
|
||||||
|
'active' => true,
|
||||||
|
'iban' => null,
|
||||||
|
];
|
||||||
|
$account = $this->repository->store($data);
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Found or created revenue account #%d ("%s")', $account->id, $account->name));
|
||||||
|
$this->newSourceAccount = $account;
|
||||||
|
}
|
||||||
|
}
|
@ -93,7 +93,7 @@ class ExpandedForm
|
|||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
$value = $this->fillFieldValue($name, $value);
|
$value = round($this->fillFieldValue($name, $value), 2);
|
||||||
$options['step'] = 'any';
|
$options['step'] = 'any';
|
||||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
||||||
$currencies = Amt::getAllCurrencies();
|
$currencies = Amt::getAllCurrencies();
|
||||||
|
158
composer.lock
generated
158
composer.lock
generated
@ -410,35 +410,35 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/annotations",
|
"name": "doctrine/annotations",
|
||||||
"version": "v1.2.7",
|
"version": "v1.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/annotations.git",
|
"url": "https://github.com/doctrine/annotations.git",
|
||||||
"reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535"
|
"reference": "30e07cf03edc3cd3ef579d0dd4dd8c58250799a5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
|
"url": "https://api.github.com/repos/doctrine/annotations/zipball/30e07cf03edc3cd3ef579d0dd4dd8c58250799a5",
|
||||||
"reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
|
"reference": "30e07cf03edc3cd3ef579d0dd4dd8c58250799a5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"doctrine/lexer": "1.*",
|
"doctrine/lexer": "1.*",
|
||||||
"php": ">=5.3.2"
|
"php": "^5.6 || ^7.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/cache": "1.*",
|
"doctrine/cache": "1.*",
|
||||||
"phpunit/phpunit": "4.*"
|
"phpunit/phpunit": "^5.6.1"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.3.x-dev"
|
"dev-master": "1.4.x-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-4": {
|
||||||
"Doctrine\\Common\\Annotations\\": "lib/"
|
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@ -474,20 +474,20 @@
|
|||||||
"docblock",
|
"docblock",
|
||||||
"parser"
|
"parser"
|
||||||
],
|
],
|
||||||
"time": "2015-08-31 12:32:49"
|
"time": "2016-10-24 11:45:47"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/cache",
|
"name": "doctrine/cache",
|
||||||
"version": "v1.6.0",
|
"version": "v1.6.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/cache.git",
|
"url": "https://github.com/doctrine/cache.git",
|
||||||
"reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6"
|
"reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6",
|
"url": "https://api.github.com/repos/doctrine/cache/zipball/b6f544a20f4807e81f7044d31e679ccbb1866dc3",
|
||||||
"reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6",
|
"reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -544,7 +544,7 @@
|
|||||||
"cache",
|
"cache",
|
||||||
"caching"
|
"caching"
|
||||||
],
|
],
|
||||||
"time": "2015-12-31 16:37:02"
|
"time": "2016-10-29 11:16:17"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/collections",
|
"name": "doctrine/collections",
|
||||||
@ -1275,16 +1275,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/csv",
|
"name": "league/csv",
|
||||||
"version": "8.1.1",
|
"version": "8.1.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thephpleague/csv.git",
|
"url": "https://github.com/thephpleague/csv.git",
|
||||||
"reference": "3b22a40804aa0bc5224ffb2f5e8248edf0a9a38c"
|
"reference": "33447984f7a7038fefaa5a6177e8407b66bc85b4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/3b22a40804aa0bc5224ffb2f5e8248edf0a9a38c",
|
"url": "https://api.github.com/repos/thephpleague/csv/zipball/33447984f7a7038fefaa5a6177e8407b66bc85b4",
|
||||||
"reference": "3b22a40804aa0bc5224ffb2f5e8248edf0a9a38c",
|
"reference": "33447984f7a7038fefaa5a6177e8407b66bc85b4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1298,7 +1298,7 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "8.0-dev"
|
"dev-master": "8.1-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -1328,7 +1328,7 @@
|
|||||||
"read",
|
"read",
|
||||||
"write"
|
"write"
|
||||||
],
|
],
|
||||||
"time": "2016-09-05 08:16:07"
|
"time": "2016-10-27 11:21:24"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/flysystem",
|
"name": "league/flysystem",
|
||||||
@ -2170,7 +2170,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/class-loader",
|
"name": "symfony/class-loader",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/class-loader.git",
|
"url": "https://github.com/symfony/class-loader.git",
|
||||||
@ -2226,16 +2226,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "6cb0872fb57b38b3b09ff213c21ed693956b9eb0"
|
"reference": "c99da1119ae61e15de0e4829196b9fba6f73d065"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/6cb0872fb57b38b3b09ff213c21ed693956b9eb0",
|
"url": "https://api.github.com/repos/symfony/console/zipball/c99da1119ae61e15de0e4829196b9fba6f73d065",
|
||||||
"reference": "6cb0872fb57b38b3b09ff213c21ed693956b9eb0",
|
"reference": "c99da1119ae61e15de0e4829196b9fba6f73d065",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2283,11 +2283,11 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Symfony Console Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-09-28 00:11:12"
|
"time": "2016-10-06 01:44:51"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/debug",
|
"name": "symfony/debug",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/debug.git",
|
"url": "https://github.com/symfony/debug.git",
|
||||||
@ -2344,16 +2344,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||||
"reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5"
|
"reference": "28b0832b2553ffb80cabef6a7a812ff1e670c0bc"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c0c00c80b3a69132c4e55c3e7db32b4a387615e5",
|
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/28b0832b2553ffb80cabef6a7a812ff1e670c0bc",
|
||||||
"reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5",
|
"reference": "28b0832b2553ffb80cabef6a7a812ff1e670c0bc",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2400,11 +2400,11 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony EventDispatcher Component",
|
"description": "Symfony EventDispatcher Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-07-19 10:45:57"
|
"time": "2016-10-13 06:28:43"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/finder.git",
|
"url": "https://github.com/symfony/finder.git",
|
||||||
@ -2453,16 +2453,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-foundation",
|
"name": "symfony/http-foundation",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-foundation.git",
|
"url": "https://github.com/symfony/http-foundation.git",
|
||||||
"reference": "5114f1becca9f29e3af94374f1689c83c1aa3d97"
|
"reference": "f21e5a8b88274b7720779aa88f9c02c6d6ec08d7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/5114f1becca9f29e3af94374f1689c83c1aa3d97",
|
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f21e5a8b88274b7720779aa88f9c02c6d6ec08d7",
|
||||||
"reference": "5114f1becca9f29e3af94374f1689c83c1aa3d97",
|
"reference": "f21e5a8b88274b7720779aa88f9c02c6d6ec08d7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2502,20 +2502,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony HttpFoundation Component",
|
"description": "Symfony HttpFoundation Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-09-21 20:55:10"
|
"time": "2016-10-24 15:52:44"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-kernel",
|
"name": "symfony/http-kernel",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-kernel.git",
|
"url": "https://github.com/symfony/http-kernel.git",
|
||||||
"reference": "dc339d6eebadfa6e39c52868b4d4a715eff13c69"
|
"reference": "c235f1b13ba67012e283996a5427f22e2e04be14"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/dc339d6eebadfa6e39c52868b4d4a715eff13c69",
|
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/c235f1b13ba67012e283996a5427f22e2e04be14",
|
||||||
"reference": "dc339d6eebadfa6e39c52868b4d4a715eff13c69",
|
"reference": "c235f1b13ba67012e283996a5427f22e2e04be14",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2523,7 +2523,7 @@
|
|||||||
"psr/log": "~1.0",
|
"psr/log": "~1.0",
|
||||||
"symfony/debug": "~2.8|~3.0",
|
"symfony/debug": "~2.8|~3.0",
|
||||||
"symfony/event-dispatcher": "~2.8|~3.0",
|
"symfony/event-dispatcher": "~2.8|~3.0",
|
||||||
"symfony/http-foundation": "~2.8.8|~3.0.8|~3.1.2|~3.2"
|
"symfony/http-foundation": "~2.8.13|~3.1.6|~3.2"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"symfony/config": "<2.8"
|
"symfony/config": "<2.8"
|
||||||
@ -2584,7 +2584,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony HttpKernel Component",
|
"description": "Symfony HttpKernel Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-10-03 19:01:06"
|
"time": "2016-10-27 02:38:31"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-mbstring",
|
||||||
@ -2755,7 +2755,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/process.git",
|
"url": "https://github.com/symfony/process.git",
|
||||||
@ -2804,7 +2804,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/routing",
|
"name": "symfony/routing",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/routing.git",
|
"url": "https://github.com/symfony/routing.git",
|
||||||
@ -2879,16 +2879,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/translation",
|
"name": "symfony/translation",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/translation.git",
|
"url": "https://github.com/symfony/translation.git",
|
||||||
"reference": "93013a18d272e59dab8e67f583155b78c68947eb"
|
"reference": "ff1285087397d2f64041b35e591f3025881c90cd"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/translation/zipball/93013a18d272e59dab8e67f583155b78c68947eb",
|
"url": "https://api.github.com/repos/symfony/translation/zipball/ff1285087397d2f64041b35e591f3025881c90cd",
|
||||||
"reference": "93013a18d272e59dab8e67f583155b78c68947eb",
|
"reference": "ff1285087397d2f64041b35e591f3025881c90cd",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2939,20 +2939,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Translation Component",
|
"description": "Symfony Translation Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-09-06 11:02:40"
|
"time": "2016-10-18 04:30:12"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-dumper.git",
|
"url": "https://github.com/symfony/var-dumper.git",
|
||||||
"reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10"
|
"reference": "4dc2f03b480c43f1665d3317d827a04ed6ffd11e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/70bfe927b86ba9999aeebd829715b0bb2cd39a10",
|
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/4dc2f03b480c43f1665d3317d827a04ed6ffd11e",
|
||||||
"reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10",
|
"reference": "4dc2f03b480c43f1665d3317d827a04ed6ffd11e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -3002,20 +3002,20 @@
|
|||||||
"debug",
|
"debug",
|
||||||
"dump"
|
"dump"
|
||||||
],
|
],
|
||||||
"time": "2016-09-29 14:13:09"
|
"time": "2016-10-18 15:46:07"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
"version": "v1.26.1",
|
"version": "v1.27.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/twigphp/Twig.git",
|
"url": "https://github.com/twigphp/Twig.git",
|
||||||
"reference": "a09d8ee17ac1cfea29ed60c83960ad685c6a898d"
|
"reference": "3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a09d8ee17ac1cfea29ed60c83960ad685c6a898d",
|
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97",
|
||||||
"reference": "a09d8ee17ac1cfea29ed60c83960ad685c6a898d",
|
"reference": "3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -3028,7 +3028,7 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.26-dev"
|
"dev-master": "1.27-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -3063,7 +3063,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"templating"
|
"templating"
|
||||||
],
|
],
|
||||||
"time": "2016-10-05 18:57:41"
|
"time": "2016-10-25 19:17:17"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "vlucas/phpdotenv",
|
"name": "vlucas/phpdotenv",
|
||||||
@ -3880,16 +3880,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "5.6.1",
|
"version": "5.6.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "60c32c5b5e79c2248001efa2560f831da11cc2d7"
|
"reference": "cd13b23ac5a519a4708e00736c26ee0bb28b2e01"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/60c32c5b5e79c2248001efa2560f831da11cc2d7",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/cd13b23ac5a519a4708e00736c26ee0bb28b2e01",
|
||||||
"reference": "60c32c5b5e79c2248001efa2560f831da11cc2d7",
|
"reference": "cd13b23ac5a519a4708e00736c26ee0bb28b2e01",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -3958,7 +3958,7 @@
|
|||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
"time": "2016-10-07 13:03:26"
|
"time": "2016-10-25 07:40:25"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit-mock-objects",
|
"name": "phpunit/phpunit-mock-objects",
|
||||||
@ -4534,7 +4534,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/css-selector",
|
"name": "symfony/css-selector",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/css-selector.git",
|
"url": "https://github.com/symfony/css-selector.git",
|
||||||
@ -4587,16 +4587,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/dom-crawler",
|
"name": "symfony/dom-crawler",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/dom-crawler.git",
|
"url": "https://github.com/symfony/dom-crawler.git",
|
||||||
"reference": "bb7395e8b1db3654de82b9f35d019958276de4d7"
|
"reference": "59eee3c76eb89f21857798620ebdad7a05ad14f4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/bb7395e8b1db3654de82b9f35d019958276de4d7",
|
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/59eee3c76eb89f21857798620ebdad7a05ad14f4",
|
||||||
"reference": "bb7395e8b1db3654de82b9f35d019958276de4d7",
|
"reference": "59eee3c76eb89f21857798620ebdad7a05ad14f4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -4639,20 +4639,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony DomCrawler Component",
|
"description": "Symfony DomCrawler Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-08-05 08:37:39"
|
"time": "2016-10-18 15:46:07"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v3.1.5",
|
"version": "v3.1.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
"reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3"
|
"reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/368b9738d4033c8b93454cb0dbd45d305135a6d3",
|
"url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27",
|
||||||
"reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3",
|
"reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -4688,7 +4688,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Yaml Component",
|
"description": "Symfony Yaml Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-09-25 08:27:07"
|
"time": "2016-10-24 18:41:13"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
|
@ -22,12 +22,13 @@ return [
|
|||||||
'single_user_mode' => true,
|
'single_user_mode' => true,
|
||||||
],
|
],
|
||||||
'chart' => 'chartjs',
|
'chart' => 'chartjs',
|
||||||
'version' => '4.1.1',
|
'version' => '4.1.4',
|
||||||
'csv_import_enabled' => true,
|
'csv_import_enabled' => true,
|
||||||
'maxUploadSize' => 5242880,
|
'maxUploadSize' => 5242880,
|
||||||
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
|
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
|
||||||
'resend_confirmation' => 3600,
|
'resend_confirmation' => 3600,
|
||||||
'confirmation_age' => 14400, // four hours
|
'confirmation_age' => 14400, // four hours
|
||||||
|
'list_length' => 10,
|
||||||
|
|
||||||
'export_formats' => [
|
'export_formats' => [
|
||||||
'csv' => 'FireflyIII\Export\Exporter\CsvExporter',
|
'csv' => 'FireflyIII\Export\Exporter\CsvExporter',
|
||||||
@ -136,6 +137,7 @@ return [
|
|||||||
'bill' => 'FireflyIII\Models\Bill',
|
'bill' => 'FireflyIII\Models\Bill',
|
||||||
'budget' => 'FireflyIII\Models\Budget',
|
'budget' => 'FireflyIII\Models\Budget',
|
||||||
'category' => 'FireflyIII\Models\Category',
|
'category' => 'FireflyIII\Models\Category',
|
||||||
|
'transaction_type' => 'FireflyIII\Models\TransactionType',
|
||||||
'currency' => 'FireflyIII\Models\TransactionCurrency',
|
'currency' => 'FireflyIII\Models\TransactionCurrency',
|
||||||
'limitrepetition' => 'FireflyIII\Models\LimitRepetition',
|
'limitrepetition' => 'FireflyIII\Models\LimitRepetition',
|
||||||
'piggyBank' => 'FireflyIII\Models\PiggyBank',
|
'piggyBank' => 'FireflyIII\Models\PiggyBank',
|
||||||
@ -183,6 +185,9 @@ return [
|
|||||||
'set_description' => 'FireflyIII\Rules\Actions\SetDescription',
|
'set_description' => 'FireflyIII\Rules\Actions\SetDescription',
|
||||||
'append_description' => 'FireflyIII\Rules\Actions\AppendDescription',
|
'append_description' => 'FireflyIII\Rules\Actions\AppendDescription',
|
||||||
'prepend_description' => 'FireflyIII\Rules\Actions\PrependDescription',
|
'prepend_description' => 'FireflyIII\Rules\Actions\PrependDescription',
|
||||||
|
|
||||||
|
'set_source_account' => 'FireflyIII\Rules\Actions\SetSourceAccount',
|
||||||
|
'set_destination_account' => 'FireflyIII\Rules\Actions\SetDestinationAccount',
|
||||||
],
|
],
|
||||||
'rule-actions-text' => [
|
'rule-actions-text' => [
|
||||||
'set_category',
|
'set_category',
|
||||||
|
4
crowdin.yaml
Normal file
4
crowdin.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
files:
|
||||||
|
-
|
||||||
|
source: /resources/lang/en_US/*.php
|
||||||
|
translation: /resources/lang/%locale_with_underscore%/%original_file_name%
|
24
docker/apache-firefly.conf
Normal file
24
docker/apache-firefly.conf
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<VirtualHost *:80>
|
||||||
|
|
||||||
|
ServerAdmin webmaster@localhost
|
||||||
|
DocumentRoot /var/www/firefly-iii/public
|
||||||
|
|
||||||
|
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
|
||||||
|
# error, crit, alert, emerg.
|
||||||
|
# It is also possible to configure the loglevel for particular
|
||||||
|
# modules, e.g.
|
||||||
|
#LogLevel info ssl:warn
|
||||||
|
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||||
|
|
||||||
|
<Directory /var/www/firefly-iii/public>
|
||||||
|
Options -Indexes +FollowSymLinks
|
||||||
|
AllowOverride All
|
||||||
|
Order allow,deny
|
||||||
|
allow from all
|
||||||
|
</Directory>
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -16,12 +16,12 @@ function showHelp(e) {
|
|||||||
$('#helpTitle').html('Please hold...');
|
$('#helpTitle').html('Please hold...');
|
||||||
|
|
||||||
$('#helpModal').modal('show');
|
$('#helpModal').modal('show');
|
||||||
|
$('#helpTitle').html('Help for this page');
|
||||||
$.getJSON('help/' + encodeURI(route)).done(function (data) {
|
$.getJSON('help/' + encodeURI(route)).done(function (data) {
|
||||||
$('#helpBody').html(data.text);
|
$('#helpBody').html(data);
|
||||||
$('#helpTitle').html(data.title);
|
|
||||||
}).fail(function () {
|
}).fail(function () {
|
||||||
$('#helpBody').html('<p class="text-danger">No help text could be found.</p>');
|
$('#helpBody').html('<p class="text-danger">No help text could be found.</p>');
|
||||||
$('#helpTitle').html('Sorry...');
|
$('#helpTitle').html('Apologies');
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,6 @@
|
|||||||
|
|
||||||
/* globals hideable */
|
/* globals hideable */
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by sander on 01/04/16.
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* globals startDate, endDate, reportType, accountIds */
|
/* globals startDate, showOnlyTop, showFullList, endDate, reportType, accountIds, inOutReportUrl, accountReportUrl */
|
||||||
/*
|
/*
|
||||||
* all.js
|
* all.js
|
||||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
@ -7,21 +7,80 @@
|
|||||||
* of the MIT license. See the LICENSE file for details.
|
* of the MIT license. See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by sander on 01/04/16.
|
|
||||||
*/
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// find the little info buttons and respond to them.
|
|
||||||
$('.firefly-info-button').click(clickInfoButton);
|
|
||||||
|
|
||||||
// load the account report, which this report shows:
|
// load the account report, which this report shows:
|
||||||
loadAccountReport();
|
loadAccountReport();
|
||||||
|
|
||||||
|
// load income / expense / difference:
|
||||||
|
loadInOutReport();
|
||||||
|
|
||||||
|
// trigger info click
|
||||||
|
triggerInfoClick();
|
||||||
|
|
||||||
|
// trigger list length things:
|
||||||
|
listLengthInitial();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function triggerInfoClick() {
|
||||||
|
"use strict";
|
||||||
|
// find the little info buttons and respond to them.
|
||||||
|
$('.firefly-info-button').unbind('clicl').click(clickInfoButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
function listLengthInitial() {
|
||||||
|
"use strict";
|
||||||
|
$('.overListLength').hide();
|
||||||
|
$('.listLengthTrigger').unbind('click').click(triggerList)
|
||||||
|
}
|
||||||
|
|
||||||
|
function triggerList(e) {
|
||||||
|
"use strict";
|
||||||
|
var link = $(e.target);
|
||||||
|
var table = link.parent().parent().parent().parent();
|
||||||
|
console.log('data-hidden = ' + table.attr('data-hidden'));
|
||||||
|
if (table.attr('data-hidden') === 'no') {
|
||||||
|
// hide all elements, return false.
|
||||||
|
table.find('.overListLength').hide();
|
||||||
|
table.attr('data-hidden', 'yes');
|
||||||
|
link.text(showFullList);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// show all, return false
|
||||||
|
table.find('.overListLength').show();
|
||||||
|
table.attr('data-hidden', 'no');
|
||||||
|
link.text(showOnlyTop);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadInOutReport() {
|
||||||
|
"use strict";
|
||||||
|
console.log('Going to grab ' + inOutReportUrl);
|
||||||
|
$.get(inOutReportUrl).done(placeInOutReport).fail(failInOutReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
function placeInOutReport(data) {
|
||||||
|
"use strict";
|
||||||
|
$('#incomeReport').removeClass('loading').html(data.income);
|
||||||
|
$('#expenseReport').removeClass('loading').html(data.expenses);
|
||||||
|
$('#incomeVsExpenseReport').removeClass('loading').html(data.incomes_expenses);
|
||||||
|
listLengthInitial();
|
||||||
|
triggerInfoClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function failInOutReport() {
|
||||||
|
"use strict";
|
||||||
|
console.log('Fail in/out report data!');
|
||||||
|
$('#incomeReport').removeClass('loading').addClass('general-chart-error');
|
||||||
|
$('#expenseReport').removeClass('loading').addClass('general-chart-error');
|
||||||
|
$('#incomeVsExpenseReport').removeClass('loading').addClass('general-chart-error');
|
||||||
|
}
|
||||||
|
|
||||||
function loadAccountReport() {
|
function loadAccountReport() {
|
||||||
"use strict";
|
"use strict";
|
||||||
$.get(accountReportUrl).done(placeAccountReport).fail(failAccountReport);
|
$.get(accountReportUrl).done(placeAccountReport).fail(failAccountReport);
|
||||||
|
@ -1,16 +1,52 @@
|
|||||||
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds, lineChart, categoryReportUrl, balanceReportUrl */
|
||||||
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
drawChart();
|
drawChart();
|
||||||
|
|
||||||
// click open the top X income list:
|
loadCategoryReport();
|
||||||
$('#showIncomes').click(showIncomes);
|
loadBalanceReport();
|
||||||
// click open the top X expense list:
|
|
||||||
$('#showExpenses').click(showExpenses);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function loadCategoryReport() {
|
||||||
|
"use strict";
|
||||||
|
console.log('Going to grab ' + categoryReportUrl);
|
||||||
|
$.get(categoryReportUrl).done(placeCategoryReport).fail(failCategoryReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadBalanceReport() {
|
||||||
|
"use strict";
|
||||||
|
console.log('Going to grab ' + categoryReportUrl);
|
||||||
|
$.get(balanceReportUrl).done(placeBalanceReport).fail(failBalanceReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
function placeBalanceReport(data) {
|
||||||
|
"use strict";
|
||||||
|
$('#balanceReport').removeClass('loading').html(data);
|
||||||
|
listLengthInitial();
|
||||||
|
triggerInfoClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function placeCategoryReport(data) {
|
||||||
|
"use strict";
|
||||||
|
$('#categoryReport').removeClass('loading').html(data);
|
||||||
|
listLengthInitial();
|
||||||
|
triggerInfoClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function failBalanceReport() {
|
||||||
|
"use strict";
|
||||||
|
console.log('Fail balance report data!');
|
||||||
|
$('#balanceReport').removeClass('loading').addClass('general-chart-error');
|
||||||
|
}
|
||||||
|
|
||||||
|
function failCategoryReport() {
|
||||||
|
"use strict";
|
||||||
|
console.log('Fail category report data!');
|
||||||
|
$('#categoryReport').removeClass('loading').addClass('general-chart-error');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function drawChart() {
|
function drawChart() {
|
||||||
"use strict";
|
"use strict";
|
||||||
@ -19,46 +55,3 @@ function drawChart() {
|
|||||||
// draw account chart
|
// draw account chart
|
||||||
lineChart('chart/account/report/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'account-balances-chart');
|
lineChart('chart/account/report/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'account-balances-chart');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function showIncomes() {
|
|
||||||
"use strict";
|
|
||||||
if (incomeRestShow) {
|
|
||||||
// hide everything, make button say "show"
|
|
||||||
$('#showIncomes').text(showTheRest);
|
|
||||||
$('.incomesCollapsed').removeClass('in').addClass('out');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
incomeRestShow = false;
|
|
||||||
} else {
|
|
||||||
// show everything, make button say "hide".
|
|
||||||
$('#showIncomes').text(hideTheRest);
|
|
||||||
$('.incomesCollapsed').removeClass('out').addClass('in');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
incomeRestShow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showExpenses() {
|
|
||||||
"use strict";
|
|
||||||
if (expenseRestShow) {
|
|
||||||
// hide everything, make button say "show"
|
|
||||||
$('#showExpenses').text(showTheRestExpense);
|
|
||||||
$('.expenseCollapsed').removeClass('in').addClass('out');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
expenseRestShow = false;
|
|
||||||
} else {
|
|
||||||
// show everything, make button say "hide".
|
|
||||||
$('#showExpenses').text(hideTheRestExpense);
|
|
||||||
$('.expenseCollapsed').removeClass('out').addClass('in');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
expenseRestShow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
@ -1,15 +1,10 @@
|
|||||||
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, year, month, columnChart, lineChart, stackedColumnChart */
|
||||||
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
drawChart();
|
drawChart();
|
||||||
|
|
||||||
// click open the top X income list:
|
|
||||||
$('#showIncomes').click(showIncomes);
|
|
||||||
// click open the top X expense list:
|
|
||||||
$('#showExpenses').click(showExpenses);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -159,47 +154,3 @@ function readCookie(name) {
|
|||||||
function eraseCookie(name) {
|
function eraseCookie(name) {
|
||||||
createCookie(name, "", -1);
|
createCookie(name, "", -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function showIncomes() {
|
|
||||||
"use strict";
|
|
||||||
if (incomeRestShow) {
|
|
||||||
// hide everything, make button say "show"
|
|
||||||
$('#showIncomes').text(showTheRest);
|
|
||||||
$('.incomesCollapsed').removeClass('in').addClass('out');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
incomeRestShow = false;
|
|
||||||
} else {
|
|
||||||
// show everything, make button say "hide".
|
|
||||||
$('#showIncomes').text(hideTheRest);
|
|
||||||
$('.incomesCollapsed').removeClass('out').addClass('in');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
incomeRestShow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showExpenses() {
|
|
||||||
"use strict";
|
|
||||||
if (expenseRestShow) {
|
|
||||||
// hide everything, make button say "show"
|
|
||||||
$('#showExpenses').text(showTheRestExpense);
|
|
||||||
$('.expenseCollapsed').removeClass('in').addClass('out');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
expenseRestShow = false;
|
|
||||||
} else {
|
|
||||||
// show everything, make button say "hide".
|
|
||||||
$('#showExpenses').text(hideTheRestExpense);
|
|
||||||
$('.expenseCollapsed').removeClass('out').addClass('in');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
expenseRestShow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, year, month, columnChart, lineChart, stackedColumnChart */
|
||||||
|
|
||||||
var chartDrawn;
|
var chartDrawn;
|
||||||
var budgetChart;
|
var budgetChart;
|
||||||
@ -7,10 +7,6 @@ $(function () {
|
|||||||
chartDrawn = false;
|
chartDrawn = false;
|
||||||
drawChart();
|
drawChart();
|
||||||
|
|
||||||
// click open the top X income list:
|
|
||||||
$('#showIncomes').click(showIncomes);
|
|
||||||
// click open the top X expense list:
|
|
||||||
$('#showExpenses').click(showExpenses);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -86,52 +82,5 @@ function clickBudgetChart(e) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if chart drawn is true, add new data to existing chart.
|
|
||||||
// console.log('Budget id is ' + budgetId);
|
|
||||||
// $('#budget_chart').empty();
|
|
||||||
// columnChart('chart/budget/period/' + budgetId + '/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'budget_chart');
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showIncomes() {
|
|
||||||
"use strict";
|
|
||||||
if (incomeRestShow) {
|
|
||||||
// hide everything, make button say "show"
|
|
||||||
$('#showIncomes').text(showTheRest);
|
|
||||||
$('.incomesCollapsed').removeClass('in').addClass('out');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
incomeRestShow = false;
|
|
||||||
} else {
|
|
||||||
// show everything, make button say "hide".
|
|
||||||
$('#showIncomes').text(hideTheRest);
|
|
||||||
$('.incomesCollapsed').removeClass('out').addClass('in');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
incomeRestShow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showExpenses() {
|
|
||||||
"use strict";
|
|
||||||
if (expenseRestShow) {
|
|
||||||
// hide everything, make button say "show"
|
|
||||||
$('#showExpenses').text(showTheRestExpense);
|
|
||||||
$('.expenseCollapsed').removeClass('in').addClass('out');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
expenseRestShow = false;
|
|
||||||
} else {
|
|
||||||
// show everything, make button say "hide".
|
|
||||||
$('#showExpenses').text(hideTheRestExpense);
|
|
||||||
$('.expenseCollapsed').removeClass('out').addClass('in');
|
|
||||||
|
|
||||||
// toggle:
|
|
||||||
expenseRestShow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, year, month, columnChart, lineChart, stackedColumnChart */
|
||||||
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
|
@ -58,11 +58,11 @@ function sortStop(event, ui) {
|
|||||||
|
|
||||||
});
|
});
|
||||||
if (parent.hasClass('rule-triggers')) {
|
if (parent.hasClass('rule-triggers')) {
|
||||||
$.post('rules/rules/trigger/reorder/' + ruleId, {_token: token, triggers: entries}).fail(function () {
|
$.post('rules/trigger/order/' + ruleId, {_token: token, triggers: entries}).fail(function () {
|
||||||
alert('Could not re-order rule triggers. Please refresh the page.');
|
alert('Could not re-order rule triggers. Please refresh the page.');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$.post('rules/rules/action/reorder/' + ruleId, {_token: token, actions: entries}).fail(function () {
|
$.post('rules/action/order/' + ruleId, {_token: token, actions: entries}).fail(function () {
|
||||||
alert('Could not re-order rule actions. Please refresh the page.');
|
alert('Could not re-order rule actions. Please refresh the page.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -136,13 +136,13 @@ function resetSplits() {
|
|||||||
// ends with ][description]
|
// ends with ][description]
|
||||||
$.each($('input[name$="][description]"]'), function (i, v) {
|
$.each($('input[name$="][description]"]'), function (i, v) {
|
||||||
var input = $(v);
|
var input = $(v);
|
||||||
input.attr('name', 'transaction[' + i + '][description]');
|
input.attr('name', 'transactions[' + i + '][description]');
|
||||||
console.log('description is now ' + input.attr('name'));
|
console.log('description is now ' + input.attr('name'));
|
||||||
});
|
});
|
||||||
// ends with ][destination_account_name]
|
// ends with ][destination_account_name]
|
||||||
$.each($('input[name$="][destination_account_name]"]'), function (i, v) {
|
$.each($('input[name$="][destination_account_name]"]'), function (i, v) {
|
||||||
var input = $(v);
|
var input = $(v);
|
||||||
input.attr('name', 'transaction[' + i + '][destination_account_name]');
|
input.attr('name', 'transactions[' + i + '][destination_account_name]');
|
||||||
console.log('destination_account_name is now ' + input.attr('name'));
|
console.log('destination_account_name is now ' + input.attr('name'));
|
||||||
});
|
});
|
||||||
// ends with ][source_account_name]
|
// ends with ][source_account_name]
|
||||||
@ -154,19 +154,19 @@ function resetSplits() {
|
|||||||
// ends with ][amount]
|
// ends with ][amount]
|
||||||
$.each($('input[name$="][amount]"]'), function (i, v) {
|
$.each($('input[name$="][amount]"]'), function (i, v) {
|
||||||
var input = $(v);
|
var input = $(v);
|
||||||
input.attr('name', 'transaction[' + i + '][amount]');
|
input.attr('name', 'transactions[' + i + '][amount]');
|
||||||
console.log('amount is now ' + input.attr('name'));
|
console.log('amount is now ' + input.attr('name'));
|
||||||
});
|
});
|
||||||
// ends with ][budget_id]
|
// ends with ][budget_id]
|
||||||
$.each($('input[name$="][budget_id]"]'), function (i, v) {
|
$.each($('input[name$="][budget_id]"]'), function (i, v) {
|
||||||
var input = $(v);
|
var input = $(v);
|
||||||
input.attr('name', 'transaction[' + i + '][budget_id]');
|
input.attr('name', 'transactions[' + i + '][budget_id]');
|
||||||
console.log('budget_id is now ' + input.attr('name'));
|
console.log('budget_id is now ' + input.attr('name'));
|
||||||
});
|
});
|
||||||
// ends with ][category]
|
// ends with ][category]
|
||||||
$.each($('input[name$="][category]"]'), function (i, v) {
|
$.each($('input[name$="][category]"]'), function (i, v) {
|
||||||
var input = $(v);
|
var input = $(v);
|
||||||
input.attr('name', 'transaction[' + i + '][category]');
|
input.attr('name', 'transactions[' + i + '][category]');
|
||||||
console.log('category is now ' + input.attr('name'));
|
console.log('category is now ' + input.attr('name'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'failed' => 'These credentials do not match our records.',
|
'failed' => 'Falscher Benutzername und/oder falsches Passwort.',
|
||||||
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
|
'throttle' => 'Zu viele Login-Versuche. Bitte versuchen Sie es in :seconds Sekunde(n) erneut.',
|
||||||
|
|
||||||
];
|
];
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user