mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-04-29 11:03:00 +00:00
Unify more event handlers.
This commit is contained in:
@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Transaction;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Transaction\UpdateRequest;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventFlags;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventObjects;
|
||||
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
@@ -55,7 +56,7 @@ class UpdateController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$admin = auth()->user();
|
||||
|
||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->groupRepository->setUser($admin);
|
||||
@@ -73,51 +74,51 @@ class UpdateController extends Controller
|
||||
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
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();
|
||||
$data = $request->getAll();
|
||||
$oldHash = $this->groupRepository->getCompareHash($transactionGroup);
|
||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||
$newHash = $this->groupRepository->getCompareHash($transactionGroup);
|
||||
$manager = $this->getManager();
|
||||
|
||||
Preferences::mark();
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
$runRecalculations = $oldHash !== $newHash;
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
$runRecalculations = $oldHash !== $newHash;
|
||||
|
||||
$flags = new TransactionGroupEventFlags();
|
||||
$flags->applyRules = $applyRules;
|
||||
$flags->fireWebhooks = $fireWebhooks;
|
||||
$flags->recalculateCredit = $runRecalculations;
|
||||
event(new UpdatedSingleTransactionGroup($transactionGroup, $flags));
|
||||
$objects = TransactionGroupEventObjects::collectFromTransactionGroup($transactionGroup);
|
||||
event(new UpdatedSingleTransactionGroup($flags, $objects));
|
||||
|
||||
/** @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.
|
||||
->setTransactionGroup($transactionGroup)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
;
|
||||
->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);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventFlags;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventObjects;
|
||||
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@@ -49,18 +50,20 @@ class CorrectsGroupAccounts extends Command
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($res as $journal) {
|
||||
if ((int) $journal->the_count > 1) {
|
||||
$groups[] = (int) $journal->transaction_group_id;
|
||||
if ((int)$journal->the_count > 1) {
|
||||
$groups[] = (int)$journal->transaction_group_id;
|
||||
}
|
||||
}
|
||||
$flags = new TransactionGroupEventFlags();
|
||||
$flags->applyRules = true;
|
||||
$flags->fireWebhooks = true;
|
||||
$flags->recalculateCredit = true;
|
||||
$objects = new TransactionGroupEventObjects();
|
||||
foreach ($groups as $groupId) {
|
||||
$group = TransactionGroup::find($groupId);
|
||||
$flags = new TransactionGroupEventFlags();
|
||||
$flags->applyRules = true;
|
||||
$flags->fireWebhooks = true;
|
||||
$flags->recalculateCredit = true;
|
||||
event(new UpdatedSingleTransactionGroup($group, $flags));
|
||||
$group = TransactionGroup::find($groupId);
|
||||
$objects->appendFromTransactionGroup($group);
|
||||
}
|
||||
event(new UpdatedSingleTransactionGroup($flags, $objects));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,21 +41,26 @@ class TransactionGroupEventObjects
|
||||
{
|
||||
Log::debug(sprintf('collectFromTransactionGroup(#%d)', $transactionGroup->id));
|
||||
$object = new self();
|
||||
$object->transactionGroups->push($transactionGroup);
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($transactionGroup->transactionJournals as $journal) {
|
||||
$object->transactionJournals->push($journal);
|
||||
$object->budgets = $object->tags->merge($journal->budgets);
|
||||
$object->categories = $object->tags->merge($journal->categories);
|
||||
$object->tags = $object->tags->merge($journal->tags);
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journal->transactions as $transaction) {
|
||||
$object->accounts->push($transaction->account);
|
||||
}
|
||||
}
|
||||
$object->appendFromTransactionGroup($transactionGroup);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function appendFromTransactionGroup(TransactionGroup $transactionGroup): void
|
||||
{
|
||||
$this->transactionGroups->push($transactionGroup);
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($transactionGroup->transactionJournals as $journal) {
|
||||
$this->transactionJournals->push($journal);
|
||||
$this->budgets = $this->budgets->merge($journal->budgets);
|
||||
$this->categories = $this->categories->merge($journal->categories);
|
||||
$this->tags = $this->tags->merge($journal->tags);
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journal->transactions as $transaction) {
|
||||
$this->accounts->push($transaction->account);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,5 @@ class UpdatedSingleTransactionGroup extends Event
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*/
|
||||
public function __construct(
|
||||
public TransactionGroup $transactionGroup,
|
||||
public TransactionGroupEventFlags $flags
|
||||
) {}
|
||||
public function __construct(public TransactionGroupEventFlags $flags, public TransactionGroupEventObjects $objects) {}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Controllers\Transaction;
|
||||
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventFlags;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventObjects;
|
||||
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\BulkEditJournalRequest;
|
||||
@@ -57,7 +58,7 @@ class BulkController extends Controller
|
||||
|
||||
$this->middleware(function ($request, $next) {
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
app('view')->share('title', (string) trans('firefly.transactions'));
|
||||
app('view')->share('title', (string)trans('firefly.transactions'));
|
||||
app('view')->share('mainTitleIcon', 'fa-exchange');
|
||||
|
||||
return $next($request);
|
||||
@@ -71,9 +72,9 @@ class BulkController extends Controller
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function edit(array $journals): Factory|\Illuminate\Contracts\View\View
|
||||
public function edit(array $journals): Factory | \Illuminate\Contracts\View\View
|
||||
{
|
||||
$subTitle = (string) trans('firefly.mass_bulk_journals');
|
||||
$subTitle = (string)trans('firefly.mass_bulk_journals');
|
||||
|
||||
$this->rememberPreviousUrl('transactions.bulk-edit.url');
|
||||
|
||||
@@ -84,7 +85,7 @@ class BulkController extends Controller
|
||||
$budgetRepos = app(BudgetRepositoryInterface::class);
|
||||
$budgetList = app('expandedform')->makeSelectListWithEmpty($budgetRepos->getActiveBudgets());
|
||||
|
||||
return view('transactions.bulk.edit', ['journals' => $journals, 'subTitle' => $subTitle, 'budgetList' => $budgetList]);
|
||||
return view('transactions.bulk.edit', ['journals' => $journals, 'subTitle' => $subTitle, 'budgetList' => $budgetList]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,18 +93,18 @@ class BulkController extends Controller
|
||||
*
|
||||
* @return Application|Redirector|RedirectResponse
|
||||
*/
|
||||
public function update(BulkEditJournalRequest $request): Redirector|RedirectResponse
|
||||
public function update(BulkEditJournalRequest $request): Redirector | RedirectResponse
|
||||
{
|
||||
$journalIds = $request->get('journals');
|
||||
$journalIds = is_array($journalIds) ? $journalIds : [];
|
||||
$ignoreCategory = 1 === (int) $request->get('ignore_category');
|
||||
$ignoreBudget = 1 === (int) $request->get('ignore_budget');
|
||||
$ignoreCategory = 1 === (int)$request->get('ignore_category');
|
||||
$ignoreBudget = 1 === (int)$request->get('ignore_budget');
|
||||
$tagsAction = $request->get('tags_action');
|
||||
$collection = new Collection();
|
||||
$count = 0;
|
||||
|
||||
foreach ($journalIds as $journalId) {
|
||||
$journalId = (int) $journalId;
|
||||
$journalId = (int)$journalId;
|
||||
$journal = $this->repository->find($journalId);
|
||||
if (null !== $journal) {
|
||||
$resultA = $this->updateJournalBudget($journal, $ignoreBudget, $request->integer('budget_id'));
|
||||
@@ -116,13 +117,15 @@ class BulkController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$flags = new TransactionGroupEventFlags();
|
||||
$flags = new TransactionGroupEventFlags();
|
||||
$objects = new TransactionGroupEventObjects();
|
||||
|
||||
// run rules on changed journals:
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($collection as $journal) {
|
||||
event(new UpdatedSingleTransactionGroup($journal->transactionGroup, $flags));
|
||||
$objects->appendFromTransactionGroup($journal->transactionGroup);
|
||||
}
|
||||
event(new UpdatedSingleTransactionGroup($flags, $objects));
|
||||
|
||||
Preferences::mark();
|
||||
$request->session()->flash('success', trans_choice('firefly.mass_edited_transactions_success', $count));
|
||||
|
||||
@@ -27,6 +27,7 @@ use Exception;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventFlags;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventObjects;
|
||||
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
@@ -72,7 +73,7 @@ class ConvertController extends Controller
|
||||
// some useful repositories:
|
||||
$this->middleware(function ($request, $next) {
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
app('view')->share('title', (string) trans('firefly.transactions'));
|
||||
app('view')->share('title', (string)trans('firefly.transactions'));
|
||||
app('view')->share('mainTitleIcon', 'fa-exchange');
|
||||
|
||||
return $next($request);
|
||||
@@ -86,23 +87,23 @@ class ConvertController extends Controller
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index(TransactionType $destinationType, TransactionGroup $group): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
|
||||
public function index(TransactionType $destinationType, TransactionGroup $group): Factory | \Illuminate\Contracts\View\View | Redirector | RedirectResponse
|
||||
{
|
||||
if (!$this->isEditableGroup($group)) {
|
||||
return $this->redirectGroupToAccount($group);
|
||||
}
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
||||
/** @var TransactionJournal $first */
|
||||
$first = $group->transactionJournals()->first();
|
||||
$sourceType = $first->transactionType;
|
||||
$first = $group->transactionJournals()->first();
|
||||
$sourceType = $first->transactionType;
|
||||
|
||||
$groupTitle = $group->title ?? $first->description;
|
||||
$groupArray = $transformer->transformObject($group);
|
||||
$subTitle = (string) trans('firefly.convert_to_'.$destinationType->type, ['description' => $groupTitle]);
|
||||
$subTitleIcon = 'fa-exchange';
|
||||
$groupTitle = $group->title ?? $first->description;
|
||||
$groupArray = $transformer->transformObject($group);
|
||||
$subTitle = (string)trans('firefly.convert_to_' . $destinationType->type, ['description' => $groupTitle]);
|
||||
$subTitleIcon = 'fa-exchange';
|
||||
|
||||
// get a list of asset accounts and liabilities and stuff, in various combinations:
|
||||
$validDepositSources = $this->getValidDepositSources();
|
||||
@@ -111,11 +112,11 @@ class ConvertController extends Controller
|
||||
$assets = $this->getAssetAccounts();
|
||||
|
||||
// old input variables:
|
||||
$preFilled = ['source_name' => old('source_name')];
|
||||
$preFilled = ['source_name' => old('source_name')];
|
||||
|
||||
if ($sourceType->type === $destinationType->type) { // cannot convert to its own type.
|
||||
Log::debug('This is already a transaction of the expected type..');
|
||||
session()->flash('info', (string) trans('firefly.convert_is_already_type_'.$destinationType->type));
|
||||
session()->flash('info', (string)trans('firefly.convert_is_already_type_' . $destinationType->type));
|
||||
|
||||
return redirect(route('transactions.show', [$group->id]));
|
||||
}
|
||||
@@ -141,26 +142,26 @@ class ConvertController extends Controller
|
||||
// make repositories
|
||||
$liabilityTypes = [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::LOAN->value];
|
||||
$accountList = $this->accountRepository->getActiveAccountsByType([
|
||||
AccountTypeEnum::REVENUE->value,
|
||||
AccountTypeEnum::CASH->value,
|
||||
AccountTypeEnum::LOAN->value,
|
||||
AccountTypeEnum::DEBT->value,
|
||||
AccountTypeEnum::MORTGAGE->value,
|
||||
]);
|
||||
AccountTypeEnum::REVENUE->value,
|
||||
AccountTypeEnum::CASH->value,
|
||||
AccountTypeEnum::LOAN->value,
|
||||
AccountTypeEnum::DEBT->value,
|
||||
AccountTypeEnum::MORTGAGE->value,
|
||||
]);
|
||||
$grouped = [];
|
||||
|
||||
// group accounts:
|
||||
/** @var Account $account */
|
||||
foreach ($accountList as $account) {
|
||||
$role = (string) $this->accountRepository->getMetaValue($account, 'account_role');
|
||||
$name = $account->name;
|
||||
$role = (string)$this->accountRepository->getMetaValue($account, 'account_role');
|
||||
$name = $account->name;
|
||||
if ('' === $role) {
|
||||
$role = 'no_account_type';
|
||||
}
|
||||
|
||||
// maybe it's a liability thing:
|
||||
if (in_array($account->accountType->type, $liabilityTypes, true)) {
|
||||
$role = 'l_'.$account->accountType->type;
|
||||
$role = 'l_' . $account->accountType->type;
|
||||
}
|
||||
if (AccountTypeEnum::CASH->value === $account->accountType->type) {
|
||||
$role = 'cash_account';
|
||||
@@ -170,7 +171,7 @@ class ConvertController extends Controller
|
||||
$role = 'revenue_account';
|
||||
}
|
||||
|
||||
$key = (string) trans('firefly.opt_group_'.$role);
|
||||
$key = (string)trans('firefly.opt_group_' . $role);
|
||||
$grouped[$key][$account->id] = $name;
|
||||
}
|
||||
|
||||
@@ -182,26 +183,26 @@ class ConvertController extends Controller
|
||||
// make repositories
|
||||
$liabilityTypes = [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::LOAN->value];
|
||||
$accountList = $this->accountRepository->getActiveAccountsByType([
|
||||
AccountTypeEnum::EXPENSE->value,
|
||||
AccountTypeEnum::CASH->value,
|
||||
AccountTypeEnum::LOAN->value,
|
||||
AccountTypeEnum::DEBT->value,
|
||||
AccountTypeEnum::MORTGAGE->value,
|
||||
]);
|
||||
AccountTypeEnum::EXPENSE->value,
|
||||
AccountTypeEnum::CASH->value,
|
||||
AccountTypeEnum::LOAN->value,
|
||||
AccountTypeEnum::DEBT->value,
|
||||
AccountTypeEnum::MORTGAGE->value,
|
||||
]);
|
||||
$grouped = [];
|
||||
|
||||
// group accounts:
|
||||
/** @var Account $account */
|
||||
foreach ($accountList as $account) {
|
||||
$role = (string) $this->accountRepository->getMetaValue($account, 'account_role');
|
||||
$name = $account->name;
|
||||
$role = (string)$this->accountRepository->getMetaValue($account, 'account_role');
|
||||
$name = $account->name;
|
||||
if ('' === $role) {
|
||||
$role = 'no_account_type';
|
||||
}
|
||||
|
||||
// maybe it's a liability thing:
|
||||
if (in_array($account->accountType->type, $liabilityTypes, true)) {
|
||||
$role = 'l_'.$account->accountType->type;
|
||||
$role = 'l_' . $account->accountType->type;
|
||||
}
|
||||
if (AccountTypeEnum::CASH->value === $account->accountType->type) {
|
||||
$role = 'cash_account';
|
||||
@@ -211,7 +212,7 @@ class ConvertController extends Controller
|
||||
$role = 'expense_account';
|
||||
}
|
||||
|
||||
$key = (string) trans('firefly.opt_group_'.$role);
|
||||
$key = (string)trans('firefly.opt_group_' . $role);
|
||||
$grouped[$key][$account->id] = $name;
|
||||
}
|
||||
|
||||
@@ -225,23 +226,23 @@ class ConvertController extends Controller
|
||||
{
|
||||
// make repositories
|
||||
$accountList = $this->accountRepository->getActiveAccountsByType([
|
||||
AccountTypeEnum::LOAN->value,
|
||||
AccountTypeEnum::DEBT->value,
|
||||
AccountTypeEnum::MORTGAGE->value,
|
||||
]);
|
||||
AccountTypeEnum::LOAN->value,
|
||||
AccountTypeEnum::DEBT->value,
|
||||
AccountTypeEnum::MORTGAGE->value,
|
||||
]);
|
||||
$grouped = [];
|
||||
|
||||
// group accounts:
|
||||
/** @var Account $account */
|
||||
foreach ($accountList as $account) {
|
||||
$date = today()->endOfDay();
|
||||
$date = today()->endOfDay();
|
||||
Log::debug(sprintf('getLiabilities: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
// 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized.
|
||||
// $balance = Steam::finalAccountBalance($account, $date)['balance'];
|
||||
$balance = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id]['balance'] ?? '0';
|
||||
$currency = $this->accountRepository->getAccountCurrency($account) ?? $this->primaryCurrency;
|
||||
$role = sprintf('l_%s', $account->accountType->type);
|
||||
$key = (string) trans(sprintf('firefly.opt_group_%s', $role));
|
||||
$key = (string)trans(sprintf('firefly.opt_group_%s', $role));
|
||||
$grouped[$key][$account->id] = sprintf('%s (%s)', $account->name, Amount::formatAnything($currency, $balance, false));
|
||||
}
|
||||
|
||||
@@ -260,19 +261,19 @@ class ConvertController extends Controller
|
||||
// group accounts:
|
||||
/** @var Account $account */
|
||||
foreach ($accountList as $account) {
|
||||
$date = today()->endOfDay();
|
||||
$date = today()->endOfDay();
|
||||
Log::debug(sprintf('getAssetAccounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
// 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized.
|
||||
// $balance = Steam::finalAccountBalance($account, $date)['balance'];
|
||||
$balance = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id]['balance'] ?? '0';
|
||||
$balance = Steam::accountsBalancesOptimized(new Collection()->push($account), $date)[$account->id]['balance'] ?? '0';
|
||||
|
||||
$currency = $this->accountRepository->getAccountCurrency($account) ?? $this->primaryCurrency;
|
||||
$role = (string) $this->accountRepository->getMetaValue($account, 'account_role');
|
||||
$currency = $this->accountRepository->getAccountCurrency($account) ?? $this->primaryCurrency;
|
||||
$role = (string)$this->accountRepository->getMetaValue($account, 'account_role');
|
||||
if ('' === $role) {
|
||||
$role = 'no_account_type';
|
||||
}
|
||||
|
||||
$key = (string) trans(sprintf('firefly.opt_group_%s', $role));
|
||||
$key = (string)trans(sprintf('firefly.opt_group_%s', $role));
|
||||
$grouped[$key][$account->id] = sprintf('%s (%s)', $account->name, Amount::formatAnything($currency, $balance, false));
|
||||
}
|
||||
|
||||
@@ -305,9 +306,10 @@ class ConvertController extends Controller
|
||||
// correct transfers:
|
||||
$group->refresh();
|
||||
|
||||
session()->flash('success', (string) trans('firefly.converted_to_'.$destinationType->type));
|
||||
$flags = new TransactionGroupEventFlags();
|
||||
event(new UpdatedSingleTransactionGroup($group, $flags));
|
||||
session()->flash('success', (string)trans('firefly.converted_to_' . $destinationType->type));
|
||||
$flags = new TransactionGroupEventFlags();
|
||||
$objects = TransactionGroupEventObjects::collectFromTransactionGroup($group);
|
||||
event(new UpdatedSingleTransactionGroup($flags, $objects));
|
||||
|
||||
return redirect(route('transactions.show', [$group->id]));
|
||||
}
|
||||
@@ -318,22 +320,22 @@ class ConvertController extends Controller
|
||||
private function convertJournal(TransactionJournal $journal, TransactionType $transactionType, array $data): TransactionJournal
|
||||
{
|
||||
/** @var AccountValidator $validator */
|
||||
$validator = app(AccountValidator::class);
|
||||
$validator = app(AccountValidator::class);
|
||||
$validator->setUser(auth()->user());
|
||||
$validator->setTransactionType($transactionType->type);
|
||||
|
||||
$sourceId = $data['source_id'][$journal->id] ?? null;
|
||||
$sourceName = $data['source_name'][$journal->id] ?? null;
|
||||
$destinationId = $data['destination_id'][$journal->id] ?? null;
|
||||
$destinationName = $data['destination_name'][$journal->id] ?? null;
|
||||
$sourceId = $data['source_id'][$journal->id] ?? null;
|
||||
$sourceName = $data['source_name'][$journal->id] ?? null;
|
||||
$destinationId = $data['destination_id'][$journal->id] ?? null;
|
||||
$destinationName = $data['destination_name'][$journal->id] ?? null;
|
||||
|
||||
// double check it's not an empty string.
|
||||
$sourceId = '' === $sourceId || null === $sourceId ? null : (int) $sourceId;
|
||||
$sourceName = '' === $sourceName ? null : (string) $sourceName;
|
||||
$destinationId = '' === $destinationId || null === $destinationId ? null : (int) $destinationId;
|
||||
$destinationName = '' === $destinationName ? null : (string) $destinationName;
|
||||
$validSource = $validator->validateSource(['id' => $sourceId, 'name' => $sourceName]);
|
||||
$validDestination = $validator->validateDestination(['id' => $destinationId, 'name' => $destinationName]);
|
||||
$sourceId = '' === $sourceId || null === $sourceId ? null : (int)$sourceId;
|
||||
$sourceName = '' === $sourceName ? null : (string)$sourceName;
|
||||
$destinationId = '' === $destinationId || null === $destinationId ? null : (int)$destinationId;
|
||||
$destinationName = '' === $destinationName ? null : (string)$destinationName;
|
||||
$validSource = $validator->validateSource(['id' => $sourceId, 'name' => $sourceName]);
|
||||
$validDestination = $validator->validateDestination(['id' => $destinationId, 'name' => $destinationName]);
|
||||
|
||||
if (false === $validSource) {
|
||||
throw new FireflyException(sprintf(trans('firefly.convert_invalid_source'), $journal->id));
|
||||
@@ -344,7 +346,7 @@ class ConvertController extends Controller
|
||||
|
||||
// TODO typeOverrule: the account validator may have another opinion on the transaction type.
|
||||
|
||||
$update = [
|
||||
$update = [
|
||||
'source_id' => $sourceId,
|
||||
'source_name' => $sourceName,
|
||||
'destination_id' => $destinationId,
|
||||
@@ -358,9 +360,9 @@ class ConvertController extends Controller
|
||||
|
||||
// also set the currency to the currency of the source account, in case you're converting a deposit into a transfer.
|
||||
if (TransactionTypeEnum::TRANSFER->value === $transactionType->type && TransactionTypeEnum::DEPOSIT->value === $journal->transactionType->type) {
|
||||
$source = $this->accountRepository->find((int) $sourceId);
|
||||
$source = $this->accountRepository->find((int)$sourceId);
|
||||
$sourceCurrency = $this->accountRepository->getAccountCurrency($source);
|
||||
$dest = $this->accountRepository->find((int) $destinationId);
|
||||
$dest = $this->accountRepository->find((int)$destinationId);
|
||||
$destCurrency = $this->accountRepository->getAccountCurrency($dest);
|
||||
if (
|
||||
$sourceCurrency instanceof TransactionCurrency
|
||||
@@ -375,9 +377,9 @@ class ConvertController extends Controller
|
||||
|
||||
// same thing for converting a withdrawal into a transfer, but with the currency of the destination account.
|
||||
if (TransactionTypeEnum::TRANSFER->value === $transactionType->type && TransactionTypeEnum::WITHDRAWAL->value === $journal->transactionType->type) {
|
||||
$source = $this->accountRepository->find((int) $sourceId);
|
||||
$source = $this->accountRepository->find((int)$sourceId);
|
||||
$sourceCurrency = $this->accountRepository->getAccountCurrency($source);
|
||||
$dest = $this->accountRepository->find((int) $destinationId);
|
||||
$dest = $this->accountRepository->find((int)$destinationId);
|
||||
$destCurrency = $this->accountRepository->getAccountCurrency($dest);
|
||||
if (
|
||||
$sourceCurrency instanceof TransactionCurrency
|
||||
@@ -391,7 +393,7 @@ class ConvertController extends Controller
|
||||
}
|
||||
|
||||
/** @var JournalUpdateService $service */
|
||||
$service = app(JournalUpdateService::class);
|
||||
$service = app(JournalUpdateService::class);
|
||||
$service->setTransactionJournal($journal);
|
||||
$service->setData($update);
|
||||
$service->update();
|
||||
|
||||
@@ -27,6 +27,7 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventFlags;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventObjects;
|
||||
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
@@ -61,7 +62,7 @@ class MassController extends Controller
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.transactions'));
|
||||
app('view')->share('title', (string)trans('firefly.transactions'));
|
||||
app('view')->share('mainTitleIcon', 'fa-exchange');
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
|
||||
@@ -74,7 +75,7 @@ class MassController extends Controller
|
||||
*/
|
||||
public function delete(array $journals): IlluminateView
|
||||
{
|
||||
$subTitle = (string) trans('firefly.mass_delete_journals');
|
||||
$subTitle = (string)trans('firefly.mass_delete_journals');
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUrl('transactions.mass-delete.url');
|
||||
@@ -87,7 +88,7 @@ class MassController extends Controller
|
||||
*
|
||||
* @return Application|Redirector|RedirectResponse
|
||||
*/
|
||||
public function destroy(MassDeleteJournalRequest $request): Redirector|RedirectResponse
|
||||
public function destroy(MassDeleteJournalRequest $request): Redirector | RedirectResponse
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$ids = $request->get('confirm_mass_delete');
|
||||
@@ -100,8 +101,8 @@ class MassController extends Controller
|
||||
Log::debug(sprintf('Searching for ID #%d', $journalId));
|
||||
|
||||
/** @var null|TransactionJournal $journal */
|
||||
$journal = $this->repository->find((int) $journalId);
|
||||
if (null !== $journal && (int) $journalId === $journal->id) {
|
||||
$journal = $this->repository->find((int)$journalId);
|
||||
if (null !== $journal && (int)$journalId === $journal->id) {
|
||||
$this->repository->destroyJournal($journal);
|
||||
++$count;
|
||||
Log::debug(sprintf('Deleted transaction journal #%d', $journalId));
|
||||
@@ -123,22 +124,22 @@ class MassController extends Controller
|
||||
*/
|
||||
public function edit(array $journals): IlluminateView
|
||||
{
|
||||
$subTitle = (string) trans('firefly.mass_edit_journals');
|
||||
$subTitle = (string)trans('firefly.mass_edit_journals');
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
// valid withdrawal sources:
|
||||
$array = array_keys(config(sprintf('firefly.source_dests.%s', TransactionTypeEnum::WITHDRAWAL->value)));
|
||||
$withdrawalSources = $accountRepository->getAccountsByType($array);
|
||||
$array = array_keys(config(sprintf('firefly.source_dests.%s', TransactionTypeEnum::WITHDRAWAL->value)));
|
||||
$withdrawalSources = $accountRepository->getAccountsByType($array);
|
||||
|
||||
// valid deposit destinations:
|
||||
$array = config(sprintf('firefly.source_dests.%s.%s', TransactionTypeEnum::DEPOSIT->value, AccountTypeEnum::REVENUE->value));
|
||||
$depositDestinations = $accountRepository->getAccountsByType($array);
|
||||
|
||||
/** @var BudgetRepositoryInterface $budgetRepository */
|
||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$budgets = $budgetRepository->getBudgets();
|
||||
$budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$budgets = $budgetRepository->getBudgets();
|
||||
|
||||
// reverse amounts
|
||||
foreach ($journals as $index => $journal) {
|
||||
@@ -162,18 +163,18 @@ class MassController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function update(MassEditJournalRequest $request): Redirector|RedirectResponse
|
||||
public function update(MassEditJournalRequest $request): Redirector | RedirectResponse
|
||||
{
|
||||
$journalIds = $request->get('journals');
|
||||
if (!is_array($journalIds)) {
|
||||
// TODO this is a weird error, should be caught.
|
||||
throw new FireflyException('This is not an array.');
|
||||
}
|
||||
$count = 0;
|
||||
$count = 0;
|
||||
|
||||
/** @var string $journalId */
|
||||
foreach ($journalIds as $journalId) {
|
||||
$integer = (int) $journalId;
|
||||
$integer = (int)$journalId;
|
||||
|
||||
try {
|
||||
$this->updateJournal($integer, $request);
|
||||
@@ -195,15 +196,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'),
|
||||
@@ -224,7 +225,8 @@ class MassController extends Controller
|
||||
$runRecalculations = $service->isCompareHashChanged();
|
||||
$flags = new TransactionGroupEventFlags();
|
||||
$flags->recalculateCredit = $runRecalculations;
|
||||
event(new UpdatedSingleTransactionGroup($journal->transactionGroup, $flags));
|
||||
$objects = TransactionGroupEventObjects::collectFromTransactionGroup($journal->transactionGroup);
|
||||
event(new UpdatedSingleTransactionGroup($flags, $objects));
|
||||
}
|
||||
|
||||
private function getDateFromRequest(MassEditJournalRequest $request, int $journalId, string $key): ?Carbon
|
||||
@@ -259,7 +261,7 @@ class MassController extends Controller
|
||||
return null;
|
||||
}
|
||||
|
||||
return (string) $value[$journalId];
|
||||
return (string)$value[$journalId];
|
||||
}
|
||||
|
||||
private function getIntFromRequest(MassEditJournalRequest $request, int $journalId, string $string): ?int
|
||||
@@ -272,6 +274,6 @@ class MassController extends Controller
|
||||
return null;
|
||||
}
|
||||
|
||||
return (int) $value[$journalId];
|
||||
return (int)$value[$journalId];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,30 +27,43 @@ namespace FireflyIII\Listeners\Model\TransactionGroup;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Enums\WebhookTrigger;
|
||||
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
|
||||
use FireflyIII\Events\Model\Webhook\WebhookMessagesRequestSending;
|
||||
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use FireflyIII\Support\Models\AccountBalanceCalculator;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ProcessesUpdatedTransactionGroup
|
||||
{
|
||||
use SupportsGroupProcessingTrait;
|
||||
|
||||
public function handle(UpdatedSingleTransactionGroup $event): void
|
||||
{
|
||||
Log::debug('Now in handle() for UpdatedSingleTransactionGroup');
|
||||
Log::debug(sprintf('User called %s', get_class($event)));
|
||||
$this->unifyAccounts($event);
|
||||
$this->processRules($event);
|
||||
$this->recalculateCredit($event);
|
||||
$this->triggerWebhooks($event);
|
||||
ProcessesNewTransactionGroup::removePeriodStatistics($event->transactionGroup->transactionJournals);
|
||||
$this->updateRunningBalance($event);
|
||||
|
||||
Log::debug(sprintf('Transaction journal count is %d', $event->objects->transactionJournals->count()));
|
||||
if (!$event->flags->applyRules) {
|
||||
Log::debug(sprintf('Will NOT process rules for %d journal(s)', $event->objects->transactionJournals->count()));
|
||||
}
|
||||
if (!$event->flags->recalculateCredit) {
|
||||
Log::debug(sprintf('Will NOT recalculate credit for %d journal(s)', $event->objects->transactionJournals->count()));
|
||||
}
|
||||
if (!$event->flags->fireWebhooks) {
|
||||
Log::debug(sprintf('Will NOT fire webhooks for %d journal(s)', $event->objects->transactionJournals->count()));
|
||||
}
|
||||
|
||||
if ($event->flags->applyRules) {
|
||||
$this->processRules($event->objects->transactionJournals, 'update-journal');
|
||||
}
|
||||
if ($event->flags->recalculateCredit) {
|
||||
$this->recalculateCredit($event->objects->accounts);
|
||||
}
|
||||
if ($event->flags->fireWebhooks) {
|
||||
$this->fireWebhooks($event->objects->transactionJournals, WebhookTrigger::UPDATE_TRANSACTION);
|
||||
}
|
||||
$this->removePeriodStatistics($event->objects);
|
||||
$this->recalculateRunningBalance($event->objects);
|
||||
|
||||
Log::debug('Done with handle() for UpdatedSingleTransactionGroup');
|
||||
}
|
||||
@@ -58,10 +71,18 @@ class ProcessesUpdatedTransactionGroup
|
||||
/**
|
||||
* This method will make sure all source / destination accounts are the same.
|
||||
*/
|
||||
public function unifyAccounts(UpdatedSingleTransactionGroup $updatedGroupEvent): void
|
||||
protected function unifyAccounts(UpdatedSingleTransactionGroup $updatedGroupEvent): void
|
||||
{
|
||||
Log::debug('Now in unifyAccounts()');
|
||||
$group = $updatedGroupEvent->transactionGroup;
|
||||
/** @var TransactionGroup $group */
|
||||
foreach ($updatedGroupEvent->objects->transactionGroups as $group) {
|
||||
$this->unifyAccountsForGroup($group);
|
||||
}
|
||||
Log::debug('Done with unifyAccounts()');
|
||||
}
|
||||
|
||||
private function unifyAccountsForGroup(TransactionGroup $group): void
|
||||
{
|
||||
if (1 === $group->transactionJournals->count()) {
|
||||
Log::debug('Nothing to do in unifyAccounts()');
|
||||
|
||||
@@ -70,14 +91,13 @@ class ProcessesUpdatedTransactionGroup
|
||||
|
||||
// first journal:
|
||||
/** @var null|TransactionJournal $first */
|
||||
$first = $group
|
||||
$first = $group
|
||||
->transactionJournals()
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->orderBy('transaction_journals.description', 'DESC')
|
||||
->first()
|
||||
;
|
||||
->first();
|
||||
|
||||
if (null === $first) {
|
||||
Log::warning(sprintf('Group #%d has no transaction journals.', $group->id));
|
||||
@@ -85,15 +105,15 @@ class ProcessesUpdatedTransactionGroup
|
||||
return;
|
||||
}
|
||||
|
||||
$all = $group->transactionJournals()->get()->pluck('id')->toArray();
|
||||
$all = $group->transactionJournals()->get()->pluck('id')->toArray();
|
||||
|
||||
/** @var Account $sourceAccount */
|
||||
$sourceAccount = $first->transactions()->where('amount', '<', '0')->first()->account;
|
||||
|
||||
/** @var Account $destAccount */
|
||||
$destAccount = $first->transactions()->where('amount', '>', '0')->first()->account;
|
||||
$destAccount = $first->transactions()->where('amount', '>', '0')->first()->account;
|
||||
|
||||
$type = $first->transactionType->type;
|
||||
$type = $first->transactionType->type;
|
||||
if (TransactionTypeEnum::TRANSFER->value === $type || TransactionTypeEnum::WITHDRAWAL->value === $type) {
|
||||
// set all source transactions to source account:
|
||||
Transaction::whereIn('transaction_journal_id', $all)->where('amount', '<', 0)->update(['account_id' => $sourceAccount->id]);
|
||||
@@ -102,92 +122,5 @@ class ProcessesUpdatedTransactionGroup
|
||||
// set all destination transactions to destination account:
|
||||
Transaction::whereIn('transaction_journal_id', $all)->where('amount', '>', 0)->update(['account_id' => $destAccount->id]);
|
||||
}
|
||||
Log::debug('Done with unifyAccounts()');
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will check all the rules when a journal is updated.
|
||||
*/
|
||||
private function processRules(UpdatedSingleTransactionGroup $updatedGroupEvent): void
|
||||
{
|
||||
Log::debug('Now in processRules()');
|
||||
if (false === $updatedGroupEvent->flags->applyRules) {
|
||||
Log::info(sprintf('Will not run rules on group #%d', $updatedGroupEvent->transactionGroup->id));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$journals = $updatedGroupEvent->transactionGroup->transactionJournals;
|
||||
$array = [];
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$array[] = $journal->id;
|
||||
}
|
||||
$journalIds = implode(',', $array);
|
||||
Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
||||
|
||||
// collect rules:
|
||||
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||
$ruleGroupRepository->setUser($updatedGroupEvent->transactionGroup->user);
|
||||
|
||||
$groups = $ruleGroupRepository->getRuleGroupsWithRules('update-journal');
|
||||
|
||||
// file rule engine.
|
||||
$newRuleEngine = app(RuleEngineInterface::class);
|
||||
$newRuleEngine->setUser($updatedGroupEvent->transactionGroup->user);
|
||||
$newRuleEngine->addOperator(['type' => 'journal_id', 'value' => $journalIds]);
|
||||
$newRuleEngine->setRuleGroups($groups);
|
||||
$newRuleEngine->fire();
|
||||
Log::debug('Done with processRules()');
|
||||
}
|
||||
|
||||
private function recalculateCredit(UpdatedSingleTransactionGroup $event): void
|
||||
{
|
||||
Log::debug('Now in recalculateCredit()');
|
||||
$group = $event->transactionGroup;
|
||||
|
||||
/** @var CreditRecalculateService $object */
|
||||
$object = app(CreditRecalculateService::class);
|
||||
$object->setGroup($group);
|
||||
$object->recalculate();
|
||||
Log::debug('Done with recalculateCredit()');
|
||||
}
|
||||
|
||||
private function triggerWebhooks(UpdatedSingleTransactionGroup $updatedGroupEvent): void
|
||||
{
|
||||
Log::debug('Now in triggerWebhooks()');
|
||||
$group = $updatedGroupEvent->transactionGroup;
|
||||
if (false === $updatedGroupEvent->flags->fireWebhooks) {
|
||||
Log::info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
||||
|
||||
return;
|
||||
}
|
||||
$user = $group->user;
|
||||
|
||||
/** @var MessageGeneratorInterface $engine */
|
||||
$engine = app(MessageGeneratorInterface::class);
|
||||
$engine->setUser($user);
|
||||
$engine->setObjects(new Collection()->push($group));
|
||||
$engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION);
|
||||
$engine->generateMessages();
|
||||
|
||||
Log::debug(sprintf('send event WebhookMessagesRequestSending from %s', __METHOD__));
|
||||
event(new WebhookMessagesRequestSending());
|
||||
Log::debug('End of triggerWebhooks()');
|
||||
}
|
||||
|
||||
private function updateRunningBalance(UpdatedSingleTransactionGroup $event): void
|
||||
{
|
||||
Log::debug('Now in updateRunningBalance()');
|
||||
if (false === FireflyConfig::get('use_running_balance', config('firefly.feature_flags.running_balance_column'))->data) {
|
||||
return;
|
||||
}
|
||||
Log::debug(__METHOD__);
|
||||
$group = $event->transactionGroup;
|
||||
foreach ($group->transactionJournals as $journal) {
|
||||
AccountBalanceCalculator::recalculateForJournal($journal);
|
||||
}
|
||||
Log::debug('Done with updateRunningBalance()');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user