mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-01-09 20:11:22 +00:00
Merge branch 'release/4.7.7'
This commit is contained in:
5
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
5
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -12,6 +12,9 @@ I am running Firefly III version x.x.x
|
||||
**Steps to reproduce**
|
||||
What do you need to do to trigger this bug?
|
||||
|
||||
**Expected behavior**
|
||||
What do you expect to see after those steps?
|
||||
|
||||
**Extra info**
|
||||
Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom).
|
||||
|
||||
@@ -19,4 +22,4 @@ Please add extra info here, such as OS, browser, and the output from the /debug
|
||||
Earn bonus points by:
|
||||
|
||||
- Post a stacktrace from your log files
|
||||
- Add a screenshot
|
||||
- Add a screenshot
|
||||
|
||||
@@ -1,3 +1,44 @@
|
||||
# 4.7.7
|
||||
- [Issue 954](https://github.com/firefly-iii/firefly-iii/issues/954) Some additional view chart ranges
|
||||
- [Issue 1710](https://github.com/firefly-iii/firefly-iii/issues/1710) Added a new currency ([hamuz](https://github.com/hamuz))
|
||||
- Transactions will now store (in the database) how they were created.
|
||||
- [Issue 907](https://github.com/firefly-iii/firefly-iii/issues/907) Better and more options on the transaction list.
|
||||
- [Issue 1450](https://github.com/firefly-iii/firefly-iii/issues/1450) Add a rule to change the type of a transaction automagically
|
||||
- [Issue 1701](https://github.com/firefly-iii/firefly-iii/issues/1701) Fix reference to PHP executable ([hertzg](https://github.com/hertzg))
|
||||
- Budget limits have currency information, for future expansion.
|
||||
- Some charts and pages can handle multiple currencies better.
|
||||
- New GA code for those who use it.
|
||||
- The credit card liability type has been removed.
|
||||
- [Issue 896](https://github.com/firefly-iii/firefly-iii/issues/896) Better redirection when coming from deleted objects.
|
||||
- [Issue 1519](https://github.com/firefly-iii/firefly-iii/issues/1519) Fix autocomplete tags
|
||||
- [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) Some fixes for the bunq api calls
|
||||
- [Issue 1650](https://github.com/firefly-iii/firefly-iii/issues/1650) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz))
|
||||
- [Issue 1658](https://github.com/firefly-iii/firefly-iii/issues/1658) Make font heavy again.
|
||||
- [Issue 1660](https://github.com/firefly-iii/firefly-iii/issues/1660) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz))
|
||||
- [Issue 1667](https://github.com/firefly-iii/firefly-iii/issues/1667) Fix pie charts
|
||||
- [Issue 1668](https://github.com/firefly-iii/firefly-iii/issues/1668) YNAB iso_code fix
|
||||
- [Issue 1670](https://github.com/firefly-iii/firefly-iii/issues/1670) Fix piggy bank API error
|
||||
- [Issue 1671](https://github.com/firefly-iii/firefly-iii/issues/1671) More options for liability accounts.
|
||||
- [Issue 1673](https://github.com/firefly-iii/firefly-iii/issues/1673) Fix reconciliation issues.
|
||||
- [Issue 1675](https://github.com/firefly-iii/firefly-iii/issues/1675) Wrong sum in tag report.
|
||||
- [Issue 1679](https://github.com/firefly-iii/firefly-iii/issues/1679) Change type of a transaction wouldn't trigger rules.
|
||||
- [Issue 1682](https://github.com/firefly-iii/firefly-iii/issues/1682) Add liability accounts to transaction conversion
|
||||
- [Issue 1683](https://github.com/firefly-iii/firefly-iii/issues/1683) See matching transaction showed transfers twice.
|
||||
- [Issue 1685](https://github.com/firefly-iii/firefly-iii/issues/1685) fix autocomplete for rules
|
||||
- [Issue 1690](https://github.com/firefly-iii/firefly-iii/issues/1690) Missing highlighted button in intro popup
|
||||
- [Issue 1691](https://github.com/firefly-iii/firefly-iii/issues/1691) No mention of liabilities in demo text
|
||||
- [Issue 1695](https://github.com/firefly-iii/firefly-iii/issues/1695) Small fixes in bills pages.
|
||||
- [Issue 1708](https://github.com/firefly-iii/firefly-iii/issues/1708) Fix by [mathieupost](https://github.com/mathieupost) for bunq
|
||||
- [Issue 1709](https://github.com/firefly-iii/firefly-iii/issues/1709) Fix oauth buttons
|
||||
- [Issue 1712](https://github.com/firefly-iii/firefly-iii/issues/1712) Double slash fix by [hamuz](https://github.com/hamuz)
|
||||
- [Issue 1719](https://github.com/firefly-iii/firefly-iii/issues/1719) Add missing accounts to API
|
||||
- [Issue 1720](https://github.com/firefly-iii/firefly-iii/issues/1720) Fix validation for transaction type.
|
||||
- [Issue 1723](https://github.com/firefly-iii/firefly-iii/issues/1723) API broken for currency exchange rates.
|
||||
- [Issue 1728](https://github.com/firefly-iii/firefly-iii/issues/1728) Fix problem with transaction factory.
|
||||
- [Issue 1729](https://github.com/firefly-iii/firefly-iii/issues/1729) Fix bulk transaction editor
|
||||
- [Issue 1731](https://github.com/firefly-iii/firefly-iii/issues/1731) API failure for budget limits.
|
||||
- Secure headers now allow Mapbox and the 2FA QR code.
|
||||
|
||||
# 4.7.6.2
|
||||
- Docker file builds again.
|
||||
- Fix CSS of OAuth2 authorization view.
|
||||
@@ -44,11 +85,12 @@
|
||||
- [Issue 1639](https://github.com/firefly-iii/firefly-iii/issues/1639) Firefly III trusts the Heroku load balancer, fixing deployment on Heroku.
|
||||
- [Issue 1642](https://github.com/firefly-iii/firefly-iii/issues/1642) Fix issue with split journals.
|
||||
- [Issue 1643](https://github.com/firefly-iii/firefly-iii/issues/1643) Fix reconciliation issue.
|
||||
- Users can no longer give expenses a budget.
|
||||
- Users can no longer give income a budget.
|
||||
- Fix bug in Spectre import.
|
||||
- Heroku would not make you owner.
|
||||
- Add `.htaccess` files to all public directories.
|
||||
- New secure headers will make Firefly III slightly more secure.
|
||||
- The rule "tester" will now also take the "strict"-checkbox into account.
|
||||
|
||||
# 4.7.5.3
|
||||
- [Issue 1527](https://github.com/firefly-iii/firefly-iii/issues/1527), fixed views for transactions without a budget.
|
||||
|
||||
@@ -37,15 +37,15 @@ HOME=/etc/mysql /usr/bin/mysql_install_db --force
|
||||
# Spawn mysqld, php
|
||||
HOME=/etc/mysql /usr/sbin/mysqld &
|
||||
|
||||
/usr/sbin/php-fpm7.1 --nodaemonize --fpm-config /etc/php/7.1/fpm/php-fpm.conf &
|
||||
/usr/sbin/php-fpm7.2 --nodaemonize --fpm-config /etc/php/7.2/fpm/php-fpm.conf &
|
||||
|
||||
# Wait until mysql and php have bound their sockets, indicating readiness
|
||||
while [ ! -e /var/run/mysqld/mysqld.sock ] ; do
|
||||
echo "waiting for mysql to be available at /var/run/mysqld/mysqld.sock"
|
||||
sleep .5
|
||||
done
|
||||
while [ ! -e /var/run/php7.1-fpm.sock ] ; do
|
||||
echo "waiting for php7.1-fpm to be available at /var/run/php7.1-fpm.sock"
|
||||
while [ ! -e /var/run/php7.2-fpm.sock ] ; do
|
||||
echo "waiting for php7.2-fpm to be available at /var/run/php7.2-fpm.sock"
|
||||
sleep .5
|
||||
done
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
|
||||
manifest = (
|
||||
appTitle = (defaultText = "Firefly III"),
|
||||
appVersion = 16,
|
||||
appMarketingVersion = (defaultText = "4.7.6.2"),
|
||||
appVersion = 17,
|
||||
appMarketingVersion = (defaultText = "4.7.7"),
|
||||
|
||||
actions = [
|
||||
# Define your "new document" handlers here.
|
||||
|
||||
@@ -53,7 +53,7 @@ http {
|
||||
}
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_pass unix:/var/run/php7.1-fpm.sock;
|
||||
fastcgi_pass unix:/var/run/php7.2-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -38,37 +38,37 @@ echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sou
|
||||
|
||||
# install packages.
|
||||
apt-get update
|
||||
apt-get install -y nginx php7.1-fpm php7.1-mysql php7.1-gd php7.1-cli php7.1-curl git php7.1-dev php7.1-zip php7.1-intl php7.1-dom php7.1-mbstring php7.1-bcmath mysql-server
|
||||
apt-get install -y nginx php7.2-fpm php7.2-mysql php7.2-gd php7.2-cli php7.2-curl git php7.2-dev php7.2-zip php7.2-intl php7.2-dom php7.2-mbstring php7.2-bcmath mysql-server
|
||||
service nginx stop
|
||||
service php7.1-fpm stop
|
||||
service php7.2-fpm stop
|
||||
service mysql stop
|
||||
systemctl disable nginx
|
||||
systemctl disable php7.1-fpm
|
||||
systemctl disable php7.2-fpm
|
||||
systemctl disable mysql
|
||||
|
||||
# make php.ini display errors:
|
||||
sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.1/fpm/php.ini
|
||||
sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.2/fpm/php.ini
|
||||
|
||||
# patch /etc/php/7.1/fpm/pool.d/www.conf to not change uid/gid to www-data
|
||||
# patch /etc/php/7.2/fpm/pool.d/www.conf to not change uid/gid to www-data
|
||||
sed --in-place='' \
|
||||
--expression='s/^listen.owner = www-data/;listen.owner = www-data/' \
|
||||
--expression='s/^listen.group = www-data/;listen.group = www-data/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
# patch /etc/php/7.1/fpm/php-fpm.conf to not have a pidfile
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
# patch /etc/php/7.2/fpm/php-fpm.conf to not have a pidfile
|
||||
sed --in-place='' \
|
||||
--expression='s/^pid =/;pid =/' \
|
||||
/etc/php/7.1/fpm/php-fpm.conf
|
||||
/etc/php/7.2/fpm/php-fpm.conf
|
||||
|
||||
# move sock file to better dir:
|
||||
sed --in-place='' \
|
||||
--expression='s/^listen = \/run\/php\/php7.1-fpm.sock/listen = \/var\/run\/php7.1-fpm.sock/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
--expression='s/^listen = \/run\/php\/php7.2-fpm.sock/listen = \/var\/run\/php7.2-fpm.sock/' \
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
|
||||
# patch /etc/php/7.1/fpm/pool.d/www.conf to no clear environment variables
|
||||
# patch /etc/php/7.2/fpm/pool.d/www.conf to no clear environment variables
|
||||
# so we can pass in SANDSTORM=1 to apps
|
||||
sed --in-place='' \
|
||||
--expression='s/^;clear_env = no/clear_env=no/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
# patch mysql conf to not change uid, and to use /var/tmp over /tmp
|
||||
# for secure-file-priv see https://github.com/sandstorm-io/vagrant-spk/issues/195
|
||||
sed --in-place='' \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
language: php
|
||||
php:
|
||||
- 7.1.18
|
||||
- 7.2
|
||||
|
||||
cache:
|
||||
directories:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM php:7.1-apache
|
||||
FROM php:7.2-apache
|
||||
|
||||
# If building on a RPi, use --build-arg cores=3 to use all cores when compiling
|
||||
# to speed up the image build
|
||||
|
||||
@@ -213,14 +213,13 @@ class AccountController extends Controller
|
||||
$types = [
|
||||
'all' => [AccountType::DEFAULT, AccountType::CASH, AccountType::ASSET, AccountType::EXPENSE, AccountType::REVENUE,
|
||||
AccountType::INITIAL_BALANCE, AccountType::BENEFICIARY, AccountType::IMPORT, AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,],
|
||||
AccountType::LOAN,AccountType::DEBT, AccountType::MORTGAGE],
|
||||
'asset' => [AccountType::DEFAULT, AccountType::ASSET,],
|
||||
'cash' => [AccountType::CASH,],
|
||||
'expense' => [AccountType::EXPENSE, AccountType::BENEFICIARY,],
|
||||
'revenue' => [AccountType::REVENUE,],
|
||||
'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,],
|
||||
'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION, AccountType::LOAN,],
|
||||
'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION,],
|
||||
'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION],
|
||||
'liability' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
|
||||
'liabilities' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
|
||||
'cc' => [AccountType::CREDITCARD],
|
||||
|
||||
@@ -25,6 +25,8 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\TransactionRequest;
|
||||
use FireflyIII\Events\StoredTransactionJournal;
|
||||
use FireflyIII\Events\UpdatedTransactionJournal;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
@@ -192,6 +194,8 @@ class TransactionController extends Controller
|
||||
$data['user'] = auth()->user()->id;
|
||||
$journal = $repository->store($data);
|
||||
|
||||
event(new StoredTransactionJournal($journal, 0));
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
@@ -241,6 +245,8 @@ class TransactionController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
event(new UpdatedTransactionJournal($journal));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
@@ -50,14 +50,17 @@ class PiggyBankRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$current = $this->string('current_amount');
|
||||
$current = '' === $current ? '0' : $current;
|
||||
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'account_id' => $this->integer('account_id'),
|
||||
'targetamount' => $this->string('target_amount'),
|
||||
'current_amount' => $this->string('current_amount'),
|
||||
'current_amount' => $current,
|
||||
'start_date' => $this->date('start_date'),
|
||||
'target_date' => $this->date('target_date'),
|
||||
'notes' => $this->string('notes'),
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -74,7 +77,7 @@ class PiggyBankRequest extends Request
|
||||
'target_amount' => 'required|numeric|more:0',
|
||||
'current_amount' => 'numeric|more:0|lte:target_amount',
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
];
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ class TransactionRequest extends Request
|
||||
'invoice_date' => $this->date('invoice_date'),
|
||||
'internal_reference' => $this->string('internal_reference'),
|
||||
'notes' => $this->string('notes'),
|
||||
'original-source' => sprintf('api-v%s', config('firefly.api_version')),
|
||||
'transactions' => $this->getTransactionData(),
|
||||
];
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Rule;
|
||||
@@ -63,6 +64,7 @@ use UnexpectedValueException;
|
||||
* Upgrade user database.
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UpgradeDatabase extends Command
|
||||
@@ -95,6 +97,8 @@ class UpgradeDatabase extends Command
|
||||
$this->migrateNotes();
|
||||
$this->migrateAttachmentData();
|
||||
$this->migrateBillsToRules();
|
||||
$this->budgetLimitCurrency();
|
||||
$this->removeCCLiabilities();
|
||||
|
||||
$this->info('Firefly III database is up to date.');
|
||||
|
||||
@@ -435,6 +439,31 @@ class UpgradeDatabase extends Command
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function budgetLimitCurrency(): void
|
||||
{
|
||||
$budgetLimits = BudgetLimit::get();
|
||||
/** @var BudgetLimit $budgetLimit */
|
||||
foreach ($budgetLimits as $budgetLimit) {
|
||||
if (null === $budgetLimit->transaction_currency_id) {
|
||||
$budget = $budgetLimit->budget;
|
||||
if (null !== $budget) {
|
||||
$user = $budget->user;
|
||||
if (null !== $user) {
|
||||
$currency = \Amount::getDefaultCurrencyByUser($user);
|
||||
$budgetLimit->transaction_currency_id = $currency->id;
|
||||
$budgetLimit->save();
|
||||
$this->line(
|
||||
sprintf('Budget limit #%d (part of budget "%s") now has a currency setting (%s).', $budgetLimit->id, $budget->name, $currency->name)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function createNewTypes(): void
|
||||
{
|
||||
// create transaction type "Reconciliation".
|
||||
@@ -507,6 +536,28 @@ class UpgradeDatabase extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function removeCCLiabilities(): void
|
||||
{
|
||||
$ccType = AccountType::where('type', AccountType::CREDITCARD)->first();
|
||||
$debtType =AccountType::where('type', AccountType::DEBT)->first();
|
||||
if(null === $ccType || null === $debtType) {
|
||||
return;
|
||||
}
|
||||
/** @var Collection $accounts */
|
||||
$accounts = Account::where('account_type_id', $ccType->id)->get();
|
||||
foreach($accounts as $account) {
|
||||
$account->account_type_id = $debtType->id;
|
||||
$account->save();
|
||||
$this->line(sprintf('Converted credit card liability account "%s" (#%d) to generic debt liability.', $account->name, $account->id));
|
||||
}
|
||||
if($accounts->count() > 0) {
|
||||
$this->info('Credit card liability types are no longer supported and have been converted to generic debts. See: http://bit.ly/FF3-credit-cards');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method makes sure that the transaction journal uses the currency given in the transaction.
|
||||
*
|
||||
|
||||
@@ -41,10 +41,21 @@ use Log;
|
||||
*/
|
||||
class AccountFactory
|
||||
{
|
||||
use AccountServiceTrait;
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
use AccountServiceTrait;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
@@ -141,17 +152,23 @@ class AccountFactory
|
||||
*/
|
||||
public function findOrCreate(string $accountName, string $accountType): Account
|
||||
{
|
||||
Log::debug(sprintf('Searching for "%s" of type "%s"', $accountName, $accountType));
|
||||
$type = AccountType::whereType($accountType)->first();
|
||||
$accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']);
|
||||
$return = null;
|
||||
|
||||
Log::debug(sprintf('Account type is #%d', $type->id));
|
||||
|
||||
/** @var Account $object */
|
||||
foreach ($accounts as $object) {
|
||||
if ($object->name === $accountName) {
|
||||
Log::debug(sprintf('Found account #%d "%s".', $object->id, $object->name));
|
||||
$return = $object;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (null === $return) {
|
||||
Log::debug('Found nothing. Will create a new one.');
|
||||
$return = $this->create(
|
||||
[
|
||||
'user_id' => $this->user->id,
|
||||
|
||||
@@ -34,7 +34,15 @@ use Log;
|
||||
*/
|
||||
class AccountMetaFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
|
||||
@@ -26,12 +26,22 @@ namespace FireflyIII\Factory;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\User;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class AttachmentFactory
|
||||
*/
|
||||
class AttachmentFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
|
||||
@@ -36,6 +36,16 @@ use Log;
|
||||
*/
|
||||
class BillFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
use BillServiceTrait;
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
@@ -27,12 +27,23 @@ namespace FireflyIII\Factory;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class BudgetFactory.
|
||||
*/
|
||||
class BudgetFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
|
||||
@@ -34,6 +34,16 @@ use Log;
|
||||
*/
|
||||
class CategoryFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
|
||||
@@ -37,6 +37,16 @@ use Log;
|
||||
*/
|
||||
class PiggyBankEventFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param PiggyBank|null $piggyBank
|
||||
|
||||
@@ -26,12 +26,23 @@ namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\User;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class PiggyBankFactory
|
||||
*/
|
||||
class PiggyBankFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
|
||||
@@ -39,6 +39,16 @@ use Log;
|
||||
*/
|
||||
class RecurrenceFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
use TransactionTypeTrait, TransactionServiceTrait, RecurringTransactionTrait;
|
||||
|
||||
/** @var User */
|
||||
|
||||
@@ -27,12 +27,23 @@ namespace FireflyIII\Factory;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class TagFactory
|
||||
*/
|
||||
class TagFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var Collection */
|
||||
private $tags;
|
||||
/** @var User */
|
||||
|
||||
@@ -36,6 +36,16 @@ use Log;
|
||||
*/
|
||||
class TransactionCurrencyFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
|
||||
@@ -40,6 +40,16 @@ use Log;
|
||||
*/
|
||||
class TransactionFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
use TransactionServiceTrait;
|
||||
|
||||
/** @var User */
|
||||
@@ -98,6 +108,7 @@ class TransactionFactory
|
||||
{
|
||||
Log::debug('Start of TransactionFactory::createPair()', $data);
|
||||
// all this data is the same for both transactions:
|
||||
Log::debug('Searching for currency info.');
|
||||
$currency = $this->findCurrency($data['currency_id'], $data['currency_code']);
|
||||
$description = $journal->description === $data['description'] ? null : $data['description'];
|
||||
|
||||
@@ -154,6 +165,7 @@ class TransactionFactory
|
||||
}
|
||||
|
||||
// set foreign currency
|
||||
Log::debug('Trying to find foreign currency information.');
|
||||
$foreign = $this->findCurrency($data['foreign_currency_id'], $data['foreign_currency_code']);
|
||||
$this->setForeignCurrency($source, $foreign);
|
||||
$this->setForeignCurrency($dest, $foreign);
|
||||
|
||||
@@ -36,10 +36,21 @@ use Log;
|
||||
*/
|
||||
class TransactionJournalFactory
|
||||
{
|
||||
use JournalServiceTrait, TransactionTypeTrait;
|
||||
/** @var User The user */
|
||||
private $user;
|
||||
|
||||
use JournalServiceTrait, TransactionTypeTrait;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new transaction journal.
|
||||
*
|
||||
@@ -57,13 +68,15 @@ class TransactionJournalFactory
|
||||
$type = $this->findTransactionType($data['type']);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
|
||||
Log::debug(sprintf('Going to store a %s', $type->type));
|
||||
$journal = TransactionJournal::create(
|
||||
$description = app('steam')->cleanString($data['description']);
|
||||
$description = str_replace(["\n", "\t", "\r"], "\x20", $description);
|
||||
$journal = TransactionJournal::create(
|
||||
[
|
||||
'user_id' => $data['user'],
|
||||
'transaction_type_id' => $type->id,
|
||||
'bill_id' => null,
|
||||
'transaction_currency_id' => $defaultCurrency->id,
|
||||
'description' => $data['description'],
|
||||
'description' => $description,
|
||||
'date' => $data['date']->format('Y-m-d'),
|
||||
'order' => 0,
|
||||
'tag_count' => 0,
|
||||
@@ -104,7 +117,7 @@ class TransactionJournalFactory
|
||||
// store date meta fields (if present):
|
||||
$fields = ['sepa-cc', 'sepa-ct-op', 'sepa-ct-id', 'sepa-db', 'sepa-country', 'sepa-ep', 'sepa-ci', 'interest_date', 'book_date', 'process_date',
|
||||
'due_date', 'recurrence_id', 'payment_date', 'invoice_date', 'internal_reference', 'bunq_payment_id', 'importHash', 'importHashV2',
|
||||
'external_id', 'sepa-batch-id'];
|
||||
'external_id', 'sepa-batch-id', 'original-source'];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$this->storeMeta($journal, $data, $field);
|
||||
|
||||
@@ -34,6 +34,16 @@ use Log;
|
||||
*/
|
||||
class TransactionJournalMetaFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
|
||||
@@ -26,12 +26,22 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Models\TransactionType;
|
||||
|
||||
use Log;
|
||||
/**
|
||||
* Class TransactionTypeFactory
|
||||
*/
|
||||
class TransactionTypeFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
|
||||
@@ -23,12 +23,22 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Generator\Chart\Basic;
|
||||
|
||||
use FireflyIII\Support\ChartColour;
|
||||
|
||||
use Log;
|
||||
/**
|
||||
* Class ChartJsGenerator.
|
||||
*/
|
||||
class ChartJsGenerator implements GeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will generate a Chart JS compatible array from the given input. Expects this format.
|
||||
*
|
||||
|
||||
@@ -42,6 +42,7 @@ use Throwable;
|
||||
|
||||
/**
|
||||
* Class MonthReportGenerator.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
@@ -66,6 +67,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
{
|
||||
$this->expenses = new Collection;
|
||||
$this->income = new Collection;
|
||||
$this->tags = new Collection;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,8 +220,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
$collector->addFilter(OpposingAccountFilter::class);
|
||||
$collector->addFilter(PositiveAmountFilter::class);
|
||||
|
||||
$transactions = $collector->getTransactions();
|
||||
|
||||
$transactions = $collector->getTransactions();
|
||||
$this->expenses = $transactions;
|
||||
|
||||
return $transactions;
|
||||
@@ -260,6 +261,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
*/
|
||||
protected function summarizeByTag(Collection $collection): array
|
||||
{
|
||||
$tagIds = array_map('\intval', $this->tags->pluck('id')->toArray());
|
||||
$result = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($collection as $transaction) {
|
||||
@@ -267,9 +269,11 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
$journalTags = $journal->tags;
|
||||
/** @var Tag $journalTag */
|
||||
foreach ($journalTags as $journalTag) {
|
||||
$journalTagId = $journalTag->id;
|
||||
$result[$journalTagId] = $result[$journalTagId] ?? '0';
|
||||
$result[$journalTagId] = bcadd($transaction->transaction_amount, $result[$journalTagId]);
|
||||
$journalTagId = (int)$journalTag->id;
|
||||
if (\in_array($journalTagId, $tagIds, true)) {
|
||||
$result[$journalTagId] = $result[$journalTagId] ?? '0';
|
||||
$result[$journalTagId] = bcadd($transaction->transaction_amount, $result[$journalTagId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Helpers\Attachments;
|
||||
|
||||
use Crypt;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -63,8 +64,13 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
$this->messages = new MessageBag;
|
||||
$this->attachments = new Collection;
|
||||
$this->uploadDisk = Storage::disk('upload');
|
||||
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the content of an attachment.
|
||||
*
|
||||
@@ -177,13 +183,17 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
/**
|
||||
* Save attachments that get uploaded with models, through the app.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param object $model
|
||||
* @param array|null $files
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Illuminate\Contracts\Encryption\EncryptException
|
||||
*/
|
||||
public function saveAttachmentsForModel(Model $model, ?array $files): bool
|
||||
public function saveAttachmentsForModel(object $model, ?array $files): bool
|
||||
{
|
||||
if(!($model instanceof Model)) {
|
||||
return false;
|
||||
}
|
||||
Log::debug(sprintf('Now in saveAttachmentsForModel for model %s', \get_class($model)));
|
||||
if (\is_array($files)) {
|
||||
Log::debug('$files is an array.');
|
||||
@@ -236,6 +246,7 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
*
|
||||
* @return Attachment|null
|
||||
* @throws \Illuminate\Contracts\Encryption\EncryptException
|
||||
* @throws FireflyException
|
||||
*/
|
||||
protected function processFile(UploadedFile $file, Model $model): ?Attachment
|
||||
{
|
||||
@@ -257,6 +268,11 @@ class AttachmentHelper implements AttachmentHelperInterface
|
||||
|
||||
$fileObject = $file->openFile('r');
|
||||
$fileObject->rewind();
|
||||
|
||||
if(0 === $file->getSize()) {
|
||||
throw new FireflyException('Cannot upload empty or non-existent file.');
|
||||
}
|
||||
|
||||
$content = $fileObject->fread($file->getSize());
|
||||
$encrypted = Crypt::encrypt($content);
|
||||
Log::debug(sprintf('Full file length is %d and upload size is %d.', \strlen($content), $file->getSize()));
|
||||
|
||||
@@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Helpers\Attachments;
|
||||
|
||||
use FireflyIII\Models\Attachment;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\MessageBag;
|
||||
|
||||
@@ -84,10 +83,10 @@ interface AttachmentHelperInterface
|
||||
/**
|
||||
* Save attachments that got uploaded.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param object $model
|
||||
* @param null|array $files
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveAttachmentsForModel(Model $model, ?array $files): bool;
|
||||
public function saveAttachmentsForModel(object $model, ?array $files): bool;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class MetaPieChart.
|
||||
@@ -88,6 +89,11 @@ class MetaPieChart implements MetaPieChartInterface
|
||||
$this->budgets = new Collection;
|
||||
$this->categories = new Collection;
|
||||
$this->tags = new Collection;
|
||||
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace FireflyIII\Helpers\Collection;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Bill as BillModel;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Class BillLine.
|
||||
@@ -42,6 +43,8 @@ class BillLine
|
||||
protected $max;
|
||||
/** @var string What was the min amount. */
|
||||
protected $min;
|
||||
/** @var TransactionCurrency The transaction currency */
|
||||
private $currency;
|
||||
/** @var Carbon Latest date that payment is expected. */
|
||||
private $endOfPayDate;
|
||||
/** @var Carbon Date of last hit */
|
||||
@@ -99,6 +102,22 @@ class BillLine
|
||||
$this->bill = $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function getCurrency(): TransactionCurrency
|
||||
{
|
||||
return $this->currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*/
|
||||
public function setCurrency(TransactionCurrency $currency): void
|
||||
{
|
||||
$this->currency = $currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of pay date getter.
|
||||
*
|
||||
|
||||
@@ -57,6 +57,16 @@ use Log;
|
||||
*/
|
||||
class TransactionCollector implements TransactionCollectorInterface
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @var array */
|
||||
private $accountIds = [];
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace FireflyIII\Helpers\Filter;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use Log;
|
||||
/**
|
||||
* Class TransferFilter.
|
||||
*
|
||||
@@ -49,6 +49,7 @@ class TransferFilter implements FilterInterface
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($set as $transaction) {
|
||||
if (TransactionType::TRANSFER !== $transaction->transaction_type_type) {
|
||||
Log::debug(sprintf('Transaction #%d is not a transfer, add it.', $transaction->id));
|
||||
$new->push($transaction);
|
||||
continue;
|
||||
}
|
||||
@@ -60,6 +61,7 @@ class TransferFilter implements FilterInterface
|
||||
sort($accountIds);
|
||||
sort($transactionIds);
|
||||
$key = $journalId . '-' . implode(',', $transactionIds) . '-' . implode(',', $accountIds) . '-' . $amount;
|
||||
Log::debug(sprintf('Current transaction key is "%s"', $key));
|
||||
if (!isset($count[$key])) {
|
||||
// not yet counted? add to new set and count it:
|
||||
$new->push($transaction);
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Helpers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class FiscalHelper.
|
||||
@@ -38,6 +39,10 @@ class FiscalHelper implements FiscalHelperInterface
|
||||
public function __construct()
|
||||
{
|
||||
$this->useCustomFiscalYear = app('preferences')->get('customFiscalYear', false)->data;
|
||||
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,6 +40,16 @@ class Help implements HelpInterface
|
||||
/** @var string The user agent. */
|
||||
protected $userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get from cache.
|
||||
*
|
||||
|
||||
@@ -51,6 +51,11 @@ class BalanceReportHelper implements BalanceReportHelperInterface
|
||||
public function __construct(BudgetRepositoryInterface $budgetRepository)
|
||||
{
|
||||
$this->budgetRepository = $budgetRepository;
|
||||
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class BudgetReportHelper.
|
||||
@@ -46,6 +47,11 @@ class BudgetReportHelper implements BudgetReportHelperInterface
|
||||
public function __construct(BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,6 +48,16 @@ class NetWorth implements NetWorthInterface
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's net worth in an array with the following layout:
|
||||
*
|
||||
|
||||
@@ -30,7 +30,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use Log;
|
||||
/**
|
||||
* Class PopupReport.
|
||||
*
|
||||
@@ -38,6 +38,16 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class PopupReport implements PopupReportInterface
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the tranactions for one account and one budget.
|
||||
*
|
||||
|
||||
@@ -32,7 +32,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use Log;
|
||||
/**
|
||||
* Class ReportHelper.
|
||||
*
|
||||
@@ -52,6 +52,12 @@ class ReportHelper implements ReportHelperInterface
|
||||
public function __construct(BudgetRepositoryInterface $budgetRepository)
|
||||
{
|
||||
$this->budgetRepository = $budgetRepository;
|
||||
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,6 +98,7 @@ class ReportHelper implements ReportHelperInterface
|
||||
|
||||
$billLine = new BillLine;
|
||||
$billLine->setBill($bill);
|
||||
$billLine->setCurrency($bill->transactionCurrency);
|
||||
$billLine->setPayDate($payDate);
|
||||
$billLine->setEndOfPayDate($endOfPayPeriod);
|
||||
$billLine->setMin((string)$bill->amount_min);
|
||||
|
||||
@@ -29,6 +29,7 @@ use FireflyIII\Http\Requests\AccountFormRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -82,12 +83,10 @@ class CreateController extends Controller
|
||||
$debt = $this->repository->getAccountTypeByType(AccountType::DEBT);
|
||||
$loan = $this->repository->getAccountTypeByType(AccountType::LOAN);
|
||||
$mortgage = $this->repository->getAccountTypeByType(AccountType::MORTGAGE);
|
||||
$creditCard = $this->repository->getAccountTypeByType(AccountType::CREDITCARD);
|
||||
$liabilityTypes = [
|
||||
$debt->id => (string)trans('firefly.account_type_' . AccountType::DEBT),
|
||||
$loan->id => (string)trans('firefly.account_type_' . AccountType::LOAN),
|
||||
$mortgage->id => (string)trans('firefly.account_type_' . AccountType::MORTGAGE),
|
||||
$creditCard->id => (string)trans('firefly.account_type_' . AccountType::CREDITCARD),
|
||||
];
|
||||
asort($liabilityTypes);
|
||||
|
||||
@@ -132,6 +131,8 @@ class CreateController extends Controller
|
||||
$request->session()->flash('success', (string)trans('firefly.stored_new_account', ['name' => $account->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
|
||||
|
||||
// update preferences if necessary:
|
||||
$frontPage = app('preferences')->get('frontPageAccounts', [])->data;
|
||||
if (AccountType::ASSET === $account->accountType->type && \count($frontPage) > 0) {
|
||||
|
||||
@@ -90,12 +90,10 @@ class EditController extends Controller
|
||||
$debt = $this->repository->getAccountTypeByType(AccountType::DEBT);
|
||||
$loan = $this->repository->getAccountTypeByType(AccountType::LOAN);
|
||||
$mortgage = $this->repository->getAccountTypeByType(AccountType::MORTGAGE);
|
||||
$creditCard = $this->repository->getAccountTypeByType(AccountType::CREDITCARD);
|
||||
$liabilityTypes = [
|
||||
$debt->id => (string)trans('firefly.account_type_' . AccountType::DEBT),
|
||||
$loan->id => (string)trans('firefly.account_type_' . AccountType::LOAN),
|
||||
$mortgage->id => (string)trans('firefly.account_type_' . AccountType::MORTGAGE),
|
||||
$creditCard->id => (string)trans('firefly.account_type_' . AccountType::CREDITCARD),
|
||||
];
|
||||
asort($liabilityTypes);
|
||||
|
||||
|
||||
@@ -64,8 +64,8 @@ class LinkController extends Controller
|
||||
$subTitleIcon = 'fa-link';
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (true !== session('link_types.create.fromStore')) {
|
||||
$this->rememberPreviousUri('link_types.create.uri');
|
||||
if (true !== session('link-types.create.fromStore')) {
|
||||
$this->rememberPreviousUri('link-types.create.uri');
|
||||
}
|
||||
|
||||
return view('admin.link.create', compact('subTitle', 'subTitleIcon'));
|
||||
@@ -100,7 +100,7 @@ class LinkController extends Controller
|
||||
}
|
||||
}
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('link_types.delete.uri');
|
||||
$this->rememberPreviousUri('link-types.delete.uri');
|
||||
|
||||
return view('admin.link.delete', compact('linkType', 'subTitle', 'moveTo', 'count'));
|
||||
}
|
||||
@@ -123,7 +123,7 @@ class LinkController extends Controller
|
||||
$request->session()->flash('success', (string)trans('firefly.deleted_link_type', ['name' => $name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
return redirect($this->getPreviousUri('link_types.delete.uri'));
|
||||
return redirect($this->getPreviousUri('link-types.delete.uri'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,10 +145,10 @@ class LinkController extends Controller
|
||||
$subTitleIcon = 'fa-link';
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('link_types.edit.fromUpdate')) {
|
||||
$this->rememberPreviousUri('link_types.edit.uri'); // @codeCoverageIgnore
|
||||
if (true !== session('link-types.edit.fromUpdate')) {
|
||||
$this->rememberPreviousUri('link-types.edit.uri'); // @codeCoverageIgnore
|
||||
}
|
||||
$request->session()->forget('link_types.edit.fromUpdate');
|
||||
$request->session()->forget('link-types.edit.fromUpdate');
|
||||
|
||||
return view('admin.link.edit', compact('subTitle', 'subTitleIcon', 'linkType'));
|
||||
}
|
||||
@@ -207,10 +207,10 @@ class LinkController extends Controller
|
||||
];
|
||||
$linkType = $repository->store($data);
|
||||
$request->session()->flash('success', (string)trans('firefly.stored_new_link_type', ['name' => $linkType->name]));
|
||||
$redirect = redirect($this->getPreviousUri('link_types.create.uri'));
|
||||
$redirect = redirect($this->getPreviousUri('link-types.create.uri'));
|
||||
if (1 === (int)$request->get('create_another')) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
$request->session()->put('link_types.create.fromStore', true);
|
||||
$request->session()->put('link-types.create.fromStore', true);
|
||||
|
||||
$redirect = redirect(route('admin.links.create'))->withInput();
|
||||
}
|
||||
@@ -245,10 +245,10 @@ class LinkController extends Controller
|
||||
|
||||
$request->session()->flash('success', (string)trans('firefly.updated_link_type', ['name' => $linkType->name]));
|
||||
app('preferences')->mark();
|
||||
$redirect = redirect($this->getPreviousUri('link_types.edit.uri'));
|
||||
$redirect = redirect($this->getPreviousUri('link-types.edit.uri'));
|
||||
if (1 === (int)$request->get('return_to_edit')) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
$request->session()->put('link_types.edit.fromUpdate', true);
|
||||
$request->session()->put('link-types.edit.fromUpdate', true);
|
||||
|
||||
$redirect = redirect(route('admin.links.edit', [$linkType->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ class ShowController extends Controller
|
||||
'firefly.without_budget_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
);
|
||||
$periods = $this->getBudgetPeriodOverview();
|
||||
$periods = $this->getBudgetPeriodOverview($end);
|
||||
$page = (int)$request->get('page');
|
||||
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ class ShowController extends Controller
|
||||
$subTitleIcon = 'fa-bar-chart';
|
||||
$page = (int)$request->get('page');
|
||||
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
|
||||
$periods = $this->getCategoryPeriodOverview($category, $start);
|
||||
$periods = $this->getCategoryPeriodOverview($category, $end);
|
||||
$path = route('categories.show', [$category->id, $start->format('Y-m-d'), $end->format('Y-m-d')]);
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_category',
|
||||
|
||||
@@ -210,23 +210,25 @@ class AccountController extends Controller
|
||||
$budgetIds[] = $budgetId;
|
||||
if (!isset($result[$combi])) {
|
||||
$result[$combi] = [
|
||||
'total' => '0',
|
||||
'budget_id' => $budgetId,
|
||||
'currency' => $currencyName,
|
||||
'total' => '0',
|
||||
'budget_id' => $budgetId,
|
||||
'currency' => $currencyName,
|
||||
'currency_symbol' => $transaction->transaction_currency_symbol,
|
||||
];
|
||||
}
|
||||
$result[$combi]['total'] = bcadd($transaction->transaction_amount, $result[$combi]['total']);
|
||||
}
|
||||
|
||||
$names = $this->getBudgetNames($budgetIds);
|
||||
|
||||
foreach ($result as $row) {
|
||||
$budgetId = $row['budget_id'];
|
||||
$name = $names[$budgetId];
|
||||
$label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency']]);
|
||||
$chartData[$label] = $row['total'];
|
||||
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol']];
|
||||
}
|
||||
|
||||
$data = $this->generator->pieChart($chartData);
|
||||
$data = $this->generator->multiCurrencyPieChart($chartData);
|
||||
$cache->store($data);
|
||||
|
||||
return response()->json($data);
|
||||
@@ -276,6 +278,7 @@ class AccountController extends Controller
|
||||
$result = [];
|
||||
$chartData = [];
|
||||
$categoryIds = [];
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$jrnlCatId = (int)$transaction->transaction_journal_category_id;
|
||||
@@ -286,24 +289,25 @@ class AccountController extends Controller
|
||||
$categoryIds[] = $categoryId;
|
||||
if (!isset($result[$combi])) {
|
||||
$result[$combi] = [
|
||||
'total' => '0',
|
||||
'category_id' => $categoryId,
|
||||
'currency' => $currencyName,
|
||||
'total' => '0',
|
||||
'category_id' => $categoryId,
|
||||
'currency' => $currencyName,
|
||||
'currency_symbol' => $transaction->transaction_currency_symbol,
|
||||
];
|
||||
}
|
||||
$result[$combi]['total'] = bcadd($transaction->transaction_amount, $result[$combi]['total']);
|
||||
}
|
||||
|
||||
$names = $this->getCategoryNames(array_keys($result));
|
||||
$names = $this->getCategoryNames($categoryIds);
|
||||
|
||||
foreach ($result as $row) {
|
||||
$categoryId = $row['category_id'];
|
||||
$name = $names[$categoryId] ?? '(unknown)';
|
||||
$label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency']]);
|
||||
$chartData[$label] = $row['total'];
|
||||
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol']];
|
||||
}
|
||||
|
||||
$data = $this->generator->pieChart($chartData);
|
||||
$data = $this->generator->multiCurrencyPieChart($chartData);
|
||||
$cache->store($data);
|
||||
|
||||
return response()->json($data);
|
||||
@@ -371,7 +375,7 @@ class AccountController extends Controller
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('chart.account.income-category');
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
//return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// grab all journals:
|
||||
@@ -381,6 +385,7 @@ class AccountController extends Controller
|
||||
$transactions = $collector->getTransactions();
|
||||
$result = [];
|
||||
$chartData = [];
|
||||
$categoryIds = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$jrnlCatId = (int)$transaction->transaction_journal_category_id;
|
||||
@@ -391,22 +396,23 @@ class AccountController extends Controller
|
||||
$categoryIds[] = $categoryId;
|
||||
if (!isset($result[$combi])) {
|
||||
$result[$combi] = [
|
||||
'total' => '0',
|
||||
'category_id' => $categoryId,
|
||||
'currency' => $currencyName,
|
||||
'total' => '0',
|
||||
'category_id' => $categoryId,
|
||||
'currency' => $currencyName,
|
||||
'currency_symbol' => $transaction->transaction_currency_symbol,
|
||||
];
|
||||
}
|
||||
$result[$combi]['total'] = bcadd($transaction->transaction_amount, $result[$combi]['total']);
|
||||
}
|
||||
|
||||
$names = $this->getCategoryNames(array_keys($result));
|
||||
$names = $this->getCategoryNames($categoryIds);
|
||||
foreach ($result as $row) {
|
||||
$categoryId = $row['category_id'];
|
||||
$name = $names[$categoryId] ?? '(unknown)';
|
||||
$label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency']]);
|
||||
$chartData[$label] = $row['total'];
|
||||
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol']];
|
||||
}
|
||||
$data = $this->generator->pieChart($chartData);
|
||||
$data = $this->generator->multiCurrencyPieChart($chartData);
|
||||
$cache->store($data);
|
||||
|
||||
return response()->json($data);
|
||||
|
||||
@@ -47,6 +47,8 @@ class JobStatusController extends Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// set time limit to zero to prevent timeouts.
|
||||
set_time_limit(0);
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
|
||||
@@ -36,8 +36,10 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* TODO refactor so each auto-complete thing is a function call because lots of code duplication.
|
||||
* Class AutoCompleteController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
|
||||
@@ -49,18 +51,40 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* Returns a JSON list of all accounts.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function allAccounts(AccountRepositoryInterface $repository): JsonResponse
|
||||
public function allAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$return = array_unique(
|
||||
$repository->getAccountsByType(
|
||||
[AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET]
|
||||
)->pluck('name')->toArray()
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-all-accounts');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
$repository->getAccountsByType(
|
||||
[AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET]
|
||||
)->pluck('name')->toArray()
|
||||
)
|
||||
);
|
||||
sort($return);
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
@@ -68,15 +92,86 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* List of all journals.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCollectorInterface $collector
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function allTransactionJournals(TransactionCollectorInterface $collector): JsonResponse
|
||||
public function allTransactionJournals(Request $request, TransactionCollectorInterface $collector): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-all-journals');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$collector->setLimit(250)->setPage(1);
|
||||
$return = array_unique($collector->getTransactions()->pluck('description')->toArray());
|
||||
sort($return);
|
||||
$return = array_values(array_unique($collector->getTransactions()->pluck('description')->toArray()));
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of revenue accounts.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function assetAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-asset-accounts');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$set = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$filtered = $set->filter(
|
||||
function (Account $account) {
|
||||
if (true === $account->active) {
|
||||
return $account;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
);
|
||||
$return = array_values(array_unique($filtered->pluck('name')->toArray()));
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
@@ -84,16 +179,37 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* Returns a JSON list of all bills.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param BillRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function bills(BillRepositoryInterface $repository): JsonResponse
|
||||
public function bills(Request $request, BillRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$return = array_unique(
|
||||
$repository->getActiveBills()->pluck('name')->toArray()
|
||||
);
|
||||
sort($return);
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-bills');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$return = array_unique($repository->getActiveBills()->pluck('name')->toArray());
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
@@ -101,14 +217,37 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* List of budgets.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function budgets(BudgetRepositoryInterface $repository): JsonResponse
|
||||
public function budgets(Request $request, BudgetRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-budgets');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$return = array_unique($repository->getBudgets()->pluck('name')->toArray());
|
||||
sort($return);
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
@@ -116,14 +255,34 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* Returns a list of categories.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function categories(CategoryRepositoryInterface $repository): JsonResponse
|
||||
public function categories(Request $request, CategoryRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-categories');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$return = array_unique($repository->getCategories()->pluck('name')->toArray());
|
||||
sort($return);
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
@@ -131,27 +290,62 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* List of currency names.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param CurrencyRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function currencyNames(CurrencyRepositoryInterface $repository): JsonResponse
|
||||
public function currencyNames(Request $request, CurrencyRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-currency-names');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$return = $repository->get()->pluck('name')->toArray();
|
||||
sort($return);
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON list of all beneficiaries.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function expenseAccounts(AccountRepositoryInterface $repository): JsonResponse
|
||||
public function expenseAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-expense-accounts');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$set = $repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY]);
|
||||
$filtered = $set->filter(
|
||||
function (Account $account) {
|
||||
@@ -166,27 +360,43 @@ class AutoCompleteController extends Controller
|
||||
|
||||
sort($return);
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List of journals with their ID.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCollectorInterface $collector
|
||||
* @param TransactionJournal $except
|
||||
* @param TransactionJournal $except
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function journalsWithId(TransactionCollectorInterface $collector, TransactionJournal $except): JsonResponse
|
||||
public function journalsWithId(Request $request, TransactionCollectorInterface $collector, TransactionJournal $except): JsonResponse
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('recent-journals-id');
|
||||
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-expense-accounts');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get()); // @codeCoverageIgnore
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
|
||||
// find everything:
|
||||
$collector->setLimit(400)->setPage(1);
|
||||
$set = $collector->getTransactions()->pluck('description', 'journal_id')->toArray();
|
||||
$return = [];
|
||||
@@ -200,6 +410,21 @@ class AutoCompleteController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
sort($return);
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (array $array) use ($search) {
|
||||
$value = $array['name'];
|
||||
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
@@ -208,12 +433,23 @@ class AutoCompleteController extends Controller
|
||||
/**
|
||||
* List of revenue accounts.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function revenueAccounts(AccountRepositoryInterface $repository): JsonResponse
|
||||
public function revenueAccounts(Request $request, AccountRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-revenue-accounts');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$set = $repository->getAccountsByType([AccountType::REVENUE]);
|
||||
$filtered = $set->filter(
|
||||
function (Account $account) {
|
||||
@@ -227,34 +463,82 @@ class AutoCompleteController extends Controller
|
||||
$return = array_unique($filtered->pluck('name')->toArray());
|
||||
sort($return);
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON list of all beneficiaries.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TagRepositoryInterface $tagRepository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function tags(TagRepositoryInterface $tagRepository): JsonResponse
|
||||
public function tags(Request $request, TagRepositoryInterface $tagRepository): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-revenue-accounts');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$return = array_unique($tagRepository->get()->pluck('tag')->toArray());
|
||||
sort($return);
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of journals by type.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCollectorInterface $collector
|
||||
* @param string $what
|
||||
* @param string $what
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactionJournals(TransactionCollectorInterface $collector, string $what): JsonResponse
|
||||
public function transactionJournals(Request $request, TransactionCollectorInterface $collector, string $what): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-revenue-accounts');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$type = config('firefly.transactionTypesByWhat.' . $what);
|
||||
$types = [$type];
|
||||
|
||||
@@ -262,21 +546,60 @@ class AutoCompleteController extends Controller
|
||||
$return = array_unique($collector->getTransactions()->pluck('description')->toArray());
|
||||
sort($return);
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* List if transaction types.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactionTypes(JournalRepositoryInterface $repository): JsonResponse
|
||||
public function transactionTypes(Request $request, JournalRepositoryInterface $repository): JsonResponse
|
||||
{
|
||||
$search = (string)$request->get('search');
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('ac-revenue-accounts');
|
||||
// very unlikely a user will actually search for this string.
|
||||
$key = '' === $search ? 'skjf0893j89fj2398hd89dh289h2398hr7isd8900828u209ujnxs88929282u' : $search;
|
||||
$cache->addProperty($key);
|
||||
if ($cache->has()) {
|
||||
return response()->json($cache->get());
|
||||
}
|
||||
// find everything:
|
||||
$return = array_unique($repository->getTransactionTypes()->pluck('type')->toArray());
|
||||
sort($return);
|
||||
|
||||
if ('' !== $search) {
|
||||
$return = array_values(
|
||||
array_unique(
|
||||
array_filter(
|
||||
$return, function (string $value) use ($search) {
|
||||
return !(false === stripos($value, $search));
|
||||
}, ARRAY_FILTER_USE_BOTH
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
return response()->json($return);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ class SelectController extends Controller
|
||||
$limit = (int)config('firefly.test-triggers.limit');
|
||||
$range = (int)config('firefly.test-triggers.range');
|
||||
$matchingTransactions = new Collection;
|
||||
$strict = $request->get('strict') === '1';
|
||||
$strict = '1' === $request->get('strict');
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
$matcher->setLimit($limit);
|
||||
|
||||
@@ -22,6 +22,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Transaction;
|
||||
|
||||
use FireflyIII\Events\UpdatedTransactionJournal;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
@@ -161,9 +162,14 @@ class ConvertController extends Controller
|
||||
$errors = $this->repository->convert($journal, $destinationType, $source, $destination);
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
Log::error('Errors while converting: ', $errors->toArray());
|
||||
return redirect(route('transactions.convert.index', [strtolower($destinationType->type), $journal->id]))->withErrors($errors)->withInput();
|
||||
}
|
||||
|
||||
// Success? Fire rules!
|
||||
event(new UpdatedTransactionJournal($journal));
|
||||
|
||||
|
||||
session()->flash('success', (string)trans('firefly.converted_to_' . $destinationType->type));
|
||||
|
||||
return redirect(route('transactions.show', [$journal->id]));
|
||||
|
||||
@@ -24,7 +24,9 @@ namespace FireflyIII\Http\Controllers\Transaction;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Helpers\Filter\TransactionViewFilter;
|
||||
use FireflyIII\Helpers\Filter\TransferFilter;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\MassDeleteJournalRequest;
|
||||
use FireflyIII\Http\Requests\MassEditJournalRequest;
|
||||
@@ -147,6 +149,9 @@ class MassController extends Controller
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setJournals($journals);
|
||||
$collector->addFilter(TransactionViewFilter::class);
|
||||
$collector->addFilter(TransferFilter::class);
|
||||
|
||||
|
||||
$collection = $collector->getTransactions();
|
||||
$transactions = $collection->map(
|
||||
function (Transaction $transaction) use ($transformer) {
|
||||
|
||||
@@ -68,7 +68,7 @@ class Authenticate
|
||||
*/
|
||||
public function handle($request, Closure $next, ...$guards)
|
||||
{
|
||||
$this->authenticate($guards);
|
||||
$this->authenticate($request, $guards);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ class Authenticate
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
protected function authenticate(array $guards)
|
||||
protected function authenticate($request, array $guards)
|
||||
{
|
||||
|
||||
if (empty($guards)) {
|
||||
|
||||
@@ -33,6 +33,8 @@ use Log;
|
||||
|
||||
/**
|
||||
* Class Installer
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
*/
|
||||
class Installer
|
||||
{
|
||||
@@ -48,6 +50,7 @@ class Installer
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ class IsDemoUser
|
||||
return response()->redirectTo($previous);
|
||||
}
|
||||
|
||||
return response()->redirectTo(route('index'));
|
||||
return response()->redirectTo(route('index')); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
||||
@@ -108,9 +108,11 @@ class Range
|
||||
private function loseItAll(Request $request): void
|
||||
{
|
||||
if ('sqlite' === getenv('DB_CONNECTION') && true === getenv('IS_DOCKER')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$request->session()->flash(
|
||||
'error', 'You seem to be using SQLite in a Docker container. Don\'t do this. If the container restarts all your data will be gone.'
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ class Sandstorm
|
||||
* @param string $email
|
||||
*
|
||||
* @return User
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function createUser(string $email): User
|
||||
{
|
||||
|
||||
@@ -47,7 +47,7 @@ class SecureHeaders
|
||||
$google = '';
|
||||
$analyticsId = env('ANALYTICS_ID', '');
|
||||
if ('' !== $analyticsId) {
|
||||
$google = 'https://www.google-analytics.com/analytics.js';
|
||||
$google = 'www.googletagmanager.com/gtag/js'; // @codeCoverageIgnore
|
||||
}
|
||||
$csp = [
|
||||
"default-src 'none'",
|
||||
@@ -57,7 +57,7 @@ class SecureHeaders
|
||||
"form-action 'self'",
|
||||
"font-src 'self'",
|
||||
"connect-src 'self'",
|
||||
"img-src 'self' data:",
|
||||
"img-src 'self' data: https://api.tiles.mapbox.com",
|
||||
];
|
||||
|
||||
$featurePolicies = [
|
||||
|
||||
@@ -75,6 +75,7 @@ class JournalFormRequest extends Request
|
||||
'piggy_bank_name' => null,
|
||||
'bill_id' => null,
|
||||
'bill_name' => null,
|
||||
'original-source' => sprintf('gui-v%s', config('firefly.version')),
|
||||
|
||||
// transaction data:
|
||||
'transactions' => [
|
||||
@@ -274,7 +275,12 @@ class JournalFormRequest extends Request
|
||||
$selectedCurrency = (int)($data['amount_currency_id_amount'] ?? 0);
|
||||
$accountCurrency = (int)($data['destination_account_currency'] ?? 0);
|
||||
$nativeAmount = (string)($data['native_amount'] ?? '');
|
||||
|
||||
Log::debug('Now in validateDeposit.');
|
||||
Log::debug(sprintf('SelectedCurrency is "%s", accountCurrency is "%s", native amount is "%s".', $selectedCurrency, $accountCurrency, $nativeAmount));
|
||||
|
||||
if ($selectedCurrency !== $accountCurrency && '' === $nativeAmount && 0 !== $selectedCurrency && 0 !== $accountCurrency) {
|
||||
Log::debug('Adding an error about missing native amount.');
|
||||
$validator->errors()->add('native_amount', (string)trans('validation.numeric_native'));
|
||||
|
||||
return;
|
||||
|
||||
@@ -208,8 +208,10 @@ class ReportFormRequest extends Request
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$set = $this->get('tag');
|
||||
$collection = new Collection;
|
||||
Log::debug('Set is:', $set ?? []);
|
||||
if (\is_array($set)) {
|
||||
foreach ($set as $tagTag) {
|
||||
Log::debug(sprintf('Now searching for "%s"', $tagTag));
|
||||
$tag = $repository->findByTag($tagTag);
|
||||
if (null !== $tag) {
|
||||
$collection->push($tag);
|
||||
|
||||
@@ -27,6 +27,7 @@ use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
/**
|
||||
* Class Request.
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
||||
*/
|
||||
@@ -91,58 +92,7 @@ class Request extends FormRequest
|
||||
*/
|
||||
public function string(string $field): string
|
||||
{
|
||||
$string = $this->get($field) ?? '';
|
||||
$search = [
|
||||
"\u{0001}", // start of heading
|
||||
"\u{0002}", // start of text
|
||||
"\u{0003}", // end of text
|
||||
"\u{0004}", // end of transmission
|
||||
"\u{0005}", // enquiry
|
||||
"\u{0006}", // ACK
|
||||
"\u{0007}", // BEL
|
||||
"\u{0008}", // backspace
|
||||
"\u{000E}", // shift out
|
||||
"\u{000F}", // shift in
|
||||
"\u{0010}", // data link escape
|
||||
"\u{0011}", // DC1
|
||||
"\u{0012}", // DC2
|
||||
"\u{0013}", // DC3
|
||||
"\u{0014}", // DC4
|
||||
"\u{0015}", // NAK
|
||||
"\u{0016}", // SYN
|
||||
"\u{0017}", // ETB
|
||||
"\u{0018}", // CAN
|
||||
"\u{0019}", // EM
|
||||
"\u{001A}", // SUB
|
||||
"\u{001B}", // escape
|
||||
"\u{001C}", // file separator
|
||||
"\u{001D}", // group separator
|
||||
"\u{001E}", // record separator
|
||||
"\u{001F}", // unit separator
|
||||
"\u{007F}", // DEL
|
||||
"\u{00A0}", // non-breaking space
|
||||
"\u{1680}", // ogham space mark
|
||||
"\u{180E}", // mongolian vowel separator
|
||||
"\u{2000}", // en quad
|
||||
"\u{2001}", // em quad
|
||||
"\u{2002}", // en space
|
||||
"\u{2003}", // em space
|
||||
"\u{2004}", // three-per-em space
|
||||
"\u{2005}", // four-per-em space
|
||||
"\u{2006}", // six-per-em space
|
||||
"\u{2007}", // figure space
|
||||
"\u{2008}", // punctuation space
|
||||
"\u{2009}", // thin space
|
||||
"\u{200A}", // hair space
|
||||
"\u{200B}", // zero width space
|
||||
"\u{202F}", // narrow no-break space
|
||||
"\u{3000}", // ideographic space
|
||||
"\u{FEFF}", // zero width no -break space
|
||||
];
|
||||
$replace = "\x20"; // plain old normal space
|
||||
$string = str_replace($search, $replace, $string);
|
||||
|
||||
return trim($string);
|
||||
return app('steam')->cleanString((string)($this->get($field) ?? ''));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
/**
|
||||
* Class RuleFormRequest.
|
||||
* Class TestRuleFormRequest.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
|
||||
@@ -91,11 +91,13 @@ class Amount implements ConverterInterface
|
||||
|
||||
return $value;
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
Log::debug(sprintf('Final value is: "%s"', $value));
|
||||
$formatted = sprintf('%01.12f', $value);
|
||||
Log::debug(sprintf('Is formatted to : "%s"', $formatted));
|
||||
|
||||
return $formatted;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
46
app/Import/Converter/AmountNegated.php
Normal file
46
app/Import/Converter/AmountNegated.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* AmountNegated.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Import\Converter;
|
||||
|
||||
/**
|
||||
* Class AmountNegated
|
||||
*/
|
||||
class AmountNegated implements ConverterInterface
|
||||
{
|
||||
/**
|
||||
* Negate amount.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert($value): string
|
||||
{
|
||||
/** @var ConverterInterface $converter */
|
||||
$converter = app(Amount::class);
|
||||
$result = $converter->convert($value);
|
||||
$result = bcmul($result, '-1');
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,12 @@ class AssetAccountIbans implements MapperInterface
|
||||
{
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$set = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$set = $accountRepository->getAccountsByType(
|
||||
[AccountType::DEFAULT, AccountType::ASSET,
|
||||
AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::CREDITCARD, AccountType::MORTGAGE,
|
||||
]
|
||||
);
|
||||
$topList = [];
|
||||
$list = [];
|
||||
|
||||
@@ -49,10 +54,22 @@ class AssetAccountIbans implements MapperInterface
|
||||
$iban = $account->iban ?? '';
|
||||
$accountId = (int)$account->id;
|
||||
if (\strlen($iban) > 0) {
|
||||
$topList[$accountId] = $account->iban . ' (' . $account->name . ')';
|
||||
$name = $account->iban . ' (' . $account->name . ')';
|
||||
|
||||
// is a liability?
|
||||
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
|
||||
$name = $name . ' (' . strtolower(trans('import.import_liability_select')) . ')';
|
||||
}
|
||||
|
||||
$topList[$accountId] = $name;
|
||||
}
|
||||
if ('' === $iban) {
|
||||
$list[$accountId] = $account->name;
|
||||
$name = $account->name;
|
||||
// is a liability?
|
||||
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
|
||||
$name = $name . ' (' . strtolower(trans('import.import_liability_select')) . ')';
|
||||
}
|
||||
$list[$accountId] = $name;
|
||||
}
|
||||
}
|
||||
/** @noinspection AdditionOperationOnArraysInspection */
|
||||
|
||||
@@ -40,7 +40,7 @@ class AssetAccounts implements MapperInterface
|
||||
{
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$set = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$set = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE,]);
|
||||
$list = [];
|
||||
|
||||
/** @var Account $account */
|
||||
@@ -51,6 +51,12 @@ class AssetAccounts implements MapperInterface
|
||||
if (\strlen($iban) > 0) {
|
||||
$name .= ' (' . $iban . ')';
|
||||
}
|
||||
|
||||
// is a liability?
|
||||
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
|
||||
$name = trans('import.import_liability_select') . ': ' . $name;
|
||||
}
|
||||
|
||||
$list[$accountId] = $name;
|
||||
}
|
||||
asort($list);
|
||||
|
||||
@@ -44,7 +44,8 @@ class OpposingAccountIbans implements MapperInterface
|
||||
[
|
||||
AccountType::DEFAULT, AccountType::ASSET,
|
||||
AccountType::EXPENSE, AccountType::BENEFICIARY,
|
||||
AccountType::REVENUE,
|
||||
AccountType::REVENUE, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::CREDITCARD, AccountType::MORTGAGE,
|
||||
]
|
||||
);
|
||||
$topList = [];
|
||||
@@ -55,10 +56,23 @@ class OpposingAccountIbans implements MapperInterface
|
||||
$iban = $account->iban ?? '';
|
||||
$accountId = (int)$account->id;
|
||||
if (\strlen($iban) > 0) {
|
||||
$topList[$accountId] = $account->iban . ' (' . $account->name . ')';
|
||||
$name = $account->iban . ' (' . $account->name . ')';
|
||||
|
||||
// is a liability?
|
||||
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
|
||||
$name = $name . ' (' . strtolower(trans('import.import_liability_select')) . ')';
|
||||
}
|
||||
|
||||
$topList[$accountId] = $name;
|
||||
|
||||
}
|
||||
if ('' === $iban) {
|
||||
$list[$accountId] = $account->name;
|
||||
$name = $account->name;
|
||||
// is a liability?
|
||||
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
|
||||
$name = $name . ' (' . strtolower(trans('import.import_liability_select')) . ')';
|
||||
}
|
||||
$list[$accountId] = $name;
|
||||
}
|
||||
}
|
||||
/** @noinspection AdditionOperationOnArraysInspection */
|
||||
|
||||
@@ -44,7 +44,8 @@ class OpposingAccounts implements MapperInterface
|
||||
[
|
||||
AccountType::DEFAULT, AccountType::ASSET,
|
||||
AccountType::EXPENSE, AccountType::BENEFICIARY,
|
||||
AccountType::REVENUE,
|
||||
AccountType::REVENUE, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::CREDITCARD, AccountType::MORTGAGE,
|
||||
]
|
||||
);
|
||||
$list = [];
|
||||
@@ -57,6 +58,10 @@ class OpposingAccounts implements MapperInterface
|
||||
if (\strlen($iban) > 0) {
|
||||
$name .= ' (' . $iban . ')';
|
||||
}
|
||||
// is a liability?
|
||||
if (\in_array($account->accountType->type, [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], true)) {
|
||||
$name = trans('import.import_liability_select') . ': ' . $name;
|
||||
}
|
||||
$list[$accountId] = $name;
|
||||
}
|
||||
asort($list);
|
||||
|
||||
@@ -123,23 +123,6 @@ class YnabRoutine implements RoutineInterface
|
||||
return;
|
||||
}
|
||||
|
||||
// if ('match_accounts' === $this->importJob->stage) {
|
||||
// // $this->repository->setStatus($this->importJob, 'running');
|
||||
// /** @var StageGetBudgetsHandler $handler */
|
||||
// $handler = app(StageGetBudgetsHandler::class);
|
||||
// $handler->setImportJob($this->importJob);
|
||||
// $handler->run();
|
||||
// $this->repository->setStage($this->importJob, 'get_transactions');
|
||||
// }
|
||||
//
|
||||
// if ('get_transactions' === $this->importJob->stage) {
|
||||
// // $this->repository->setStatus($this->importJob, 'running');
|
||||
// /** @var StageGetBudgetsHandler $handler */
|
||||
// $handler = app(StageGetBudgetsHandler::class);
|
||||
// $handler->setImportJob($this->importJob);
|
||||
// $handler->run();
|
||||
// $this->repository->setStage($this->importJob, 'get_transactions');
|
||||
// }
|
||||
throw new FireflyException(sprintf('YNAB import routine cannot handle stage "%s"', $this->importJob->stage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ class ImportArrayStorage
|
||||
*/
|
||||
private function getHash(array $transaction): string
|
||||
{
|
||||
unset($transaction['importHashV2']);
|
||||
unset($transaction['importHashV2'], $transaction['original-source']);
|
||||
$json = json_encode($transaction);
|
||||
if (false === $json) {
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
|
||||
@@ -238,7 +238,7 @@ class CreateRecurringTransactions implements ShouldQueue
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$single = [
|
||||
'currency_id' => $transaction->transaction_currency_id,
|
||||
'currency_id' => (int)$transaction->transaction_currency_id,
|
||||
'currency_code' => null,
|
||||
'description' => null,
|
||||
'amount' => $transaction->amount,
|
||||
|
||||
@@ -39,6 +39,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
* @property string $amount
|
||||
* @property int $budget_id
|
||||
* @property string spent
|
||||
* @property int $transaction_currency_id
|
||||
*/
|
||||
class BudgetLimit extends Model
|
||||
{
|
||||
@@ -89,4 +90,13 @@ class BudgetLimit extends Model
|
||||
{
|
||||
return $this->belongsTo(Budget::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function transactionCurrency(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TransactionCurrency::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ namespace FireflyIII\Repositories\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@@ -68,18 +70,28 @@ class AccountTasker implements AccountTaskerInterface
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
|
||||
/** @var CurrencyRepositoryInterface $currencyRepository */
|
||||
$currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
|
||||
|
||||
$return = [
|
||||
'currencies' => [],
|
||||
'start' => '0',
|
||||
'end' => '0',
|
||||
'difference' => '0',
|
||||
'accounts' => [],
|
||||
];
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$id = $account->id;
|
||||
$entry = [
|
||||
$id = $account->id;
|
||||
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
|
||||
$currency = $currencyRepository->findNull($currencyId);
|
||||
$return['currencies'][] = $currencyId;
|
||||
$entry = [
|
||||
'name' => $account->name,
|
||||
'id' => $account->id,
|
||||
'currency' => $currency ?? $defaultCurrency,
|
||||
'start_balance' => '0',
|
||||
'end_balance' => '0',
|
||||
];
|
||||
@@ -100,7 +112,7 @@ class AccountTasker implements AccountTaskerInterface
|
||||
|
||||
$return['accounts'][$id] = $entry;
|
||||
}
|
||||
|
||||
$return['currencies'] = count(array_unique($return['currencies']));
|
||||
$return['difference'] = bcsub($return['end'], $return['start']);
|
||||
|
||||
return $return;
|
||||
@@ -206,29 +218,51 @@ class AccountTasker implements AccountTaskerInterface
|
||||
*/
|
||||
private function groupByOpposing(Collection $transactions): array
|
||||
{
|
||||
$expenses = [];
|
||||
// join the result together:
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
|
||||
/** @var CurrencyRepositoryInterface $currencyRepos */
|
||||
$currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
$currencies = [$defaultCurrency->id => $defaultCurrency,];
|
||||
$expenses = [];
|
||||
$countAccounts = []; // if count remains 0 use original name, not the name with the currency.
|
||||
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$opposingId = $transaction->opposing_account_id;
|
||||
$name = $transaction->opposing_account_name;
|
||||
if (!isset($expenses[$opposingId])) {
|
||||
$expenses[$opposingId] = [
|
||||
'id' => $opposingId,
|
||||
'name' => $name,
|
||||
'sum' => '0',
|
||||
'average' => '0',
|
||||
'count' => 0,
|
||||
$opposingId = (int)$transaction->opposing_account_id;
|
||||
$currencyId = (int)$transaction->transaction_currency_id;
|
||||
$key = sprintf('%s-%s', $opposingId, $currencyId);
|
||||
$name = sprintf('%s (%s)', $transaction->opposing_account_name, $transaction->transaction_currency_code);
|
||||
$countAccounts[$opposingId] = isset($countAccounts[$opposingId]) ? $countAccounts[$opposingId] + 1 : 1;
|
||||
if (!isset($expenses[$key])) {
|
||||
$currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepos->findNull($currencyId);
|
||||
$expenses[$key] = [
|
||||
'id' => $opposingId,
|
||||
'name' => $name,
|
||||
'original' => $transaction->opposing_account_name,
|
||||
'sum' => '0',
|
||||
'average' => '0',
|
||||
'currencies' => [],
|
||||
'single_currency' => $currencies[$currencyId],
|
||||
'count' => 0,
|
||||
];
|
||||
}
|
||||
$expenses[$opposingId]['sum'] = bcadd($expenses[$opposingId]['sum'], $transaction->transaction_amount);
|
||||
++$expenses[$opposingId]['count'];
|
||||
$expenses[$key]['currencies'][] = (int)$transaction->transaction_currency_id;
|
||||
$expenses[$key]['sum'] = bcadd($expenses[$key]['sum'], $transaction->transaction_amount);
|
||||
++$expenses[$key]['count'];
|
||||
}
|
||||
// do averages:
|
||||
$keys = array_keys($expenses);
|
||||
foreach ($keys as $key) {
|
||||
$opposingId = $expenses[$key]['id'];
|
||||
if(1===$countAccounts[$opposingId]) {
|
||||
$expenses[$key]['name'] = $expenses[$key]['original'];
|
||||
}
|
||||
|
||||
if ($expenses[$key]['count'] > 1) {
|
||||
$expenses[$key]['average'] = bcdiv($expenses[$key]['sum'], (string)$expenses[$key]['count']);
|
||||
}
|
||||
$expenses[$key]['currencies'] = \count(array_unique($expenses[$key]['currencies']));
|
||||
$expenses[$key]['all_currencies'] = \count($currencies);
|
||||
}
|
||||
|
||||
return $expenses;
|
||||
|
||||
@@ -148,7 +148,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
public function getBillsForAccounts(Collection $accounts): Collection
|
||||
{
|
||||
$fields = ['bills.id', 'bills.created_at', 'bills.updated_at', 'bills.deleted_at', 'bills.user_id', 'bills.name', 'bills.match', 'bills.amount_min',
|
||||
'bills.amount_max', 'bills.date', 'bills.repeat_freq', 'bills.skip', 'bills.automatch', 'bills.active', 'bills.name_encrypted',
|
||||
'bills.amount_max', 'bills.date','bills.transaction_currency_id', 'bills.repeat_freq', 'bills.skip', 'bills.automatch', 'bills.active', 'bills.name_encrypted',
|
||||
'bills.match_encrypted',];
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
$set = $this->user->bills()
|
||||
|
||||
@@ -315,6 +315,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
$set = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->with(['budget'])
|
||||
->where('budgets.user_id', $this->user->id)
|
||||
->whereNull('budgets.deleted_at')
|
||||
->get(['budget_limits.*']);
|
||||
|
||||
return $set;
|
||||
@@ -323,6 +324,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
if (null === $start xor null === $end) {
|
||||
$query = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->with(['budget'])
|
||||
->whereNull('budgets.deleted_at')
|
||||
->where('budgets.user_id', $this->user->id);
|
||||
if (null !== $end) {
|
||||
// end date must be before $end.
|
||||
@@ -340,6 +342,7 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
$set = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||
->with(['budget'])
|
||||
->where('budgets.user_id', $this->user->id)
|
||||
->whereNull('budgets.deleted_at')
|
||||
->where(
|
||||
function (Builder $q5) use ($start, $end) {
|
||||
$q5->where(
|
||||
|
||||
@@ -83,14 +83,37 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
* @return string
|
||||
*/
|
||||
public function earnedInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string
|
||||
{
|
||||
$set = $this->earnedInPeriodCollection($categories, $accounts, $start, $end);
|
||||
|
||||
return (string)$set->sum('transaction_amount');
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function earnedInPeriodCollection(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($this->user);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($accounts)->setCategories($categories);
|
||||
$set = $collector->getTransactions();
|
||||
if (0 !== $accounts->count()) {
|
||||
$collector->setAccounts($accounts);
|
||||
}
|
||||
|
||||
return (string)$set->sum('transaction_amount');
|
||||
if (0 === $accounts->count()) {
|
||||
$collector->setAllAssetAccounts();
|
||||
}
|
||||
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setCategories($categories);
|
||||
|
||||
return $collector->getTransactions();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,6 +205,8 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $set;
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param Collection $accounts
|
||||
@@ -212,7 +237,6 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $lastJournalDate;
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
@@ -258,6 +282,8 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
@@ -296,7 +322,6 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
@@ -383,6 +408,8 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
@@ -401,6 +428,23 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
* @return string
|
||||
*/
|
||||
public function spentInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string
|
||||
{
|
||||
$set = $this->spentInPeriodCollection($categories, $accounts, $start, $end);
|
||||
|
||||
|
||||
return (string)$set->sum('transaction_amount');
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function spentInPeriodCollection(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
@@ -414,13 +458,9 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
$collector->setAllAssetAccounts();
|
||||
}
|
||||
|
||||
$set = $collector->getTransactions();
|
||||
|
||||
return (string)$set->sum('transaction_amount');
|
||||
return $collector->getTransactions();
|
||||
}
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
|
||||
/**
|
||||
* A very cryptic method name that means:
|
||||
*
|
||||
|
||||
@@ -51,6 +51,17 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function earnedInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string;
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function earnedInPeriodCollection(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): Collection;
|
||||
|
||||
/**
|
||||
* Find a category.
|
||||
*
|
||||
@@ -158,6 +169,17 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function spentInPeriod(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): string;
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function spentInPeriodCollection(Collection $categories, Collection $accounts, Carbon $start, Carbon $end): Collection;
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
|
||||
/**
|
||||
|
||||
@@ -342,6 +342,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface
|
||||
* @param UploadedFile $file
|
||||
*
|
||||
* @return MessageBag
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function storeFileUpload(ImportJob $job, string $name, UploadedFile $file): MessageBag
|
||||
{
|
||||
@@ -374,6 +375,12 @@ class ImportJobRepository implements ImportJobRepositoryInterface
|
||||
$attachment->save();
|
||||
$fileObject = $file->openFile('r');
|
||||
$fileObject->rewind();
|
||||
|
||||
|
||||
if(0 === $file->getSize()) {
|
||||
throw new FireflyException('Cannot upload empty or non-existent file.');
|
||||
}
|
||||
|
||||
$content = $fileObject->fread($file->getSize());
|
||||
$encrypted = Crypt::encrypt($content);
|
||||
$this->uploadDisk->put($attachment->fileName(), $encrypted);
|
||||
|
||||
@@ -64,8 +64,10 @@ class FixerIOv2 implements ExchangeRateInterface
|
||||
$exchangeRate->user()->associate($this->user);
|
||||
$exchangeRate->fromCurrency()->associate($fromCurrency);
|
||||
$exchangeRate->toCurrency()->associate($toCurrency);
|
||||
$exchangeRate->date = $date;
|
||||
$exchangeRate->rate = $rate;
|
||||
$exchangeRate->date = $date;
|
||||
$exchangeRate->rate = $rate;
|
||||
$exchangeRate->updated_at = new Carbon;
|
||||
$exchangeRate->created_at = new Carbon;
|
||||
|
||||
// get API key
|
||||
$apiKey = env('FIXER_API_KEY', '');
|
||||
|
||||
@@ -34,6 +34,16 @@ use RuntimeException;
|
||||
*/
|
||||
class IpifyOrg implements IPRetrievalInterface
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's IP address.
|
||||
*
|
||||
|
||||
@@ -37,6 +37,16 @@ use Log;
|
||||
*/
|
||||
class AccountDestroyService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Account|null $moveTo
|
||||
|
||||
@@ -33,6 +33,16 @@ use Log;
|
||||
*/
|
||||
class BillDestroyService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,16 @@ use Log;
|
||||
*/
|
||||
class CategoryDestroyService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,16 @@ use Log;
|
||||
*/
|
||||
class CurrencyDestroyService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,16 @@ use Log;
|
||||
*/
|
||||
class JournalDestroyService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,16 @@ use Log;
|
||||
*/
|
||||
class RecurrenceDestroyService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recurrence.
|
||||
*
|
||||
|
||||
@@ -33,6 +33,16 @@ use Log;
|
||||
*/
|
||||
class EncryptService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $file
|
||||
* @param string $key
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Internal\Support;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Factory\BillFactory;
|
||||
use FireflyIII\Factory\TagFactory;
|
||||
use FireflyIII\Factory\TransactionJournalMetaFactory;
|
||||
@@ -128,7 +129,11 @@ trait JournalServiceTrait
|
||||
}
|
||||
$note = $journal->notes()->first();
|
||||
if (null !== $note) {
|
||||
$note->delete();
|
||||
try {
|
||||
$note->delete();
|
||||
} catch (Exception $e) {
|
||||
Log::debug(sprintf('Journal service trait could not delete note: %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace FireflyIII\Services\Internal\Update;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Services\Internal\Support\AccountServiceTrait;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class AccountUpdateService
|
||||
@@ -32,7 +33,15 @@ use FireflyIII\Services\Internal\Support\AccountServiceTrait;
|
||||
class AccountUpdateService
|
||||
{
|
||||
use AccountServiceTrait;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update account data.
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace FireflyIII\Services\Internal\Update;
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Services\Internal\Support\BillServiceTrait;
|
||||
|
||||
use Log;
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* Class BillUpdateService
|
||||
@@ -34,6 +34,16 @@ class BillUpdateService
|
||||
{
|
||||
use BillServiceTrait;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param array $data
|
||||
|
||||
@@ -24,13 +24,23 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Services\Internal\Update;
|
||||
|
||||
use FireflyIII\Models\Category;
|
||||
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class CategoryUpdateService
|
||||
*/
|
||||
class CategoryUpdateService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param array $data
|
||||
|
||||
@@ -24,12 +24,22 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Services\Internal\Update;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
|
||||
use Log;
|
||||
/**
|
||||
* Class CurrencyUpdateService
|
||||
*/
|
||||
class CurrencyUpdateService
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
* @param array $data
|
||||
|
||||
@@ -30,7 +30,6 @@ use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Services\Internal\Support\JournalServiceTrait;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class to centralise code that updates a journal given the input by system.
|
||||
*
|
||||
@@ -39,6 +38,16 @@ use Log;
|
||||
class JournalUpdateService
|
||||
{
|
||||
use JournalServiceTrait;
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace FireflyIII\Services\Internal\Update;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Services\Internal\Support\TransactionServiceTrait;
|
||||
use FireflyIII\User;
|
||||
|
||||
use Log;
|
||||
/**
|
||||
* Class TransactionUpdateService
|
||||
*/
|
||||
@@ -34,6 +34,16 @@ class TransactionUpdateService
|
||||
{
|
||||
use TransactionServiceTrait;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
|
||||
@@ -33,6 +33,16 @@ use RuntimeException;
|
||||
*/
|
||||
class PwndVerifierV2 implements Verifier
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === env('APP_ENV')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the given password against (some) service.
|
||||
*
|
||||
|
||||
@@ -50,16 +50,19 @@ class GetBudgetsRequest extends YnabRequest
|
||||
Log::debug(sprintf('URI is %s', $uri));
|
||||
|
||||
$result = $this->authenticatedGetRequest($uri, []);
|
||||
//Log::debug('Raw GetBudgetsRequest result', $result);
|
||||
Log::debug('Raw GetBudgetsRequest result', $result);
|
||||
|
||||
// expect data in [data][budgets]
|
||||
$rawBudgets = $result['data']['budgets'] ?? [];
|
||||
$freshBudgets = [];
|
||||
foreach ($rawBudgets as $rawBudget) {
|
||||
Log::debug(sprintf('Raw content of budget is: %s', json_encode($rawBudget)));
|
||||
Log::debug(sprintf('Content of currency format is: %s', json_encode($rawBudget['currency_format'] ?? [])));
|
||||
Log::debug(sprintf('ISO code is: %s', $rawBudget['currency_format']['iso_code'] ?? '(none)'));
|
||||
$freshBudgets[] = [
|
||||
'id' => $rawBudget['id'],
|
||||
'name' => $rawBudget['name'],
|
||||
'currency_code' => $rawBudget['currency_format']['iso_code'],
|
||||
'currency_code' => $rawBudget['currency_format']['iso_code'] ?? null,
|
||||
];
|
||||
}
|
||||
$this->budgets = $freshBudgets;
|
||||
|
||||
@@ -74,6 +74,7 @@ abstract class YnabRequest
|
||||
}
|
||||
try {
|
||||
$content = trim($res->getBody()->getContents());
|
||||
Log::debug(sprintf('Raw body is: %s', $content));
|
||||
} catch (RuntimeException $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user