mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-30 01:27:40 +00:00
Compare commits
78 Commits
develop-20
...
develop-20
Author | SHA1 | Date | |
---|---|---|---|
|
b93cfc5de2 | ||
|
d41f5b1090 | ||
|
40322813c9 | ||
|
4a98927e32 | ||
|
193e529803 | ||
|
fbf20ef2c2 | ||
|
54de829c8a | ||
|
131b987561 | ||
|
dce6754c62 | ||
|
f4bca90080 | ||
|
b2960b1ed9 | ||
|
33f87bce23 | ||
|
23aa45609b | ||
|
b098952f82 | ||
|
68c3e14b0c | ||
|
19d08137a5 | ||
|
73776e7869 | ||
|
bf04ca12c1 | ||
|
a4637debe9 | ||
|
48c1b525be | ||
|
56470bfbba | ||
|
0f732ca874 | ||
|
e452ba938d | ||
|
9921c5a925 | ||
|
58fab75681 | ||
|
54990308f6 | ||
|
f95758ff47 | ||
|
8d830e178f | ||
|
334a521ca1 | ||
|
12629a1955 | ||
|
2e3669a32f | ||
|
ea337607c4 | ||
|
f7f317a3b2 | ||
|
adbf6defe5 | ||
|
e0709f2975 | ||
|
30007b05cb | ||
|
13fc7f0d8d | ||
|
7c85138115 | ||
|
2c25f65f7f | ||
|
7eaba962e8 | ||
|
7c38393cde | ||
|
153fd2ae74 | ||
|
c0204c810c | ||
|
944c107e26 | ||
|
18e05c06fd | ||
|
fb79dbf17c | ||
|
31a8163c61 | ||
|
8bcd729250 | ||
|
80c4e69528 | ||
|
7f6d8fdb87 | ||
|
c8e301326e | ||
|
4820ef6580 | ||
|
4cb775cf4b | ||
|
c371662c51 | ||
|
ffaa164aa5 | ||
|
344bfbe059 | ||
|
6c38b87ec5 | ||
|
dfcd5d79be | ||
|
07631eea28 | ||
|
26c4fe36cc | ||
|
90fc4b44f2 | ||
|
f755dd2d48 | ||
|
d2647f96e7 | ||
|
9f94ec067a | ||
|
a795755618 | ||
|
8457a1c881 | ||
|
fc9429bf3e | ||
|
b6e8b66035 | ||
|
7504b21c3e | ||
|
b7dad8166d | ||
|
2da1b43c37 | ||
|
a606315884 | ||
|
295feedd77 | ||
|
d3b2748c8f | ||
|
1b4655fd70 | ||
|
05f67ef584 | ||
|
04ab7ba07d | ||
|
5806323970 |
48
.ci/php-cs-fixer/composer.lock
generated
48
.ci/php-cs-fixer/composer.lock
generated
@@ -406,16 +406,16 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.68.5",
|
||||
"version": "v3.69.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "7bedb718b633355272428c60736dc97fb96daf27"
|
||||
"reference": "13b0c0eede38c11cd674b080f2b485d0f14ffa9f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7bedb718b633355272428c60736dc97fb96daf27",
|
||||
"reference": "7bedb718b633355272428c60736dc97fb96daf27",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/13b0c0eede38c11cd674b080f2b485d0f14ffa9f",
|
||||
"reference": "13b0c0eede38c11cd674b080f2b485d0f14ffa9f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -432,7 +432,7 @@
|
||||
"react/promise": "^2.0 || ^3.0",
|
||||
"react/socket": "^1.0",
|
||||
"react/stream": "^1.0",
|
||||
"sebastian/diff": "^4.0 || ^5.1 || ^6.0",
|
||||
"sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0",
|
||||
"symfony/console": "^5.4 || ^6.4 || ^7.0",
|
||||
"symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0",
|
||||
"symfony/filesystem": "^5.4 || ^6.4 || ^7.0",
|
||||
@@ -445,18 +445,18 @@
|
||||
"symfony/stopwatch": "^5.4 || ^6.4 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.4",
|
||||
"infection/infection": "^0.29.8",
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.5",
|
||||
"infection/infection": "^0.29.10",
|
||||
"justinrainbow/json-schema": "^5.3 || ^6.0",
|
||||
"keradus/cli-executor": "^2.1",
|
||||
"mikey179/vfsstream": "^1.6.12",
|
||||
"php-coveralls/php-coveralls": "^2.7",
|
||||
"php-cs-fixer/accessible-object": "^1.1",
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5",
|
||||
"phpunit/phpunit": "^9.6.22 || ^10.5.40 || ^11.5.2",
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.15 || ^7.2.0",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.2.0"
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
|
||||
"phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.7",
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.0",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "For handling output formats in XML",
|
||||
@@ -497,7 +497,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.68.5"
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.69.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -505,7 +505,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-30T17:00:50+00:00"
|
||||
"time": "2025-02-18T23:57:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -1188,29 +1188,29 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "6.0.2",
|
||||
"version": "7.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "b4ccd857127db5d41a5b676f24b51371d76d8544"
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544",
|
||||
"reference": "b4ccd857127db5d41a5b676f24b51371d76d8544",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2"
|
||||
"php": ">=8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.0",
|
||||
"symfony/process": "^4.2 || ^5"
|
||||
"phpunit/phpunit": "^12.0",
|
||||
"symfony/process": "^7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "6.0-dev"
|
||||
"dev-main": "7.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1243,7 +1243,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"security": "https://github.com/sebastianbergmann/diff/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/6.0.2"
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/7.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1251,7 +1251,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-03T04:53:05+00:00"
|
||||
"time": "2025-02-07T04:55:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
|
@@ -19,7 +19,7 @@ SITE_OWNER=mail@example.com
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
# Firefly III will launch using this language (for new users and unauthenticated visitors)
|
||||
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang
|
||||
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/blob/main/config/firefly.php#L123
|
||||
#
|
||||
# If text is still in English, remember that not everything may have been translated.
|
||||
DEFAULT_LANGUAGE=en_US
|
||||
|
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@@ -204,9 +204,9 @@ jobs:
|
||||
|
||||
# zip and tar everything
|
||||
echo 'Zip and tar...'
|
||||
zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*"
|
||||
zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*" "*Procfile*" "*crowdin.yml*" "*sonar-project.properties*"
|
||||
touch $tarName
|
||||
tar --exclude=$tarName --exclude=$zipName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' -czf $tarName .
|
||||
tar --exclude=$tarName --exclude=$zipName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' --exclude='./Procfile' --exclude='../crowdin.yml' --exclude='./sonar-project.properties' -czf $tarName .
|
||||
|
||||
# add sha256 sum
|
||||
echo 'Sha sum ...'
|
||||
@@ -225,7 +225,7 @@ jobs:
|
||||
sudo chown -R runner:docker output.txt
|
||||
echo "Weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d %H:%M')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
@@ -240,7 +240,7 @@ jobs:
|
||||
sudo chown -R runner:docker output.txt
|
||||
echo "Irregular BRANCH release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d %H:%M')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
@@ -268,7 +268,7 @@ jobs:
|
||||
sudo chown -R runner:docker output.txt
|
||||
echo "Very early ALPHA release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d %H:%M')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo '### Instructions' >> output.txt
|
||||
echo '' >> output.txt
|
||||
@@ -286,7 +286,7 @@ jobs:
|
||||
sudo chown -R runner:docker output.txt
|
||||
echo "Very early BETA release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d %H:%M')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo '### Instructions' >> output.txt
|
||||
echo '' >> output.txt
|
||||
|
9
.gitignore
vendored
9
.gitignore
vendored
@@ -14,7 +14,16 @@ public/build
|
||||
# ignore v1 build files
|
||||
resources/assets/v1/node_modules
|
||||
resources/assets/v1/build
|
||||
public/v1/js/app.js*
|
||||
public/v1/js/app_vue.js*
|
||||
public/v1/js/create*
|
||||
public/v1/js/edit*
|
||||
public/v1/js/profile*
|
||||
public/v1/js/administrations
|
||||
public/v1/js/exchange-rates
|
||||
public/v1/js/webhooks
|
||||
|
||||
# ignore v2 build files
|
||||
resources/assets/v2/node_modules
|
||||
resources/assets/v2/build
|
||||
public/v2/i18n
|
||||
|
@@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
|
||||
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
|
||||
|
||||
## 2025
|
||||
- Jose Diaz-Gonzalez
|
||||
- SoftBrix
|
||||
|
||||
## 2024
|
||||
|
@@ -93,6 +93,7 @@ class AccountController extends Controller
|
||||
$currency = $this->repository->getAccountCurrency($account) ?? $this->nativeCurrency;
|
||||
$useCurrency = $currency;
|
||||
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
|
||||
// this one is correct.
|
||||
Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$balance = Steam::finalAccountBalance($account, $date);
|
||||
$key = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? 'native_balance' : 'balance';
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
@@ -140,18 +141,18 @@ class ListController extends Controller
|
||||
*/
|
||||
public function transactions(Request $request, Account $account): JsonResponse
|
||||
{
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = $this->getManager();
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setUser($admin)->setAccounts(new Collection([$account]))
|
||||
->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types)
|
||||
;
|
||||
@@ -163,15 +164,19 @@ class ListController extends Controller
|
||||
$collector->setEnd($this->parameters->get('end'));
|
||||
}
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.accounts.transactions', [$account->id]).$this->buildParams());
|
||||
$groups = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($groups, $transformer, 'transactions');
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
@@ -29,7 +29,9 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@@ -88,9 +90,17 @@ class ShowController extends Controller
|
||||
$count = $collection->count();
|
||||
|
||||
// continue sort:
|
||||
|
||||
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setConvertToNative($this->convertToNative);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$accounts = $enrichment->enrich($accounts);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.accounts.index').$this->buildParams());
|
||||
@@ -118,6 +128,16 @@ class ShowController extends Controller
|
||||
$account->refresh();
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setConvertToNative($this->convertToNative);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$account = $enrichment->enrichSingle($account);
|
||||
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -27,7 +27,9 @@ namespace FireflyIII\Api\V1\Controllers\Models\Account;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Account\StoreRequest;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -69,6 +71,15 @@ class StoreController extends Controller
|
||||
$account = $this->repository->store($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setConvertToNative($this->convertToNative);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$account = $enrichment->enrichSingle($account);
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Account\UpdateRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -73,6 +75,15 @@ class UpdateController extends Controller
|
||||
$account->refresh();
|
||||
app('preferences')->mark();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setConvertToNative($this->convertToNative);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$account = $enrichment->enrichSingle($account);
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
@@ -176,7 +177,11 @@ class ListController extends Controller
|
||||
// get paginator.
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.bills.transactions', [$bill->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -32,6 +32,7 @@ use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
@@ -172,7 +173,11 @@ class ListController extends Controller
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
@@ -232,7 +237,11 @@ class ListController extends Controller
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.budgets.without-budget').$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -84,7 +85,11 @@ class ListController extends Controller
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.budgets.limits.transactions', [$budget->id, $budgetLimit->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
@@ -139,7 +140,11 @@ class ListController extends Controller
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.categories.transactions', [$category->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -28,9 +28,11 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
@@ -75,17 +77,26 @@ class ListController extends Controller
|
||||
|
||||
$collection = $piggyBank->accounts;
|
||||
$count = $collection->count();
|
||||
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setConvertToNative($this->convertToNative);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$accounts = $enrichment->enrich($accounts);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($events, $transformer, 'accounts');
|
||||
$resource = new FractalCollection($accounts, $transformer, 'accounts');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -110,7 +111,11 @@ class ListController extends Controller
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Models\Rule\TestRequest;
|
||||
use FireflyIII\Api\V1\Requests\Models\Rule\TriggerRequest;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
@@ -94,6 +95,11 @@ class TriggerController extends Controller
|
||||
$transactions = $ruleEngine->find();
|
||||
$count = $transactions->count();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($rule->user);
|
||||
$transactions = $enrichment->enrich($transactions);
|
||||
|
||||
$paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rules.test', [$rule->id]).$this->buildParams());
|
||||
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Api\V1\Requests\Models\RuleGroup\TriggerRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
@@ -100,6 +101,11 @@ class TriggerController extends Controller
|
||||
$transactions = $ruleEngine->find();
|
||||
$count = $transactions->count();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($group->user);
|
||||
$transactions = $enrichment->enrich($transactions);
|
||||
|
||||
$paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rule-groups.test', [$group->id]).$this->buildParams());
|
||||
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
@@ -141,7 +142,12 @@ class ListController extends Controller
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.tags.transactions', [$tag->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -85,7 +86,11 @@ class ShowController extends Controller
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
@@ -137,6 +142,11 @@ class ShowController extends Controller
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -34,6 +34,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Rules\IsDuplicateTransaction;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -89,6 +90,7 @@ class StoreController extends Controller
|
||||
$data['user'] = auth()->user();
|
||||
$data['user_group'] = $this->userGroup;
|
||||
|
||||
|
||||
Log::channel('audit')->info('Store new transaction over API.', $data);
|
||||
|
||||
try {
|
||||
@@ -133,6 +135,11 @@ class StoreController extends Controller
|
||||
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
|
||||
}
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -99,6 +100,11 @@ class UpdateController extends Controller
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -42,6 +42,8 @@ use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
@@ -100,6 +102,15 @@ class ListController extends Controller
|
||||
$count = $collection->count();
|
||||
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setConvertToNative($this->convertToNative);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$accounts = $enrichment->enrich($accounts);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]).$this->buildParams());
|
||||
@@ -360,7 +371,11 @@ class ListController extends Controller
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -109,7 +110,11 @@ class ListController extends Controller
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -26,8 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Search;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Support\Search\AccountSearch;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
@@ -81,6 +83,15 @@ class AccountController extends Controller
|
||||
|
||||
$accounts = $search->search();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setConvertToNative($this->convertToNative);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$accounts = $enrichment->enrich($accounts);
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Search;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Support\Search\SearchInterface;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -57,7 +58,11 @@ class TransactionController extends Controller
|
||||
$parameters = ['search' => $fullQuery];
|
||||
$url = route('api.v1.search.transactions').'?'.http_build_query($parameters);
|
||||
$groups->setPath($url);
|
||||
$transactions = $groups->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser(auth()->user());
|
||||
$transactions = $enrichment->enrich($groups->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -102,7 +102,7 @@ class BasicController extends Controller
|
||||
$balanceData = $this->getBalanceInformation($start, $end);
|
||||
$billData = $this->getBillInformation($start, $end);
|
||||
$spentData = $this->getLeftToSpendInfo($start, $end);
|
||||
$netWorthData = $this->getNetWorthInfo($start, $end);
|
||||
$netWorthData = $this->getNetWorthInfo($end);
|
||||
// $balanceData = [];
|
||||
// $billData = [];
|
||||
// $spentData = [];
|
||||
@@ -319,18 +319,13 @@ class BasicController extends Controller
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function getNetWorthInfo(Carbon $start, Carbon $end): array
|
||||
private function getNetWorthInfo(Carbon $end): array
|
||||
{
|
||||
Log::debug('getNetWorthInfo');
|
||||
$end->endOfDay();
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$date = now(config('app.timezone'));
|
||||
// start and end in the future? use $end
|
||||
if ($this->notInDateRange($date, $start, $end)) {
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
}
|
||||
Log::debug(sprintf('getNetWorthInfo up until "%s".', $end->format('Y-m-d H:i:s')));
|
||||
|
||||
/** @var NetWorthInterface $netWorthHelper */
|
||||
$netWorthHelper = app(NetWorthInterface::class);
|
||||
@@ -346,7 +341,7 @@ class BasicController extends Controller
|
||||
}
|
||||
);
|
||||
|
||||
$netWorthSet = $netWorthHelper->byAccounts($filtered, $date);
|
||||
$netWorthSet = $netWorthHelper->byAccounts($filtered, $end);
|
||||
$return = [];
|
||||
foreach ($netWorthSet as $key => $data) {
|
||||
if ('native' === $key) {
|
||||
@@ -370,6 +365,22 @@ class BasicController extends Controller
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
if (0 === count($return)) {
|
||||
$return[] = [
|
||||
'key' => sprintf('net-worth-in-%s', $this->nativeCurrency->code),
|
||||
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $this->nativeCurrency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $this->nativeCurrency->id,
|
||||
'currency_code' => $this->nativeCurrency->code,
|
||||
'currency_symbol' => $this->nativeCurrency->symbol,
|
||||
'currency_decimal_places' => $this->nativeCurrency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatFlat($this->nativeCurrency->symbol, $this->nativeCurrency->decimal_places, '0', false),
|
||||
'local_icon' => 'line-chart',
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Log::debug('End of getNetWorthInfo');
|
||||
|
||||
return $return;
|
||||
|
@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\System;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Transformers\UserTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
/**
|
||||
@@ -48,7 +49,7 @@ class AboutController extends Controller
|
||||
$replace = ['\~', '# '];
|
||||
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
||||
$phpOs = str_replace($search, $replace, PHP_OS);
|
||||
$currentDriver = \DB::getDriverName();
|
||||
$currentDriver = DB::getDriverName();
|
||||
$data
|
||||
= [
|
||||
'version' => config('firefly.version'),
|
||||
|
@@ -65,25 +65,6 @@ class StoreRequest extends FormRequest
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function parseAccounts(mixed $array): array
|
||||
{
|
||||
if (!is_array($array)) {
|
||||
return [];
|
||||
}
|
||||
$return = [];
|
||||
foreach ($array as $entry) {
|
||||
if (!is_array($entry)) {
|
||||
continue;
|
||||
}
|
||||
$return[] = [
|
||||
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
|
||||
'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*/
|
||||
|
@@ -25,8 +25,8 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
|
||||
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Rules\IsAssetAccountId;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
|
||||
use FireflyIII\Rules\LessThanPiggyTarget;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
@@ -45,20 +45,23 @@ class UpdateRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$fields = [
|
||||
'name' => ['name', 'convertString'],
|
||||
'account_id' => ['account_id', 'convertInteger'],
|
||||
'targetamount' => ['target_amount', 'convertString'],
|
||||
'current_amount' => ['current_amount', 'convertString'],
|
||||
'startdate' => ['start_date', 'convertDateTime'],
|
||||
'targetdate' => ['target_date', 'convertDateTime'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
'order' => ['order', 'convertInteger'],
|
||||
'object_group_title' => ['object_group_title', 'convertString'],
|
||||
'object_group_id' => ['object_group_id', 'convertInteger'],
|
||||
$fields = [
|
||||
'name' => ['name', 'convertString'],
|
||||
'target_amount' => ['target_amount', 'convertString'],
|
||||
'start_date' => ['start_date', 'convertDateTime'],
|
||||
'target_date' => ['target_date', 'convertDateTime'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
'order' => ['order', 'convertInteger'],
|
||||
'object_group_title' => ['object_group_title', 'convertString'],
|
||||
'object_group_id' => ['object_group_id', 'convertInteger'],
|
||||
'transaction_currency_code' => ['transaction_currency_code', 'convertString'],
|
||||
'transaction_currency_id' => ['transaction_currency_id', 'convertInteger'],
|
||||
];
|
||||
|
||||
return $this->getAllData($fields);
|
||||
$result = $this->getAllData($fields);
|
||||
$result['accounts'] = $this->parseAccounts($this->get('accounts'));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,13 +73,20 @@ class UpdateRequest extends FormRequest
|
||||
$piggyBank = $this->route()->parameter('piggyBank');
|
||||
|
||||
return [
|
||||
'name' => 'min:1|max:255|uniquePiggyBankForUser:'.$piggyBank->id,
|
||||
'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()],
|
||||
'target_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
'account_id' => ['belongsToUser:accounts', new IsAssetAccountId()],
|
||||
'name' => 'min:1|max:255|uniquePiggyBankForUser:'.$piggyBank->id,
|
||||
'current_amount' => ['nullable', new LessThanPiggyTarget(), new IsValidPositiveAmount()],
|
||||
'target_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
'accounts' => 'required',
|
||||
'accounts.*' => 'array|required',
|
||||
'accounts.*.account_id' => ['required', 'numeric', 'belongsToUser:accounts,id'],
|
||||
'accounts.*.current_amount' => ['numeric', new IsValidZeroOrMoreAmount()],
|
||||
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
|
||||
'object_group_title' => ['min:1', 'max:255'],
|
||||
'transaction_currency_id' => 'exists:transaction_currencies,id|nullable',
|
||||
'transaction_currency_code' => 'exists:transaction_currencies,code|nullable',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -65,7 +65,7 @@ class TestRequest extends FormRequest
|
||||
|
||||
private function getAccounts(): array
|
||||
{
|
||||
return $this->get('accounts');
|
||||
return $this->get('accounts') ?? [];
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
|
@@ -59,7 +59,7 @@ class TestRequest extends FormRequest
|
||||
|
||||
private function getAccounts(): array
|
||||
{
|
||||
return $this->get('accounts');
|
||||
return $this->get('accounts') ?? [];
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
|
@@ -73,6 +73,7 @@ class StoreController extends Controller
|
||||
$userGroup = $request->getUserGroup();
|
||||
$data['user_group'] = $userGroup;
|
||||
|
||||
|
||||
// overrule user group and see where we end up.
|
||||
// what happens when we refer to a budget that is not in this user group?
|
||||
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Handlers\Events\UpdatedGroupEventHandler;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CorrectsGroupAccounts extends Command
|
||||
{
|
||||
@@ -45,7 +46,7 @@ class CorrectsGroupAccounts extends Command
|
||||
{
|
||||
$groups = [];
|
||||
$res = TransactionJournal::groupBy('transaction_group_id')
|
||||
->get(['transaction_group_id', \DB::raw('COUNT(transaction_group_id) as the_count')])// @phpstan-ignore-line
|
||||
->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')])// @phpstan-ignore-line
|
||||
;
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
|
@@ -33,6 +33,7 @@ use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
@@ -89,6 +90,7 @@ class CorrectsGroupInformation extends Command
|
||||
Category::class,
|
||||
ObjectGroup::class,
|
||||
CurrencyExchangeRate::class,
|
||||
Preference::class,
|
||||
Recurrence::class,
|
||||
RuleGroup::class,
|
||||
Rule::class,
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Support\Models\AccountBalanceCalculator;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CorrectsUnevenAmount extends Command
|
||||
@@ -118,10 +119,10 @@ class CorrectsUnevenAmount extends Command
|
||||
|
||||
private function fixUnevenAmounts(): void
|
||||
{
|
||||
$journals = \DB::table('transactions')
|
||||
$journals = DB::table('transactions')
|
||||
->groupBy('transaction_journal_id')
|
||||
->whereNull('deleted_at')
|
||||
->get(['transaction_journal_id', \DB::raw('SUM(amount) AS the_sum')]) // @phpstan-ignore-line
|
||||
->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]) // @phpstan-ignore-line
|
||||
;
|
||||
|
||||
/** @var \stdClass $entry */
|
||||
@@ -262,7 +263,7 @@ class CorrectsUnevenAmount extends Command
|
||||
private function matchCurrencies(): void
|
||||
{
|
||||
$journals = TransactionJournal::leftJoin('transactions', 'transaction_journals.id', 'transactions.transaction_journal_id')
|
||||
->where('transactions.transaction_currency_id', '!=', \DB::raw('transaction_journals.transaction_currency_id'))
|
||||
->where('transactions.transaction_currency_id', '!=', DB::raw('transaction_journals.transaction_currency_id'))
|
||||
->get(['transaction_journals.*'])
|
||||
;
|
||||
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class RemovesEmptyJournals extends Command
|
||||
{
|
||||
@@ -56,7 +57,7 @@ class RemovesEmptyJournals extends Command
|
||||
{
|
||||
$set = Transaction::whereNull('deleted_at')
|
||||
->groupBy('transactions.transaction_journal_id')
|
||||
->get([\DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']) // @phpstan-ignore-line
|
||||
->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']) // @phpstan-ignore-line
|
||||
;
|
||||
$total = 0;
|
||||
|
||||
|
@@ -106,7 +106,7 @@ class ExportsData extends Command
|
||||
$exporter->setExportTags($options['export']['tags']);
|
||||
$exporter->setExportRecurring($options['export']['recurring']);
|
||||
$exporter->setExportRules($options['export']['rules']);
|
||||
$exporter->setExportBills($options['export']['subscriptions']);
|
||||
$exporter->setExportBills($options['export']['bills']);
|
||||
$exporter->setExportPiggies($options['export']['piggies']);
|
||||
$data = $exporter->export();
|
||||
if (0 === count($data)) {
|
||||
|
@@ -31,6 +31,7 @@ use FireflyIII\Support\Cronjobs\AutoBudgetCronjob;
|
||||
use FireflyIII\Support\Cronjobs\BillWarningCronjob;
|
||||
use FireflyIII\Support\Cronjobs\ExchangeRatesCronjob;
|
||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||
use FireflyIII\Support\Cronjobs\UpdateCheckCronjob;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -43,6 +44,7 @@ class Cron extends Command
|
||||
protected $signature = 'firefly-iii:cron
|
||||
{--F|force : Force the cron job(s) to execute.}
|
||||
{--date= : Set the date in YYYY-MM-DD to make Firefly III think that\'s the current date.}
|
||||
{--check-version : Check if there is a new Firefly III version. Other tasks will be skipped unless also requested.}
|
||||
{--download-cer : Download exchange rates. Other tasks will be skipped unless also requested.}
|
||||
{--create-recurring : Create recurring transactions. Other tasks will be skipped unless also requested.}
|
||||
{--create-auto-budgets : Create auto budgets. Other tasks will be skipped unless also requested.}
|
||||
@@ -51,7 +53,11 @@ class Cron extends Command
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$doAll = !$this->option('download-cer') && !$this->option('create-recurring') && !$this->option('create-auto-budgets') && !$this->option('send-bill-warnings');
|
||||
$doAll = !$this->option('download-cer')
|
||||
&& !$this->option('create-recurring')
|
||||
&& !$this->option('create-auto-budgets')
|
||||
&& !$this->option('send-bill-warnings')
|
||||
&& !$this->option('check-version');
|
||||
$date = null;
|
||||
|
||||
try {
|
||||
@@ -72,6 +78,17 @@ class Cron extends Command
|
||||
}
|
||||
}
|
||||
|
||||
// check for new version
|
||||
if ($doAll || $this->option('check-version')) {
|
||||
try {
|
||||
$this->checkForUpdates($force);
|
||||
} catch (FireflyException $e) {
|
||||
app('log')->error($e->getMessage());
|
||||
app('log')->error($e->getTraceAsString());
|
||||
$this->friendlyError($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Fire recurring transaction cron job.
|
||||
if ($doAll || $this->option('create-recurring')) {
|
||||
try {
|
||||
@@ -204,4 +221,21 @@ class Cron extends Command
|
||||
$this->friendlyPositive(sprintf('"Send bill warnings" cron ran with success: %s', $autoBudget->message));
|
||||
}
|
||||
}
|
||||
|
||||
private function checkForUpdates(bool $force): void
|
||||
{
|
||||
$updateCheck = new UpdateCheckCronjob();
|
||||
$updateCheck->setForce($force);
|
||||
$updateCheck->fire();
|
||||
|
||||
if ($updateCheck->jobErrored) {
|
||||
$this->friendlyError(sprintf('Error in "update check" cron: %s', $updateCheck->message));
|
||||
}
|
||||
if ($updateCheck->jobFired) {
|
||||
$this->friendlyInfo(sprintf('"Update check" cron fired: %s', $updateCheck->message));
|
||||
}
|
||||
if ($updateCheck->jobSucceeded) {
|
||||
$this->friendlyPositive(sprintf('"Update check" cron ran with success: %s', $updateCheck->message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Preference;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class RemovesDatabaseDecryption extends Command
|
||||
{
|
||||
@@ -101,7 +102,7 @@ class RemovesDatabaseDecryption extends Command
|
||||
|
||||
private function decryptField(string $table, string $field): void
|
||||
{
|
||||
$rows = \DB::table($table)->get(['id', $field]);
|
||||
$rows = DB::table($table)->get(['id', $field]);
|
||||
|
||||
/** @var \stdClass $row */
|
||||
foreach ($rows as $row) {
|
||||
@@ -135,7 +136,7 @@ class RemovesDatabaseDecryption extends Command
|
||||
}
|
||||
|
||||
if ($value !== $original) {
|
||||
\DB::table($table)->where('id', $id)->update([$field => $value]);
|
||||
DB::table($table)->where('id', $id)->update([$field => $value]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands\Upgrade;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class RepairsPostgresSequences extends Command
|
||||
{
|
||||
@@ -40,7 +41,7 @@ class RepairsPostgresSequences extends Command
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
if ('pgsql' !== \DB::connection()->getName()) {
|
||||
if ('pgsql' !== DB::connection()->getName()) {
|
||||
return 0;
|
||||
}
|
||||
$this->friendlyLine('Going to verify PostgreSQL table sequences.');
|
||||
@@ -49,8 +50,8 @@ class RepairsPostgresSequences extends Command
|
||||
foreach ($tablesToCheck as $tableToCheck) {
|
||||
$this->friendlyLine(sprintf('Checking the next id sequence for table "%s".', $tableToCheck));
|
||||
|
||||
$highestId = \DB::table($tableToCheck)->select(\DB::raw('MAX(id)'))->first();
|
||||
$nextId = \DB::table($tableToCheck)->select(\DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))->first();
|
||||
$highestId = DB::table($tableToCheck)->select(DB::raw('MAX(id)'))->first();
|
||||
$nextId = DB::table($tableToCheck)->select(DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))->first();
|
||||
if (null === $nextId) {
|
||||
$this->friendlyInfo(sprintf('nextval is NULL for table "%s", go to next table.', $tableToCheck));
|
||||
|
||||
@@ -58,9 +59,9 @@ class RepairsPostgresSequences extends Command
|
||||
}
|
||||
|
||||
if ($nextId->nextval < $highestId->max) { // @phpstan-ignore-line
|
||||
\DB::select(sprintf('SELECT setval(\'%s_id_seq\', %d)', $tableToCheck, $highestId->max));
|
||||
$highestId = \DB::table($tableToCheck)->select(\DB::raw('MAX(id)'))->first();
|
||||
$nextId = \DB::table($tableToCheck)->select(\DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))->first();
|
||||
DB::select(sprintf('SELECT setval(\'%s_id_seq\', %d)', $tableToCheck, $highestId->max));
|
||||
$highestId = DB::table($tableToCheck)->select(DB::raw('MAX(id)'))->first();
|
||||
$nextId = DB::table($tableToCheck)->select(DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))->first();
|
||||
if ($nextId->nextval > $highestId->max) { // @phpstan-ignore-line
|
||||
$this->friendlyInfo(sprintf('Table "%s" autoincrement corrected.', $tableToCheck));
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class UpgradesJournalMetaData extends Command
|
||||
{
|
||||
@@ -86,8 +87,8 @@ class UpgradesJournalMetaData extends Command
|
||||
$this->migrateCategories();
|
||||
|
||||
// empty tables
|
||||
\DB::table('budget_transaction')->delete();
|
||||
\DB::table('category_transaction')->delete();
|
||||
DB::table('budget_transaction')->delete();
|
||||
DB::table('category_transaction')->delete();
|
||||
}
|
||||
|
||||
private function migrateBudgets(): void
|
||||
@@ -108,12 +109,12 @@ class UpgradesJournalMetaData extends Command
|
||||
|
||||
private function getIdsForBudgets(): array
|
||||
{
|
||||
$transactions = \DB::table('budget_transaction')->distinct()->pluck('transaction_id')->toArray();
|
||||
$transactions = DB::table('budget_transaction')->distinct()->pluck('transaction_id')->toArray();
|
||||
$array = [];
|
||||
$chunks = array_chunk($transactions, 500);
|
||||
|
||||
foreach ($chunks as $chunk) {
|
||||
$set = \DB::table('transactions')->whereIn('transactions.id', $chunk)->pluck('transaction_journal_id')->toArray();
|
||||
$set = DB::table('transactions')->whereIn('transactions.id', $chunk)->pluck('transaction_journal_id')->toArray();
|
||||
$array = array_merge($array, $set);
|
||||
}
|
||||
|
||||
@@ -171,12 +172,12 @@ class UpgradesJournalMetaData extends Command
|
||||
|
||||
private function getIdsForCategories(): array
|
||||
{
|
||||
$transactions = \DB::table('category_transaction')->distinct()->pluck('transaction_id')->toArray();
|
||||
$transactions = DB::table('category_transaction')->distinct()->pluck('transaction_id')->toArray();
|
||||
$array = [];
|
||||
$chunks = array_chunk($transactions, 500);
|
||||
|
||||
foreach ($chunks as $chunk) {
|
||||
$set = \DB::table('transactions')
|
||||
$set = DB::table('transactions')
|
||||
->whereIn('transactions.id', $chunk)
|
||||
->pluck('transaction_journal_id')->toArray()
|
||||
;
|
||||
|
@@ -35,6 +35,7 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class UpgradesToGroups extends Command
|
||||
{
|
||||
@@ -237,7 +238,8 @@ class UpgradesToGroups extends Command
|
||||
return [
|
||||
'type' => strtolower($journal->transactionType->type),
|
||||
'date' => $journal->date,
|
||||
'user' => $journal->user_id,
|
||||
'user' => $journal->user,
|
||||
'user_group' => $journal->user->userGroup,
|
||||
'currency_id' => $transaction->transaction_currency_id,
|
||||
'foreign_currency_id' => $transaction->foreign_currency_id,
|
||||
'amount' => $transaction->amount,
|
||||
@@ -364,7 +366,7 @@ class UpgradesToGroups extends Command
|
||||
|
||||
private function giveGroup(array $array): void
|
||||
{
|
||||
$groupId = \DB::table('transaction_groups')->insertGetId(
|
||||
$groupId = DB::table('transaction_groups')->insertGetId(
|
||||
[
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
@@ -372,7 +374,7 @@ class UpgradesToGroups extends Command
|
||||
'user_id' => $array['user_id'],
|
||||
]
|
||||
);
|
||||
\DB::table('transaction_journals')->where('id', $array['id'])->update(['transaction_group_id' => $groupId]);
|
||||
DB::table('transaction_journals')->where('id', $array['id'])->update(['transaction_group_id' => $groupId]);
|
||||
++$this->count;
|
||||
}
|
||||
|
||||
|
@@ -76,7 +76,7 @@ class TagFactory
|
||||
$longitude = 0.0 === (float) $data['longitude'] ? null : (float) $data['longitude']; // intentional float
|
||||
$array = [
|
||||
'user_id' => $this->user->id,
|
||||
'user_group_id' => $this->user->user_group_id,
|
||||
'user_group_id' => $this->userGroup->id,
|
||||
'tag' => trim($data['tag']),
|
||||
'tagMode' => 'nothing',
|
||||
'date' => $data['date'],
|
||||
|
@@ -79,7 +79,7 @@ class TransactionGroupFactory
|
||||
|
||||
$group = new TransactionGroup();
|
||||
$group->user()->associate($this->user);
|
||||
$group->userGroup()->associate($data['user_group']);
|
||||
$group->userGroup()->associate($this->userGroup);
|
||||
$group->title = $title;
|
||||
$group->save();
|
||||
|
||||
@@ -93,7 +93,8 @@ class TransactionGroupFactory
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->user = $user;
|
||||
$this->userGroup = $user->userGroup;
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
|
@@ -136,6 +136,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
;
|
||||
$journals = $collector->getExtractedJournals();
|
||||
$journals = array_reverse($journals, true);
|
||||
// this call is correct.
|
||||
Log::debug(sprintf('getAuditReport: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$dayBeforeBalance = Steam::finalAccountBalance($account, $date);
|
||||
$startBalance = $dayBeforeBalance['balance'];
|
||||
@@ -171,6 +172,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
$journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date');
|
||||
}
|
||||
$locale = app('steam')->getLocale();
|
||||
// call is correct.
|
||||
Log::debug(sprintf('getAuditReport end: Call finalAccountBalance with date/time "%s"', $this->end->toIso8601String()));
|
||||
|
||||
return [
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Update\UpdateTrait;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class VersionCheckEventHandler
|
||||
@@ -45,13 +46,13 @@ class VersionCheckEventHandler
|
||||
*/
|
||||
public function checkForUpdates(RequestedVersionCheckStatus $event): void
|
||||
{
|
||||
app('log')->debug('Now in checkForUpdates()');
|
||||
Log::debug('Now in checkForUpdates()');
|
||||
|
||||
// should not check for updates:
|
||||
$permission = app('fireflyconfig')->get('permission_update_check', -1);
|
||||
$value = (int) $permission->data;
|
||||
if (1 !== $value) {
|
||||
app('log')->debug('Update check is not enabled.');
|
||||
Log::debug('Update check is not enabled.');
|
||||
$this->warnToCheckForUpdates($event);
|
||||
|
||||
return;
|
||||
@@ -61,7 +62,7 @@ class VersionCheckEventHandler
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
$user = $event->user;
|
||||
if (!$repository->hasRole($user, 'owner')) {
|
||||
app('log')->debug('User is not admin, done.');
|
||||
Log::debug('User is not admin, done.');
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -70,14 +71,14 @@ class VersionCheckEventHandler
|
||||
$lastCheckTime = app('fireflyconfig')->get('last_update_check', time());
|
||||
$now = time();
|
||||
$diff = $now - $lastCheckTime->data;
|
||||
app('log')->debug(sprintf('Last check time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff));
|
||||
Log::debug(sprintf('Last check time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff));
|
||||
if ($diff < 604800) {
|
||||
app('log')->debug(sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data)));
|
||||
Log::debug(sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data)));
|
||||
|
||||
return;
|
||||
}
|
||||
// last check time was more than a week ago.
|
||||
app('log')->debug('Have not checked for a new version in a week!');
|
||||
Log::debug('Have not checked for a new version in a week!');
|
||||
$release = $this->getLatestRelease();
|
||||
|
||||
session()->flash($release['level'], $release['message']);
|
||||
@@ -93,7 +94,7 @@ class VersionCheckEventHandler
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
$user = $event->user;
|
||||
if (!$repository->hasRole($user, 'owner')) {
|
||||
app('log')->debug('User is not admin, done.');
|
||||
Log::debug('User is not admin, done.');
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -102,14 +103,14 @@ class VersionCheckEventHandler
|
||||
$lastCheckTime = app('fireflyconfig')->get('last_update_warning', time());
|
||||
$now = time();
|
||||
$diff = $now - $lastCheckTime->data;
|
||||
app('log')->debug(sprintf('Last warning time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff));
|
||||
Log::debug(sprintf('Last warning time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff));
|
||||
if ($diff < 604800 * 4) {
|
||||
app('log')->debug(sprintf('Warned about updates less than four weeks ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data)));
|
||||
Log::debug(sprintf('Warned about updates less than four weeks ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data)));
|
||||
|
||||
return;
|
||||
}
|
||||
// last check time was more than a week ago.
|
||||
app('log')->debug('Have warned about a new version in four weeks!');
|
||||
Log::debug('Have warned about a new version in four weeks!');
|
||||
|
||||
session()->flash('info', (string) trans('firefly.disabled_but_check'));
|
||||
app('fireflyconfig')->set('last_update_warning', time());
|
||||
|
@@ -26,11 +26,14 @@ namespace FireflyIII\Handlers\Observer;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
@@ -72,24 +75,31 @@ class AccountObserver
|
||||
*/
|
||||
public function deleting(Account $account): void
|
||||
{
|
||||
// app('log')->debug('Observe "deleting" of an account.');
|
||||
$account->accountMeta()->delete();
|
||||
app('log')->debug('Observe "deleting" of an account.');
|
||||
|
||||
$repository = app(AttachmentRepositoryInterface::class);
|
||||
$repository->setUser($account->user);
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($account->piggyBanks()->get() as $piggy) {
|
||||
$piggy->accounts()->detach($account);
|
||||
}
|
||||
DB::table('account_piggy_bank')->where('account_id', $account->id)->delete();
|
||||
|
||||
/** @var Attachment $attachment */
|
||||
foreach ($account->attachments()->get() as $attachment) {
|
||||
$repository->destroy($attachment);
|
||||
}
|
||||
foreach ($account->transactions()->get() as $transaction) {
|
||||
$transaction->delete();
|
||||
|
||||
$journalIds = Transaction::where('account_id', $account->id)->get(['transactions.transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
|
||||
$groupIds = TransactionJournal::whereIn('id', $journalIds)->get(['transaction_journals.transaction_group_id'])->pluck('transaction_group_id')->toArray();
|
||||
if (count($journalIds) > 0) {
|
||||
Transaction::whereIn('transaction_journal_id', $journalIds)->delete();
|
||||
TransactionJournal::whereIn('id', $journalIds)->delete();
|
||||
}
|
||||
if (count($groupIds) > 0) {
|
||||
TransactionGroup::whereIn('id', $groupIds)->delete();
|
||||
}
|
||||
|
||||
Log::debug(sprintf('Delete %d journal(s)', count($journalIds)));
|
||||
Log::debug(sprintf('Delete %d group(s)', count($groupIds)));
|
||||
|
||||
$account->notes()->delete();
|
||||
$account->locations()->delete();
|
||||
}
|
||||
|
@@ -115,6 +115,7 @@ class ReconcileController extends Controller
|
||||
|
||||
$startDate = clone $start;
|
||||
$startDate->subDay()->endOfDay(); // this is correct, subday endofday ends at 23:59:59
|
||||
// both are validated and are correct.
|
||||
Log::debug(sprintf('reconcile: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String()));
|
||||
Log::debug(sprintf('reconcile2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
$startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places);
|
||||
@@ -224,11 +225,13 @@ class ReconcileController extends Controller
|
||||
]
|
||||
);
|
||||
$submission = [
|
||||
'user' => auth()->user()->id,
|
||||
'group_title' => null,
|
||||
'transactions' => [
|
||||
'user' => auth()->user(),
|
||||
'user_group' => auth()->user()->userGroup,
|
||||
'group_title' => null,
|
||||
'transactions' => [
|
||||
[
|
||||
'user' => auth()->user()->id,
|
||||
'user' => auth()->user(),
|
||||
'user_group' => auth()->user()->userGroup,
|
||||
'type' => strtolower(TransactionTypeEnum::RECONCILIATION->value),
|
||||
'date' => $end,
|
||||
'order' => 0,
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Controllers\PeriodOverview;
|
||||
@@ -80,6 +81,7 @@ class ShowController extends Controller
|
||||
* */
|
||||
public function show(Request $request, Account $account, ?Carbon $start = null, ?Carbon $end = null)
|
||||
{
|
||||
|
||||
$objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type));
|
||||
|
||||
if (!$this->isEditableAccount($account)) {
|
||||
@@ -121,12 +123,7 @@ class ShowController extends Controller
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setAccounts(new Collection([$account]))
|
||||
->setLimit($pageSize)
|
||||
->setPage($page)->withAccountInformation()->withCategoryInformation()
|
||||
->setRange($start, $end)
|
||||
;
|
||||
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation()->setRange($start, $end);
|
||||
|
||||
// this search will not include transaction groups where this asset account (or liability)
|
||||
// is just part of ONE of the journals. To force this:
|
||||
@@ -136,8 +133,14 @@ class ShowController extends Controller
|
||||
|
||||
$groups->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||
$showAll = false;
|
||||
Log::debug(sprintf('show: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
$balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $end), $account, $this->convertToNative, $accountCurrency);
|
||||
// correct
|
||||
$now = today()->endOfDay();
|
||||
if ($now->gt($end) || $now->lt($start)) {
|
||||
$now = $end;
|
||||
}
|
||||
|
||||
Log::debug(sprintf('show: Call finalAccountBalance with date/time "%s"', $now->toIso8601String()));
|
||||
$balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $now), $account, $this->convertToNative, $accountCurrency);
|
||||
|
||||
return view(
|
||||
'accounts.show',
|
||||
@@ -202,6 +205,7 @@ class ShowController extends Controller
|
||||
$groups->setPath(route('accounts.show.all', [$account->id]));
|
||||
$chartUrl = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]);
|
||||
$showAll = true;
|
||||
// correct
|
||||
Log::debug(sprintf('showAll: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
$balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $end), $account, $this->convertToNative, $accountCurrency);
|
||||
|
||||
|
@@ -41,6 +41,7 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
@@ -223,7 +224,7 @@ class LoginController extends Controller
|
||||
{
|
||||
Log::channel('audit')->info('Show login form (1.1).');
|
||||
|
||||
$count = \DB::table('users')->count();
|
||||
$count = DB::table('users')->count();
|
||||
$guard = config('auth.defaults.guard');
|
||||
$title = (string) trans('firefly.login_page_title');
|
||||
|
||||
|
@@ -424,8 +424,8 @@ class AccountController extends Controller
|
||||
{
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
// TODO not sure if these date ranges will work as expected.
|
||||
Log::debug(sprintf('Now in period("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
$chartData = [];
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty('chart.account.period');
|
||||
$cache->addProperty($start);
|
||||
@@ -454,7 +454,6 @@ class AccountController extends Controller
|
||||
$range = Steam::filterAccountBalances($range, $account, $this->convertToNative, $accountCurrency);
|
||||
|
||||
// temp, get end balance.
|
||||
Log::debug('temp get end balance');
|
||||
Log::debug(sprintf('period: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
Steam::finalAccountBalance($account, $end);
|
||||
Log::debug('END temp get end balance done');
|
||||
@@ -508,7 +507,7 @@ class AccountController extends Controller
|
||||
$chartData = [];
|
||||
|
||||
foreach ($return as $key => $info) {
|
||||
if (3 === strlen($key)) {
|
||||
if ('balance' !== $key && 'native_balance' !== $key) {
|
||||
// assume it's a currency:
|
||||
$setCurrency = $this->currencyRepository->findByCode($key);
|
||||
$info['currency_symbol'] = $setCurrency->symbol;
|
||||
|
@@ -42,6 +42,7 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\View\View;
|
||||
@@ -268,8 +269,8 @@ class DebugController extends Controller
|
||||
{
|
||||
$maxFileSize = Steam::phpBytes((string) ini_get('upload_max_filesize'));
|
||||
$maxPostSize = Steam::phpBytes((string) ini_get('post_max_size'));
|
||||
$drivers = \DB::availableDrivers();
|
||||
$currentDriver = \DB::getDriverName();
|
||||
$drivers = DB::availableDrivers();
|
||||
$currentDriver = DB::getDriverName();
|
||||
|
||||
return [
|
||||
'db_version' => app('fireflyconfig')->get('db_version', 1)->data,
|
||||
|
@@ -195,6 +195,7 @@ class ReconcileController extends Controller
|
||||
$startDate->subDay();
|
||||
|
||||
$currency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency;
|
||||
// correct
|
||||
Log::debug(sprintf('transactions: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String()));
|
||||
Log::debug(sprintf('transactions2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String()));
|
||||
$startBalance = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places);
|
||||
|
@@ -31,6 +31,7 @@ use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
@@ -81,25 +82,25 @@ class IndexController extends Controller
|
||||
{
|
||||
$this->cleanupObjectGroups();
|
||||
$this->piggyRepos->resetOrder();
|
||||
$collection = $this->piggyRepos->getPiggyBanks();
|
||||
$collection = $this->piggyRepos->getPiggyBanks();
|
||||
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
$end = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
|
||||
// transform piggies using the transformer:
|
||||
$parameters = new ParameterBag();
|
||||
$parameters->set('end', $end);
|
||||
// $parameters = new ParameterBag();
|
||||
// $parameters->set('end', $end);
|
||||
|
||||
|
||||
/** @var AccountTransformer $accountTransformer */
|
||||
$accountTransformer = app(AccountTransformer::class);
|
||||
$accountTransformer->setParameters($parameters);
|
||||
// /** @var AccountTransformer $accountTransformer */
|
||||
// $accountTransformer = app(AccountTransformer::class);
|
||||
// $accountTransformer->setParameters($parameters);
|
||||
|
||||
// data
|
||||
$piggyBanks = $this->groupPiggyBanks($collection);
|
||||
$accounts = $this->collectAccounts($collection);
|
||||
$accounts = $this->mergeAccountsAndPiggies($piggyBanks, $accounts);
|
||||
$piggyBanks = $this->makeSums($piggyBanks);
|
||||
$piggyBanks = $this->groupPiggyBanks($collection);
|
||||
$accounts = $this->collectAccounts($collection);
|
||||
$accounts = $this->mergeAccountsAndPiggies($piggyBanks, $accounts);
|
||||
$piggyBanks = $this->makeSums($piggyBanks);
|
||||
|
||||
ksort($piggyBanks);
|
||||
|
||||
@@ -144,6 +145,11 @@ class IndexController extends Controller
|
||||
$accountTransformer = app(AccountTransformer::class);
|
||||
$accountTransformer->setParameters($parameters);
|
||||
|
||||
// enrich each account.
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser(auth()->user());
|
||||
$enrichment->setConvertToNative($this->convertToNative);
|
||||
$enrichment->setNative($this->defaultCurrency);
|
||||
$return = [];
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
@@ -152,6 +158,7 @@ class IndexController extends Controller
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$account = $enrichment->enrichSingle($account);
|
||||
$array = $accountTransformer->transform($account);
|
||||
$accountId = (int) $array['id'];
|
||||
if (!array_key_exists($accountId, $return)) {
|
||||
|
@@ -42,6 +42,7 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\View\View;
|
||||
use Laravel\Passport\ClientRepository;
|
||||
|
||||
@@ -139,7 +140,7 @@ class ProfileController extends Controller
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$isInternalAuth = $this->internalAuth;
|
||||
$count = \DB::table('oauth_clients')->where('personal_access_client', true)->whereNull('user_id')->count();
|
||||
$count = DB::table('oauth_clients')->where('personal_access_client', true)->whereNull('user_id')->count();
|
||||
$subTitle = $user->email;
|
||||
$userId = $user->id;
|
||||
$enabled2FA = null !== $user->mfa_secret;
|
||||
|
@@ -103,7 +103,7 @@ class ShowController extends Controller
|
||||
|
||||
foreach (array_keys($groupArray['transactions']) as $index) {
|
||||
$groupArray['transactions'][$index]['tags'] = $this->repository->getTagObjects(
|
||||
$groupArray['transactions'][$index]['transaction_journal_id']
|
||||
(int) $groupArray['transactions'][$index]['transaction_journal_id']
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\System\OAuthKeys;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
@@ -83,7 +84,7 @@ class Installer
|
||||
// Log::debug('Now in routine hasNoTables()');
|
||||
|
||||
try {
|
||||
\DB::table('users')->count();
|
||||
DB::table('users')->count();
|
||||
} catch (QueryException $e) {
|
||||
$message = $e->getMessage();
|
||||
Log::error(sprintf('Error message trying to access users-table: %s', $message));
|
||||
|
@@ -380,9 +380,10 @@ class CreateRecurringTransactions implements ShouldQueue
|
||||
}
|
||||
|
||||
$array = [
|
||||
'user' => $recurrence->user_id,
|
||||
'group_title' => $groupTitle,
|
||||
'transactions' => $this->getTransactionData($recurrence, $repetition, $date),
|
||||
'user' => $recurrence->user,
|
||||
'user_group' => $recurrence->user->userGroup,
|
||||
'group_title' => $groupTitle,
|
||||
'transactions' => $this->getTransactionData($recurrence, $repetition, $date),
|
||||
];
|
||||
|
||||
/** @var TransactionGroup $group */
|
||||
@@ -421,7 +422,8 @@ class CreateRecurringTransactions implements ShouldQueue
|
||||
$single = [
|
||||
'type' => null === $transaction?->transactionType?->type ? strtolower($recurrence->transactionType->type) : strtolower($transaction->transactionType->type), // @phpstan-ignore-line
|
||||
'date' => $date,
|
||||
'user' => $recurrence->user_id,
|
||||
'user' => $recurrence->user,
|
||||
'user_group' => $recurrence->user->userGroup,
|
||||
'currency_id' => $transaction->transaction_currency_id,
|
||||
'currency_code' => null,
|
||||
'description' => $transaction->description,
|
||||
|
@@ -48,14 +48,15 @@ class Account extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'user_id' => 'integer',
|
||||
'deleted_at' => 'datetime',
|
||||
'active' => 'boolean',
|
||||
'encrypted' => 'boolean',
|
||||
'virtual_balance' => 'string',
|
||||
'native_virtual_balance' => 'string',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
'deleted_at' => 'datetime',
|
||||
'active' => 'boolean',
|
||||
'encrypted' => 'boolean',
|
||||
'virtual_balance' => 'string',
|
||||
'native_virtual_balance' => 'string',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'user_group_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban', 'native_virtual_balance'];
|
||||
|
@@ -42,13 +42,15 @@ class Attachment extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'uploaded' => 'boolean',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'uploaded' => 'boolean',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'md5', 'filename', 'mime', 'title', 'description', 'size', 'uploaded'];
|
||||
protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'user_group_id', 'md5', 'filename', 'mime', 'title', 'description', 'size', 'uploaded'];
|
||||
|
||||
/**
|
||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||
|
@@ -41,14 +41,16 @@ class AvailableBudget extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
'transaction_currency_id' => 'int',
|
||||
'amount' => 'string',
|
||||
'native_amount' => 'string',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
'transaction_currency_id' => 'int',
|
||||
'amount' => 'string',
|
||||
'native_amount' => 'string',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'user_group_id', 'transaction_currency_id', 'amount', 'start_date', 'end_date', 'start_date_tz', 'end_date_tz', 'native_amount'];
|
||||
|
@@ -43,14 +43,16 @@ class Budget extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'active' => 'boolean',
|
||||
'encrypted' => 'boolean',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'active' => 'boolean',
|
||||
'encrypted' => 'boolean',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'name', 'active', 'order', 'user_group_id'];
|
||||
protected $fillable = ['user_id', 'user_group_id', 'name', 'active', 'order', 'user_group_id'];
|
||||
|
||||
protected $hidden = ['encrypted'];
|
||||
|
||||
|
@@ -42,10 +42,12 @@ class Category extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'encrypted' => 'boolean',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'encrypted' => 'boolean',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'user_group_id', 'name'];
|
||||
|
@@ -40,14 +40,15 @@ class CurrencyExchangeRate extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'user_id' => 'int',
|
||||
'from_currency_id' => 'int',
|
||||
'to_currency_id' => 'int',
|
||||
'date' => SeparateTimezoneCaster::class,
|
||||
'rate' => 'string',
|
||||
'user_rate' => 'string',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
'from_currency_id' => 'integer',
|
||||
'to_currency_id' => 'integer',
|
||||
'date' => SeparateTimezoneCaster::class,
|
||||
'rate' => 'string',
|
||||
'user_rate' => 'string',
|
||||
];
|
||||
protected $fillable = ['user_id', 'from_currency_id', 'to_currency_id', 'date', 'date_tz', 'rate'];
|
||||
|
||||
|
@@ -36,6 +36,13 @@ class GroupMembership extends Model
|
||||
use ReturnsIntegerIdTrait;
|
||||
use ReturnsIntegerUserIdTrait;
|
||||
|
||||
protected $casts = [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'user_group_id', 'user_role_id'];
|
||||
|
||||
public function user(): BelongsTo
|
||||
|
@@ -39,10 +39,12 @@ class InvitedUser extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'expires' => SeparateTimezoneCaster::class,
|
||||
'redeemed' => 'boolean',
|
||||
'expires' => SeparateTimezoneCaster::class,
|
||||
'redeemed' => 'boolean',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
protected $fillable = ['user_id', 'email', 'invite_code', 'expires', 'expires_tz', 'redeemed'];
|
||||
protected $fillable = ['user_group_id', 'user_id', 'email', 'invite_code', 'expires', 'expires_tz', 'redeemed'];
|
||||
|
||||
/**
|
||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||
|
@@ -40,10 +40,11 @@ class ObjectGroup extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'user_id' => 'integer',
|
||||
'deleted_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
protected $fillable = ['title', 'order', 'user_id', 'user_group_id'];
|
||||
|
||||
|
@@ -37,9 +37,11 @@ class Preference extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'data' => 'array',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'data' => 'array',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'data', 'name', 'user_group_id'];
|
||||
|
@@ -44,22 +44,24 @@ class Recurrence extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'title' => 'string',
|
||||
'id' => 'int',
|
||||
'description' => 'string',
|
||||
'first_date' => SeparateTimezoneCaster::class,
|
||||
'repeat_until' => SeparateTimezoneCaster::class,
|
||||
'latest_date' => SeparateTimezoneCaster::class,
|
||||
'repetitions' => 'int',
|
||||
'active' => 'bool',
|
||||
'apply_rules' => 'bool',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'title' => 'string',
|
||||
'id' => 'int',
|
||||
'description' => 'string',
|
||||
'first_date' => SeparateTimezoneCaster::class,
|
||||
'repeat_until' => SeparateTimezoneCaster::class,
|
||||
'latest_date' => SeparateTimezoneCaster::class,
|
||||
'repetitions' => 'int',
|
||||
'active' => 'bool',
|
||||
'apply_rules' => 'bool',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable
|
||||
= ['user_id', 'transaction_type_id', 'title', 'description', 'first_date', 'first_date_tz', 'repeat_until', 'repeat_until_tz', 'latest_date', 'latest_date_tz', 'repetitions', 'apply_rules', 'active'];
|
||||
= ['user_id', 'user_group_id', 'transaction_type_id', 'title', 'description', 'first_date', 'first_date_tz', 'repeat_until', 'repeat_until_tz', 'latest_date', 'latest_date_tz', 'repetitions', 'apply_rules', 'active'];
|
||||
|
||||
protected $table = 'recurrences';
|
||||
|
||||
|
@@ -41,17 +41,19 @@ class Rule extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'active' => 'boolean',
|
||||
'order' => 'int',
|
||||
'stop_processing' => 'boolean',
|
||||
'id' => 'int',
|
||||
'strict' => 'boolean',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'active' => 'boolean',
|
||||
'order' => 'int',
|
||||
'stop_processing' => 'boolean',
|
||||
'id' => 'int',
|
||||
'strict' => 'boolean',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['rule_group_id', 'order', 'active', 'title', 'description', 'user_id', 'strict'];
|
||||
protected $fillable = ['rule_group_id', 'order', 'active', 'title', 'description', 'user_id', 'user_group_id', 'strict'];
|
||||
|
||||
/**
|
||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||
|
@@ -41,12 +41,14 @@ class RuleGroup extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'active' => 'boolean',
|
||||
'stop_processing' => 'boolean',
|
||||
'order' => 'int',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'active' => 'boolean',
|
||||
'stop_processing' => 'boolean',
|
||||
'order' => 'int',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'user_group_id', 'stop_processing', 'order', 'title', 'description', 'active'];
|
||||
|
@@ -42,13 +42,15 @@ class Tag extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'date' => SeparateTimezoneCaster::class,
|
||||
'zoomLevel' => 'int',
|
||||
'latitude' => 'float',
|
||||
'longitude' => 'float',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'date' => SeparateTimezoneCaster::class,
|
||||
'zoomLevel' => 'int',
|
||||
'latitude' => 'float',
|
||||
'longitude' => 'float',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'user_group_id', 'tag', 'date', 'date_tz', 'description', 'tagMode'];
|
||||
|
@@ -40,12 +40,14 @@ class TransactionGroup extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'id' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'title' => 'string',
|
||||
'date' => 'datetime',
|
||||
'id' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'title' => 'string',
|
||||
'date' => 'datetime',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable = ['user_id', 'user_group_id', 'title'];
|
||||
|
@@ -54,17 +54,19 @@ class TransactionJournal extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'date' => SeparateTimezoneCaster::class,
|
||||
'interest_date' => 'date',
|
||||
'book_date' => 'date',
|
||||
'process_date' => 'date',
|
||||
'order' => 'int',
|
||||
'tag_count' => 'int',
|
||||
'encrypted' => 'boolean',
|
||||
'completed' => 'boolean',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'date' => SeparateTimezoneCaster::class,
|
||||
'interest_date' => 'date',
|
||||
'book_date' => 'date',
|
||||
'process_date' => 'date',
|
||||
'order' => 'int',
|
||||
'tag_count' => 'int',
|
||||
'encrypted' => 'boolean',
|
||||
'completed' => 'boolean',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $fillable
|
||||
|
@@ -44,10 +44,12 @@ class Webhook extends Model
|
||||
|
||||
protected $casts
|
||||
= [
|
||||
'active' => 'boolean',
|
||||
'trigger' => 'integer',
|
||||
'response' => 'integer',
|
||||
'delivery' => 'integer',
|
||||
'active' => 'boolean',
|
||||
'trigger' => 'integer',
|
||||
'response' => 'integer',
|
||||
'delivery' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'user_group_id' => 'integer',
|
||||
];
|
||||
protected $fillable = ['active', 'trigger', 'response', 'delivery', 'user_id', 'user_group_id', 'url', 'title', 'secret'];
|
||||
|
||||
|
@@ -498,6 +498,8 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
}
|
||||
$query->orderBy('accounts.active', 'DESC');
|
||||
$query->orderBy('accounts.name', 'ASC');
|
||||
$query->orderBy('accounts.account_type_id', 'ASC');
|
||||
$query->orderBy('accounts.id', 'ASC');
|
||||
}
|
||||
|
||||
return $query->get(['accounts.*']);
|
||||
|
@@ -42,6 +42,7 @@ use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
@@ -556,7 +557,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
return $this->user->bills()
|
||||
->where('active', true)
|
||||
->orderBy('bills.name', 'ASC')
|
||||
->get(['bills.*', \DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount')]) // @phpstan-ignore-line
|
||||
->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount')]) // @phpstan-ignore-line
|
||||
;
|
||||
}
|
||||
|
||||
|
@@ -214,7 +214,6 @@ class OperationsRepository implements OperationsRepositoryInterface
|
||||
Log::debug(sprintf('Start of %s.', __METHOD__));
|
||||
// this collector excludes all transfers TO liabilities (which are also withdrawals)
|
||||
// because those expenses only become expenses once they move from the liability to the friend.
|
||||
|
||||
// 2024-12-24 disable the exclusion for now.
|
||||
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
@@ -245,7 +244,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
||||
}
|
||||
if (null !== $currency) {
|
||||
Log::debug(sprintf('Limit to currency %s', $currency->code));
|
||||
$collector->setNormalCurrency($currency);
|
||||
$collector->setCurrency($currency);
|
||||
}
|
||||
$collector->setBudgets($budgets);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Repositories\Currency;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -36,6 +37,7 @@ use Illuminate\Support\Collection;
|
||||
class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
{
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
|
||||
#[\Override]
|
||||
public function find(int $currencyId): ?TransactionCurrency
|
||||
@@ -109,7 +111,14 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
public function setUser(null|Authenticatable|User $user): void
|
||||
{
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
$this->user = $user;
|
||||
$this->userGroup = $user->userGroup;
|
||||
}
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Repositories\Currency;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -67,4 +68,6 @@ interface CurrencyRepositoryInterface
|
||||
public function setExchangeRate(TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date, float $rate): CurrencyExchangeRate;
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void;
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void;
|
||||
}
|
||||
|
@@ -222,7 +222,8 @@ trait ModifiesPiggyBanks
|
||||
// update the accounts
|
||||
$factory = new PiggyBankFactory();
|
||||
$factory->user = $this->user;
|
||||
$factory->linkToAccountIds($piggyBank, $data['accounts']);
|
||||
|
||||
$factory->linkToAccountIds($piggyBank, $data['accounts'] ?? []);
|
||||
|
||||
|
||||
// if the piggy bank is now smaller than the sum of the money saved,
|
||||
@@ -233,8 +234,8 @@ trait ModifiesPiggyBanks
|
||||
$difference = bcsub($piggyBank->target_amount, $currentAmount);
|
||||
|
||||
// an amount will be removed, create "negative" event:
|
||||
Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference));
|
||||
event(new ChangedAmount($piggyBank, $difference, null, null));
|
||||
// Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference));
|
||||
// event(new ChangedAmount($piggyBank, $difference, null, null));
|
||||
|
||||
// question is, from which account(s) to remove the difference?
|
||||
// solution: just start from the top until there is no more money left to remove.
|
||||
|
@@ -361,6 +361,8 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
}
|
||||
$query->orderBy('accounts.order', 'ASC');
|
||||
$query->orderBy('accounts.name', 'ASC');
|
||||
$query->orderBy('accounts.account_type_id', 'ASC');
|
||||
$query->orderBy('accounts.id', 'ASC');
|
||||
}
|
||||
|
||||
return $query->get(['accounts.*']);
|
||||
|
@@ -37,7 +37,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
{
|
||||
public function getUpdateInformation(string $channel): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in getUpdateInformation(%s)', $channel));
|
||||
Log::debug(sprintf('Now in getUpdateInformation(%s)', $channel));
|
||||
$information = [
|
||||
'level' => 'error',
|
||||
'message' => (string) trans('firefly.unknown_error'),
|
||||
@@ -46,8 +46,8 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
// try to get array from update server:
|
||||
$updateInfo = $this->contactServer($channel);
|
||||
if ('error' === $updateInfo['level']) {
|
||||
app('log')->error('Update information contains an error.');
|
||||
app('log')->error($updateInfo['message']);
|
||||
Log::error('Update information contains an error.');
|
||||
Log::error($updateInfo['message']);
|
||||
$information['message'] = $updateInfo['message'];
|
||||
|
||||
return $information;
|
||||
@@ -59,7 +59,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
|
||||
private function contactServer(string $channel): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in contactServer(%s)', $channel));
|
||||
Log::debug(sprintf('Now in contactServer(%s)', $channel));
|
||||
// always fall back to current version:
|
||||
$return = [
|
||||
'version' => config('firefly.version'),
|
||||
@@ -69,7 +69,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
];
|
||||
|
||||
$url = config('firefly.update_endpoint');
|
||||
app('log')->debug(sprintf('Going to call %s', $url));
|
||||
Log::debug(sprintf('Going to call %s', $url));
|
||||
|
||||
try {
|
||||
$client = new Client();
|
||||
@@ -81,17 +81,17 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
];
|
||||
$res = $client->request('GET', $url, $options);
|
||||
} catch (GuzzleException $e) {
|
||||
app('log')->error('Ran into Guzzle error.');
|
||||
app('log')->error($e->getMessage());
|
||||
app('log')->error($e->getTraceAsString());
|
||||
Log::error('Ran into Guzzle error.');
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
$return['message'] = sprintf('Guzzle: %s', strip_tags($e->getMessage()));
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if (200 !== $res->getStatusCode()) {
|
||||
app('log')->error(sprintf('Response status from server is %d.', $res->getStatusCode()));
|
||||
app('log')->error((string) $res->getBody());
|
||||
Log::error(sprintf('Response status from server is %d.', $res->getStatusCode()));
|
||||
Log::error((string) $res->getBody());
|
||||
$return['message'] = sprintf('Error: %d', $res->getStatusCode());
|
||||
|
||||
return $return;
|
||||
@@ -101,16 +101,16 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
try {
|
||||
$json = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
app('log')->error('Body is not valid JSON');
|
||||
app('log')->error($body);
|
||||
Log::error('Body is not valid JSON');
|
||||
Log::error($body);
|
||||
$return['message'] = 'Invalid JSON :(';
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if (!array_key_exists($channel, $json['firefly_iii'])) {
|
||||
app('log')->error(sprintf('No valid update channel "%s"', $channel));
|
||||
app('log')->error($body);
|
||||
Log::error(sprintf('No valid update channel "%s"', $channel));
|
||||
Log::error($body);
|
||||
$return['message'] = sprintf('Unknown update channel "%s" :(', $channel);
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
$return['level'] = 'success';
|
||||
$return['date'] = $date->startOfDay();
|
||||
|
||||
app('log')->info('Response from update server', $response);
|
||||
Log::info('Response from update server', $response);
|
||||
|
||||
return $return;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
*/
|
||||
private function parseResult(array $information): array
|
||||
{
|
||||
app('log')->debug('Now in parseResult()', $information);
|
||||
Log::debug('Now in parseResult()', $information);
|
||||
$current = (string) config('firefly.version');
|
||||
$latest = (string) $information['version'];
|
||||
|
||||
@@ -148,7 +148,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
|
||||
$compare = version_compare($latest, $current);
|
||||
|
||||
app('log')->debug(sprintf('Current version is "%s", latest is "%s", result is: %d', $current, $latest, $compare));
|
||||
Log::debug(sprintf('Current version is "%s", latest is "%s", result is: %d', $current, $latest, $compare));
|
||||
|
||||
// -1: you're running a newer version:
|
||||
if (-1 === $compare) {
|
||||
@@ -206,7 +206,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
'level' => 'info',
|
||||
'message' => (string) trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]),
|
||||
];
|
||||
app('log')->debug('User is running a newer version', $return);
|
||||
Log::debug('User is running a newer version', $return);
|
||||
|
||||
return $return;
|
||||
}
|
||||
@@ -217,14 +217,14 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
'level' => 'info',
|
||||
'message' => (string) trans('firefly.update_current_version_alert', ['version' => $current]),
|
||||
];
|
||||
app('log')->debug('User is the current version.', $return);
|
||||
Log::debug('User is the current version.', $return);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function releasedNewAlpha(string $current, string $latest, Carbon $date): array
|
||||
{
|
||||
app('log')->debug('New release is also a alpha!');
|
||||
Log::debug('New release is also a alpha!');
|
||||
$message = (string) trans(
|
||||
'firefly.update_new_version_alert',
|
||||
[
|
||||
@@ -242,7 +242,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
|
||||
private function releasedNewBeta(string $current, string $latest, Carbon $date): array
|
||||
{
|
||||
app('log')->debug('New release is also a beta!');
|
||||
Log::debug('New release is also a beta!');
|
||||
$message = (string) trans(
|
||||
'firefly.update_new_version_alert',
|
||||
[
|
||||
@@ -260,7 +260,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
|
||||
private function releasedNewVersion(string $current, string $latest, Carbon $date): array
|
||||
{
|
||||
app('log')->debug('New release is old enough.');
|
||||
Log::debug('New release is old enough.');
|
||||
$message = (string) trans(
|
||||
'firefly.update_new_version_alert',
|
||||
[
|
||||
@@ -269,7 +269,7 @@ class UpdateRequest implements UpdateRequestInterface
|
||||
'date' => $date->isoFormat((string) trans('config.month_and_day_js')),
|
||||
]
|
||||
);
|
||||
app('log')->debug('New release is here!', [$message]);
|
||||
Log::debug('New release is here!', [$message]);
|
||||
event(new NewVersionAvailable($message));
|
||||
|
||||
return [
|
||||
|
@@ -31,6 +31,7 @@ use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* Class AccountDestroyService
|
||||
@@ -46,8 +47,6 @@ class AccountDestroyService
|
||||
$this->moveTransactions($account, $moveTo);
|
||||
$this->updateRecurrences($account, $moveTo);
|
||||
}
|
||||
$this->destroyJournals($account);
|
||||
|
||||
// delete recurring transactions with this account:
|
||||
if (null === $moveTo) {
|
||||
$this->destroyRecurrences($account);
|
||||
@@ -59,6 +58,7 @@ class AccountDestroyService
|
||||
// delete account meta:
|
||||
$account->accountMeta()->delete();
|
||||
// delete account.
|
||||
// at this point the account observer interferes and deletes most of the other stuff.
|
||||
$account->delete();
|
||||
}
|
||||
|
||||
@@ -134,28 +134,8 @@ class AccountDestroyService
|
||||
|
||||
private function updateRecurrences(Account $account, Account $moveTo): void
|
||||
{
|
||||
\DB::table('recurrences_transactions')->where('source_id', $account->id)->update(['source_id' => $moveTo->id]);
|
||||
\DB::table('recurrences_transactions')->where('destination_id', $account->id)->update(['destination_id' => $moveTo->id]);
|
||||
}
|
||||
|
||||
private function destroyJournals(Account $account): void
|
||||
{
|
||||
/** @var JournalDestroyService $service */
|
||||
$service = app(JournalDestroyService::class);
|
||||
|
||||
app('log')->debug('Now trigger account delete response #'.$account->id);
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($account->transactions()->get() as $transaction) {
|
||||
app('log')->debug('Now at transaction #'.$transaction->id);
|
||||
|
||||
/** @var null|TransactionJournal $journal */
|
||||
$journal = $transaction->transactionJournal()->first();
|
||||
if (null !== $journal) {
|
||||
app('log')->debug('Call for deletion of journal #'.$journal->id);
|
||||
$service->destroy($journal);
|
||||
}
|
||||
}
|
||||
DB::table('recurrences_transactions')->where('source_id', $account->id)->update(['source_id' => $moveTo->id]);
|
||||
DB::table('recurrences_transactions')->where('destination_id', $account->id)->update(['destination_id' => $moveTo->id]);
|
||||
}
|
||||
|
||||
private function destroyRecurrences(Account $account): void
|
||||
|
@@ -239,7 +239,8 @@ trait AccountServiceTrait
|
||||
// submit to factory:
|
||||
$submission = [
|
||||
'group_title' => null,
|
||||
'user' => $account->user_id,
|
||||
'user' => $account->user,
|
||||
'user_group' => $account->user->userGroup,
|
||||
'transactions' => [
|
||||
[
|
||||
'type' => 'Opening balance',
|
||||
@@ -248,7 +249,8 @@ trait AccountServiceTrait
|
||||
'source_name' => $sourceName,
|
||||
'destination_id' => $destId,
|
||||
'destination_name' => $destName,
|
||||
'user' => $account->user_id,
|
||||
'user' => $account->user,
|
||||
'user_group' => $account->user->userGroup,
|
||||
'currency_id' => $currency->id,
|
||||
'order' => 0,
|
||||
'amount' => $amount,
|
||||
@@ -459,11 +461,11 @@ trait AccountServiceTrait
|
||||
if (null === $currency) {
|
||||
$currency = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup);
|
||||
}
|
||||
|
||||
// submit to factory:
|
||||
$submission = [
|
||||
'group_title' => null,
|
||||
'user' => $account->user_id,
|
||||
'user' => $account->user,
|
||||
'user_group' => $account->user->userGroup,
|
||||
'transactions' => [
|
||||
[
|
||||
'type' => 'Liability credit',
|
||||
@@ -472,7 +474,8 @@ trait AccountServiceTrait
|
||||
'source_name' => $sourceName,
|
||||
'destination_id' => $destId,
|
||||
'destination_name' => $destName,
|
||||
'user' => $account->user_id,
|
||||
'user' => $account->user,
|
||||
'user_group' => $account->user->userGroup,
|
||||
'currency_id' => $currency->id,
|
||||
'order' => 0,
|
||||
'amount' => $amount,
|
||||
|
@@ -31,6 +31,7 @@ use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class RemoteUserGuard
|
||||
@@ -48,7 +49,7 @@ class RemoteUserGuard implements Guard
|
||||
{
|
||||
/** @var null|Request $request */
|
||||
$request = $app->get('request');
|
||||
app('log')->debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri()));
|
||||
Log::debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri()));
|
||||
$this->application = $app;
|
||||
$this->provider = $provider;
|
||||
$this->user = null;
|
||||
@@ -56,9 +57,9 @@ class RemoteUserGuard implements Guard
|
||||
|
||||
public function authenticate(): void
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
if (null !== $this->user) {
|
||||
app('log')->debug(sprintf('%s is found: #%d, "%s".', get_class($this->user), $this->user->id, $this->user->email));
|
||||
Log::debug(sprintf('%s is found: #%d, "%s".', get_class($this->user), $this->user->id, $this->user->email));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -67,17 +68,17 @@ class RemoteUserGuard implements Guard
|
||||
$userID = request()->server($header) ?? null;
|
||||
|
||||
if (function_exists('apache_request_headers')) {
|
||||
app('log')->debug('Use apache_request_headers to find user ID.');
|
||||
Log::debug('Use apache_request_headers to find user ID.');
|
||||
$userID = request()->server($header) ?? apache_request_headers()[$header] ?? null;
|
||||
}
|
||||
|
||||
if (null === $userID || '' === $userID) {
|
||||
app('log')->error(sprintf('No user in header "%s".', $header));
|
||||
Log::error(sprintf('No user in header "%s".', $header));
|
||||
|
||||
throw new FireflyException('The guard header was unexpectedly empty. See the logs.');
|
||||
}
|
||||
|
||||
app('log')->debug(sprintf('User ID found in header is "%s"', $userID));
|
||||
Log::debug(sprintf('User ID found in header is "%s"', $userID));
|
||||
|
||||
/** @var User $retrievedUser */
|
||||
$retrievedUser = $this->provider->retrieveById($userID);
|
||||
@@ -98,30 +99,30 @@ class RemoteUserGuard implements Guard
|
||||
}
|
||||
}
|
||||
|
||||
app('log')->debug(sprintf('Result of getting user from provider: %s', $retrievedUser->email));
|
||||
Log::debug(sprintf('Result of getting user from provider: %s', $retrievedUser->email));
|
||||
$this->user = $retrievedUser;
|
||||
}
|
||||
|
||||
public function guest(): bool
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
|
||||
return !$this->check();
|
||||
}
|
||||
|
||||
public function check(): bool
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
|
||||
return null !== $this->user();
|
||||
}
|
||||
|
||||
public function user(): ?User
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
$user = $this->user;
|
||||
if (null === $user) {
|
||||
app('log')->debug('User is NULL');
|
||||
Log::debug('User is NULL');
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -131,7 +132,7 @@ class RemoteUserGuard implements Guard
|
||||
|
||||
public function hasUser(): bool
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
|
||||
throw new FireflyException('Did not implement RemoteUserGuard::hasUser()');
|
||||
}
|
||||
@@ -141,20 +142,20 @@ class RemoteUserGuard implements Guard
|
||||
*/
|
||||
public function id(): null|int|string
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
|
||||
return $this->user?->id;
|
||||
}
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void // @phpstan-ignore-line
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
if ($user instanceof User) {
|
||||
$this->user = $user;
|
||||
|
||||
return;
|
||||
}
|
||||
app('log')->error(sprintf('Did not set user at %s', __METHOD__));
|
||||
Log::error(sprintf('Did not set user at %s', __METHOD__));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,14 +165,14 @@ class RemoteUserGuard implements Guard
|
||||
*/
|
||||
public function validate(array $credentials = []): bool
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
|
||||
throw new FireflyException('Did not implement RemoteUserGuard::validate()');
|
||||
}
|
||||
|
||||
public function viaRemember(): bool
|
||||
{
|
||||
app('log')->debug(sprintf('Now at %s', __METHOD__));
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ namespace FireflyIII\Support\Cronjobs;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Jobs\DownloadExchangeRates;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class ExchangeRatesCronjob
|
||||
@@ -41,23 +42,23 @@ class ExchangeRatesCronjob extends AbstractCronjob
|
||||
$diff = time() - $lastTime;
|
||||
$diffForHumans = today(config('app.timezone'))->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true);
|
||||
if (0 === $lastTime) {
|
||||
app('log')->info('Exchange rates cron-job has never fired before.');
|
||||
Log::info('Exchange rates cron-job has never fired before.');
|
||||
}
|
||||
// less than half a day ago:
|
||||
if ($lastTime > 0 && $diff <= 43200) {
|
||||
app('log')->info(sprintf('It has been %s since the exchange rates cron-job has fired.', $diffForHumans));
|
||||
Log::info(sprintf('It has been %s since the exchange rates cron-job has fired.', $diffForHumans));
|
||||
if (false === $this->force) {
|
||||
app('log')->info('The exchange rates cron-job will not fire now.');
|
||||
Log::info('The exchange rates cron-job will not fire now.');
|
||||
$this->message = sprintf('It has been %s since the exchange rates cron-job has fired. It will not fire now.', $diffForHumans);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
app('log')->info('Execution of the exchange rates cron-job has been FORCED.');
|
||||
Log::info('Execution of the exchange rates cron-job has been FORCED.');
|
||||
}
|
||||
|
||||
if ($lastTime > 0 && $diff > 43200) {
|
||||
app('log')->info(sprintf('It has been %s since the exchange rates cron-job has fired. It will fire now!', $diffForHumans));
|
||||
Log::info(sprintf('It has been %s since the exchange rates cron-job has fired. It will fire now!', $diffForHumans));
|
||||
}
|
||||
|
||||
$this->fireExchangeRateJob();
|
||||
@@ -66,7 +67,7 @@ class ExchangeRatesCronjob extends AbstractCronjob
|
||||
|
||||
private function fireExchangeRateJob(): void
|
||||
{
|
||||
app('log')->info(sprintf('Will now fire exchange rates cron job task for date "%s".', $this->date->format('Y-m-d')));
|
||||
Log::info(sprintf('Will now fire exchange rates cron job task for date "%s".', $this->date->format('Y-m-d')));
|
||||
|
||||
/** @var DownloadExchangeRates $job */
|
||||
$job = app(DownloadExchangeRates::class);
|
||||
@@ -80,6 +81,6 @@ class ExchangeRatesCronjob extends AbstractCronjob
|
||||
$this->message = 'Exchange rates cron job fired successfully.';
|
||||
|
||||
app('fireflyconfig')->set('last_cer_job', (int) $this->date->format('U'));
|
||||
app('log')->info('Done with exchange rates job task.');
|
||||
Log::info('Done with exchange rates job task.');
|
||||
}
|
||||
}
|
||||
|
88
app/Support/Cronjobs/UpdateCheckCronjob.php
Normal file
88
app/Support/Cronjobs/UpdateCheckCronjob.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* UpdateCheckCronjob.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\Cronjobs;
|
||||
|
||||
use FireflyIII\Helpers\Update\UpdateTrait;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UpdateCheckCronjob extends AbstractCronjob
|
||||
{
|
||||
use UpdateTrait;
|
||||
|
||||
#[\Override]
|
||||
public function fire(): void
|
||||
{
|
||||
Log::debug('Now in checkForUpdates()');
|
||||
|
||||
// should not check for updates:
|
||||
$permission = app('fireflyconfig')->get('permission_update_check', -1);
|
||||
$value = (int) $permission->data;
|
||||
if (1 !== $value) {
|
||||
Log::debug('Update check is not enabled.');
|
||||
// get stuff from job:
|
||||
$this->jobFired = false;
|
||||
$this->jobErrored = true;
|
||||
$this->jobSucceeded = false;
|
||||
$this->message = 'The update check is not enabled.';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO this is duplicate.
|
||||
/** @var Configuration $lastCheckTime */
|
||||
$lastCheckTime = FireflyConfig::get('last_update_check', time());
|
||||
$now = time();
|
||||
$diff = $now - $lastCheckTime->data;
|
||||
Log::debug(sprintf('Last check time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff));
|
||||
if ($diff < 604800 && false === $this->force) {
|
||||
// get stuff from job:
|
||||
$this->jobFired = false;
|
||||
$this->jobErrored = true;
|
||||
$this->jobSucceeded = false;
|
||||
$this->message = sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data));
|
||||
|
||||
return;
|
||||
}
|
||||
// last check time was more than a week ago.
|
||||
Log::debug('Have not checked for a new version in a week!');
|
||||
$release = $this->getLatestRelease();
|
||||
if ('error' === $release['level']) {
|
||||
// get stuff from job:
|
||||
$this->jobFired = true;
|
||||
$this->jobErrored = true;
|
||||
$this->jobSucceeded = false;
|
||||
$this->message = $release['message'];
|
||||
|
||||
return;
|
||||
}
|
||||
// get stuff from job:
|
||||
$this->jobFired = true;
|
||||
$this->jobErrored = false;
|
||||
$this->jobSucceeded = false;
|
||||
$this->message = $release['message'];
|
||||
}
|
||||
}
|
@@ -199,7 +199,7 @@ trait ModelInformation
|
||||
++$index;
|
||||
|
||||
// amount_exactly:
|
||||
$journalTriggers[$index] = 'amount_exactly';
|
||||
$journalTriggers[$index] = 'amount_is';
|
||||
$values[$index] = $destination->amount;
|
||||
++$index;
|
||||
|
||||
@@ -244,7 +244,7 @@ trait ModelInformation
|
||||
// notes (if)
|
||||
$notes = $journal->notes()->first();
|
||||
if (null !== $notes) {
|
||||
$journalTriggers[$index] = 'notes_are';
|
||||
$journalTriggers[$index] = 'notes_is';
|
||||
$values[$index] = $notes->text;
|
||||
}
|
||||
|
||||
|
@@ -25,14 +25,19 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Support\Facades\Balance;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -44,27 +49,50 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
class AccountEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private array $balances;
|
||||
private Collection $collection;
|
||||
private array $currencies;
|
||||
private CurrencyRepositoryInterface $currencyRepository;
|
||||
private TransactionCurrency $default;
|
||||
private ?Carbon $end;
|
||||
private array $grouped;
|
||||
private array $objectGroups;
|
||||
private AccountRepositoryInterface $repository;
|
||||
private ?Carbon $start;
|
||||
// private array $balances;
|
||||
// private array $currencies;
|
||||
// private CurrencyRepositoryInterface $currencyRepository;
|
||||
// private TransactionCurrency $default;
|
||||
// private ?Carbon $end;
|
||||
// private array $grouped;
|
||||
// private array $objectGroups;
|
||||
// private AccountRepositoryInterface $repository;
|
||||
// private ?Carbon $start;
|
||||
|
||||
private Collection $collection;
|
||||
|
||||
private bool $convertToNative;
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
private TransactionCurrency $native;
|
||||
private array $accountIds;
|
||||
private array $accountTypeIds;
|
||||
private array $accountTypes;
|
||||
private array $currencies;
|
||||
private array $meta;
|
||||
private array $openingBalances;
|
||||
private array $notes;
|
||||
private array $locations;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$this->start = null;
|
||||
$this->end = null;
|
||||
$this->convertToNative = false;
|
||||
$this->accountIds = [];
|
||||
$this->openingBalances = [];
|
||||
$this->currencies = [];
|
||||
$this->accountTypeIds = [];
|
||||
$this->accountTypes = [];
|
||||
$this->meta = [];
|
||||
$this->notes = [];
|
||||
$this->locations = [];
|
||||
// $this->repository = app(AccountRepositoryInterface::class);
|
||||
// $this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
// $this->start = null;
|
||||
// $this->end = null;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function enrichSingle(Model $model): Account
|
||||
public function enrichSingle(array|Model $model): Account|array
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection([$model]);
|
||||
@@ -80,202 +108,187 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
public function enrich(Collection $collection): Collection
|
||||
{
|
||||
Log::debug(sprintf('Now doing account enrichment for %d account(s)', $collection->count()));
|
||||
|
||||
// prep local fields
|
||||
$this->collection = $collection;
|
||||
$this->default = app('amount')->getNativeCurrency();
|
||||
$this->currencies = [];
|
||||
$this->balances = [];
|
||||
$this->objectGroups = [];
|
||||
$this->grouped = [];
|
||||
|
||||
// do everything here:
|
||||
$this->getLastActivity();
|
||||
$this->collectAccountTypes();
|
||||
$this->collection = $collection;
|
||||
$this->collectAccountIds();
|
||||
$this->getAccountTypes();
|
||||
$this->collectMetaData();
|
||||
$this->getMetaBalances();
|
||||
$this->getObjectGroups();
|
||||
|
||||
// $this->collection->transform(function (Account $account) {
|
||||
// $account->user_array = ['id' => 1, 'bla bla' => 'bla'];
|
||||
// $account->balances = collect([
|
||||
// ['balance_id' => 1, 'balance' => 5],
|
||||
// ['balance_id' => 2, 'balance' => 5],
|
||||
// ['balance_id' => 3, 'balance' => 5],
|
||||
// ]);
|
||||
//
|
||||
// return $account;
|
||||
// });
|
||||
$this->collectNotes();
|
||||
$this->collectLocations();
|
||||
$this->collectOpeningBalances();
|
||||
$this->appendCollectedData();
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO this method refers to a single-use method inside Steam that could be moved here.
|
||||
*/
|
||||
private function getLastActivity(): void
|
||||
private function getAccountTypes(): void
|
||||
{
|
||||
$lastActivity = $this->repository->getLastActivity($this->collection);
|
||||
foreach ($lastActivity as $row) {
|
||||
$this->collection->where('id', $row['account_id'])->first()->last_activity = Carbon::parse($row['date_max'], config('app.timezone'));
|
||||
$types = AccountType::whereIn('id', $this->accountTypeIds)->get();
|
||||
|
||||
/** @var AccountType $type */
|
||||
foreach ($types as $type) {
|
||||
$this->accountTypes[(int) $type->id] = $type->type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO this method refers to a single-use method inside Steam that could be moved here.
|
||||
*/
|
||||
private function collectAccountTypes(): void
|
||||
private function collectAccountIds(): void
|
||||
{
|
||||
$accountTypes = $this->repository->getAccountTypes($this->collection);
|
||||
$types = [];
|
||||
|
||||
/** @var AccountType $row */
|
||||
foreach ($accountTypes as $row) {
|
||||
$types[$row->id] = $row->type;
|
||||
/** @var Account $account */
|
||||
foreach ($this->collection as $account) {
|
||||
$this->accountIds[] = (int) $account->id;
|
||||
$this->accountTypeIds[] = (int) $account->account_type_id;
|
||||
}
|
||||
$this->collection->transform(function (Account $account) use ($types) {
|
||||
$account->account_type_string = $types[$account->id];
|
||||
$this->accountIds = array_unique($this->accountIds);
|
||||
$this->accountTypeIds = array_unique($this->accountTypeIds);
|
||||
}
|
||||
|
||||
return $account;
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$accountTypes = $this->accountTypes;
|
||||
$meta = $this->meta;
|
||||
$currencies = $this->currencies;
|
||||
$notes = $this->notes;
|
||||
$openingBalances = $this->openingBalances;
|
||||
$locations = $this->locations;
|
||||
$this->collection = $this->collection->map(function (Account $item) use ($accountTypes, $meta, $currencies, $notes, $openingBalances, $locations) {
|
||||
$item->full_account_type = $accountTypes[(int) $item->account_type_id] ?? null;
|
||||
$accountMeta = [
|
||||
'currency' => null,
|
||||
'location' => [
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoom_level' => null,
|
||||
],
|
||||
];
|
||||
if (array_key_exists((int) $item->id, $meta)) {
|
||||
foreach ($meta[(int) $item->id] as $name => $value) {
|
||||
$accountMeta[$name] = $value;
|
||||
}
|
||||
}
|
||||
// also add currency, if present.
|
||||
if (array_key_exists('currency_id', $accountMeta)) {
|
||||
$currencyId = (int) $accountMeta['currency_id'];
|
||||
$accountMeta['currency'] = $currencies[$currencyId];
|
||||
}
|
||||
|
||||
// if notes, add notes.
|
||||
if (array_key_exists($item->id, $notes)) {
|
||||
$accountMeta['notes'] = $notes[$item->id];
|
||||
}
|
||||
// if opening balance, add opening balance
|
||||
if (array_key_exists($item->id, $openingBalances)) {
|
||||
$accountMeta['opening_balance_date'] = $openingBalances[$item->id]['date'];
|
||||
$accountMeta['opening_balance_amount'] = $openingBalances[$item->id]['amount'];
|
||||
}
|
||||
|
||||
// if location, add location:
|
||||
if (array_key_exists($item->id, $locations)) {
|
||||
$accountMeta['location'] = $locations[$item->id];
|
||||
}
|
||||
$item->meta = $accountMeta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
|
||||
private function collectOpeningBalances(): void
|
||||
{
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setUser($this->user)->setAccounts($this->collection)
|
||||
->withAccountInformation()
|
||||
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value])
|
||||
;
|
||||
$journals = $collector->getExtractedJournals();
|
||||
foreach ($journals as $journal) {
|
||||
$this->openingBalances[(int) $journal['source_account_id']]
|
||||
= [
|
||||
'amount' => Steam::negative($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
$this->openingBalances[(int) $journal['destination_account_id']]
|
||||
= [
|
||||
'amount' => Steam::positive($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private function collectLocations(): void
|
||||
{
|
||||
$locations = Location::query()->whereIn('locatable_id', $this->accountIds)
|
||||
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray()
|
||||
;
|
||||
foreach ($locations as $location) {
|
||||
$this->locations[(int) $location['locatable_id']]
|
||||
= [
|
||||
'latitude' => (float) $location['latitude'],
|
||||
'longitude' => (float) $location['longitude'],
|
||||
'zoom_level' => (int) $location['zoom_level'],
|
||||
];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
|
||||
}
|
||||
|
||||
private function collectMetaData(): void
|
||||
{
|
||||
$metaFields = $this->repository->getMetaValues($this->collection, ['is_multi_currency', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']);
|
||||
$currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray();
|
||||
|
||||
$currencies = [];
|
||||
foreach ($this->currencyRepository->getByIds($currencyIds) as $currency) {
|
||||
$id = $currency->id;
|
||||
$currencies[$id] = $currency;
|
||||
}
|
||||
|
||||
$this->collection->transform(function (Account $account) use ($metaFields, $currencies) {
|
||||
$set = $metaFields->where('account_id', $account->id);
|
||||
foreach ($set as $entry) {
|
||||
$account->{$entry->name} = $entry->data;
|
||||
if ('currency_id' === $entry->name) {
|
||||
$id = (int) $entry->data;
|
||||
$account->currency_name = $currencies[$id]?->name;
|
||||
$account->currency_code = $currencies[$id]?->code;
|
||||
$account->currency_symbol = $currencies[$id]?->symbol;
|
||||
$account->currency_decimal_places = $currencies[$id]?->decimal_places;
|
||||
}
|
||||
}
|
||||
|
||||
return $account;
|
||||
});
|
||||
}
|
||||
|
||||
private function getMetaBalances(): void
|
||||
{
|
||||
$this->balances = Balance::getAccountBalances($this->collection, today());
|
||||
$balances = $this->balances;
|
||||
$default = $this->default;
|
||||
|
||||
// get start and end, so the balance difference can be generated.
|
||||
$start = null;
|
||||
$end = null;
|
||||
if (null !== $this->start) {
|
||||
$start = Balance::getAccountBalances($this->collection, $this->start);
|
||||
}
|
||||
if (null !== $this->end) {
|
||||
$end = Balance::getAccountBalances($this->collection, $this->end);
|
||||
}
|
||||
|
||||
$this->collection->transform(function (Account $account) use ($balances, $default, $start, $end) {
|
||||
$converter = new ExchangeRateConverter();
|
||||
$native = [
|
||||
'currency_id' => $this->default->id,
|
||||
'currency_name' => $this->default->name,
|
||||
'currency_code' => $this->default->code,
|
||||
'currency_symbol' => $this->default->symbol,
|
||||
'currency_decimal_places' => $this->default->decimal_places,
|
||||
'balance' => '0',
|
||||
'period_start_balance' => null,
|
||||
'period_end_balance' => null,
|
||||
'balance_difference' => null,
|
||||
];
|
||||
if (array_key_exists($account->id, $balances)) {
|
||||
$set = [];
|
||||
foreach ($balances[$account->id] as $currencyId => $entry) {
|
||||
$left = $start[$account->id][$currencyId]['balance'] ?? null;
|
||||
$right = $end[$account->id][$currencyId]['balance'] ?? null;
|
||||
$diff = null;
|
||||
if (null !== $left && null !== $right) {
|
||||
$diff = bcsub($right, $left);
|
||||
}
|
||||
|
||||
$item = [
|
||||
'currency_id' => $entry['currency']->id,
|
||||
'currency_name' => $entry['currency']->name,
|
||||
'currency_code' => $entry['currency']->code,
|
||||
'currency_symbol' => $entry['currency']->symbol,
|
||||
'currency_decimal_places' => $entry['currency']->decimal_places,
|
||||
'balance' => $entry['balance'],
|
||||
'period_start_balance' => $left,
|
||||
'period_end_balance' => $right,
|
||||
'balance_difference' => $diff,
|
||||
];
|
||||
$set[] = $item;
|
||||
if ($converter->enabled()) {
|
||||
$native['balance'] = bcadd($native['balance'], $converter->convert($entry['currency'], $default, today(), $entry['balance']));
|
||||
if (null !== $diff) {
|
||||
$native['period_start_balance'] = $converter->convert($entry['currency'], $default, today(), $item['period_start_balance']);
|
||||
$native['period_end_balance'] = $converter->convert($entry['currency'], $default, today(), $item['period_end_balance']);
|
||||
$native['balance_difference'] = bcsub($native['period_end_balance'], $native['period_start_balance']);
|
||||
}
|
||||
}
|
||||
}
|
||||
$account->balance = $set;
|
||||
if ($converter->enabled()) {
|
||||
$account->native_balance = $native;
|
||||
}
|
||||
}
|
||||
|
||||
return $account;
|
||||
});
|
||||
}
|
||||
|
||||
private function getObjectGroups(): void
|
||||
{
|
||||
$set = \DB::table('object_groupables')
|
||||
->where('object_groupable_type', Account::class)
|
||||
->whereIn('object_groupable_id', $this->collection->pluck('id')->toArray())
|
||||
->distinct()
|
||||
->get(['object_groupables.object_groupable_id', 'object_groupables.object_group_id'])
|
||||
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
|
||||
->whereIn('account_id', $this->accountIds)
|
||||
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray()
|
||||
;
|
||||
// get the groups:
|
||||
$groupIds = $set->pluck('object_group_id')->toArray();
|
||||
$groups = ObjectGroup::whereIn('id', $groupIds)->get();
|
||||
|
||||
/** @var ObjectGroup $group */
|
||||
foreach ($groups as $group) {
|
||||
$this->objectGroups[$group->id] = $group;
|
||||
}
|
||||
|
||||
/** @var \stdClass $entry */
|
||||
/** @var array $entry */
|
||||
foreach ($set as $entry) {
|
||||
$this->grouped[(int) $entry->object_groupable_id] = (int) $entry->object_group_id;
|
||||
}
|
||||
$this->collection->transform(function (Account $account) {
|
||||
$account->object_group_id = $this->grouped[$account->id] ?? null;
|
||||
if (null !== $account->object_group_id) {
|
||||
$account->object_group_title = $this->objectGroups[$account->object_group_id]->title;
|
||||
$account->object_group_order = $this->objectGroups[$account->object_group_id]->order;
|
||||
$this->meta[(int) $entry['account_id']][$entry['name']] = (string) $entry['data'];
|
||||
if ('currency_id' === $entry['name']) {
|
||||
$this->currencies[(int) $entry['data']] = true;
|
||||
}
|
||||
|
||||
return $account;
|
||||
});
|
||||
}
|
||||
$currencies = TransactionCurrency::whereIn('id', array_keys($this->currencies))->get();
|
||||
foreach ($currencies as $currency) {
|
||||
$this->currencies[(int) $currency->id] = $currency;
|
||||
}
|
||||
$this->currencies[0] = $this->native;
|
||||
foreach ($this->currencies as $id => $currency) {
|
||||
if (true === $currency) {
|
||||
throw new FireflyException(sprintf('Currency #%d not found.', $id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setEnd(?Carbon $end): void
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->end = $end;
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
|
||||
public function setStart(?Carbon $start): void
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->start = $start;
|
||||
$this->user = $user;
|
||||
$this->userGroup = $user->userGroup;
|
||||
}
|
||||
|
||||
public function setConvertToNative(bool $convertToNative): void
|
||||
{
|
||||
$this->convertToNative = $convertToNative;
|
||||
}
|
||||
|
||||
public function setNative(TransactionCurrency $native): void
|
||||
{
|
||||
$this->native = $native;
|
||||
}
|
||||
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->accountIds)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int) $note['noteable_id']] = (string) $note['text'];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d note(s)', count($this->notes)));
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
@@ -31,5 +33,9 @@ interface EnrichmentInterface
|
||||
{
|
||||
public function enrich(Collection $collection): Collection;
|
||||
|
||||
public function enrichSingle(Model $model): Model;
|
||||
public function enrichSingle(array|Model $model): array|Model;
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void;
|
||||
|
||||
public function setUser(User $user): void;
|
||||
}
|
||||
|
250
app/Support/JsonApi/Enrichments/TransactionGroupEnrichment.php
Normal file
250
app/Support/JsonApi/Enrichments/TransactionGroupEnrichment.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* TransactionGroupEnrichment.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private Collection $collection;
|
||||
private array $notes;
|
||||
private array $tags;
|
||||
private array $locations;
|
||||
private array $journalIds;
|
||||
private User $user;
|
||||
private UserGroup $userGroup;
|
||||
private array $metaData;
|
||||
private array $dateFields;
|
||||
private array $attachmentCount;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->notes = [];
|
||||
$this->journalIds = [];
|
||||
$this->tags = [];
|
||||
$this->metaData = [];
|
||||
$this->locations = [];
|
||||
$this->attachmentCount = [];
|
||||
$this->dateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function enrich(Collection $collection): Collection
|
||||
{
|
||||
Log::debug(sprintf('Now doing account enrichment for %d transaction group(s)', $collection->count()));
|
||||
// prep local fields
|
||||
$this->collection = $collection;
|
||||
$this->collectJournalIds();
|
||||
|
||||
// collect first, then enrich.
|
||||
$this->collectNotes();
|
||||
$this->collectTags();
|
||||
$this->collectMetaData();
|
||||
$this->collectLocations();
|
||||
$this->collectAttachmentCount();
|
||||
$this->appendCollectedData();
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function enrichSingle(array|Model $model): array|TransactionGroup
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
if (is_array($model)) {
|
||||
$collection = new Collection([$model]);
|
||||
$collection = $this->enrich($collection);
|
||||
|
||||
return $collection->first();
|
||||
}
|
||||
|
||||
throw new FireflyException('Cannot enrich single model.');
|
||||
}
|
||||
|
||||
private function collectJournalIds(): void
|
||||
{
|
||||
/** @var array $group */
|
||||
foreach ($this->collection as $group) {
|
||||
foreach ($group['transactions'] as $journal) {
|
||||
$this->journalIds[] = $journal['transaction_journal_id'];
|
||||
}
|
||||
}
|
||||
$this->journalIds = array_unique($this->journalIds);
|
||||
}
|
||||
|
||||
public function setUserGroup(UserGroup $userGroup): void
|
||||
{
|
||||
$this->userGroup = $userGroup;
|
||||
}
|
||||
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->userGroup = $user->userGroup;
|
||||
}
|
||||
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->journalIds)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', TransactionJournal::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int) $note['noteable_id']] = (string) $note['text'];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d note(s)', count($this->notes)));
|
||||
}
|
||||
|
||||
private function collectTags(): void
|
||||
{
|
||||
$set = Tag::leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id')
|
||||
->whereIn('tag_transaction_journal.transaction_journal_id', $this->journalIds)
|
||||
->get(['tag_transaction_journal.transaction_journal_id', 'tags.tag'])->toArray()
|
||||
;
|
||||
foreach ($set as $item) {
|
||||
$journalId = $item['transaction_journal_id'];
|
||||
$this->tags[$journalId] ??= [];
|
||||
$this->tags[$journalId][] = $item['tag'];
|
||||
}
|
||||
}
|
||||
|
||||
private function collectMetaData(): void
|
||||
{
|
||||
$set = TransactionJournalMeta::whereIn('transaction_journal_id', $this->journalIds)->get(['transaction_journal_id', 'name', 'data'])->toArray();
|
||||
foreach ($set as $entry) {
|
||||
$name = $entry['name'];
|
||||
$data = (string) $entry['data'];
|
||||
if ('' === $data) {
|
||||
continue;
|
||||
}
|
||||
if (in_array($name, $this->dateFields, true)) {
|
||||
$this->metaData[$entry['transaction_journal_id']][$name] = Carbon::parse($data);
|
||||
|
||||
continue;
|
||||
}
|
||||
$this->metaData[(int) $entry['transaction_journal_id']][$name] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
private function collectLocations(): void
|
||||
{
|
||||
$locations = Location::query()->whereIn('locatable_id', $this->journalIds)
|
||||
->where('locatable_type', TransactionJournal::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray()
|
||||
;
|
||||
foreach ($locations as $location) {
|
||||
$this->locations[(int) $location['locatable_id']]
|
||||
= [
|
||||
'latitude' => (float) $location['latitude'],
|
||||
'longitude' => (float) $location['longitude'],
|
||||
'zoom_level' => (int) $location['zoom_level'],
|
||||
];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
|
||||
}
|
||||
|
||||
private function collectAttachmentCount(): void
|
||||
{
|
||||
// select count(id) as nr_of_attachments, attachable_id from attachments
|
||||
// group by attachable_id
|
||||
$attachments = Attachment::query()
|
||||
->whereIn('attachable_id', $this->journalIds)
|
||||
->where('attachable_type', TransactionJournal::class)
|
||||
->groupBy('attachable_id')
|
||||
->get(['attachable_id', DB::raw('COUNT(id) as nr_of_attachments')]) // @phpstan-ignore-line
|
||||
->toArray()
|
||||
;
|
||||
foreach ($attachments as $row) {
|
||||
$this->attachmentCount[(int) $row['attachable_id']] = (int) $row['nr_of_attachments'];
|
||||
}
|
||||
}
|
||||
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$notes = $this->notes;
|
||||
$tags = $this->tags;
|
||||
$metaData = $this->metaData;
|
||||
$locations = $this->locations;
|
||||
$attachmentCount = $this->attachmentCount;
|
||||
|
||||
$this->collection = $this->collection->map(function (array $item) use ($notes, $tags, $metaData, $locations, $attachmentCount) {
|
||||
foreach ($item['transactions'] as $index => $transaction) {
|
||||
$journalId = (int) $transaction['transaction_journal_id'];
|
||||
|
||||
// attach notes if they exist:
|
||||
$item['transactions'][$index]['notes'] = array_key_exists($journalId, $notes) ? $notes[$journalId] : null;
|
||||
|
||||
// attach tags if they exist:
|
||||
$item['transactions'][$index]['tags'] = array_key_exists($journalId, $tags) ? $tags[$journalId] : [];
|
||||
|
||||
// attachment count
|
||||
$item['transactions'][$index]['attachment_count'] = array_key_exists($journalId, $attachmentCount) ? $attachmentCount[$journalId] : 0;
|
||||
|
||||
// default location data
|
||||
$item['transactions'][$index]['location'] = [
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoom_level' => null,
|
||||
];
|
||||
|
||||
// append meta data
|
||||
$item['transactions'][$index]['meta'] = [];
|
||||
$item['transactions'][$index]['meta_date'] = [];
|
||||
if (array_key_exists($journalId, $metaData)) {
|
||||
// loop al meta data:
|
||||
foreach ($metaData[$journalId] as $name => $value) {
|
||||
if (in_array($name, $this->dateFields, true)) {
|
||||
$item['transactions'][$index]['meta_date'][$name] = Carbon::parse($value);
|
||||
|
||||
continue;
|
||||
}
|
||||
$item['transactions'][$index]['meta'][$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// append location data
|
||||
if (array_key_exists($journalId, $locations)) {
|
||||
$item['transactions'][$index]['location'] = $locations[$journalId];
|
||||
}
|
||||
}
|
||||
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
}
|
@@ -72,20 +72,32 @@ class Preferences
|
||||
|
||||
public function getForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference
|
||||
{
|
||||
Log::debug(sprintf('getForUser(#%d, "%s")', $user->id, $name));
|
||||
// don't care about user group ID, except for some specific preferences.
|
||||
$userGroupId = $this->getUserGroupId($user, $name);
|
||||
$preference = Preference::where('user_group_id', $userGroupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']);
|
||||
$query = Preference::where('user_id', $user->id)->where('name', $name);
|
||||
if (null !== $userGroupId) {
|
||||
Log::debug('Include user group ID in query');
|
||||
$query->where('user_group_id', $userGroupId);
|
||||
}
|
||||
|
||||
$preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']);
|
||||
|
||||
if (null !== $preference && null === $preference->data) {
|
||||
$preference->delete();
|
||||
$preference = null;
|
||||
Log::debug('Removed empty preference.');
|
||||
}
|
||||
|
||||
if (null !== $preference) {
|
||||
Log::debug(sprintf('Found preference #%d for user #%d: %s', $preference->id, $user->id, $name));
|
||||
|
||||
return $preference;
|
||||
}
|
||||
// no preference found and default is null:
|
||||
if (null === $default) {
|
||||
Log::debug('Return NULL, create no preference.');
|
||||
|
||||
// return NULL
|
||||
return null;
|
||||
}
|
||||
@@ -124,35 +136,40 @@ class Preferences
|
||||
|
||||
public function setForUser(User $user, string $name, null|array|bool|int|string $value): Preference
|
||||
{
|
||||
$fullName = sprintf('preference%s%s', $user->id, $name);
|
||||
$groupId = $this->getUserGroupId($user, $name);
|
||||
$groupId = 0 === (int) $groupId ? null : (int) $groupId;
|
||||
$fullName = sprintf('preference%s%s', $user->id, $name);
|
||||
$userGroupId = $this->getUserGroupId($user, $name);
|
||||
$userGroupId = 0 === (int) $userGroupId ? null : (int) $userGroupId;
|
||||
|
||||
Cache::forget($fullName);
|
||||
|
||||
/** @var null|Preference $pref */
|
||||
$pref = Preference::where('user_group_id', $groupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']);
|
||||
$query = Preference::where('user_id', $user->id)->where('name', $name);
|
||||
if (null !== $userGroupId) {
|
||||
Log::debug('Include user group ID in query');
|
||||
$query->where('user_group_id', $userGroupId);
|
||||
}
|
||||
|
||||
if (null !== $pref && null === $value) {
|
||||
$pref->delete();
|
||||
$preference = $query->first(['id', 'user_id', 'user_group_id', 'name', 'data', 'updated_at', 'created_at']);
|
||||
|
||||
if (null !== $preference && null === $value) {
|
||||
$preference->delete();
|
||||
|
||||
return new Preference();
|
||||
}
|
||||
if (null === $value) {
|
||||
return new Preference();
|
||||
}
|
||||
if (null === $pref) {
|
||||
$pref = new Preference();
|
||||
$pref->user_id = (int) $user->id;
|
||||
$pref->user_group_id = $groupId;
|
||||
$pref->name = $name;
|
||||
if (null === $preference) {
|
||||
$preference = new Preference();
|
||||
$preference->user_id = (int) $user->id;
|
||||
$preference->user_group_id = $userGroupId;
|
||||
$preference->name = $name;
|
||||
|
||||
}
|
||||
$pref->data = $value;
|
||||
$pref->save();
|
||||
Cache::forever($fullName, $pref);
|
||||
$preference->data = $value;
|
||||
$preference->save();
|
||||
Cache::forever($fullName, $preference);
|
||||
|
||||
return $pref;
|
||||
return $preference;
|
||||
}
|
||||
|
||||
public function beginsWith(User $user, string $search): Collection
|
||||
|
@@ -51,16 +51,25 @@ class TransactionSummarizer
|
||||
|
||||
public function groupByCurrencyId(array $journals, string $method = 'negative'): array
|
||||
{
|
||||
Log::debug(sprintf('Now in groupByCurrencyId(array, "%s")', $method));
|
||||
$array = [];
|
||||
foreach ($journals as $journal) {
|
||||
$field = 'amount';
|
||||
$field = 'amount';
|
||||
|
||||
// grab default currency information.
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyName = $journal['currency_name'];
|
||||
$currencySymbol = $journal['currency_symbol'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$currencyDecimalPlaces = $journal['currency_decimal_places'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyName = $journal['currency_name'];
|
||||
$currencySymbol = $journal['currency_symbol'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$currencyDecimalPlaces = $journal['currency_decimal_places'];
|
||||
|
||||
// prepare foreign currency info:
|
||||
$foreignCurrencyId = 0;
|
||||
$foreignCurrencyName = null;
|
||||
$foreignCurrencySymbol = null;
|
||||
$foreignCurrencyCode = null;
|
||||
$foreignCurrencyDecimalPlaces = null;
|
||||
|
||||
if ($this->convertToNative) {
|
||||
// if convert to native, use the native amount yes or no?
|
||||
$useNative = $this->default->id !== (int) $journal['currency_id'];
|
||||
@@ -85,9 +94,19 @@ class TransactionSummarizer
|
||||
}
|
||||
}
|
||||
if (!$this->convertToNative) {
|
||||
// default to the normal amount, but also
|
||||
Log::debug(sprintf('Journal #%d also includes foreign amount (foreign is %s)', $journal['transaction_journal_id'], $journal['foreign_currency_code']));
|
||||
// use foreign amount?
|
||||
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$foreignCurrencyName = $journal['foreign_currency_name'];
|
||||
$foreignCurrencySymbol = $journal['foreign_currency_symbol'];
|
||||
$foreignCurrencyCode = $journal['foreign_currency_code'];
|
||||
$foreignCurrencyDecimalPlaces = $journal['foreign_currency_decimal_places'];
|
||||
}
|
||||
}
|
||||
$amount = (string) ($journal[$field] ?? '0');
|
||||
|
||||
// first process normal amount
|
||||
$amount = (string) ($journal[$field] ?? '0');
|
||||
$array[$currencyId] ??= [
|
||||
'sum' => '0',
|
||||
'currency_id' => $currencyId,
|
||||
@@ -96,12 +115,34 @@ class TransactionSummarizer
|
||||
'currency_code' => $currencyCode,
|
||||
'currency_decimal_places' => $currencyDecimalPlaces,
|
||||
];
|
||||
|
||||
if ('positive' === $method) {
|
||||
$array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->positive($amount));
|
||||
}
|
||||
if ('negative' === $method) {
|
||||
$array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($amount));
|
||||
}
|
||||
|
||||
// then process foreign amount, if it exists.
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$amount = (string) ($journal['foreign_amount'] ?? '0');
|
||||
$array[$foreignCurrencyId] ??= [
|
||||
'sum' => '0',
|
||||
'currency_id' => $foreignCurrencyId,
|
||||
'currency_name' => $foreignCurrencyName,
|
||||
'currency_symbol' => $foreignCurrencySymbol,
|
||||
'currency_code' => $foreignCurrencyCode,
|
||||
'currency_decimal_places' => $foreignCurrencyDecimalPlaces,
|
||||
];
|
||||
|
||||
if ('positive' === $method) {
|
||||
$array[$foreignCurrencyId]['sum'] = bcadd($array[$foreignCurrencyId]['sum'], app('steam')->positive($amount));
|
||||
}
|
||||
if ('negative' === $method) {
|
||||
$array[$foreignCurrencyId]['sum'] = bcadd($array[$foreignCurrencyId]['sum'], app('steam')->negative($amount));
|
||||
}
|
||||
}
|
||||
|
||||
// $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->{$method}($amount));
|
||||
// Log::debug(sprintf('Journal #%d adds amount %s %s', $journal['transaction_journal_id'], $currencyCode, $amount));
|
||||
}
|
||||
|
@@ -390,6 +390,25 @@ trait ConvertsDataTypes
|
||||
return (int) $string;
|
||||
}
|
||||
|
||||
protected function parseAccounts(mixed $array): array
|
||||
{
|
||||
if (!is_array($array)) {
|
||||
return [];
|
||||
}
|
||||
$return = [];
|
||||
foreach ($array as $entry) {
|
||||
if (!is_array($entry)) {
|
||||
continue;
|
||||
}
|
||||
$return[] = [
|
||||
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
|
||||
'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
protected function floatFromValue(?string $string): ?float
|
||||
{
|
||||
if (null === $string) {
|
||||
|
@@ -48,7 +48,7 @@ class Steam
|
||||
if (!in_array($type, $list, true)) {
|
||||
return null;
|
||||
}
|
||||
$result = $account->accountMeta->where('name', 'currency_id')->first();
|
||||
$result = $account->accountMeta()->where('name', 'currency_id')->first();
|
||||
if (null === $result) {
|
||||
return null;
|
||||
}
|
||||
@@ -76,8 +76,15 @@ class Steam
|
||||
|
||||
$balances = [];
|
||||
$formatted = $start->format('Y-m-d');
|
||||
Log::debug(sprintf('finalAccountBalanceInRange: Call finalAccountBalance with date/time "%s"', $start->toIso8601String()));
|
||||
$startBalance = $this->finalAccountBalance($account, $start);
|
||||
/*
|
||||
* To make sure the start balance is correct, we need to get the balance at the exact end of the previous day.
|
||||
* Since we just did "startOfDay" we can do subDay()->endOfDay() to get the correct moment.
|
||||
* THAT will be the start balance.
|
||||
*/
|
||||
$request = clone $start;
|
||||
$request->subDay()->endOfDay();
|
||||
Log::debug(sprintf('finalAccountBalanceInRange: Call finalAccountBalance with date/time "%s"', $request->toIso8601String()));
|
||||
$startBalance = $this->finalAccountBalance($account, $request);
|
||||
$nativeCurrency = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup);
|
||||
$accountCurrency = $this->getAccountCurrency($account);
|
||||
$hasCurrency = null !== $accountCurrency;
|
||||
@@ -141,6 +148,8 @@ class Steam
|
||||
$entryCurrency = $currencies[$entry->transaction_currency_id];
|
||||
|
||||
Log::debug(sprintf('Processing transaction(s) on moment %s', $carbon->format('Y-m-d H:i:s')));
|
||||
|
||||
// add amount to current balance in currency code.
|
||||
$currentBalance[$entryCurrency->code] ??= '0';
|
||||
$currentBalance[$entryCurrency->code] = bcadd($sumOfDay, $currentBalance[$entryCurrency->code]);
|
||||
|
||||
@@ -149,9 +158,14 @@ class Steam
|
||||
$currentBalance['balance'] = bcadd($currentBalance['balance'], $sumOfDay);
|
||||
}
|
||||
// if convert to native add the converted amount to "native_balance".
|
||||
// if there is a request to convert, convert to "native_balance" and use "balance" for whichever amount is in the native currency.
|
||||
if ($convertToNative) {
|
||||
$nativeSumOfDay = $converter->convert($entryCurrency, $nativeCurrency, $carbon, $sumOfDay);
|
||||
$currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $nativeSumOfDay);
|
||||
if ($currency->id === $entryCurrency->id) {
|
||||
$currentBalance['balance'] = bcadd($currentBalance['balance'], $sumOfDay);
|
||||
}
|
||||
|
||||
}
|
||||
// just set it.
|
||||
$balances[$carbonKey] = $currentBalance;
|
||||
@@ -274,21 +288,33 @@ class Steam
|
||||
* --> "native_balance": balance in the user's native balance, with all amounts converted to native.
|
||||
* "EUR": balance in EUR (or whatever currencies the account has balance in)
|
||||
*/
|
||||
public function finalAccountBalance(Account $account, Carbon $date): array
|
||||
public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $native = null, ?bool $convertToNative = null): array
|
||||
{
|
||||
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($account->id);
|
||||
$cache->addProperty($date);
|
||||
if ($cache->has()) {
|
||||
// Log::debug(sprintf('CACHED finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('CACHED finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||
if (null === $convertToNative) {
|
||||
$convertToNative = Amount::convertToNative($account->user);
|
||||
}
|
||||
if (null === $native) {
|
||||
$native = Amount::getNativeCurrencyByUserGroup($account->user->userGroup);
|
||||
}
|
||||
// account balance thing.
|
||||
$currencyPresent = isset($account->meta) && array_key_exists('currency', $account->meta) && null !== $account->meta['currency'];
|
||||
if ($currencyPresent) {
|
||||
$accountCurrency = $account->meta['currency'];
|
||||
}
|
||||
if (!$currencyPresent) {
|
||||
|
||||
$native = Amount::getNativeCurrencyByUserGroup($account->user->userGroup);
|
||||
$convertToNative = Amount::convertToNative($account->user);
|
||||
$accountCurrency = $this->getAccountCurrency($account);
|
||||
$accountCurrency = $this->getAccountCurrency($account);
|
||||
}
|
||||
$hasCurrency = null !== $accountCurrency;
|
||||
$currency = $hasCurrency ? $accountCurrency : $native;
|
||||
$return = [
|
||||
@@ -361,8 +387,8 @@ class Steam
|
||||
$defaultCurrency = app('amount')->getNativeCurrency();
|
||||
if ($convertToNative) {
|
||||
if ($defaultCurrency->id === $currency?->id) {
|
||||
Log::debug(sprintf('Unset "native_balance" and [%s] for account #%d', $defaultCurrency->code, $account->id));
|
||||
unset($set['native_balance'], $set[$defaultCurrency->code]);
|
||||
Log::debug(sprintf('Unset [%s] for account #%d (no longer unset "native_balance")', $defaultCurrency->code, $account->id));
|
||||
unset($set[$defaultCurrency->code]);
|
||||
}
|
||||
// todo rethink this logic.
|
||||
if (null !== $currency && $defaultCurrency->id !== $currency->id) {
|
||||
|
@@ -31,6 +31,7 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
@@ -61,26 +62,25 @@ class AccountTransformer extends AbstractTransformer
|
||||
*/
|
||||
public function transform(Account $account): array
|
||||
{
|
||||
$this->repository->setUser($account->user);
|
||||
if (null === $account->meta) {
|
||||
$account->meta = [];
|
||||
}
|
||||
|
||||
// get account type:
|
||||
|
||||
$fullType = $account->accountType->type;
|
||||
$accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType));
|
||||
$liabilityType = (string) config(sprintf('firefly.shortLiabilityNameByFullName.%s', $fullType));
|
||||
$accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $account->full_account_type));
|
||||
$liabilityType = (string) config(sprintf('firefly.shortLiabilityNameByFullName.%s', $account->full_account_type));
|
||||
$liabilityType = '' === $liabilityType ? null : strtolower($liabilityType);
|
||||
$liabilityDirection = $this->repository->getMetaValue($account, 'liability_direction');
|
||||
$convertToNative = Amount::convertToNative();
|
||||
|
||||
$liabilityDirection = $account->meta['liability_direction'] ?? null;
|
||||
// get account role (will only work if the type is asset).
|
||||
$native = Amount::getNativeCurrency();
|
||||
$accountRole = $this->getAccountRole($account, $accountType);
|
||||
|
||||
// date (for balance etc.)
|
||||
$date = $this->getDate();
|
||||
$date->endOfDay();
|
||||
|
||||
[$currencyId, $currencyCode, $currencySymbol, $decimalPlaces] = $this->getCurrency($account);
|
||||
[$creditCardType, $monthlyPaymentDate] = $this->getCCInfo($account, $accountRole, $accountType);
|
||||
[$openingBalance, $nativeOpeningBalance, $openingBalanceDate] = $this->getOpeningBalance($account, $accountType, $convertToNative);
|
||||
[$openingBalance, $nativeOpeningBalance, $openingBalanceDate] = $this->getOpeningBalance($account, $accountType);
|
||||
[$interest, $interestPeriod] = $this->getInterest($account, $accountType);
|
||||
|
||||
$native = $this->native;
|
||||
@@ -89,17 +89,13 @@ class AccountTransformer extends AbstractTransformer
|
||||
$native = null;
|
||||
}
|
||||
|
||||
$openingBalance = app('steam')->bcround($openingBalance, $decimalPlaces);
|
||||
$includeNetWorth = '0' !== $this->repository->getMetaValue($account, 'include_net_worth');
|
||||
$longitude = null;
|
||||
$latitude = null;
|
||||
$zoomLevel = null;
|
||||
$location = $this->repository->getLocation($account);
|
||||
if (null !== $location) {
|
||||
$longitude = $location->longitude;
|
||||
$latitude = $location->latitude;
|
||||
$zoomLevel = (int) $location->zoom_level;
|
||||
}
|
||||
$decimalPlaces = (int) $account->meta['currency']?->decimal_places;
|
||||
$decimalPlaces = 0 === $decimalPlaces ? 2 : $decimalPlaces;
|
||||
$openingBalance = Steam::bcround($openingBalance, $decimalPlaces);
|
||||
$includeNetWorth = 1 === (int) ($account->meta['include_net_worth'] ?? 0);
|
||||
$longitude = $account->meta['location']['longitude'] ?? null;
|
||||
$latitude = $account->meta['location']['latitude'] ?? null;
|
||||
$zoomLevel = $account->meta['location']['zoom_level'] ?? null;
|
||||
|
||||
// no order for some accounts:
|
||||
$order = $account->order;
|
||||
@@ -108,13 +104,13 @@ class AccountTransformer extends AbstractTransformer
|
||||
}
|
||||
// balance, native balance, virtual balance, native virtual balance?
|
||||
Log::debug(sprintf('transform: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$finalBalance = Steam::finalAccountBalance($account, $date);
|
||||
if ($convertToNative) {
|
||||
$finalBalance['balance'] = $finalBalance[$currencyCode] ?? '0';
|
||||
$finalBalance = Steam::finalAccountBalance($account, $date, $this->native, $this->convertToNative);
|
||||
if ($this->convertToNative) {
|
||||
$finalBalance['balance'] = $finalBalance[$account->meta['currency']?->code] ?? '0';
|
||||
}
|
||||
|
||||
$currentBalance = app('steam')->bcround($finalBalance['balance'] ?? '0', $decimalPlaces);
|
||||
$nativeCurrentBalance = $convertToNative ? app('steam')->bcround($finalBalance['native_balance'] ?? '0', $native->decimal_places) : null;
|
||||
$currentBalance = Steam::bcround($finalBalance['balance'] ?? '0', $decimalPlaces);
|
||||
$nativeCurrentBalance = $this->convertToNative ? Steam::bcround($finalBalance['native_balance'] ?? '0', $native->decimal_places) : null;
|
||||
|
||||
return [
|
||||
'id' => (string) $account->id,
|
||||
@@ -125,10 +121,10 @@ class AccountTransformer extends AbstractTransformer
|
||||
'name' => $account->name,
|
||||
'type' => strtolower($accountType),
|
||||
'account_role' => $accountRole,
|
||||
'currency_id' => $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
'currency_symbol' => $currencySymbol,
|
||||
'currency_decimal_places' => $decimalPlaces,
|
||||
'currency_id' => $account->meta['currency_id'] ?? null,
|
||||
'currency_code' => $account->meta['currency']?->code,
|
||||
'currency_symbol' => $account->meta['currency']?->symbol,
|
||||
'currency_decimal_places' => $account->meta['currency']?->decimal_places,
|
||||
'native_currency_id' => null === $native ? null : (string) $native->id,
|
||||
'native_currency_code' => $native?->code,
|
||||
'native_currency_symbol' => $native?->symbol,
|
||||
@@ -136,14 +132,14 @@ class AccountTransformer extends AbstractTransformer
|
||||
'current_balance' => $currentBalance,
|
||||
'native_current_balance' => $nativeCurrentBalance,
|
||||
'current_balance_date' => $date->toAtomString(),
|
||||
'notes' => $this->repository->getNoteText($account),
|
||||
'notes' => $account->meta['notes'] ?? null,
|
||||
'monthly_payment_date' => $monthlyPaymentDate,
|
||||
'credit_card_type' => $creditCardType,
|
||||
'account_number' => $this->repository->getMetaValue($account, 'account_number'),
|
||||
'account_number' => $account->meta['account_number'] ?? null,
|
||||
'iban' => '' === $account->iban ? null : $account->iban,
|
||||
'bic' => $this->repository->getMetaValue($account, 'BIC'),
|
||||
'virtual_balance' => app('steam')->bcround($account->virtual_balance, $decimalPlaces),
|
||||
'native_virtual_balance' => $this->convertToNative ? app('steam')->bcround($account->native_virtual_balance, $native->decimal_places) : null,
|
||||
'bic' => $account->meta['BIC'] ?? null,
|
||||
'virtual_balance' => Steam::bcround($account->virtual_balance, $decimalPlaces),
|
||||
'native_virtual_balance' => $this->convertToNative ? Steam::bcround($account->native_virtual_balance, $native->decimal_places) : null,
|
||||
'opening_balance' => $openingBalance,
|
||||
'native_opening_balance' => $nativeOpeningBalance,
|
||||
'opening_balance_date' => $openingBalanceDate,
|
||||
@@ -151,7 +147,7 @@ class AccountTransformer extends AbstractTransformer
|
||||
'liability_direction' => $liabilityDirection,
|
||||
'interest' => $interest,
|
||||
'interest_period' => $interestPeriod,
|
||||
'current_debt' => $this->repository->getMetaValue($account, 'current_debt'),
|
||||
'current_debt' => $account->meta['current_debt'] ?? null,
|
||||
'include_net_worth' => $includeNetWorth,
|
||||
'longitude' => $longitude,
|
||||
'latitude' => $latitude,
|
||||
@@ -159,7 +155,7 @@ class AccountTransformer extends AbstractTransformer
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'self',
|
||||
'uri' => '/accounts/'.$account->id,
|
||||
'uri' => sprintf('/accounts/%d', $account->id),
|
||||
],
|
||||
],
|
||||
];
|
||||
@@ -167,7 +163,7 @@ class AccountTransformer extends AbstractTransformer
|
||||
|
||||
private function getAccountRole(Account $account, string $accountType): ?string
|
||||
{
|
||||
$accountRole = $this->repository->getMetaValue($account, 'account_role');
|
||||
$accountRole = $account->meta['account_role'] ?? null;
|
||||
if ('asset' !== $accountType || '' === (string) $accountRole) {
|
||||
$accountRole = null;
|
||||
}
|
||||
@@ -188,29 +184,13 @@ class AccountTransformer extends AbstractTransformer
|
||||
return $date;
|
||||
}
|
||||
|
||||
private function getCurrency(Account $account): array
|
||||
{
|
||||
$currency = $this->repository->getAccountCurrency($account);
|
||||
|
||||
// only grab native when result is null:
|
||||
if (null === $currency) {
|
||||
$currency = $this->native;
|
||||
}
|
||||
$currencyId = (string) $currency->id;
|
||||
$currencyCode = $currency->code;
|
||||
$decimalPlaces = $currency->decimal_places;
|
||||
$currencySymbol = $currency->symbol;
|
||||
|
||||
return [$currencyId, $currencyCode, $currencySymbol, $decimalPlaces];
|
||||
}
|
||||
|
||||
private function getCCInfo(Account $account, ?string $accountRole, string $accountType): array
|
||||
{
|
||||
$monthlyPaymentDate = null;
|
||||
$creditCardType = null;
|
||||
if ('ccAsset' === $accountRole && 'asset' === $accountType) {
|
||||
$creditCardType = $this->repository->getMetaValue($account, 'cc_type');
|
||||
$monthlyPaymentDate = $this->repository->getMetaValue($account, 'cc_monthly_payment_date');
|
||||
$creditCardType = $account->meta['cc_type'] ?? null;
|
||||
$monthlyPaymentDate = $account->meta['cc_monthly_payment_date'] ?? null;
|
||||
}
|
||||
if (null !== $monthlyPaymentDate) {
|
||||
// try classic date:
|
||||
@@ -229,18 +209,16 @@ class AccountTransformer extends AbstractTransformer
|
||||
return [$creditCardType, $monthlyPaymentDate];
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO refactor call to get~OpeningBalanceAmount / Date because it is a lot of queries
|
||||
*/
|
||||
private function getOpeningBalance(Account $account, string $accountType, bool $convertToNative): array
|
||||
private function getOpeningBalance(Account $account, string $accountType): array
|
||||
{
|
||||
$openingBalance = null;
|
||||
$openingBalanceDate = null;
|
||||
$nativeOpeningBalance = null;
|
||||
if (in_array($accountType, ['asset', 'liabilities'], true)) {
|
||||
$openingBalance = $this->repository->getOpeningBalanceAmount($account, false);
|
||||
$nativeOpeningBalance = $this->repository->getOpeningBalanceAmount($account, true);
|
||||
$openingBalanceDate = $this->repository->getOpeningBalanceDate($account);
|
||||
// grab from meta.
|
||||
$openingBalance = $account->meta['opening_balance_amount'] ?? null;
|
||||
$nativeOpeningBalance = null;
|
||||
$openingBalanceDate = $account->meta['opening_balance_date'] ?? null;
|
||||
}
|
||||
if (null !== $openingBalanceDate) {
|
||||
$object = Carbon::createFromFormat('Y-m-d H:i:s', $openingBalanceDate, config('app.timezone'));
|
||||
@@ -248,6 +226,13 @@ class AccountTransformer extends AbstractTransformer
|
||||
$object = today(config('app.timezone'));
|
||||
}
|
||||
$openingBalanceDate = $object->toAtomString();
|
||||
|
||||
// NOW do conversion.
|
||||
if ($this->convertToNative && null !== $account->meta['currency']) {
|
||||
$converter = new ExchangeRateConverter();
|
||||
$nativeOpeningBalance = $converter->convert($account->meta['currency'], $this->native, $object, $openingBalance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [$openingBalance, $nativeOpeningBalance, $openingBalanceDate];
|
||||
@@ -258,8 +243,8 @@ class AccountTransformer extends AbstractTransformer
|
||||
$interest = null;
|
||||
$interestPeriod = null;
|
||||
if ('liabilities' === $accountType) {
|
||||
$interest = $this->repository->getMetaValue($account, 'interest');
|
||||
$interestPeriod = $this->repository->getMetaValue($account, 'interest_period');
|
||||
$interest = $account->meta['interest'] ?? null;
|
||||
$interestPeriod = $account->meta['interest_period'] ?? null;
|
||||
}
|
||||
|
||||
return [$interest, $interestPeriod];
|
||||
|
@@ -54,7 +54,7 @@ class PiggyBankEventTransformer extends AbstractTransformer
|
||||
public function transform(PiggyBankEvent $event): array
|
||||
{
|
||||
// get account linked to piggy bank
|
||||
$account = $event->piggyBank->account;
|
||||
$account = $event->piggyBank->accounts()->first();
|
||||
|
||||
// set up repositories.
|
||||
$this->repository->setUser($account->user);
|
||||
|
@@ -37,6 +37,7 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class TransactionGroupTransformer
|
||||
@@ -52,6 +53,7 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
Log::debug('TransactionGroupTransformer constructor.');
|
||||
$this->groupRepos = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->metaFields = [
|
||||
'sepa_cc',
|
||||
@@ -81,13 +83,14 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
$first = new NullArrayObject(reset($group['transactions']));
|
||||
|
||||
return [
|
||||
'id' => (int) $first['transaction_group_id'],
|
||||
'created_at' => $first['created_at']->toAtomString(),
|
||||
'updated_at' => $first['updated_at']->toAtomString(),
|
||||
'user' => (string) $data['user_id'],
|
||||
'group_title' => $data['title'],
|
||||
'transactions' => $this->transformTransactions($data),
|
||||
'links' => [
|
||||
'id' => (int) $first['transaction_group_id'],
|
||||
'created_at' => $first['created_at']->toAtomString(),
|
||||
'updated_at' => $first['updated_at']->toAtomString(),
|
||||
'user' => (string) $data['user_id'],
|
||||
'user_group' => (string) $data['user_group_id'],
|
||||
'group_title' => $data['title'],
|
||||
'transactions' => $this->transformTransactions($data),
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'self',
|
||||
'uri' => '/transactions/'.$first['transaction_group_id'],
|
||||
@@ -112,107 +115,96 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
*/
|
||||
private function transformTransaction(array $transaction): array
|
||||
{
|
||||
$row = new NullArrayObject($transaction);
|
||||
|
||||
// amount:
|
||||
$amount = app('steam')->positive((string) ($row['amount'] ?? '0'));
|
||||
$foreignAmount = null;
|
||||
if (null !== $row['foreign_amount'] && '' !== $row['foreign_amount'] && 0 !== bccomp('0', $row['foreign_amount'])) {
|
||||
$foreignAmount = app('steam')->positive($row['foreign_amount']);
|
||||
$amount = app('steam')->positive((string) ($transaction['amount'] ?? '0'));
|
||||
$foreignAmount = null;
|
||||
if (null !== $transaction['foreign_amount'] && '' !== $transaction['foreign_amount'] && 0 !== bccomp('0', $transaction['foreign_amount'])) {
|
||||
$foreignAmount = app('steam')->positive($transaction['foreign_amount']);
|
||||
}
|
||||
$type = $this->stringFromArray($transaction, 'transaction_type_type', TransactionTypeEnum::WITHDRAWAL->value);
|
||||
|
||||
$metaFieldData = $this->groupRepos->getMetaFields((int) $row['transaction_journal_id'], $this->metaFields);
|
||||
$metaDateData = $this->groupRepos->getMetaDateFields((int) $row['transaction_journal_id'], $this->metaDateFields);
|
||||
$type = $this->stringFromArray($transaction, 'transaction_type_type', TransactionTypeEnum::WITHDRAWAL->value);
|
||||
|
||||
$longitude = null;
|
||||
$latitude = null;
|
||||
$zoomLevel = null;
|
||||
$location = $this->getLocationById((int) $row['transaction_journal_id']);
|
||||
if (null !== $location) {
|
||||
$longitude = $location->longitude;
|
||||
$latitude = $location->latitude;
|
||||
$zoomLevel = $location->zoom_level;
|
||||
}
|
||||
// must be 0 (int) or NULL
|
||||
$recurrenceTotal = $transaction['meta']['recurrence_total'] ?? null;
|
||||
$recurrenceTotal = null !== $recurrenceTotal ? (int) $recurrenceTotal : null;
|
||||
$recurrenceCount = $transaction['meta']['recurrence_count'] ?? null;
|
||||
$recurrenceCount = null !== $recurrenceCount ? (int) $recurrenceCount : null;
|
||||
|
||||
return [
|
||||
'user' => (string) $row['user_id'],
|
||||
'transaction_journal_id' => (string) $row['transaction_journal_id'],
|
||||
'user' => (string) $transaction['user_id'],
|
||||
'transaction_journal_id' => (string) $transaction['transaction_journal_id'],
|
||||
'type' => strtolower($type),
|
||||
'date' => $row['date']->toAtomString(),
|
||||
'order' => $row['order'],
|
||||
'date' => $transaction['date']->toAtomString(),
|
||||
'order' => $transaction['order'],
|
||||
|
||||
'currency_id' => (string) $row['currency_id'],
|
||||
'currency_code' => $row['currency_code'],
|
||||
'currency_name' => $row['currency_name'],
|
||||
'currency_symbol' => $row['currency_symbol'],
|
||||
'currency_decimal_places' => (int) $row['currency_decimal_places'],
|
||||
'currency_id' => (string) $transaction['currency_id'],
|
||||
'currency_code' => $transaction['currency_code'],
|
||||
'currency_name' => $transaction['currency_name'],
|
||||
'currency_symbol' => $transaction['currency_symbol'],
|
||||
'currency_decimal_places' => (int) $transaction['currency_decimal_places'],
|
||||
|
||||
'foreign_currency_id' => $this->stringFromArray($transaction, 'foreign_currency_id', null),
|
||||
'foreign_currency_code' => $row['foreign_currency_code'],
|
||||
'foreign_currency_symbol' => $row['foreign_currency_symbol'],
|
||||
'foreign_currency_decimal_places' => $row['foreign_currency_decimal_places'],
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'],
|
||||
'foreign_currency_symbol' => $transaction['foreign_currency_symbol'],
|
||||
'foreign_currency_decimal_places' => $transaction['foreign_currency_decimal_places'],
|
||||
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => $foreignAmount,
|
||||
|
||||
'description' => $row['description'],
|
||||
'description' => $transaction['description'],
|
||||
|
||||
'source_id' => (string) $row['source_account_id'],
|
||||
'source_name' => $row['source_account_name'],
|
||||
'source_iban' => $row['source_account_iban'],
|
||||
'source_type' => $row['source_account_type'],
|
||||
'source_id' => (string) $transaction['source_account_id'],
|
||||
'source_name' => $transaction['source_account_name'],
|
||||
'source_iban' => $transaction['source_account_iban'],
|
||||
'source_type' => $transaction['source_account_type'],
|
||||
|
||||
'destination_id' => (string) $row['destination_account_id'],
|
||||
'destination_name' => $row['destination_account_name'],
|
||||
'destination_iban' => $row['destination_account_iban'],
|
||||
'destination_type' => $row['destination_account_type'],
|
||||
'destination_id' => (string) $transaction['destination_account_id'],
|
||||
'destination_name' => $transaction['destination_account_name'],
|
||||
'destination_iban' => $transaction['destination_account_iban'],
|
||||
'destination_type' => $transaction['destination_account_type'],
|
||||
|
||||
'budget_id' => $this->stringFromArray($transaction, 'budget_id', null),
|
||||
'budget_name' => $row['budget_name'],
|
||||
'budget_name' => $transaction['budget_name'],
|
||||
|
||||
'category_id' => $this->stringFromArray($transaction, 'category_id', null),
|
||||
'category_name' => $row['category_name'],
|
||||
'category_name' => $transaction['category_name'],
|
||||
|
||||
'bill_id' => $this->stringFromArray($transaction, 'bill_id', null),
|
||||
'bill_name' => $row['bill_name'],
|
||||
'bill_name' => $transaction['bill_name'],
|
||||
|
||||
'reconciled' => $row['reconciled'],
|
||||
'notes' => $this->groupRepos->getNoteText((int) $row['transaction_journal_id']),
|
||||
'tags' => $this->groupRepos->getTags((int) $row['transaction_journal_id']),
|
||||
'reconciled' => $transaction['reconciled'],
|
||||
'notes' => $transaction['notes'],
|
||||
'tags' => $transaction['tags'],
|
||||
|
||||
'internal_reference' => $metaFieldData['internal_reference'],
|
||||
'external_id' => $metaFieldData['external_id'],
|
||||
'original_source' => $metaFieldData['original_source'],
|
||||
'recurrence_id' => $this->stringFromArray($metaFieldData->getArrayCopy(), 'recurrence_id', null),
|
||||
'recurrence_total' => $this->integerFromArray($metaFieldData->getArrayCopy(), 'recurrence_total'),
|
||||
'recurrence_count' => $this->integerFromArray($metaFieldData->getArrayCopy(), 'recurrence_count'),
|
||||
'bunq_payment_id' => $metaFieldData['bunq_payment_id'],
|
||||
'external_url' => $metaFieldData['external_url'],
|
||||
'import_hash_v2' => $metaFieldData['import_hash_v2'],
|
||||
'internal_reference' => $transaction['meta']['internal_reference'] ?? null,
|
||||
'external_id' => $transaction['meta']['external_id'] ?? null,
|
||||
'original_source' => $transaction['meta']['original_source'] ?? null,
|
||||
'recurrence_id' => $transaction['meta']['recurrence_id'] ?? null,
|
||||
'recurrence_total' => $recurrenceTotal,
|
||||
'recurrence_count' => $recurrenceCount,
|
||||
'bunq_payment_id' => $transaction['meta']['bunq_payment_id'] ?? null,
|
||||
'external_url' => $transaction['meta']['external_url'] ?? null,
|
||||
'import_hash_v2' => $transaction['meta']['import_hash_v2'] ?? null,
|
||||
|
||||
'sepa_cc' => $metaFieldData['sepa_cc'],
|
||||
'sepa_ct_op' => $metaFieldData['sepa_ct_op'],
|
||||
'sepa_ct_id' => $metaFieldData['sepa_ct_id'],
|
||||
'sepa_db' => $metaFieldData['sepa_db'],
|
||||
'sepa_country' => $metaFieldData['sepa_country'],
|
||||
'sepa_ep' => $metaFieldData['sepa_ep'],
|
||||
'sepa_ci' => $metaFieldData['sepa_ci'],
|
||||
'sepa_batch_id' => $metaFieldData['sepa_batch_id'],
|
||||
|
||||
'interest_date' => $this->dateFromArray($metaDateData, 'interest_date'),
|
||||
'book_date' => $this->dateFromArray($metaDateData, 'book_date'),
|
||||
'process_date' => $this->dateFromArray($metaDateData, 'process_date'),
|
||||
'due_date' => $this->dateFromArray($metaDateData, 'due_date'),
|
||||
'payment_date' => $this->dateFromArray($metaDateData, 'payment_date'),
|
||||
'invoice_date' => $this->dateFromArray($metaDateData, 'invoice_date'),
|
||||
'sepa_cc' => $transaction['meta']['sepa_cc'] ?? null,
|
||||
'sepa_ct_op' => $transaction['meta']['sepa_ct_op'] ?? null,
|
||||
'sepa_ct_id' => $transaction['meta']['sepa_ct_id'] ?? null,
|
||||
'sepa_db' => $transaction['meta']['sepa_db'] ?? null,
|
||||
'sepa_country' => $transaction['meta']['sepa_country'] ?? null,
|
||||
'sepa_ep' => $transaction['meta']['sepa_ep'] ?? null,
|
||||
'sepa_ci' => $transaction['meta']['sepa_ci'] ?? null,
|
||||
'sepa_batch_id' => $transaction['meta']['sepa_batch_id'] ?? null,
|
||||
|
||||
'interest_date' => $transaction['meta_date']['interest_date'] ?? null,
|
||||
'book_date' => $transaction['meta_date']['book_date'] ?? null,
|
||||
'process_date' => $transaction['meta_date']['process_date'] ?? null,
|
||||
'due_date' => $transaction['meta_date']['due_date'] ?? null,
|
||||
'payment_date' => $transaction['meta_date']['payment_date'] ?? null,
|
||||
'invoice_date' => $transaction['meta_date']['invoice_date'] ?? null,
|
||||
// location data
|
||||
'longitude' => $longitude,
|
||||
'latitude' => $latitude,
|
||||
'zoom_level' => $zoomLevel,
|
||||
|
||||
'has_attachments' => $this->hasAttachments((int) $row['transaction_journal_id']),
|
||||
'longitude' => $transaction['location']['longitude'],
|
||||
'latitude' => $transaction['location']['latitude'],
|
||||
'zoom_level' => $transaction['location']['zoom_level'],
|
||||
'has_attachments' => $transaction['attachment_count'] > 0,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -239,40 +231,12 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getLocationById(int $journalId): ?Location
|
||||
{
|
||||
return $this->groupRepos->getLocation($journalId);
|
||||
}
|
||||
|
||||
private function getLocation(TransactionJournal $journal): ?Location
|
||||
{
|
||||
/** @var null|Location */
|
||||
return $journal->locations()->first();
|
||||
}
|
||||
|
||||
private function integerFromArray(array $array, string $key): ?int
|
||||
{
|
||||
if (array_key_exists($key, $array)) {
|
||||
return (int) $array[$key];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function dateFromArray(NullArrayObject $object, string $key): ?string
|
||||
{
|
||||
if (null === $object[$key]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $object[$key]->toAtomString();
|
||||
}
|
||||
|
||||
private function hasAttachments(int $journalId): bool
|
||||
{
|
||||
return $this->groupRepos->countAttachments($journalId) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
@@ -356,17 +320,17 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
|
||||
return [
|
||||
'user' => $journal->user_id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'transaction_journal_id' => (string) $journal->id,
|
||||
'type' => strtolower($type),
|
||||
'date' => $journal->date->toAtomString(),
|
||||
'order' => $journal->order,
|
||||
|
||||
'currency_id' => $currency->id,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
|
||||
'foreign_currency_id' => $foreignCurrency['id'],
|
||||
'foreign_currency_id' => (string) $foreignCurrency['id'],
|
||||
'foreign_currency_code' => $foreignCurrency['code'],
|
||||
'foreign_currency_symbol' => $foreignCurrency['symbol'],
|
||||
'foreign_currency_decimal_places' => $foreignCurrency['decimal_places'],
|
||||
@@ -376,23 +340,23 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
|
||||
'description' => $journal->description,
|
||||
|
||||
'source_id' => $source->account_id,
|
||||
'source_id' => (string) $source->account_id,
|
||||
'source_name' => $source->account->name,
|
||||
'source_iban' => $source->account->iban,
|
||||
'source_type' => $source->account->accountType->type,
|
||||
|
||||
'destination_id' => $destination->account_id,
|
||||
'destination_id' => (string) $destination->account_id,
|
||||
'destination_name' => $destination->account->name,
|
||||
'destination_iban' => $destination->account->iban,
|
||||
'destination_type' => $destination->account->accountType->type,
|
||||
|
||||
'budget_id' => $budget['id'],
|
||||
'budget_id' => (string) $budget['id'],
|
||||
'budget_name' => $budget['name'],
|
||||
|
||||
'category_id' => $category['id'],
|
||||
'category_id' => (string) $category['id'],
|
||||
'category_name' => $category['name'],
|
||||
|
||||
'bill_id' => $bill['id'],
|
||||
'bill_id' => (string) $bill['id'],
|
||||
'bill_name' => $bill['name'],
|
||||
|
||||
'reconciled' => $source->reconciled,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user