mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-27 05:51:56 +00:00
Compare commits
89 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05986cb6a6 | ||
|
|
0c4ee9f043 | ||
|
|
ff222795cf | ||
|
|
e0c76695ee | ||
|
|
ae126e8322 | ||
|
|
8f9c35fbe8 | ||
|
|
84efd6e2ee | ||
|
|
b1fbe4e909 | ||
|
|
8576877072 | ||
|
|
ac61a78d8d | ||
|
|
fce90a94c4 | ||
|
|
023a4f178d | ||
|
|
ef254995ad | ||
|
|
faeb74634b | ||
|
|
b5baae373f | ||
|
|
63de711cda | ||
|
|
bd28d116cb | ||
|
|
7efc2861bc | ||
|
|
5c689a2ca2 | ||
|
|
d5d65df76f | ||
|
|
df7d4f700c | ||
|
|
efebe3cb41 | ||
|
|
2ba5b6ae49 | ||
|
|
31d93efab2 | ||
|
|
657b95485c | ||
|
|
3bfc12f93b | ||
|
|
ccfd2f2ac3 | ||
|
|
fb3fe0d87b | ||
|
|
c80c6d52fe | ||
|
|
0fb3c0c7bf | ||
|
|
43c625bee2 | ||
|
|
967a5dd256 | ||
|
|
3c9d1bcaa1 | ||
|
|
8cd2de14a9 | ||
|
|
7728a35e04 | ||
|
|
49000da123 | ||
|
|
32a8f89875 | ||
|
|
49e5a81bd3 | ||
|
|
a8efe86af0 | ||
|
|
4f07b089d2 | ||
|
|
e786bf47c2 | ||
|
|
be11778c53 | ||
|
|
3d7325424c | ||
|
|
f4ffed99ef | ||
|
|
52dfe9a738 | ||
|
|
a0bc8b2ba2 | ||
|
|
4ffca9e2ca | ||
|
|
a6afec9afa | ||
|
|
5d859222f8 | ||
|
|
0e3ba14666 | ||
|
|
860767fe5a | ||
|
|
91b0ad625c | ||
|
|
67bab2561a | ||
|
|
b7908ebcb4 | ||
|
|
a20601ea85 | ||
|
|
14622329a8 | ||
|
|
5577be7b08 | ||
|
|
e3bab9d7d8 | ||
|
|
e0512bee3d | ||
|
|
20827a5fd1 | ||
|
|
8819dac1e1 | ||
|
|
da0a07262c | ||
|
|
9c195dcc66 | ||
|
|
0b45506e52 | ||
|
|
51e58f8d88 | ||
|
|
d0c658e79a | ||
|
|
35e0791a9f | ||
|
|
637ecc66d2 | ||
|
|
3a38175b2a | ||
|
|
d78fd86d7a | ||
|
|
395332d6dd | ||
|
|
c5cbceb81a | ||
|
|
ec94f1bcf1 | ||
|
|
ee3d18a8ea | ||
|
|
a9cd8b6512 | ||
|
|
5bd87036b0 | ||
|
|
0e7d72023d | ||
|
|
314f91ff24 | ||
|
|
ed54a5c9a4 | ||
|
|
5d35edb126 | ||
|
|
8bdfdc39cb | ||
|
|
d465b51da8 | ||
|
|
3344d2e5f3 | ||
|
|
0521da124e | ||
|
|
7e9c5a668f | ||
|
|
adbf785aba | ||
|
|
1fae39a49d | ||
|
|
659240a98b | ||
|
|
e9644c9679 |
13
.github/ISSUE_TEMPLATE/bug.yml
vendored
13
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Bug Report
|
||||
name: Bug report
|
||||
description: Report a bug in Firefly III (or associated tools)
|
||||
body:
|
||||
- type: checkboxes
|
||||
@@ -12,7 +12,7 @@ body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: I've found a bug and checked that ...
|
||||
description: Make sure that your request fulfills all of the following requirements. If one requirement cannot be satisfied, explain in detail why.
|
||||
description: Make sure that your request fulfills all of the following requirements. If one requirement cannot be satisfied, please explain why.
|
||||
options:
|
||||
- label: ... [the documentation](https://docs.firefly-iii.org/) does not mention anything about my problem
|
||||
- label: ... there are no open or closed issues that are related to my problem
|
||||
@@ -33,13 +33,6 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: Please describe precisely what you'd expect to happen. Be specific.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
@@ -54,4 +47,4 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional info
|
||||
description: Please provide any additional information that seem useful.
|
||||
description: Please provide any additional information that seems useful.
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/config.yml
vendored
3
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -3,3 +3,6 @@ contact_links:
|
||||
- name: Ask a question
|
||||
url: https://github.com/firefly-iii/firefly-iii/discussions
|
||||
about: Please ask and answer questions here.
|
||||
- name: I need support!
|
||||
url: https://github.com/firefly-iii/firefly-iii/discussions
|
||||
about: I think I broke something...
|
||||
|
||||
7
.github/ISSUE_TEMPLATE/fr.yml
vendored
7
.github/ISSUE_TEMPLATE/fr.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Feature Request
|
||||
name: Feature request
|
||||
description: Request a feature or enhancement in Firefly III (or associated tools)
|
||||
body:
|
||||
- type: checkboxes
|
||||
@@ -31,11 +31,6 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What are alternatives?
|
||||
description: Please describe what alternatives currently exist.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
|
||||
17
.github/workflows/release.yml
vendored
17
.github/workflows/release.yml
vendored
@@ -279,10 +279,20 @@ jobs:
|
||||
if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]] && [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then
|
||||
echo 'Describe the latest release'
|
||||
sudo chown -R runner:docker output.txt
|
||||
|
||||
# the changelog is in output.txt
|
||||
mv output.txt output2.txt
|
||||
|
||||
touch output.txt
|
||||
echo '' >> output.txt
|
||||
echo "Welcome to release $version of Firefly III. It contains the the latest fixes, translations and features. Docker users can find this release under the \`latest\` tag." >> output.txt
|
||||
echo '' >> output.txt
|
||||
|
||||
# add changelog to file.
|
||||
cat output2.txt >> output.txt
|
||||
echo '' >> output.txt
|
||||
rm -f output2.txt
|
||||
|
||||
echo '### Instructions' >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "* 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
|
||||
@@ -465,20 +475,27 @@ jobs:
|
||||
- name: Upload artifacts
|
||||
run: |
|
||||
# add zip file to release.
|
||||
echo "Upload $zipName to $releaseName"
|
||||
gh release upload $releaseName $zipName
|
||||
echo "Upload $tarName to $releaseName"
|
||||
gh release upload $releaseName $tarName
|
||||
|
||||
# add sha256 sum to release
|
||||
echo "Upload $zipName.sha256 to $releaseName"
|
||||
gh release upload $releaseName $zipName.sha256
|
||||
echo "Upload $tarName.sha256 to $releaseName"
|
||||
gh release upload $releaseName $tarName.sha256
|
||||
|
||||
# add signatures to release
|
||||
echo "Upload $zipName.asc to $releaseName"
|
||||
gh release upload $releaseName $zipName.asc
|
||||
echo "Upload $tarName.asc to $releaseName"
|
||||
gh release upload $releaseName $tarName.asc
|
||||
|
||||
# get current HEAD and add as file to the release
|
||||
HEAD=$(git rev-parse HEAD)
|
||||
echo $HEAD > HEAD.txt
|
||||
echo "Upload HEAD.txt to $releaseName"
|
||||
gh release upload $releaseName HEAD.txt
|
||||
|
||||
# remove all temporary files
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
||||
|
||||
use Deprecated;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
@@ -83,9 +84,8 @@ class CurrencyController extends Controller
|
||||
/**
|
||||
* Documentation for this endpoint is at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getCurrenciesCodeAC
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function currenciesWithCode(AutocompleteRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
use FireflyIII\Exceptions\ValidationException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
@@ -35,6 +36,7 @@ use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Chart\ChartData;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\ApiSupport;
|
||||
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
|
||||
@@ -139,7 +141,7 @@ class AccountController extends Controller
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/charts/getChartAccountOverview
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
{
|
||||
@@ -160,7 +162,7 @@ class AccountController extends Controller
|
||||
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
||||
|
||||
/** @var Preference $frontpage */
|
||||
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
|
||||
$frontpage = Preferences::get('frontpageAccounts', $defaultSet);
|
||||
|
||||
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
|
||||
$frontpage->data = $defaultSet;
|
||||
|
||||
@@ -212,7 +212,7 @@ class BudgetController extends Controller
|
||||
*/
|
||||
private function budgetLimits(Budget $budget, Collection $limits): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in budgetLimits(#%d)', $budget->id));
|
||||
Log::debug(sprintf('Now in budgetLimits(#%d)', $budget->id));
|
||||
$data = [];
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
@@ -233,16 +233,11 @@ class BudgetController extends Controller
|
||||
$end->endOfDay();
|
||||
$spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
|
||||
$limitCurrencyId = $limit->transaction_currency_id;
|
||||
$filtered = [];
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($spent as $currencyId => $entry) {
|
||||
// only spent the entry where the entry's currency matches the budget limit's currency
|
||||
// so $filtered will only have 1 or 0 entries
|
||||
if ($entry['currency_id'] === $limitCurrencyId) {
|
||||
$filtered[$currencyId] = $entry;
|
||||
}
|
||||
}
|
||||
// only spent the entry where the entry's currency matches the budget limit's currency
|
||||
// so $filtered will only have 1 or 0 entries
|
||||
$filtered = array_filter($spent, fn ($entry) => $entry['currency_id'] === $limitCurrencyId);
|
||||
$result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
|
||||
if (1 === count($result)) {
|
||||
$compare = bccomp($limit->amount, (string) app('steam')->positive($result[$limitCurrencyId]['spent']));
|
||||
|
||||
@@ -127,7 +127,6 @@ abstract class Controller extends BaseController
|
||||
Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field));
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
$value = null;
|
||||
}
|
||||
$obj = null;
|
||||
if (null !== $date) {
|
||||
|
||||
@@ -64,7 +64,7 @@ class DestroyController extends Controller
|
||||
public function destroy(DestroyRequest $request): JsonResponse
|
||||
{
|
||||
$objects = $request->getObjects();
|
||||
$this->unused = $request->boolean('unused', false);
|
||||
$this->unused = $request->boolean('unused');
|
||||
|
||||
$allExceptAssets = [AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::REVENUE->value];
|
||||
$all = [AccountTypeEnum::ASSET->value, AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::RECONCILIATION->value];
|
||||
@@ -176,14 +176,14 @@ class DestroyController extends Controller
|
||||
foreach ($collection as $account) {
|
||||
$count = $account->transactions()->count();
|
||||
if (true === $this->unused && 0 === $count) {
|
||||
app('log')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
||||
Log::info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
||||
Log::channel('audit')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
||||
$service->destroy($account, null);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (false === $this->unused) {
|
||||
app('log')->info(sprintf('Deleting account #%d "%s"', $account->id, $account->name));
|
||||
Log::info(sprintf('Deleting account #%d "%s"', $account->id, $account->name));
|
||||
Log::channel('audit')->warning(sprintf('Deleted account #%d "%s"', $account->id, $account->name));
|
||||
$service->destroy($account, null);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Data\Export\ExportRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\Export\ExportDataGenerator;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
use Safe\Exceptions\DatetimeException;
|
||||
|
||||
use function Safe\date;
|
||||
|
||||
@@ -72,6 +73,7 @@ class ExportController extends Controller
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
* @throws DatetimeException
|
||||
*/
|
||||
private function returnExport(string $key): LaravelResponse
|
||||
{
|
||||
|
||||
@@ -32,6 +32,7 @@ use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
/**
|
||||
@@ -67,7 +68,7 @@ class UpdateController extends Controller
|
||||
*/
|
||||
public function update(UpdateRequest $request, Account $account): JsonResponse
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$data = $request->getUpdateData();
|
||||
$data['type'] = config('firefly.shortNamesByFullName.'.$account->accountType->type);
|
||||
$account = $this->repository->update($account, $data);
|
||||
|
||||
@@ -80,7 +80,7 @@ class StoreController extends Controller
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$data = $request->getAll();
|
||||
$attachment = $this->repository->store($data);
|
||||
$manager = $this->getManager();
|
||||
@@ -109,13 +109,13 @@ class StoreController extends Controller
|
||||
$helper = app(AttachmentHelperInterface::class);
|
||||
$body = $request->getContent();
|
||||
if ('' === $body) {
|
||||
app('log')->error('Body of attachment is empty.');
|
||||
Log::error('Body of attachment is empty.');
|
||||
|
||||
return response()->json([], 422);
|
||||
}
|
||||
$result = $helper->saveAttachmentFromApi($attachment, $body);
|
||||
if (false === $result) {
|
||||
app('log')->error('Could not save attachment from API.');
|
||||
Log::error('Could not save attachment from API.');
|
||||
|
||||
return response()->json([], 422);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ class StoreController extends Controller
|
||||
$data = $request->getAll();
|
||||
$data['start_date'] = $data['start'];
|
||||
$data['end_date'] = $data['end'];
|
||||
$data['notes'] = $data['notes'];
|
||||
$data['budget_id'] = $budget->id;
|
||||
|
||||
$budgetLimit = $this->blRepository->store($data);
|
||||
|
||||
@@ -34,6 +34,7 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepository;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class DestroyController
|
||||
@@ -73,7 +74,7 @@ class DestroyController extends Controller
|
||||
*/
|
||||
public function destroy(TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
// grab asset account(s) from group:
|
||||
$accounts = [];
|
||||
|
||||
@@ -95,7 +96,7 @@ class DestroyController extends Controller
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
app('log')->debug(sprintf('Now going to trigger updated account event for account #%d', $account->id));
|
||||
Log::debug(sprintf('Now going to trigger updated account event for account #%d', $account->id));
|
||||
event(new UpdatedAccount($account));
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class StoreController extends Controller
|
||||
*/
|
||||
public function store(StoreRequest $request): JsonResponse
|
||||
{
|
||||
app('log')->debug('Now in API StoreController::store()');
|
||||
Log::debug('Now in API StoreController::store()');
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user();
|
||||
$data['user_group'] = $this->userGroup;
|
||||
@@ -95,13 +95,13 @@ class StoreController extends Controller
|
||||
try {
|
||||
$transactionGroup = $this->groupRepository->store($data);
|
||||
} catch (DuplicateTransactionException $e) {
|
||||
app('log')->warning('Caught a duplicate transaction. Return error message.');
|
||||
Log::warning('Caught a duplicate transaction. Return error message.');
|
||||
$validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
|
||||
throw new ValidationException($validator);
|
||||
} catch (FireflyException $e) {
|
||||
app('log')->warning('Caught an exception. Return error message.');
|
||||
app('log')->error($e->getMessage());
|
||||
Log::warning('Caught an exception. Return error message.');
|
||||
Log::error($e->getMessage());
|
||||
$message = sprintf('Internal exception: %s', $e->getMessage());
|
||||
$validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
@@ -71,22 +72,25 @@ class UpdateController extends Controller
|
||||
*/
|
||||
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
app('log')->debug('Now in update routine for transaction group');
|
||||
$data = $request->getAll();
|
||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||
$manager = $this->getManager();
|
||||
Log::debug('Now in update routine for transaction group');
|
||||
$data = $request->getAll();
|
||||
$oldHash = $this->groupRepository->getCompareHash($transactionGroup);
|
||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||
$newHash = $this->groupRepository->getCompareHash($transactionGroup);
|
||||
$manager = $this->getManager();
|
||||
|
||||
app('preferences')->mark();
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks));
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
$runRecalculations = $oldHash !== $newHash;
|
||||
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, $runRecalculations));
|
||||
|
||||
/** @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)
|
||||
// filter on transaction group.
|
||||
@@ -95,20 +99,20 @@ class UpdateController extends Controller
|
||||
->withAPIInformation()
|
||||
;
|
||||
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
/**
|
||||
* Class DestroyController
|
||||
@@ -65,6 +66,7 @@ class DestroyController extends Controller
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function destroy(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
|
||||
@@ -250,10 +250,8 @@ class ListController extends Controller
|
||||
$collection = $unfiltered->filter(
|
||||
static function (Recurrence $recurrence) use ($currency) { // @phpstan-ignore-line
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($recurrence->recurrenceTransactions as $transaction) {
|
||||
if ($transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id) {
|
||||
return $recurrence;
|
||||
}
|
||||
if (array_any($recurrence->recurrenceTransactions, fn ($transaction) => $transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id)) {
|
||||
return $recurrence;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -297,10 +295,8 @@ class ListController extends Controller
|
||||
$collection = $unfiltered->filter(
|
||||
static function (Rule $rule) use ($currency) { // @phpstan-ignore-line
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
if ('currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value) {
|
||||
return $rule;
|
||||
}
|
||||
if (array_any($rule->ruleTriggers, fn ($trigger) => 'currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value)) {
|
||||
return $rule;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -27,13 +27,13 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionLinkType;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\TransactionLinkType\StoreRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\LinkTypeTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
/**
|
||||
@@ -71,7 +71,7 @@ class StoreController extends Controller
|
||||
*
|
||||
* Store new object.
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function store(StoreRequest $request): JsonResponse
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\LinkTypeTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
/**
|
||||
@@ -73,6 +74,7 @@ class UpdateController extends Controller
|
||||
* Update object.
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function update(UpdateRequest $request, LinkType $linkType): JsonResponse
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
|
||||
use FireflyIII\Transformers\UserGroupTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UpdateController extends Controller
|
||||
{
|
||||
@@ -54,7 +55,7 @@ class UpdateController extends Controller
|
||||
|
||||
public function update(UpdateRequest $request, UserGroup $userGroup): JsonResponse
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$data = $request->getData();
|
||||
$userGroup = $this->repository->update($userGroup, $data);
|
||||
$userGroup->refresh();
|
||||
|
||||
@@ -34,6 +34,7 @@ use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
|
||||
@@ -71,7 +72,7 @@ class AccountController extends Controller
|
||||
if ('' === $query || !in_array($field, $this->validFields, true)) {
|
||||
return response(null, 422);
|
||||
}
|
||||
app('log')->debug(sprintf('Now in account search("%s", "%s")', $field, $query));
|
||||
Log::debug(sprintf('Now in account search("%s", "%s")', $field, $query));
|
||||
$types = $this->mapAccountTypes($type);
|
||||
|
||||
/** @var AccountSearch $search */
|
||||
|
||||
@@ -130,8 +130,6 @@ class BasicController extends Controller
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
// prep some arrays:
|
||||
$incomes = [];
|
||||
$expenses = [];
|
||||
$sums = [];
|
||||
$return = [];
|
||||
$currencies = [
|
||||
|
||||
@@ -24,6 +24,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\System;
|
||||
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\System\UpdateRequest;
|
||||
@@ -31,6 +33,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Binder\EitherConfigKey;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
/**
|
||||
* Class ConfigurationController
|
||||
@@ -65,8 +68,8 @@ class ConfigurationController extends Controller
|
||||
try {
|
||||
$dynamicData = $this->getDynamicConfiguration();
|
||||
} catch (FireflyException $e) {
|
||||
app('log')->error($e->getMessage());
|
||||
app('log')->error($e->getTraceAsString());
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
|
||||
throw new FireflyException('200030: Could not load config variables.', 0, $e);
|
||||
}
|
||||
@@ -92,13 +95,15 @@ class ConfigurationController extends Controller
|
||||
|
||||
/**
|
||||
* Get all config values.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getDynamicConfiguration(): array
|
||||
{
|
||||
$isDemoSite = app('fireflyconfig')->get('is_demo_site');
|
||||
$updateCheck = app('fireflyconfig')->get('permission_update_check');
|
||||
$lastCheck = app('fireflyconfig')->get('last_update_check');
|
||||
$singleUser = app('fireflyconfig')->get('single_user_mode');
|
||||
$isDemoSite = FireflyConfig::get('is_demo_site');
|
||||
$updateCheck = FireflyConfig::get('permission_update_check');
|
||||
$lastCheck = FireflyConfig::get('last_update_check');
|
||||
$singleUser = FireflyConfig::get('single_user_mode');
|
||||
|
||||
return [
|
||||
'is_demo_site' => $isDemoSite?->data,
|
||||
@@ -153,6 +158,7 @@ class ConfigurationController extends Controller
|
||||
* Update the configuration.
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function update(UpdateRequest $request, string $name): JsonResponse
|
||||
{
|
||||
@@ -164,7 +170,7 @@ class ConfigurationController extends Controller
|
||||
$data = $request->getAll();
|
||||
$shortName = str_replace('configuration.', '', $name);
|
||||
|
||||
app('fireflyconfig')->set($shortName, $data['value']);
|
||||
FireflyConfig::set($shortName, $data['value']);
|
||||
|
||||
// get updated config:
|
||||
$newConfig = $this->getDynamicConfiguration();
|
||||
|
||||
@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\System\CronRequest;
|
||||
use FireflyIII\Support\Http\Controllers\CronRunner;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class CronController
|
||||
@@ -44,8 +45,8 @@ class CronController extends Controller
|
||||
{
|
||||
$config = $request->getAll();
|
||||
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
app('log')->debug(sprintf('Date is %s', $config['date']->toIsoString()));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Date is %s', $config['date']->toIsoString()));
|
||||
$return = [];
|
||||
$return['recurring_transactions'] = $this->runRecurring($config['force'], $config['date']);
|
||||
$return['auto_budgets'] = $this->runAutoBudget($config['force'], $config['date']);
|
||||
|
||||
@@ -33,6 +33,7 @@ use FireflyIII\Transformers\UserTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
@@ -174,7 +175,7 @@ class UserController extends Controller
|
||||
|
||||
// can only update 'blocked' when user is admin.
|
||||
if (!$this->repository->hasRole(auth()->user(), 'owner')) {
|
||||
app('log')->debug('Quietly drop fields "blocked" and "blocked_code" from request.');
|
||||
Log::debug('Quietly drop fields "blocked" and "blocked_code" from request.');
|
||||
unset($data['blocked'], $data['blocked_code']);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ class ShowController extends Controller
|
||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||
}
|
||||
|
||||
app('log')->debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id));
|
||||
Log::debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id));
|
||||
Log::channel('audit')->info(sprintf('User triggers webhook #%d on transaction group #%d.', $webhook->id, $group->id));
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
@@ -155,7 +155,7 @@ class ShowController extends Controller
|
||||
$engine->generateMessages();
|
||||
|
||||
// trigger event to send them:
|
||||
app('log')->debug('send event RequestedSendWebhookMessages');
|
||||
Log::debug('send event RequestedSendWebhookMessages');
|
||||
event(new RequestedSendWebhookMessages());
|
||||
|
||||
return response()->json([], 204);
|
||||
|
||||
@@ -76,6 +76,6 @@ class SubmitController extends Controller
|
||||
SendWebhookMessage::dispatch($message)->afterResponse();
|
||||
}
|
||||
|
||||
return response()->json([]);
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ class TransactionRequest extends FormRequest
|
||||
'query' => json_decode($this->get('query'), true, 8, JSON_THROW_ON_ERROR),
|
||||
];
|
||||
} catch (JsonException $e) {
|
||||
// dont really care. the validation should catch invalid json.
|
||||
app('log')->error($e->getMessage());
|
||||
// don't really care. the validation should catch invalid json.
|
||||
Log::error($e->getMessage());
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
@@ -47,7 +47,7 @@ class StoreRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
app('log')->debug('Raw fields in Bill StoreRequest', $this->all());
|
||||
Log::debug('Raw fields in Bill StoreRequest', $this->all());
|
||||
$fields = [
|
||||
'name' => ['name', 'convertString'],
|
||||
'amount_min' => ['amount_min', 'convertString'],
|
||||
@@ -128,7 +128,6 @@ class StoreRequest extends FormRequest
|
||||
$failed = $validator->fails();
|
||||
} catch (TypeError $e) {
|
||||
Log::error($e->getMessage());
|
||||
$failed = false;
|
||||
}
|
||||
if ($failed) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
|
||||
|
||||
@@ -76,7 +76,7 @@ class StoreRequest extends FormRequest
|
||||
|
||||
/**
|
||||
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
||||
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||
* standards, but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
|
||||
@@ -122,7 +122,7 @@ class UpdateRequest extends FormRequest
|
||||
|
||||
/**
|
||||
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
||||
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||
* standards, but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
|
||||
@@ -58,7 +58,7 @@ class StoreRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
app('log')->debug('get all data in TransactionStoreRequest');
|
||||
Log::debug('get all data in TransactionStoreRequest');
|
||||
|
||||
return [
|
||||
'group_title' => $this->convertString('group_title'),
|
||||
@@ -175,7 +175,7 @@ class StoreRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
app('log')->debug('Collect rules of TransactionStoreRequest');
|
||||
Log::debug('Collect rules of TransactionStoreRequest');
|
||||
$validProtocols = config('firefly.valid_url_protocols');
|
||||
$locationRules = Location::requestRules([]);
|
||||
|
||||
@@ -276,9 +276,9 @@ class StoreRequest extends FormRequest
|
||||
$this->validateTransactionArray($validator);
|
||||
|
||||
// must submit at least one transaction.
|
||||
app('log')->debug('Now going to validateOneTransaction');
|
||||
Log::debug('Now going to validateOneTransaction');
|
||||
$this->validateOneTransaction($validator);
|
||||
app('log')->debug('Now done with validateOneTransaction');
|
||||
Log::debug('Now done with validateOneTransaction');
|
||||
|
||||
// all journals must have a description
|
||||
$this->validateDescriptions($validator);
|
||||
|
||||
@@ -183,7 +183,7 @@ class UpdateRequest extends FormRequest
|
||||
foreach ($this->dateFields as $fieldName) {
|
||||
app('log')->debug(sprintf('Now at date field %s', $fieldName));
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
|
||||
Log::debug(sprintf('New value: "%s"', $transaction[$fieldName]));
|
||||
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\UserGroup;
|
||||
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
@@ -53,9 +52,6 @@ class UpdateRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
/** @var UserGroup $userGroup */
|
||||
$userGroup = $this->route()->parameter('userGroup');
|
||||
|
||||
return [
|
||||
'title' => ['required', 'min:1', 'max:255'],
|
||||
'native_currency_id' => 'exists:transaction_currencies,id',
|
||||
|
||||
@@ -39,7 +39,6 @@ use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
@@ -82,7 +81,7 @@ class Controller extends BaseController
|
||||
|
||||
try {
|
||||
$page = (int) request()->get('page');
|
||||
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
|
||||
} catch (ContainerExceptionInterface) {
|
||||
$page = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ class ListController extends Controller
|
||||
*/
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
return response()->json([]);
|
||||
return response()->json();
|
||||
// throw new FireflyException('Needs refactoring, move to IndexController.');
|
||||
// $pageSize = $this->parameters->get('limit');
|
||||
// $dates = $request->getAll();
|
||||
|
||||
@@ -70,7 +70,7 @@ class UpdateController extends Controller
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
|
||||
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks));
|
||||
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, true));
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var User $admin */
|
||||
|
||||
@@ -31,6 +31,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Transformers\CurrencyTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class IndexController extends Controller
|
||||
{
|
||||
@@ -56,6 +57,7 @@ class IndexController extends Controller
|
||||
public function index(IndexRequest $request): JsonResponse
|
||||
{
|
||||
$settings = $request->getAll();
|
||||
$currencies = new Collection();
|
||||
if (true === $settings['enabled']) {
|
||||
$currencies = $this->repository->get();
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ class UpdateRequest extends Request
|
||||
#[Override]
|
||||
public function getAll(): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$this->integerFields = ['order', 'currency_id', 'foreign_currency_id', 'transaction_journal_id', 'source_id', 'destination_id', 'budget_id', 'category_id', 'bill_id', 'recurrence_id'];
|
||||
$this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||
$this->textareaFields = ['notes'];
|
||||
@@ -101,7 +101,7 @@ class UpdateRequest extends Request
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$return = [];
|
||||
|
||||
/** @var null|array $transactions */
|
||||
@@ -185,9 +185,9 @@ class UpdateRequest extends Request
|
||||
private function getDateData(array $current, array $transaction): array
|
||||
{
|
||||
foreach ($this->dateFields as $fieldName) {
|
||||
app('log')->debug(sprintf('Now at date field %s', $fieldName));
|
||||
Log::debug(sprintf('Now at date field %s', $fieldName));
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
|
||||
Log::debug(sprintf('New value: "%s"', $transaction[$fieldName]));
|
||||
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
@@ -252,7 +252,7 @@ class UpdateRequest extends Request
|
||||
#[Override]
|
||||
public function rules(): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$validProtocols = config('firefly.valid_url_protocols');
|
||||
|
||||
return [
|
||||
@@ -336,7 +336,7 @@ class UpdateRequest extends Request
|
||||
#[Override]
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
app('log')->debug('Now in withValidator');
|
||||
Log::debug('Now in withValidator');
|
||||
|
||||
/** @var TransactionGroup $transactionGroup */
|
||||
$transactionGroup = $this->route()->parameter('userGroupTransaction');
|
||||
|
||||
@@ -58,7 +58,8 @@ class CorrectsGroupAccounts extends Command
|
||||
$handler = new UpdatedGroupEventHandler();
|
||||
foreach ($groups as $groupId) {
|
||||
$group = TransactionGroup::find($groupId);
|
||||
$event = new UpdatedTransactionGroup($group, true, true);
|
||||
// TODO in theory the "unifyAccounts" method could lead to the need for run recalculations.
|
||||
$event = new UpdatedTransactionGroup($group, true, true, false);
|
||||
$handler->unifyAccounts($event);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class CorrectsIbans extends Command
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$accounts = Account::whereNotNull('iban')->get();
|
||||
$accounts = Account::with('accountMeta')->get();
|
||||
$this->filterIbans($accounts);
|
||||
$this->countAndCorrectIbans($accounts);
|
||||
|
||||
@@ -54,14 +54,26 @@ class CorrectsIbans extends Command
|
||||
{
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$iban = (string) $account->iban;
|
||||
$newIban = app('steam')->filterSpaces($iban);
|
||||
$iban = (string) $account->iban;
|
||||
$newIban = app('steam')->filterSpaces($iban);
|
||||
if ('' !== $iban && $iban !== $newIban) {
|
||||
$account->iban = $newIban;
|
||||
$account->save();
|
||||
$this->friendlyInfo(sprintf('Removed spaces from IBAN of account #%d', $account->id));
|
||||
++$this->count;
|
||||
}
|
||||
// same for account number:
|
||||
$accountNumber = $account->accountMeta->where('name', 'account_number')->first();
|
||||
if (null !== $accountNumber) {
|
||||
$number = (string) $accountNumber->value;
|
||||
$newNumber = app('steam')->filterSpaces($number);
|
||||
if ('' !== $number && $number !== $newNumber) {
|
||||
$accountNumber->value = $newNumber;
|
||||
$accountNumber->save();
|
||||
$this->friendlyInfo(sprintf('Removed spaces from account number of account #%d', $account->id));
|
||||
++$this->count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Models\AccountBalanceCalculator;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -140,6 +141,7 @@ class CorrectsUnevenAmount extends Command
|
||||
/** @var stdClass $entry */
|
||||
foreach ($journals as $entry) {
|
||||
$sum = (string) $entry->the_sum;
|
||||
$sum = Steam::floatalize($sum);
|
||||
if (!is_numeric($sum)
|
||||
|| '' === $sum // @phpstan-ignore-line
|
||||
|| str_contains($sum, 'e')
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands\Integrity;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
@@ -60,6 +61,8 @@ class ReportsSums extends Command
|
||||
$foreign = (string) $user->transactions()->selectRaw('SUM(foreign_amount) as total')->value('total');
|
||||
$sum = '' === $sum ? '0' : $sum;
|
||||
$foreign = '' === $foreign ? '0' : $foreign;
|
||||
$sum = Steam::floatalize($sum);
|
||||
$foreign = Steam::floatalize($foreign);
|
||||
$total = bcadd($sum, $foreign);
|
||||
|
||||
if (0 !== bccomp($total, '0')) {
|
||||
|
||||
@@ -87,6 +87,12 @@ class UpgradesMultiPiggyBanks extends Command
|
||||
|
||||
private function upgradePiggyBank(PiggyBank $piggyBank): void
|
||||
{
|
||||
if (null === $piggyBank->account) {
|
||||
// #10432 account has been deleted, delete piggy bank.
|
||||
$piggyBank->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
$this->repository->setUser($piggyBank->account->user);
|
||||
$this->accountRepository->setUser($piggyBank->account->user);
|
||||
$repetition = $this->repository->getRepetition($piggyBank, true);
|
||||
|
||||
16
app/Events/Model/PiggyBank/ChangedName.php
Normal file
16
app/Events/Model/PiggyBank/ChangedName.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events\Model\PiggyBank;
|
||||
|
||||
use FireflyIII\Events\Event;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ChangedName extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public function __construct(public PiggyBank $piggyBank, public string $oldName, public string $newName) {}
|
||||
}
|
||||
@@ -37,5 +37,5 @@ class UpdatedTransactionGroup extends Event
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*/
|
||||
public function __construct(public TransactionGroup $transactionGroup, public bool $applyRules, public bool $fireWebhooks) {}
|
||||
public function __construct(public TransactionGroup $transactionGroup, public bool $applyRules, public bool $fireWebhooks, public bool $runRecalculations) {}
|
||||
}
|
||||
|
||||
@@ -58,11 +58,13 @@ use function Safe\parse_url;
|
||||
*/
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
public static ?Throwable $lastError = null;
|
||||
|
||||
/**
|
||||
* @var array<int, class-string<Throwable>>
|
||||
*/
|
||||
protected $dontReport
|
||||
= [
|
||||
= [
|
||||
AuthenticationException::class,
|
||||
LaravelValidationException::class,
|
||||
NotFoundHttpException::class,
|
||||
@@ -123,7 +125,7 @@ class Handler extends ExceptionHandler
|
||||
// somehow Laravel handler does not catch this:
|
||||
app('log')->debug('Return JSON unauthenticated error.');
|
||||
|
||||
return response()->json(['message' => 'Unauthenticated', 'exception' => 'AuthenticationException'], 401);
|
||||
return response()->json(['message' => $e->getMessage(), 'exception' => 'AuthenticationException'], 401);
|
||||
}
|
||||
|
||||
if ($e instanceof OAuthServerException && $expectsJson) {
|
||||
@@ -215,13 +217,14 @@ class Handler extends ExceptionHandler
|
||||
#[Override]
|
||||
public function report(Throwable $e): void
|
||||
{
|
||||
$doMailError = (bool) config('firefly.send_error_message');
|
||||
self::$lastError = $e;
|
||||
$doMailError = (bool) config('firefly.send_error_message');
|
||||
if ($this->shouldntReportLocal($e) || !$doMailError) {
|
||||
parent::report($e);
|
||||
|
||||
return;
|
||||
}
|
||||
$userData = [
|
||||
$userData = [
|
||||
'id' => 0,
|
||||
'email' => 'unknown@example.com',
|
||||
];
|
||||
@@ -230,9 +233,9 @@ class Handler extends ExceptionHandler
|
||||
$userData['email'] = auth()->user()->email;
|
||||
}
|
||||
|
||||
$headers = request()->headers->all();
|
||||
$headers = request()->headers->all();
|
||||
|
||||
$data = [
|
||||
$data = [
|
||||
'class' => $e::class,
|
||||
'errorMessage' => $e->getMessage(),
|
||||
'time' => Carbon::now()->format('r'),
|
||||
@@ -250,8 +253,8 @@ class Handler extends ExceptionHandler
|
||||
];
|
||||
|
||||
// create job that will mail.
|
||||
$ipAddress = request()->ip() ?? '0.0.0.0';
|
||||
$job = new MailError($userData, (string) config('firefly.site_owner'), $ipAddress, $data);
|
||||
$ipAddress = request()->ip() ?? '0.0.0.0';
|
||||
$job = new MailError($userData, (string) config('firefly.site_owner'), $ipAddress, $data);
|
||||
dispatch($job);
|
||||
|
||||
parent::report($e);
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
|
||||
/**
|
||||
* Class AccountMetaFactory
|
||||
@@ -41,11 +42,16 @@ class AccountMetaFactory
|
||||
$entry = $account->accountMeta()->where('name', $field)->first();
|
||||
// must not be an empty string:
|
||||
if ('' !== $value) {
|
||||
if ('account_number' === $field) {
|
||||
$value = Steam::filterSpaces($value);
|
||||
$value = trim(str_replace([' ', "\t", "\n", "\r"], '', $value));
|
||||
}
|
||||
// if $data has field and $entry is null, create new one:
|
||||
if (null === $entry) {
|
||||
return $this->create(['account_id' => $account->id, 'name' => $field, 'data' => $value]);
|
||||
}
|
||||
|
||||
|
||||
// if $data has field and $entry is not null, update $entry:
|
||||
$entry->data = $value;
|
||||
$entry->save();
|
||||
|
||||
@@ -46,9 +46,9 @@ class PiggyBankFactory
|
||||
{
|
||||
use CreatesObjectGroups;
|
||||
|
||||
public User $user;
|
||||
private AccountRepositoryInterface $accountRepository;
|
||||
private CurrencyRepositoryInterface $currencyRepository;
|
||||
public User $user;
|
||||
private AccountRepositoryInterface $accountRepository;
|
||||
private CurrencyRepositoryInterface $currencyRepository;
|
||||
private PiggyBankRepositoryInterface $piggyBankRepository;
|
||||
|
||||
public function __construct()
|
||||
@@ -78,7 +78,7 @@ class PiggyBankFactory
|
||||
unset($piggyBankData['object_group_title'], $piggyBankData['transaction_currency_code'], $piggyBankData['transaction_currency_id'], $piggyBankData['accounts'], $piggyBankData['object_group_id'], $piggyBankData['notes']);
|
||||
|
||||
// validate amount:
|
||||
if (array_key_exists('target_amount', $piggyBankData) && '' === (string) $piggyBankData['target_amount']) {
|
||||
if (array_key_exists('target_amount', $piggyBankData) && '' === (string)$piggyBankData['target_amount']) {
|
||||
$piggyBankData['target_amount'] = '0';
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ class PiggyBankFactory
|
||||
}
|
||||
}
|
||||
// try also with ID
|
||||
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
|
||||
$objectGroupId = (int)($data['object_group_id'] ?? 0);
|
||||
if (0 !== $objectGroupId) {
|
||||
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
||||
if ($objectGroup instanceof ObjectGroup) {
|
||||
@@ -129,10 +129,10 @@ class PiggyBankFactory
|
||||
$defaultCurrency = app('amount')->getNativeCurrency();
|
||||
$currency = null;
|
||||
if (array_key_exists('transaction_currency_code', $data)) {
|
||||
$currency = $this->currencyRepository->findByCode((string) ($data['transaction_currency_code'] ?? ''));
|
||||
$currency = $this->currencyRepository->findByCode((string)($data['transaction_currency_code'] ?? ''));
|
||||
}
|
||||
if (array_key_exists('transaction_currency_id', $data)) {
|
||||
$currency = $this->currencyRepository->find((int) ($data['transaction_currency_id'] ?? 0));
|
||||
$currency = $this->currencyRepository->find((int)($data['transaction_currency_id'] ?? 0));
|
||||
}
|
||||
$currency ??= $defaultCurrency;
|
||||
|
||||
@@ -141,8 +141,8 @@ class PiggyBankFactory
|
||||
|
||||
public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank
|
||||
{
|
||||
$piggyBankId = (int) $piggyBankId;
|
||||
$piggyBankName = (string) $piggyBankName;
|
||||
$piggyBankId = (int)$piggyBankId;
|
||||
$piggyBankName = (string)$piggyBankName;
|
||||
if ('' === $piggyBankName && 0 === $piggyBankId) {
|
||||
return null;
|
||||
}
|
||||
@@ -221,7 +221,7 @@ class PiggyBankFactory
|
||||
|
||||
private function getMaxOrder(): int
|
||||
{
|
||||
return (int) $this->piggyBankRepository->getPiggyBanks()->max('order');
|
||||
return (int)$this->piggyBankRepository->getPiggyBanks()->max('order');
|
||||
|
||||
}
|
||||
|
||||
@@ -230,12 +230,13 @@ class PiggyBankFactory
|
||||
Log::debug(sprintf('Linking piggy bank #%d to %d accounts.', $piggyBank->id, count($accounts)), $accounts);
|
||||
// collect current current_amount so the sync does not remove them.
|
||||
// TODO this is a tedious check. Feels like a hack.
|
||||
$toBeLinked = [];
|
||||
$toBeLinked = [];
|
||||
$oldSavedAmount = $this->piggyBankRepository->getCurrentAmount($piggyBank);
|
||||
foreach ($piggyBank->accounts as $account) {
|
||||
Log::debug(sprintf('Checking account #%d', $account->id));
|
||||
foreach ($accounts as $info) {
|
||||
Log::debug(sprintf(' Checking other account #%d', $info['account_id']));
|
||||
if ((int) $account->id === (int) $info['account_id']) {
|
||||
if ((int)$account->id === (int)$info['account_id']) {
|
||||
$toBeLinked[$account->id] = ['current_amount' => $account->pivot->current_amount ?? '0'];
|
||||
Log::debug(sprintf('Prefilled for account #%d with amount %s', $account->id, $account->pivot->current_amount ?? '0'));
|
||||
}
|
||||
@@ -244,9 +245,9 @@ class PiggyBankFactory
|
||||
|
||||
/** @var array $info */
|
||||
foreach ($accounts as $info) {
|
||||
$account = $this->accountRepository->find((int) ($info['account_id'] ?? 0));
|
||||
$account = $this->accountRepository->find((int)($info['account_id'] ?? 0));
|
||||
if (!$account instanceof Account) {
|
||||
Log::debug(sprintf('Account #%d not found, skipping.', (int) ($info['account_id'] ?? 0)));
|
||||
Log::debug(sprintf('Account #%d not found, skipping.', (int)($info['account_id'] ?? 0)));
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -290,7 +291,16 @@ class PiggyBankFactory
|
||||
}
|
||||
Log::debug(sprintf('Link information: %s', json_encode($toBeLinked)));
|
||||
if (0 !== count($toBeLinked)) {
|
||||
Log::debug('Syncing accounts to piggy bank.');
|
||||
$piggyBank->accounts()->sync($toBeLinked);
|
||||
$piggyBank->refresh();
|
||||
$newSavedAmount = $this->piggyBankRepository->getCurrentAmount($piggyBank);
|
||||
Log::debug(sprintf('Old saved amount: %s, new saved amount is %s', $oldSavedAmount, $newSavedAmount));
|
||||
if (0 !== bccomp($oldSavedAmount, $newSavedAmount)) {
|
||||
Log::debug('Amount changed, will create event for it.');
|
||||
// create event for difference.
|
||||
event(new ChangedAmount($piggyBank, bcsub($newSavedAmount, $oldSavedAmount), null, null));
|
||||
}
|
||||
}
|
||||
if (0 === count($toBeLinked)) {
|
||||
Log::warning('No accounts to link to piggy bank, will not change whatever is there now.');
|
||||
|
||||
@@ -24,6 +24,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events\Model;
|
||||
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
@@ -33,6 +37,24 @@ use FireflyIII\Models\PiggyBankEvent;
|
||||
*/
|
||||
class PiggyBankEventHandler
|
||||
{
|
||||
public function changedPiggyBankName(ChangedName $event): void
|
||||
{
|
||||
// loop all accounts, collect all user's rules.
|
||||
/** @var Account $account */
|
||||
foreach ($event->piggyBank->accounts as $account) {
|
||||
/** @var Rule $rule */
|
||||
foreach ($account->user->rules as $rule) {
|
||||
/** @var RuleAction $ruleAction */
|
||||
foreach ($rule->ruleActions()->where('action_type', 'update_piggy')->get() as $ruleAction) {
|
||||
if ($event->oldName === $ruleAction->action_value) {
|
||||
$ruleAction->action_value = $event->newName;
|
||||
$ruleAction->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function changePiggyAmount(ChangedAmount $event): void
|
||||
{
|
||||
// find journal if group is present.
|
||||
|
||||
@@ -49,7 +49,9 @@ class UpdatedGroupEventHandler
|
||||
$this->processRules($event);
|
||||
$this->recalculateCredit($event);
|
||||
$this->triggerWebhooks($event);
|
||||
$this->updateRunningBalance($event);
|
||||
if ($event->runRecalculations) {
|
||||
$this->updateRunningBalance($event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Events\RequestedVersionCheckStatus;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
@@ -42,9 +43,8 @@ class VersionCheckEventHandler
|
||||
* Checks with GitHub to see if there is a new version.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @deprecated ?
|
||||
*/
|
||||
#[Deprecated(message: '?')]
|
||||
public function checkForUpdates(RequestedVersionCheckStatus $event): void
|
||||
{
|
||||
Log::debug('Now in checkForUpdates()');
|
||||
|
||||
@@ -86,7 +86,7 @@ class GroupCollector implements GroupCollectorInterface
|
||||
$this->hasJoinedAttTables = false;
|
||||
$this->expandGroupSearch = false;
|
||||
$this->hasJoinedMetaTables = false;
|
||||
$this->booleanFields = ['balance_dirty'];
|
||||
$this->booleanFields = ['source_balance_dirty', 'destination_balance_dirty'];
|
||||
$this->integerFields = [
|
||||
'transaction_group_id',
|
||||
'user_id',
|
||||
@@ -137,7 +137,7 @@ class GroupCollector implements GroupCollectorInterface
|
||||
// currency info:
|
||||
'source.amount as amount',
|
||||
'source.balance_after as source_balance_after',
|
||||
'source.balance_dirty as balance_dirty',
|
||||
'source.balance_dirty as source_balance_dirty',
|
||||
'source.native_amount as native_amount',
|
||||
'source.transaction_currency_id as currency_id',
|
||||
'currency.code as currency_code',
|
||||
@@ -157,6 +157,7 @@ class GroupCollector implements GroupCollectorInterface
|
||||
// destination account info (always present)
|
||||
'destination.account_id as destination_account_id',
|
||||
'destination.balance_after as destination_balance_after',
|
||||
'destination.balance_dirty as destination_balance_dirty',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
@@ -134,9 +135,7 @@ class NetWorth implements NetWorthInterface
|
||||
$this->currencyRepos->setUserGroup($this->userGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function sumNetWorthByCurrency(Carbon $date): array
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\User;
|
||||
@@ -53,8 +54,7 @@ interface NetWorthInterface
|
||||
* TODO move to repository
|
||||
*
|
||||
* Same as above but cleaner function with less dependencies.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function sumNetWorthByCurrency(Carbon $date): array;
|
||||
}
|
||||
|
||||
@@ -61,12 +61,12 @@ class ForgotPasswordController extends Controller
|
||||
*
|
||||
* @return Factory|RedirectResponse|View
|
||||
*/
|
||||
public function sendResetLinkEmail(Request $request, ?UserRepositoryInterface $repository = null)
|
||||
public function sendResetLinkEmail(Request $request, UserRepositoryInterface $repository)
|
||||
{
|
||||
app('log')->info('Start of sendResetLinkEmail()');
|
||||
if ('web' !== config('firefly.authentication_guard')) {
|
||||
Log::info('Start of sendResetLinkEmail()');
|
||||
if ('web' !== config('firefly.authentication_guard')) {
|
||||
$message = sprintf('Cannot reset password when authenticating over "%s".', config('firefly.authentication_guard'));
|
||||
app('log')->error($message);
|
||||
Log::error($message);
|
||||
|
||||
return view('error', compact('message'));
|
||||
}
|
||||
@@ -89,7 +89,7 @@ class ForgotPasswordController extends Controller
|
||||
// need to show to the user. Finally, we'll send out a proper response.
|
||||
$result = $this->broker()->sendResetLink($request->only('email'));
|
||||
if ('passwords.throttled' === $result) {
|
||||
app('log')->error(sprintf('Cowardly refuse to send a password reset message to user #%d because the reset button has been throttled.', $user->id));
|
||||
Log::error(sprintf('Cowardly refuse to send a password reset message to user #%d because the reset button has been throttled.', $user->id));
|
||||
}
|
||||
|
||||
// always send the same response to the user:
|
||||
|
||||
@@ -223,7 +223,7 @@ class LoginController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function showLoginForm(?Request $request = null)
|
||||
public function showLoginForm(Request $request)
|
||||
{
|
||||
Log::channel('audit')->info('Show login form (1.1).');
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ class IndexController extends Controller
|
||||
public function index(?Carbon $start = null, ?Carbon $end = null)
|
||||
{
|
||||
$this->abRepository->cleanup();
|
||||
app('log')->debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d')));
|
||||
Log::debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d')));
|
||||
|
||||
// collect some basic vars:
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
@@ -199,12 +199,12 @@ class IndexController extends Controller
|
||||
// get all budgets, and paginate them into $budgets.
|
||||
$collection = $this->repository->getActiveBudgets();
|
||||
$budgets = [];
|
||||
app('log')->debug(sprintf('7) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('(getAllBudgets) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
|
||||
// complement budget with budget limits in range, and expenses in currency X in range.
|
||||
/** @var Budget $current */
|
||||
foreach ($collection as $current) {
|
||||
app('log')->debug(sprintf('Working on budget #%d ("%s")', $current->id, $current->name));
|
||||
Log::debug(sprintf('Working on budget #%d ("%s")', $current->id, $current->name));
|
||||
$array = $current->toArray();
|
||||
$array['spent'] = [];
|
||||
$array['spent_total'] = [];
|
||||
@@ -215,7 +215,7 @@ class IndexController extends Controller
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($budgetLimits as $limit) {
|
||||
app('log')->debug(sprintf('Working on budget limit #%d', $limit->id));
|
||||
Log::debug(sprintf('Working on budget limit #%d', $limit->id));
|
||||
$currency = $limit->transactionCurrency ?? $defaultCurrency;
|
||||
$amount = app('steam')->bcround($limit->amount, $currency->decimal_places);
|
||||
$array['budgeted'][] = [
|
||||
@@ -225,14 +225,17 @@ class IndexController extends Controller
|
||||
'start_date' => $limit->start_date->isoFormat($this->monthAndDayFormat),
|
||||
'end_date' => $limit->end_date->isoFormat($this->monthAndDayFormat),
|
||||
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),
|
||||
'total_days' => $limit->start_date->diffInDays($limit->end_date) + 1,
|
||||
'currency_id' => $currency->id,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
];
|
||||
app('log')->debug(sprintf('The amount budgeted for budget limit #%d is %s %s', $limit->id, $currency->code, $amount));
|
||||
Log::debug(sprintf('The amount budgeted for budget limit #%d is %s %s', $limit->id, $currency->code, $amount));
|
||||
}
|
||||
|
||||
// #10463
|
||||
|
||||
/** @var TransactionCurrency $currency */
|
||||
foreach ($currencies as $currency) {
|
||||
$spentArr = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$current]), $currency, false);
|
||||
@@ -259,6 +262,8 @@ class IndexController extends Controller
|
||||
|
||||
/** @var array $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
Log::debug(sprintf('Now working on budget #%d ("%s")', $budget['id'], $budget['name']));
|
||||
|
||||
/** @var array $spent */
|
||||
foreach ($budget['spent'] as $spent) {
|
||||
$currencyId = $spent['currency_id'];
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Json;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
@@ -46,9 +47,8 @@ class BoxController extends Controller
|
||||
|
||||
/**
|
||||
* Deprecated method, no longer in use.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function available(): JsonResponse
|
||||
{
|
||||
return response()->json([]);
|
||||
|
||||
@@ -75,13 +75,22 @@ class AmountController extends Controller
|
||||
$totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||
foreach ($piggyBank->accounts as $account) {
|
||||
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date);
|
||||
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank, $account);
|
||||
$leftToSave = bcsub($piggyBank->target_amount, $savedSoFar);
|
||||
$leftToSave = bcsub($piggyBank->target_amount, $totalSaved);
|
||||
$maxAmount = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave);
|
||||
|
||||
Log::debug(sprintf(
|
||||
'Account "%s", left on account "%s", saved so far "%s", left to save "%s", max amount "%s".',
|
||||
$account->name,
|
||||
$leftOnAccount,
|
||||
$totalSaved,
|
||||
$leftToSave,
|
||||
$maxAmount,
|
||||
));
|
||||
|
||||
$accounts[] = [
|
||||
'account' => $account,
|
||||
'left_on_account' => $leftOnAccount,
|
||||
'saved_so_far' => $savedSoFar,
|
||||
'total_saved' => $totalSaved,
|
||||
'left_to_save' => $leftToSave,
|
||||
'max_amount' => $maxAmount,
|
||||
];
|
||||
@@ -100,18 +109,18 @@ class AmountController extends Controller
|
||||
public function addMobile(PiggyBank $piggyBank)
|
||||
{
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', today(config('app.timezone')));
|
||||
$accounts = [];
|
||||
$total = '0';
|
||||
$date = session('end', today(config('app.timezone')));
|
||||
$accounts = [];
|
||||
$total = '0';
|
||||
$totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||
foreach ($piggyBank->accounts as $account) {
|
||||
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date);
|
||||
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank, $account);
|
||||
$leftToSave = bcsub($piggyBank->target_amount, $savedSoFar);
|
||||
$leftToSave = bcsub($piggyBank->target_amount, $totalSaved);
|
||||
$maxAmount = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave);
|
||||
$accounts[] = [
|
||||
'account' => $account,
|
||||
'left_on_account' => $leftOnAccount,
|
||||
'saved_so_far' => $savedSoFar,
|
||||
'total_saved' => $totalSaved,
|
||||
'left_to_save' => $leftToSave,
|
||||
'max_amount' => $maxAmount,
|
||||
];
|
||||
|
||||
@@ -63,6 +63,14 @@ class EditController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
public function resetHistory(PiggyBank $piggyBank): RedirectResponse
|
||||
{
|
||||
$this->piggyRepos->resetHistory($piggyBank);
|
||||
session()->flash('success', (string) trans('firefly.piggy_history_reset'));
|
||||
|
||||
return redirect(route('piggy-banks.show', [$piggyBank->id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a piggy bank.
|
||||
*
|
||||
|
||||
@@ -34,6 +34,7 @@ use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
@@ -75,7 +76,6 @@ class ExecutionController extends Controller
|
||||
$accounts = implode(',', $request->get('accounts'));
|
||||
$startDate = new Carbon($request->get('start'));
|
||||
$endDate = new Carbon($request->get('end'));
|
||||
$rules = $this->ruleGroupRepository->getActiveRules($ruleGroup);
|
||||
// create new rule engine:
|
||||
$newRuleEngine = app(RuleEngineInterface::class);
|
||||
$newRuleEngine->setUser($user);
|
||||
@@ -86,7 +86,9 @@ class ExecutionController extends Controller
|
||||
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
|
||||
|
||||
// set rules:
|
||||
$newRuleEngine->setRules($rules);
|
||||
// #10427, file rule group and not the set of rules.
|
||||
$collection = new Collection([$ruleGroup]);
|
||||
$newRuleEngine->setRuleGroups($collection);
|
||||
$newRuleEngine->fire();
|
||||
|
||||
// Tell the user that the job is queued
|
||||
|
||||
@@ -118,7 +118,7 @@ class BulkController extends Controller
|
||||
// run rules on changed journals:
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($collection as $journal) {
|
||||
event(new UpdatedTransactionGroup($journal->transactionGroup, true, true));
|
||||
event(new UpdatedTransactionGroup($journal->transactionGroup, true, true, false));
|
||||
}
|
||||
|
||||
app('preferences')->mark();
|
||||
|
||||
@@ -292,7 +292,7 @@ class ConvertController extends Controller
|
||||
$group->refresh();
|
||||
|
||||
session()->flash('success', (string) trans('firefly.converted_to_'.$destinationType->type));
|
||||
event(new UpdatedTransactionGroup($group, true, true));
|
||||
event(new UpdatedTransactionGroup($group, true, true, true));
|
||||
|
||||
return redirect(route('transactions.show', [$group->id]));
|
||||
}
|
||||
|
||||
@@ -191,15 +191,15 @@ class MassController extends Controller
|
||||
*/
|
||||
private function updateJournal(int $journalId, MassEditJournalRequest $request): void
|
||||
{
|
||||
$journal = $this->repository->find($journalId);
|
||||
$journal = $this->repository->find($journalId);
|
||||
if (!$journal instanceof TransactionJournal) {
|
||||
throw new FireflyException(sprintf('Trying to edit non-existent or deleted journal #%d', $journalId));
|
||||
}
|
||||
$service = app(JournalUpdateService::class);
|
||||
$service = app(JournalUpdateService::class);
|
||||
// for each field, call the update service.
|
||||
$service->setTransactionJournal($journal);
|
||||
|
||||
$data = [
|
||||
$data = [
|
||||
'date' => $this->getDateFromRequest($request, $journal->id, 'date'),
|
||||
'description' => $this->getStringFromRequest($request, $journal->id, 'description'),
|
||||
'source_id' => $this->getIntFromRequest($request, $journal->id, 'source_id'),
|
||||
@@ -217,7 +217,8 @@ class MassController extends Controller
|
||||
$service->setData($data);
|
||||
$service->update();
|
||||
// trigger rules
|
||||
event(new UpdatedTransactionGroup($journal->transactionGroup, true, true));
|
||||
$runRecalculations = $service->isCompareHashChanged();
|
||||
event(new UpdatedTransactionGroup($journal->transactionGroup, true, true, $runRecalculations));
|
||||
}
|
||||
|
||||
private function getDateFromRequest(MassEditJournalRequest $request, int $journalId, string $key): ?Carbon
|
||||
|
||||
@@ -26,10 +26,12 @@ namespace FireflyIII\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Exceptions\Handler;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Contracts\Auth\Factory as Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
|
||||
/**
|
||||
* Class Authenticate
|
||||
@@ -84,6 +86,7 @@ class Authenticate
|
||||
if ($this->auth->check()) {
|
||||
// do an extra check on user object.
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->auth->authenticate();
|
||||
$this->validateBlockedUser($user, $guards);
|
||||
@@ -94,9 +97,6 @@ class Authenticate
|
||||
}
|
||||
|
||||
foreach ($guards as $guard) {
|
||||
if ('api' !== $guard) {
|
||||
$this->auth->guard($guard)->authenticate();
|
||||
}
|
||||
$result = $this->auth->guard($guard)->check();
|
||||
if ($result) {
|
||||
$user = $this->auth->guard($guard)->user();
|
||||
@@ -107,7 +107,14 @@ class Authenticate
|
||||
}
|
||||
}
|
||||
|
||||
throw new AuthenticationException('Unauthenticated.', $guards);
|
||||
// this is a massive hack, but if the hander has the oauth exception
|
||||
// at this point we can report its error instead of a generic one.
|
||||
$message = 'Unauthenticated.';
|
||||
if (Handler::$lastError instanceof OAuthServerException) {
|
||||
$message = Handler::$lastError->getHint();
|
||||
}
|
||||
|
||||
throw new AuthenticationException($message, $guards);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -41,15 +40,9 @@ class SelectTransactionsRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
// fixed
|
||||
/** @var Carbon $sessionFirst */
|
||||
$sessionFirst = clone session('first');
|
||||
$first = $sessionFirst->subDay()->format('Y-m-d');
|
||||
$today = today(config('app.timezone'))->addDay()->format('Y-m-d');
|
||||
|
||||
return [
|
||||
'start' => 'required|date|after:'.$first,
|
||||
'end' => 'required|date|before:'.$today,
|
||||
'start' => 'required|date|after:1900-01-01|before:2099-12-31|before:end|required_with:end',
|
||||
'end' => 'required|date|after:1900-01-01|before:2099-12-31|after:start|required_with:start',
|
||||
'accounts' => 'required',
|
||||
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
|
||||
@@ -67,9 +67,10 @@ class UserFailedLoginAttempt extends Notification
|
||||
{
|
||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
||||
$message = new Message();
|
||||
$ip = Request::ip();
|
||||
$message->topic($settings['ntfy_topic']);
|
||||
$message->title((string) trans('email.failed_login_subject'));
|
||||
$message->body((string) trans('email.failed_login_message', ['email' => $this->user->email]));
|
||||
$message->body((string) trans('email.failed_login_message', ['ip' => $ip, 'email' => $this->user->email]));
|
||||
|
||||
return $message;
|
||||
}
|
||||
@@ -79,7 +80,9 @@ class UserFailedLoginAttempt extends Notification
|
||||
*/
|
||||
public function toPushover(User $notifiable): PushoverMessage
|
||||
{
|
||||
return PushoverMessage::create((string) trans('email.failed_login_message', ['email' => $this->user->email]))
|
||||
$ip = Request::ip();
|
||||
|
||||
return PushoverMessage::create((string) trans('email.failed_login_message', ['ip' => $ip, 'email' => $this->user->email]))
|
||||
->title((string) trans('email.failed_login_subject'))
|
||||
;
|
||||
}
|
||||
@@ -89,7 +92,8 @@ class UserFailedLoginAttempt extends Notification
|
||||
*/
|
||||
public function toSlack(User $notifiable): SlackMessage
|
||||
{
|
||||
$message = (string) trans('email.failed_login_message', ['email' => $this->user->email]);
|
||||
$ip = Request::ip();
|
||||
$message = (string) trans('email.failed_login_message', ['ip' => $ip, 'email' => $this->user->email]);
|
||||
|
||||
return new SlackMessage()->content($message);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ use FireflyIII\Events\Model\BudgetLimit\Created;
|
||||
use FireflyIII\Events\Model\BudgetLimit\Deleted;
|
||||
use FireflyIII\Events\Model\BudgetLimit\Updated;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
|
||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
|
||||
use FireflyIII\Events\NewVersionAvailable;
|
||||
@@ -210,6 +211,9 @@ class EventServiceProvider extends ServiceProvider
|
||||
ChangedAmount::class => [
|
||||
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changePiggyAmount',
|
||||
],
|
||||
ChangedName::class => [
|
||||
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changedPiggyBankName',
|
||||
],
|
||||
|
||||
// budget related events: CRUD budget limit
|
||||
Created::class => [
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Repositories\Budget;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
@@ -205,9 +206,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget
|
||||
{
|
||||
/** @var null|AvailableBudget */
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Repositories\Budget;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
@@ -66,9 +67,7 @@ interface AvailableBudgetRepositoryInterface
|
||||
*/
|
||||
public function get(?Carbon $start = null, ?Carbon $end = null): Collection;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string;
|
||||
|
||||
public function getAvailableBudgetWithCurrency(Carbon $start, Carbon $end): array;
|
||||
@@ -90,9 +89,7 @@ interface AvailableBudgetRepositoryInterface
|
||||
*/
|
||||
public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget;
|
||||
|
||||
public function store(array $data): ?AvailableBudget;
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Repositories\Budget;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
@@ -44,9 +45,7 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface NoBudgetRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array;
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Repositories\Budget;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
@@ -74,9 +75,8 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
/**
|
||||
* This method is being used to generate the budget overview in the year/multi-year report. Its used
|
||||
* in both the year/multi-year budget overview AND in the accompanying chart.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$carbonFormat = app('navigation')->preferredCarbonFormat($start, $end);
|
||||
@@ -204,7 +204,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
||||
?TransactionCurrency $currency = null,
|
||||
bool $convertToNative = false
|
||||
): array {
|
||||
Log::debug(sprintf('Start of %s(date, date, array, array, "%s", "%s").', __METHOD__, $currency?->code, var_export($convertToNative, true)));
|
||||
Log::debug(sprintf('Start of %s(date, date, array, array, "%s", %s).', __METHOD__, $currency?->code, var_export($convertToNative, true)));
|
||||
// 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.
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Repositories\Budget;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\Budget;
|
||||
@@ -51,9 +52,7 @@ interface OperationsRepositoryInterface
|
||||
*/
|
||||
public function budgetedPerDay(Budget $budget): string;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array;
|
||||
|
||||
/**
|
||||
@@ -71,6 +70,7 @@ interface OperationsRepositoryInterface
|
||||
Carbon $end,
|
||||
?Collection $accounts = null,
|
||||
?Collection $budgets = null,
|
||||
?TransactionCurrency $currency = null
|
||||
?TransactionCurrency $currency = null,
|
||||
bool $convertToNative = false
|
||||
): array;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Factory\PiggyBankFactory;
|
||||
use FireflyIII\Models\Account;
|
||||
@@ -66,7 +67,7 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
||||
$pivot->current_amount = bcsub((string) $currentAmount, $amount);
|
||||
$pivot->current_amount = bcsub((string)$currentAmount, $amount);
|
||||
$pivot->native_current_amount = null;
|
||||
|
||||
// also update native_current_amount.
|
||||
@@ -89,7 +90,7 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
||||
$pivot->current_amount = bcadd((string) $currentAmount, $amount);
|
||||
$pivot->current_amount = bcadd((string)$currentAmount, $amount);
|
||||
$pivot->native_current_amount = null;
|
||||
|
||||
// also update native_current_amount.
|
||||
@@ -121,13 +122,13 @@ trait ModifiesPiggyBanks
|
||||
|
||||
|
||||
if (0 !== bccomp($piggyBank->target_amount, '0')) {
|
||||
$leftToSave = bcsub($piggyBank->target_amount, (string) $savedSoFar);
|
||||
$maxAmount = 1 === bccomp((string) $leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
||||
$leftToSave = bcsub($piggyBank->target_amount, (string)$savedSoFar);
|
||||
$maxAmount = 1 === bccomp((string)$leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
||||
Log::debug(sprintf('Left to save: %s', $leftToSave));
|
||||
Log::debug(sprintf('Maximum amount: %s', $maxAmount));
|
||||
}
|
||||
|
||||
$compare = bccomp($amount, (string) $maxAmount);
|
||||
$compare = bccomp($amount, (string)$maxAmount);
|
||||
$result = $compare <= 0;
|
||||
|
||||
Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true)));
|
||||
@@ -139,7 +140,7 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$savedSoFar = $this->getCurrentAmount($piggyBank, $account);
|
||||
|
||||
return bccomp($amount, (string) $savedSoFar) <= 0;
|
||||
return bccomp($amount, (string)$savedSoFar) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +171,7 @@ trait ModifiesPiggyBanks
|
||||
if (1 === bccomp($amount, $max) && 0 !== bccomp($piggyBank->target_amount, '0')) {
|
||||
$amount = $max;
|
||||
}
|
||||
$difference = bcsub($amount, (string) $repetition->current_amount);
|
||||
$difference = bcsub($amount, (string)$repetition->current_amount);
|
||||
$repetition->current_amount = $amount;
|
||||
$repetition->save();
|
||||
|
||||
@@ -211,12 +212,12 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$piggyBank = $this->updateProperties($piggyBank, $data);
|
||||
if (array_key_exists('notes', $data)) {
|
||||
$this->updateNote($piggyBank, (string) $data['notes']);
|
||||
$this->updateNote($piggyBank, (string)$data['notes']);
|
||||
}
|
||||
|
||||
// update the order of the piggy bank:
|
||||
$oldOrder = $piggyBank->order;
|
||||
$newOrder = (int) ($data['order'] ?? $oldOrder);
|
||||
$newOrder = (int)($data['order'] ?? $oldOrder);
|
||||
if ($oldOrder !== $newOrder) {
|
||||
$this->setOrder($piggyBank, $newOrder);
|
||||
}
|
||||
@@ -233,9 +234,9 @@ trait ModifiesPiggyBanks
|
||||
// if the piggy bank is now smaller than the sum of the money saved,
|
||||
// remove money from all accounts until the piggy bank is the right amount.
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank);
|
||||
if (1 === bccomp((string) $currentAmount, (string) $piggyBank->target_amount) && 0 !== bccomp((string) $piggyBank->target_amount, '0')) {
|
||||
if (1 === bccomp((string)$currentAmount, (string)$piggyBank->target_amount) && 0 !== bccomp((string)$piggyBank->target_amount, '0')) {
|
||||
Log::debug(sprintf('Current amount is %s, target amount is %s', $currentAmount, $piggyBank->target_amount));
|
||||
$difference = bcsub((string) $piggyBank->target_amount, (string) $currentAmount);
|
||||
$difference = bcsub((string)$piggyBank->target_amount, (string)$currentAmount);
|
||||
|
||||
// an amount will be removed, create "negative" event:
|
||||
// Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference));
|
||||
@@ -248,7 +249,7 @@ trait ModifiesPiggyBanks
|
||||
|
||||
// update using name:
|
||||
if (array_key_exists('object_group_title', $data)) {
|
||||
$objectGroupTitle = (string) $data['object_group_title'];
|
||||
$objectGroupTitle = (string)$data['object_group_title'];
|
||||
if ('' !== $objectGroupTitle) {
|
||||
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
|
||||
if (null !== $objectGroup) {
|
||||
@@ -264,7 +265,7 @@ trait ModifiesPiggyBanks
|
||||
|
||||
// try also with ID:
|
||||
if (array_key_exists('object_group_id', $data)) {
|
||||
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
|
||||
$objectGroupId = (int)($data['object_group_id'] ?? 0);
|
||||
if (0 !== $objectGroupId) {
|
||||
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
||||
if (null !== $objectGroup) {
|
||||
@@ -282,6 +283,7 @@ trait ModifiesPiggyBanks
|
||||
private function updateProperties(PiggyBank $piggyBank, array $data): PiggyBank
|
||||
{
|
||||
if (array_key_exists('name', $data) && '' !== $data['name']) {
|
||||
event(new ChangedName($piggyBank, $piggyBank->name, $data['name']));
|
||||
$piggyBank->name = $data['name'];
|
||||
}
|
||||
if (array_key_exists('transaction_currency_id', $data) && is_int($data['transaction_currency_id'])) {
|
||||
@@ -366,14 +368,14 @@ trait ModifiesPiggyBanks
|
||||
foreach ($piggyBank->accounts as $account) {
|
||||
$current = $account->pivot->current_amount;
|
||||
// if this account contains more than the amount, remove the amount and return.
|
||||
if (1 === bccomp((string) $current, $amount)) {
|
||||
if (1 === bccomp((string)$current, $amount)) {
|
||||
$this->removeAmount($piggyBank, $account, $amount);
|
||||
|
||||
return;
|
||||
}
|
||||
// if this account contains less than the amount, remove the current amount, update the amount and continue.
|
||||
$this->removeAmount($piggyBank, $account, $current);
|
||||
$amount = bcsub($amount, (string) $current);
|
||||
$amount = bcsub($amount, (string)$current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\User;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
@@ -275,7 +276,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
|
||||
$amount = '' === $amount ? '0' : $amount;
|
||||
$sum = bcadd($sum, $amount);
|
||||
}
|
||||
// Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum));
|
||||
Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum));
|
||||
|
||||
return $sum;
|
||||
}
|
||||
@@ -438,4 +439,14 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
|
||||
|
||||
return $search->take($limit)->get(['piggy_banks.*']);
|
||||
}
|
||||
|
||||
public function resetHistory(PiggyBank $piggyBank): void
|
||||
{
|
||||
$piggyBank->piggyBankEvents()->delete();
|
||||
foreach ($piggyBank->accounts as $account) {
|
||||
if (0 !== bccomp('0', (string) $account->pivot->current_amount)) {
|
||||
event(new ChangedAmount($piggyBank, $account->pivot->current_amount, null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,8 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface PiggyBankRepositoryInterface
|
||||
{
|
||||
public function resetHistory(PiggyBank $piggyBank): void;
|
||||
|
||||
public function addAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool;
|
||||
|
||||
public function addAmountToPiggyBank(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): void;
|
||||
|
||||
@@ -217,7 +217,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
'link' => $entry->outward,
|
||||
'group' => $entry->destination->transaction_group_id,
|
||||
'description' => $entry->destination->description,
|
||||
'editable' => 1 === (int) $entry->editable,
|
||||
'editable' => 1 === (int)$entry->editable,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => $foreignAmount,
|
||||
];
|
||||
@@ -230,7 +230,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
'link' => $entry->inward,
|
||||
'group' => $entry->source->transaction_group_id,
|
||||
'description' => $entry->source->description,
|
||||
'editable' => 1 === (int) $entry->editable,
|
||||
'editable' => 1 === (int)$entry->editable,
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => $foreignAmount,
|
||||
];
|
||||
@@ -264,7 +264,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
if (null === $transaction->foreign_amount || '' === $transaction->foreign_amount) {
|
||||
return '';
|
||||
}
|
||||
if (0 === bccomp('0', (string) $transaction->foreign_amount)) {
|
||||
if (0 === bccomp('0', (string)$transaction->foreign_amount)) {
|
||||
return '';
|
||||
}
|
||||
$currency = $transaction->foreignCurrency;
|
||||
@@ -305,7 +305,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
$return = [];
|
||||
|
||||
foreach ($query as $row) {
|
||||
$return[$row->name] = new Carbon(json_decode((string) $row->data, true, 512, JSON_THROW_ON_ERROR));
|
||||
$return[$row->name] = new Carbon(json_decode((string)$row->data, true, 512, JSON_THROW_ON_ERROR));
|
||||
}
|
||||
|
||||
return new NullArrayObject($return);
|
||||
@@ -325,7 +325,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
$return = [];
|
||||
|
||||
foreach ($query as $row) {
|
||||
$return[$row->name] = json_decode((string) $row->data);
|
||||
$return[$row->name] = json_decode((string)$row->data);
|
||||
}
|
||||
|
||||
return new NullArrayObject($return);
|
||||
@@ -432,4 +432,25 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
||||
|
||||
return $service->update($transactionGroup, $data);
|
||||
}
|
||||
|
||||
public function getCompareHash(TransactionGroup $group): string
|
||||
{
|
||||
$sum = '0';
|
||||
$names = '';
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($group->transactionJournals as $journal) {
|
||||
$names = sprintf('%s%s', $names, $journal->date->format('Y-m-d-H:i:s'));
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journal->transactions as $transaction) {
|
||||
if (-1 === bccomp('0', (string)$transaction->amount)) {
|
||||
$sum = bcadd($sum, (string) $transaction->amount);
|
||||
$names = sprintf('%s%s', $names, $transaction->account->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hash('sha256', sprintf('%s-%s', $names, $sum));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,11 @@ interface TransactionGroupRepositoryInterface
|
||||
{
|
||||
public function countAttachments(int $journalId): int;
|
||||
|
||||
/**
|
||||
* Small method that returns a hash that can be used to compare two transaction groups.
|
||||
*/
|
||||
public function getCompareHash(TransactionGroup $group): string;
|
||||
|
||||
public function destroy(TransactionGroup $group): void;
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Internal\Support;
|
||||
|
||||
use Deprecated;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
@@ -193,8 +194,8 @@ trait AccountServiceTrait
|
||||
/**
|
||||
* @throws FireflyException
|
||||
* *
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
protected function createOBGroup(Account $account, array $data): TransactionGroup
|
||||
{
|
||||
app('log')->debug('Now going to create an OB group.');
|
||||
|
||||
@@ -43,6 +43,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Support\JournalServiceTrait;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
@@ -58,36 +59,39 @@ class JournalUpdateService
|
||||
{
|
||||
use JournalServiceTrait;
|
||||
|
||||
private BillRepositoryInterface $billRepository;
|
||||
private BillRepositoryInterface $billRepository;
|
||||
private CurrencyRepositoryInterface $currencyRepository;
|
||||
private array $data;
|
||||
private ?Account $destinationAccount;
|
||||
private ?Transaction $destinationTransaction;
|
||||
private array $metaDate;
|
||||
private array $metaString;
|
||||
private ?Account $sourceAccount;
|
||||
private ?Transaction $sourceTransaction;
|
||||
private ?TransactionGroup $transactionGroup;
|
||||
private ?TransactionJournal $transactionJournal;
|
||||
private TransactionGroupRepositoryInterface $transactionGroupRepository;
|
||||
private array $data;
|
||||
private ?Account $destinationAccount;
|
||||
private ?Transaction $destinationTransaction;
|
||||
private array $metaDate;
|
||||
private array $metaString;
|
||||
private ?Account $sourceAccount;
|
||||
private ?Transaction $sourceTransaction;
|
||||
private ?TransactionGroup $transactionGroup;
|
||||
private ?TransactionJournal $transactionJournal;
|
||||
private string $startCompareHash = '';
|
||||
|
||||
/**
|
||||
* JournalUpdateService constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->destinationAccount = null;
|
||||
$this->destinationTransaction = null;
|
||||
$this->sourceAccount = null;
|
||||
$this->sourceTransaction = null;
|
||||
$this->transactionGroup = null;
|
||||
$this->transactionJournal = null;
|
||||
$this->billRepository = app(BillRepositoryInterface::class);
|
||||
$this->categoryRepository = app(CategoryRepositoryInterface::class);
|
||||
$this->budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$this->tagFactory = app(TagFactory::class);
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$this->metaString = [
|
||||
$this->destinationAccount = null;
|
||||
$this->destinationTransaction = null;
|
||||
$this->sourceAccount = null;
|
||||
$this->sourceTransaction = null;
|
||||
$this->transactionGroup = null;
|
||||
$this->transactionJournal = null;
|
||||
$this->billRepository = app(BillRepositoryInterface::class);
|
||||
$this->categoryRepository = app(CategoryRepositoryInterface::class);
|
||||
$this->budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$this->tagFactory = app(TagFactory::class);
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$this->transactionGroupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->metaString = [
|
||||
'sepa_cc',
|
||||
'sepa_ct_op',
|
||||
'sepa_ct_id',
|
||||
@@ -102,7 +106,7 @@ class JournalUpdateService
|
||||
'external_id',
|
||||
'external_url',
|
||||
];
|
||||
$this->metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date',
|
||||
$this->metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date',
|
||||
'invoice_date', ];
|
||||
}
|
||||
|
||||
@@ -119,10 +123,12 @@ class JournalUpdateService
|
||||
$this->budgetRepository->setUser($transactionGroup->user);
|
||||
$this->tagFactory->setUser($transactionGroup->user);
|
||||
$this->accountRepository->setUser($transactionGroup->user);
|
||||
$this->transactionGroupRepository->setUser($transactionGroup->user);
|
||||
$this->destinationAccount = null;
|
||||
$this->destinationTransaction = null;
|
||||
$this->sourceAccount = null;
|
||||
$this->sourceTransaction = null;
|
||||
$this->startCompareHash = $this->transactionGroupRepository->getCompareHash($transactionGroup);
|
||||
}
|
||||
|
||||
public function setTransactionJournal(TransactionJournal $transactionJournal): void
|
||||
@@ -338,7 +344,7 @@ class JournalUpdateService
|
||||
}
|
||||
|
||||
$sourceInfo = [
|
||||
'id' => (int) ($this->data['source_id'] ?? null),
|
||||
'id' => (int)($this->data['source_id'] ?? null),
|
||||
'name' => $this->data['source_name'] ?? null,
|
||||
'iban' => $this->data['source_iban'] ?? null,
|
||||
'number' => $this->data['source_number'] ?? null,
|
||||
@@ -402,7 +408,7 @@ class JournalUpdateService
|
||||
}
|
||||
|
||||
$destInfo = [
|
||||
'id' => (int) ($this->data['destination_id'] ?? null),
|
||||
'id' => (int)($this->data['destination_id'] ?? null),
|
||||
'name' => $this->data['destination_name'] ?? null,
|
||||
'iban' => $this->data['destination_iban'] ?? null,
|
||||
'number' => $this->data['destination_number'] ?? null,
|
||||
@@ -468,8 +474,8 @@ class JournalUpdateService
|
||||
)
|
||||
&& TransactionTypeEnum::WITHDRAWAL->value === $type
|
||||
) {
|
||||
$billId = (int) ($this->data['bill_id'] ?? 0);
|
||||
$billName = (string) ($this->data['bill_name'] ?? '');
|
||||
$billId = (int)($this->data['bill_id'] ?? 0);
|
||||
$billName = (string)($this->data['bill_name'] ?? '');
|
||||
$bill = $this->billRepository->findBill($billId, $billName);
|
||||
$this->transactionJournal->bill_id = $bill?->id;
|
||||
Log::debug('Updated bill ID');
|
||||
@@ -481,7 +487,7 @@ class JournalUpdateService
|
||||
*/
|
||||
private function updateField(string $fieldName): void
|
||||
{
|
||||
if (array_key_exists($fieldName, $this->data) && '' !== (string) $this->data[$fieldName]) {
|
||||
if (array_key_exists($fieldName, $this->data) && '' !== (string)$this->data[$fieldName]) {
|
||||
$value = $this->data[$fieldName];
|
||||
|
||||
if ('date' === $fieldName) {
|
||||
@@ -557,7 +563,7 @@ class JournalUpdateService
|
||||
{
|
||||
// update notes.
|
||||
if ($this->hasFields(['notes'])) {
|
||||
$notes = '' === (string) $this->data['notes'] ? null : $this->data['notes'];
|
||||
$notes = '' === (string)$this->data['notes'] ? null : $this->data['notes'];
|
||||
$this->storeNotes($this->transactionJournal, $notes);
|
||||
}
|
||||
}
|
||||
@@ -605,7 +611,7 @@ class JournalUpdateService
|
||||
foreach ($this->metaDate as $field) {
|
||||
if ($this->hasFields([$field])) {
|
||||
try {
|
||||
$value = '' === (string) $this->data[$field] ? null : new Carbon($this->data[$field]);
|
||||
$value = '' === (string)$this->data[$field] ? null : new Carbon($this->data[$field]);
|
||||
} catch (InvalidDateException|InvalidFormatException $e) { // @phpstan-ignore-line
|
||||
Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage()));
|
||||
|
||||
@@ -673,7 +679,6 @@ class JournalUpdateService
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$origSourceTransaction = $this->getSourceTransaction();
|
||||
$origSourceTransaction->amount = app('steam')->negative($amount);
|
||||
$origSourceTransaction->balance_dirty = true;
|
||||
@@ -705,7 +710,7 @@ class JournalUpdateService
|
||||
$newForeignId = $this->data['foreign_currency_id'] ?? null;
|
||||
$newForeignCode = $this->data['foreign_currency_code'] ?? null;
|
||||
$foreignCurrency = $this->currencyRepository->findCurrencyNull($newForeignId, $newForeignCode)
|
||||
?? $foreignCurrency;
|
||||
?? $foreignCurrency;
|
||||
|
||||
// not the same as normal currency
|
||||
if (null !== $foreignCurrency && $foreignCurrency->id === $this->transactionJournal->transaction_currency_id) {
|
||||
@@ -816,4 +821,20 @@ class JournalUpdateService
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isCompareHashChanged(): bool
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$compareHash = hash('sha256', sprintf('%s', Carbon::now()->getTimestamp()));
|
||||
if (!$this->transactionGroup instanceof TransactionGroup) {
|
||||
$compareHash = $this->transactionGroupRepository->getCompareHash($this->transactionJournal->transactionGroup);
|
||||
}
|
||||
if ($this->transactionGroup instanceof TransactionGroup) {
|
||||
$this->transactionGroupRepository->getCompareHash($this->transactionGroup);
|
||||
}
|
||||
Log::debug(sprintf('Compare hash is "%s".', $compareHash));
|
||||
Log::debug(sprintf('Start compare hash is "%s".', $this->startCompareHash));
|
||||
|
||||
return $compareHash !== $this->startCompareHash;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support;
|
||||
|
||||
use Deprecated;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
@@ -195,25 +196,19 @@ class Amount
|
||||
return $user->currencies()->orderBy('code', 'ASC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getDefaultCurrency(): TransactionCurrency
|
||||
{
|
||||
return $this->getNativeCurrency();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getDefaultCurrencyByUserGroup instead
|
||||
*/
|
||||
#[Deprecated(message: 'use getDefaultCurrencyByUserGroup instead')]
|
||||
public function getDefaultCurrencyByUser(User $user): TransactionCurrency
|
||||
{
|
||||
return $this->getDefaultCurrencyByUserGroup($user->userGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
||||
{
|
||||
return $this->getNativeCurrencyByUserGroup($userGroup);
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace FireflyIII\Support\Cronjobs;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Jobs\CreateAutoBudgetLimits;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
|
||||
/**
|
||||
* Class AutoBudgetCronjob
|
||||
@@ -36,7 +37,7 @@ class AutoBudgetCronjob extends AbstractCronjob
|
||||
public function fire(): void
|
||||
{
|
||||
/** @var Configuration $config */
|
||||
$config = app('fireflyconfig')->get('last_ab_job', 0);
|
||||
$config = FireflyConfig::get('last_ab_job', 0);
|
||||
$lastTime = (int) $config->data;
|
||||
$diff = Carbon::now()->getTimestamp() - $lastTime;
|
||||
$diffForHumans = today(config('app.timezone'))->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true);
|
||||
@@ -78,7 +79,7 @@ class AutoBudgetCronjob extends AbstractCronjob
|
||||
$this->jobSucceeded = true;
|
||||
$this->message = 'Auto-budget cron job fired successfully.';
|
||||
|
||||
app('fireflyconfig')->set('last_ab_job', (int) $this->date->format('U'));
|
||||
FireflyConfig::set('last_ab_job', (int) $this->date->format('U'));
|
||||
app('log')->info('Done with auto budget cron job task.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Jobs\CreateRecurringTransactions;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class RecurringCronjob
|
||||
@@ -39,34 +41,34 @@ class RecurringCronjob extends AbstractCronjob
|
||||
*/
|
||||
public function fire(): void
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
|
||||
/** @var Configuration $config */
|
||||
$config = app('fireflyconfig')->get('last_rt_job', 0);
|
||||
$config = FireflyConfig::get('last_rt_job', 0);
|
||||
$lastTime = (int) $config->data;
|
||||
$diff = Carbon::now()->getTimestamp() - $lastTime;
|
||||
$diffForHumans = today(config('app.timezone'))->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true);
|
||||
|
||||
if (0 === $lastTime) {
|
||||
app('log')->info('Recurring transactions cron-job has never fired before.');
|
||||
Log::info('Recurring transactions 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 recurring transactions cron-job has fired.', $diffForHumans));
|
||||
Log::info(sprintf('It has been "%s" since the recurring transactions cron-job has fired.', $diffForHumans));
|
||||
if (false === $this->force) {
|
||||
app('log')->info('The cron-job will not fire now.');
|
||||
$this->message = sprintf('It has been %s since the recurring transactions cron-job has fired. It will not fire now.', $diffForHumans);
|
||||
Log::info('The cron-job will not fire now.');
|
||||
$this->message = sprintf('It has been "%s" since the recurring transactions cron-job has fired. It will not fire now.', $diffForHumans);
|
||||
$this->jobFired = false;
|
||||
$this->jobErrored = false;
|
||||
$this->jobSucceeded = false;
|
||||
|
||||
return;
|
||||
}
|
||||
app('log')->info('Execution of the recurring transaction cron-job has been FORCED.');
|
||||
Log::info('Execution of the recurring transaction cron-job has been FORCED.');
|
||||
}
|
||||
|
||||
if ($lastTime > 0 && $diff > 43200) {
|
||||
app('log')->info(sprintf('It has been %s since the recurring transactions cron-job has fired. It will fire now!', $diffForHumans));
|
||||
Log::info(sprintf('It has been "%s" since the recurring transactions cron-job has fired. It will fire now!', $diffForHumans));
|
||||
}
|
||||
|
||||
$this->fireRecurring();
|
||||
@@ -76,7 +78,7 @@ class RecurringCronjob extends AbstractCronjob
|
||||
|
||||
private function fireRecurring(): void
|
||||
{
|
||||
app('log')->info(sprintf('Will now fire recurring cron job task for date "%s".', $this->date->format('Y-m-d H:i:s')));
|
||||
Log::info(sprintf('Will now fire recurring cron job task for date "%s".', $this->date->format('Y-m-d H:i:s')));
|
||||
|
||||
$job = new CreateRecurringTransactions($this->date);
|
||||
$job->setForce($this->force);
|
||||
@@ -88,8 +90,8 @@ class RecurringCronjob extends AbstractCronjob
|
||||
$this->jobSucceeded = true;
|
||||
$this->message = 'Recurring transactions cron job fired successfully.';
|
||||
|
||||
app('fireflyconfig')->set('last_rt_job', (int) $this->date->format('U'));
|
||||
app('log')->info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int) $this->date->format('U')));
|
||||
app('log')->info('Done with recurring cron job task.');
|
||||
FireflyConfig::set('last_rt_job', (int) $this->date->format('U'));
|
||||
Log::info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int) $this->date->format('U')));
|
||||
Log::info('Done with recurring cron job task.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class FireflyConfig
|
||||
{
|
||||
public function delete(string $name): void
|
||||
{
|
||||
$fullName = 'ff-config-'.$name;
|
||||
$fullName = 'ff3-config-'.$name;
|
||||
if (Cache::has($fullName)) {
|
||||
Cache::forget($fullName);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class FireflyConfig
|
||||
*/
|
||||
public function get(string $name, mixed $default = null): ?Configuration
|
||||
{
|
||||
$fullName = 'ff-config-'.$name;
|
||||
$fullName = 'ff3-config-'.$name;
|
||||
if (Cache::has($fullName)) {
|
||||
return Cache::get($fullName);
|
||||
}
|
||||
|
||||
@@ -79,12 +79,12 @@ class ExchangeRateConverter
|
||||
public function getCurrencyRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||
{
|
||||
if (false === $this->enabled()) {
|
||||
Log::debug('ExchangeRateConverter: disabled, return "1".');
|
||||
// Log::debug('ExchangeRateConverter: disabled, return "1".');
|
||||
|
||||
return '1';
|
||||
}
|
||||
if ($from->id === $to->id) {
|
||||
Log::debug('ExchangeRateConverter: From and to are the same, return "1".');
|
||||
// Log::debug('ExchangeRateConverter: From and to are the same, return "1".');
|
||||
|
||||
return '1';
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Support\Http\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
@@ -205,7 +206,7 @@ trait GetConfigurationData
|
||||
|
||||
protected function verifyRecurringCronJob(): void
|
||||
{
|
||||
$config = app('fireflyconfig')->get('last_rt_job', 0);
|
||||
$config = FireflyConfig::get('last_rt_job', 0);
|
||||
$lastTime = (int) $config?->data;
|
||||
$now = Carbon::now()->getTimestamp();
|
||||
app('log')->debug(sprintf('verifyRecurringCronJob: last time is %d ("%s"), now is %d', $lastTime, $config?->data, $now));
|
||||
|
||||
@@ -35,6 +35,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use FireflyIII\Support\Debug\Timer;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Trait PeriodOverview.
|
||||
@@ -77,6 +78,7 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug('Now in getAccountPeriodOverview()');
|
||||
Timer::start('account-period-total');
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$range = app('navigation')->getViewRange(true);
|
||||
@@ -100,6 +102,7 @@ trait PeriodOverview
|
||||
$transactions = $this->accountRepository->periodCollection($account, $start, $end);
|
||||
|
||||
// loop dates
|
||||
Log::debug(sprintf('Count of loops: %d', count($dates)));
|
||||
foreach ($dates as $currentDate) {
|
||||
$title = app('navigation')->periodShow($currentDate['start'], $currentDate['period']);
|
||||
[$transactions, $spent] = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $transactions, $currentDate['start'], $currentDate['end']);
|
||||
@@ -119,6 +122,7 @@ trait PeriodOverview
|
||||
}
|
||||
$cache->store($entries);
|
||||
Timer::stop('account-period-total');
|
||||
Log::debug('End of getAccountPeriodOverview()');
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
@@ -30,10 +30,12 @@ use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -52,6 +54,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
private array $notes; // @phpstan-ignore-line
|
||||
private array $tags;
|
||||
private User $user;
|
||||
private readonly TransactionCurrency $nativeCurrency;
|
||||
private UserGroup $userGroup;
|
||||
|
||||
public function __construct()
|
||||
@@ -63,6 +66,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
$this->locations = [];
|
||||
$this->attachmentCount = [];
|
||||
$this->dateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||
$this->nativeCurrency = Amount::getNativeCurrency();
|
||||
}
|
||||
|
||||
#[Override]
|
||||
@@ -192,8 +196,9 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
$metaData = $this->metaData;
|
||||
$locations = $this->locations;
|
||||
$attachmentCount = $this->attachmentCount;
|
||||
$nativeCurrency = $this->nativeCurrency;
|
||||
|
||||
$this->collection = $this->collection->map(function (array $item) use ($notes, $tags, $metaData, $locations, $attachmentCount) {
|
||||
$this->collection = $this->collection->map(function (array $item) use ($nativeCurrency, $notes, $tags, $metaData, $locations, $attachmentCount) {
|
||||
foreach ($item['transactions'] as $index => $transaction) {
|
||||
$journalId = (int) $transaction['transaction_journal_id'];
|
||||
|
||||
@@ -213,6 +218,15 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
'zoom_level' => null,
|
||||
];
|
||||
|
||||
// native currency
|
||||
$item['transactions'][$index]['native_currency'] = [
|
||||
'id' => (string) $nativeCurrency->id,
|
||||
'code' => $nativeCurrency->code,
|
||||
'name' => $nativeCurrency->name,
|
||||
'symbol' => $nativeCurrency->symbol,
|
||||
'decimal_places' => $nativeCurrency->decimal_places,
|
||||
];
|
||||
|
||||
// append meta data
|
||||
$item['transactions'][$index]['meta'] = [];
|
||||
$item['transactions'][$index]['meta_date'] = [];
|
||||
|
||||
@@ -582,7 +582,7 @@ class Navigation
|
||||
*/
|
||||
public function preferredEndOfPeriod(Carbon $start, Carbon $end): string
|
||||
{
|
||||
if ((int) $start->diffInMonths($end, true) > 1) {
|
||||
if ((int) $start->diffInMonths($end, true) > 1 && (int) $start->diffInMonths($end, true) <= 12) {
|
||||
return 'endOfMonth';
|
||||
}
|
||||
|
||||
@@ -599,7 +599,7 @@ class Navigation
|
||||
*/
|
||||
public function preferredRangeFormat(Carbon $start, Carbon $end): string
|
||||
{
|
||||
if ((int) $start->diffInMonths($end, true) > 1) {
|
||||
if ((int) $start->diffInMonths($end, true) > 1 && (int) $start->diffInMonths($end, true) <= 12) {
|
||||
return '1M';
|
||||
}
|
||||
|
||||
@@ -616,7 +616,7 @@ class Navigation
|
||||
*/
|
||||
public function preferredSqlFormat(Carbon $start, Carbon $end): string
|
||||
{
|
||||
if ((int) $start->diffInMonths($end, true) > 1) {
|
||||
if ((int) $start->diffInMonths($end, true) > 1 && (int) $start->diffInMonths($end, true) <= 12) {
|
||||
return '%Y-%m';
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class TransactionSummarizer
|
||||
|
||||
public function groupByCurrencyId(array $journals, string $method = 'negative', bool $includeForeign = true): array
|
||||
{
|
||||
Log::debug(sprintf('Now in groupByCurrencyId([%d journals], "%s")', count($journals), $method));
|
||||
Log::debug(sprintf('Now in groupByCurrencyId([%d journals], "%s", %s)', count($journals), $method, var_export($includeForeign, true)));
|
||||
$array = [];
|
||||
foreach ($journals as $journal) {
|
||||
$field = 'amount';
|
||||
|
||||
@@ -278,6 +278,8 @@ class Steam
|
||||
$carbonKey = $carbon->format('Y-m-d');
|
||||
// make sure sum is a string:
|
||||
$sumOfDay = (string) ($entry->sum_of_day ?? '0');
|
||||
// #10426 make sure sum is not in scientific notation.
|
||||
$sumOfDay = $this->floatalize($sumOfDay);
|
||||
|
||||
// find currency of this entry, does not have to exist.
|
||||
$currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id);
|
||||
|
||||
@@ -67,6 +67,16 @@ class UpdatePiggyBank implements ActionInterface
|
||||
|
||||
Log::debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name));
|
||||
|
||||
// piggy bank already has an event for this transaction journal?
|
||||
if ($this->alreadyEventPresent($piggyBank, $journal)) {
|
||||
Log::info(sprintf('Piggy bank #%d ("%s") already has an event for transaction journal #%d, so no action will be taken.', $piggyBank->id, $piggyBank->name, $journalObj->id));
|
||||
|
||||
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_piggy', ['name' => $actionValue])));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** @var Transaction $destination */
|
||||
$destination = $journalObj->transactions()->where('amount', '>', 0)->first();
|
||||
|
||||
@@ -231,4 +241,9 @@ class UpdatePiggyBank implements ActionInterface
|
||||
|
||||
$repository->addAmount($piggyBank, $account, $amount, $journal);
|
||||
}
|
||||
|
||||
private function alreadyEventPresent(PiggyBank $piggyBank, array $journal): bool
|
||||
{
|
||||
return $piggyBank->piggyBankEvents()->where('transaction_journal_id', $journal['transaction_journal_id'])->exists();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,13 +64,13 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
|
||||
public function addOperator(array $operator): void
|
||||
{
|
||||
app('log')->debug('Add extra operator: ', $operator);
|
||||
Log::debug('Add extra operator: ', $operator);
|
||||
$this->operators[] = $operator;
|
||||
}
|
||||
|
||||
public function find(): Collection
|
||||
{
|
||||
app('log')->debug('SearchRuleEngine::find()');
|
||||
Log::debug('SearchRuleEngine::find()');
|
||||
$collection = new Collection();
|
||||
foreach ($this->rules as $rule) {
|
||||
$found = new Collection();
|
||||
@@ -83,7 +83,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
$collection = $collection->merge($found);
|
||||
}
|
||||
$result = $collection->unique();
|
||||
app('log')->debug(sprintf('SearchRuleEngine::find() returns %d unique transactions.', $result->count()));
|
||||
Log::debug(sprintf('SearchRuleEngine::find() returns %d unique transactions.', $result->count()));
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function findStrictRule(Rule $rule): Collection
|
||||
{
|
||||
app('log')->debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0));
|
||||
Log::debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0));
|
||||
$searchArray = [];
|
||||
$triggers = [];
|
||||
if ($this->refreshTriggers) {
|
||||
@@ -116,18 +116,18 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
// if the trigger needs no context, value is different:
|
||||
$needsContext = (bool) (config(sprintf('search.operators.%s.needs_context', $contextSearch)) ?? true);
|
||||
if (false === $needsContext) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: add a rule trigger (no context): %s:true', $ruleTrigger->trigger_type));
|
||||
Log::debug(sprintf('SearchRuleEngine:: add a rule trigger (no context): %s:true', $ruleTrigger->trigger_type));
|
||||
$searchArray[$ruleTrigger->trigger_type][] = 'true';
|
||||
}
|
||||
if (true === $needsContext) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: add a rule trigger (context): %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
|
||||
Log::debug(sprintf('SearchRuleEngine:: add a rule trigger (context): %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
|
||||
$searchArray[$ruleTrigger->trigger_type][] = sprintf('"%s"', $ruleTrigger->trigger_value);
|
||||
}
|
||||
}
|
||||
|
||||
// add local operators:
|
||||
foreach ($this->operators as $operator) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
|
||||
Log::debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
|
||||
$searchArray[$operator['type']][] = sprintf('"%s"', $operator['value']);
|
||||
}
|
||||
$date = today(config('app.timezone'));
|
||||
@@ -141,11 +141,11 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
$searchEngine->setPage(1);
|
||||
$searchEngine->setLimit(31337);
|
||||
$searchEngine->setDate($date);
|
||||
app('log')->debug('Search array', $searchArray);
|
||||
Log::debug('Search array', $searchArray);
|
||||
foreach ($searchArray as $type => $searches) {
|
||||
foreach ($searches as $value) {
|
||||
$query = sprintf('%s:%s', $type, $value);
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: add query "%s"', $query));
|
||||
Log::debug(sprintf('SearchRuleEngine:: add query "%s"', $query));
|
||||
$searchEngine->parseQuery($query);
|
||||
}
|
||||
}
|
||||
@@ -162,33 +162,33 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function hasSpecificJournalTrigger(array $array): bool
|
||||
{
|
||||
app('log')->debug('Now in hasSpecificJournalTrigger.');
|
||||
Log::debug('Now in hasSpecificJournalTrigger.');
|
||||
$journalTrigger = false;
|
||||
$dateTrigger = false;
|
||||
foreach ($array as $triggerName => $values) {
|
||||
if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) {
|
||||
app('log')->debug('Found a journal_id trigger with 1 journal, true.');
|
||||
Log::debug('Found a journal_id trigger with 1 journal, true.');
|
||||
$journalTrigger = true;
|
||||
}
|
||||
if (in_array($triggerName, ['date_is', 'date', 'on', 'date_before', 'before', 'date_after', 'after'], true)) {
|
||||
app('log')->debug('Found a date related trigger, set to true.');
|
||||
Log::debug('Found a date related trigger, set to true.');
|
||||
$dateTrigger = true;
|
||||
}
|
||||
}
|
||||
$result = $journalTrigger && $dateTrigger;
|
||||
app('log')->debug(sprintf('Result of hasSpecificJournalTrigger is %s.', var_export($result, true)));
|
||||
Log::debug(sprintf('Result of hasSpecificJournalTrigger is %s.', var_export($result, true)));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function setDateFromJournalTrigger(array $array): Carbon
|
||||
{
|
||||
app('log')->debug('Now in setDateFromJournalTrigger()');
|
||||
Log::debug('Now in setDateFromJournalTrigger()');
|
||||
$journalId = 0;
|
||||
foreach ($array as $triggerName => $values) {
|
||||
if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) {
|
||||
$journalId = (int) trim($values[0] ?? '"0"', '"'); // follows format "123".
|
||||
app('log')->debug(sprintf('Found journal ID #%d', $journalId));
|
||||
Log::debug(sprintf('Found journal ID #%d', $journalId));
|
||||
}
|
||||
}
|
||||
if (0 !== $journalId) {
|
||||
@@ -197,12 +197,12 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
$journal = $repository->find($journalId);
|
||||
if (null !== $journal) {
|
||||
$date = $journal->date;
|
||||
app('log')->debug(sprintf('Found journal #%d with date %s.', $journal->id, $journal->date->format('Y-m-d')));
|
||||
Log::debug(sprintf('Found journal #%d with date %s.', $journal->id, $journal->date->format('Y-m-d')));
|
||||
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
app('log')->debug('Found no journal, return default date.');
|
||||
Log::debug('Found no journal, return default date.');
|
||||
|
||||
return today(config('app.timezone'));
|
||||
}
|
||||
@@ -215,48 +215,48 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
|
||||
private function findNonStrictRule(Rule $rule): Collection
|
||||
{
|
||||
app('log')->debug(sprintf('findNonStrictRule(#%d)', $rule->id));
|
||||
Log::debug(sprintf('findNonStrictRule(#%d)', $rule->id));
|
||||
// start a search query for individual each trigger:
|
||||
$total = new Collection();
|
||||
$count = 0;
|
||||
$triggers = [];
|
||||
if ($this->refreshTriggers) {
|
||||
app('log')->debug('Will refresh triggers.');
|
||||
Log::debug('Will refresh triggers.');
|
||||
$triggers = $rule->ruleTriggers()->orderBy('order', 'ASC')->get();
|
||||
}
|
||||
if (!$this->refreshTriggers) {
|
||||
app('log')->debug('Will not refresh triggers.');
|
||||
Log::debug('Will not refresh triggers.');
|
||||
$triggers = $rule->ruleTriggers;
|
||||
}
|
||||
app('log')->debug(sprintf('Will run %d trigger(s).', count($triggers)));
|
||||
Log::debug(sprintf('Will run %d trigger(s).', count($triggers)));
|
||||
|
||||
/** @var RuleTrigger $ruleTrigger */
|
||||
foreach ($triggers as $ruleTrigger) {
|
||||
app('log')->debug(sprintf('Now at rule trigger #%d: %s:"%s" (%s).', $ruleTrigger->id, $ruleTrigger->trigger_type, $ruleTrigger->trigger_value, var_export($ruleTrigger->stop_processing, true)));
|
||||
Log::debug(sprintf('Now at rule trigger #%d: %s:"%s" (%s).', $ruleTrigger->id, $ruleTrigger->trigger_type, $ruleTrigger->trigger_value, var_export($ruleTrigger->stop_processing, true)));
|
||||
if (false === $ruleTrigger->active) {
|
||||
app('log')->debug('Trigger is not active, continue.');
|
||||
Log::debug('Trigger is not active, continue.');
|
||||
|
||||
continue;
|
||||
}
|
||||
if ('user_action' === $ruleTrigger->trigger_type) {
|
||||
app('log')->debug('Skip trigger type. continue.');
|
||||
Log::debug('Skip trigger type. continue.');
|
||||
|
||||
continue;
|
||||
}
|
||||
$searchArray = [];
|
||||
$needsContext = config(sprintf('search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
||||
if (false === $needsContext) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:true', $ruleTrigger->trigger_type));
|
||||
Log::debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:true', $ruleTrigger->trigger_type));
|
||||
$searchArray[$ruleTrigger->trigger_type] = 'true';
|
||||
}
|
||||
if (true === $needsContext) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
|
||||
Log::debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
|
||||
$searchArray[$ruleTrigger->trigger_type] = sprintf('"%s"', $ruleTrigger->trigger_value);
|
||||
}
|
||||
|
||||
// then, add local operators as well:
|
||||
foreach ($this->operators as $operator) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
|
||||
Log::debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
|
||||
$searchArray[$operator['type']] = sprintf('"%s"', $operator['value']);
|
||||
}
|
||||
|
||||
@@ -272,19 +272,19 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
|
||||
$result = $searchEngine->searchTransactions();
|
||||
$collection = $result->getCollection();
|
||||
app('log')->debug(sprintf('Found in this run, %d transactions', $collection->count()));
|
||||
Log::debug(sprintf('Found in this run, %d transactions', $collection->count()));
|
||||
$total = $total->merge($collection);
|
||||
app('log')->debug(sprintf('Total collection is now %d transactions', $total->count()));
|
||||
Log::debug(sprintf('Total collection is now %d transactions', $total->count()));
|
||||
++$count;
|
||||
// if trigger says stop processing, do so.
|
||||
if (true === $ruleTrigger->stop_processing && $result->count() > 0) {
|
||||
app('log')->debug('The trigger says to stop processing, so stop processing other triggers.');
|
||||
Log::debug('The trigger says to stop processing, so stop processing other triggers.');
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
app('log')->debug(sprintf('Total collection is now %d transactions', $total->count()));
|
||||
app('log')->debug(sprintf('Done running %d trigger(s)', $count));
|
||||
Log::debug(sprintf('Total collection is now %d transactions', $total->count()));
|
||||
Log::debug(sprintf('Done running %d trigger(s)', $count));
|
||||
|
||||
// make collection unique
|
||||
$unique = $total->unique(
|
||||
@@ -295,11 +295,11 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
}
|
||||
|
||||
return sprintf('%d%s', $group['id'], $str);
|
||||
// app('log')->debug(sprintf('Return key: %s ', $key));
|
||||
// Log::debug(sprintf('Return key: %s ', $key));
|
||||
}
|
||||
);
|
||||
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: Found %d transactions using search engine.', $unique->count()));
|
||||
Log::debug(sprintf('SearchRuleEngine:: Found %d transactions using search engine.', $unique->count()));
|
||||
|
||||
return $unique;
|
||||
}
|
||||
@@ -310,28 +310,28 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
public function fire(): void
|
||||
{
|
||||
$this->resultCount = [];
|
||||
app('log')->debug('SearchRuleEngine::fire()!');
|
||||
Log::debug('SearchRuleEngine::fire()!');
|
||||
|
||||
// if rules and no rule groups, file each rule separately.
|
||||
if (0 !== $this->rules->count()) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: found %d rule(s) to fire.', $this->rules->count()));
|
||||
Log::debug(sprintf('SearchRuleEngine:: found %d rule(s) to fire.', $this->rules->count()));
|
||||
|
||||
/** @var Rule $rule */
|
||||
foreach ($this->rules as $rule) {
|
||||
$result = $this->fireRule($rule);
|
||||
if (true === $result && true === $rule->stop_processing) {
|
||||
app('log')->debug(sprintf('Rule #%d has triggered and executed, but calls to stop processing. Since not in the context of a group, do not stop.', $rule->id));
|
||||
Log::debug(sprintf('Rule #%d has triggered and executed, but calls to stop processing. Since not in the context of a group, do not stop.', $rule->id));
|
||||
}
|
||||
if (false === $result && true === $rule->stop_processing) {
|
||||
app('log')->debug(sprintf('Rule #%d has triggered and changed nothing, but calls to stop processing. Do not stop.', $rule->id));
|
||||
Log::debug(sprintf('Rule #%d has triggered and changed nothing, but calls to stop processing. Do not stop.', $rule->id));
|
||||
}
|
||||
}
|
||||
app('log')->debug('SearchRuleEngine:: done processing all rules!');
|
||||
Log::debug('SearchRuleEngine:: done processing all rules!');
|
||||
|
||||
return;
|
||||
}
|
||||
if (0 !== $this->groups->count()) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: found %d rule group(s) to fire.', $this->groups->count()));
|
||||
Log::debug(sprintf('SearchRuleEngine:: found %d rule group(s) to fire.', $this->groups->count()));
|
||||
|
||||
// fire each group:
|
||||
/** @var RuleGroup $group */
|
||||
@@ -339,7 +339,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
$this->fireGroup($group);
|
||||
}
|
||||
}
|
||||
app('log')->debug('SearchRuleEngine:: done processing all rules!');
|
||||
Log::debug('SearchRuleEngine:: done processing all rules!');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,18 +349,18 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function fireRule(Rule $rule): bool
|
||||
{
|
||||
app('log')->debug(sprintf('Now going to fire rule #%d', $rule->id));
|
||||
Log::debug(sprintf('Now going to fire rule #%d', $rule->id));
|
||||
if (false === $rule->active) {
|
||||
app('log')->debug(sprintf('Rule #%d is not active!', $rule->id));
|
||||
Log::debug(sprintf('Rule #%d is not active!', $rule->id));
|
||||
|
||||
return false;
|
||||
}
|
||||
if (true === $rule->strict) {
|
||||
app('log')->debug(sprintf('Rule #%d is a strict rule.', $rule->id));
|
||||
Log::debug(sprintf('Rule #%d is a strict rule.', $rule->id));
|
||||
|
||||
return $this->fireStrictRule($rule);
|
||||
}
|
||||
app('log')->debug(sprintf('Rule #%d is not strict rule.', $rule->id));
|
||||
Log::debug(sprintf('Rule #%d is not strict rule.', $rule->id));
|
||||
|
||||
return $this->fireNonStrictRule($rule);
|
||||
}
|
||||
@@ -372,19 +372,19 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function fireStrictRule(Rule $rule): bool
|
||||
{
|
||||
app('log')->debug(sprintf('SearchRuleEngine::fireStrictRule(%d)!', $rule->id));
|
||||
Log::debug(sprintf('SearchRuleEngine::fireStrictRule(%d)!', $rule->id));
|
||||
$collection = $this->findStrictRule($rule);
|
||||
|
||||
$this->processResults($rule, $collection);
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: done processing strict rule #%d', $rule->id));
|
||||
Log::debug(sprintf('SearchRuleEngine:: done processing strict rule #%d', $rule->id));
|
||||
|
||||
$result = $collection->count() > 0;
|
||||
if (true === $result) {
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: rule #%d was triggered (on %d transaction(s)).', $rule->id, $collection->count()));
|
||||
Log::debug(sprintf('SearchRuleEngine:: rule #%d was triggered (on %d transaction(s)).', $rule->id, $collection->count()));
|
||||
|
||||
return true;
|
||||
}
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: rule #%d was not triggered (on %d transaction(s)).', $rule->id, $collection->count()));
|
||||
Log::debug(sprintf('SearchRuleEngine:: rule #%d was not triggered (on %d transaction(s)).', $rule->id, $collection->count()));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -394,7 +394,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function processResults(Rule $rule, Collection $collection): void
|
||||
{
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: Going to process %d results.', $collection->count()));
|
||||
Log::debug(sprintf('SearchRuleEngine:: Going to process %d results.', $collection->count()));
|
||||
|
||||
/** @var array $group */
|
||||
foreach ($collection as $group) {
|
||||
@@ -407,7 +407,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function processTransactionGroup(Rule $rule, array $group): void
|
||||
{
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction group #%d', $group['id']));
|
||||
Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction group #%d', $group['id']));
|
||||
|
||||
/** @var array $transaction */
|
||||
foreach ($group['transactions'] as $transaction) {
|
||||
@@ -420,7 +420,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function processTransactionJournal(Rule $rule, array $transaction): void
|
||||
{
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id']));
|
||||
Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id']));
|
||||
$actions = $rule->ruleActions()->orderBy('order', 'ASC')->get();
|
||||
|
||||
/** @var RuleAction $ruleAction */
|
||||
@@ -440,14 +440,14 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function processRuleAction(RuleAction $ruleAction, array $transaction): bool
|
||||
{
|
||||
app('log')->debug(sprintf('Executing rule action "%s" with value "%s"', $ruleAction->action_type, $ruleAction->action_value));
|
||||
Log::debug(sprintf('Executing rule action "%s" with value "%s"', $ruleAction->action_type, $ruleAction->action_value));
|
||||
$transaction = $this->addNotes($transaction);
|
||||
$actionClass = ActionFactory::getAction($ruleAction);
|
||||
$result = $actionClass->actOnArray($transaction);
|
||||
$journalId = $transaction['transaction_journal_id'] ?? 0;
|
||||
if (true === $result) {
|
||||
$this->resultCount[$journalId] = array_key_exists($journalId, $this->resultCount) ? $this->resultCount[$journalId]++ : 1;
|
||||
app('log')->debug(
|
||||
Log::debug(
|
||||
sprintf(
|
||||
'Action "%s" on journal #%d was executed, so count a result. Updated transaction journal count is now %d.',
|
||||
$ruleAction->action_type,
|
||||
@@ -457,17 +457,17 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
);
|
||||
}
|
||||
if (false === $result) {
|
||||
app('log')->debug(sprintf('Action "%s" reports NO changes were made.', $ruleAction->action_type));
|
||||
Log::debug(sprintf('Action "%s" reports NO changes were made.', $ruleAction->action_type));
|
||||
}
|
||||
|
||||
// pick up from the action if it actually acted or not:
|
||||
if (true === $ruleAction->stop_processing && true === $result) {
|
||||
app('log')->debug(sprintf('Rule action "%s" reports changes AND asks to break, so break!', $ruleAction->action_type));
|
||||
Log::debug(sprintf('Rule action "%s" reports changes AND asks to break, so break!', $ruleAction->action_type));
|
||||
|
||||
return true;
|
||||
}
|
||||
if (true === $ruleAction->stop_processing && false === $result) {
|
||||
app('log')->debug(sprintf('Rule action "%s" reports NO changes AND asks to break, but we wont break!', $ruleAction->action_type));
|
||||
Log::debug(sprintf('Rule action "%s" reports NO changes AND asks to break, but we wont break!', $ruleAction->action_type));
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -492,11 +492,11 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function fireNonStrictRule(Rule $rule): bool
|
||||
{
|
||||
app('log')->debug(sprintf('SearchRuleEngine::fireNonStrictRule(%d)!', $rule->id));
|
||||
Log::debug(sprintf('SearchRuleEngine::fireNonStrictRule(%d)!', $rule->id));
|
||||
$collection = $this->findNonStrictRule($rule);
|
||||
|
||||
$this->processResults($rule, $collection);
|
||||
app('log')->debug(sprintf('SearchRuleEngine:: done processing non-strict rule #%d', $rule->id));
|
||||
Log::debug(sprintf('SearchRuleEngine:: done processing non-strict rule #%d', $rule->id));
|
||||
|
||||
return $collection->count() > 0;
|
||||
}
|
||||
@@ -506,14 +506,14 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
*/
|
||||
private function fireGroup(RuleGroup $group): void
|
||||
{
|
||||
app('log')->debug(sprintf('Going to fire group #%d with %d rule(s)', $group->id, $group->rules->count()));
|
||||
Log::debug(sprintf('Going to fire group #%d with %d rule(s)', $group->id, $group->rules->count()));
|
||||
|
||||
/** @var Rule $rule */
|
||||
foreach ($group->rules as $rule) {
|
||||
app('log')->debug(sprintf('Going to fire rule #%d from group #%d', $rule->id, $group->id));
|
||||
Log::debug(sprintf('Going to fire rule #%d from group #%d', $rule->id, $group->id));
|
||||
$result = $this->fireRule($rule);
|
||||
if (true === $result && true === $rule->stop_processing) {
|
||||
app('log')->debug(sprintf('The rule was triggered and rule->stop_processing = true, so group #%d will stop processing further rules.', $group->id));
|
||||
Log::debug(sprintf('The rule was triggered and rule->stop_processing = true, so group #%d will stop processing further rules.', $group->id));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -535,10 +535,10 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
|
||||
public function setRuleGroups(Collection $ruleGroups): void
|
||||
{
|
||||
app('log')->debug(__METHOD__);
|
||||
Log::debug(__METHOD__);
|
||||
foreach ($ruleGroups as $group) {
|
||||
if ($group instanceof RuleGroup) {
|
||||
app('log')->debug(sprintf('Adding a rule group to the SearchRuleEngine: #%d ("%s")', $group->id, $group->title));
|
||||
Log::debug(sprintf('Adding a rule group to the SearchRuleEngine: #%d ("%s")', $group->id, $group->title));
|
||||
$this->groups->push($group);
|
||||
}
|
||||
}
|
||||
@@ -546,10 +546,10 @@ class SearchRuleEngine implements RuleEngineInterface
|
||||
|
||||
public function setRules(Collection $rules): void
|
||||
{
|
||||
app('log')->debug(__METHOD__);
|
||||
Log::debug(__METHOD__);
|
||||
foreach ($rules as $rule) {
|
||||
if ($rule instanceof Rule) {
|
||||
app('log')->debug(sprintf('Adding a rule to the SearchRuleEngine: #%d ("%s")', $rule->id, $rule->title));
|
||||
Log::debug(sprintf('Adding a rule to the SearchRuleEngine: #%d ("%s")', $rule->id, $rule->title));
|
||||
$this->rules->push($rule);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ class PiggyBankEventTransformer extends AbstractTransformer
|
||||
|
||||
return [
|
||||
'id' => (string) $event->id,
|
||||
'created_at' => $event->created_at->toAtomString(),
|
||||
'updated_at' => $event->updated_at->toAtomString(),
|
||||
'created_at' => $event->created_at?->toAtomString(),
|
||||
'updated_at' => $event->updated_at?->toAtomString(),
|
||||
'amount' => app('steam')->bcround($event->amount, $currency->decimal_places),
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
|
||||
@@ -144,12 +144,38 @@ class TransactionGroupTransformer extends AbstractTransformer
|
||||
|
||||
'foreign_currency_id' => $this->stringFromArray($transaction, 'foreign_currency_id', null),
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'],
|
||||
'foreign_currency_name' => $transaction['foreign_currency_name'],
|
||||
'foreign_currency_symbol' => $transaction['foreign_currency_symbol'],
|
||||
'foreign_currency_decimal_places' => $transaction['foreign_currency_decimal_places'],
|
||||
|
||||
'amount' => $amount,
|
||||
'foreign_amount' => $foreignAmount,
|
||||
|
||||
// native amount, defaults to NULL when convertToNative is false.
|
||||
'native_amount' => $transaction['native_amount'] ?? null,
|
||||
|
||||
// native currency, always present.
|
||||
'native_currency_id' => $transaction['native_currency']['id'] ?? null,
|
||||
'native_currency_code' => $transaction['native_currency']['code'] ?? null,
|
||||
'native_currency_name' => $transaction['native_currency']['name'] ?? null,
|
||||
'native_currency_symbol' => $transaction['native_currency']['symbol'] ?? null,
|
||||
'native_currency_decimal_places' => $transaction['native_currency']['decimal_places'] ?? null,
|
||||
|
||||
// source balance after
|
||||
'source_balance_after' => $transaction['source_balance_after'] ?? null,
|
||||
'source_balance_dirty' => $transaction['source_balance_dirty'],
|
||||
|
||||
// destination balance after
|
||||
'destination_balance_after' => $transaction['destination_balance_after'] ?? null,
|
||||
'destination_balance_dirty' => $transaction['destination_balance_dirty'],
|
||||
|
||||
// balance before and after, if not dirty.
|
||||
// 'running_balance_dirty' => $transaction['balance_dirty'] ?? false,
|
||||
// 'running_balance_before' => $transaction['balance_before'] ?? null,
|
||||
// 'running_balance_after' => $transaction['balance_after'] ?? null,
|
||||
|
||||
|
||||
|
||||
'description' => $transaction['description'],
|
||||
|
||||
'source_id' => (string) $transaction['source_account_id'],
|
||||
|
||||
19
app/User.php
19
app/User.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII;
|
||||
|
||||
use Deprecated;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Events\RequestedNewPassword;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
@@ -188,9 +189,8 @@ class User extends Authenticatable
|
||||
* Get the models LDAP domain.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getLdapDomain()
|
||||
{
|
||||
return $this->{$this->getLdapDomainColumn()};
|
||||
@@ -200,9 +200,8 @@ class User extends Authenticatable
|
||||
* Get the database column name of the domain.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getLdapDomainColumn()
|
||||
{
|
||||
return 'domain';
|
||||
@@ -212,9 +211,8 @@ class User extends Authenticatable
|
||||
* Get the models LDAP GUID.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getLdapGuid()
|
||||
{
|
||||
return $this->{$this->getLdapGuidColumn()};
|
||||
@@ -224,9 +222,8 @@ class User extends Authenticatable
|
||||
* Get the models LDAP GUID database column name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function getLdapGuidColumn()
|
||||
{
|
||||
return 'objectguid';
|
||||
@@ -468,9 +465,8 @@ class User extends Authenticatable
|
||||
* Set the models LDAP domain.
|
||||
*
|
||||
* @param string $domain
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function setLdapDomain($domain): void
|
||||
{
|
||||
$this->{$this->getLdapDomainColumn()} = $domain;
|
||||
@@ -480,9 +476,8 @@ class User extends Authenticatable
|
||||
* Set the models LDAP GUID.
|
||||
*
|
||||
* @param string $guid
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function setLdapGuid($guid): void
|
||||
{
|
||||
$this->{$this->getLdapGuidColumn()} = $guid;
|
||||
|
||||
39
changelog.md
39
changelog.md
@@ -3,6 +3,45 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 6.2.18 - 2025-06-20
|
||||
|
||||
### Changed
|
||||
|
||||
- Give more details about OAuth errors.
|
||||
- Currency seeder adds "RMB" instead of "CNY" for Chinese Yuan.
|
||||
|
||||
### Fixed
|
||||
|
||||
- [Issue 10454](https://github.com/firefly-iii/firefly-iii/issues/10454) (Bulk edit individually give an error) reported by @Rick45
|
||||
- [Issue 10470](https://github.com/firefly-iii/firefly-iii/issues/10470) (API endpoint `/api/v1/chart/account/overview` throws error) reported by @dreautall
|
||||
- Remove some leftover debug info
|
||||
|
||||
## 6.2.17 - 2025-06-12
|
||||
|
||||
### Changed
|
||||
|
||||
- Firefly III will trim account numbers with spaces for better matching during imports
|
||||
- Running balance is only updated when amounts or accounts change.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Transactions can't be linked to a piggy bank twice.
|
||||
- [Issue 10229](https://github.com/firefly-iii/firefly-iii/issues/10229) (Please show transaction ID in the Meta information) reported by @srikakulamts
|
||||
- [Issue 10382](https://github.com/firefly-iii/firefly-iii/issues/10382) (Have a link to search page on mobile layout) reported by @sergeolkhovik
|
||||
- [Issue 10399](https://github.com/firefly-iii/firefly-iii/issues/10399) (Can not apply rules to future dates) reported by @sanderr
|
||||
- [Issue 10403](https://github.com/firefly-iii/firefly-iii/issues/10403) (Piggy banks over multiple accounts are too restrictive) reported by @sanderr
|
||||
- [Issue 10413](https://github.com/firefly-iii/firefly-iii/issues/10413) (Piggy Bank math seems broken, deductions are not registered, Saved so far 0 but balance is positive) reported by @Skiri-ki
|
||||
- [Issue 10419](https://github.com/firefly-iii/firefly-iii/issues/10419) (Add quarters to report view to prefill date ranges) reported by @othmar52
|
||||
- [Issue 10426](https://github.com/firefly-iii/firefly-iii/issues/10426) (bcadd(): Argument #1 ($num1) is not well-formed) reported by @grgar
|
||||
- [Discussion 10427](https://github.com/orgs/firefly-iii/discussions/10427) ("Stop processing" doesn't seem to work? (6.2.12)) started by @rarosalion
|
||||
- [Issue 10432](https://github.com/firefly-iii/firefly-iii/issues/10432) (Error during upgrade 6.1.25 → 6.2.16: $piggyBank->account is null) reported by @Digi92
|
||||
- [Issue 10433](https://github.com/firefly-iii/firefly-iii/issues/10433) (500 error when using forgot password link (running in Docker)) reported by @jegelandsdal
|
||||
- [Issue 10441](https://github.com/firefly-iii/firefly-iii/issues/10441) (Missing spent per day info on mismatching budget limit periods) reported by @Kaotic3
|
||||
|
||||
### API
|
||||
|
||||
- Transactions now contain balance before/after.
|
||||
|
||||
## 6.2.16 - 2025-xx-xx
|
||||
|
||||
### Fixed
|
||||
|
||||
350
composer.lock
generated
350
composer.lock
generated
@@ -129,16 +129,16 @@
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.12.3",
|
||||
"version": "0.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/brick/math.git",
|
||||
"reference": "866551da34e9a618e64a819ee1e01c20d8a588ba"
|
||||
"reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba",
|
||||
"reference": "866551da34e9a618e64a819ee1e01c20d8a588ba",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04",
|
||||
"reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -177,7 +177,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/brick/math/issues",
|
||||
"source": "https://github.com/brick/math/tree/0.12.3"
|
||||
"source": "https://github.com/brick/math/tree/0.13.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -185,7 +185,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-28T13:11:00+00:00"
|
||||
"time": "2025-03-29T13:50:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "carbonphp/carbon-doctrine-types",
|
||||
@@ -939,16 +939,16 @@
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.18.0",
|
||||
"version": "2.18.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e"
|
||||
"reference": "59a123a3d459c5a23055802237cb317f609867e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e",
|
||||
"reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/59a123a3d459c5a23055802237cb317f609867e5",
|
||||
"reference": "59a123a3d459c5a23055802237cb317f609867e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -998,7 +998,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/filp/whoops/issues",
|
||||
"source": "https://github.com/filp/whoops/tree/2.18.0"
|
||||
"source": "https://github.com/filp/whoops/tree/2.18.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1006,7 +1006,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-15T12:00:00+00:00"
|
||||
"time": "2025-06-16T00:02:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
@@ -1879,20 +1879,20 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v12.16.0",
|
||||
"version": "v12.19.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "293bb1c70224faebfd3d4328e201c37115da055f"
|
||||
"reference": "4e6ec689ef704bb4bd282f29d9dd658dfb4fb262"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/293bb1c70224faebfd3d4328e201c37115da055f",
|
||||
"reference": "293bb1c70224faebfd3d4328e201c37115da055f",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/4e6ec689ef704bb4bd282f29d9dd658dfb4fb262",
|
||||
"reference": "4e6ec689ef704bb4bd282f29d9dd658dfb4fb262",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.11|^0.12",
|
||||
"brick/math": "^0.11|^0.12|^0.13",
|
||||
"composer-runtime-api": "^2.2",
|
||||
"doctrine/inflector": "^2.0.5",
|
||||
"dragonmantank/cron-expression": "^3.4",
|
||||
@@ -2090,7 +2090,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2025-05-27T15:49:44+00:00"
|
||||
"time": "2025-06-18T12:56:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/passport",
|
||||
@@ -2808,16 +2808,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
"version": "9.23.0",
|
||||
"version": "9.24.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/csv.git",
|
||||
"reference": "774008ad8a634448e4f8e288905e070e8b317ff3"
|
||||
"reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/774008ad8a634448e4f8e288905e070e8b317ff3",
|
||||
"reference": "774008ad8a634448e4f8e288905e070e8b317ff3",
|
||||
"url": "https://api.github.com/repos/thephpleague/csv/zipball/e0221a3f16aa2a823047d59fab5809d552e29bc8",
|
||||
"reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2827,14 +2827,14 @@
|
||||
"require-dev": {
|
||||
"ext-dom": "*",
|
||||
"ext-xdebug": "*",
|
||||
"friendsofphp/php-cs-fixer": "^3.69.0",
|
||||
"phpbench/phpbench": "^1.4.0",
|
||||
"phpstan/phpstan": "^1.12.18",
|
||||
"friendsofphp/php-cs-fixer": "^3.75.0",
|
||||
"phpbench/phpbench": "^1.4.1",
|
||||
"phpstan/phpstan": "^1.12.27",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.2.1",
|
||||
"phpstan/phpstan-phpunit": "^1.4.2",
|
||||
"phpstan/phpstan-strict-rules": "^1.6.2",
|
||||
"phpunit/phpunit": "^10.5.16 || ^11.5.7",
|
||||
"symfony/var-dumper": "^6.4.8 || ^7.2.3"
|
||||
"phpunit/phpunit": "^10.5.16 || ^11.5.22",
|
||||
"symfony/var-dumper": "^6.4.8 || ^7.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "Required to use the XMLConverter and the HTMLConverter classes",
|
||||
@@ -2895,7 +2895,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-28T06:52:04+00:00"
|
||||
"time": "2025-06-25T14:53:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/event",
|
||||
@@ -2953,16 +2953,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
"version": "3.29.1",
|
||||
"version": "3.30.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/flysystem.git",
|
||||
"reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319"
|
||||
"reference": "2203e3151755d874bb2943649dae1eb8533ac93e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319",
|
||||
"reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e",
|
||||
"reference": "2203e3151755d874bb2943649dae1eb8533ac93e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2986,13 +2986,13 @@
|
||||
"composer/semver": "^3.0",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-ftp": "*",
|
||||
"ext-mongodb": "^1.3",
|
||||
"ext-mongodb": "^1.3|^2",
|
||||
"ext-zip": "*",
|
||||
"friendsofphp/php-cs-fixer": "^3.5",
|
||||
"google/cloud-storage": "^1.23",
|
||||
"guzzlehttp/psr7": "^2.6",
|
||||
"microsoft/azure-storage-blob": "^1.1",
|
||||
"mongodb/mongodb": "^1.2",
|
||||
"mongodb/mongodb": "^1.2|^2",
|
||||
"phpseclib/phpseclib": "^3.0.36",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phpunit/phpunit": "^9.5.11|^10.0",
|
||||
@@ -3030,22 +3030,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/flysystem/issues",
|
||||
"source": "https://github.com/thephpleague/flysystem/tree/3.29.1"
|
||||
"source": "https://github.com/thephpleague/flysystem/tree/3.30.0"
|
||||
},
|
||||
"time": "2024-10-08T08:58:34+00:00"
|
||||
"time": "2025-06-25T13:29:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem-local",
|
||||
"version": "3.29.0",
|
||||
"version": "3.30.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/flysystem-local.git",
|
||||
"reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27"
|
||||
"reference": "6691915f77c7fb69adfb87dcd550052dc184ee10"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27",
|
||||
"reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10",
|
||||
"reference": "6691915f77c7fb69adfb87dcd550052dc184ee10",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3079,9 +3079,9 @@
|
||||
"local"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0"
|
||||
"source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0"
|
||||
},
|
||||
"time": "2024-08-09T21:24:39+00:00"
|
||||
"time": "2025-05-21T10:34:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/fractal",
|
||||
@@ -3473,22 +3473,22 @@
|
||||
},
|
||||
{
|
||||
"name": "mailersend/laravel-driver",
|
||||
"version": "v2.9.1",
|
||||
"version": "v2.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mailersend/mailersend-laravel-driver.git",
|
||||
"reference": "87fd5ab76808bbaac9221be0d306baef13e98725"
|
||||
"reference": "63acebb5064745076df27b1a80423986b6d7b69e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/87fd5ab76808bbaac9221be0d306baef13e98725",
|
||||
"reference": "87fd5ab76808bbaac9221be0d306baef13e98725",
|
||||
"url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/63acebb5064745076df27b1a80423986b6d7b69e",
|
||||
"reference": "63acebb5064745076df27b1a80423986b6d7b69e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||
"mailersend/mailersend": "^0.31.0",
|
||||
"mailersend/mailersend": "^0.34.0",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"php": ">=8.0",
|
||||
"php-http/guzzle7-adapter": "^1.0",
|
||||
@@ -3536,29 +3536,28 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/mailersend/mailersend-laravel-driver/issues",
|
||||
"source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.9.1"
|
||||
"source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.11.0"
|
||||
},
|
||||
"time": "2025-04-09T09:33:07+00:00"
|
||||
"time": "2025-06-04T08:47:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mailersend/mailersend",
|
||||
"version": "v0.31.0",
|
||||
"version": "v0.34.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mailersend/mailersend-php.git",
|
||||
"reference": "513ff83ee768526055ad52987cde401ea7218c67"
|
||||
"reference": "1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/513ff83ee768526055ad52987cde401ea7218c67",
|
||||
"reference": "513ff83ee768526055ad52987cde401ea7218c67",
|
||||
"url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab",
|
||||
"reference": "1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"beberlei/assert": "^3.2",
|
||||
"ext-json": "*",
|
||||
"illuminate/collections": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||
"php": "^7.4|^8.0",
|
||||
"php": "^7.4 || ^8.0 <8.5",
|
||||
"php-http/client-common": "^2.2",
|
||||
"php-http/discovery": "^1.9",
|
||||
"php-http/httplug": "^2.1",
|
||||
@@ -3603,9 +3602,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/mailersend/mailersend-php/issues",
|
||||
"source": "https://github.com/mailersend/mailersend-php/tree/v0.31.0"
|
||||
"source": "https://github.com/mailersend/mailersend-php/tree/v0.34.0"
|
||||
},
|
||||
"time": "2025-04-03T12:16:11+00:00"
|
||||
"time": "2025-06-04T07:53:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
@@ -3712,16 +3711,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "3.9.1",
|
||||
"version": "3.10.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/CarbonPHP/carbon.git",
|
||||
"reference": "ced71f79398ece168e24f7f7710462f462310d4d"
|
||||
"reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d",
|
||||
"reference": "ced71f79398ece168e24f7f7710462f462310d4d",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/1fd1935b2d90aef2f093c5e35f7ae1257c448d00",
|
||||
"reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3729,9 +3728,9 @@
|
||||
"ext-json": "*",
|
||||
"php": "^8.1",
|
||||
"psr/clock": "^1.0",
|
||||
"symfony/clock": "^6.3 || ^7.0",
|
||||
"symfony/clock": "^6.3.12 || ^7.0",
|
||||
"symfony/polyfill-mbstring": "^1.0",
|
||||
"symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0"
|
||||
"symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/clock-implementation": "1.0"
|
||||
@@ -3739,14 +3738,13 @@
|
||||
"require-dev": {
|
||||
"doctrine/dbal": "^3.6.3 || ^4.0",
|
||||
"doctrine/orm": "^2.15.2 || ^3.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.57.2",
|
||||
"friendsofphp/php-cs-fixer": "^3.75.0",
|
||||
"kylekatarnls/multi-tester": "^2.5.3",
|
||||
"ondrejmirtes/better-reflection": "^6.25.0.4",
|
||||
"phpmd/phpmd": "^2.15.0",
|
||||
"phpstan/extension-installer": "^1.3.1",
|
||||
"phpstan/phpstan": "^1.11.2",
|
||||
"phpunit/phpunit": "^10.5.20",
|
||||
"squizlabs/php_codesniffer": "^3.9.0"
|
||||
"phpstan/extension-installer": "^1.4.3",
|
||||
"phpstan/phpstan": "^2.1.17",
|
||||
"phpunit/phpunit": "^10.5.46",
|
||||
"squizlabs/php_codesniffer": "^3.13.0"
|
||||
},
|
||||
"bin": [
|
||||
"bin/carbon"
|
||||
@@ -3814,7 +3812,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-05-01T19:51:51+00:00"
|
||||
"time": "2025-06-21T15:19:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/schema",
|
||||
@@ -3880,16 +3878,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v4.0.6",
|
||||
"version": "v4.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "ce708655043c7050eb050df361c5e313cf708309"
|
||||
"reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309",
|
||||
"reference": "ce708655043c7050eb050df361c5e313cf708309",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2",
|
||||
"reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3960,29 +3958,29 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/utils/issues",
|
||||
"source": "https://github.com/nette/utils/tree/v4.0.6"
|
||||
"source": "https://github.com/nette/utils/tree/v4.0.7"
|
||||
},
|
||||
"time": "2025-03-30T21:06:30+00:00"
|
||||
"time": "2025-06-03T04:55:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nunomaduro/collision",
|
||||
"version": "v8.8.0",
|
||||
"version": "v8.8.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nunomaduro/collision.git",
|
||||
"reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8"
|
||||
"reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8",
|
||||
"reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8",
|
||||
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb",
|
||||
"reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"filp/whoops": "^2.18.0",
|
||||
"nunomaduro/termwind": "^2.3.0",
|
||||
"filp/whoops": "^2.18.1",
|
||||
"nunomaduro/termwind": "^2.3.1",
|
||||
"php": "^8.2.0",
|
||||
"symfony/console": "^7.2.5"
|
||||
"symfony/console": "^7.3.0"
|
||||
},
|
||||
"conflict": {
|
||||
"laravel/framework": "<11.44.2 || >=13.0.0",
|
||||
@@ -3990,15 +3988,15 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"brianium/paratest": "^7.8.3",
|
||||
"larastan/larastan": "^3.2",
|
||||
"laravel/framework": "^11.44.2 || ^12.6",
|
||||
"laravel/pint": "^1.21.2",
|
||||
"laravel/sail": "^1.41.0",
|
||||
"laravel/sanctum": "^4.0.8",
|
||||
"larastan/larastan": "^3.4.2",
|
||||
"laravel/framework": "^11.44.2 || ^12.18",
|
||||
"laravel/pint": "^1.22.1",
|
||||
"laravel/sail": "^1.43.1",
|
||||
"laravel/sanctum": "^4.1.1",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"orchestra/testbench-core": "^9.12.0 || ^10.1",
|
||||
"pestphp/pest": "^3.8.0",
|
||||
"sebastian/environment": "^7.2.0 || ^8.0"
|
||||
"orchestra/testbench-core": "^9.12.0 || ^10.4",
|
||||
"pestphp/pest": "^3.8.2",
|
||||
"sebastian/environment": "^7.2.1 || ^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@@ -4061,7 +4059,7 @@
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2025-04-03T14:33:09+00:00"
|
||||
"time": "2025-06-25T02:12:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nunomaduro/termwind",
|
||||
@@ -4807,16 +4805,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "3.0.43",
|
||||
"version": "3.0.45",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "709ec107af3cb2f385b9617be72af8cf62441d02"
|
||||
"reference": "bd81b90d5963c6b9d87de50357585375223f4dd8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02",
|
||||
"reference": "709ec107af3cb2f385b9617be72af8cf62441d02",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8",
|
||||
"reference": "bd81b90d5963c6b9d87de50357585375223f4dd8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4897,7 +4895,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.43"
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.45"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4913,7 +4911,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-12-14T21:12:59+00:00"
|
||||
"time": "2025-06-22T22:54:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pragmarx/google2fa",
|
||||
@@ -5747,20 +5745,20 @@
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "4.7.6",
|
||||
"version": "4.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "91039bc1faa45ba123c4328958e620d382ec7088"
|
||||
"reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
|
||||
"reference": "91039bc1faa45ba123c4328958e620d382ec7088",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28",
|
||||
"reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
|
||||
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13",
|
||||
"ext-json": "*",
|
||||
"php": "^8.0",
|
||||
"ramsey/collection": "^1.2 || ^2.0"
|
||||
@@ -5769,26 +5767,23 @@
|
||||
"rhumsaa/uuid": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"captainhook/captainhook": "^5.10",
|
||||
"captainhook/captainhook": "^5.25",
|
||||
"captainhook/plugin-composer": "^5.3",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
||||
"doctrine/annotations": "^1.8",
|
||||
"ergebnis/composer-normalize": "^2.15",
|
||||
"mockery/mockery": "^1.3",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
|
||||
"ergebnis/composer-normalize": "^2.47",
|
||||
"mockery/mockery": "^1.6",
|
||||
"paragonie/random-lib": "^2",
|
||||
"php-mock/php-mock": "^2.2",
|
||||
"php-mock/php-mock-mockery": "^1.3",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.1",
|
||||
"phpbench/phpbench": "^1.0",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpstan/phpstan-mockery": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.1",
|
||||
"phpunit/phpunit": "^8.5 || ^9",
|
||||
"ramsey/composer-repl": "^1.4",
|
||||
"slevomat/coding-standard": "^8.4",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.9"
|
||||
"php-mock/php-mock": "^2.6",
|
||||
"php-mock/php-mock-mockery": "^1.5",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.4.0",
|
||||
"phpbench/phpbench": "^1.2.14",
|
||||
"phpstan/extension-installer": "^1.4",
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"phpstan/phpstan-mockery": "^2.0",
|
||||
"phpstan/phpstan-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"slevomat/coding-standard": "^8.18",
|
||||
"squizlabs/php_codesniffer": "^3.13"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
||||
@@ -5823,19 +5818,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/uuid/issues",
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.7.6"
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.8.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ramsey",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-27T21:32:50+00:00"
|
||||
"time": "2025-06-01T06:28:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rcrowe/twigbridge",
|
||||
@@ -10487,16 +10472,16 @@
|
||||
},
|
||||
{
|
||||
"name": "larastan/larastan",
|
||||
"version": "v3.4.0",
|
||||
"version": "v3.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/larastan/larastan.git",
|
||||
"reference": "1042fa0c2ee490bb6da7381f3323f7292ad68222"
|
||||
"reference": "e8ccd73008487ba91da9877b373f8c447743f1ce"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/1042fa0c2ee490bb6da7381f3323f7292ad68222",
|
||||
"reference": "1042fa0c2ee490bb6da7381f3323f7292ad68222",
|
||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/e8ccd73008487ba91da9877b373f8c447743f1ce",
|
||||
"reference": "e8ccd73008487ba91da9877b373f8c447743f1ce",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10564,7 +10549,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/larastan/larastan/issues",
|
||||
"source": "https://github.com/larastan/larastan/tree/v3.4.0"
|
||||
"source": "https://github.com/larastan/larastan/tree/v3.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10572,7 +10557,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-04-22T09:44:59+00:00"
|
||||
"time": "2025-06-19T22:41:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel-json-api/testing",
|
||||
@@ -10784,16 +10769,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v5.4.0",
|
||||
"version": "v5.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "447a020a1f875a434d62f2a401f53b82a396e494"
|
||||
"reference": "ae59794362fe85e051a58ad36b289443f57be7a9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494",
|
||||
"reference": "447a020a1f875a434d62f2a401f53b82a396e494",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9",
|
||||
"reference": "ae59794362fe85e051a58ad36b289443f57be7a9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10836,9 +10821,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0"
|
||||
},
|
||||
"time": "2024-12-30T11:07:19+00:00"
|
||||
"time": "2025-05-31T08:24:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@@ -11231,16 +11216,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "12.3.0",
|
||||
"version": "12.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "9075a8efc66e11bc55c319062e147bdb06777267"
|
||||
"reference": "ddec29dfc128eba9c204389960f2063f3b7fa170"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9075a8efc66e11bc55c319062e147bdb06777267",
|
||||
"reference": "9075a8efc66e11bc55c319062e147bdb06777267",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ddec29dfc128eba9c204389960f2063f3b7fa170",
|
||||
"reference": "ddec29dfc128eba9c204389960f2063f3b7fa170",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11296,7 +11281,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.0"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11316,7 +11301,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-05-23T15:49:03+00:00"
|
||||
"time": "2025-06-18T08:58:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@@ -11565,16 +11550,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "12.1.6",
|
||||
"version": "12.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "2fdf0056c673c8f0f1eed00030be5f8243c1e6e0"
|
||||
"reference": "60a8ea2d8b2f070000051b56778009e11576e7d1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2fdf0056c673c8f0f1eed00030be5f8243c1e6e0",
|
||||
"reference": "2fdf0056c673c8f0f1eed00030be5f8243c1e6e0",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/60a8ea2d8b2f070000051b56778009e11576e7d1",
|
||||
"reference": "60a8ea2d8b2f070000051b56778009e11576e7d1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11588,15 +11573,15 @@
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=8.3",
|
||||
"phpunit/php-code-coverage": "^12.2.1",
|
||||
"phpunit/php-code-coverage": "^12.3.1",
|
||||
"phpunit/php-file-iterator": "^6.0.0",
|
||||
"phpunit/php-invoker": "^6.0.0",
|
||||
"phpunit/php-text-template": "^5.0.0",
|
||||
"phpunit/php-timer": "^8.0.0",
|
||||
"sebastian/cli-parser": "^4.0.0",
|
||||
"sebastian/comparator": "^7.0.1",
|
||||
"sebastian/comparator": "^7.1.0",
|
||||
"sebastian/diff": "^7.0.0",
|
||||
"sebastian/environment": "^8.0.1",
|
||||
"sebastian/environment": "^8.0.2",
|
||||
"sebastian/exporter": "^7.0.0",
|
||||
"sebastian/global-state": "^8.0.0",
|
||||
"sebastian/object-enumerator": "^7.0.0",
|
||||
@@ -11610,7 +11595,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "12.1-dev"
|
||||
"dev-main": "12.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -11642,7 +11627,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.1.6"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11666,25 +11651,25 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-05-21T12:36:31+00:00"
|
||||
"time": "2025-06-20T11:33:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
"version": "2.0.16",
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rectorphp/rector.git",
|
||||
"reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2"
|
||||
"reference": "d513dea45a94394b660e15c155d1fa27826f8e30"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2",
|
||||
"reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2",
|
||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/d513dea45a94394b660e15c155d1fa27826f8e30",
|
||||
"reference": "d513dea45a94394b660e15c155d1fa27826f8e30",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4|^8.0",
|
||||
"phpstan/phpstan": "^2.1.14"
|
||||
"phpstan/phpstan": "^2.1.17"
|
||||
},
|
||||
"conflict": {
|
||||
"rector/rector-doctrine": "*",
|
||||
@@ -11709,6 +11694,7 @@
|
||||
"MIT"
|
||||
],
|
||||
"description": "Instant Upgrade and Automated Refactoring of any PHP code",
|
||||
"homepage": "https://getrector.com/",
|
||||
"keywords": [
|
||||
"automation",
|
||||
"dev",
|
||||
@@ -11717,7 +11703,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/rectorphp/rector/issues",
|
||||
"source": "https://github.com/rectorphp/rector/tree/2.0.16"
|
||||
"source": "https://github.com/rectorphp/rector/tree/2.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11725,7 +11711,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-05-12T16:37:16+00:00"
|
||||
"time": "2025-06-24T20:26:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@@ -11786,16 +11772,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/comparator",
|
||||
"version": "7.0.1",
|
||||
"version": "7.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/comparator.git",
|
||||
"reference": "b478f34614f934e0291598d0c08cbaba9644bee5"
|
||||
"reference": "03d905327dccc0851c9a08d6a979dfc683826b6f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b478f34614f934e0291598d0c08cbaba9644bee5",
|
||||
"reference": "b478f34614f934e0291598d0c08cbaba9644bee5",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/03d905327dccc0851c9a08d6a979dfc683826b6f",
|
||||
"reference": "03d905327dccc0851c9a08d6a979dfc683826b6f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11806,7 +11792,7 @@
|
||||
"sebastian/exporter": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^12.0"
|
||||
"phpunit/phpunit": "^12.2"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "For comparing BcMath\\Number objects"
|
||||
@@ -11814,7 +11800,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "7.0-dev"
|
||||
"dev-main": "7.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -11854,15 +11840,27 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
||||
"security": "https://github.com/sebastianbergmann/comparator/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/7.0.1"
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/7.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://liberapay.com/sebastianbergmann",
|
||||
"type": "liberapay"
|
||||
},
|
||||
{
|
||||
"url": "https://thanks.dev/u/gh/sebastianbergmann",
|
||||
"type": "thanks_dev"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-07T07:00:32+00:00"
|
||||
"time": "2025-06-17T07:41:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/complexity",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user