mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-17 20:08:52 +00:00
Merge pull request #11340 from firefly-iii/release-1765124558
🤖 Automatically merge the PR into the develop branch.
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
/*
|
/*
|
||||||
* ValidatesFilePermissions.php
|
* ValidatesFilePermissions.php
|
||||||
* Copyright (c) 2025 james@firefly-iii.org
|
* Copyright (c) 2025 james@firefly-iii.org
|
||||||
@@ -33,7 +35,7 @@ class ValidatesFilePermissions extends Command
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'integrity:file-permissions';
|
protected $signature = 'integrity:file-permissions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
@@ -48,12 +50,14 @@ class ValidatesFilePermissions extends Command
|
|||||||
public function handle(): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
$directories = [storage_path('upload')];
|
$directories = [storage_path('upload')];
|
||||||
$errors = false;
|
$errors = false;
|
||||||
|
|
||||||
/** @var string $directory */
|
/** @var string $directory */
|
||||||
foreach ($directories as $directory) {
|
foreach ($directories as $directory) {
|
||||||
if (!is_dir($directory)) {
|
if (!is_dir($directory)) {
|
||||||
$this->friendlyError(sprintf('Directory "%s" cannot found. It is necessary to allow files to be uploaded.', $uploadDir));
|
$this->friendlyError(sprintf('Directory "%s" cannot found. It is necessary to allow files to be uploaded.', $uploadDir));
|
||||||
$errors = true;
|
$errors = true;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!is_writable($directory)) {
|
if (!is_writable($directory)) {
|
||||||
@@ -61,7 +65,7 @@ class ValidatesFilePermissions extends Command
|
|||||||
$errors = true;
|
$errors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(false === $errors) {
|
if (false === $errors) {
|
||||||
$this->friendlyInfo('All necessary file paths seem to exist, and are writeable.');
|
$this->friendlyInfo('All necessary file paths seem to exist, and are writeable.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
/*
|
/*
|
||||||
* TriggeredStoredTransactionGroup.php
|
* TriggeredStoredTransactionGroup.php
|
||||||
* Copyright (c) 2025 james@firefly-iii.org
|
* Copyright (c) 2025 james@firefly-iii.org
|
||||||
|
|||||||
@@ -70,14 +70,14 @@ class StoredGroupEventHandler
|
|||||||
}
|
}
|
||||||
Log::debug('Now in StoredGroupEventHandler::processRules()');
|
Log::debug('Now in StoredGroupEventHandler::processRules()');
|
||||||
|
|
||||||
$journals = $storedGroupEvent->transactionGroup->transactionJournals;
|
$journals = $storedGroupEvent->transactionGroup->transactionJournals;
|
||||||
$array = [];
|
$array = [];
|
||||||
|
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$array[] = $journal->id;
|
$array[] = $journal->id;
|
||||||
}
|
}
|
||||||
$journalIds = implode(',', $array);
|
$journalIds = implode(',', $array);
|
||||||
Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
||||||
|
|
||||||
// collect rules:
|
// collect rules:
|
||||||
@@ -86,10 +86,10 @@ class StoredGroupEventHandler
|
|||||||
|
|
||||||
// add the groups to the rule engine.
|
// add the groups to the rule engine.
|
||||||
// it should run the rules in the group and cancel the group if necessary.
|
// it should run the rules in the group and cancel the group if necessary.
|
||||||
$groups = $ruleGroupRepository->getRuleGroupsWithRules('store-journal');
|
$groups = $ruleGroupRepository->getRuleGroupsWithRules('store-journal');
|
||||||
|
|
||||||
// create and fire rule engine.
|
// create and fire rule engine.
|
||||||
$newRuleEngine = app(RuleEngineInterface::class);
|
$newRuleEngine = app(RuleEngineInterface::class);
|
||||||
$newRuleEngine->setUser($storedGroupEvent->transactionGroup->user);
|
$newRuleEngine->setUser($storedGroupEvent->transactionGroup->user);
|
||||||
$newRuleEngine->addOperator(['type' => 'journal_id', 'value' => $journalIds]);
|
$newRuleEngine->addOperator(['type' => 'journal_id', 'value' => $journalIds]);
|
||||||
$newRuleEngine->setRuleGroups($groups);
|
$newRuleEngine->setRuleGroups($groups);
|
||||||
@@ -98,7 +98,7 @@ class StoredGroupEventHandler
|
|||||||
|
|
||||||
private function recalculateCredit(StoredTransactionGroup $event): void
|
private function recalculateCredit(StoredTransactionGroup $event): void
|
||||||
{
|
{
|
||||||
$group = $event->transactionGroup;
|
$group = $event->transactionGroup;
|
||||||
|
|
||||||
/** @var CreditRecalculateService $object */
|
/** @var CreditRecalculateService $object */
|
||||||
$object = app(CreditRecalculateService::class);
|
$object = app(CreditRecalculateService::class);
|
||||||
@@ -114,10 +114,10 @@ class StoredGroupEventHandler
|
|||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
foreach ($event->transactionGroup->transactionJournals as $journal) {
|
foreach ($event->transactionGroup->transactionJournals as $journal) {
|
||||||
/** @var null|Transaction $source */
|
/** @var null|Transaction $source */
|
||||||
$source = $journal->transactions()->where('amount', '<', '0')->first();
|
$source = $journal->transactions()->where('amount', '<', '0')->first();
|
||||||
|
|
||||||
/** @var null|Transaction $dest */
|
/** @var null|Transaction $dest */
|
||||||
$dest = $journal->transactions()->where('amount', '>', '0')->first();
|
$dest = $journal->transactions()->where('amount', '>', '0')->first();
|
||||||
|
|
||||||
if (null !== $source) {
|
if (null !== $source) {
|
||||||
$repository->deleteStatisticsForModel($source->account, $journal->date);
|
$repository->deleteStatisticsForModel($source->account, $journal->date);
|
||||||
@@ -152,14 +152,14 @@ class StoredGroupEventHandler
|
|||||||
private function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void
|
private function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
$group = $storedGroupEvent->transactionGroup;
|
$group = $storedGroupEvent->transactionGroup;
|
||||||
if (false === $storedGroupEvent->fireWebhooks) {
|
if (false === $storedGroupEvent->fireWebhooks) {
|
||||||
Log::info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
Log::info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $group->user;
|
$user = $group->user;
|
||||||
|
|
||||||
/** @var MessageGeneratorInterface $engine */
|
/** @var MessageGeneratorInterface $engine */
|
||||||
$engine = app(MessageGeneratorInterface::class);
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
|
|||||||
@@ -71,8 +71,9 @@ class ExecutionController extends Controller
|
|||||||
public function execute(SelectTransactionsRequest $request, RuleGroup $ruleGroup): RedirectResponse
|
public function execute(SelectTransactionsRequest $request, RuleGroup $ruleGroup): RedirectResponse
|
||||||
{
|
{
|
||||||
// Get parameters specified by the user
|
// Get parameters specified by the user
|
||||||
$accounts = $request->get('accounts');
|
$accounts = $request->get('accounts');
|
||||||
$set = $this->repository->getAccountsById($accounts);
|
$set = $this->repository->getAccountsById($accounts);
|
||||||
|
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setAccounts($set);
|
$collector->setAccounts($set);
|
||||||
@@ -85,12 +86,13 @@ class ExecutionController extends Controller
|
|||||||
$endDate = new Carbon($request->get('end'));
|
$endDate = new Carbon($request->get('end'));
|
||||||
$collector->setEnd($endDate);
|
$collector->setEnd($endDate);
|
||||||
}
|
}
|
||||||
$final = $collector->getGroups();
|
$final = $collector->getGroups();
|
||||||
$ids = $final->pluck('id')->toArray();
|
$ids = $final->pluck('id')->toArray();
|
||||||
Log::debug(sprintf('Found %d groups collected from %d account(s)', $final->count(), $set->count()));
|
Log::debug(sprintf('Found %d groups collected from %d account(s)', $final->count(), $set->count()));
|
||||||
foreach (array_chunk($ids, 1337) as $setOfIds) {
|
foreach (array_chunk($ids, 1337) as $setOfIds) {
|
||||||
Log::debug(sprintf('Now processing %d groups', count($setOfIds)));
|
Log::debug(sprintf('Now processing %d groups', count($setOfIds)));
|
||||||
$groups = TransactionGroup::whereIn('id', $setOfIds)->get();
|
$groups = TransactionGroup::whereIn('id', $setOfIds)->get();
|
||||||
|
|
||||||
/** @var TransactionGroup $group */
|
/** @var TransactionGroup $group */
|
||||||
foreach ($groups as $group) {
|
foreach ($groups as $group) {
|
||||||
Log::debug(sprintf('Processing group #%d.', $group->id));
|
Log::debug(sprintf('Processing group #%d.', $group->id));
|
||||||
@@ -109,7 +111,7 @@ class ExecutionController extends Controller
|
|||||||
*
|
*
|
||||||
* @return Factory|View
|
* @return Factory|View
|
||||||
*/
|
*/
|
||||||
public function selectTransactions(RuleGroup $ruleGroup): Factory | \Illuminate\Contracts\View\View
|
public function selectTransactions(RuleGroup $ruleGroup): Factory|\Illuminate\Contracts\View\View
|
||||||
{
|
{
|
||||||
$subTitle = (string)trans('firefly.apply_rule_group_selection', ['title' => $ruleGroup->title]);
|
$subTitle = (string)trans('firefly.apply_rule_group_selection', ['title' => $ruleGroup->title]);
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class JournalUpdateService
|
|||||||
private ?Transaction $destinationTransaction = null;
|
private ?Transaction $destinationTransaction = null;
|
||||||
private array $metaDate
|
private array $metaDate
|
||||||
= ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date',
|
= ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date',
|
||||||
'invoice_date',];
|
'invoice_date', ];
|
||||||
private array $metaString
|
private array $metaString
|
||||||
= [
|
= [
|
||||||
'sepa_cc',
|
'sepa_cc',
|
||||||
@@ -112,7 +112,7 @@ class JournalUpdateService
|
|||||||
|
|
||||||
public function setTransactionGroup(TransactionGroup $transactionGroup): void
|
public function setTransactionGroup(TransactionGroup $transactionGroup): void
|
||||||
{
|
{
|
||||||
$this->transactionGroup = $transactionGroup;
|
$this->transactionGroup = $transactionGroup;
|
||||||
$this->billRepository->setUser($transactionGroup->user);
|
$this->billRepository->setUser($transactionGroup->user);
|
||||||
$this->categoryRepository->setUser($transactionGroup->user);
|
$this->categoryRepository->setUser($transactionGroup->user);
|
||||||
$this->budgetRepository->setUser($transactionGroup->user);
|
$this->budgetRepository->setUser($transactionGroup->user);
|
||||||
@@ -183,8 +183,8 @@ class JournalUpdateService
|
|||||||
|
|
||||||
private function hasValidSourceAccount(): bool
|
private function hasValidSourceAccount(): bool
|
||||||
{
|
{
|
||||||
$sourceId = $this->data['source_id'] ?? null;
|
$sourceId = $this->data['source_id'] ?? null;
|
||||||
$sourceName = $this->data['source_name'] ?? null;
|
$sourceName = $this->data['source_name'] ?? null;
|
||||||
Log::debug(sprintf('Now in hasValidSourceAccount("%s","%s").', $sourceId, $sourceName));
|
Log::debug(sprintf('Now in hasValidSourceAccount("%s","%s").', $sourceId, $sourceName));
|
||||||
|
|
||||||
if (!$this->hasFields(['source_id', 'source_name'])) {
|
if (!$this->hasFields(['source_id', 'source_name'])) {
|
||||||
@@ -199,11 +199,11 @@ class JournalUpdateService
|
|||||||
|
|
||||||
// make a new validator.
|
// make a new validator.
|
||||||
/** @var AccountValidator $validator */
|
/** @var AccountValidator $validator */
|
||||||
$validator = app(AccountValidator::class);
|
$validator = app(AccountValidator::class);
|
||||||
$validator->setTransactionType($expectedType);
|
$validator->setTransactionType($expectedType);
|
||||||
$validator->setUser($this->transactionJournal->user);
|
$validator->setUser($this->transactionJournal->user);
|
||||||
|
|
||||||
$result = $validator->validateSource(['id' => $sourceId, 'name' => $sourceName]);
|
$result = $validator->validateSource(['id' => $sourceId, 'name' => $sourceName]);
|
||||||
Log::debug(
|
Log::debug(
|
||||||
sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true))
|
sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true))
|
||||||
);
|
);
|
||||||
@@ -216,7 +216,7 @@ class JournalUpdateService
|
|||||||
|
|
||||||
private function hasFields(array $fields): bool
|
private function hasFields(array $fields): bool
|
||||||
{
|
{
|
||||||
return array_any($fields, fn($field): bool => array_key_exists($field, $this->data));
|
return array_any($fields, fn ($field): bool => array_key_exists($field, $this->data));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getOriginalSourceAccount(): Account
|
private function getOriginalSourceAccount(): Account
|
||||||
@@ -261,8 +261,8 @@ class JournalUpdateService
|
|||||||
private function hasValidDestinationAccount(): bool
|
private function hasValidDestinationAccount(): bool
|
||||||
{
|
{
|
||||||
Log::debug('Now in hasValidDestinationAccount().');
|
Log::debug('Now in hasValidDestinationAccount().');
|
||||||
$destId = $this->data['destination_id'] ?? null;
|
$destId = $this->data['destination_id'] ?? null;
|
||||||
$destName = $this->data['destination_name'] ?? null;
|
$destName = $this->data['destination_name'] ?? null;
|
||||||
|
|
||||||
if (!$this->hasFields(['destination_id', 'destination_name'])) {
|
if (!$this->hasFields(['destination_id', 'destination_name'])) {
|
||||||
Log::debug('No destination info submitted, grab the original data.');
|
Log::debug('No destination info submitted, grab the original data.');
|
||||||
@@ -272,12 +272,12 @@ class JournalUpdateService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make new account validator.
|
// make new account validator.
|
||||||
$expectedType = $this->getExpectedType();
|
$expectedType = $this->getExpectedType();
|
||||||
Log::debug(sprintf('(b) Expected type (new or unchanged) is %s', $expectedType));
|
Log::debug(sprintf('(b) Expected type (new or unchanged) is %s', $expectedType));
|
||||||
|
|
||||||
// make a new validator.
|
// make a new validator.
|
||||||
/** @var AccountValidator $validator */
|
/** @var AccountValidator $validator */
|
||||||
$validator = app(AccountValidator::class);
|
$validator = app(AccountValidator::class);
|
||||||
$validator->setTransactionType($expectedType);
|
$validator->setTransactionType($expectedType);
|
||||||
$validator->setUser($this->transactionJournal->user);
|
$validator->setUser($this->transactionJournal->user);
|
||||||
$validator->source = $this->getValidSourceAccount();
|
$validator->source = $this->getValidSourceAccount();
|
||||||
@@ -332,7 +332,7 @@ class JournalUpdateService
|
|||||||
return $this->getOriginalSourceAccount();
|
return $this->getOriginalSourceAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
$sourceInfo = [
|
$sourceInfo = [
|
||||||
'id' => (int)($this->data['source_id'] ?? null),
|
'id' => (int)($this->data['source_id'] ?? null),
|
||||||
'name' => $this->data['source_name'] ?? null,
|
'name' => $this->data['source_name'] ?? null,
|
||||||
'iban' => $this->data['source_iban'] ?? null,
|
'iban' => $this->data['source_iban'] ?? null,
|
||||||
@@ -360,8 +360,8 @@ class JournalUpdateService
|
|||||||
*/
|
*/
|
||||||
private function updateAccounts(): void
|
private function updateAccounts(): void
|
||||||
{
|
{
|
||||||
$source = $this->getValidSourceAccount();
|
$source = $this->getValidSourceAccount();
|
||||||
$destination = $this->getValidDestinationAccount();
|
$destination = $this->getValidDestinationAccount();
|
||||||
|
|
||||||
// cowardly refuse to update if both accounts are the same.
|
// cowardly refuse to update if both accounts are the same.
|
||||||
if ($source->id === $destination->id) {
|
if ($source->id === $destination->id) {
|
||||||
@@ -374,7 +374,7 @@ class JournalUpdateService
|
|||||||
$origSourceTransaction->account()->associate($source);
|
$origSourceTransaction->account()->associate($source);
|
||||||
$origSourceTransaction->save();
|
$origSourceTransaction->save();
|
||||||
|
|
||||||
$destTransaction = $this->getDestinationTransaction();
|
$destTransaction = $this->getDestinationTransaction();
|
||||||
$destTransaction->account()->associate($destination);
|
$destTransaction->account()->associate($destination);
|
||||||
$destTransaction->save();
|
$destTransaction->save();
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ class JournalUpdateService
|
|||||||
return $this->getOriginalDestinationAccount();
|
return $this->getOriginalDestinationAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
$destInfo = [
|
$destInfo = [
|
||||||
'id' => (int)($this->data['destination_id'] ?? null),
|
'id' => (int)($this->data['destination_id'] ?? null),
|
||||||
'name' => $this->data['destination_name'] ?? null,
|
'name' => $this->data['destination_name'] ?? null,
|
||||||
'iban' => $this->data['destination_iban'] ?? null,
|
'iban' => $this->data['destination_iban'] ?? null,
|
||||||
@@ -425,7 +425,7 @@ class JournalUpdateService
|
|||||||
{
|
{
|
||||||
Log::debug('Now in updateType()');
|
Log::debug('Now in updateType()');
|
||||||
if ($this->hasFields(['type'])) {
|
if ($this->hasFields(['type'])) {
|
||||||
$type = 'opening-balance' === $this->data['type'] ? 'opening balance' : $this->data['type'];
|
$type = 'opening-balance' === $this->data['type'] ? 'opening balance' : $this->data['type'];
|
||||||
Log::debug(
|
Log::debug(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Trying to change journal #%d from a %s to a %s.',
|
'Trying to change journal #%d from a %s to a %s.',
|
||||||
@@ -458,9 +458,9 @@ class JournalUpdateService
|
|||||||
{
|
{
|
||||||
$type = $this->transactionJournal->transactionType->type;
|
$type = $this->transactionJournal->transactionType->type;
|
||||||
if ((
|
if ((
|
||||||
array_key_exists('bill_id', $this->data)
|
array_key_exists('bill_id', $this->data)
|
||||||
|| array_key_exists('bill_name', $this->data)
|
|| array_key_exists('bill_name', $this->data)
|
||||||
)
|
)
|
||||||
&& TransactionTypeEnum::WITHDRAWAL->value === $type
|
&& TransactionTypeEnum::WITHDRAWAL->value === $type
|
||||||
) {
|
) {
|
||||||
$billId = (int)($this->data['bill_id'] ?? 0);
|
$billId = (int)($this->data['bill_id'] ?? 0);
|
||||||
@@ -477,7 +477,7 @@ class JournalUpdateService
|
|||||||
private function updateField(string $fieldName): void
|
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];
|
$value = $this->data[$fieldName];
|
||||||
|
|
||||||
if ('date' === $fieldName) {
|
if ('date' === $fieldName) {
|
||||||
if (!$value instanceof Carbon) {
|
if (!$value instanceof Carbon) {
|
||||||
@@ -574,7 +574,7 @@ class JournalUpdateService
|
|||||||
if ($this->hasFields([$field])) {
|
if ($this->hasFields([$field])) {
|
||||||
$value = '' === $this->data[$field] ? null : $this->data[$field];
|
$value = '' === $this->data[$field] ? null : $this->data[$field];
|
||||||
Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value));
|
Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value));
|
||||||
$set = [
|
$set = [
|
||||||
'journal' => $this->transactionJournal,
|
'journal' => $this->transactionJournal,
|
||||||
'name' => $field,
|
'name' => $field,
|
||||||
'data' => $value,
|
'data' => $value,
|
||||||
@@ -593,7 +593,7 @@ class JournalUpdateService
|
|||||||
if ($this->hasFields([$field])) {
|
if ($this->hasFields([$field])) {
|
||||||
try {
|
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
|
} catch (InvalidDateException|InvalidFormatException $e) { // @phpstan-ignore-line
|
||||||
Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage()));
|
Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage()));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -622,19 +622,19 @@ class JournalUpdateService
|
|||||||
if (!$this->hasFields(['currency_id', 'currency_code'])) {
|
if (!$this->hasFields(['currency_id', 'currency_code'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$currencyId = $this->data['currency_id'] ?? null;
|
$currencyId = $this->data['currency_id'] ?? null;
|
||||||
$currencyCode = $this->data['currency_code'] ?? null;
|
$currencyCode = $this->data['currency_code'] ?? null;
|
||||||
$currency = $this->currencyRepository->findCurrency($currencyId, $currencyCode);
|
$currency = $this->currencyRepository->findCurrency($currencyId, $currencyCode);
|
||||||
// update currency everywhere.
|
// update currency everywhere.
|
||||||
$this->transactionJournal->transaction_currency_id = $currency->id;
|
$this->transactionJournal->transaction_currency_id = $currency->id;
|
||||||
$this->transactionJournal->save();
|
$this->transactionJournal->save();
|
||||||
|
|
||||||
$source = $this->getSourceTransaction();
|
$source = $this->getSourceTransaction();
|
||||||
$source->transaction_currency_id = $currency->id;
|
$source->transaction_currency_id = $currency->id;
|
||||||
$source->save();
|
$source->save();
|
||||||
|
|
||||||
$dest = $this->getDestinationTransaction();
|
$dest = $this->getDestinationTransaction();
|
||||||
$dest->transaction_currency_id = $currency->id;
|
$dest->transaction_currency_id = $currency->id;
|
||||||
$dest->save();
|
$dest->save();
|
||||||
|
|
||||||
// refresh transactions.
|
// refresh transactions.
|
||||||
@@ -650,7 +650,7 @@ class JournalUpdateService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $this->data['amount'] ?? '';
|
$value = $this->data['amount'] ?? '';
|
||||||
Log::debug(sprintf('Amount is now "%s"', $value));
|
Log::debug(sprintf('Amount is now "%s"', $value));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -664,28 +664,31 @@ class JournalUpdateService
|
|||||||
$origSourceTransaction->amount = app('steam')->negative($amount);
|
$origSourceTransaction->amount = app('steam')->negative($amount);
|
||||||
$origSourceTransaction->balance_dirty = true;
|
$origSourceTransaction->balance_dirty = true;
|
||||||
$origSourceTransaction->save();
|
$origSourceTransaction->save();
|
||||||
$destTransaction = $this->getDestinationTransaction();
|
$destTransaction = $this->getDestinationTransaction();
|
||||||
$originalAmount = $destTransaction->amount;
|
$originalAmount = $destTransaction->amount;
|
||||||
$destTransaction->amount = app('steam')->positive($amount);
|
$destTransaction->amount = app('steam')->positive($amount);
|
||||||
$destTransaction->balance_dirty = true;
|
$destTransaction->balance_dirty = true;
|
||||||
$destTransaction->save();
|
$destTransaction->save();
|
||||||
// refresh transactions.
|
// refresh transactions.
|
||||||
$this->sourceTransaction->refresh();
|
$this->sourceTransaction->refresh();
|
||||||
$this->destinationTransaction->refresh();
|
$this->destinationTransaction->refresh();
|
||||||
Log::debug(sprintf('Updated amount to "%s"', $amount));
|
Log::debug(sprintf('Updated amount to "%s"', $amount));
|
||||||
|
|
||||||
event(new TriggeredAuditLog($this->transactionGroup->user, $this->transactionGroup, 'update_amount',
|
event(new TriggeredAuditLog(
|
||||||
[
|
$this->transactionGroup->user,
|
||||||
'currency_symbol' => $destTransaction->transactionCurrency->symbol,
|
$this->transactionGroup,
|
||||||
'decimal_places' => $destTransaction->transactionCurrency->decimal_places,
|
'update_amount',
|
||||||
'amount' => $originalAmount,
|
[
|
||||||
],
|
'currency_symbol' => $destTransaction->transactionCurrency->symbol,
|
||||||
[
|
'decimal_places' => $destTransaction->transactionCurrency->decimal_places,
|
||||||
'currency_symbol' => $destTransaction->transactionCurrency->symbol,
|
'amount' => $originalAmount,
|
||||||
'decimal_places' => $destTransaction->transactionCurrency->decimal_places,
|
],
|
||||||
'amount' => $value,
|
[
|
||||||
]
|
'currency_symbol' => $destTransaction->transactionCurrency->symbol,
|
||||||
));
|
'decimal_places' => $destTransaction->transactionCurrency->decimal_places,
|
||||||
|
'amount' => $value,
|
||||||
|
]
|
||||||
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,9 +727,9 @@ class JournalUpdateService
|
|||||||
// if the transaction is a TRANSFER, and the foreign amount and currency are set (like they seem to be)
|
// if the transaction is a TRANSFER, and the foreign amount and currency are set (like they seem to be)
|
||||||
// the correct fields to update in the destination transaction are NOT the foreign amount and currency
|
// the correct fields to update in the destination transaction are NOT the foreign amount and currency
|
||||||
// but rather the normal amount and currency. This is new behavior.
|
// but rather the normal amount and currency. This is new behavior.
|
||||||
$isTransfer = TransactionTypeEnum::TRANSFER->value === $this->transactionJournal->transactionType->type;
|
$isTransfer = TransactionTypeEnum::TRANSFER->value === $this->transactionJournal->transactionType->type;
|
||||||
// also check if it is not between an asset account and a liability, because then the same rule applies.
|
// also check if it is not between an asset account and a liability, because then the same rule applies.
|
||||||
$isBetween = $this->isBetweenAssetAndLiability();
|
$isBetween = $this->isBetweenAssetAndLiability();
|
||||||
|
|
||||||
if ($isTransfer || $isBetween) {
|
if ($isTransfer || $isBetween) {
|
||||||
Log::debug('Switch amounts, store in amount and not foreign_amount');
|
Log::debug('Switch amounts, store in amount and not foreign_amount');
|
||||||
@@ -762,8 +765,8 @@ class JournalUpdateService
|
|||||||
$source->foreign_amount = null;
|
$source->foreign_amount = null;
|
||||||
$source->save();
|
$source->save();
|
||||||
|
|
||||||
$dest->foreign_currency_id = null;
|
$dest->foreign_currency_id = null;
|
||||||
$dest->foreign_amount = null;
|
$dest->foreign_amount = null;
|
||||||
$dest->save();
|
$dest->save();
|
||||||
Log::debug(sprintf('Foreign amount is "%s" so remove foreign amount info.', $amount));
|
Log::debug(sprintf('Foreign amount is "%s" so remove foreign amount info.', $amount));
|
||||||
}
|
}
|
||||||
@@ -777,7 +780,7 @@ class JournalUpdateService
|
|||||||
private function isBetweenAssetAndLiability(): bool
|
private function isBetweenAssetAndLiability(): bool
|
||||||
{
|
{
|
||||||
/** @var null|Transaction $sourceTransaction */
|
/** @var null|Transaction $sourceTransaction */
|
||||||
$sourceTransaction = $this->transactionJournal->transactions()->where('amount', '<', 0)->first();
|
$sourceTransaction = $this->transactionJournal->transactions()->where('amount', '<', 0)->first();
|
||||||
|
|
||||||
/** @var null|Transaction $destinationTransaction */
|
/** @var null|Transaction $destinationTransaction */
|
||||||
$destinationTransaction = $this->transactionJournal->transactions()->where('amount', '>', 0)->first();
|
$destinationTransaction = $this->transactionJournal->transactions()->where('amount', '>', 0)->first();
|
||||||
@@ -792,15 +795,15 @@ class JournalUpdateService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$source = $sourceTransaction->account;
|
$source = $sourceTransaction->account;
|
||||||
$destination = $destinationTransaction->account;
|
$destination = $destinationTransaction->account;
|
||||||
|
|
||||||
if (null === $source || null === $destination) {
|
if (null === $source || null === $destination) {
|
||||||
Log::warning('Either is false, stop.');
|
Log::warning('Either is false, stop.');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$sourceTypes = [AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value];
|
$sourceTypes = [AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value];
|
||||||
|
|
||||||
// source is liability, destination is asset
|
// source is liability, destination is asset
|
||||||
if (in_array($source->accountType->type, $sourceTypes, true) && AccountTypeEnum::ASSET->value === $destination->accountType->type) {
|
if (in_array($source->accountType->type, $sourceTypes, true) && AccountTypeEnum::ASSET->value === $destination->accountType->type) {
|
||||||
|
|||||||
29
composer.lock
generated
29
composer.lock
generated
@@ -3543,22 +3543,22 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mailersend/laravel-driver",
|
"name": "mailersend/laravel-driver",
|
||||||
"version": "v2.9.1",
|
"version": "v2.12.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/mailersend/mailersend-laravel-driver.git",
|
"url": "https://github.com/mailersend/mailersend-laravel-driver.git",
|
||||||
"reference": "87fd5ab76808bbaac9221be0d306baef13e98725"
|
"reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/87fd5ab76808bbaac9221be0d306baef13e98725",
|
"url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/15e1ec41e29e65d3ca226929c65804190aaa93eb",
|
||||||
"reference": "87fd5ab76808bbaac9221be0d306baef13e98725",
|
"reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0",
|
"illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||||
"mailersend/mailersend": "^0.31.0",
|
"mailersend/mailersend": "^0.35.0",
|
||||||
"nyholm/psr7": "^1.5",
|
"nyholm/psr7": "^1.5",
|
||||||
"php": ">=8.0",
|
"php": ">=8.0",
|
||||||
"php-http/guzzle7-adapter": "^1.0",
|
"php-http/guzzle7-adapter": "^1.0",
|
||||||
@@ -3606,29 +3606,28 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/mailersend/mailersend-laravel-driver/issues",
|
"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.12.0"
|
||||||
},
|
},
|
||||||
"time": "2025-04-09T09:33:07+00:00"
|
"time": "2025-10-28T14:59:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mailersend/mailersend",
|
"name": "mailersend/mailersend",
|
||||||
"version": "v0.31.0",
|
"version": "v0.35.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/mailersend/mailersend-php.git",
|
"url": "https://github.com/mailersend/mailersend-php.git",
|
||||||
"reference": "513ff83ee768526055ad52987cde401ea7218c67"
|
"reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/513ff83ee768526055ad52987cde401ea7218c67",
|
"url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/f1696cf9e727e9503fbc5882d2a111bd966ad276",
|
||||||
"reference": "513ff83ee768526055ad52987cde401ea7218c67",
|
"reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"beberlei/assert": "^3.2",
|
"beberlei/assert": "^3.2",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"illuminate/collections": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0",
|
"php": "^7.4 || ^8.0 <8.5",
|
||||||
"php": "^7.4|^8.0",
|
|
||||||
"php-http/client-common": "^2.2",
|
"php-http/client-common": "^2.2",
|
||||||
"php-http/discovery": "^1.9",
|
"php-http/discovery": "^1.9",
|
||||||
"php-http/httplug": "^2.1",
|
"php-http/httplug": "^2.1",
|
||||||
@@ -3673,9 +3672,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/mailersend/mailersend-php/issues",
|
"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.35.0"
|
||||||
},
|
},
|
||||||
"time": "2025-04-03T12:16:11+00:00"
|
"time": "2025-10-28T13:11:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ return [
|
|||||||
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
||||||
// see cer.php for exchange rates feature flag.
|
// see cer.php for exchange rates feature flag.
|
||||||
],
|
],
|
||||||
'version' => 'develop/2025-12-06',
|
'version' => 'develop/2025-12-07',
|
||||||
'build_time' => 1765004025,
|
'build_time' => 1765124451,
|
||||||
'api_version' => '2.1.0', // field is no longer used.
|
'api_version' => '2.1.0', // field is no longer used.
|
||||||
'db_version' => 28, // field is no longer used.
|
'db_version' => 28, // field is no longer used.
|
||||||
|
|
||||||
|
|||||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -4075,9 +4075,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/baseline-browser-mapping": {
|
"node_modules/baseline-browser-mapping": {
|
||||||
"version": "2.9.3",
|
"version": "2.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.4.tgz",
|
||||||
"integrity": "sha512-8QdH6czo+G7uBsNo0GiUfouPN1lRzKdJTGnKXwe12gkFbnnOUaUKGN55dMkfy+mnxmvjwl9zcI4VncczcVXDhA==",
|
"integrity": "sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
Reference in New Issue
Block a user