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
|
@ -118,4 +118,4 @@ class UpgradeDatabase extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -107,4 +107,4 @@ class BudgetEventHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,4 +121,4 @@ class StoredJournalEventHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,4 +125,4 @@ class UpdatedJournalEventHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,4 +222,4 @@ class UserEventHandler
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -328,4 +328,4 @@ class SingleController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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,4 +58,4 @@ class PresidentsChoice implements SpecificInterface
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,4 +64,4 @@ class Note extends Model
|
|||||||
return $this->morphTo();
|
return $this->morphTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
@ -429,4 +437,4 @@ class AccountTasker implements AccountTaskerInterface
|
|||||||
|
|
||||||
return $collection;
|
return $collection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,4 +96,4 @@ interface AccountTaskerInterface
|
|||||||
*/
|
*/
|
||||||
public function incomeReport(Collection $accounts, Collection $excluded, Carbon $start, Carbon $end): Collection;
|
public function incomeReport(Collection $accounts, Collection $excluded, Carbon $start, Carbon $end): Collection;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -290,4 +291,4 @@ class JournalTasker implements JournalTaskerInterface
|
|||||||
|
|
||||||
return strval($sum);
|
return strval($sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,4 +64,4 @@ interface JournalTaskerInterface
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getTransactionsOverview(TransactionJournal $journal): array;
|
public function getTransactionsOverview(TransactionJournal $journal): array;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -363,4 +363,4 @@ class Transaction extends Twig_Extension
|
|||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user